@patternfly/chatbot 6.6.0-prerelease.2 → 6.6.0-prerelease.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/cjs/Message/Message.d.ts +4 -0
  2. package/dist/cjs/Message/Message.js +3 -2
  3. package/dist/cjs/Message/Message.test.js +14 -0
  4. package/dist/cjs/SourcesCard/SourcesCard.d.ts +4 -0
  5. package/dist/cjs/SourcesCard/SourcesCard.js +3 -3
  6. package/dist/cjs/SourcesCard/SourcesCard.test.js +12 -0
  7. package/dist/cjs/SourcesCardBase/SourcesCardBase.d.ts +4 -0
  8. package/dist/cjs/SourcesCardBase/SourcesCardBase.js +13 -4
  9. package/dist/cjs/SourcesCardBase/SourcesCardBase.test.js +28 -0
  10. package/dist/css/main.css +16 -0
  11. package/dist/css/main.css.map +1 -1
  12. package/dist/esm/Message/Message.d.ts +4 -0
  13. package/dist/esm/Message/Message.js +3 -2
  14. package/dist/esm/Message/Message.test.js +14 -0
  15. package/dist/esm/SourcesCard/SourcesCard.d.ts +4 -0
  16. package/dist/esm/SourcesCard/SourcesCard.js +3 -3
  17. package/dist/esm/SourcesCard/SourcesCard.test.js +12 -0
  18. package/dist/esm/SourcesCardBase/SourcesCardBase.d.ts +4 -0
  19. package/dist/esm/SourcesCardBase/SourcesCardBase.js +13 -4
  20. package/dist/esm/SourcesCardBase/SourcesCardBase.test.js +28 -0
  21. package/package.json +1 -1
  22. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +7 -0
  23. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +37 -0
  24. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +14 -0
  25. package/src/Message/Message.scss +9 -0
  26. package/src/Message/Message.test.tsx +21 -0
  27. package/src/Message/Message.tsx +23 -14
  28. package/src/SourcesCard/SourcesCard.scss +13 -1
  29. package/src/SourcesCard/SourcesCard.test.tsx +20 -0
  30. package/src/SourcesCard/SourcesCard.tsx +9 -3
  31. package/src/SourcesCardBase/SourcesCardBase.test.tsx +49 -0
  32. package/src/SourcesCardBase/SourcesCardBase.tsx +72 -3
@@ -48,6 +48,10 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
48
48
  id?: string;
49
49
  /** Role of the user sending the message */
50
50
  role: 'user' | 'bot';
51
+ /** Whether the message is aligned at the horizontal start or end of the message container. */
52
+ alignment?: 'start' | 'end';
53
+ /** Flag indicating whether message metadata (user name and timestamp) are visible. */
54
+ isMetadataVisible?: boolean;
51
55
  /** Message content */
52
56
  content?: string;
53
57
  /** Extra Message content */
@@ -37,8 +37,9 @@ const ToolResponse_1 = __importDefault(require("../ToolResponse"));
37
37
  const DeepThinking_1 = __importDefault(require("../DeepThinking"));
38
38
  const ToolCall_1 = __importDefault(require("../ToolCall"));
39
39
  const MarkdownContent_1 = __importDefault(require("../MarkdownContent"));
40
+ const react_styles_1 = require("@patternfly/react-styles");
40
41
  const MessageBase = (_a) => {
41
- var { children, role, content, extraContent, name, avatar, timestamp, isLoading, actions, persistActionSelection, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], additionalRemarkPlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking, remarkGfmProps, toolCall, hasNoImagesInUserMessages = true, isPrimary } = _a, props = __rest(_a, ["children", "role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "persistActionSelection", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages", "isPrimary"]);
42
+ var { children, role, alignment = 'start', isMetadataVisible = true, content, extraContent, name, avatar, timestamp, isLoading, actions, persistActionSelection, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], additionalRemarkPlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking, remarkGfmProps, toolCall, hasNoImagesInUserMessages = true, isPrimary } = _a, props = __rest(_a, ["children", "role", "alignment", "isMetadataVisible", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "persistActionSelection", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages", "isPrimary"]);
42
43
  const [messageText, setMessageText] = (0, react_1.useState)(content);
43
44
  (0, react_1.useEffect)(() => {
44
45
  setMessageText(content);
@@ -66,7 +67,7 @@ const MessageBase = (_a) => {
66
67
  }
67
68
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [beforeMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: beforeMainContent }), error ? (0, jsx_runtime_1.jsx)(ErrorMessage_1.default, Object.assign({}, error)) : handleMarkdown()] }));
68
69
  };
69
- return ((0, jsx_runtime_1.jsxs)("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [avatar && ((0, jsx_runtime_1.jsx)(react_core_1.Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps))), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-contents", children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-meta", children: [name && ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-name", children: (0, jsx_runtime_1.jsx)(react_core_1.Truncate, { content: name }) })), role === 'bot' && ((0, jsx_runtime_1.jsx)(react_core_1.Label, { variant: "outline", isCompact: true, children: botWord })), (0, jsx_runtime_1.jsx)(react_core_1.Timestamp, { date: date, children: timestamp })] }), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-response", children: children ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: afterMainContent }), toolResponse && (0, jsx_runtime_1.jsx)(ToolResponse_1.default, Object.assign({}, toolResponse)), deepThinking && (0, jsx_runtime_1.jsx)(DeepThinking_1.default, Object.assign({}, deepThinking)), toolCall && (0, jsx_runtime_1.jsx)(ToolCall_1.default, Object.assign({}, toolCall)), !isLoading && sources && (0, jsx_runtime_1.jsx)(SourcesCard_1.default, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && ((0, jsx_runtime_1.jsx)(QuickStartTile_1.default, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: Array.isArray(actions) ? ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__response-actions-groups", children: actions.map((actionGroup, index) => ((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actionGroup.actions || actionGroup, persistActionSelection: persistActionSelection || actionGroup.persistActionSelection }, index))) })) : ((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actions, persistActionSelection: persistActionSelection })) })), userFeedbackForm && ((0, jsx_runtime_1.jsx)(UserFeedback_1.default, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact }))), userFeedbackComplete && ((0, jsx_runtime_1.jsx)(UserFeedbackComplete_1.default, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && ((0, jsx_runtime_1.jsx)(QuickResponse_1.default, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
70
+ return ((0, jsx_runtime_1.jsxs)("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: (0, react_styles_1.css)(`pf-chatbot__message pf-chatbot__message--${role}`, alignment === 'end' && 'pf-m-end'), "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [avatar && ((0, jsx_runtime_1.jsx)(react_core_1.Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps))), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-contents", children: [isMetadataVisible && ((0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-meta", children: [name && ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-name", children: (0, jsx_runtime_1.jsx)(react_core_1.Truncate, { content: name }) })), role === 'bot' && ((0, jsx_runtime_1.jsx)(react_core_1.Label, { variant: "outline", isCompact: true, children: botWord })), (0, jsx_runtime_1.jsx)(react_core_1.Timestamp, { date: date, children: timestamp })] })), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-response", children: children ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: afterMainContent }), toolResponse && (0, jsx_runtime_1.jsx)(ToolResponse_1.default, Object.assign({}, toolResponse)), deepThinking && (0, jsx_runtime_1.jsx)(DeepThinking_1.default, Object.assign({}, deepThinking)), toolCall && (0, jsx_runtime_1.jsx)(ToolCall_1.default, Object.assign({}, toolCall)), !isLoading && sources && (0, jsx_runtime_1.jsx)(SourcesCard_1.default, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && ((0, jsx_runtime_1.jsx)(QuickStartTile_1.default, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: Array.isArray(actions) ? ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__response-actions-groups", children: actions.map((actionGroup, index) => ((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actionGroup.actions || actionGroup, persistActionSelection: persistActionSelection || actionGroup.persistActionSelection }, index))) })) : ((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actions, persistActionSelection: persistActionSelection })) })), userFeedbackForm && ((0, jsx_runtime_1.jsx)(UserFeedback_1.default, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact }))), userFeedbackComplete && ((0, jsx_runtime_1.jsx)(UserFeedbackComplete_1.default, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && ((0, jsx_runtime_1.jsx)(QuickResponse_1.default, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
70
71
  var _a;
71
72
  return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachment", children: (0, jsx_runtime_1.jsx)(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, variant: isPrimary ? 'outline' : undefined }) }, (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name));
72
73
  }) })), !isLoading && endContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: endContent })] })) })] })] })));
@@ -234,6 +234,12 @@ describe('Message', () => {
234
234
  return hasText && isVisible;
235
235
  })).not.toBeInTheDocument();
236
236
  });
237
+ it('Does not render metadata when isMetadataVisible is false', () => {
238
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { isMetadataVisible: false, avatar: "./img", role: "bot", name: "Bot", content: "Hi", timestamp: "2 hours ago" }));
239
+ expect(react_2.screen.queryByText('Bot')).not.toBeInTheDocument();
240
+ expect(react_2.screen.queryByText('AI')).not.toBeInTheDocument();
241
+ expect(react_2.screen.queryByText('2 hours ago')).not.toBeInTheDocument();
242
+ });
237
243
  it('should render attachments', () => {
238
244
  (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", content: "Hi", attachments: [{ name: 'testAttachment' }] }));
239
245
  expect(react_2.screen.getByText('Hi')).toBeTruthy();
@@ -990,4 +996,12 @@ describe('Message', () => {
990
996
  const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "", attachments: [{ name: 'testAttachment' }] }));
991
997
  expect(container.querySelector('.pf-m-outline')).toBeFalsy();
992
998
  });
999
+ it('Renders without pf-m-end class by default', () => {
1000
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "" }));
1001
+ expect(react_2.screen.getByRole('region')).not.toHaveClass('pf-m-end');
1002
+ });
1003
+ it('Renders with pf-m-end class when alignment="end"', () => {
1004
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { alignment: "end", avatar: "./img", role: "user", name: "User", content: "" }));
1005
+ expect(react_2.screen.getByRole('region')).toHaveClass('pf-m-end');
1006
+ });
993
1007
  });
@@ -3,6 +3,10 @@ import { ButtonProps, CardBodyProps, CardFooterProps, CardProps, CardTitleProps,
3
3
  export interface SourcesCardProps extends CardProps {
4
4
  /** Additional classes for the pagination navigation container. */
5
5
  className?: string;
6
+ /** The layout used to display source cards. Use wrap to display and wrap all sources at once. */
7
+ layout?: 'paginated' | 'wrap';
8
+ /** Max width of a source card when the wrap layout is used. Can be any valid CSS width value. */
9
+ cardMaxWidth?: string;
6
10
  /** Flag indicating if the pagination is disabled. */
7
11
  isDisabled?: boolean;
8
12
  /** @deprecated ofWord has been deprecated. Label for the English word "of." */
@@ -15,11 +15,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  const jsx_runtime_1 = require("react/jsx-runtime");
18
- // Import PatternFly components
19
18
  const react_core_1 = require("@patternfly/react-core");
19
+ const react_styles_1 = require("@patternfly/react-styles");
20
20
  const SourcesCardBase_1 = __importDefault(require("../SourcesCardBase"));
21
21
  const SourcesCard = (_a) => {
22
- var { sources, sourceWord = 'source', sourceWordPlural = 'sources' } = _a, props = __rest(_a, ["sources", "sourceWord", "sourceWordPlural"]);
23
- return ((0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__source", children: [(0, jsx_runtime_1.jsx)("span", { children: (0, react_core_1.pluralize)(sources.length, sourceWord, sourceWordPlural) }), (0, jsx_runtime_1.jsx)(SourcesCardBase_1.default, Object.assign({ sources: sources }, props))] }));
22
+ var { sources, sourceWord = 'source', sourceWordPlural = 'sources', layout = 'paginated', cardMaxWidth = '400px' } = _a, props = __rest(_a, ["sources", "sourceWord", "sourceWordPlural", "layout", "cardMaxWidth"]);
23
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, react_styles_1.css)('pf-chatbot__source', layout === 'wrap' && 'pf-m-wrap'), children: [(0, jsx_runtime_1.jsx)("span", { children: (0, react_core_1.pluralize)(sources.length, sourceWord, sourceWordPlural) }), (0, jsx_runtime_1.jsx)(SourcesCardBase_1.default, Object.assign({ sources: sources, layout: layout, cardMaxWidth: cardMaxWidth }, props))] }));
24
24
  };
