@patternfly/chatbot 2.2.0-prerelease.24 → 2.2.0-prerelease.25
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/Message/ImageMessage/ImageMessage.d.ts +4 -0
- package/dist/cjs/Message/ImageMessage/ImageMessage.js +25 -0
- package/dist/cjs/Message/Message.d.ts +11 -1
- package/dist/cjs/Message/Message.js +38 -30
- package/dist/cjs/Message/Message.test.js +68 -0
- package/dist/cjs/__mocks__/rehype-unwrap-images.d.ts +2 -0
- package/dist/cjs/__mocks__/rehype-unwrap-images.js +4 -0
- package/dist/css/main.css +8 -0
- package/dist/css/main.css.map +1 -1
- package/dist/esm/Message/ImageMessage/ImageMessage.d.ts +4 -0
- package/dist/esm/Message/ImageMessage/ImageMessage.js +20 -0
- package/dist/esm/Message/Message.d.ts +11 -1
- package/dist/esm/Message/Message.js +38 -30
- package/dist/esm/Message/Message.test.js +68 -0
- package/dist/esm/__mocks__/rehype-unwrap-images.d.ts +2 -0
- package/dist/esm/__mocks__/rehype-unwrap-images.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +11 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +11 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +11 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +54 -0
- package/src/Message/ImageMessage/ImageMessage.scss +9 -0
- package/src/Message/ImageMessage/ImageMessage.tsx +14 -0
- package/src/Message/Message.test.tsx +120 -0
- package/src/Message/Message.tsx +59 -35
- package/src/__mocks__/rehype-unwrap-images.tsx +3 -0
- package/src/main.scss +1 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
"use strict";
|
2
|
+
// ============================================================================
|
3
|
+
// Chatbot Main - Message - Content - Image
|
4
|
+
// ============================================================================
|
5
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
6
|
+
var t = {};
|
7
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
8
|
+
t[p] = s[p];
|
9
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
10
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
11
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
12
|
+
t[p[i]] = s[p[i]];
|
13
|
+
}
|
14
|
+
return t;
|
15
|
+
};
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
18
|
+
};
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
20
|
+
const react_1 = __importDefault(require("react"));
|
21
|
+
const ImageMessage = (_a) => {
|
22
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
23
|
+
return (react_1.default.createElement("img", Object.assign({ className: "pf-chatbot__message-image" }, props), children));
|
24
|
+
};
|
25
|
+
exports.default = ImageMessage;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { ReactNode } from 'react';
|
2
2
|
import { AvatarProps, LabelGroupProps } from '@patternfly/react-core';
|
3
3
|
import { ActionProps } from '../ResponseActions/ResponseActions';
|
4
4
|
import { SourcesCardProps } from '../SourcesCard';
|
@@ -25,6 +25,14 @@ export interface MessageAttachment {
|
|
25
25
|
/** Custom test id for the loading spinner in the attachment component */
|
26
26
|
spinnerTestId?: string;
|
27
27
|
}
|
28
|
+
export interface MessageExtraContent {
|
29
|
+
/** Content to display before the main content */
|
30
|
+
beforeMainContent?: ReactNode;
|
31
|
+
/** Content to display after the main content */
|
32
|
+
afterMainContent?: ReactNode;
|
33
|
+
/** Content to display at the end */
|
34
|
+
endContent?: ReactNode;
|
35
|
+
}
|
28
36
|
export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'role'> {
|
29
37
|
/** Unique id for message */
|
30
38
|
id?: string;
|
@@ -32,6 +40,8 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
|
|
32
40
|
role: 'user' | 'bot';
|
33
41
|
/** Message content */
|
34
42
|
content?: string;
|
43
|
+
/** Extra Message content */
|
44
|
+
extraContent?: MessageExtraContent;
|
35
45
|
/** Name of the user */
|
36
46
|
name?: string;
|
37
47
|
/** Avatar src for the user */
|
@@ -41,8 +41,11 @@ const TdMessage_1 = __importDefault(require("./TableMessage/TdMessage"));
|
|
41
41
|
const TbodyMessage_1 = __importDefault(require("./TableMessage/TbodyMessage"));
|
42
42
|
const TheadMessage_1 = __importDefault(require("./TableMessage/TheadMessage"));
|
43
43
|
const ThMessage_1 = __importDefault(require("./TableMessage/ThMessage"));
|
44
|
+
const ImageMessage_1 = __importDefault(require("./ImageMessage/ImageMessage"));
|
45
|
+
const rehype_unwrap_images_1 = __importDefault(require("rehype-unwrap-images"));
|
44
46
|
const MessageBase = (_a) => {
|
45
|
-
var { role, content, 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 } = _a, props = __rest(_a, ["role", "content", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps"]);
|
47
|
+
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 } = _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"]);
|
48
|
+
const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
|
46
49
|
let avatarClassName;
|
47
50
|
if (avatarProps && 'className' in avatarProps) {
|
48
51
|
const { className } = avatarProps, rest = __rest(avatarProps, ["className"]);
|
@@ -62,34 +65,38 @@ const MessageBase = (_a) => {
|
|
62
65
|
react_1.default.createElement(react_core_1.Timestamp, { date: date }, timestamp)),
|
63
66
|
react_1.default.createElement("div", { className: "pf-chatbot__message-response" },
|
64
67
|
react_1.default.createElement("div", { className: "pf-chatbot__message-and-actions" },
|
65
|
-
isLoading ? (react_1.default.createElement(MessageLoading_1.default, { loadingWord: loadingWord })) : (react_1.default.createElement(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
68
|
+
isLoading ? (react_1.default.createElement(MessageLoading_1.default, { loadingWord: loadingWord })) : (react_1.default.createElement(react_1.default.Fragment, null,
|
69
|
+
beforeMainContent && react_1.default.createElement(react_1.default.Fragment, null, beforeMainContent),
|
70
|
+
react_1.default.createElement(react_markdown_1.default, { components: {
|
71
|
+
p: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.p }, props)),
|
72
|
+
code: (_a) => {
|
73
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
74
|
+
return (react_1.default.createElement(CodeBlockMessage_1.default, Object.assign({}, props, codeBlockProps), children));
|
75
|
+
},
|
76
|
+
h1: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.h1 }, props)),
|
77
|
+
h2: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.h2 }, props)),
|
78
|
+
h3: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.h3 }, props)),
|
79
|
+
h4: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.h4 }, props)),
|
80
|
+
h5: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.h5 }, props)),
|
81
|
+
h6: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.h6 }, props)),
|
82
|
+
blockquote: (props) => react_1.default.createElement(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.blockquote }, props)),
|
83
|
+
ul: (props) => react_1.default.createElement(UnorderedListMessage_1.default, Object.assign({}, props)),
|
84
|
+
ol: (props) => react_1.default.createElement(OrderedListMessage_1.default, Object.assign({}, props)),
|
85
|
+
li: (props) => react_1.default.createElement(ListItemMessage_1.default, Object.assign({}, props)),
|
86
|
+
table: (props) => react_1.default.createElement(TableMessage_1.default, Object.assign({}, props, tableProps)),
|
87
|
+
tbody: (props) => react_1.default.createElement(TbodyMessage_1.default, Object.assign({}, props)),
|
88
|
+
thead: (props) => react_1.default.createElement(TheadMessage_1.default, Object.assign({}, props)),
|
89
|
+
tr: (props) => react_1.default.createElement(TrMessage_1.default, Object.assign({}, props)),
|
90
|
+
td: (props) => {
|
91
|
+
// Conflicts with Td type
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
93
|
+
const { width } = props, rest = __rest(props, ["width"]);
|
94
|
+
return react_1.default.createElement(TdMessage_1.default, Object.assign({}, rest));
|
95
|
+
},
|
96
|
+
th: (props) => react_1.default.createElement(ThMessage_1.default, Object.assign({}, props)),
|
97
|
+
img: (props) => react_1.default.createElement(ImageMessage_1.default, Object.assign({}, props))
|
98
|
+
}, remarkPlugins: [remark_gfm_1.default], rehypePlugins: [rehype_unwrap_images_1.default] }, content),
|
99
|
+
afterMainContent && react_1.default.createElement(react_1.default.Fragment, null, afterMainContent))),
|
93
100
|
!isLoading && sources && react_1.default.createElement(SourcesCard_1.default, Object.assign({}, sources)),
|
94
101
|
quickStarts && quickStarts.quickStart && (react_1.default.createElement(QuickStartTile_1.default, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel })),
|
95
102
|
!isLoading && actions && react_1.default.createElement(ResponseActions_1.default, { actions: actions }),
|
@@ -100,7 +107,8 @@ const MessageBase = (_a) => {
|
|
100
107
|
var _a;
|
101
108
|
return (react_1.default.createElement("div", { key: (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name, className: "pf-chatbot__message-attachment" },
|
102
109
|
react_1.default.createElement(FileDetailsLabel_1.default, { fileName: attachment.name, fileId: attachment.id, onClose: attachment.onClose, onClick: attachment.onClick, isLoading: attachment.isLoading, closeButtonAriaLabel: attachment.closeButtonAriaLabel, languageTestId: attachment.languageTestId, spinnerTestId: attachment.spinnerTestId })));
|
103
|
-
})))
|
110
|
+
}))),
|
111
|
+
!isLoading && endContent && react_1.default.createElement(react_1.default.Fragment, null, endContent)))));
|
104
112
|
};
|
105
113
|
exports.MessageBase = MessageBase;
|
106
114
|
const Message = react_1.default.forwardRef((props, ref) => (react_1.default.createElement(exports.MessageBase, Object.assign({ innerRef: ref }, props))));
|
@@ -137,6 +137,7 @@ const EMPTY_TABLE = `
|
|
137
137
|
| |
|
138
138
|
|
139
139
|
`;
|
140
|
+
const IMAGE = ``;
|
140
141
|
const checkListItemsRendered = () => {
|
141
142
|
const items = ['Item 1', 'Item 2', 'Item 3'];
|
142
143
|
expect(react_2.screen.getAllByRole('listitem')).toHaveLength(3);
|
@@ -512,4 +513,71 @@ describe('Message', () => {
|
|
512
513
|
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: TABLE, tableProps: { 'aria-label': 'Test' } }));
|
513
514
|
expect(react_2.screen.getByRole('grid', { name: /Test/i })).toBeTruthy();
|
514
515
|
});
|
516
|
+
it('should render beforeMainContent with main content', () => {
|
517
|
+
const mainContent = 'Main message content';
|
518
|
+
const beforeMainContentText = 'Before main content';
|
519
|
+
const beforeMainContent = react_1.default.createElement("div", null, beforeMainContentText);
|
520
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: mainContent, extraContent: { beforeMainContent } }));
|
521
|
+
expect(react_2.screen.getByText(beforeMainContentText)).toBeTruthy();
|
522
|
+
expect(react_2.screen.getByText(mainContent)).toBeTruthy();
|
523
|
+
});
|
524
|
+
it('should render afterMainContent with main content', () => {
|
525
|
+
const mainContent = 'Main message content';
|
526
|
+
const afterMainContentText = 'After main content';
|
527
|
+
const afterMainContent = react_1.default.createElement("div", null, afterMainContentText);
|
528
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: mainContent, extraContent: { afterMainContent } }));
|
529
|
+
expect(react_2.screen.getByText(afterMainContentText)).toBeTruthy();
|
530
|
+
expect(react_2.screen.getByText(mainContent)).toBeTruthy();
|
531
|
+
});
|
532
|
+
it('should render endContent with main content', () => {
|
533
|
+
const mainContent = 'Main message content';
|
534
|
+
const endMainContentText = 'End content';
|
535
|
+
const endContent = react_1.default.createElement("div", null, endMainContentText);
|
536
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: mainContent, extraContent: { endContent } }));
|
537
|
+
expect(react_2.screen.getByText(endMainContentText)).toBeTruthy();
|
538
|
+
expect(react_2.screen.getByText(mainContent)).toBeTruthy();
|
539
|
+
});
|
540
|
+
it('should render all parts of extraContent with main content', () => {
|
541
|
+
const beforeMainContent = react_1.default.createElement("div", null, "Before main content");
|
542
|
+
const afterMainContent = react_1.default.createElement("div", null, "After main content");
|
543
|
+
const endContent = react_1.default.createElement("div", null, "End content");
|
544
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "Main message content", extraContent: { beforeMainContent, afterMainContent, endContent } }));
|
545
|
+
expect(react_2.screen.getByText('Before main content')).toBeTruthy();
|
546
|
+
expect(react_2.screen.getByText('Main message content')).toBeTruthy();
|
547
|
+
expect(react_2.screen.getByText('After main content')).toBeTruthy();
|
548
|
+
expect(react_2.screen.getByText('End content')).toBeTruthy();
|
549
|
+
});
|
550
|
+
it('should not render extraContent when not provided', () => {
|
551
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "Main message content" }));
|
552
|
+
// Ensure no extraContent is rendered
|
553
|
+
expect(react_2.screen.getByText('Main message content')).toBeTruthy();
|
554
|
+
expect(react_2.screen.queryByText('Before main content')).toBeFalsy();
|
555
|
+
expect(react_2.screen.queryByText('After main content')).toBeFalsy();
|
556
|
+
expect(react_2.screen.queryByText('end message content')).toBeFalsy();
|
557
|
+
});
|
558
|
+
it('should handle undefined or null values in extraContent gracefully', () => {
|
559
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "Main message content", extraContent: { beforeMainContent: null, afterMainContent: undefined, endContent: null } }));
|
560
|
+
// Ensure that no extraContent is rendered if they are null or undefined
|
561
|
+
expect(react_2.screen.getByText('Main message content')).toBeTruthy();
|
562
|
+
expect(react_2.screen.queryByText('Before main content')).toBeFalsy();
|
563
|
+
expect(react_2.screen.queryByText('After main content')).toBeFalsy();
|
564
|
+
expect(react_2.screen.queryByText('end message content')).toBeFalsy();
|
565
|
+
});
|
566
|
+
it('should render JSX in extraContent correctly', () => {
|
567
|
+
const beforeMainContent = (react_1.default.createElement("div", { "data-testid": "before-main-content" },
|
568
|
+
react_1.default.createElement("strong", null, "Bold before content")));
|
569
|
+
const afterMainContent = (react_1.default.createElement("div", { "data-testid": "after-main-content" },
|
570
|
+
react_1.default.createElement("strong", null, "Bold after content")));
|
571
|
+
const endContent = (react_1.default.createElement("div", { "data-testid": "end-main-content" },
|
572
|
+
react_1.default.createElement("strong", null, "Bold end content")));
|
573
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "Main message content", extraContent: { beforeMainContent, afterMainContent, endContent } }));
|
574
|
+
// Check that the JSX is correctly rendered
|
575
|
+
expect(react_2.screen.getByTestId('before-main-content')).toContainHTML('<strong>Bold before content</strong>');
|
576
|
+
expect(react_2.screen.getByTestId('after-main-content')).toContainHTML('<strong>Bold after content</strong>');
|
577
|
+
expect(react_2.screen.getByTestId('end-main-content')).toContainHTML('<strong>Bold end content</strong>');
|
578
|
+
});
|
579
|
+
it('should handle image correctly', () => {
|
580
|
+
(0, react_2.render)(react_1.default.createElement(Message_1.default, { avatar: "./img", role: "user", name: "User", content: IMAGE }));
|
581
|
+
expect(react_2.screen.getByRole('img', { name: /Multi-colored wavy lines on a black background/i })).toBeTruthy();
|
582
|
+
});
|
515
583
|
});
|
package/dist/css/main.css
CHANGED
@@ -1192,6 +1192,14 @@
|
|
1192
1192
|
font-size: var(--pf-t--global--font--size--body--default);
|
1193
1193
|
}
|
1194
1194
|
|
1195
|
+
.pf-chatbot__message-image {
|
1196
|
+
border-radius: var(--pf-t--global--border--radius--small);
|
1197
|
+
max-width: 37.5rem;
|
1198
|
+
max-height: 25rem;
|
1199
|
+
min-height: 6.25rem;
|
1200
|
+
display: block;
|
1201
|
+
}
|
1202
|
+
|
1195
1203
|
.pf-chatbot__message-and-actions blockquote .pf-chatbot__message-text {
|
1196
1204
|
display: inline-block;
|
1197
1205
|
}
|
package/dist/css/main.css.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sourceRoot":"","sources":["../../src/AttachMenu/AttachMenu.scss","../../src/Chatbot/Chatbot.scss","../../src/ChatbotAlert/ChatbotAlert.scss","../../src/ChatbotContent/ChatbotContent.scss","../../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss","../../src/ChatbotFooter/ChatbotFootnote.scss","../../src/ChatbotFooter/ChatbotFooter.scss","../../src/ChatbotHeader/ChatbotHeader.scss","../../src/ChatbotModal/ChatbotModal.scss","../../src/ChatbotPopover/ChatbotPopover.scss","../../src/ChatbotToggle/ChatbotToggle.scss","../../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.scss","../../src/CodeModal/CodeModal.scss","../../src/Compare/Compare.scss","../../src/FileDetails/FileDetails.scss","../../src/FileDetailsLabel/FileDetailsLabel.scss","../../src/FileDropZone/FileDropZone.scss","../../src/Message/Message.scss","../../src/Message/MessageLoading.scss","../../src/Message/CodeBlockMessage/CodeBlockMessage.scss","../../src/Message/TextMessage/TextMessage.scss","../../src/Message/ListMessage/ListMessage.scss","../../src/Message/TableMessage/TableMessage.scss","../../src/Message/QuickStarts/QuickStartTile.scss","../../src/Message/QuickResponse/QuickResponse.scss","../../src/Message/UserFeedback/UserFeedback.scss","../../src/MessageBar/AttachButton.scss","../../src/MessageBar/MicrophoneButton.scss","../../src/MessageBar/SendButton.scss","../../src/MessageBar/StopButton.scss","../../src/MessageBar/MessageBar.scss","../../src/MessageBox/JumpButton.scss","../../src/MessageBox/MessageBox.scss","../../src/ResponseActions/ResponseActions.scss","../../src/Settings/Settings.scss","../../src/SourcesCard/SourcesCard.scss","../../src/SourceDetailsMenuItem/SourceDetailsMenuItem.scss","../../src/TermsOfUse/TermsOfUse.scss","../../src/main.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;AACE;AAsBA;AASA;;AA9BA;EACE;EACA;EACA;EACA;;AAEF;EACE;;AAGF;AACE;;AACA;EACE;EACA;EACA;EACA;EACA;;AAKJ;EACE;;AAGF;EACE;;AAIF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;;ACxDJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAKF;EAvBF;IAwBI;IACA;;;AAIF;EA7BF;IA8BI;;;;AAOJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EAXF;IAYI;;;;AAOJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAIF;EAdF;IAeI;;;;AAIJ;EACE;;;AAGF;AAAA;AAAA;EAGE;;;AC1GF;EACE;EACA;EACA;;;ACAF;EACE;EACA;EACA;EACA;EACA;;AAGA;EARF;IASI;;;;AAOJ;EAGI;AAAA;IACE;IACA;;;ACpBJ;EACE;EACA;;AAIF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAMJ;EACE;EACA;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAIF;EACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAKA;EACE;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAKA;EACE;;;AASJ;EACE;;;AAQF;EACE;;AACA;EACE;;;AASJ;EACE;;AACA;EACE;EACA;;AAEF;EACE;;;AASF;AAAA;AAAA;EACE;;;ACvLN;EACE;;AAEA;EACE;EACA;;;ACHJ;EACE;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;AAMF;EAGI;AAAA;IACE;;EACA;AAAA;IACE;;EAGJ;AAAA;IACE;IACA;IACA;;;AASJ;EACE;;;AC5CJ;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAKJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;;;AAQN;EAGI;AAAA;IACE;;EAEF;AAAA;IACE;;;AASJ;EACE;;;AAOJ;AAAA;EAEE;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;AAGF;AAAA;AAAA;AAAA;EAEE;EACA;EACA;;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;;AAOJ;EACE;;;AAOJ;AAAA;EAEE;;;AAGF;EACE;;;AAGF;EACE;;;ACvIF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;AAAA;EAEE;;AAEF;EACE;EACA;;AAEF;EACE;;;AAOJ;EACE;AAAA;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;;;AAGJ;EACE;AAAA;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;;;AAOJ;EACE;;;AAMF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAQE;EACE;;;AAQN;EACE;;;ACvFA;EAA0B;;AAMxB;EAAM;;AACN;EAAuB;;AACvB;EACE;;AAIF;EACE;EACA;;AAEF;EACE;;;ACnBN;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;;AAIF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;;AC3BF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;;AAOJ;EAIM;AAAA;IACE;IACA;;;AC1CN;EACE;EACA;EACA;EACA;;AAEF;EACE;AACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;;;AASA;EACE;EACA;;;AAKN;EACE;;;AAGF;EACE;;;AClFF;EACE;EACA;EACA;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;EACA;;;AAGJ;EACE;EACA;EACA;;AAEA;EALF;IAMI;;;AAGF;EACE;;AAEA;EAHF;IAII;;;;AAKN;EACE;;AAEA;EACE;;AAGF;EACE;;AAIA;EADF;IAEI;;;;AAIN;EACE;;AAEA;EAHF;IAII;;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EARF;IASI;IACA;IACA;;;;ACrEJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAIF;EACE;EACA;EACA;EACA;EACA;;;ACvBF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EAEA;EACA;EACA;;AACA;EACE;;AAGF;AAAA;EAEE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;;AAGF;EACE;;;AAIJ;AAAA;EAEE;EACA;;AAEA;AAAA;EACE;;;AAKF;EACE;;;AAMF;AAAA;EACE;;;AC/DJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;AAGA;EANF;IAOI;;;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;AACA;EACE;EACA;EACA;EACA;;;AAME;EADF;IAEI;IACA;IACA;;EAEA;IACE;;;;AChDR;EACE;EACA;EACA;EACA;;AAIA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAKF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;;AAKF;EACE;EACA;EACA;;AAGA;EACE;EACA;EACA;;AAIF;EACE;EACA;EACA;;AAEA;EACE;;AAKJ;EACE;;AAEF;EACE;;AAMJ;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAMJ;EACE;EACA;EACA;;;AC7FF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;IACE;;EAEF;IAEE;;;;AC9CN;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEA;EAEE;;AAMN;EACE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEE;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;;;AC1EE;EACE;;;AAMN;EACE;;;AAIF;EACE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AAKF;EACE;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAKE;;;AD9CN;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEA;EAEE;;AAMN;EACE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEE;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;;;
|
1
|
+
{"version":3,"sourceRoot":"","sources":["../../src/AttachMenu/AttachMenu.scss","../../src/Chatbot/Chatbot.scss","../../src/ChatbotAlert/ChatbotAlert.scss","../../src/ChatbotContent/ChatbotContent.scss","../../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss","../../src/ChatbotFooter/ChatbotFootnote.scss","../../src/ChatbotFooter/ChatbotFooter.scss","../../src/ChatbotHeader/ChatbotHeader.scss","../../src/ChatbotModal/ChatbotModal.scss","../../src/ChatbotPopover/ChatbotPopover.scss","../../src/ChatbotToggle/ChatbotToggle.scss","../../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.scss","../../src/CodeModal/CodeModal.scss","../../src/Compare/Compare.scss","../../src/FileDetails/FileDetails.scss","../../src/FileDetailsLabel/FileDetailsLabel.scss","../../src/FileDropZone/FileDropZone.scss","../../src/Message/Message.scss","../../src/Message/MessageLoading.scss","../../src/Message/CodeBlockMessage/CodeBlockMessage.scss","../../src/Message/TextMessage/TextMessage.scss","../../src/Message/ImageMessage/ImageMessage.scss","../../src/Message/ListMessage/ListMessage.scss","../../src/Message/TableMessage/TableMessage.scss","../../src/Message/QuickStarts/QuickStartTile.scss","../../src/Message/QuickResponse/QuickResponse.scss","../../src/Message/UserFeedback/UserFeedback.scss","../../src/MessageBar/AttachButton.scss","../../src/MessageBar/MicrophoneButton.scss","../../src/MessageBar/SendButton.scss","../../src/MessageBar/StopButton.scss","../../src/MessageBar/MessageBar.scss","../../src/MessageBox/JumpButton.scss","../../src/MessageBox/MessageBox.scss","../../src/ResponseActions/ResponseActions.scss","../../src/Settings/Settings.scss","../../src/SourcesCard/SourcesCard.scss","../../src/SourceDetailsMenuItem/SourceDetailsMenuItem.scss","../../src/TermsOfUse/TermsOfUse.scss","../../src/main.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;AACE;AAsBA;AASA;;AA9BA;EACE;EACA;EACA;EACA;;AAEF;EACE;;AAGF;AACE;;AACA;EACE;EACA;EACA;EACA;EACA;;AAKJ;EACE;;AAGF;EACE;;AAIF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;;ACxDJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAKF;EAvBF;IAwBI;IACA;;;AAIF;EA7BF;IA8BI;;;;AAOJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EAXF;IAYI;;;;AAOJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAIF;EAdF;IAeI;;;;AAIJ;EACE;;;AAGF;AAAA;AAAA;EAGE;;;AC1GF;EACE;EACA;EACA;;;ACAF;EACE;EACA;EACA;EACA;EACA;;AAGA;EARF;IASI;;;;AAOJ;EAGI;AAAA;IACE;IACA;;;ACpBJ;EACE;EACA;;AAIF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAMJ;EACE;EACA;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;;AAIF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAIF;EACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAKA;EACE;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAKA;EACE;;;AASJ;EACE;;;AAQF;EACE;;AACA;EACE;;;AASJ;EACE;;AACA;EACE;EACA;;AAEF;EACE;;;AASF;AAAA;AAAA;EACE;;;ACvLN;EACE;;AAEA;EACE;EACA;;;ACHJ;EACE;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;AAMF;EAGI;AAAA;IACE;;EACA;AAAA;IACE;;EAGJ;AAAA;IACE;IACA;IACA;;;AASJ;EACE;;;AC5CJ;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAKJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;;;AAQN;EAGI;AAAA;IACE;;EAEF;AAAA;IACE;;;AASJ;EACE;;;AAOJ;AAAA;EAEE;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;AAGF;AAAA;AAAA;AAAA;EAEE;EACA;EACA;;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;;AAOJ;EACE;;;AAOJ;AAAA;EAEE;;;AAGF;EACE;;;AAGF;EACE;;;ACvIF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;AAAA;EAEE;;AAEF;EACE;EACA;;AAEF;EACE;;;AAOJ;EACE;AAAA;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;;;AAGJ;EACE;AAAA;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;;;AAOJ;EACE;;;AAMF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAQE;EACE;;;AAQN;EACE;;;ACvFA;EAA0B;;AAMxB;EAAM;;AACN;EAAuB;;AACvB;EACE;;AAIF;EACE;EACA;;AAEF;EACE;;;ACnBN;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;;AAGF;EACE;;AAIF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;;AC3BF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;;AAOJ;EAIM;AAAA;IACE;IACA;;;AC1CN;EACE;EACA;EACA;EACA;;AAEF;EACE;AACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;;;AASA;EACE;EACA;;;AAKN;EACE;;;AAGF;EACE;;;AClFF;EACE;EACA;EACA;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;EACA;;;AAGJ;EACE;EACA;EACA;;AAEA;EALF;IAMI;;;AAGF;EACE;;AAEA;EAHF;IAII;;;;AAKN;EACE;;AAEA;EACE;;AAGF;EACE;;AAIA;EADF;IAEI;;;;AAIN;EACE;;AAEA;EAHF;IAII;;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EARF;IASI;IACA;IACA;;;;ACrEJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAIF;EACE;EACA;EACA;EACA;EACA;;;ACvBF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EAEA;EACA;EACA;;AACA;EACE;;AAGF;AAAA;EAEE;EACA;;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;;AAGF;EACE;;;AAIJ;AAAA;EAEE;EACA;;AAEA;AAAA;EACE;;;AAKF;EACE;;;AAMF;AAAA;EACE;;;AC/DJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;AAGA;EANF;IAOI;;;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;AACA;EACE;EACA;EACA;EACA;;;AAME;EADF;IAEI;IACA;IACA;;EAEA;IACE;;;;AChDR;EACE;EACA;EACA;EACA;;AAIA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAKF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;;AAKF;EACE;EACA;EACA;;AAGA;EACE;EACA;EACA;;AAIF;EACE;EACA;EACA;;AAEA;EACE;;AAKJ;EACE;;AAEF;EACE;;AAMJ;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAMJ;EACE;EACA;EACA;;;AC7FF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;IACE;;EAEF;IAEE;;;;AC9CN;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEA;EAEE;;AAMN;EACE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEE;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;;;AC1EE;EACE;;;AAMN;EACE;;;AAIF;EACE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AAKF;EACE;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAKE;;;AD9CN;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAEA;EAEE;;AAMN;EACE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEE;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;;;AEhFF;EACE;EACA;EACA;EACA;EAGA;;;ADDE;EACE;;;AAMN;EACE;;;AAIF;EACE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AAKF;EACE;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;EAKE;;;AE7CN;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;;AAKF;AAAA;EAEE;EACA;EACA;;;ACtBJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;;ALjBJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EAEE;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;IACE;;EAEF;IAEE;;;;AMjDN;EACE;EACA;;AAEA;EAJF;IAKI;IACA;;;AAKA;EACE;;;AAOF;EACE;;;ACnBJ;EACE;;AAEA;EAHF;IAII;;;AAGF;EAPF;IAQI;;;AAKF;EACE;EACA;;AAIJ;AAAA;EAEE;EACA;;AAIF;EACE;EACA;EACA;;;AC7BJ;EACE;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AChDF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAKA;EACE;;AAIJ;EAEE;;AAEA;EACE;;AAKA;EACE;;;AC5BR;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAMA;EACE;;AAKJ;EACE;EACA;;AAGA;EACE;;AAKA;EACE;;;AAMR;EACE;IACE;;EAEF;IACE;;;AC1CJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EAEE;EACA;;AAEA;EACE;;;AAMJ;EACE;;AACA;EACE;;AAIJ;EACE;EACA;;AAGF;AAAA;EAEE;;;AAIJ;EACE;IACE;IACA;;EAEF;IACE;IACA;;;AC/CJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;;AAKA;EACE;;;ACrBR;EACE;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACE;;;AAIJ;EACE;IACE;IACA;;;AAKF;EACE;IACE;IACA;;;;ACxFN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;EAIF;;AAEA;EACE;;AAGF;EAEE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAIF;EA3CF;IA4CI;;;;AC9CJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAIA;EAVF;IAWI;;;AAGF;EAdF;IAeI;;;;AAIJ;EACE;;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAGI;AAAA;IACE;IACA;;;ADtCN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YACE;EAIF;;AAEA;EACE;;AAGF;EAEE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAIF;EA3CF;IA4CI;;;;AEhDJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;;;AAKN;EACE;EACA;;;AC1BF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AChCF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;EACE;;AAGJ;EACE;EACA;;AAKA;AAAA;EACE;;AAGJ;EACE;;;ACrER;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAIF;EACE;EACA;;;AAGA;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AC9BA;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAIF;EACE;IACE;IACA;;;;AAKN;AAAA;EAGE;;AAGE;AAAA;EACE;;AAIJ;AAAA;EACE;;;AC5BJ;EAKE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EASA;EACA;EAEA;EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EAMA;EAKA;EAEA;EACA;EACA;EAEA;EAEA;;;AAMF;EACE;EACA;EAEA;EAEA;EACA;;;AAGF;EACE;EACA","file":"main.css"}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
// ============================================================================
|
2
|
+
// Chatbot Main - Message - Content - Image
|
3
|
+
// ============================================================================
|
4
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
5
|
+
var t = {};
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
7
|
+
t[p] = s[p];
|
8
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
9
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
10
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
11
|
+
t[p[i]] = s[p[i]];
|
12
|
+
}
|
13
|
+
return t;
|
14
|
+
};
|
15
|
+
import React from 'react';
|
16
|
+
const ImageMessage = (_a) => {
|
17
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
18
|
+
return (React.createElement("img", Object.assign({ className: "pf-chatbot__message-image" }, props), children));
|
19
|
+
};
|
20
|
+
export default ImageMessage;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { ReactNode } from 'react';
|
2
2
|
import { AvatarProps, LabelGroupProps } from '@patternfly/react-core';
|
3
3
|
import { ActionProps } from '../ResponseActions/ResponseActions';
|
4
4
|
import { SourcesCardProps } from '../SourcesCard';
|
@@ -25,6 +25,14 @@ export interface MessageAttachment {
|
|
25
25
|
/** Custom test id for the loading spinner in the attachment component */
|
26
26
|
spinnerTestId?: string;
|
27
27
|
}
|
28
|
+
export interface MessageExtraContent {
|
29
|
+
/** Content to display before the main content */
|
30
|
+
beforeMainContent?: ReactNode;
|
31
|
+
/** Content to display after the main content */
|
32
|
+
afterMainContent?: ReactNode;
|
33
|
+
/** Content to display at the end */
|
34
|
+
endContent?: ReactNode;
|
35
|
+
}
|
28
36
|
export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'role'> {
|
29
37
|
/** Unique id for message */
|
30
38
|
id?: string;
|
@@ -32,6 +40,8 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
|
|
32
40
|
role: 'user' | 'bot';
|
33
41
|
/** Message content */
|
34
42
|
content?: string;
|
43
|
+
/** Extra Message content */
|
44
|
+
extraContent?: MessageExtraContent;
|
35
45
|
/** Name of the user */
|
36
46
|
name?: string;
|
37
47
|
/** Avatar src for the user */
|
@@ -35,8 +35,11 @@ import TdMessage from './TableMessage/TdMessage';
|
|
35
35
|
import TbodyMessage from './TableMessage/TbodyMessage';
|
36
36
|
import TheadMessage from './TableMessage/TheadMessage';
|
37
37
|
import ThMessage from './TableMessage/ThMessage';
|
38
|
+
import ImageMessage from './ImageMessage/ImageMessage';
|
39
|
+
import rehypeUnwrapImages from 'rehype-unwrap-images';
|
38
40
|
export const MessageBase = (_a) => {
|
39
|
-
var { role, content, 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 } = _a, props = __rest(_a, ["role", "content", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps"]);
|
41
|
+
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 } = _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"]);
|
42
|
+
const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
|
40
43
|
let avatarClassName;
|
41
44
|
if (avatarProps && 'className' in avatarProps) {
|
42
45
|
const { className } = avatarProps, rest = __rest(avatarProps, ["className"]);
|
@@ -56,34 +59,38 @@ export const MessageBase = (_a) => {
|
|
56
59
|
React.createElement(Timestamp, { date: date }, timestamp)),
|
57
60
|
React.createElement("div", { className: "pf-chatbot__message-response" },
|
58
61
|
React.createElement("div", { className: "pf-chatbot__message-and-actions" },
|
59
|
-
isLoading ? (React.createElement(MessageLoading, { loadingWord: loadingWord })) : (React.createElement(
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
62
|
+
isLoading ? (React.createElement(MessageLoading, { loadingWord: loadingWord })) : (React.createElement(React.Fragment, null,
|
63
|
+
beforeMainContent && React.createElement(React.Fragment, null, beforeMainContent),
|
64
|
+
React.createElement(Markdown, { components: {
|
65
|
+
p: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.p }, props)),
|
66
|
+
code: (_a) => {
|
67
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
68
|
+
return (React.createElement(CodeBlockMessage, Object.assign({}, props, codeBlockProps), children));
|
69
|
+
},
|
70
|
+
h1: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.h1 }, props)),
|
71
|
+
h2: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.h2 }, props)),
|
72
|
+
h3: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.h3 }, props)),
|
73
|
+
h4: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.h4 }, props)),
|
74
|
+
h5: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.h5 }, props)),
|
75
|
+
h6: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.h6 }, props)),
|
76
|
+
blockquote: (props) => React.createElement(TextMessage, Object.assign({ component: ContentVariants.blockquote }, props)),
|
77
|
+
ul: (props) => React.createElement(UnorderedListMessage, Object.assign({}, props)),
|
78
|
+
ol: (props) => React.createElement(OrderedListMessage, Object.assign({}, props)),
|
79
|
+
li: (props) => React.createElement(ListItemMessage, Object.assign({}, props)),
|
80
|
+
table: (props) => React.createElement(TableMessage, Object.assign({}, props, tableProps)),
|
81
|
+
tbody: (props) => React.createElement(TbodyMessage, Object.assign({}, props)),
|
82
|
+
thead: (props) => React.createElement(TheadMessage, Object.assign({}, props)),
|
83
|
+
tr: (props) => React.createElement(TrMessage, Object.assign({}, props)),
|
84
|
+
td: (props) => {
|
85
|
+
// Conflicts with Td type
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
87
|
+
const { width } = props, rest = __rest(props, ["width"]);
|
88
|
+
return React.createElement(TdMessage, Object.assign({}, rest));
|
89
|
+
},
|
90
|
+
th: (props) => React.createElement(ThMessage, Object.assign({}, props)),
|
91
|
+
img: (props) => React.createElement(ImageMessage, Object.assign({}, props))
|
92
|
+
}, remarkPlugins: [remarkGfm], rehypePlugins: [rehypeUnwrapImages] }, content),
|
93
|
+
afterMainContent && React.createElement(React.Fragment, null, afterMainContent))),
|
87
94
|
!isLoading && sources && React.createElement(SourcesCard, Object.assign({}, sources)),
|
88
95
|
quickStarts && quickStarts.quickStart && (React.createElement(QuickStartTile, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel })),
|
89
96
|
!isLoading && actions && React.createElement(ResponseActions, { actions: actions }),
|
@@ -94,7 +101,8 @@ export const MessageBase = (_a) => {
|
|
94
101
|
var _a;
|
95
102
|
return (React.createElement("div", { key: (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name, className: "pf-chatbot__message-attachment" },
|
96
103
|
React.createElement(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 })));
|
97
|
-
})))
|
104
|
+
}))),
|
105
|
+
!isLoading && endContent && React.createElement(React.Fragment, null, endContent)))));
|
98
106
|
};
|
99
107
|
const Message = React.forwardRef((props, ref) => (React.createElement(MessageBase, Object.assign({ innerRef: ref }, props))));
|
100
108
|
export default Message;
|
@@ -132,6 +132,7 @@ const EMPTY_TABLE = `
|
|
132
132
|
| |
|
133
133
|
|
134
134
|
`;
|
135
|
+
const IMAGE = ``;
|
135
136
|
const checkListItemsRendered = () => {
|
136
137
|
const items = ['Item 1', 'Item 2', 'Item 3'];
|
137
138
|
expect(screen.getAllByRole('listitem')).toHaveLength(3);
|
@@ -507,4 +508,71 @@ describe('Message', () => {
|
|
507
508
|
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: TABLE, tableProps: { 'aria-label': 'Test' } }));
|
508
509
|
expect(screen.getByRole('grid', { name: /Test/i })).toBeTruthy();
|
509
510
|
});
|
511
|
+
it('should render beforeMainContent with main content', () => {
|
512
|
+
const mainContent = 'Main message content';
|
513
|
+
const beforeMainContentText = 'Before main content';
|
514
|
+
const beforeMainContent = React.createElement("div", null, beforeMainContentText);
|
515
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: mainContent, extraContent: { beforeMainContent } }));
|
516
|
+
expect(screen.getByText(beforeMainContentText)).toBeTruthy();
|
517
|
+
expect(screen.getByText(mainContent)).toBeTruthy();
|
518
|
+
});
|
519
|
+
it('should render afterMainContent with main content', () => {
|
520
|
+
const mainContent = 'Main message content';
|
521
|
+
const afterMainContentText = 'After main content';
|
522
|
+
const afterMainContent = React.createElement("div", null, afterMainContentText);
|
523
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: mainContent, extraContent: { afterMainContent } }));
|
524
|
+
expect(screen.getByText(afterMainContentText)).toBeTruthy();
|
525
|
+
expect(screen.getByText(mainContent)).toBeTruthy();
|
526
|
+
});
|
527
|
+
it('should render endContent with main content', () => {
|
528
|
+
const mainContent = 'Main message content';
|
529
|
+
const endMainContentText = 'End content';
|
530
|
+
const endContent = React.createElement("div", null, endMainContentText);
|
531
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: mainContent, extraContent: { endContent } }));
|
532
|
+
expect(screen.getByText(endMainContentText)).toBeTruthy();
|
533
|
+
expect(screen.getByText(mainContent)).toBeTruthy();
|
534
|
+
});
|
535
|
+
it('should render all parts of extraContent with main content', () => {
|
536
|
+
const beforeMainContent = React.createElement("div", null, "Before main content");
|
537
|
+
const afterMainContent = React.createElement("div", null, "After main content");
|
538
|
+
const endContent = React.createElement("div", null, "End content");
|
539
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: "Main message content", extraContent: { beforeMainContent, afterMainContent, endContent } }));
|
540
|
+
expect(screen.getByText('Before main content')).toBeTruthy();
|
541
|
+
expect(screen.getByText('Main message content')).toBeTruthy();
|
542
|
+
expect(screen.getByText('After main content')).toBeTruthy();
|
543
|
+
expect(screen.getByText('End content')).toBeTruthy();
|
544
|
+
});
|
545
|
+
it('should not render extraContent when not provided', () => {
|
546
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: "Main message content" }));
|
547
|
+
// Ensure no extraContent is rendered
|
548
|
+
expect(screen.getByText('Main message content')).toBeTruthy();
|
549
|
+
expect(screen.queryByText('Before main content')).toBeFalsy();
|
550
|
+
expect(screen.queryByText('After main content')).toBeFalsy();
|
551
|
+
expect(screen.queryByText('end message content')).toBeFalsy();
|
552
|
+
});
|
553
|
+
it('should handle undefined or null values in extraContent gracefully', () => {
|
554
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: "Main message content", extraContent: { beforeMainContent: null, afterMainContent: undefined, endContent: null } }));
|
555
|
+
// Ensure that no extraContent is rendered if they are null or undefined
|
556
|
+
expect(screen.getByText('Main message content')).toBeTruthy();
|
557
|
+
expect(screen.queryByText('Before main content')).toBeFalsy();
|
558
|
+
expect(screen.queryByText('After main content')).toBeFalsy();
|
559
|
+
expect(screen.queryByText('end message content')).toBeFalsy();
|
560
|
+
});
|
561
|
+
it('should render JSX in extraContent correctly', () => {
|
562
|
+
const beforeMainContent = (React.createElement("div", { "data-testid": "before-main-content" },
|
563
|
+
React.createElement("strong", null, "Bold before content")));
|
564
|
+
const afterMainContent = (React.createElement("div", { "data-testid": "after-main-content" },
|
565
|
+
React.createElement("strong", null, "Bold after content")));
|
566
|
+
const endContent = (React.createElement("div", { "data-testid": "end-main-content" },
|
567
|
+
React.createElement("strong", null, "Bold end content")));
|
568
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: "Main message content", extraContent: { beforeMainContent, afterMainContent, endContent } }));
|
569
|
+
// Check that the JSX is correctly rendered
|
570
|
+
expect(screen.getByTestId('before-main-content')).toContainHTML('<strong>Bold before content</strong>');
|
571
|
+
expect(screen.getByTestId('after-main-content')).toContainHTML('<strong>Bold after content</strong>');
|
572
|
+
expect(screen.getByTestId('end-main-content')).toContainHTML('<strong>Bold end content</strong>');
|
573
|
+
});
|
574
|
+
it('should handle image correctly', () => {
|
575
|
+
render(React.createElement(Message, { avatar: "./img", role: "user", name: "User", content: IMAGE }));
|
576
|
+
expect(screen.getByRole('img', { name: /Multi-colored wavy lines on a black background/i })).toBeTruthy();
|
577
|
+
});
|
510
578
|
});
|
@@ -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/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/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.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.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/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/ListMessage/ListItemMessage.tsx","../src/Message/ListMessage/OrderedListMessage.tsx","../src/Message/ListMessage/UnorderedListMessage.tsx","../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/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"],"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/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/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.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.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/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/ImageMessage/ImageMessage.tsx","../src/Message/ListMessage/ListItemMessage.tsx","../src/Message/ListMessage/OrderedListMessage.tsx","../src/Message/ListMessage/UnorderedListMessage.tsx","../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/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/__mocks__/rehype-unwrap-images.tsx"],"version":"5.6.3"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@patternfly/chatbot",
|
3
|
-
"version": "2.2.0-prerelease.
|
3
|
+
"version": "2.2.0-prerelease.25",
|
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",
|
@@ -39,6 +39,7 @@
|
|
39
39
|
"react-markdown": "^9.0.1",
|
40
40
|
"react-syntax-highlighter": "^15.5.0",
|
41
41
|
"remark-gfm": "^4.0.0",
|
42
|
+
"rehype-unwrap-images": "^1.0.0",
|
42
43
|
"path-browserify": "^1.0.1"
|
43
44
|
},
|
44
45
|
"peerDependencies": {
|
@@ -30,6 +30,8 @@ export const BotMessageExample: React.FunctionComponent = () => {
|
|
30
30
|
return link;
|
31
31
|
case 'table':
|
32
32
|
return table;
|
33
|
+
case 'image':
|
34
|
+
return image;
|
33
35
|
default:
|
34
36
|
return;
|
35
37
|
}
|
@@ -136,6 +138,8 @@ _Italic text, formatted with single underscores_
|
|
136
138
|
| 3.0 | April 1, 2025 | Administrator
|
137
139
|
`;
|
138
140
|
|
141
|
+
const image = ``;
|
142
|
+
|
139
143
|
return (
|
140
144
|
<>
|
141
145
|
<Message name="Bot" role="bot" avatar={patternflyAvatar} content={`Text-based message from a bot named "Bot"`} />
|
@@ -234,6 +238,13 @@ _Italic text, formatted with single underscores_
|
|
234
238
|
label="Table"
|
235
239
|
id="table"
|
236
240
|
/>
|
241
|
+
<Radio
|
242
|
+
isChecked={variant === 'image'}
|
243
|
+
onChange={() => setVariant('image')}
|
244
|
+
name="bot-message-type"
|
245
|
+
label="Image"
|
246
|
+
id="image"
|
247
|
+
/>
|
237
248
|
</FormGroup>
|
238
249
|
</Form>
|
239
250
|
<Message
|
@@ -19,6 +19,7 @@ propComponents:
|
|
19
19
|
'FileDropZone',
|
20
20
|
'PreviewAttachment',
|
21
21
|
'Message',
|
22
|
+
'MessageExtraContent',
|
22
23
|
'PreviewAttachment',
|
23
24
|
'ActionProps',
|
24
25
|
'SourcesCardProps',
|
@@ -165,6 +166,16 @@ Messages from users have a different background color to differentiate them from
|
|
165
166
|
|
166
167
|
```
|
167
168
|
|
169
|
+
### Custom message content
|
170
|
+
|
171
|
+
**Caution:** Take care when using this feature. It can cause you to stray from accessibility and design best practice standards. If you frequently need add the same component via custom message content, reach out to the PatternFly team. If there's a consistent need for a certain component, we can look into adding native support for additional features.
|
172
|
+
|
173
|
+
You can add custom content to specific parts of a `<Message>` via the `extraContent` prop, including additional components (like timestamps, badges, or custom elements). This prop allows you to create dynamic and reusable elements for various use cases, without changing the default message layout.
|
174
|
+
|
175
|
+
```js file="./UserMessageWithExtraContent.tsx"
|
176
|
+
|
177
|
+
```
|
178
|
+
|
168
179
|
## File attachments
|
169
180
|
|
170
181
|
### Messages with attachments
|
@@ -30,6 +30,8 @@ export const UserMessageExample: React.FunctionComponent = () => {
|
|
30
30
|
return link;
|
31
31
|
case 'table':
|
32
32
|
return table;
|
33
|
+
case 'image':
|
34
|
+
return image;
|
33
35
|
default:
|
34
36
|
return;
|
35
37
|
}
|
@@ -136,6 +138,8 @@ _Italic text, formatted with single underscores_
|
|
136
138
|
| 3.0 | April 1, 2025 | Administrator
|
137
139
|
`;
|
138
140
|
|
141
|
+
const image = ``;
|
142
|
+
|
139
143
|
return (
|
140
144
|
<>
|
141
145
|
<Message
|
@@ -224,6 +228,13 @@ _Italic text, formatted with single underscores_
|
|
224
228
|
label="Table"
|
225
229
|
id="user-table"
|
226
230
|
/>
|
231
|
+
<Radio
|
232
|
+
isChecked={variant === 'image'}
|
233
|
+
onChange={() => setVariant('image')}
|
234
|
+
name="user-message-type"
|
235
|
+
label="Image"
|
236
|
+
id="user-image"
|
237
|
+
/>
|
227
238
|
</FormGroup>
|
228
239
|
</Form>
|
229
240
|
<Message
|
package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
import Message from '@patternfly/chatbot/dist/dynamic/Message';
|
4
|
+
import userAvatar from './user_avatar.svg';
|
5
|
+
import { Alert, Badge, Button, Card, CardBody, CardFooter, CardTitle } from '@patternfly/react-core';
|
6
|
+
|
7
|
+
const UserActionEndContent = () => {
|
8
|
+
// eslint-disable-next-line no-console
|
9
|
+
const onClick = () => console.log('custom button click');
|
10
|
+
return (
|
11
|
+
<React.Fragment>
|
12
|
+
<Button variant="secondary" ouiaId="Secondary" onClick={onClick}>
|
13
|
+
End content button
|
14
|
+
</Button>
|
15
|
+
<Alert variant="danger" title="Danger alert title" ouiaId="DangerAlert" />
|
16
|
+
</React.Fragment>
|
17
|
+
);
|
18
|
+
};
|
19
|
+
|
20
|
+
const CardInformationAfterMainContent = () => (
|
21
|
+
<Card ouiaId="BasicCard">
|
22
|
+
<CardTitle>This is content card after main content</CardTitle>
|
23
|
+
<CardBody>Body</CardBody>
|
24
|
+
<CardFooter>Footer</CardFooter>
|
25
|
+
</Card>
|
26
|
+
);
|
27
|
+
|
28
|
+
const BeforeMainContent = () => (
|
29
|
+
<div>
|
30
|
+
<Badge key={1} isRead>
|
31
|
+
7
|
32
|
+
</Badge>
|
33
|
+
<Badge key={2} isRead>
|
34
|
+
24
|
35
|
+
</Badge>
|
36
|
+
</div>
|
37
|
+
);
|
38
|
+
|
39
|
+
export const UserMessageWithExtraContent: React.FunctionComponent = () => (
|
40
|
+
<>
|
41
|
+
<Message
|
42
|
+
avatar={userAvatar}
|
43
|
+
name="User"
|
44
|
+
role="user"
|
45
|
+
content="This is a main message."
|
46
|
+
timestamp="1 hour ago"
|
47
|
+
extraContent={{
|
48
|
+
beforeMainContent: <BeforeMainContent />,
|
49
|
+
afterMainContent: <CardInformationAfterMainContent />,
|
50
|
+
endContent: <UserActionEndContent />
|
51
|
+
}}
|
52
|
+
/>
|
53
|
+
</>
|
54
|
+
);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
.pf-chatbot__message-image {
|
2
|
+
border-radius: var(--pf-t--global--border--radius--small);
|
3
|
+
max-width: 37.5rem; // 600px
|
4
|
+
max-height: 25rem; // 400px
|
5
|
+
min-height: 6.25rem; // 100px
|
6
|
+
// with rehypePlugins={[rehypeUnwrapImages]}, image is not wrapped in p if it is by itself
|
7
|
+
// however, if in a paragraph tag as part of other content, it should be a block element
|
8
|
+
display: block;
|
9
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
// ============================================================================
|
2
|
+
// Chatbot Main - Message - Content - Image
|
3
|
+
// ============================================================================
|
4
|
+
|
5
|
+
import React from 'react';
|
6
|
+
import { ExtraProps } from 'react-markdown';
|
7
|
+
|
8
|
+
const ImageMessage = ({ children, ...props }: JSX.IntrinsicElements['img'] & ExtraProps) => (
|
9
|
+
<img className="pf-chatbot__message-image" {...props}>
|
10
|
+
{children}
|
11
|
+
</img>
|
12
|
+
);
|
13
|
+
|
14
|
+
export default ImageMessage;
|
@@ -138,6 +138,8 @@ const EMPTY_TABLE = `
|
|
138
138
|
|
139
139
|
`;
|
140
140
|
|
141
|
+
const IMAGE = ``;
|
142
|
+
|
141
143
|
const checkListItemsRendered = () => {
|
142
144
|
const items = ['Item 1', 'Item 2', 'Item 3'];
|
143
145
|
expect(screen.getAllByRole('listitem')).toHaveLength(3);
|
@@ -627,4 +629,122 @@ describe('Message', () => {
|
|
627
629
|
render(<Message avatar="./img" role="user" name="User" content={TABLE} tableProps={{ 'aria-label': 'Test' }} />);
|
628
630
|
expect(screen.getByRole('grid', { name: /Test/i })).toBeTruthy();
|
629
631
|
});
|
632
|
+
it('should render beforeMainContent with main content', () => {
|
633
|
+
const mainContent = 'Main message content';
|
634
|
+
const beforeMainContentText = 'Before main content';
|
635
|
+
const beforeMainContent = <div>{beforeMainContentText}</div>;
|
636
|
+
|
637
|
+
render(
|
638
|
+
<Message avatar="./img" role="user" name="User" content={mainContent} extraContent={{ beforeMainContent }} />
|
639
|
+
);
|
640
|
+
|
641
|
+
expect(screen.getByText(beforeMainContentText)).toBeTruthy();
|
642
|
+
expect(screen.getByText(mainContent)).toBeTruthy();
|
643
|
+
});
|
644
|
+
it('should render afterMainContent with main content', () => {
|
645
|
+
const mainContent = 'Main message content';
|
646
|
+
const afterMainContentText = 'After main content';
|
647
|
+
const afterMainContent = <div>{afterMainContentText}</div>;
|
648
|
+
|
649
|
+
render(
|
650
|
+
<Message avatar="./img" role="user" name="User" content={mainContent} extraContent={{ afterMainContent }} />
|
651
|
+
);
|
652
|
+
|
653
|
+
expect(screen.getByText(afterMainContentText)).toBeTruthy();
|
654
|
+
expect(screen.getByText(mainContent)).toBeTruthy();
|
655
|
+
});
|
656
|
+
|
657
|
+
it('should render endContent with main content', () => {
|
658
|
+
const mainContent = 'Main message content';
|
659
|
+
const endMainContentText = 'End content';
|
660
|
+
const endContent = <div>{endMainContentText}</div>;
|
661
|
+
|
662
|
+
render(<Message avatar="./img" role="user" name="User" content={mainContent} extraContent={{ endContent }} />);
|
663
|
+
|
664
|
+
expect(screen.getByText(endMainContentText)).toBeTruthy();
|
665
|
+
expect(screen.getByText(mainContent)).toBeTruthy();
|
666
|
+
});
|
667
|
+
it('should render all parts of extraContent with main content', () => {
|
668
|
+
const beforeMainContent = <div>Before main content</div>;
|
669
|
+
const afterMainContent = <div>After main content</div>;
|
670
|
+
const endContent = <div>End content</div>;
|
671
|
+
|
672
|
+
render(
|
673
|
+
<Message
|
674
|
+
avatar="./img"
|
675
|
+
role="user"
|
676
|
+
name="User"
|
677
|
+
content="Main message content"
|
678
|
+
extraContent={{ beforeMainContent, afterMainContent, endContent }}
|
679
|
+
/>
|
680
|
+
);
|
681
|
+
|
682
|
+
expect(screen.getByText('Before main content')).toBeTruthy();
|
683
|
+
expect(screen.getByText('Main message content')).toBeTruthy();
|
684
|
+
expect(screen.getByText('After main content')).toBeTruthy();
|
685
|
+
expect(screen.getByText('End content')).toBeTruthy();
|
686
|
+
});
|
687
|
+
|
688
|
+
it('should not render extraContent when not provided', () => {
|
689
|
+
render(<Message avatar="./img" role="user" name="User" content="Main message content" />);
|
690
|
+
|
691
|
+
// Ensure no extraContent is rendered
|
692
|
+
expect(screen.getByText('Main message content')).toBeTruthy();
|
693
|
+
expect(screen.queryByText('Before main content')).toBeFalsy();
|
694
|
+
expect(screen.queryByText('After main content')).toBeFalsy();
|
695
|
+
expect(screen.queryByText('end message content')).toBeFalsy();
|
696
|
+
});
|
697
|
+
|
698
|
+
it('should handle undefined or null values in extraContent gracefully', () => {
|
699
|
+
render(
|
700
|
+
<Message
|
701
|
+
avatar="./img"
|
702
|
+
role="user"
|
703
|
+
name="User"
|
704
|
+
content="Main message content"
|
705
|
+
extraContent={{ beforeMainContent: null, afterMainContent: undefined, endContent: null }}
|
706
|
+
/>
|
707
|
+
);
|
708
|
+
|
709
|
+
// Ensure that no extraContent is rendered if they are null or undefined
|
710
|
+
expect(screen.getByText('Main message content')).toBeTruthy();
|
711
|
+
expect(screen.queryByText('Before main content')).toBeFalsy();
|
712
|
+
expect(screen.queryByText('After main content')).toBeFalsy();
|
713
|
+
expect(screen.queryByText('end message content')).toBeFalsy();
|
714
|
+
});
|
715
|
+
it('should render JSX in extraContent correctly', () => {
|
716
|
+
const beforeMainContent = (
|
717
|
+
<div data-testid="before-main-content">
|
718
|
+
<strong>Bold before content</strong>
|
719
|
+
</div>
|
720
|
+
);
|
721
|
+
const afterMainContent = (
|
722
|
+
<div data-testid="after-main-content">
|
723
|
+
<strong>Bold after content</strong>
|
724
|
+
</div>
|
725
|
+
);
|
726
|
+
const endContent = (
|
727
|
+
<div data-testid="end-main-content">
|
728
|
+
<strong>Bold end content</strong>
|
729
|
+
</div>
|
730
|
+
);
|
731
|
+
render(
|
732
|
+
<Message
|
733
|
+
avatar="./img"
|
734
|
+
role="user"
|
735
|
+
name="User"
|
736
|
+
content="Main message content"
|
737
|
+
extraContent={{ beforeMainContent, afterMainContent, endContent }}
|
738
|
+
/>
|
739
|
+
);
|
740
|
+
|
741
|
+
// Check that the JSX is correctly rendered
|
742
|
+
expect(screen.getByTestId('before-main-content')).toContainHTML('<strong>Bold before content</strong>');
|
743
|
+
expect(screen.getByTestId('after-main-content')).toContainHTML('<strong>Bold after content</strong>');
|
744
|
+
expect(screen.getByTestId('end-main-content')).toContainHTML('<strong>Bold end content</strong>');
|
745
|
+
});
|
746
|
+
it('should handle image correctly', () => {
|
747
|
+
render(<Message avatar="./img" role="user" name="User" content={IMAGE} />);
|
748
|
+
expect(screen.getByRole('img', { name: /Multi-colored wavy lines on a black background/i })).toBeTruthy();
|
749
|
+
});
|
630
750
|
});
|
package/src/Message/Message.tsx
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
// Chatbot Main - Message
|
3
3
|
// ============================================================================
|
4
4
|
|
5
|
-
import React from 'react';
|
5
|
+
import React, { ReactNode } from 'react';
|
6
6
|
|
7
7
|
import Markdown from 'react-markdown';
|
8
8
|
import remarkGfm from 'remark-gfm';
|
@@ -36,6 +36,8 @@ import TbodyMessage from './TableMessage/TbodyMessage';
|
|
36
36
|
import TheadMessage from './TableMessage/TheadMessage';
|
37
37
|
import ThMessage from './TableMessage/ThMessage';
|
38
38
|
import { TableProps } from '@patternfly/react-table';
|
39
|
+
import ImageMessage from './ImageMessage/ImageMessage';
|
40
|
+
import rehypeUnwrapImages from 'rehype-unwrap-images';
|
39
41
|
|
40
42
|
export interface MessageAttachment {
|
41
43
|
/** Name of file attached to the message */
|
@@ -56,6 +58,17 @@ export interface MessageAttachment {
|
|
56
58
|
spinnerTestId?: string;
|
57
59
|
}
|
58
60
|
|
61
|
+
export interface MessageExtraContent {
|
62
|
+
/** Content to display before the main content */
|
63
|
+
beforeMainContent?: ReactNode;
|
64
|
+
|
65
|
+
/** Content to display after the main content */
|
66
|
+
afterMainContent?: ReactNode;
|
67
|
+
|
68
|
+
/** Content to display at the end */
|
69
|
+
endContent?: ReactNode;
|
70
|
+
}
|
71
|
+
|
59
72
|
export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'role'> {
|
60
73
|
/** Unique id for message */
|
61
74
|
id?: string;
|
@@ -63,6 +76,8 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
|
|
63
76
|
role: 'user' | 'bot';
|
64
77
|
/** Message content */
|
65
78
|
content?: string;
|
79
|
+
/** Extra Message content */
|
80
|
+
extraContent?: MessageExtraContent;
|
66
81
|
/** Name of the user */
|
67
82
|
name?: string;
|
68
83
|
/** Avatar src for the user */
|
@@ -123,6 +138,7 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
|
|
123
138
|
export const MessageBase: React.FunctionComponent<MessageProps> = ({
|
124
139
|
role,
|
125
140
|
content,
|
141
|
+
extraContent,
|
126
142
|
name,
|
127
143
|
avatar,
|
128
144
|
timestamp,
|
@@ -145,6 +161,7 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
|
|
145
161
|
tableProps,
|
146
162
|
...props
|
147
163
|
}: MessageProps) => {
|
164
|
+
const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
|
148
165
|
let avatarClassName;
|
149
166
|
if (avatarProps && 'className' in avatarProps) {
|
150
167
|
const { className, ...rest } = avatarProps;
|
@@ -189,40 +206,46 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
|
|
189
206
|
{isLoading ? (
|
190
207
|
<MessageLoading loadingWord={loadingWord} />
|
191
208
|
) : (
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
<
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
209
|
+
<>
|
210
|
+
{beforeMainContent && <>{beforeMainContent}</>}
|
211
|
+
<Markdown
|
212
|
+
components={{
|
213
|
+
p: (props) => <TextMessage component={ContentVariants.p} {...props} />,
|
214
|
+
code: ({ children, ...props }) => (
|
215
|
+
<CodeBlockMessage {...props} {...codeBlockProps}>
|
216
|
+
{children}
|
217
|
+
</CodeBlockMessage>
|
218
|
+
),
|
219
|
+
h1: (props) => <TextMessage component={ContentVariants.h1} {...props} />,
|
220
|
+
h2: (props) => <TextMessage component={ContentVariants.h2} {...props} />,
|
221
|
+
h3: (props) => <TextMessage component={ContentVariants.h3} {...props} />,
|
222
|
+
h4: (props) => <TextMessage component={ContentVariants.h4} {...props} />,
|
223
|
+
h5: (props) => <TextMessage component={ContentVariants.h5} {...props} />,
|
224
|
+
h6: (props) => <TextMessage component={ContentVariants.h6} {...props} />,
|
225
|
+
blockquote: (props) => <TextMessage component={ContentVariants.blockquote} {...props} />,
|
226
|
+
ul: (props) => <UnorderedListMessage {...props} />,
|
227
|
+
ol: (props) => <OrderedListMessage {...props} />,
|
228
|
+
li: (props) => <ListItemMessage {...props} />,
|
229
|
+
table: (props) => <TableMessage {...props} {...tableProps} />,
|
230
|
+
tbody: (props) => <TbodyMessage {...props} />,
|
231
|
+
thead: (props) => <TheadMessage {...props} />,
|
232
|
+
tr: (props) => <TrMessage {...props} />,
|
233
|
+
td: (props) => {
|
234
|
+
// Conflicts with Td type
|
235
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
236
|
+
const { width, ...rest } = props;
|
237
|
+
return <TdMessage {...rest} />;
|
238
|
+
},
|
239
|
+
th: (props) => <ThMessage {...props} />,
|
240
|
+
img: (props) => <ImageMessage {...props} />
|
241
|
+
}}
|
242
|
+
remarkPlugins={[remarkGfm]}
|
243
|
+
rehypePlugins={[rehypeUnwrapImages]}
|
244
|
+
>
|
245
|
+
{content}
|
246
|
+
</Markdown>
|
247
|
+
{afterMainContent && <>{afterMainContent}</>}
|
248
|
+
</>
|
226
249
|
)}
|
227
250
|
{!isLoading && sources && <SourcesCard {...sources} />}
|
228
251
|
{quickStarts && quickStarts.quickStart && (
|
@@ -264,6 +287,7 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
|
|
264
287
|
))}
|
265
288
|
</div>
|
266
289
|
)}
|
290
|
+
{!isLoading && endContent && <>{endContent}</>}
|
267
291
|
</div>
|
268
292
|
</div>
|
269
293
|
</section>
|
package/src/main.scss
CHANGED
@@ -16,6 +16,7 @@
|
|
16
16
|
@import './FileDropZone/FileDropZone';
|
17
17
|
@import './Message/Message';
|
18
18
|
@import './Message/CodeBlockMessage/CodeBlockMessage';
|
19
|
+
@import './Message/ImageMessage/ImageMessage';
|
19
20
|
@import './Message/TextMessage/TextMessage';
|
20
21
|
@import './Message/ListMessage/ListMessage';
|
21
22
|
@import './Message/TableMessage/TableMessage';
|