@patternfly/chatbot 6.5.0-prerelease.2 → 6.5.0-prerelease.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/AttachMenu/AttachMenu.d.ts +8 -2
- package/dist/cjs/AttachMenu/AttachMenu.js +2 -2
- package/dist/cjs/ChatbotFooter/ChatbotFooter.d.ts +5 -2
- package/dist/cjs/ChatbotFooter/ChatbotFooter.js +2 -2
- package/dist/cjs/ChatbotFooter/ChatbotFooter.test.js +5 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +29 -2
- package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
- package/dist/cjs/CodeModal/CodeModal.js +53 -8
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +2 -2
- package/dist/cjs/Message/Message.d.ts +7 -1
- package/dist/cjs/Message/Message.js +11 -8
- package/dist/cjs/Message/Message.test.js +36 -0
- package/dist/cjs/Message/MessageLoading.d.ts +2 -1
- package/dist/cjs/Message/MessageLoading.js +1 -1
- package/dist/cjs/Message/TableMessage/TableMessage.d.ts +4 -1
- package/dist/cjs/Message/TableMessage/TableMessage.js +2 -2
- package/dist/cjs/Message/TextMessage/TextMessage.d.ts +4 -1
- package/dist/cjs/Message/TextMessage/TextMessage.js +2 -2
- package/dist/cjs/MessageBar/AttachButton.d.ts +2 -0
- package/dist/cjs/MessageBar/AttachButton.js +2 -2
- package/dist/cjs/MessageBar/AttachButton.test.js +4 -0
- package/dist/cjs/MessageBar/MessageBar.d.ts +16 -6
- package/dist/cjs/MessageBar/MessageBar.js +6 -5
- package/dist/cjs/MessageBar/MessageBar.test.js +62 -0
- package/dist/cjs/Onboarding/Onboarding.d.ts +36 -0
- package/dist/cjs/Onboarding/Onboarding.js +37 -0
- package/dist/cjs/Onboarding/Onboarding.test.d.ts +1 -0
- package/dist/cjs/Onboarding/Onboarding.test.js +80 -0
- package/dist/cjs/Onboarding/index.d.ts +2 -0
- package/dist/cjs/Onboarding/index.js +23 -0
- package/dist/cjs/ResponseActions/ResponseActions.d.ts +3 -0
- package/dist/cjs/ResponseActions/ResponseActions.js +28 -7
- package/dist/cjs/ResponseActions/ResponseActions.test.js +67 -12
- package/dist/cjs/__mocks__/monaco-editor.d.ts +11 -0
- package/dist/cjs/__mocks__/monaco-editor.js +18 -0
- package/dist/cjs/__mocks__/rehype-highlight.d.ts +2 -0
- package/dist/cjs/__mocks__/rehype-highlight.js +4 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +4 -1
- package/dist/css/main.css +219 -21
- package/dist/css/main.css.map +1 -1
- package/dist/dynamic/Onboarding/package.json +1 -0
- package/dist/esm/AttachMenu/AttachMenu.d.ts +8 -2
- package/dist/esm/AttachMenu/AttachMenu.js +2 -2
- package/dist/esm/ChatbotFooter/ChatbotFooter.d.ts +5 -2
- package/dist/esm/ChatbotFooter/ChatbotFooter.js +2 -2
- package/dist/esm/ChatbotFooter/ChatbotFooter.test.js +5 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +30 -3
- package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
- package/dist/esm/CodeModal/CodeModal.js +54 -9
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +2 -2
- package/dist/esm/Message/Message.d.ts +7 -1
- package/dist/esm/Message/Message.js +11 -8
- package/dist/esm/Message/Message.test.js +36 -0
- package/dist/esm/Message/MessageLoading.d.ts +2 -1
- package/dist/esm/Message/MessageLoading.js +1 -1
- package/dist/esm/Message/TableMessage/TableMessage.d.ts +4 -1
- package/dist/esm/Message/TableMessage/TableMessage.js +2 -2
- package/dist/esm/Message/TextMessage/TextMessage.d.ts +4 -1
- package/dist/esm/Message/TextMessage/TextMessage.js +2 -2
- package/dist/esm/MessageBar/AttachButton.d.ts +2 -0
- package/dist/esm/MessageBar/AttachButton.js +2 -2
- package/dist/esm/MessageBar/AttachButton.test.js +4 -0
- package/dist/esm/MessageBar/MessageBar.d.ts +16 -6
- package/dist/esm/MessageBar/MessageBar.js +6 -5
- package/dist/esm/MessageBar/MessageBar.test.js +62 -0
- package/dist/esm/Onboarding/Onboarding.d.ts +36 -0
- package/dist/esm/Onboarding/Onboarding.js +30 -0
- package/dist/esm/Onboarding/Onboarding.test.d.ts +1 -0
- package/dist/esm/Onboarding/Onboarding.test.js +75 -0
- package/dist/esm/Onboarding/index.d.ts +2 -0
- package/dist/esm/Onboarding/index.js +2 -0
- package/dist/esm/ResponseActions/ResponseActions.d.ts +3 -0
- package/dist/esm/ResponseActions/ResponseActions.js +28 -7
- package/dist/esm/ResponseActions/ResponseActions.test.js +67 -12
- package/dist/esm/__mocks__/monaco-editor.d.ts +11 -0
- package/dist/esm/__mocks__/monaco-editor.js +18 -0
- package/dist/esm/__mocks__/rehype-highlight.d.ts +2 -0
- package/dist/esm/__mocks__/rehype-highlight.js +2 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -2
- package/patternfly-docs/content/extensions/chatbot/chatbot.md +57 -0
- package/patternfly-docs/content/extensions/chatbot/design-guidelines.md +12 -12
- package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Customizing Messages/Customizing Messages.md +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +1 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +18 -4
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +3 -1
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +55 -27
- package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +29 -21
- package/patternfly-docs/content/extensions/chatbot/examples/demos/WhiteEmbeddedChatbot.tsx +451 -0
- package/patternfly-docs/patternfly-docs.config.js +2 -1
- package/patternfly-docs/patternfly-docs.source.js +1 -1
- package/src/AttachMenu/AttachMenu.tsx +26 -11
- package/src/Chatbot/Chatbot.scss +23 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +25 -0
- package/src/ChatbotFooter/ChatbotFooter.scss +21 -0
- package/src/ChatbotFooter/ChatbotFooter.test.tsx +10 -1
- package/src/ChatbotFooter/ChatbotFooter.tsx +10 -3
- package/src/ChatbotHeader/ChatbotHeader.scss +19 -0
- package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
- package/src/ChatbotModal/ChatbotModal.scss +3 -0
- package/src/CodeModal/CodeModal.tsx +72 -23
- package/src/DeepThinking/DeepThinking.scss +1 -1
- package/src/FileDetailsLabel/FileDetailsLabel.tsx +2 -2
- package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +12 -0
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +4 -1
- package/src/Message/Message.scss +11 -7
- package/src/Message/Message.test.tsx +41 -0
- package/src/Message/Message.tsx +28 -13
- package/src/Message/MessageLoading.scss +7 -0
- package/src/Message/MessageLoading.tsx +2 -2
- package/src/Message/TableMessage/TableMessage.scss +6 -1
- package/src/Message/TableMessage/TableMessage.tsx +6 -2
- package/src/Message/TextMessage/TextMessage.scss +10 -0
- package/src/Message/TextMessage/TextMessage.tsx +11 -2
- package/src/Message/UserFeedback/UserFeedback.scss +2 -1
- package/src/MessageBar/AttachButton.test.tsx +4 -0
- package/src/MessageBar/AttachButton.tsx +4 -1
- package/src/MessageBar/MessageBar.scss +40 -3
- package/src/MessageBar/MessageBar.test.tsx +102 -1
- package/src/MessageBar/MessageBar.tsx +44 -11
- package/src/Onboarding/Onboarding.scss +101 -0
- package/src/Onboarding/Onboarding.test.tsx +148 -0
- package/src/Onboarding/Onboarding.tsx +126 -0
- package/src/Onboarding/index.ts +3 -0
- package/src/ResponseActions/ResponseActions.scss +1 -1
- package/src/ResponseActions/ResponseActions.test.tsx +111 -12
- package/src/ResponseActions/ResponseActions.tsx +38 -10
- package/src/ToolCall/ToolCall.scss +1 -1
- package/src/ToolResponse/ToolResponse.scss +3 -3
- package/src/__mocks__/monaco-editor.ts +19 -0
- package/src/__mocks__/rehype-highlight.ts +3 -0
- package/src/index.ts +3 -0
- package/src/main.scss +1 -0
- package/tsconfig.json +1 -1
- package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
|
@@ -10,13 +10,40 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
-
import { forwardRef } from 'react';
|
|
13
|
+
import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
|
|
14
14
|
import { Button, Icon, Tooltip } from '@patternfly/react-core';
|
|
15
15
|
import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
|
|
16
16
|
const ChatbotHeaderMenuBase = (_a) => {
|
|
17
17
|
var { className, onMenuToggle, tooltipProps, menuAriaLabel = 'Chat history menu', innerRef, tooltipContent = 'Chat history menu', isCompact } = _a, props = __rest(_a, ["className", "onMenuToggle", "tooltipProps", "menuAriaLabel", "innerRef", "tooltipContent", "isCompact"]);
|
|
18
|
-
|
|
18
|
+
const [isDrawerAnimating, setIsDrawerAnimating] = useState(false);
|
|
19
|
+
// I'd like to use a prop here later if this works
|
|
20
|
+
const drawerState = props['aria-expanded'];
|
|
21
|
+
const isDrawerOpen = drawerState === true;
|
|
22
|
+
const prevDrawerStateRef = useRef(isDrawerOpen);
|
|
23
|
+
const buttonRef = useRef(null);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (drawerState !== undefined) {
|
|
26
|
+
const wasDrawerOpen = prevDrawerStateRef.current === true;
|
|
27
|
+
const isDrawerClosing = wasDrawerOpen && !isDrawerOpen;
|
|
28
|
+
setIsDrawerAnimating(true);
|
|
29
|
+
const timeout = setTimeout(() => {
|
|
30
|
+
setIsDrawerAnimating(false);
|
|
31
|
+
if (isDrawerClosing) {
|
|
32
|
+
requestAnimationFrame(() => {
|
|
33
|
+
var _a;
|
|
34
|
+
(_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}, 350);
|
|
38
|
+
prevDrawerStateRef.current = isDrawerOpen;
|
|
39
|
+
return () => clearTimeout(timeout);
|
|
40
|
+
}
|
|
41
|
+
}, [drawerState, isDrawerOpen]);
|
|
42
|
+
const button = useMemo(() => (_jsx(Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onMenuToggle, "aria-label": menuAriaLabel, ref: innerRef !== null && innerRef !== void 0 ? innerRef : buttonRef, icon: _jsx(Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: _jsx(BarsIcon, {}) }), size: isCompact ? 'sm' : undefined }, props))),
|
|
43
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
44
|
+
[isCompact, menuAriaLabel, onMenuToggle, innerRef, buttonRef]);
|
|
45
|
+
return (_jsx("div", { className: `pf-chatbot__menu ${className}`, children: isDrawerAnimating ? (button) : (_jsx(Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
|
|
19
46
|
// prevents VO announcements of both aria label and tooltip
|
|
20
|
-
aria: "none" }, tooltipProps, { children:
|
|
47
|
+
aria: "none" }, tooltipProps, { children: button }))) }));
|
|
21
48
|
};
|
|
22
49
|
export const ChatbotHeaderMenu = forwardRef((props, ref) => (_jsx(ChatbotHeaderMenuBase, Object.assign({ innerRef: ref }, props))));
|
|
@@ -37,6 +37,8 @@ export interface CodeModalProps {
|
|
|
37
37
|
modalBodyClassName?: string;
|
|
38
38
|
/** Class applied to modal footer */
|
|
39
39
|
modalFooterClassName?: string;
|
|
40
|
+
/** Aria label applied to spinner when loading Monaco */
|
|
41
|
+
spinnerAriaLabel?: string;
|
|
40
42
|
}
|
|
41
43
|
export declare const CodeModal: FunctionComponent<CodeModalProps>;
|
|
42
44
|
export default CodeModal;
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
11
|
var t = {};
|
|
3
12
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -14,16 +23,43 @@ import { useState, useEffect, useRef } from 'react';
|
|
|
14
23
|
import path from 'path-browserify';
|
|
15
24
|
// Import PatternFly components
|
|
16
25
|
import { CodeEditor } from '@patternfly/react-code-editor';
|
|
17
|
-
import { Button, getResizeObserver, ModalBody, ModalFooter, ModalHeader, Stack, StackItem } from '@patternfly/react-core';
|
|
26
|
+
import { Bullseye, Button, getResizeObserver, ModalBody, ModalFooter, ModalHeader, Spinner, Stack, StackItem } from '@patternfly/react-core';
|
|
18
27
|
import FileDetails, { extensionToLanguage } from '../FileDetails';
|
|
19
28
|
import { ChatbotDisplayMode } from '../Chatbot';
|
|
20
29
|
import ChatbotModal from '../ChatbotModal/ChatbotModal';
|
|
30
|
+
// Try to lazy load - some consumers need to be below a certain bundle size, but can't use the CDN and don't have webpack
|
|
31
|
+
let monacoInstance = null;
|
|
32
|
+
const loadMonaco = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
33
|
+
if (!monacoInstance) {
|
|
34
|
+
const [monaco, { loader }] = yield Promise.all([import('monaco-editor'), import('@monaco-editor/react')]);
|
|
35
|
+
monacoInstance = monaco;
|
|
36
|
+
loader.config({ monaco });
|
|
37
|
+
}
|
|
38
|
+
return monacoInstance;
|
|
39
|
+
});
|
|
21
40
|
export const CodeModal = (_a) => {
|
|
22
|
-
var { fileName, code, codeEditorControlClassName: codeEditorClassName, handleModalToggle, isCopyEnabled, isLineNumbersVisible, isModalOpen, isReadOnly, onPrimaryAction, onSecondaryAction, primaryActionBtn, secondaryActionBtn, title, displayMode = ChatbotDisplayMode.default, isCompact, modalHeaderClassName, modalBodyClassName, modalFooterClassName } = _a, props = __rest(_a, ["fileName", "code", "codeEditorControlClassName", "handleModalToggle", "isCopyEnabled", "isLineNumbersVisible", "isModalOpen", "isReadOnly", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "displayMode", "isCompact", "modalHeaderClassName", "modalBodyClassName", "modalFooterClassName"]);
|
|
41
|
+
var { fileName, code, codeEditorControlClassName: codeEditorClassName, handleModalToggle, isCopyEnabled, isLineNumbersVisible, isModalOpen, isReadOnly, onPrimaryAction, onSecondaryAction, primaryActionBtn, secondaryActionBtn, title, displayMode = ChatbotDisplayMode.default, isCompact, modalHeaderClassName, modalBodyClassName, modalFooterClassName, spinnerAriaLabel = 'Loading' } = _a, props = __rest(_a, ["fileName", "code", "codeEditorControlClassName", "handleModalToggle", "isCopyEnabled", "isLineNumbersVisible", "isModalOpen", "isReadOnly", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "displayMode", "isCompact", "modalHeaderClassName", "modalBodyClassName", "modalFooterClassName", "spinnerAriaLabel"]);
|
|
23
42
|
const [newCode, setNewCode] = useState(code);
|
|
24
43
|
const [editorInstance, setEditorInstance] = useState(null);
|
|
25
44
|
const [isEditorReady, setIsEditorReady] = useState(false);
|
|
45
|
+
const [isMonacoLoading, setIsMonacoLoading] = useState(false);
|
|
46
|
+
const [isMonacoLoaded, setIsMonacoLoaded] = useState(false);
|
|
26
47
|
const containerRef = useRef(null);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (isModalOpen && !isMonacoLoaded && !isMonacoLoading) {
|
|
50
|
+
setIsMonacoLoading(true);
|
|
51
|
+
loadMonaco()
|
|
52
|
+
.then(() => {
|
|
53
|
+
setIsMonacoLoaded(true);
|
|
54
|
+
setIsMonacoLoading(false);
|
|
55
|
+
})
|
|
56
|
+
.catch((error) => {
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
58
|
+
console.error('Failed to load Monaco editor:', error);
|
|
59
|
+
setIsMonacoLoading(false);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}, [isModalOpen, isMonacoLoaded, isMonacoLoading]);
|
|
27
63
|
useEffect(() => {
|
|
28
64
|
if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
|
|
29
65
|
return;
|
|
@@ -73,13 +109,22 @@ export const CodeModal = (_a) => {
|
|
|
73
109
|
setNewCode(value);
|
|
74
110
|
}
|
|
75
111
|
};
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
112
|
+
const renderMonacoEditor = () => {
|
|
113
|
+
if (isMonacoLoading) {
|
|
114
|
+
return (_jsx(Bullseye, { children: _jsx(Spinner, { "aria-label": spinnerAriaLabel }) }));
|
|
115
|
+
}
|
|
116
|
+
if (isMonacoLoaded) {
|
|
117
|
+
return (_jsx(CodeEditor, Object.assign({ isDarkTheme: true, isLineNumbersVisible: isLineNumbersVisible, isLanguageLabelVisible: true, isCopyEnabled: isCopyEnabled, isReadOnly: isReadOnly, code: newCode, language: extensionToLanguage[path.extname(fileName).slice(1)], onEditorDidMount: onEditorDidMount, onCodeChange: onCodeChange, className: codeEditorClassName, isFullHeight: true, options: {
|
|
118
|
+
glyphMargin: false,
|
|
119
|
+
folding: false,
|
|
120
|
+
// prevents Monaco from handling resizing itself
|
|
121
|
+
// was causing ResizeObserver issues
|
|
122
|
+
automaticLayout: false
|
|
123
|
+
} }, props)));
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
};
|
|
127
|
+
const modal = (_jsxs(ChatbotModal, { isOpen: isModalOpen, onClose: handleModalToggle, ouiaId: "CodeModal", "aria-labelledby": "code-modal-title", "aria-describedby": "code-modal", className: `pf-chatbot__code-modal ${isCompact ? 'pf-m-compact' : ''} pf-chatbot__code-modal--${displayMode}`, displayMode: displayMode, isCompact: isCompact, children: [_jsx(ModalHeader, { className: modalHeaderClassName, title: title, labelId: "code-modal-title" }), _jsx(ModalBody, { className: modalBodyClassName, id: "code-modal-body", children: _jsxs(Stack, { className: "pf-chatbot__code-modal-body", children: [_jsx(StackItem, { className: "pf-chatbot__code-modal-file-details", children: _jsx(FileDetails, { fileName: fileName }) }), _jsx("div", { className: "pf-v6-l-stack__item pf-chatbot__code-modal-editor", ref: containerRef, children: renderMonacoEditor() })] }) }), _jsxs(ModalFooter, { className: modalFooterClassName, children: [_jsx(Button, { isBlock: true, variant: "primary", onClick: handlePrimaryAction, form: "code-modal-form", children: primaryActionBtn }, "code-modal-primary"), _jsx(Button, { isBlock: true, variant: "link", onClick: handleSecondaryAction, children: secondaryActionBtn }, "code-modal-secondary")] })] }));
|
|
83
128
|
return modal;
|
|
84
129
|
};
|
|
85
130
|
export default CodeModal;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
|
|
2
|
+
import { LabelProps } from '@patternfly/react-core';
|
|
3
|
+
export interface FileDetailsLabelProps extends Omit<LabelProps, 'onClose' | 'onClick'> {
|
|
3
4
|
/** Name of file, including extension */
|
|
4
5
|
fileName: string;
|
|
5
6
|
/** Unique id of file */
|
|
@@ -18,6 +18,8 @@ export interface CodeBlockMessageProps {
|
|
|
18
18
|
collapsedText?: string;
|
|
19
19
|
/** Custom actions added to header of code block, after any default actions such as the "copy" action. */
|
|
20
20
|
customActions?: React.ReactNode;
|
|
21
|
+
/** Sets background colors to be appropriate on primary chatbot background */
|
|
22
|
+
isPrimary?: boolean;
|
|
21
23
|
}
|
|
22
|
-
declare const CodeBlockMessage: ({ children, className, "aria-label": ariaLabel, isExpandable, expandableSectionProps, expandableSectionToggleProps, expandedText, collapsedText, customActions, ...props }: CodeBlockMessageProps) => import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
declare const CodeBlockMessage: ({ children, className, "aria-label": ariaLabel, isExpandable, expandableSectionProps, expandableSectionToggleProps, expandedText, collapsedText, customActions, isPrimary, ...props }: CodeBlockMessageProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
25
|
export default CodeBlockMessage;
|
|
@@ -22,7 +22,7 @@ const DEFAULT_EXPANDED_TEXT = 'Show less';
|
|
|
22
22
|
const DEFAULT_COLLAPSED_TEXT = 'Show more';
|
|
23
23
|
const CodeBlockMessage = (_a) => {
|
|
24
24
|
var _b;
|
|
25
|
-
var { children, className, 'aria-label': ariaLabel, isExpandable = false, expandableSectionProps, expandableSectionToggleProps, expandedText = DEFAULT_EXPANDED_TEXT, collapsedText = DEFAULT_COLLAPSED_TEXT, customActions } = _a, props = __rest(_a, ["children", "className", 'aria-label', "isExpandable", "expandableSectionProps", "expandableSectionToggleProps", "expandedText", "collapsedText", "customActions"]);
|
|
25
|
+
var { children, className, 'aria-label': ariaLabel, isExpandable = false, expandableSectionProps, expandableSectionToggleProps, expandedText = DEFAULT_EXPANDED_TEXT, collapsedText = DEFAULT_COLLAPSED_TEXT, customActions, isPrimary } = _a, props = __rest(_a, ["children", "className", 'aria-label', "isExpandable", "expandableSectionProps", "expandableSectionToggleProps", "expandedText", "collapsedText", "customActions", "isPrimary"]);
|
|
26
26
|
const [copied, setCopied] = useState(false);
|
|
27
27
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
28
28
|
const buttonRef = useRef();
|
|
@@ -59,7 +59,7 @@ const CodeBlockMessage = (_a) => {
|
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
if (!String(children).includes('\n')) {
|
|
62
|
-
return (_jsx("code", Object.assign({}, props, { className:
|
|
62
|
+
return (_jsx("code", Object.assign({}, props, { className: `pf-chatbot__message-inline-code ${isPrimary ? 'pf-m-primary' : ''}`, children: children })));
|
|
63
63
|
}
|
|
64
64
|
// Setup code block header
|
|
65
65
|
const actions = (_jsxs(_Fragment, { children: [_jsxs(CodeBlockAction, { className: "pf-chatbot__message-code-block-default-action", children: [language && _jsx("div", { className: "pf-chatbot__message-code-block-language", children: language }), _jsx(Button, { ref: buttonRef, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : 'Copy code', variant: "plain", className: "pf-chatbot__button--copy", onClick: (event) => handleCopy(event, children), children: copied ? _jsx(CheckIcon, {}) : _jsx(CopyIcon, {}) }), _jsx(Tooltip, { id: tooltipID, content: "Copy", position: "top", triggerRef: buttonRef })] }), customActions] }));
|
|
@@ -10,6 +10,7 @@ import QuickResponse from './QuickResponse/QuickResponse';
|
|
|
10
10
|
import { UserFeedbackProps } from './UserFeedback/UserFeedback';
|
|
11
11
|
import { UserFeedbackCompleteProps } from './UserFeedback/UserFeedbackComplete';
|
|
12
12
|
import { TableProps } from '@patternfly/react-table';
|
|
13
|
+
import 'highlight.js/styles/vs2015.css';
|
|
13
14
|
import { PluggableList } from 'unified';
|
|
14
15
|
import { ToolResponseProps } from '../ToolResponse';
|
|
15
16
|
import { DeepThinkingProps } from '../DeepThinking';
|
|
@@ -52,7 +53,7 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
52
53
|
/** Name of the user */
|
|
53
54
|
name?: string;
|
|
54
55
|
/** Avatar src for the user */
|
|
55
|
-
avatar
|
|
56
|
+
avatar?: string;
|
|
56
57
|
/** Timestamp for the message */
|
|
57
58
|
timestamp?: string;
|
|
58
59
|
/** Set this to true if message is being loaded */
|
|
@@ -63,6 +64,9 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
63
64
|
actions?: {
|
|
64
65
|
[key: string]: ActionProps;
|
|
65
66
|
};
|
|
67
|
+
/** When true, the selected action will persist even when clicking outside the component.
|
|
68
|
+
* When false (default), clicking outside or clicking another action will deselect the current selection. */
|
|
69
|
+
persistActionSelection?: boolean;
|
|
66
70
|
/** Sources for message */
|
|
67
71
|
sources?: SourcesCardProps;
|
|
68
72
|
/** Label for the English word "AI," used to tag messages with role "bot" */
|
|
@@ -144,6 +148,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
144
148
|
toolCall?: ToolCallProps;
|
|
145
149
|
/** Whether user messages default to stripping out images in markdown */
|
|
146
150
|
hasNoImagesInUserMessages?: boolean;
|
|
151
|
+
/** Sets background colors to be appropriate on primary chatbot background */
|
|
152
|
+
isPrimary?: boolean;
|
|
147
153
|
}
|
|
148
154
|
export declare const MessageBase: FunctionComponent<MessageProps>;
|
|
149
155
|
declare const Message: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -40,6 +40,9 @@ import ImageMessage from './ImageMessage/ImageMessage';
|
|
|
40
40
|
import rehypeUnwrapImages from 'rehype-unwrap-images';
|
|
41
41
|
import rehypeExternalLinks from 'rehype-external-links';
|
|
42
42
|
import rehypeSanitize from 'rehype-sanitize';
|
|
43
|
+
import rehypeHighlight from 'rehype-highlight';
|
|
44
|
+
// see the full list of styles here: https://highlightjs.org/examples
|
|
45
|
+
import 'highlight.js/styles/vs2015.css';
|
|
43
46
|
import LinkMessage from './LinkMessage/LinkMessage';
|
|
44
47
|
import ErrorMessage from './ErrorMessage/ErrorMessage';
|
|
45
48
|
import MessageInput from './MessageInput';
|
|
@@ -49,13 +52,13 @@ import DeepThinking from '../DeepThinking';
|
|
|
49
52
|
import SuperscriptMessage from './SuperscriptMessage/SuperscriptMessage';
|
|
50
53
|
import ToolCall from '../ToolCall';
|
|
51
54
|
export const MessageBase = (_a) => {
|
|
52
|
-
var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], 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 } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages"]);
|
|
55
|
+
var { 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, ["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"]);
|
|
53
56
|
const [messageText, setMessageText] = useState(content);
|
|
54
57
|
useEffect(() => {
|
|
55
58
|
setMessageText(content);
|
|
56
59
|
}, [content]);
|
|
57
60
|
const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
|
|
58
|
-
let rehypePlugins = [rehypeUnwrapImages, rehypeMoveImagesOutOfParagraphs];
|
|
61
|
+
let rehypePlugins = [rehypeUnwrapImages, rehypeMoveImagesOutOfParagraphs, rehypeHighlight];
|
|
59
62
|
if (openLinkInNewTab) {
|
|
60
63
|
rehypePlugins = rehypePlugins.concat([[rehypeExternalLinks, { target: '_blank' }, rehypeSanitize]]);
|
|
61
64
|
}
|
|
@@ -88,13 +91,13 @@ export const MessageBase = (_a) => {
|
|
|
88
91
|
p: (props) => {
|
|
89
92
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
90
93
|
const { node } = props, rest = __rest(props, ["node"]);
|
|
91
|
-
return _jsx(TextMessage, Object.assign({ component: ContentVariants.p }, rest));
|
|
94
|
+
return _jsx(TextMessage, Object.assign({ component: ContentVariants.p }, rest, { isPrimary: isPrimary }));
|
|
92
95
|
},
|
|
93
96
|
code: (_a) => {
|
|
94
97
|
var { children } = _a, props = __rest(_a, ["children"]);
|
|
95
98
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
96
99
|
const { node } = props, codeProps = __rest(props, ["node"]);
|
|
97
|
-
return (_jsx(CodeBlockMessage, Object.assign({}, codeProps, codeBlockProps, { children: children })));
|
|
100
|
+
return (_jsx(CodeBlockMessage, Object.assign({}, codeProps, codeBlockProps, { isPrimary: isPrimary, children: children })));
|
|
98
101
|
},
|
|
99
102
|
h1: (props) => {
|
|
100
103
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -147,7 +150,7 @@ export const MessageBase = (_a) => {
|
|
|
147
150
|
return _jsx(ListItemMessage, Object.assign({}, rest));
|
|
148
151
|
},
|
|
149
152
|
// table requires node attribute for calculating headers for mobile breakpoint
|
|
150
|
-
table: (props) => _jsx(TableMessage, Object.assign({}, props, tableProps)),
|
|
153
|
+
table: (props) => _jsx(TableMessage, Object.assign({}, props, tableProps, { isPrimary: isPrimary })),
|
|
151
154
|
tbody: (props) => {
|
|
152
155
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
153
156
|
const { node } = props, rest = __rest(props, ["node"]);
|
|
@@ -200,7 +203,7 @@ export const MessageBase = (_a) => {
|
|
|
200
203
|
};
|
|
201
204
|
const renderMessage = () => {
|
|
202
205
|
if (isLoading) {
|
|
203
|
-
return _jsx(MessageLoading, { loadingWord: loadingWord });
|
|
206
|
+
return _jsx(MessageLoading, { loadingWord: loadingWord, isPrimary: isPrimary });
|
|
204
207
|
}
|
|
205
208
|
if (isEditable) {
|
|
206
209
|
return (_jsxs(_Fragment, { children: [beforeMainContent && _jsx(_Fragment, { children: beforeMainContent }), _jsx(MessageInput, Object.assign({ content: messageText, editPlaceholder: editPlaceholder, updateWord: updateWord, cancelWord: cancelWord, onEditUpdate: (event, value) => {
|
|
@@ -210,9 +213,9 @@ export const MessageBase = (_a) => {
|
|
|
210
213
|
}
|
|
211
214
|
return (_jsxs(_Fragment, { children: [beforeMainContent && _jsx(_Fragment, { children: beforeMainContent }), error ? _jsx(ErrorMessage, Object.assign({}, error)) : handleMarkdown()] }));
|
|
212
215
|
};
|
|
213
|
-
return (_jsxs("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [_jsx(Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps)), _jsxs("div", { className: "pf-chatbot__message-contents", children: [_jsxs("div", { className: "pf-chatbot__message-meta", children: [name && (_jsx("span", { className: "pf-chatbot__message-name", children: _jsx(Truncate, { content: name }) })), role === 'bot' && (_jsx(Label, { variant: "outline", isCompact: true, children: botWord })), _jsx(Timestamp, { date: date, children: timestamp })] }), _jsxs("div", { className: "pf-chatbot__message-response", children: [_jsxs("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && _jsx(_Fragment, { children: afterMainContent }), toolResponse && _jsx(ToolResponse, Object.assign({}, toolResponse)), deepThinking && _jsx(DeepThinking, Object.assign({}, deepThinking)), 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(ResponseActions, { actions: actions }), userFeedbackForm && _jsx(UserFeedback, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact })), userFeedbackComplete && (_jsx(UserFeedbackComplete, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && (_jsx("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
|
|
216
|
+
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 })] }), _jsxs("div", { className: "pf-chatbot__message-response", children: [_jsxs("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && _jsx(_Fragment, { children: afterMainContent }), toolResponse && _jsx(ToolResponse, Object.assign({}, toolResponse)), deepThinking && _jsx(DeepThinking, Object.assign({}, deepThinking)), 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(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) => {
|
|
214
217
|
var _a;
|
|
215
|
-
return (_jsx("div", { className: "pf-chatbot__message-attachment", children: _jsx(FileDetailsLabel, { fileName: attachment.name, fileId: attachment.id, onClose: attachment.onClose, onClick: attachment.onClick, isLoading: attachment.isLoading, closeButtonAriaLabel: attachment.closeButtonAriaLabel, languageTestId: attachment.languageTestId, spinnerTestId: attachment.spinnerTestId }) }, (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name));
|
|
218
|
+
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));
|
|
216
219
|
}) })), !isLoading && endContent && _jsx(_Fragment, { children: endContent })] })] })] })));
|
|
217
220
|
};
|
|
218
221
|
const Message = forwardRef((props, ref) => (_jsx(MessageBase, Object.assign({ innerRef: ref }, props))));
|
|
@@ -204,6 +204,10 @@ describe('Message', () => {
|
|
|
204
204
|
render(_jsx(Message, { avatar: "./testImg", role: "bot", name: "Bot", content: "Hi" }));
|
|
205
205
|
expect(screen.getByRole('img')).toHaveAttribute('src', './testImg');
|
|
206
206
|
});
|
|
207
|
+
it('should not render avatar if no avatar prop is passed', () => {
|
|
208
|
+
render(_jsx(Message, { role: "bot", name: "Bot", content: "Hi" }));
|
|
209
|
+
expect(screen.queryByRole('img')).not.toBeInTheDocument();
|
|
210
|
+
});
|
|
207
211
|
it('should render botWord correctly', () => {
|
|
208
212
|
render(_jsx(Message, { avatar: "./img", role: "bot", name: "Bot", content: "Hi", botWord: "\u4EBA\u5DE5\u77E5\u80FD" }));
|
|
209
213
|
expect(screen.getByText('Bot')).toBeTruthy();
|
|
@@ -826,4 +830,36 @@ describe('Message', () => {
|
|
|
826
830
|
expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
|
|
827
831
|
expect(screen.getByText("Here's why I said this.")).toBeTruthy();
|
|
828
832
|
});
|
|
833
|
+
it('should handle isPrimary correctly for inline code when it is true', () => {
|
|
834
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: INLINE_CODE, isPrimary: true }));
|
|
835
|
+
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
|
|
836
|
+
});
|
|
837
|
+
it('should handle isPrimary correctly for inline code when it is false', () => {
|
|
838
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: INLINE_CODE }));
|
|
839
|
+
expect(container.querySelector('.pf-m-primary')).toBeFalsy();
|
|
840
|
+
});
|
|
841
|
+
it('should handle isPrimary correctly for table when it is true', () => {
|
|
842
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: TABLE, isPrimary: true }));
|
|
843
|
+
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
|
|
844
|
+
});
|
|
845
|
+
it('should handle isPrimary correctly for table when it is false', () => {
|
|
846
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: TABLE }));
|
|
847
|
+
expect(container.querySelector('.pf-m-primary')).toBeFalsy();
|
|
848
|
+
});
|
|
849
|
+
it('should handle isPrimary correctly for loading when it is true', () => {
|
|
850
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "", isPrimary: true, isLoading: true }));
|
|
851
|
+
expect(container.querySelector('.pf-m-primary')).toBeTruthy();
|
|
852
|
+
});
|
|
853
|
+
it('should handle isPrimary correctly for loading when it is false', () => {
|
|
854
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "", isLoading: true }));
|
|
855
|
+
expect(container.querySelector('.pf-m-primary')).toBeFalsy();
|
|
856
|
+
});
|
|
857
|
+
it('should handle isPrimary correctly for attachments when it is true', () => {
|
|
858
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "", isPrimary: true, attachments: [{ name: 'testAttachment' }] }));
|
|
859
|
+
expect(container.querySelector('.pf-m-outline')).toBeTruthy();
|
|
860
|
+
});
|
|
861
|
+
it('should handle isPrimary correctly for attachments when it is false', () => {
|
|
862
|
+
const { container } = render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "", attachments: [{ name: 'testAttachment' }] }));
|
|
863
|
+
expect(container.querySelector('.pf-m-outline')).toBeFalsy();
|
|
864
|
+
});
|
|
829
865
|
});
|
|
@@ -2,5 +2,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
// ============================================================================
|
|
3
3
|
// Chatbot Main - Message - Processing
|
|
4
4
|
// ============================================================================
|
|
5
|
-
const MessageLoading = ({ loadingWord }) => (_jsx("div", { className:
|
|
5
|
+
const MessageLoading = ({ loadingWord, isPrimary }) => (_jsx("div", { className: `pf-chatbot__message-loading ${isPrimary ? 'pf-m-primary' : ''}`, children: _jsx("span", { className: "pf-chatbot__message-loading-dots", children: _jsx("span", { className: "pf-v6-screen-reader", children: loadingWord }) }) }));
|
|
6
6
|
export default MessageLoading;
|
|
@@ -15,5 +15,8 @@ export interface TableNode {
|
|
|
15
15
|
tagName: string;
|
|
16
16
|
type: string;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
export interface TableMessageProps {
|
|
19
|
+
isPrimary?: boolean;
|
|
20
|
+
}
|
|
21
|
+
declare const TableMessage: ({ children, isPrimary, ...props }: Omit<TableProps, "ref"> & ExtraProps & TableMessageProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
22
|
export default TableMessage;
|
|
@@ -17,7 +17,7 @@ import { Children, cloneElement } from 'react';
|
|
|
17
17
|
import { Table } from '@patternfly/react-table';
|
|
18
18
|
const TableMessage = (_a) => {
|
|
19
19
|
var _b;
|
|
20
|
-
var { children } = _a, props = __rest(_a, ["children"]);
|
|
20
|
+
var { children, isPrimary } = _a, props = __rest(_a, ["children", "isPrimary"]);
|
|
21
21
|
const { className } = props, rest = __rest(props, ["className"]);
|
|
22
22
|
// This allows us to parse the nested data we get back from the 3rd party Markdown parser
|
|
23
23
|
// Open to feedback here if there is a better way to do this
|
|
@@ -58,6 +58,6 @@ const TableMessage = (_a) => {
|
|
|
58
58
|
}
|
|
59
59
|
return (
|
|
60
60
|
// gridBreakPoint is so we show mobile-styled-PF table
|
|
61
|
-
_jsx(Table, Object.assign({ "aria-label": props['aria-label'], gridBreakPoint: "grid", className: `pf-chatbot__message-table ${className ? className : ''}` }, rest, { children: modifyChildren(children) })));
|
|
61
|
+
_jsx(Table, Object.assign({ "aria-label": props['aria-label'], gridBreakPoint: "grid", className: `pf-chatbot__message-table ${isPrimary ? 'pf-m-primary' : ''} ${className ? className : ''}` }, rest, { children: modifyChildren(children) })));
|
|
62
62
|
};
|
|
63
63
|
export default TableMessage;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { ExtraProps } from 'react-markdown';
|
|
2
2
|
import { ContentProps } from '@patternfly/react-core';
|
|
3
|
-
|
|
3
|
+
export interface TextMessageProps {
|
|
4
|
+
isPrimary?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const TextMessage: ({ component, children, isPrimary, ...props }: Omit<ContentProps, "ref"> & ExtraProps & TextMessageProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
7
|
export default TextMessage;
|
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { Content } from '@patternfly/react-core';
|
|
14
14
|
const TextMessage = (_a) => {
|
|
15
|
-
var { component, children } = _a, props = __rest(_a, ["component", "children"]);
|
|
16
|
-
return (_jsx("span", { className:
|
|
15
|
+
var { component, children, isPrimary } = _a, props = __rest(_a, ["component", "children", "isPrimary"]);
|
|
16
|
+
return (_jsx("span", { className: `pf-chatbot__message-text ${isPrimary ? 'pf-m-primary' : ''}`, children: _jsx(Content, Object.assign({ component: component }, props, { children: children })) }));
|
|
17
17
|
};
|
|
18
18
|
export default TextMessage;
|
|
@@ -41,5 +41,7 @@ export interface AttachButtonProps extends ButtonProps {
|
|
|
41
41
|
validator?: <T extends File>(file: T) => FileError | readonly FileError[] | null;
|
|
42
42
|
/** Additional props passed to react-dropzone */
|
|
43
43
|
dropzoneProps?: DropzoneOptions;
|
|
44
|
+
/** Icon displayed in attach button */
|
|
45
|
+
icon?: React.ReactNode;
|
|
44
46
|
}
|
|
45
47
|
export declare const AttachButton: import("react").ForwardRefExoticComponent<AttachButtonProps & import("react").RefAttributes<any>>;
|
|
@@ -16,12 +16,12 @@ import { Button, Icon, Tooltip } from '@patternfly/react-core';
|
|
|
16
16
|
import { useDropzone } from 'react-dropzone';
|
|
17
17
|
import { PaperclipIcon } from '@patternfly/react-icons/dist/esm/icons/paperclip-icon';
|
|
18
18
|
const AttachButtonBase = (_a) => {
|
|
19
|
-
var { onAttachAccepted, onClick, isDisabled, className, tooltipProps, innerRef, tooltipContent = 'Attach', inputTestId, isCompact, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps } = _a, props = __rest(_a, ["onAttachAccepted", "onClick", "isDisabled", "className", "tooltipProps", "innerRef", "tooltipContent", "inputTestId", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps"]);
|
|
19
|
+
var { onAttachAccepted, onClick, isDisabled, className, tooltipProps, innerRef, tooltipContent = 'Attach', inputTestId, isCompact, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps, icon = _jsx(PaperclipIcon, {}) } = _a, props = __rest(_a, ["onAttachAccepted", "onClick", "isDisabled", "className", "tooltipProps", "innerRef", "tooltipContent", "inputTestId", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps", "icon"]);
|
|
20
20
|
const { open, getInputProps } = useDropzone(Object.assign({ multiple: true, onDropAccepted: onAttachAccepted, accept: allowedFileTypes, minSize,
|
|
21
21
|
maxSize,
|
|
22
22
|
maxFiles, disabled: isAttachmentDisabled, onDrop: onAttach, onDropRejected: onAttachRejected, validator }, dropzoneProps));
|
|
23
23
|
return (_jsxs(_Fragment, { children: [_jsx("input", Object.assign({ "data-testid": inputTestId }, getInputProps(), { hidden: true })), _jsx(Tooltip, Object.assign({ id: "pf-chatbot__tooltip--attach", content: tooltipContent, position: "top", entryDelay: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.entryDelay) || 0, exitDelay: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.exitDelay) || 0, distance: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.distance) || 8, animationDuration: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.animationDuration) || 0,
|
|
24
24
|
// prevents VO announcements of both aria label and tooltip
|
|
25
|
-
aria: "none" }, tooltipProps, { children: _jsx(Button, Object.assign({ variant: "plain", ref: innerRef, className: `pf-chatbot__button--attach ${isCompact ? 'pf-m-compact' : ''} ${className !== null && className !== void 0 ? className : ''}`, "aria-label": props['aria-label'] || 'Attach', isDisabled: isDisabled, onClick: onClick !== null && onClick !== void 0 ? onClick : open, icon: _jsx(Icon, { iconSize: isCompact ? 'lg' : 'xl', isInline: true, children:
|
|
25
|
+
aria: "none" }, tooltipProps, { children: _jsx(Button, Object.assign({ variant: "plain", ref: innerRef, className: `pf-chatbot__button--attach ${isCompact ? 'pf-m-compact' : ''} ${className !== null && className !== void 0 ? className : ''}`, "aria-label": props['aria-label'] || 'Attach', isDisabled: isDisabled, onClick: onClick !== null && onClick !== void 0 ? onClick : open, icon: _jsx(Icon, { iconSize: isCompact ? 'lg' : 'xl', isInline: true, children: icon }), size: isCompact ? 'sm' : undefined }, props)) }))] }));
|
|
26
26
|
};
|
|
27
27
|
export const AttachButton = forwardRef((props, ref) => (_jsx(AttachButtonBase, Object.assign({ innerRef: ref }, props))));
|
|
@@ -140,4 +140,8 @@ describe('Attach button', () => {
|
|
|
140
140
|
expect(validator).toHaveBeenCalledWith(file);
|
|
141
141
|
expect(onAttachRejected).toHaveBeenCalled();
|
|
142
142
|
}));
|
|
143
|
+
it('should handle icon prop', () => {
|
|
144
|
+
render(_jsx(AttachButton, { icon: _jsx("img", { alt: "", src: "" }) }));
|
|
145
|
+
expect(screen.getByRole('img')).toBeVisible();
|
|
146
|
+
});
|
|
143
147
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FunctionComponent } from 'react';
|
|
2
2
|
import { Accept, DropEvent, DropzoneOptions, FileError, FileRejection } from 'react-dropzone';
|
|
3
|
-
import { ButtonProps, TextAreaProps, TooltipProps } from '@patternfly/react-core';
|
|
3
|
+
import { ButtonProps, MenuSearchInputProps, MenuSearchProps, SearchInputProps, TextAreaProps, TooltipProps } from '@patternfly/react-core';
|
|
4
|
+
import { AttachButtonProps } from './AttachButton';
|
|
4
5
|
import { ChatbotDisplayMode } from '../Chatbot';
|
|
5
6
|
export interface MessageBarWithAttachMenuProps {
|
|
6
7
|
/** Flag to enable whether attach menu is open */
|
|
@@ -12,7 +13,7 @@ export interface MessageBarWithAttachMenuProps {
|
|
|
12
13
|
/** A callback for when the attachment menu toggle is clicked */
|
|
13
14
|
onAttachMenuToggleClick: () => void;
|
|
14
15
|
/** A callback for when the input value in the menu changes. */
|
|
15
|
-
onAttachMenuInputChange
|
|
16
|
+
onAttachMenuInputChange?: (value: string) => void;
|
|
16
17
|
/** Function callback called when user selects item in menu. */
|
|
17
18
|
onAttachMenuSelect?: (event?: React.MouseEvent<Element, MouseEvent>, value?: string | number) => void;
|
|
18
19
|
/** Placeholder for search input */
|
|
@@ -21,6 +22,12 @@ export interface MessageBarWithAttachMenuProps {
|
|
|
21
22
|
onAttachMenuOnOpenChangeKeys?: string[];
|
|
22
23
|
/** Callback to change the open state of the menu. Triggered by clicking outside of the menu. */
|
|
23
24
|
onAttachMenuOpenChange?: (isOpen: boolean) => void;
|
|
25
|
+
/** Additional props passed to MenuSearch component in attach menu */
|
|
26
|
+
menuSearchProps?: Omit<MenuSearchProps, 'ref'>;
|
|
27
|
+
/** Additional props passed to MenuSearchInput component in attach menu */
|
|
28
|
+
menuSearchInputProps?: Omit<MenuSearchInputProps, 'ref'>;
|
|
29
|
+
/** Additional props passed to SearchInput component in attach menu */
|
|
30
|
+
searchInputProps?: SearchInputProps;
|
|
24
31
|
}
|
|
25
32
|
export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
|
|
26
33
|
/** Callback to get the value of input message by user */
|
|
@@ -71,11 +78,8 @@ export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
|
|
|
71
78
|
isSendButtonDisabled?: boolean;
|
|
72
79
|
/** Prop to allow passage of additional props to buttons */
|
|
73
80
|
buttonProps?: {
|
|
74
|
-
attach?: {
|
|
75
|
-
tooltipContent?: string;
|
|
81
|
+
attach?: AttachButtonProps & {
|
|
76
82
|
props?: ButtonProps;
|
|
77
|
-
inputTestId?: string;
|
|
78
|
-
tooltipProps?: Omit<TooltipProps, 'content'>;
|
|
79
83
|
};
|
|
80
84
|
stop?: {
|
|
81
85
|
tooltipContent?: string;
|
|
@@ -105,6 +109,12 @@ export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
|
|
|
105
109
|
isCompact?: boolean;
|
|
106
110
|
/** Ref applied to message bar textarea, for use with focus or other custom behaviors */
|
|
107
111
|
innerRef?: React.Ref<HTMLTextAreaElement>;
|
|
112
|
+
/** Sets background color to primary */
|
|
113
|
+
isPrimary?: boolean;
|
|
114
|
+
/** @beta Flag indicating whether the message bar has an AI indicator border. */
|
|
115
|
+
hasAiIndicator?: boolean;
|
|
116
|
+
/** @beta Flag indicating whether the chatbot is thinking in response to a query, adding an animation to the message bar. */
|
|
117
|
+
isThinking?: boolean;
|
|
108
118
|
}
|
|
109
119
|
export declare const MessageBarBase: FunctionComponent<MessageBarProps>;
|
|
110
120
|
declare const MessageBar: import("react").ForwardRefExoticComponent<MessageBarProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
@@ -12,6 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
|
|
14
14
|
import { TextArea } from '@patternfly/react-core';
|
|
15
|
+
import { css } from '@patternfly/react-styles';
|
|
15
16
|
// Import Chatbot components
|
|
16
17
|
import SendButton from './SendButton';
|
|
17
18
|
import MicrophoneButton from './MicrophoneButton';
|
|
@@ -20,7 +21,7 @@ import AttachMenu from '../AttachMenu';
|
|
|
20
21
|
import StopButton from './StopButton';
|
|
21
22
|
export const MessageBarBase = (_a) => {
|
|
22
23
|
var _b;
|
|
23
|
-
var { onSendMessage, className, alwayShowSendButton, placeholder = 'Send a message...', hasAttachButton = true, hasMicrophoneButton, listeningText = 'Listening', handleAttach, attachMenuProps, isSendButtonDisabled, handleStopButton, hasStopButton, buttonProps, onChange, displayMode, value, isCompact = false, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps, innerRef } = _a, props = __rest(_a, ["onSendMessage", "className", "alwayShowSendButton", "placeholder", "hasAttachButton", "hasMicrophoneButton", "listeningText", "handleAttach", "attachMenuProps", "isSendButtonDisabled", "handleStopButton", "hasStopButton", "buttonProps", "onChange", "displayMode", "value", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps", "innerRef"]);
|
|
24
|
+
var { onSendMessage, className, alwayShowSendButton, placeholder = 'Send a message...', hasAttachButton = true, hasMicrophoneButton, listeningText = 'Listening', handleAttach, attachMenuProps, isSendButtonDisabled, handleStopButton, hasStopButton, buttonProps, onChange, displayMode, value, isCompact = false, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps, innerRef, isPrimary, hasAiIndicator, isThinking } = _a, props = __rest(_a, ["onSendMessage", "className", "alwayShowSendButton", "placeholder", "hasAttachButton", "hasMicrophoneButton", "listeningText", "handleAttach", "attachMenuProps", "isSendButtonDisabled", "handleStopButton", "hasStopButton", "buttonProps", "onChange", "displayMode", "value", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps", "innerRef", "isPrimary", "hasAiIndicator", "isThinking"]);
|
|
24
25
|
// Text Input
|
|
25
26
|
// --------------------------------------------------------------------------
|
|
26
27
|
const [message, setMessage] = useState(value !== null && value !== void 0 ? value : '');
|
|
@@ -187,11 +188,11 @@ export const MessageBarBase = (_a) => {
|
|
|
187
188
|
onChange && onChange({}, message);
|
|
188
189
|
};
|
|
189
190
|
const renderButtons = () => {
|
|
190
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r
|
|
191
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
191
192
|
if (hasStopButton && handleStopButton) {
|
|
192
193
|
return (_jsx(StopButton, Object.assign({ onClick: handleStopButton, tooltipContent: (_a = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.stop) === null || _a === void 0 ? void 0 : _a.tooltipContent, isCompact: isCompact, tooltipProps: (_b = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.stop) === null || _b === void 0 ? void 0 : _b.tooltipProps }, (_c = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.stop) === null || _c === void 0 ? void 0 : _c.props)));
|
|
193
194
|
}
|
|
194
|
-
return (_jsxs(_Fragment, { children: [attachMenuProps && (_jsx(AttachButton, Object.assign({ ref: attachButtonRef, onClick: handleAttachMenuToggle, isDisabled: isListeningMessage, tooltipContent: (_d = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _d === void 0 ? void 0 : _d.tooltipContent, isCompact: isCompact, tooltipProps: (_e = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _e === void 0 ? void 0 : _e.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps },
|
|
195
|
+
return (_jsxs(_Fragment, { children: [attachMenuProps && (_jsx(AttachButton, Object.assign({ ref: attachButtonRef, onClick: handleAttachMenuToggle, isDisabled: isListeningMessage, tooltipContent: (_d = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _d === void 0 ? void 0 : _d.tooltipContent, isCompact: isCompact, tooltipProps: (_e = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _e === void 0 ? void 0 : _e.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach))), !attachMenuProps && hasAttachButton && (_jsx(AttachButton, Object.assign({ onAttachAccepted: handleAttach, isDisabled: isListeningMessage, tooltipContent: (_f = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _f === void 0 ? void 0 : _f.tooltipContent, inputTestId: (_g = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _g === void 0 ? void 0 : _g.inputTestId, isCompact: isCompact, tooltipProps: (_h = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _h === void 0 ? void 0 : _h.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach, (_j = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _j === void 0 ? void 0 : _j.props))), hasMicrophoneButton && (_jsx(MicrophoneButton, Object.assign({ isListening: isListeningMessage, onIsListeningChange: setIsListeningMessage, onSpeechRecognition: handleSpeechRecognition, tooltipContent: (_k = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _k === void 0 ? void 0 : _k.tooltipContent, language: (_l = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _l === void 0 ? void 0 : _l.language, isCompact: isCompact, tooltipProps: (_m = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _m === void 0 ? void 0 : _m.tooltipProps }, (_o = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _o === void 0 ? void 0 : _o.props))), (alwayShowSendButton || message) && (_jsx(SendButton, Object.assign({ value: message, onClick: () => handleSend(message), isDisabled: isSendButtonDisabled, tooltipContent: (_p = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _p === void 0 ? void 0 : _p.tooltipContent, isCompact: isCompact, tooltipProps: (_q = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _q === void 0 ? void 0 : _q.tooltipProps }, (_r = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _r === void 0 ? void 0 : _r.props)))] }));
|
|
195
196
|
};
|
|
196
197
|
const messageBarContents = (_jsxs(_Fragment, { children: [_jsx("div", { className: `pf-chatbot__message-bar-input ${isCompact ? 'pf-m-compact' : ''}`, children: _jsx(TextArea, Object.assign({ className: "pf-chatbot__message-textarea", value: message, onChange: handleChange, "aria-label": isListeningMessage ? listeningText : placeholder, placeholder: isListeningMessage ? listeningText : placeholder, ref: textareaRef, onKeyDown: handleKeyDown, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd }, props)) }), _jsx("div", { className: "pf-chatbot__message-bar-actions", children: renderButtons() })] }));
|
|
197
198
|
if (attachMenuProps) {
|
|
@@ -200,9 +201,9 @@ export const MessageBarBase = (_a) => {
|
|
|
200
201
|
(_a = attachButtonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
201
202
|
attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen(isAttachMenuOpen);
|
|
202
203
|
(attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOpenChange) && (attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOpenChange(isAttachMenuOpen));
|
|
203
|
-
}, onOpenChangeKeys: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOnOpenChangeKeys, onSelect: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuSelect }, (attachMenuProps && { handleTextInputChange: attachMenuProps.onAttachMenuInputChange }), { popperProps: { direction: 'up', distance: 8 }, searchInputPlaceholder: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuInputPlaceholder })));
|
|
204
|
+
}, onOpenChangeKeys: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOnOpenChangeKeys, onSelect: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuSelect }, (attachMenuProps && { handleTextInputChange: attachMenuProps.onAttachMenuInputChange }), { popperProps: { direction: 'up', distance: 8 }, searchInputPlaceholder: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuInputPlaceholder }, attachMenuProps)));
|
|
204
205
|
}
|
|
205
|
-
return _jsx("div", { className:
|
|
206
|
+
return (_jsx("div", { className: css('pf-chatbot__message-bar', isPrimary && 'pf-m-primary', hasAiIndicator && 'pf-v6-m-ai-indicator', isThinking && 'pf-v6-m-thinking', className), children: messageBarContents }));
|
|
206
207
|
};
|
|
207
208
|
const MessageBar = forwardRef((props, ref) => (_jsx(MessageBarBase, Object.assign({ innerRef: ref }, props))));
|
|
208
209
|
export { MessageBar };
|