25
25
  exports.default = SourcesCard;
@@ -24,4 +24,16 @@ describe('SourcesCard', () => {
24
24
  react_1.screen.getByRole('button', { name: /Go to previous page/i });
25
25
  react_1.screen.getByRole('button', { name: /Go to next page/i });
26
26
  });
27
+ it('should render with wrap layout when layout is set to wrap', () => {
28
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(SourcesCard_1.default, { layout: "wrap", sources: [
29
+ { title: 'How to make an apple pie', link: '' },
30
+ { title: 'How to make cookies', link: '' },
31
+ { title: 'How to make a sandwich', link: '' }
32
+ ] }));
33
+ expect(react_1.screen.getByText('How to make an apple pie')).toBeVisible();
34
+ expect(react_1.screen.getByText('How to make cookies')).toBeVisible();
35
+ expect(react_1.screen.getByText('How to make a sandwich')).toBeVisible();
36
+ expect(react_1.screen.queryByRole('navigation')).not.toBeInTheDocument();
37
+ expect(react_1.screen.queryByText('1/3')).not.toBeInTheDocument();
38
+ });
27
39
  });
@@ -3,12 +3,16 @@ import { ButtonProps, CardBodyProps, CardFooterProps, CardProps, CardTitleProps,
3
3
  export interface SourcesCardBaseProps extends CardProps {
4
4
  /** Additional classes for the pagination navigation container. */
5
5
  className?: string;
6
+ /** The layout used to display source cards. Use wrap to display and wrap all sources at once. */
7
+ layout?: 'paginated' | 'wrap';
6
8
  /** Flag indicating if the pagination is disabled. */
7
9
  isDisabled?: boolean;
8
10
  /** @deprecated ofWord has been deprecated. Label for the English word "of." */
9
11
  ofWord?: string;
10
12
  /** Accessible label for the pagination component. */
11
13
  paginationAriaLabel?: string;
14
+ /** Max width of a source card when the wrap layout is used. Can be any valid CSS width value. */
15
+ cardMaxWidth?: string;
12
16
  /** Content rendered inside the paginated card */
13
17
  sources: {
14
18
  /** Title of sources card */
@@ -18,7 +18,7 @@ const react_core_1 = require("@patternfly/react-core");
18
18
  const react_icons_1 = require("@patternfly/react-icons");
19
19
  const SourcesCardBase = (_a) => {
20
20
  var _b;
21
- var { className, isDisabled, paginationAriaLabel = 'Pagination', sources, toNextPageAriaLabel = 'Go to next page', toPreviousPageAriaLabel = 'Go to previous page', onNextClick, onPreviousClick, onSetPage, showMoreWords = 'show more', showLessWords = 'show less', isCompact, cardTitleProps, cardBodyProps, cardFooterProps } = _a, props = __rest(_a, ["className", "isDisabled", "paginationAriaLabel", "sources", "toNextPageAriaLabel", "toPreviousPageAriaLabel", "onNextClick", "onPreviousClick", "onSetPage", "showMoreWords", "showLessWords", "isCompact", "cardTitleProps", "cardBodyProps", "cardFooterProps"]);
21
+ var { className, isDisabled, paginationAriaLabel = 'Pagination', sources, toNextPageAriaLabel = 'Go to next page', toPreviousPageAriaLabel = 'Go to previous page', onNextClick, onPreviousClick, onSetPage, showMoreWords = 'show more', showLessWords = 'show less', isCompact, cardTitleProps, cardBodyProps, cardFooterProps, layout = 'paginated', cardMaxWidth = '400px' } = _a, props = __rest(_a, ["className", "isDisabled", "paginationAriaLabel", "sources", "toNextPageAriaLabel", "toPreviousPageAriaLabel", "onNextClick", "onPreviousClick", "onSetPage", "showMoreWords", "showLessWords", "isCompact", "cardTitleProps", "cardBodyProps", "cardFooterProps", "layout", "cardMaxWidth"]);
22
22
  const [page, setPage] = (0, react_1.useState)(1);
23
23
  const [isExpanded, setIsExpanded] = (0, react_1.useState)(false);
24
24
  const onToggle = (_event, isExpanded) => {
@@ -28,13 +28,22 @@ const SourcesCardBase = (_a) => {
28
28
  setPage(newPage);
29
29
  onSetPage && onSetPage(_evt, newPage);
30
30
  };
31
- const renderTitle = (title, truncateProps) => {
31
+ const renderTitle = (title, index, truncateProps) => {
32
32
  if (title) {
33
33
  return (0, jsx_runtime_1.jsx)(react_core_1.Truncate, Object.assign({ content: title }, truncateProps));
34
34
  }
35
- return `Source ${page}`;
35
+ return `Source ${index !== undefined ? index + 1 : page}`;
36
36
  };
37
- return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__sources-card-base", children: (0, jsx_runtime_1.jsxs)(react_core_1.Card, Object.assign({ isCompact: isCompact, className: "pf-chatbot__sources-card" }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.CardTitle, Object.assign({ className: "pf-chatbot__sources-card-title" }, cardTitleProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__sources-card-title-container", children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ component: "a", variant: react_core_1.ButtonVariant.link, href: sources[page - 1].link, icon: sources[page - 1].isExternal ? (0, jsx_runtime_1.jsx)(react_icons_1.ExternalLinkSquareAltIcon, {}) : undefined, iconPosition: "end", isInline: true, rel: sources[page - 1].isExternal ? 'noreferrer' : undefined, target: sources[page - 1].isExternal ? '_blank' : undefined, onClick: (_b = sources[page - 1].onClick) !== null && _b !== void 0 ? _b : undefined }, sources[page - 1].titleProps, { children: renderTitle(sources[page - 1].title, sources[page - 1].truncateProps) })), sources[page - 1].subtitle && ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__sources-card-subtitle", children: sources[page - 1].subtitle }))] }) })), sources[page - 1].body && ((0, jsx_runtime_1.jsx)(react_core_1.CardBody, Object.assign({ className: `pf-chatbot__sources-card-body ${sources[page - 1].footer ? 'pf-chatbot__compact-sources-card-body' : undefined}` }, cardBodyProps, { children: sources[page - 1].hasShowMore ? (
37
+ const renderUncontrolledSourceCard = (source, index) => {
38
+ var _a;
39
+ return ((0, jsx_runtime_1.jsx)("li", { className: "pf-chatbot__sources-list-item", children: (0, jsx_runtime_1.jsxs)(react_core_1.Card, Object.assign({ isCompact: isCompact, className: "pf-chatbot__sources-card", style: { maxWidth: cardMaxWidth } }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.CardTitle, Object.assign({ className: "pf-chatbot__sources-card-title" }, cardTitleProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__sources-card-title-container", children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ component: "a", variant: react_core_1.ButtonVariant.link, href: source.link, icon: source.isExternal ? (0, jsx_runtime_1.jsx)(react_icons_1.ExternalLinkSquareAltIcon, {}) : undefined, iconPosition: "end", isInline: true, rel: source.isExternal ? 'noreferrer' : undefined, target: source.isExternal ? '_blank' : undefined, onClick: (_a = source.onClick) !== null && _a !== void 0 ? _a : undefined }, source.titleProps, { children: renderTitle(source.title, index, source.truncateProps) })), source.subtitle && (0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__sources-card-subtitle", children: source.subtitle })] }) })), source.body && ((0, jsx_runtime_1.jsx)(react_core_1.CardBody, Object.assign({ className: `pf-chatbot__sources-card-body ${source.footer ? 'pf-chatbot__compact-sources-card-body' : undefined}` }, cardBodyProps, { children: source.hasShowMore ? (
40
+ // prevents extra VO announcements of button text - parent Message has aria-live
41
+ (0, jsx_runtime_1.jsx)("div", { "aria-live": "off", children: (0, jsx_runtime_1.jsx)(react_core_1.ExpandableSection, { variant: react_core_1.ExpandableSectionVariant.truncate, toggleTextCollapsed: showMoreWords, toggleTextExpanded: showLessWords, truncateMaxLines: 2, children: source.body }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__sources-card-body-text", children: source.body })) }))), source.footer && ((0, jsx_runtime_1.jsx)(react_core_1.CardFooter, Object.assign({ className: "pf-chatbot__sources-card-footer" }, cardFooterProps, { children: source.footer })))] })) }, index));
42
+ };
43
+ if (layout === 'wrap') {
44
+ return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__sources-card-base pf-m-wrap", children: (0, jsx_runtime_1.jsx)("ul", { className: "pf-chatbot__sources-list", role: "list", children: sources.map((source, index) => renderUncontrolledSourceCard(source, index)) }) }));
45
+ }
46
+ return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__sources-card-base", children: (0, jsx_runtime_1.jsxs)(react_core_1.Card, Object.assign({ isCompact: isCompact, className: "pf-chatbot__sources-card" }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.CardTitle, Object.assign({ className: "pf-chatbot__sources-card-title" }, cardTitleProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__sources-card-title-container", children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ component: "a", variant: react_core_1.ButtonVariant.link, href: sources[page - 1].link, icon: sources[page - 1].isExternal ? (0, jsx_runtime_1.jsx)(react_icons_1.ExternalLinkSquareAltIcon, {}) : undefined, iconPosition: "end", isInline: true, rel: sources[page - 1].isExternal ? 'noreferrer' : undefined, target: sources[page - 1].isExternal ? '_blank' : undefined, onClick: (_b = sources[page - 1].onClick) !== null && _b !== void 0 ? _b : undefined }, sources[page - 1].titleProps, { children: renderTitle(sources[page - 1].title, undefined, sources[page - 1].truncateProps) })), sources[page - 1].subtitle && ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__sources-card-subtitle", children: sources[page - 1].subtitle }))] }) })), sources[page - 1].body && ((0, jsx_runtime_1.jsx)(react_core_1.CardBody, Object.assign({ className: `pf-chatbot__sources-card-body ${sources[page - 1].footer ? 'pf-chatbot__compact-sources-card-body' : undefined}` }, cardBodyProps, { children: sources[page - 1].hasShowMore ? (
38
47
  // prevents extra VO announcements of button text - parent Message has aria-live
39
48
  (0, jsx_runtime_1.jsx)("div", { "aria-live": "off", children: (0, jsx_runtime_1.jsx)(react_core_1.ExpandableSection, { variant: react_core_1.ExpandableSectionVariant.truncate, toggleText: isExpanded ? showLessWords : showMoreWords, onToggle: onToggle, isExpanded: isExpanded, truncateMaxLines: 2, children: sources[page - 1].body }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__sources-card-body-text", children: sources[page - 1].body })) }))), sources[page - 1].footer ? ((0, jsx_runtime_1.jsx)(react_core_1.CardFooter, Object.assign({ className: "pf-chatbot__sources-card-footer" }, cardFooterProps, { children: sources[page - 1].footer }))) : (sources.length > 1 && ((0, jsx_runtime_1.jsx)(react_core_1.CardFooter, Object.assign({ className: "pf-chatbot__sources-card-footer-container" }, cardFooterProps, { children: (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__sources-card-footer", children: (0, jsx_runtime_1.jsxs)("nav", { className: `pf-chatbot__sources-card-footer-buttons ${className}`, "aria-label": paginationAriaLabel, children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, { variant: react_core_1.ButtonVariant.plain, isDisabled: isDisabled || page === 1, "data-action": "previous", onClick: (event) => {
40
49
  const newPage = page >= 1 ? page - 1 : 1;
@@ -168,4 +168,32 @@ describe('SourcesCardBase', () => {
168
168
  (0, react_1.render)((0, jsx_runtime_1.jsx)(SourcesCardBase_1.default, { sources: [{ title: 'How to make an apple pie', link: '', titleProps: { className: 'test' } }] }));
169
169
  expect(react_1.screen.getByRole('link', { name: /How to make an apple pie/i })).toHaveClass('test');
170
170
  });
171
+ it('should render with wrap layout when layout prop is set to wrap', () => {
172
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(SourcesCardBase_1.default, { layout: "wrap", sources: [
173
+ { title: 'How to make an apple pie', link: '' },
174
+ { title: 'How to make cookies', link: '' },
175
+ { title: 'How to make a sandwich', link: '' }
176
+ ] }));
177
+ expect(react_1.screen.getByText('How to make an apple pie')).toBeVisible();
178
+ expect(react_1.screen.getByText('How to make cookies')).toBeVisible();
179
+ expect(react_1.screen.getByText('How to make a sandwich')).toBeVisible();
180
+ expect(react_1.screen.queryByRole('navigation')).not.toBeInTheDocument();
181
+ expect(react_1.screen.queryByText('1/3')).not.toBeInTheDocument();
182
+ });
183
+ it('should apply default cardMaxWidth when using wrap layout', () => {
184
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(SourcesCardBase_1.default, { layout: "wrap", sources: [
185
+ { title: 'How to make an apple pie', link: '' },
186
+ { title: 'How to make cookies', link: '' }
187
+ ] }));
188
+ const firstCard = react_1.screen.getByText('How to make an apple pie').closest('.pf-chatbot__sources-card');
189
+ expect(firstCard).toHaveStyle({ maxWidth: '400px' });
190
+ });
191
+ it('should apply custom cardMaxWidth when using wrap layout', () => {
192
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(SourcesCardBase_1.default, { layout: "wrap", sources: [
193
+ { title: 'How to make an apple pie', link: '' },
194
+ { title: 'How to make cookies', link: '' }
195
+ ], cardMaxWidth: "500px" }));
196
+ const firstCard = react_1.screen.getByText('How to make an apple pie').closest('.pf-chatbot__sources-card');
197
+ expect(firstCard).toHaveStyle({ maxWidth: '500px' });
198
+ });
171
199
  });
package/dist/css/main.css CHANGED
@@ -1342,6 +1342,12 @@
1342
1342
  .pf-chatbot__message .footnotes {
1343
1343
  background-color: var(--pf-t--global--background--color--tertiary--default);
1344
1344
  }
1345
+ .pf-chatbot__message.pf-m-end {
1346
+ flex-direction: row-reverse;
1347
+ }
1348
+ .pf-chatbot__message.pf-m-end .pf-chatbot__message-contents {
1349
+ align-items: flex-end;
1350
+ }
1345
1351
 
1346
1352
  .pf-chatbot__message-attachments-container {
1347
1353
  display: flex;
@@ -2673,6 +2679,9 @@ li[id*=user-content-fn-]:has(> span > span > .pf-chatbot__message-text + .pf-cha
2673
2679
  flex-direction: column;
2674
2680
  gap: var(--pf-t--global--spacer--sm);
2675
2681
  padding-block-start: var(--pf-t--global--spacer--sm);
2682
+ }
2683
+ .pf-chatbot__source:not(.pf-m-wrap),
2684
+ .pf-chatbot__sources-card-base:not(.pf-m-wrap) {
2676
2685
  max-width: 22.5rem;
2677
2686
  }
2678
2687
 
@@ -2682,6 +2691,13 @@ li[id*=user-content-fn-]:has(> span > span > .pf-chatbot__message-text + .pf-cha
2682
2691
  text-decoration: var(--pf-t--global--text-decoration--link--line--default) !important;
2683
2692
  }
2684
2693
 
2694
+ .pf-chatbot__sources-card-base.pf-m-wrap .pf-chatbot__sources-list {
2695
+ display: flex;
2696
+ flex-wrap: wrap;
2697
+ list-style: none;
2698
+ gap: var(--pf-t--global--spacer--xs);
2699
+ }
2700
+
2685
2701
  .pf-chatbot__sources-card {
2686
2702
  box-shadow: var(--pf-t--global--box-shadow--sm);
2687
2703
  }
@@ -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/DeepThinking/DeepThinking.scss","../../src/FileDetails/FileDetails.scss","../../src/FileDetailsLabel/FileDetailsLabel.scss","../../src/FileDropZone/FileDropZone.scss","../../src/FilePreview/FilePreview.scss","../../src/ImagePreview/ImagePreview.scss","../../src/Message/Message.scss","../../src/Message/MessageLoading.scss","../../src/Message/CodeBlockMessage/CodeBlockMessage.scss","../../src/Message/TextMessage/TextMessage.scss","../../src/Message/SuperscriptMessage/SuperscriptMessage.scss","../../src/Message/ImageMessage/ImageMessage.scss","../../src/Message/LinkMessage/LinkMessage.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/MessageDivider/MessageDivider.scss","../../src/Onboarding/Onboarding.scss","../../src/ResponseActions/ResponseActions.scss","../../src/Settings/Settings.scss","../../src/SourcesCard/SourcesCard.scss","../../src/SourceDetailsMenuItem/SourceDetailsMenuItem.scss","../../src/TermsOfUse/TermsOfUse.scss","../../src/ToolResponse/ToolResponse.scss","../../src/ToolCall/ToolCall.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;EACA,YACE;EAYF;;AAVA;EACE;EACA;EACA;;AAEF;EACE;EACA;;AAQF;EAjCF;IAkCI;IACA;;;AAIF;EAvCF;IAwCI;;;;AAOJ;EAEE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EAfF;IAgBI;;;;AAOJ;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMF;EAEE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAIF;EAdF;IAeI;;;;AAIJ;EACE;;;AAGF;AAAA;AAAA;EAGE;;;AAMF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EAdF;IAgBI;;;;AAMF;EACE;;;AAOJ;EACE;;;ACjKF;EACE;EACA;EACA;;;ACAF;EACE;EACA;EACA;EACA;EACA;;AAGA;EARF;IASI;;;AAGF;EACE;;;AAOJ;EAII;AAAA;AAAA;IACE;IACA;;;ACzBJ;EACE;EACA;;AAGF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAKA;EACE;EACA;;AAIJ;EACE;;AAKF;EACE;EACA;EAEA;EACA;EACA;;AAEF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;AAIF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;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;;AAKJ;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAKA;EACE;;;AASJ;EACE;;;AASF;AAAA;EACE;;AACA;AAAA;EACE;;;AASJ;EACE;;AACA;EACE;EACA;;AAEF;EACE;;;AAUF;AAAA;AAAA;AAAA;EACE;;;AAKN;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAKE;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;;;ACvSN;EACE;;AAEA;EACE;EACA;;;ACHJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;;AAMF;EAGI;AAAA;IACE;;EACA;AAAA;IACE;;EAGJ;AAAA;IACE;IACA;IACA;;;AASJ;EACE;;;AAQF;EACE;;;AAIJ;EACE;EACA;;;AAQA;EAIM;AAAA;IACE;;;;AC5EV;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;EACA;;;AAQN;EAGI;AAAA;IACE;;EAEF;AAAA;IACE;;;AAUJ;AAAA;EACE;;;AAOJ;AAAA;EAEE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACE;;AAGF;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;;;AAOA;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;AAAA;EAEE;EACA;;;AAGF;EACE;;;AAQA;EAGI;AAAA;IACE;;;;AClLR;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AAIF;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;;;AAOA;EACE;;AAGF;EACE;EACA;;;ACpGF;EACE;;AAMA;EACE;;AAEF;EACE;;AAEF;EACE;;AAIF;EACE;EACA;;AAEF;EACE;;;ACxBN;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;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;AAEA;EACE;;;AAOJ;EAIM;AAAA;IACE;IACA;;;ACpDN;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;AACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;AAAA;AAAA;EAGA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAGA;EACE;;;AAUF;EACE;EACA;;;AAKN;EACE;;;AAGF;EACE;;;AAIA;EACE;;;AC9FJ;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;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;ACtBF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;EACE;EACA;EACA;EACA;EACA;;;ACjCF;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;;;;ACnDR;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAEF;EACE;EACA;;;ACpBF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;EACE;;AAGJ;EACE;EACA;;AAKA;AAAA;EACE;;AAGJ;EACE;;;ACvDJ;EACE;EACA;EACA;EACA;;AAIA;EACE;EACA;EACA;EACA;EACA;;AAGF;EAKE;;AAJA;EACE;EACA;;AAOJ;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;;AAKF;EACE;EACA;EACA;;AAGA;EACE;EAQA;EACA;;AAIF;EACE;EACA;;AAIF;EACE;;AAEF;EACE;;AAMJ;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIF;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;EACA;EACA;;AAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAKE;;AAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAQE;;AAIJ;EACE;;;AAMJ;EACE;EACA;EACA;;;AAGF;EACE;;;AChJF;EACE;EACA;EACA;EACA;EAEA;;AAGA;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;;;AAIJ;EACE;;;ACtDJ;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIF;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;;AAIJ;EACE;;;AAIJ;EACE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;EACA;;;ACrGJ;EACE;;AAGE;EACE;;;AAMN;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;;AAIJ;EACE;;AAEF;EACE;EACA;;;AAUJ;EAIE;;;AAIF;EAKE;;;AAIA;EACE;;;AAKF;EACE;EACA;EACA;EACA;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAIJ;EACE;;AAGF;EACE;EACA;;;AASF;EACE;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AC/IN;EACE;EACA;;AACA;EACE;EACA;;;AJ0JF;EACE;EACA;;AAEA;EACE;;AAIJ;EACE;;AAIA;EACE;EACA;;AAIJ;EACE;;;AEjLJ;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIF;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;;AAIJ;EACE;;;AAIJ;EACE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;EACA;;;AGzGJ;EACE;EACA;EACA;EACA;EAGA;;;ACNA;EACE;;;AHEJ;EACE;;AAGE;EACE;;;AAMN;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;;AAIJ;EACE;;AAEF;EACE;EACA;;;AAUJ;EAIE;;;AAIF;EAKE;;;AAIA;EACE;;;AAKF;EACE;EACA;EACA;EACA;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAIJ;EACE;;AAGF;EACE;EACA;;;AASF;EACE;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AI3IN;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;;AAMJ;AAAA;EAEE;EACA;EACA;;AAGA;AAAA;EACE;;AAMF;EACE;EACA;;AAIJ;EACE;;;AC/CJ;EACE;EACA;EACA;EAEA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;;APhCN;EACE;EACA;EACA;EACA;EAEA;;AAGA;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;;;AAIJ;EACE;;;AQzDJ;EACE;EACA;;AAEA;EAJF;IAKI;IACA;;;AAKA;EACE;;;AAOF;EACE;;;AClBF;EACE;;AAGF;EALF;IAMI;;;AAGF;EATF;IAUI;;;AAKF;EACE;EACA;;AAIJ;AAAA;EAEE;EACA;;AAIF;EACE;EACA;EACA;;;AC/BJ;EACE;EAEA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAKA;EACE;;;AAGJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;EACE;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;;AAGF;EACE;;;AAMJ;EACE;;AAGF;EACE;;AAIA;EACE;;;AC/FN;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAKA;EACE;;AAIJ;EAEE;;AAEA;EACE;;AAKA;EACE;;;AASR;EACE;EACA;EACA;;;ACxCF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAMA;EACE;;AAKJ;EACE;EACA;;AAGA;EACE;;AAKA;EACE;;;AAMR;EACE;IACE;;EAEF;IACE;;;AAOJ;EACE;EACA;EACA;;;ACpDF;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;;;AAOJ;EACE;EACA;EACA;;;ACzDF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;;AAKA;EACE;;;AASR;EACE;EACA;EACA;;;ACjCF;EACE;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAKF;EACE;;AAKF;EACE;EACA;;AAKF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;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;EACA;;AAEF;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;IACE;IACA;;;AAKF;EACE;IACE;IACA;;;;AAQN;EACE;EACA;;AAEA;EACE;;;AAKF;AAAA;EAEE;EACA;;;AAOJ;EACE;;;AAQE;EACE;;;ACrLN;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;;;AAGF;EAII;AAAA;AAAA;IACE;IACA;;;AAMJ;EACE;;;ACnCJ;EACE;EACA;;AAEA;AAAA;EAEE;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAKF;EACE;EACA;EAEA;;AAGF;EACE;;AAKF;AAAA;EAEE;;;AFrCN;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;;;;AGhDJ;EACE;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;;AAGF;EACE;;AAIF;EACE;IACE;IACA;;;;AASF;AAAA;AAAA;EACE;EACA;;;AAKN;AAAA;EAGE;;AAEA;AAAA;EACE;;;AAKF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AClGJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;;;AAKN;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;;;ACrCF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAIA;EACE;EACA;;;AAIJ;EACE;;;AC3CF;AAAA;EAEE;EACA;EACA;EACA;EACA;;;AAIA;EACE;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;EACE;;AAGJ;EACE;EACA;;AAKA;AAAA;EACE;;AAGJ;EACE;;;AAON;EACE;EACA;;;ACpGJ;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;;;AAKF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;ACnFJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAIA;EACE;;;AC3CJ;EACE;EACA;EAEA;EACA;;AAEA;EACE;EACA;EACA;;AAIA;EACE;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;;AAIJ;EACE;;;ACWJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA","file":"main.css"}
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/DeepThinking/DeepThinking.scss","../../src/FileDetails/FileDetails.scss","../../src/FileDetailsLabel/FileDetailsLabel.scss","../../src/FileDropZone/FileDropZone.scss","../../src/FilePreview/FilePreview.scss","../../src/ImagePreview/ImagePreview.scss","../../src/Message/Message.scss","../../src/Message/MessageLoading.scss","../../src/Message/CodeBlockMessage/CodeBlockMessage.scss","../../src/Message/TextMessage/TextMessage.scss","../../src/Message/SuperscriptMessage/SuperscriptMessage.scss","../../src/Message/ImageMessage/ImageMessage.scss","../../src/Message/LinkMessage/LinkMessage.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/MessageDivider/MessageDivider.scss","../../src/Onboarding/Onboarding.scss","../../src/ResponseActions/ResponseActions.scss","../../src/Settings/Settings.scss","../../src/SourcesCard/SourcesCard.scss","../../src/SourceDetailsMenuItem/SourceDetailsMenuItem.scss","../../src/TermsOfUse/TermsOfUse.scss","../../src/ToolResponse/ToolResponse.scss","../../src/ToolCall/ToolCall.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;EACA,YACE;EAYF;;AAVA;EACE;EACA;EACA;;AAEF;EACE;EACA;;AAQF;EAjCF;IAkCI;IACA;;;AAIF;EAvCF;IAwCI;;;;AAOJ;EAEE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EAfF;IAgBI;;;;AAOJ;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMF;EAEE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;;AAIF;EAdF;IAeI;;;;AAIJ;EACE;;;AAGF;AAAA;AAAA;EAGE;;;AAMF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EAdF;IAgBI;;;;AAMF;EACE;;;AAOJ;EACE;;;ACjKF;EACE;EACA;EACA;;;ACAF;EACE;EACA;EACA;EACA;EACA;;AAGA;EARF;IASI;;;AAGF;EACE;;;AAOJ;EAII;AAAA;AAAA;IACE;IACA;;;ACzBJ;EACE;EACA;;AAGF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAKA;EACE;EACA;;AAIJ;EACE;;AAKF;EACE;EACA;EAEA;EACA;EACA;;AAEF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;AAIF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;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;;AAKJ;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;;AAKA;EACE;;;AASJ;EACE;;;AASF;AAAA;EACE;;AACA;AAAA;EACE;;;AASJ;EACE;;AACA;EACE;EACA;;AAEF;EACE;;;AAUF;AAAA;AAAA;AAAA;EACE;;;AAKN;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAKE;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;EACA;;;ACvSN;EACE;;AAEA;EACE;EACA;;;ACHJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;;AAMF;EAGI;AAAA;IACE;;EACA;AAAA;IACE;;EAGJ;AAAA;IACE;IACA;IACA;;;AASJ;EACE;;;AAQF;EACE;;;AAIJ;EACE;EACA;;;AAQA;EAIM;AAAA;IACE;;;;AC5EV;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;EACA;;;AAQN;EAGI;AAAA;IACE;;EAEF;AAAA;IACE;;;AAUJ;AAAA;EACE;;;AAOJ;AAAA;EAEE;EACA;EACA;EACA;EACA;;AAEA;AAAA;EACE;;AAGF;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;;;AAOA;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;AAAA;EAEE;EACA;;;AAGF;EACE;;;AAQA;EAGI;AAAA;IACE;;;;AClLR;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AAIF;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;;;AAOA;EACE;;AAGF;EACE;EACA;;;ACpGF;EACE;;AAMA;EACE;;AAEF;EACE;;AAEF;EACE;;AAIF;EACE;EACA;;AAEF;EACE;;;ACxBN;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;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;AAEA;EACE;;;AAOJ;EAIM;AAAA;IACE;IACA;;;ACpDN;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;AACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;AAAA;AAAA;EAGA;EACA;;AAEF;EACE;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAGA;EACE;;;AAUF;EACE;EACA;;;AAKN;EACE;;;AAGF;EACE;;;AAIA;EACE;;;AC9FJ;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;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;ACtBF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;EACE;EACA;EACA;EACA;EACA;;;ACjCF;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;;;;ACnDR;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAEF;EACE;EACA;;;ACpBF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;EACE;;AAGJ;EACE;EACA;;AAKA;AAAA;EACE;;AAGJ;EACE;;;ACvDJ;EACE;EACA;EACA;EACA;;AAIA;EACE;EACA;EACA;EACA;EACA;;AAGF;EAKE;;AAJA;EACE;EACA;;AAOJ;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;;AAKF;EACE;EACA;EACA;;AAGA;EACE;EAQA;EACA;;AAIF;EACE;EACA;;AAIF;EACE;;AAEF;EACE;;AAMJ;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAIF;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;EACA;EACA;;AAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAKE;;AAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAQE;;AAIJ;EACE;;AAIF;EACE;;AAEA;EACE;;;AAON;EACE;EACA;EACA;;;AAGF;EACE;;;ACzJF;EACE;EACA;EACA;EACA;EAEA;;AAGA;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;;;AAIJ;EACE;;;ACtDJ;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIF;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;;AAIJ;EACE;;;AAIJ;EACE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;EACA;;;ACrGJ;EACE;;AAGE;EACE;;;AAMN;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;;AAIJ;EACE;;AAEF;EACE;EACA;;;AAUJ;EAIE;;;AAIF;EAKE;;;AAIA;EACE;;;AAKF;EACE;EACA;EACA;EACA;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAIJ;EACE;;AAGF;EACE;EACA;;;AASF;EACE;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AC/IN;EACE;EACA;;AACA;EACE;EACA;;;AJmKF;EACE;EACA;;AAEA;EACE;;AAIJ;EACE;;AAIA;EACE;EACA;;AAIJ;EACE;;;AE1LJ;EACE;EACA;EACA;EACA;;AAGA;EACE;EACA;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIF;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;;AAIJ;EACE;;;AAIJ;EACE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKF;EACE;EACA;;;AGzGJ;EACE;EACA;EACA;EACA;EAGA;;;ACNA;EACE;;;AHEJ;EACE;;AAGE;EACE;;;AAMN;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;;AAIJ;EACE;;AAEF;EACE;EACA;;;AAUJ;EAIE;;;AAIF;EAKE;;;AAIA;EACE;;;AAKF;EACE;EACA;EACA;EACA;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAIJ;EACE;;AAGF;EACE;EACA;;;AASF;EACE;;AACA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;;AAGF;EACE;EACA;;;AI3IN;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;;AAMJ;AAAA;EAEE;EACA;EACA;;AAGA;AAAA;EACE;;AAMF;EACE;EACA;;AAIJ;EACE;;;AC/CJ;EACE;EACA;EACA;EAEA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAIA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;;APhCN;EACE;EACA;EACA;EACA;EAEA;;AAGA;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;;;AAIJ;EACE;;;AQzDJ;EACE;EACA;;AAEA;EAJF;IAKI;IACA;;;AAKA;EACE;;;AAOF;EACE;;;AClBF;EACE;;AAGF;EALF;IAMI;;;AAGF;EATF;IAUI;;;AAKF;EACE;EACA;;AAIJ;AAAA;EAEE;EACA;;AAIF;EACE;EACA;EACA;;;AC/BJ;EACE;EAEA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;;;AAKA;EACE;;;AAGJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;EACE;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;;AAGF;EACE;;;AAMJ;EACE;;AAGF;EACE;;AAIA;EACE;;;AC/FN;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAKA;EACE;;AAIJ;EAEE;;AAEA;EACE;;AAKA;EACE;;;AASR;EACE;EACA;EACA;;;ACxCF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAMA;EACE;;AAKJ;EACE;EACA;;AAGA;EACE;;AAKA;EACE;;;AAMR;EACE;IACE;;EAEF;IACE;;;AAOJ;EACE;EACA;EACA;;;ACpDF;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;;;AAOJ;EACE;EACA;EACA;;;ACzDF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;;AAKA;EACE;;;AASR;EACE;EACA;EACA;;;ACjCF;EACE;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA,YACE;;AAKF;EACE;;AAKF;EACE;EACA;;AAKF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;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;EACA;;AAEF;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;IACE;IACA;;;AAKF;EACE;IACE;IACA;;;;AAQN;EACE;EACA;;AAEA;EACE;;;AAKF;AAAA;EAEE;EACA;;;AAOJ;EACE;;;AAQE;EACE;;;ACrLN;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;;;AAGF;EAII;AAAA;AAAA;IACE;IACA;;;AAMJ;EACE;;;ACnCJ;EACE;EACA;;AAEA;AAAA;EAEE;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAKF;EACE;EACA;EAEA;;AAGF;EACE;;AAKF;AAAA;EAEE;;;AFrCN;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;;;;AGhDJ;EACE;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;;AAGF;EACE;;AAIF;EACE;IACE;IACA;;;;AASF;AAAA;AAAA;EACE;EACA;;;AAKN;AAAA;EAGE;;AAEA;AAAA;EACE;;;AAKF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AClGJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;;;AAKN;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;;;ACrCF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAIA;EACE;EACA;;;AAIJ;EACE;;;AC3CF;AAAA;EAEE;EACA;EACA;EACA;;AAEA;AAAA;EACE;;;AAKF;EACE;EACA;EACA;;;AAKF;EACE;EACA;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;AAAA;EACE;;AAGJ;EACE;EACA;;AAKA;AAAA;EACE;;AAGJ;EACE;;;AAON;EACE;EACA;;;AChHJ;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;;;AAKF;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;;;ACnFJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAIA;EACE;;;AC3CJ;EACE;EACA;EAEA;EACA;;AAEA;EACE;EACA;EACA;;AAIA;EACE;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;;AAIJ;EACE;;;ACWJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA","file":"main.css"}
@@ -48,6 +48,10 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
48
48
  id?: string;
49
49
  /** Role of the user sending the message */
50
50
  role: 'user' | 'bot';
51
+ /** Whether the message is aligned at the horizontal start or end of the message container. */
52
+ alignment?: 'start' | 'end';
53
+ /** Flag indicating whether message metadata (user name and timestamp) are visible. */
54
+ isMetadataVisible?: boolean;
51
55
  /** Message content */
52
56
  content?: string;
53
57
  /** Extra Message content */
@@ -31,8 +31,9 @@ import ToolResponse from '../ToolResponse';
31
31
  import DeepThinking from '../DeepThinking';
32
32
  import ToolCall from '../ToolCall';
33
33
  import MarkdownContent from '../MarkdownContent';
34
+ import { css } from '@patternfly/react-styles';
34
35
  export const MessageBase = (_a) => {
35
- var { children, role, content, extraContent, name, avatar, timestamp, isLoading, actions, persistActionSelection, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], additionalRemarkPlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking, remarkGfmProps, toolCall, hasNoImagesInUserMessages = true, isPrimary } = _a, props = __rest(_a, ["children", "role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "persistActionSelection", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages", "isPrimary"]);
36
+ var { children, role, alignment = 'start', isMetadataVisible = true, content, extraContent, name, avatar, timestamp, isLoading, actions, persistActionSelection, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], additionalRemarkPlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking, remarkGfmProps, toolCall, hasNoImagesInUserMessages = true, isPrimary } = _a, props = __rest(_a, ["children", "role", "alignment", "isMetadataVisible", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "persistActionSelection", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages", "isPrimary"]);
36
37
  const [messageText, setMessageText] = useState(content);
37
38
  useEffect(() => {
38
39
  setMessageText(content);
@@ -60,7 +61,7 @@ export const MessageBase = (_a) => {
60
61
  }
61
62
  return (_jsxs(_Fragment, { children: [beforeMainContent && _jsx(_Fragment, { children: beforeMainContent }), error ? _jsx(ErrorMessage, Object.assign({}, error)) : handleMarkdown()] }));
62
63
  };
63
- return (_jsxs("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [avatar && (_jsx(Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps))), _jsxs("div", { className: "pf-chatbot__message-contents", children: [_jsxs("div", { className: "pf-chatbot__message-meta", children: [name && (_jsx("span", { className: "pf-chatbot__message-name", children: _jsx(Truncate, { content: name }) })), role === 'bot' && (_jsx(Label, { variant: "outline", isCompact: true, children: botWord })), _jsx(Timestamp, { date: date, children: timestamp })] }), _jsx("div", { className: "pf-chatbot__message-response", children: children ? (_jsx(_Fragment, { children: children })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && _jsx(_Fragment, { children: afterMainContent }), toolResponse && _jsx(ToolResponse, Object.assign({}, toolResponse)), deepThinking && _jsx(DeepThinking, Object.assign({}, deepThinking)), toolCall && _jsx(ToolCall, Object.assign({}, toolCall)), !isLoading && sources && _jsx(SourcesCard, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && (_jsx(QuickStartTile, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && (_jsx(_Fragment, { children: Array.isArray(actions) ? (_jsx("div", { className: "pf-chatbot__response-actions-groups", children: actions.map((actionGroup, index) => (_jsx(ResponseActions, { actions: actionGroup.actions || actionGroup, persistActionSelection: persistActionSelection || actionGroup.persistActionSelection }, index))) })) : (_jsx(ResponseActions, { actions: actions, persistActionSelection: persistActionSelection })) })), userFeedbackForm && (_jsx(UserFeedback, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact }))), userFeedbackComplete && (_jsx(UserFeedbackComplete, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && (_jsx("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
64
+ return (_jsxs("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: css(`pf-chatbot__message pf-chatbot__message--${role}`, alignment === 'end' && 'pf-m-end'), "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [avatar && (_jsx(Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps))), _jsxs("div", { className: "pf-chatbot__message-contents", children: [isMetadataVisible && (_jsxs("div", { className: "pf-chatbot__message-meta", children: [name && (_jsx("span", { className: "pf-chatbot__message-name", children: _jsx(Truncate, { content: name }) })), role === 'bot' && (_jsx(Label, { variant: "outline", isCompact: true, children: botWord })), _jsx(Timestamp, { date: date, children: timestamp })] })), _jsx("div", { className: "pf-chatbot__message-response", children: children ? (_jsx(_Fragment, { children: children })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && _jsx(_Fragment, { children: afterMainContent }), toolResponse && _jsx(ToolResponse, Object.assign({}, toolResponse)), deepThinking && _jsx(DeepThinking, Object.assign({}, deepThinking)), toolCall && _jsx(ToolCall, Object.assign({}, toolCall)), !isLoading && sources && _jsx(SourcesCard, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && (_jsx(QuickStartTile, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && (_jsx(_Fragment, { children: Array.isArray(actions) ? (_jsx("div", { className: "pf-chatbot__response-actions-groups", children: actions.map((actionGroup, index) => (_jsx(ResponseActions, { actions: actionGroup.actions || actionGroup, persistActionSelection: persistActionSelection || actionGroup.persistActionSelection }, index))) })) : (_jsx(ResponseActions, { actions: actions, persistActionSelection: persistActionSelection })) })), userFeedbackForm && (_jsx(UserFeedback, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact }))), userFeedbackComplete && (_jsx(UserFeedbackComplete, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && (_jsx("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
64
65
  var _a;
65
66
  return (_jsx("div", { className: "pf-chatbot__message-attachment", children: _jsx(FileDetailsLabel, { fileName: attachment.name, fileId: attachment.id, onClose: attachment.onClose, onClick: attachment.onClick, isLoading: attachment.isLoading, closeButtonAriaLabel: attachment.closeButtonAriaLabel, languageTestId: attachment.languageTestId, spinnerTestId: attachment.spinnerTestId, variant: isPrimary ? 'outline' : undefined }) }, (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name));
66
67
  }) })), !isLoading && endContent && _jsx(_Fragment, { children: endContent })] })) })] })] })));
@@ -229,6 +229,12 @@ describe('Message', () => {
229
229
  return hasText && isVisible;
230
230
  })).not.toBeInTheDocument();
231
231
  });
232
+ it('Does not render metadata when isMetadataVisible is false', () => {
233
+ render(_jsx(Message, { isMetadataVisible: false, avatar: "./img", role: "bot", name: "Bot", content: "Hi", timestamp: "2 hours ago" }));
234
+ expect(screen.queryByText('Bot')).not.toBeInTheDocument();
235
+ expect(screen.queryByText('AI')).not.toBeInTheDocument();
236
+ expect(screen.queryByText('2 hours ago')).not.toBeInTheDocument();
237
+ });
232
238
  it('should render attachments', () => {
233
239
  render(_jsx(Message, { avatar: "./img", role: "user", content: "Hi", attachments: [{ name: 'testAttachment' }] }));
234
240
  expect(screen.getByText('Hi')).toBeTruthy();
@@ -985,4 +991,12 @@ describe('Message', () => {
985
991
  const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "", attachments: [{ name: 'testAttachment' }] }));
986
992
  expect(container.querySelector('.pf-m-outline')).toBeFalsy();
987
993
  });
994
+ it('Renders without pf-m-end class by default', () => {
995
+ render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "" }));
996
+ expect(screen.getByRole('region')).not.toHaveClass('pf-m-end');
997
+ });
998
+ it('Renders with pf-m-end class when alignment="end"', () => {
999
+ render(_jsx(Message, { alignment: "end", avatar: "./img", role: "user", name: "User", content: "" }));
1000
+ expect(screen.getByRole('region')).toHaveClass('pf-m-end');
1001
+ });
988
1002
  });
@@ -3,6 +3,10 @@ import { ButtonProps, CardBodyProps, CardFooterProps, CardProps, CardTitleProps,
3
3
  export interface SourcesCardProps extends CardProps {
4
4
  /** Additional classes for the pagination navigation container. */
5
5
  className?: string;
6
+ /** The layout used to display source cards. Use wrap to display and wrap all sources at once. */
7
+ layout?: 'paginated' | 'wrap';
8
+ /** Max width of a source card when the wrap layout is used. Can be any valid CSS width value. */
9
+ cardMaxWidth?: string;
6
10
  /** Flag indicating if the pagination is disabled. */
7
11
  isDisabled?: boolean;
8
12
  /** @deprecated ofWord has been deprecated. Label for the English word "of." */
@@ -10,11 +10,11 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- // Import PatternFly components
14
13
  import { pluralize } from '@patternfly/react-core';
14
+ import { css } from '@patternfly/react-styles';
15
15
  import SourcesCardBase from '../SourcesCardBase';
16
16
  const SourcesCard = (_a) => {
17
- var { sources, sourceWord = 'source', sourceWordPlural = 'sources' } = _a, props = __rest(_a, ["sources", "sourceWord", "sourceWordPlural"]);
18
- return (_jsxs("div", { className: "pf-chatbot__source", children: [_jsx("span", { children: pluralize(sources.length, sourceWord, sourceWordPlural) }), _jsx(SourcesCardBase, Object.assign({ sources: sources }, props))] }));
17
+ var { sources, sourceWord = 'source', sourceWordPlural = 'sources', layout = 'paginated', cardMaxWidth = '400px' } = _a, props = __rest(_a, ["sources", "sourceWord", "sourceWordPlural", "layout", "cardMaxWidth"]);
18
+ return (_jsxs("div", { className: css('pf-chatbot__source', layout === 'wrap' && 'pf-m-wrap'), children: [_jsx("span", { children: pluralize(sources.length, sourceWord, sourceWordPlural) }), _jsx(SourcesCardBase, Object.assign({ sources: sources, layout: layout, cardMaxWidth: cardMaxWidth }, props))] }));
19
19
  };
20
20
  export default SourcesCard;
@@ -19,4 +19,16 @@ describe('SourcesCard', () => {
19
19
  screen.getByRole('button', { name: /Go to previous page/i });
20
20
  screen.getByRole('button', { name: /Go to next page/i });
21
21
  });
22
+ it('should render with wrap layout when layout is set to wrap', () => {
23
+ render(_jsx(SourcesCard, { layout: "wrap", sources: [
24
+ { title: 'How to make an apple pie', link: '' },
25
+ { title: 'How to make cookies', link: '' },
26
+ { title: 'How to make a sandwich', link: '' }
27
+ ] }));
28
+ expect(screen.getByText('How to make an apple pie')).toBeVisible();
29
+ expect(screen.getByText('How to make cookies')).toBeVisible();
30
+ expect(screen.getByText('How to make a sandwich')).toBeVisible();
31
+ expect(screen.queryByRole('navigation')).not.toBeInTheDocument();
32
+ expect(screen.queryByText('1/3')).not.toBeInTheDocument();
33
+ });
22
34
  });
@@ -3,12 +3,16 @@ import { ButtonProps, CardBodyProps, CardFooterProps, CardProps, CardTitleProps,
3
3
  export interface SourcesCardBaseProps extends CardProps {
4
4
  /** Additional classes for the pagination navigation container. */
5
5
  className?: string;
6
+ /** The layout used to display source cards. Use wrap to display and wrap all sources at once. */
7
+ layout?: 'paginated' | 'wrap';
6
8
  /** Flag indicating if the pagination is disabled. */
7
9
  isDisabled?: boolean;
8
10
  /** @deprecated ofWord has been deprecated. Label for the English word "of." */
9
11
  ofWord?: string;
10
12
  /** Accessible label for the pagination component. */
11
13
  paginationAriaLabel?: string;
14
+ /** Max width of a source card when the wrap layout is used. Can be any valid CSS width value. */
15
+ cardMaxWidth?: string;
12
16
  /** Content rendered inside the paginated card */
13
17
  sources: {
14
18
  /** Title of sources card */
@@ -16,7 +16,7 @@ import { Button, ButtonVariant, Card, CardBody, CardFooter, CardTitle, Expandabl
16
16
  import { ExternalLinkSquareAltIcon } from '@patternfly/react-icons';
17
17
  const SourcesCardBase = (_a) => {
18
18
  var _b;
19
- var { className, isDisabled, paginationAriaLabel = 'Pagination', sources, toNextPageAriaLabel = 'Go to next page', toPreviousPageAriaLabel = 'Go to previous page', onNextClick, onPreviousClick, onSetPage, showMoreWords = 'show more', showLessWords = 'show less', isCompact, cardTitleProps, cardBodyProps, cardFooterProps } = _a, props = __rest(_a, ["className", "isDisabled", "paginationAriaLabel", "sources", "toNextPageAriaLabel", "toPreviousPageAriaLabel", "onNextClick", "onPreviousClick", "onSetPage", "showMoreWords", "showLessWords", "isCompact", "cardTitleProps", "cardBodyProps", "cardFooterProps"]);
19
+ var { className, isDisabled, paginationAriaLabel = 'Pagination', sources, toNextPageAriaLabel = 'Go to next page', toPreviousPageAriaLabel = 'Go to previous page', onNextClick, onPreviousClick, onSetPage, showMoreWords = 'show more', showLessWords = 'show less', isCompact, cardTitleProps, cardBodyProps, cardFooterProps, layout = 'paginated', cardMaxWidth = '400px' } = _a, props = __rest(_a, ["className", "isDisabled", "paginationAriaLabel", "sources", "toNextPageAriaLabel", "toPreviousPageAriaLabel", "onNextClick", "onPreviousClick", "onSetPage", "showMoreWords", "showLessWords", "isCompact", "cardTitleProps", "cardBodyProps", "cardFooterProps", "layout", "cardMaxWidth"]);
20
20
  const [page, setPage] = useState(1);
21
21
  const [isExpanded, setIsExpanded] = useState(false);
22
22
  const onToggle = (_event, isExpanded) => {
@@ -26,13 +26,22 @@ const SourcesCardBase = (_a) => {
26
26
  setPage(newPage);
27
27
  onSetPage && onSetPage(_evt, newPage);
28
28
  };
29
- const renderTitle = (title, truncateProps) => {
29
+ const renderTitle = (title, index, truncateProps) => {
30
30
  if (title) {
31
31
  return _jsx(Truncate, Object.assign({ content: title }, truncateProps));
32
32
  }
33
- return `Source ${page}`;
33
+ return `Source ${index !== undefined ? index + 1 : page}`;
34
34
  };
35
- return (_jsx("div", { className: "pf-chatbot__sources-card-base", children: _jsxs(Card, Object.assign({ isCompact: isCompact, className: "pf-chatbot__sources-card" }, props, { children: [_jsx(CardTitle, Object.assign({ className: "pf-chatbot__sources-card-title" }, cardTitleProps, { children: _jsxs("div", { className: "pf-chatbot__sources-card-title-container", children: [_jsx(Button, Object.assign({ component: "a", variant: ButtonVariant.link, href: sources[page - 1].link, icon: sources[page - 1].isExternal ? _jsx(ExternalLinkSquareAltIcon, {}) : undefined, iconPosition: "end", isInline: true, rel: sources[page - 1].isExternal ? 'noreferrer' : undefined, target: sources[page - 1].isExternal ? '_blank' : undefined, onClick: (_b = sources[page - 1].onClick) !== null && _b !== void 0 ? _b : undefined }, sources[page - 1].titleProps, { children: renderTitle(sources[page - 1].title, sources[page - 1].truncateProps) })), sources[page - 1].subtitle && (_jsx("span", { className: "pf-chatbot__sources-card-subtitle", children: sources[page - 1].subtitle }))] }) })), sources[page - 1].body && (_jsx(CardBody, Object.assign({ className: `pf-chatbot__sources-card-body ${sources[page - 1].footer ? 'pf-chatbot__compact-sources-card-body' : undefined}` }, cardBodyProps, { children: sources[page - 1].hasShowMore ? (
35
+ const renderUncontrolledSourceCard = (source, index) => {
36
+ var _a;
37
+ return (_jsx("li", { className: "pf-chatbot__sources-list-item", children: _jsxs(Card, Object.assign({ isCompact: isCompact, className: "pf-chatbot__sources-card", style: { maxWidth: cardMaxWidth } }, props, { children: [_jsx(CardTitle, Object.assign({ className: "pf-chatbot__sources-card-title" }, cardTitleProps, { children: _jsxs("div", { className: "pf-chatbot__sources-card-title-container", children: [_jsx(Button, Object.assign({ component: "a", variant: ButtonVariant.link, href: source.link, icon: source.isExternal ? _jsx(ExternalLinkSquareAltIcon, {}) : undefined, iconPosition: "end", isInline: true, rel: source.isExternal ? 'noreferrer' : undefined, target: source.isExternal ? '_blank' : undefined, onClick: (_a = source.onClick) !== null && _a !== void 0 ? _a : undefined }, source.titleProps, { children: renderTitle(source.title, index, source.truncateProps) })), source.subtitle && _jsx("span", { className: "pf-chatbot__sources-card-subtitle", children: source.subtitle })] }) })), source.body && (_jsx(CardBody, Object.assign({ className: `pf-chatbot__sources-card-body ${source.footer ? 'pf-chatbot__compact-sources-card-body' : undefined}` }, cardBodyProps, { children: source.hasShowMore ? (
38
+ // prevents extra VO announcements of button text - parent Message has aria-live
39
+ _jsx("div", { "aria-live": "off", children: _jsx(ExpandableSection, { variant: ExpandableSectionVariant.truncate, toggleTextCollapsed: showMoreWords, toggleTextExpanded: showLessWords, truncateMaxLines: 2, children: source.body }) })) : (_jsx("div", { className: "pf-chatbot__sources-card-body-text", children: source.body })) }))), source.footer && (_jsx(CardFooter, Object.assign({ className: "pf-chatbot__sources-card-footer" }, cardFooterProps, { children: source.footer })))] })) }, index));
40
+ };
41
+ if (layout === 'wrap') {
42
+ return (_jsx("div", { className: "pf-chatbot__sources-card-base pf-m-wrap", children: _jsx("ul", { className: "pf-chatbot__sources-list", role: "list", children: sources.map((source, index) => renderUncontrolledSourceCard(source, index)) }) }));
43
+ }
44
+ return (_jsx("div", { className: "pf-chatbot__sources-card-base", children: _jsxs(Card, Object.assign({ isCompact: isCompact, className: "pf-chatbot__sources-card" }, props, { children: [_jsx(CardTitle, Object.assign({ className: "pf-chatbot__sources-card-title" }, cardTitleProps, { children: _jsxs("div", { className: "pf-chatbot__sources-card-title-container", children: [_jsx(Button, Object.assign({ component: "a", variant: ButtonVariant.link, href: sources[page - 1].link, icon: sources[page - 1].isExternal ? _jsx(ExternalLinkSquareAltIcon, {}) : undefined, iconPosition: "end", isInline: true, rel: sources[page - 1].isExternal ? 'noreferrer' : undefined, target: sources[page - 1].isExternal ? '_blank' : undefined, onClick: (_b = sources[page - 1].onClick) !== null && _b !== void 0 ? _b : undefined }, sources[page - 1].titleProps, { children: renderTitle(sources[page - 1].title, undefined, sources[page - 1].truncateProps) })), sources[page - 1].subtitle && (_jsx("span", { className: "pf-chatbot__sources-card-subtitle", children: sources[page - 1].subtitle }))] }) })), sources[page - 1].body && (_jsx(CardBody, Object.assign({ className: `pf-chatbot__sources-card-body ${sources[page - 1].footer ? 'pf-chatbot__compact-sources-card-body' : undefined}` }, cardBodyProps, { children: sources[page - 1].hasShowMore ? (
36
45
  // prevents extra VO announcements of button text - parent Message has aria-live
37
46
  _jsx("div", { "aria-live": "off", children: _jsx(ExpandableSection, { variant: ExpandableSectionVariant.truncate, toggleText: isExpanded ? showLessWords : showMoreWords, onToggle: onToggle, isExpanded: isExpanded, truncateMaxLines: 2, children: sources[page - 1].body }) })) : (_jsx("div", { className: "pf-chatbot__sources-card-body-text", children: sources[page - 1].body })) }))), sources[page - 1].footer ? (_jsx(CardFooter, Object.assign({ className: "pf-chatbot__sources-card-footer" }, cardFooterProps, { children: sources[page - 1].footer }))) : (sources.length > 1 && (_jsx(CardFooter, Object.assign({ className: "pf-chatbot__sources-card-footer-container" }, cardFooterProps, { children: _jsx("div", { className: "pf-chatbot__sources-card-footer", children: _jsxs("nav", { className: `pf-chatbot__sources-card-footer-buttons ${className}`, "aria-label": paginationAriaLabel, children: [_jsx(Button, { variant: ButtonVariant.plain, isDisabled: isDisabled || page === 1, "data-action": "previous", onClick: (event) => {
38
47
  const newPage = page >= 1 ? page - 1 : 1;
@@ -163,4 +163,32 @@ describe('SourcesCardBase', () => {
163
163
  render(_jsx(SourcesCardBase, { sources: [{ title: 'How to make an apple pie', link: '', titleProps: { className: 'test' } }] }));
164
164
  expect(screen.getByRole('link', { name: /How to make an apple pie/i })).toHaveClass('test');
165
165
  });
166
+ it('should render with wrap layout when layout prop is set to wrap', () => {
167
+ render(_jsx(SourcesCardBase, { layout: "wrap", sources: [
168
+ { title: 'How to make an apple pie', link: '' },
169
+ { title: 'How to make cookies', link: '' },
170
+ { title: 'How to make a sandwich', link: '' }
171
+ ] }));
172
+ expect(screen.getByText('How to make an apple pie')).toBeVisible();
173
+ expect(screen.getByText('How to make cookies')).toBeVisible();
174
+ expect(screen.getByText('How to make a sandwich')).toBeVisible();
175
+ expect(screen.queryByRole('navigation')).not.toBeInTheDocument();
176
+ expect(screen.queryByText('1/3')).not.toBeInTheDocument();
177
+ });
178
+ it('should apply default cardMaxWidth when using wrap layout', () => {
179
+ render(_jsx(SourcesCardBase, { layout: "wrap", sources: [
180
+ { title: 'How to make an apple pie', link: '' },
181
+ { title: 'How to make cookies', link: '' }
182
+ ] }));
183
+ const firstCard = screen.getByText('How to make an apple pie').closest('.pf-chatbot__sources-card');
184
+ expect(firstCard).toHaveStyle({ maxWidth: '400px' });
185
+ });
186
+ it('should apply custom cardMaxWidth when using wrap layout', () => {
187
+ render(_jsx(SourcesCardBase, { layout: "wrap", sources: [
188
+ { title: 'How to make an apple pie', link: '' },
189
+ { title: 'How to make cookies', link: '' }
190
+ ], cardMaxWidth: "500px" }));
191
+ const firstCard = screen.getByText('How to make an apple pie').closest('.pf-chatbot__sources-card');
192
+ expect(firstCard).toHaveStyle({ maxWidth: '500px' });
193
+ });
166
194
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/chatbot",
3
- "version": "6.6.0-prerelease.2",
3
+ "version": "6.6.0-prerelease.3",
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",
@@ -319,6 +319,13 @@ _Italic text, formatted with single underscores_
319
319
  hasRoundAvatar={false}
320
320
  />
321
321
  <Message name="Bot" role="bot" content="This is a message from a bot with no avatar." />
322
+ <Message
323
+ name="Bot"
324
+ role="bot"
325
+ avatar={patternflyAvatar}
326
+ isMetadataVisible={false}
327
+ content="This is a message from a bot with metadata not visible."
328
+ />
322
329
  <Select
323
330
  id="single-select"
324
331
  isOpen={isOpen}
@@ -241,6 +241,43 @@ export const MessageWithSourcesExample: FunctionComponent = () => {
241
241
  }}
242
242
  isCompact
243
243
  />
244
+
245
+ <Message
246
+ name="Bot"
247
+ role="bot"
248
+ avatar={patternflyAvatar}
249
+ content="This example demonstrates the non-paginated layout option. When enabled, all source cards are displayed in a flex layout that wraps automatically based on available space:"
250
+ sources={{
251
+ sources: [
252
+ {
253
+ title: 'Getting started with Red Hat OpenShift',
254
+ link: '#',
255
+ body: 'Red Hat OpenShift on IBM Cloud is a managed offering to create your own cluster of compute hosts where you can deploy and manage containerized apps on IBM Cloud.',
256
+ isExternal: true,
257
+ hasShowMore: true
258
+ },
259
+ {
260
+ title: 'Azure Red Hat OpenShift documentation',
261
+ link: '#',
262
+ body: 'Microsoft Azure Red Hat OpenShift allows you to deploy a production ready Red Hat OpenShift cluster in Azure.',
263
+ isExternal: true
264
+ },
265
+ {
266
+ title: 'OKD Documentation: Home',
267
+ link: '#',
268
+ body: 'OKD is a distribution of Kubernetes optimized for continuous application development and multi-tenant deployment.',
269
+ isExternal: true
270
+ },
271
+ {
272
+ title: 'Red Hat OpenShift Container Platform',
273
+ link: '#',
274
+ body: 'Red Hat OpenShift Container Platform is a Kubernetes platform that provides a cloud-like experience anywhere it is deployed.',
275
+ isExternal: true
276
+ }
277
+ ],
278
+ layout: 'wrap'
279
+ }}
280
+ />
244
281
  </>
245
282
  );
246
283
  };
@@ -334,6 +334,13 @@ _Italic text, formatted with single underscores_
334
334
  avatarProps={{ isBordered: true }}
335
335
  />
336
336
  <Message name="User" role="user" content="This is a user message with no avatar" />
337
+ <Message
338
+ name="User"
339
+ role="user"
340
+ content="This is a user message with metadata not visible."
341
+ avatar={userAvatar}
342
+ isMetadataVisible={false}
343
+ />
337
344
  <Message
338
345
  name="User"
339
346
  role="user"
@@ -345,6 +352,13 @@ _Italic text, formatted with single underscores_
345
352
  avatar={userAvatar}
346
353
  inputRef={messageInputRef}
347
354
  />
355
+ <Message
356
+ name="User"
357
+ role="user"
358
+ avatar={userAvatar}
359
+ alignment="end"
360
+ content="This is a user message that is aligned at the end of the message container."
361
+ />
348
362
  <Select
349
363
  id="single-select"
350
364
  isOpen={isOpen}
@@ -134,6 +134,15 @@
134
134
  .footnotes {
135
135
  background-color: var(--pf-t--global--background--color--tertiary--default);
136
136
  }
137
+
138
+ // Right/End-aligned messages
139
+ &.pf-m-end {
140
+ flex-direction: row-reverse;
141
+
142
+ .pf-chatbot__message-contents {
143
+ align-items: flex-end;
144
+ }
145
+ }
137
146
  }
138
147
 
139
148
  // Attachments
@@ -255,6 +255,17 @@ describe('Message', () => {
255
255
  })
256
256
  ).not.toBeInTheDocument();
257
257
  });
258
+
259
+ it('Does not render metadata when isMetadataVisible is false', () => {
260
+ render(
261
+ <Message isMetadataVisible={false} avatar="./img" role="bot" name="Bot" content="Hi" timestamp="2 hours ago" />
262
+ );
263
+
264
+ expect(screen.queryByText('Bot')).not.toBeInTheDocument();
265
+ expect(screen.queryByText('AI')).not.toBeInTheDocument();
266
+ expect(screen.queryByText('2 hours ago')).not.toBeInTheDocument();
267
+ });
268
+
258
269
  it('should render attachments', () => {
259
270
  render(<Message avatar="./img" role="user" content="Hi" attachments={[{ name: 'testAttachment' }]} />);
260
271
  expect(screen.getByText('Hi')).toBeTruthy();
@@ -1330,4 +1341,14 @@ describe('Message', () => {
1330
1341
  );
1331
1342
  expect(container.querySelector('.pf-m-outline')).toBeFalsy();
1332
1343
  });
1344
+
1345
+ it('Renders without pf-m-end class by default', () => {
1346
+ render(<Message avatar="./img" role="user" name="User" content="" />);
1347
+ expect(screen.getByRole('region')).not.toHaveClass('pf-m-end');
1348
+ });
1349
+
1350
+ it('Renders with pf-m-end class when alignment="end"', () => {
1351
+ render(<Message alignment="end" avatar="./img" role="user" name="User" content="" />);
1352
+ expect(screen.getByRole('region')).toHaveClass('pf-m-end');
1353
+ });
1333
1354
  });
@@ -35,6 +35,7 @@ import ToolResponse, { ToolResponseProps } from '../ToolResponse';
35
35
  import DeepThinking, { DeepThinkingProps } from '../DeepThinking';
36
36
  import ToolCall, { ToolCallProps } from '../ToolCall';
37
37
  import MarkdownContent from '../MarkdownContent';
38
+ import { css } from '@patternfly/react-styles';
38
39
 
39
40
  export interface MessageAttachment {
40
41
  /** Name of file attached to the message */
@@ -73,6 +74,10 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
73
74
  id?: string;
74
75
  /** Role of the user sending the message */
75
76
  role: 'user' | 'bot';
77
+ /** Whether the message is aligned at the horizontal start or end of the message container. */
78
+ alignment?: 'start' | 'end';
79
+ /** Flag indicating whether message metadata (user name and timestamp) are visible. */
80
+ isMetadataVisible?: boolean;
76
81
  /** Message content */
77
82
  content?: string;
78
83
  /** Extra Message content */
@@ -197,6 +202,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
197
202
  export const MessageBase: FunctionComponent<MessageProps> = ({
198
203
  children,
199
204
  role,
205
+ alignment = 'start',
206
+ isMetadataVisible = true,
200
207
  content,
201
208
  extraContent,
202
209
  name,
@@ -314,7 +321,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
314
321
  return (
315
322
  <section
316
323
  aria-label={`Message from ${role} - ${dateString}`}
317
- className={`pf-chatbot__message pf-chatbot__message--${role}`}
324
+ className={css(`pf-chatbot__message pf-chatbot__message--${role}`, alignment === 'end' && 'pf-m-end')}
318
325
  aria-live={isLiveRegion ? 'polite' : undefined}
319
326
  aria-atomic={isLiveRegion ? false : undefined}
320
327
  ref={innerRef}
@@ -330,19 +337,21 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
330
337
  />
331
338
  )}
332
339
  <div className="pf-chatbot__message-contents">
333
- <div className="pf-chatbot__message-meta">
334
- {name && (
335
- <span className="pf-chatbot__message-name">
336
- <Truncate content={name} />
337
- </span>
338
- )}
339
- {role === 'bot' && (
340
- <Label variant="outline" isCompact>
341
- {botWord}
342
- </Label>
343
- )}
344
- <Timestamp date={date}>{timestamp}</Timestamp>
345
- </div>
340
+ {isMetadataVisible && (
341
+ <div className="pf-chatbot__message-meta">
342
+ {name && (
343
+ <span className="pf-chatbot__message-name">
344
+ <Truncate content={name} />
345
+ </span>
346
+ )}
347
+ {role === 'bot' && (
348
+ <Label variant="outline" isCompact>
349
+ {botWord}
350
+ </Label>
351
+ )}
352
+ <Timestamp date={date}>{timestamp}</Timestamp>
353
+ </div>
354
+ )}
346
355
  <div className="pf-chatbot__message-response">
347
356
  {children ? (
348
357
  <>{children}</>
@@ -4,7 +4,10 @@
4
4
  flex-direction: column;
5
5
  gap: var(--pf-t--global--spacer--sm);
6
6
  padding-block-start: var(--pf-t--global--spacer--sm);
7
- max-width: 22.5rem;
7
+
8
+ &:not(.pf-m-wrap) {
9
+ max-width: 22.5rem;
10
+ }
8
11
  }
9
12
 
10
13
  .pf-chatbot__sources-card-base {
@@ -15,6 +18,15 @@
15
18
  }
16
19
  }
17
20
 
21
+ .pf-chatbot__sources-card-base.pf-m-wrap {
22
+ .pf-chatbot__sources-list {
23
+ display: flex;
24
+ flex-wrap: wrap;
25
+ list-style: none;
26
+ gap: var(--pf-t--global--spacer--xs);
27
+ }
28
+ }
29
+
18
30
  .pf-chatbot__sources-card {
19
31
  box-shadow: var(--pf-t--global--box-shadow--sm);
20
32
  }
@@ -24,4 +24,24 @@ describe('SourcesCard', () => {
24
24
  screen.getByRole('button', { name: /Go to previous page/i });
25
25
  screen.getByRole('button', { name: /Go to next page/i });
26
26
  });
27
+
28
+ it('should render with wrap layout when layout is set to wrap', () => {
29
+ render(
30
+ <SourcesCard
31
+ layout="wrap"
32
+ sources={[
33
+ { title: 'How to make an apple pie', link: '' },
34
+ { title: 'How to make cookies', link: '' },
35
+ { title: 'How to make a sandwich', link: '' }
36
+ ]}
37
+ />
38
+ );
39
+
40
+ expect(screen.getByText('How to make an apple pie')).toBeVisible();
41
+ expect(screen.getByText('How to make cookies')).toBeVisible();
42
+ expect(screen.getByText('How to make a sandwich')).toBeVisible();
43
+
44
+ expect(screen.queryByRole('navigation')).not.toBeInTheDocument();
45
+ expect(screen.queryByText('1/3')).not.toBeInTheDocument();
46
+ });
27
47
  });
@@ -2,7 +2,6 @@
2
2
  // Chatbot Main - Messages - Sources Card
3
3
  // ============================================================================
4
4
  import type { FunctionComponent } from 'react';
5
- // Import PatternFly components
6
5
  import {
7
6
  ButtonProps,
8
7
  CardBodyProps,
@@ -12,11 +11,16 @@ import {
12
11
  pluralize,
13
12
  TruncateProps
14
13
  } from '@patternfly/react-core';
14
+ import { css } from '@patternfly/react-styles';
15
15
  import SourcesCardBase from '../SourcesCardBase';
16
16
 
17
17
  export interface SourcesCardProps extends CardProps {
18
18
  /** Additional classes for the pagination navigation container. */
19
19
  className?: string;
20
+ /** The layout used to display source cards. Use wrap to display and wrap all sources at once. */
21
+ layout?: 'paginated' | 'wrap';
22
+ /** Max width of a source card when the wrap layout is used. Can be any valid CSS width value. */
23
+ cardMaxWidth?: string;
20
24
  /** Flag indicating if the pagination is disabled. */
21
25
  isDisabled?: boolean;
22
26
  /** @deprecated ofWord has been deprecated. Label for the English word "of." */
@@ -76,11 +80,13 @@ const SourcesCard: FunctionComponent<SourcesCardProps> = ({
76
80
  sources,
77
81
  sourceWord = 'source',
78
82
  sourceWordPlural = 'sources',
83
+ layout = 'paginated',
84
+ cardMaxWidth = '400px',
79
85
  ...props
80
86
  }: SourcesCardProps) => (
81
- <div className="pf-chatbot__source">
87
+ <div className={css('pf-chatbot__source', layout === 'wrap' && 'pf-m-wrap')}>
82
88
  <span>{pluralize(sources.length, sourceWord, sourceWordPlural)}</span>
83
- <SourcesCardBase sources={sources} {...props} />
89
+ <SourcesCardBase sources={sources} layout={layout} cardMaxWidth={cardMaxWidth} {...props} />
84
90
  </div>
85
91
  );
86
92
 
@@ -233,4 +233,53 @@ describe('SourcesCardBase', () => {
233
233
  );
234
234
  expect(screen.getByRole('link', { name: /How to make an apple pie/i })).toHaveClass('test');
235
235
  });
236
+
237
+ it('should render with wrap layout when layout prop is set to wrap', () => {
238
+ render(
239
+ <SourcesCardBase
240
+ layout="wrap"
241
+ sources={[
242
+ { title: 'How to make an apple pie', link: '' },
243
+ { title: 'How to make cookies', link: '' },
244
+ { title: 'How to make a sandwich', link: '' }
245
+ ]}
246
+ />
247
+ );
248
+
249
+ expect(screen.getByText('How to make an apple pie')).toBeVisible();
250
+ expect(screen.getByText('How to make cookies')).toBeVisible();
251
+ expect(screen.getByText('How to make a sandwich')).toBeVisible();
252
+
253
+ expect(screen.queryByRole('navigation')).not.toBeInTheDocument();
254
+ expect(screen.queryByText('1/3')).not.toBeInTheDocument();
255
+ });
256
+
257
+ it('should apply default cardMaxWidth when using wrap layout', () => {
258
+ render(
259
+ <SourcesCardBase
260
+ layout="wrap"
261
+ sources={[
262
+ { title: 'How to make an apple pie', link: '' },
263
+ { title: 'How to make cookies', link: '' }
264
+ ]}
265
+ />
266
+ );
267
+ const firstCard = screen.getByText('How to make an apple pie').closest('.pf-chatbot__sources-card');
268
+ expect(firstCard).toHaveStyle({ maxWidth: '400px' });
269
+ });
270
+
271
+ it('should apply custom cardMaxWidth when using wrap layout', () => {
272
+ render(
273
+ <SourcesCardBase
274
+ layout="wrap"
275
+ sources={[
276
+ { title: 'How to make an apple pie', link: '' },
277
+ { title: 'How to make cookies', link: '' }
278
+ ]}
279
+ cardMaxWidth="500px"
280
+ />
281
+ );
282
+ const firstCard = screen.getByText('How to make an apple pie').closest('.pf-chatbot__sources-card');
283
+ expect(firstCard).toHaveStyle({ maxWidth: '500px' });
284
+ });
236
285
  });
@@ -27,12 +27,16 @@ import { ExternalLinkSquareAltIcon } from '@patternfly/react-icons';
27
27
  export interface SourcesCardBaseProps extends CardProps {
28
28
  /** Additional classes for the pagination navigation container. */
29
29
  className?: string;
30
+ /** The layout used to display source cards. Use wrap to display and wrap all sources at once. */
31
+ layout?: 'paginated' | 'wrap';
30
32
  /** Flag indicating if the pagination is disabled. */
31
33
  isDisabled?: boolean;
32
34
  /** @deprecated ofWord has been deprecated. Label for the English word "of." */
33
35
  ofWord?: string;
34
36
  /** Accessible label for the pagination component. */
35
37
  paginationAriaLabel?: string;
38
+ /** Max width of a source card when the wrap layout is used. Can be any valid CSS width value. */
39
+ cardMaxWidth?: string;
36
40
  /** Content rendered inside the paginated card */
37
41
  sources: {
38
42
  /** Title of sources card */
@@ -94,6 +98,8 @@ const SourcesCardBase: FunctionComponent<SourcesCardBaseProps> = ({
94
98
  cardTitleProps,
95
99
  cardBodyProps,
96
100
  cardFooterProps,
101
+ layout = 'paginated',
102
+ cardMaxWidth = '400px',
97
103
  ...props
98
104
  }: SourcesCardBaseProps) => {
99
105
  const [page, setPage] = useState(1);
@@ -108,13 +114,76 @@ const SourcesCardBase: FunctionComponent<SourcesCardBaseProps> = ({
108
114
  onSetPage && onSetPage(_evt, newPage);
109
115
  };
110
116
 
111
- const renderTitle = (title?: string, truncateProps?: TruncateProps) => {
117
+ const renderTitle = (title?: string, index?: number, truncateProps?: TruncateProps) => {
112
118
  if (title) {
113
119
  return <Truncate content={title} {...truncateProps} />;
114
120
  }
115
- return `Source ${page}`;
121
+ return `Source ${index !== undefined ? index + 1 : page}`;
116
122
  };
117
123
 
124
+ const renderUncontrolledSourceCard = (source: SourcesCardBaseProps['sources'][0], index: number) => (
125
+ <li key={index} className="pf-chatbot__sources-list-item">
126
+ <Card isCompact={isCompact} className="pf-chatbot__sources-card" style={{ maxWidth: cardMaxWidth }} {...props}>
127
+ <CardTitle className="pf-chatbot__sources-card-title" {...cardTitleProps}>
128
+ <div className="pf-chatbot__sources-card-title-container">
129
+ <Button
130
+ component="a"
131
+ variant={ButtonVariant.link}
132
+ href={source.link}
133
+ icon={source.isExternal ? <ExternalLinkSquareAltIcon /> : undefined}
134
+ iconPosition="end"
135
+ isInline
136
+ rel={source.isExternal ? 'noreferrer' : undefined}
137
+ target={source.isExternal ? '_blank' : undefined}
138
+ onClick={source.onClick ?? undefined}
139
+ {...source.titleProps}
140
+ >
141
+ {renderTitle(source.title, index, source.truncateProps)}
142
+ </Button>
143
+ {source.subtitle && <span className="pf-chatbot__sources-card-subtitle">{source.subtitle}</span>}
144
+ </div>
145
+ </CardTitle>
146
+ {source.body && (
147
+ <CardBody
148
+ className={`pf-chatbot__sources-card-body ${source.footer ? 'pf-chatbot__compact-sources-card-body' : undefined}`}
149
+ {...cardBodyProps}
150
+ >
151
+ {source.hasShowMore ? (
152
+ // prevents extra VO announcements of button text - parent Message has aria-live
153
+ <div aria-live="off">
154
+ <ExpandableSection
155
+ variant={ExpandableSectionVariant.truncate}
156
+ toggleTextCollapsed={showMoreWords}
157
+ toggleTextExpanded={showLessWords}
158
+ truncateMaxLines={2}
159
+ >
160
+ {source.body}
161
+ </ExpandableSection>
162
+ </div>
163
+ ) : (
164
+ <div className="pf-chatbot__sources-card-body-text">{source.body}</div>
165
+ )}
166
+ </CardBody>
167
+ )}
168
+ {source.footer && (
169
+ <CardFooter className="pf-chatbot__sources-card-footer" {...cardFooterProps}>
170
+ {source.footer}
171
+ </CardFooter>
172
+ )}
173
+ </Card>
174
+ </li>
175
+ );
176
+
177
+ if (layout === 'wrap') {
178
+ return (
179
+ <div className="pf-chatbot__sources-card-base pf-m-wrap">
180
+ <ul className="pf-chatbot__sources-list" role="list">
181
+ {sources.map((source, index) => renderUncontrolledSourceCard(source, index))}
182
+ </ul>
183
+ </div>
184
+ );
185
+ }
186
+
118
187
  return (
119
188
  <div className="pf-chatbot__sources-card-base">
120
189
  <Card isCompact={isCompact} className="pf-chatbot__sources-card" {...props}>
@@ -132,7 +201,7 @@ const SourcesCardBase: FunctionComponent<SourcesCardBaseProps> = ({
132
201
  onClick={sources[page - 1].onClick ?? undefined}
133
202
  {...sources[page - 1].titleProps}
134
203
  >
135
- {renderTitle(sources[page - 1].title, sources[page - 1].truncateProps)}
204
+ {renderTitle(sources[page - 1].title, undefined, sources[page - 1].truncateProps)}
136
205
  </Button>
137
206
  {sources[page - 1].subtitle && (
138
207
  <span className="pf-chatbot__sources-card-subtitle">{sources[page - 1].subtitle}</span>