@patternfly/chatbot 6.5.0-prerelease.23 → 6.5.0-prerelease.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +12 -2
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.js +131 -0
- package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +2 -0
- package/dist/cjs/Message/UserFeedback/UserFeedback.js +5 -5
- package/dist/cjs/MessageBar/MessageBar.js +18 -4
- package/dist/css/main.css +34 -9
- package/dist/css/main.css.map +1 -1
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +12 -2
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.js +126 -0
- package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +2 -0
- package/dist/esm/Message/UserFeedback/UserFeedback.js +6 -6
- package/dist/esm/MessageBar/MessageBar.js +18 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +14 -1
- package/src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx +171 -0
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +12 -3
- package/src/Message/QuickResponse/QuickResponse.scss +3 -1
- package/src/Message/UserFeedback/UserFeedback.scss +28 -1
- package/src/Message/UserFeedback/UserFeedback.tsx +22 -12
- package/src/MessageBar/AttachButton.scss +0 -1
- package/src/MessageBar/MessageBar.scss +11 -2
- package/src/MessageBar/MessageBar.tsx +22 -3
- package/src/MessageBar/MicrophoneButton.scss +0 -1
- package/src/MessageBar/SendButton.scss +0 -1
- package/src/MessageBar/StopButton.scss +0 -1
|
@@ -9,14 +9,14 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import { useState, useRef, useEffect } from 'react';
|
|
14
14
|
// Import PatternFly components
|
|
15
15
|
import { ActionGroup, Button, Card, CardBody, CardHeader, Form, TextArea } from '@patternfly/react-core';
|
|
16
16
|
import QuickResponse from '../QuickResponse/QuickResponse';
|
|
17
17
|
import CloseButton from './CloseButton';
|
|
18
18
|
const UserFeedback = (_a) => {
|
|
19
|
-
var { className, timestamp, title = 'Why did you choose this rating?', hasTextArea, textAreaAriaLabel = `Provide optional additional feedback for message received at ${timestamp}`, textAreaPlaceholder = 'Provide optional additional feedback', onTextAreaChange, submitWord = 'Submit', quickResponses, quickResponseContainerProps = { 'aria-label': `Quick feedback for message received at ${timestamp}` }, onSubmit, onClose, closeButtonAriaLabel = `Close feedback for message received at ${timestamp}`, id, headingLevel: HeadingLevel = 'h1', focusOnLoad = true, isCompact, children, cardHeaderProps, cardBodyProps, headingLevelProps, formProps, textAreaProps, actionGroupProps, submitButtonProps } = _a, props = __rest(_a, ["className", "timestamp", "title", "hasTextArea", "textAreaAriaLabel", "textAreaPlaceholder", "onTextAreaChange", "submitWord", "quickResponses", "quickResponseContainerProps", "onSubmit", "onClose", "closeButtonAriaLabel", "id", "headingLevel", "focusOnLoad", "isCompact", "children", "cardHeaderProps", "cardBodyProps", "headingLevelProps", "formProps", "textAreaProps", "actionGroupProps", "submitButtonProps"]);
|
|
19
|
+
var { className, timestamp, title = 'Why did you choose this rating?', hasTextArea, textAreaAriaLabel = `Provide optional additional feedback for message received at ${timestamp}`, textAreaPlaceholder = 'Provide optional additional feedback', onTextAreaChange, submitWord = 'Submit', quickResponses, quickResponseContainerProps = { 'aria-label': `Quick feedback for message received at ${timestamp}` }, onSubmit, onClose, closeButtonAriaLabel = `Close feedback for message received at ${timestamp}`, id, headingLevel: HeadingLevel = 'h1', focusOnLoad = true, isCompact, children, cardHeaderProps, cardBodyProps, headingLevelProps, formProps, textAreaProps, actionGroupProps, submitButtonProps, privacyStatement } = _a, props = __rest(_a, ["className", "timestamp", "title", "hasTextArea", "textAreaAriaLabel", "textAreaPlaceholder", "onTextAreaChange", "submitWord", "quickResponses", "quickResponseContainerProps", "onSubmit", "onClose", "closeButtonAriaLabel", "id", "headingLevel", "focusOnLoad", "isCompact", "children", "cardHeaderProps", "cardBodyProps", "headingLevelProps", "formProps", "textAreaProps", "actionGroupProps", "submitButtonProps", "privacyStatement"]);
|
|
20
20
|
const [selectedResponse, setSelectedResponse] = useState();
|
|
21
21
|
const [value, setValue] = useState('');
|
|
22
22
|
const divRef = useRef(null);
|
|
@@ -30,9 +30,9 @@ const UserFeedback = (_a) => {
|
|
|
30
30
|
/* card does not have ref forwarding; hence wrapper div */
|
|
31
31
|
_jsx("div", { ref: divRef, id: id, tabIndex: 0, "aria-label": title, children: _jsxs(Card, Object.assign({ isCompact: isCompact, className: `pf-chatbot__feedback-card ${className ? className : ''}` }, props, { children: [_jsx(CardHeader, Object.assign({ actions: {
|
|
32
32
|
actions: _jsx(CloseButton, { onClose: onClose, ariaLabel: closeButtonAriaLabel })
|
|
33
|
-
} }, cardHeaderProps, { children: _jsx(HeadingLevel, Object.assign({ className: "pf-chatbot__feedback-card-title" }, headingLevelProps, { children: title })) })), _jsx(CardBody, Object.assign({}, cardBodyProps, { children: _jsxs(Form, Object.assign({ className: `pf-chatbot__feedback-card-form ${isCompact ? 'pf-m-compact' : ''}` }, formProps, { children: [quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, onSelect: (id) => setSelectedResponse(id), isCompact: isCompact })), hasTextArea && (_jsx(TextArea, Object.assign({ value: value, onChange: (_event, value) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
} }, cardHeaderProps, { children: _jsx(HeadingLevel, Object.assign({ className: "pf-chatbot__feedback-card-title" }, headingLevelProps, { children: title })) })), _jsx(CardBody, Object.assign({}, cardBodyProps, { children: _jsxs(Form, Object.assign({ className: `pf-chatbot__feedback-card-form ${isCompact ? 'pf-m-compact' : ''}` }, formProps, { children: [quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, onSelect: (id) => setSelectedResponse(id), isCompact: isCompact })), hasTextArea && (_jsx(_Fragment, { children: _jsx(TextArea, Object.assign({ value: value, onChange: (_event, value) => {
|
|
34
|
+
setValue(value);
|
|
35
|
+
onTextAreaChange && onTextAreaChange(_event, value);
|
|
36
|
+
}, placeholder: textAreaPlaceholder, "aria-label": textAreaAriaLabel, resizeOrientation: "vertical" }, textAreaProps)) })), privacyStatement && _jsx("div", { className: "pf-chatbot__feedback-card-privacy", children: privacyStatement }), children, _jsx(ActionGroup, Object.assign({}, actionGroupProps, { children: _jsx(Button, Object.assign({ onClick: () => onSubmit(selectedResponse, value), size: isCompact ? 'sm' : undefined }, submitButtonProps, { children: submitWord })) }))] })) }))] })) }));
|
|
37
37
|
};
|
|
38
38
|
export default UserFeedback;
|
|
@@ -28,6 +28,7 @@ export const MessageBarBase = (_a) => {
|
|
|
28
28
|
const [isListeningMessage, setIsListeningMessage] = useState(false);
|
|
29
29
|
const [hasSentMessage, setHasSentMessage] = useState(false);
|
|
30
30
|
const [isComposing, setIsComposing] = useState(false);
|
|
31
|
+
const [isMultiline, setIsMultiline] = useState(false);
|
|
31
32
|
const inputRef = useRef(null);
|
|
32
33
|
const textareaRef = (_b = innerRef) !== null && _b !== void 0 ? _b : inputRef;
|
|
33
34
|
const attachButtonRef = useRef(null);
|
|
@@ -68,6 +69,15 @@ export const MessageBarBase = (_a) => {
|
|
|
68
69
|
const lines = field.scrollHeight / lineHeight;
|
|
69
70
|
return lines > 2;
|
|
70
71
|
};
|
|
72
|
+
const checkIfMultiline = useCallback((field) => {
|
|
73
|
+
const parent = field.parentElement;
|
|
74
|
+
const grandparent = parent === null || parent === void 0 ? void 0 : parent.parentElement;
|
|
75
|
+
if (grandparent) {
|
|
76
|
+
const containerHeight = grandparent.offsetHeight;
|
|
77
|
+
const threshold = isCompact ? 56 : 70;
|
|
78
|
+
setIsMultiline(containerHeight > threshold);
|
|
79
|
+
}
|
|
80
|
+
}, [isCompact]);
|
|
71
81
|
const setAutoWidth = useCallback((field) => {
|
|
72
82
|
const parent = field.parentElement;
|
|
73
83
|
if (parent) {
|
|
@@ -120,13 +130,15 @@ export const MessageBarBase = (_a) => {
|
|
|
120
130
|
if (field) {
|
|
121
131
|
if (field.value === '') {
|
|
122
132
|
setInitialLineHeight(field);
|
|
133
|
+
setIsMultiline(false);
|
|
123
134
|
}
|
|
124
135
|
else {
|
|
125
136
|
setAutoHeight(field);
|
|
126
137
|
setAutoWidth(field);
|
|
138
|
+
checkIfMultiline(field);
|
|
127
139
|
}
|
|
128
140
|
}
|
|
129
|
-
}, [displayMode, message, setAutoWidth]);
|
|
141
|
+
}, [displayMode, message, setAutoWidth, checkIfMultiline]);
|
|
130
142
|
useEffect(() => {
|
|
131
143
|
const field = textareaRef.current;
|
|
132
144
|
if (field) {
|
|
@@ -139,13 +151,15 @@ export const MessageBarBase = (_a) => {
|
|
|
139
151
|
if (textareaRef.current) {
|
|
140
152
|
if (event.target.value === '') {
|
|
141
153
|
setInitialLineHeight(textareaRef.current);
|
|
154
|
+
setIsMultiline(false);
|
|
142
155
|
}
|
|
143
156
|
else {
|
|
144
157
|
setAutoHeight(textareaRef.current);
|
|
158
|
+
checkIfMultiline(textareaRef.current);
|
|
145
159
|
}
|
|
146
160
|
}
|
|
147
161
|
setMessage(event.target.value);
|
|
148
|
-
}, [onChange]);
|
|
162
|
+
}, [onChange, checkIfMultiline]);
|
|
149
163
|
// Handle sending message
|
|
150
164
|
const handleSend = useCallback((newMessage) => {
|
|
151
165
|
onSendMessage(newMessage);
|
|
@@ -196,14 +210,14 @@ export const MessageBarBase = (_a) => {
|
|
|
196
210
|
};
|
|
197
211
|
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() })] }));
|
|
198
212
|
if (attachMenuProps) {
|
|
199
|
-
return (_jsx(AttachMenu, Object.assign({ toggle: (toggleRef) => (_jsx("div", { ref: toggleRef, className:
|
|
213
|
+
return (_jsx(AttachMenu, Object.assign({ toggle: (toggleRef) => (_jsx("div", { ref: toggleRef, className: css('pf-chatbot__message-bar', isMultiline && 'pf-m-multiline', className), children: messageBarContents })), filteredItems: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuItems }, (attachMenuProps && { isOpen: attachMenuProps.isAttachMenuOpen }), { onOpenChange: (isAttachMenuOpen) => {
|
|
200
214
|
var _a;
|
|
201
215
|
(_a = attachButtonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
202
216
|
attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen(isAttachMenuOpen);
|
|
203
217
|
(attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOpenChange) && (attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOpenChange(isAttachMenuOpen));
|
|
204
218
|
}, 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)));
|
|
205
219
|
}
|
|
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 }));
|
|
220
|
+
return (_jsx("div", { className: css('pf-chatbot__message-bar', isPrimary && 'pf-m-primary', hasAiIndicator && 'pf-v6-m-ai-indicator', isThinking && 'pf-v6-m-thinking', isMultiline && 'pf-m-multiline', className), children: messageBarContents }));
|
|
207
221
|
};
|
|
208
222
|
const MessageBar = forwardRef((props, ref) => (_jsx(MessageBarBase, Object.assign({ innerRef: ref }, props))));
|
|
209
223
|
export { MessageBar };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/index.ts","../src/AttachMenu/AttachMenu.tsx","../src/AttachMenu/index.ts","../src/AttachmentEdit/AttachmentEdit.test.tsx","../src/AttachmentEdit/AttachmentEdit.tsx","../src/AttachmentEdit/index.ts","../src/Chatbot/Chatbot.test.tsx","../src/Chatbot/Chatbot.tsx","../src/Chatbot/index.ts","../src/ChatbotAlert/ChatbotAlert.test.tsx","../src/ChatbotAlert/ChatbotAlert.tsx","../src/ChatbotAlert/index.ts","../src/ChatbotContent/ChatbotContent.test.tsx","../src/ChatbotContent/ChatbotContent.tsx","../src/ChatbotContent/index.ts","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx","../src/ChatbotConversationHistoryNav/EmptyState.tsx","../src/ChatbotConversationHistoryNav/LoadingState.tsx","../src/ChatbotConversationHistoryNav/index.ts","../src/ChatbotFooter/ChatbotFooter.test.tsx","../src/ChatbotFooter/ChatbotFooter.tsx","../src/ChatbotFooter/ChatbotFooternote.test.tsx","../src/ChatbotFooter/ChatbotFootnote.tsx","../src/ChatbotFooter/index.ts","../src/ChatbotHeader/ChatbotHeader.test.tsx","../src/ChatbotHeader/ChatbotHeader.tsx","../src/ChatbotHeader/ChatbotHeaderActions.test.tsx","../src/ChatbotHeader/ChatbotHeaderActions.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.tsx","../src/ChatbotHeader/ChatbotHeaderMain.test.tsx","../src/ChatbotHeader/ChatbotHeaderMain.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.test.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.test.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.tsx","../src/ChatbotHeader/index.ts","../src/ChatbotModal/ChatbotModal.test.tsx","../src/ChatbotModal/ChatbotModal.tsx","../src/ChatbotModal/index.ts","../src/ChatbotPopover/ChatbotPopover.tsx","../src/ChatbotPopover/index.ts","../src/ChatbotToggle/ChatbotToggle.test.tsx","../src/ChatbotToggle/ChatbotToggle.tsx","../src/ChatbotToggle/index.ts","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.tsx","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.tsx","../src/ChatbotWelcomePrompt/index.ts","../src/CodeModal/CodeModal.test.tsx","../src/CodeModal/CodeModal.tsx","../src/CodeModal/index.ts","../src/Compare/Compare.test.tsx","../src/Compare/Compare.tsx","../src/Compare/index.ts","../src/DeepThinking/DeepThinking.test.tsx","../src/DeepThinking/DeepThinking.tsx","../src/DeepThinking/index.ts","../src/FileDetails/FileDetails.test.tsx","../src/FileDetails/FileDetails.tsx","../src/FileDetails/index.ts","../src/FileDetailsLabel/FileDetailsLabel.test.tsx","../src/FileDetailsLabel/FileDetailsLabel.tsx","../src/FileDetailsLabel/index.ts","../src/FileDropZone/FileDropZone.test.tsx","../src/FileDropZone/FileDropZone.tsx","../src/FileDropZone/index.ts","../src/FilePreview/FilePreview.test.tsx","../src/FilePreview/FilePreview.tsx","../src/FilePreview/index.ts","../src/ImagePreview/ImagePreview.test.tsx","../src/ImagePreview/ImagePreview.tsx","../src/ImagePreview/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/MarkdownContent/MarkdownContent.test.tsx","../src/MarkdownContent/MarkdownContent.tsx","../src/MarkdownContent/index.ts","../src/Message/Message.test.tsx","../src/Message/Message.tsx","../src/Message/MessageInput.tsx","../src/Message/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/ErrorMessage/ErrorMessage.tsx","../src/Message/ImageMessage/ImageMessage.tsx","../src/Message/LinkMessage/LinkMessage.tsx","../src/Message/ListMessage/ListItemMessage.tsx","../src/Message/ListMessage/OrderedListMessage.tsx","../src/Message/ListMessage/UnorderedListMessage.tsx","../src/Message/Plugins/index.ts","../src/Message/Plugins/rehypeCodeBlockToggle.ts","../src/Message/Plugins/rehypeMoveImagesOutOfParagraphs.ts","../src/Message/QuickResponse/QuickResponse.tsx","../src/Message/QuickStarts/FallbackImg.tsx","../src/Message/QuickStarts/QuickStartTile.tsx","../src/Message/QuickStarts/QuickStartTileDescription.test.tsx","../src/Message/QuickStarts/QuickStartTileDescription.tsx","../src/Message/QuickStarts/QuickStartTileHeader.tsx","../src/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.ts","../src/Message/QuickStarts/monitor-sampleapp-quickstart.ts","../src/Message/QuickStarts/types.ts","../src/Message/SuperscriptMessage/SuperscriptMessage.tsx","../src/Message/TableMessage/TableMessage.tsx","../src/Message/TableMessage/TbodyMessage.tsx","../src/Message/TableMessage/TdMessage.tsx","../src/Message/TableMessage/ThMessage.tsx","../src/Message/TableMessage/TheadMessage.tsx","../src/Message/TableMessage/TrMessage.tsx","../src/Message/TextMessage/TextMessage.tsx","../src/Message/UserFeedback/CloseButton.tsx","../src/Message/UserFeedback/UserFeedback.test.tsx","../src/Message/UserFeedback/UserFeedback.tsx","../src/Message/UserFeedback/UserFeedbackComplete.test.tsx","../src/Message/UserFeedback/UserFeedbackComplete.tsx","../src/MessageBar/AttachButton.test.tsx","../src/MessageBar/AttachButton.tsx","../src/MessageBar/MessageBar.test.tsx","../src/MessageBar/MessageBar.tsx","../src/MessageBar/MicrophoneButton.tsx","../src/MessageBar/SendButton.test.tsx","../src/MessageBar/SendButton.tsx","../src/MessageBar/StopButton.test.tsx","../src/MessageBar/StopButton.tsx","../src/MessageBar/index.ts","../src/MessageBox/JumpButton.test.tsx","../src/MessageBox/JumpButton.tsx","../src/MessageBox/MessageBox.test.tsx","../src/MessageBox/MessageBox.tsx","../src/MessageBox/index.ts","../src/MessageDivider/MessageDivider.test.tsx","../src/MessageDivider/MessageDivider.tsx","../src/MessageDivider/index.ts","../src/Onboarding/Onboarding.test.tsx","../src/Onboarding/Onboarding.tsx","../src/Onboarding/index.ts","../src/PreviewAttachment/PreviewAttachment.test.tsx","../src/PreviewAttachment/PreviewAttachment.tsx","../src/PreviewAttachment/index.ts","../src/ResponseActions/ResponseActionButton.test.tsx","../src/ResponseActions/ResponseActionButton.tsx","../src/ResponseActions/ResponseActions.test.tsx","../src/ResponseActions/ResponseActions.tsx","../src/ResponseActions/index.ts","../src/Settings/SettingsForm.test.tsx","../src/Settings/SettingsForm.tsx","../src/Settings/index.ts","../src/SourceDetailsMenuItem/SourceDetailsMenuItem.tsx","../src/SourceDetailsMenuItem/index.ts","../src/SourcesCard/SourcesCard.test.tsx","../src/SourcesCard/SourcesCard.tsx","../src/SourcesCard/index.ts","../src/SourcesCardBase/SourcesCardBase.test.tsx","../src/SourcesCardBase/SourcesCardBase.tsx","../src/SourcesCardBase/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/ToolCall/ToolCall.test.tsx","../src/ToolCall/ToolCall.tsx","../src/ToolCall/index.ts","../src/ToolResponse/ToolResponse.test.tsx","../src/ToolResponse/ToolResponse.tsx","../src/ToolResponse/index.ts","../src/__mocks__/monaco-editor.ts","../src/__mocks__/rehype-external-links.ts","../src/__mocks__/rehype-highlight.ts","../src/__mocks__/rehype-sanitize.ts","../src/__mocks__/rehype-unwrap-images.tsx","../src/tracking/console_tracking_provider.ts","../src/tracking/index.ts","../src/tracking/posthog_tracking_provider.ts","../src/tracking/segment_tracking_provider.ts","../src/tracking/trackingProviderProxy.ts","../src/tracking/tracking_api.ts","../src/tracking/tracking_registry.ts","../src/tracking/tracking_spi.ts","../src/tracking/umami_tracking_provider.ts"],"version":"5.6.3"}
|
|
1
|
+
{"root":["../src/index.ts","../src/AttachMenu/AttachMenu.tsx","../src/AttachMenu/index.ts","../src/AttachmentEdit/AttachmentEdit.test.tsx","../src/AttachmentEdit/AttachmentEdit.tsx","../src/AttachmentEdit/index.ts","../src/Chatbot/Chatbot.test.tsx","../src/Chatbot/Chatbot.tsx","../src/Chatbot/index.ts","../src/ChatbotAlert/ChatbotAlert.test.tsx","../src/ChatbotAlert/ChatbotAlert.tsx","../src/ChatbotAlert/index.ts","../src/ChatbotContent/ChatbotContent.test.tsx","../src/ChatbotContent/ChatbotContent.tsx","../src/ChatbotContent/index.ts","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx","../src/ChatbotConversationHistoryNav/EmptyState.tsx","../src/ChatbotConversationHistoryNav/LoadingState.tsx","../src/ChatbotConversationHistoryNav/index.ts","../src/ChatbotFooter/ChatbotFooter.test.tsx","../src/ChatbotFooter/ChatbotFooter.tsx","../src/ChatbotFooter/ChatbotFooternote.test.tsx","../src/ChatbotFooter/ChatbotFootnote.tsx","../src/ChatbotFooter/index.ts","../src/ChatbotHeader/ChatbotHeader.test.tsx","../src/ChatbotHeader/ChatbotHeader.tsx","../src/ChatbotHeader/ChatbotHeaderActions.test.tsx","../src/ChatbotHeader/ChatbotHeaderActions.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.tsx","../src/ChatbotHeader/ChatbotHeaderMain.test.tsx","../src/ChatbotHeader/ChatbotHeaderMain.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.test.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.test.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.tsx","../src/ChatbotHeader/index.ts","../src/ChatbotModal/ChatbotModal.test.tsx","../src/ChatbotModal/ChatbotModal.tsx","../src/ChatbotModal/index.ts","../src/ChatbotPopover/ChatbotPopover.tsx","../src/ChatbotPopover/index.ts","../src/ChatbotToggle/ChatbotToggle.test.tsx","../src/ChatbotToggle/ChatbotToggle.tsx","../src/ChatbotToggle/index.ts","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.tsx","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.tsx","../src/ChatbotWelcomePrompt/index.ts","../src/CodeModal/CodeModal.test.tsx","../src/CodeModal/CodeModal.tsx","../src/CodeModal/index.ts","../src/Compare/Compare.test.tsx","../src/Compare/Compare.tsx","../src/Compare/index.ts","../src/DeepThinking/DeepThinking.test.tsx","../src/DeepThinking/DeepThinking.tsx","../src/DeepThinking/index.ts","../src/FileDetails/FileDetails.test.tsx","../src/FileDetails/FileDetails.tsx","../src/FileDetails/index.ts","../src/FileDetailsLabel/FileDetailsLabel.test.tsx","../src/FileDetailsLabel/FileDetailsLabel.tsx","../src/FileDetailsLabel/index.ts","../src/FileDropZone/FileDropZone.test.tsx","../src/FileDropZone/FileDropZone.tsx","../src/FileDropZone/index.ts","../src/FilePreview/FilePreview.test.tsx","../src/FilePreview/FilePreview.tsx","../src/FilePreview/index.ts","../src/ImagePreview/ImagePreview.test.tsx","../src/ImagePreview/ImagePreview.tsx","../src/ImagePreview/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/MarkdownContent/MarkdownContent.test.tsx","../src/MarkdownContent/MarkdownContent.tsx","../src/MarkdownContent/index.ts","../src/Message/Message.test.tsx","../src/Message/Message.tsx","../src/Message/MessageInput.tsx","../src/Message/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/ErrorMessage/ErrorMessage.tsx","../src/Message/ImageMessage/ImageMessage.tsx","../src/Message/LinkMessage/LinkMessage.tsx","../src/Message/ListMessage/ListItemMessage.tsx","../src/Message/ListMessage/OrderedListMessage.tsx","../src/Message/ListMessage/UnorderedListMessage.tsx","../src/Message/Plugins/index.ts","../src/Message/Plugins/rehypeCodeBlockToggle.ts","../src/Message/Plugins/rehypeMoveImagesOutOfParagraphs.ts","../src/Message/QuickResponse/QuickResponse.tsx","../src/Message/QuickStarts/FallbackImg.tsx","../src/Message/QuickStarts/QuickStartTile.tsx","../src/Message/QuickStarts/QuickStartTileDescription.test.tsx","../src/Message/QuickStarts/QuickStartTileDescription.tsx","../src/Message/QuickStarts/QuickStartTileHeader.tsx","../src/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.ts","../src/Message/QuickStarts/monitor-sampleapp-quickstart.ts","../src/Message/QuickStarts/types.ts","../src/Message/SuperscriptMessage/SuperscriptMessage.tsx","../src/Message/TableMessage/TableMessage.tsx","../src/Message/TableMessage/TbodyMessage.tsx","../src/Message/TableMessage/TdMessage.tsx","../src/Message/TableMessage/ThMessage.tsx","../src/Message/TableMessage/TheadMessage.tsx","../src/Message/TableMessage/TrMessage.tsx","../src/Message/TextMessage/TextMessage.tsx","../src/Message/UserFeedback/CloseButton.tsx","../src/Message/UserFeedback/UserFeedback.test.tsx","../src/Message/UserFeedback/UserFeedback.tsx","../src/Message/UserFeedback/UserFeedbackComplete.test.tsx","../src/Message/UserFeedback/UserFeedbackComplete.tsx","../src/MessageBar/AttachButton.test.tsx","../src/MessageBar/AttachButton.tsx","../src/MessageBar/MessageBar.test.tsx","../src/MessageBar/MessageBar.tsx","../src/MessageBar/MicrophoneButton.tsx","../src/MessageBar/SendButton.test.tsx","../src/MessageBar/SendButton.tsx","../src/MessageBar/StopButton.test.tsx","../src/MessageBar/StopButton.tsx","../src/MessageBar/index.ts","../src/MessageBox/JumpButton.test.tsx","../src/MessageBox/JumpButton.tsx","../src/MessageBox/MessageBox.test.tsx","../src/MessageBox/MessageBox.tsx","../src/MessageBox/index.ts","../src/MessageDivider/MessageDivider.test.tsx","../src/MessageDivider/MessageDivider.tsx","../src/MessageDivider/index.ts","../src/Onboarding/Onboarding.test.tsx","../src/Onboarding/Onboarding.tsx","../src/Onboarding/index.ts","../src/PreviewAttachment/PreviewAttachment.test.tsx","../src/PreviewAttachment/PreviewAttachment.tsx","../src/PreviewAttachment/index.ts","../src/ResponseActions/ResponseActionButton.test.tsx","../src/ResponseActions/ResponseActionButton.tsx","../src/ResponseActions/ResponseActions.test.tsx","../src/ResponseActions/ResponseActions.tsx","../src/ResponseActions/index.ts","../src/Settings/SettingsForm.test.tsx","../src/Settings/SettingsForm.tsx","../src/Settings/index.ts","../src/SourceDetailsMenuItem/SourceDetailsMenuItem.tsx","../src/SourceDetailsMenuItem/index.ts","../src/SourcesCard/SourcesCard.test.tsx","../src/SourcesCard/SourcesCard.tsx","../src/SourcesCard/index.ts","../src/SourcesCardBase/SourcesCardBase.test.tsx","../src/SourcesCardBase/SourcesCardBase.tsx","../src/SourcesCardBase/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/ToolCall/ToolCall.test.tsx","../src/ToolCall/ToolCall.tsx","../src/ToolCall/index.ts","../src/ToolResponse/ToolResponse.test.tsx","../src/ToolResponse/ToolResponse.tsx","../src/ToolResponse/index.ts","../src/__mocks__/monaco-editor.ts","../src/__mocks__/rehype-external-links.ts","../src/__mocks__/rehype-highlight.ts","../src/__mocks__/rehype-sanitize.ts","../src/__mocks__/rehype-unwrap-images.tsx","../src/tracking/console_tracking_provider.ts","../src/tracking/index.ts","../src/tracking/posthog_tracking_provider.ts","../src/tracking/segment_tracking_provider.ts","../src/tracking/trackingProviderProxy.ts","../src/tracking/tracking_api.ts","../src/tracking/tracking_registry.ts","../src/tracking/tracking_spi.ts","../src/tracking/umami_tracking_provider.ts"],"version":"5.6.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/chatbot",
|
|
3
|
-
"version": "6.5.0-prerelease.
|
|
3
|
+
"version": "6.5.0-prerelease.25",
|
|
4
4
|
"description": "This library provides React components based on PatternFly 6 that can be used to build chatbots.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx
CHANGED
|
@@ -7,8 +7,10 @@ export const MessageWithFeedbackExample: FunctionComponent = () => {
|
|
|
7
7
|
const [hasCloseButton, setHasCloseButton] = useState(false);
|
|
8
8
|
const [hasTextArea, setHasTextArea] = useState(false);
|
|
9
9
|
const [hasChildren, setHasChildren] = useState(false);
|
|
10
|
+
const [hasPrivacyStatement, setHasPrivacyStatement] = useState(false);
|
|
10
11
|
|
|
11
|
-
const children = <>
|
|
12
|
+
const children = <>This is additional content.</>;
|
|
13
|
+
const privacyStatement = 'Do not share any personal or other sensitive information in your feedback.';
|
|
12
14
|
|
|
13
15
|
return (
|
|
14
16
|
<>
|
|
@@ -33,6 +35,15 @@ export const MessageWithFeedbackExample: FunctionComponent = () => {
|
|
|
33
35
|
label="Has additional content"
|
|
34
36
|
id="has-children"
|
|
35
37
|
/>
|
|
38
|
+
<Checkbox
|
|
39
|
+
isChecked={hasPrivacyStatement}
|
|
40
|
+
onChange={() => {
|
|
41
|
+
setHasPrivacyStatement(!hasPrivacyStatement);
|
|
42
|
+
}}
|
|
43
|
+
name="feedback-card-with-privacy"
|
|
44
|
+
label="Has privacy statement"
|
|
45
|
+
id="has-privacy"
|
|
46
|
+
/>
|
|
36
47
|
</FormGroup>
|
|
37
48
|
</FlexItem>
|
|
38
49
|
<FlexItem>
|
|
@@ -51,6 +62,7 @@ export const MessageWithFeedbackExample: FunctionComponent = () => {
|
|
|
51
62
|
alert(`Selected ${quickResponse} and received the additional feedback: ${additionalFeedback}`),
|
|
52
63
|
hasTextArea,
|
|
53
64
|
children: hasChildren ? children : undefined,
|
|
65
|
+
privacyStatement: hasPrivacyStatement ? privacyStatement : undefined,
|
|
54
66
|
// eslint-disable-next-line no-console
|
|
55
67
|
onClose: () => console.log('closed feedback form'),
|
|
56
68
|
focusOnLoad: false
|
|
@@ -73,6 +85,7 @@ export const MessageWithFeedbackExample: FunctionComponent = () => {
|
|
|
73
85
|
alert(`Selected ${quickResponse} and received the additional feedback: ${additionalFeedback}`),
|
|
74
86
|
hasTextArea,
|
|
75
87
|
children: hasChildren ? children : undefined,
|
|
88
|
+
privacyStatement: hasPrivacyStatement ? privacyStatement : undefined,
|
|
76
89
|
// eslint-disable-next-line no-console
|
|
77
90
|
onClose: () => console.log('closed feedback form'),
|
|
78
91
|
focusOnLoad: false
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import CodeBlockMessage from './CodeBlockMessage';
|
|
5
|
+
|
|
6
|
+
// Mock clipboard API
|
|
7
|
+
Object.assign(navigator, {
|
|
8
|
+
clipboard: {
|
|
9
|
+
writeText: jest.fn()
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('CodeBlockMessage', () => {
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
jest.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should render inline code for single-line content', () => {
|
|
19
|
+
render(<CodeBlockMessage className="language-javascript">const x = 5;</CodeBlockMessage>);
|
|
20
|
+
const code = screen.getByText('const x = 5;');
|
|
21
|
+
expect(code.tagName).toBe('CODE');
|
|
22
|
+
expect(code).toHaveClass('pf-chatbot__message-inline-code');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should render code block for multi-line content', () => {
|
|
26
|
+
const multilineCode = 'const x = 5;\nconst y = 10;';
|
|
27
|
+
const { container } = render(<CodeBlockMessage className="language-javascript">{multilineCode}</CodeBlockMessage>);
|
|
28
|
+
const codeElement = container.querySelector('code');
|
|
29
|
+
expect(codeElement?.textContent).toBe(multilineCode);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should display language label', () => {
|
|
33
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
34
|
+
render(<CodeBlockMessage className="language-javascript">{code}</CodeBlockMessage>);
|
|
35
|
+
expect(screen.getByText('javascript')).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should render copy button', () => {
|
|
39
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
40
|
+
render(<CodeBlockMessage>{code}</CodeBlockMessage>);
|
|
41
|
+
expect(screen.getByRole('button', { name: 'Copy code' })).toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should copy plain string content to clipboard', async () => {
|
|
45
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
46
|
+
render(<CodeBlockMessage>{code}</CodeBlockMessage>);
|
|
47
|
+
|
|
48
|
+
const copyButton = screen.getByRole('button', { name: 'Copy code' });
|
|
49
|
+
await userEvent.click(copyButton);
|
|
50
|
+
|
|
51
|
+
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(code);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should extract text content from React elements when copying', async () => {
|
|
55
|
+
// Simulate what happens with syntax highlighting - children become React elements
|
|
56
|
+
const { container } = render(
|
|
57
|
+
<CodeBlockMessage className="language-javascript">
|
|
58
|
+
<span className="hljs-keyword">const</span> x = 5;{'\n'}
|
|
59
|
+
<span className="hljs-keyword">const</span> y = 10;
|
|
60
|
+
</CodeBlockMessage>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const copyButton = screen.getByRole('button', { name: 'Copy code' });
|
|
64
|
+
await userEvent.click(copyButton);
|
|
65
|
+
|
|
66
|
+
// Should extract actual text content from DOM, not "[object Object]"
|
|
67
|
+
const codeElement = container.querySelector('code');
|
|
68
|
+
const expectedText = codeElement?.textContent || '';
|
|
69
|
+
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(expectedText);
|
|
70
|
+
expect(expectedText).not.toContain('[object Object]');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should show check icon after copying', async () => {
|
|
74
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
75
|
+
render(<CodeBlockMessage>{code}</CodeBlockMessage>);
|
|
76
|
+
|
|
77
|
+
const copyButton = screen.getByRole('button', { name: 'Copy code' });
|
|
78
|
+
await userEvent.click(copyButton);
|
|
79
|
+
|
|
80
|
+
// Check icon should be visible (we can verify by checking if CopyIcon is not present)
|
|
81
|
+
const svgElement = copyButton.querySelector('svg');
|
|
82
|
+
expect(svgElement).toBeInTheDocument();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should render expandable section when isExpandable is true', () => {
|
|
86
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
87
|
+
render(<CodeBlockMessage isExpandable>{code}</CodeBlockMessage>);
|
|
88
|
+
|
|
89
|
+
expect(screen.getByRole('button', { name: 'Show more' })).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should toggle expandable section', async () => {
|
|
93
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
94
|
+
render(<CodeBlockMessage isExpandable>{code}</CodeBlockMessage>);
|
|
95
|
+
|
|
96
|
+
const toggleButton = screen.getByRole('button', { name: 'Show more' });
|
|
97
|
+
await userEvent.click(toggleButton);
|
|
98
|
+
|
|
99
|
+
expect(screen.getByRole('button', { name: 'Show less' })).toBeInTheDocument();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should use custom expanded/collapsed text', () => {
|
|
103
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
104
|
+
render(
|
|
105
|
+
<CodeBlockMessage isExpandable expandedText="Hide" collapsedText="Reveal">
|
|
106
|
+
{code}
|
|
107
|
+
</CodeBlockMessage>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
expect(screen.getByRole('button', { name: 'Reveal' })).toBeInTheDocument();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should pass through expandableSectionProps', () => {
|
|
114
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
115
|
+
const { container } = render(
|
|
116
|
+
<CodeBlockMessage isExpandable expandableSectionProps={{ className: 'custom-expandable-class' }}>
|
|
117
|
+
{code}
|
|
118
|
+
</CodeBlockMessage>
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const expandableSection = container.querySelector('.pf-v6-c-expandable-section.custom-expandable-class');
|
|
122
|
+
expect(expandableSection).toBeInTheDocument();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should render custom actions', () => {
|
|
126
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
127
|
+
const customAction = <button aria-label="Custom action">Custom</button>;
|
|
128
|
+
render(<CodeBlockMessage customActions={customAction}>{code}</CodeBlockMessage>);
|
|
129
|
+
|
|
130
|
+
expect(screen.getByRole('button', { name: 'Custom action' })).toBeInTheDocument();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should apply isPrimary class to inline code', () => {
|
|
134
|
+
render(<CodeBlockMessage isPrimary>const x = 5;</CodeBlockMessage>);
|
|
135
|
+
const code = screen.getByText('const x = 5;');
|
|
136
|
+
expect(code).toHaveClass('pf-m-primary');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should apply shouldRetainStyles class to code block', () => {
|
|
140
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
141
|
+
const { container } = render(<CodeBlockMessage shouldRetainStyles>{code}</CodeBlockMessage>);
|
|
142
|
+
|
|
143
|
+
const codeBlockDiv = container.querySelector('.pf-chatbot__message-code-block');
|
|
144
|
+
expect(codeBlockDiv).toHaveClass('pf-m-markdown');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should use custom aria-label for copy button', () => {
|
|
148
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
149
|
+
render(<CodeBlockMessage aria-label="Copy this code">{code}</CodeBlockMessage>);
|
|
150
|
+
|
|
151
|
+
expect(screen.getByRole('button', { name: 'Copy this code' })).toBeInTheDocument();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should prioritize data-expanded-text over expandedText prop', () => {
|
|
155
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
156
|
+
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn());
|
|
157
|
+
|
|
158
|
+
render(
|
|
159
|
+
<CodeBlockMessage isExpandable expandedText="Custom Expanded" data-expanded-text="Data Expanded">
|
|
160
|
+
{code}
|
|
161
|
+
</CodeBlockMessage>
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
|
165
|
+
'Message:',
|
|
166
|
+
expect.stringContaining('data-expanded-text or data-collapsed-text will override')
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
consoleErrorSpy.mockRestore();
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -92,13 +92,22 @@ const CodeBlockMessage = ({
|
|
|
92
92
|
);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
const onToggle = (isExpanded) => {
|
|
95
|
+
const onToggle = (isExpanded: boolean) => {
|
|
96
96
|
setIsExpanded(isExpanded);
|
|
97
97
|
};
|
|
98
98
|
|
|
99
99
|
// Handle clicking copy button
|
|
100
|
-
const handleCopy = useCallback((
|
|
101
|
-
|
|
100
|
+
const handleCopy = useCallback((_event: React.MouseEvent, text: React.ReactNode) => {
|
|
101
|
+
let textToCopy = '';
|
|
102
|
+
if (typeof text === 'string') {
|
|
103
|
+
textToCopy = text;
|
|
104
|
+
} else {
|
|
105
|
+
if (codeBlockRef.current) {
|
|
106
|
+
const codeElement = codeBlockRef.current.querySelector('code');
|
|
107
|
+
textToCopy = codeElement?.textContent || '';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
navigator.clipboard.writeText(textToCopy);
|
|
102
111
|
setCopied(true);
|
|
103
112
|
}, []);
|
|
104
113
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
.pf-chatbot__message-quick-response {
|
|
2
2
|
.pf-v6-c-label {
|
|
3
|
-
|
|
3
|
+
&:not(.pf-m-compact) {
|
|
4
|
+
--pf-v6-c-label--FontSize: var(--pf-t--global--font--size--md);
|
|
5
|
+
}
|
|
4
6
|
|
|
5
7
|
@media screen and (min-width: 401px) and (max-width: 600px) {
|
|
6
8
|
--pf-v6-c-label__text--MaxWidth: 20ch;
|
|
@@ -36,6 +36,11 @@
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// feedback card
|
|
39
|
+
.pf-chatbot__feedback-card-complete-header {
|
|
40
|
+
.pf-v6-c-card__actions {
|
|
41
|
+
--pf-v6-c-card__actions--MarginBlockEnd: calc(var(--pf-t--global--spacer--xl) * -1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
39
44
|
.pf-chatbot__feedback-card-title {
|
|
40
45
|
font-family: var(--pf-t--global--font--family--heading);
|
|
41
46
|
font-size: var(--pf-t--global--font--size--md);
|
|
@@ -51,10 +56,32 @@
|
|
|
51
56
|
font-weight: initial;
|
|
52
57
|
}
|
|
53
58
|
|
|
59
|
+
// Privacy statement
|
|
60
|
+
.pf-chatbot__feedback-card-privacy {
|
|
61
|
+
font-size: var(--pf-t--global--font--size--body--sm);
|
|
62
|
+
font-weight: var(--pf-t--global--font--weight--body--default);
|
|
63
|
+
line-height: var(--pf-t--global--font--line-height--body);
|
|
64
|
+
color: var(--pf-t--global--text--color--subtle);
|
|
65
|
+
}
|
|
66
|
+
|
|
54
67
|
// Compact styles
|
|
55
68
|
.pf-v6-c-card.pf-m-compact.pf-chatbot__feedback-card {
|
|
69
|
+
--pf-v6-c-card--first-child--PaddingBlockStart: var(--pf-t--global--spacer--md);
|
|
70
|
+
--pf-v6-c-card--child--PaddingInlineEnd: var(--pf-t--global--spacer--md);
|
|
71
|
+
--pf-v6-c-card--child--PaddingInlineStart: var(--pf-t--global--spacer--md);
|
|
72
|
+
--pf-v6-c-card--last-child--PaddingBlockEnd: var(--pf-t--global--spacer--md);
|
|
73
|
+
--pf-v6-c-card__title--not--last-child--PaddingBlockEnd: var(--pf-t--global--spacer--md);
|
|
74
|
+
|
|
56
75
|
.pf-chatbot__feedback-card-form.pf-m-compact {
|
|
57
|
-
--pf-v6-c-form--GridGap: var(--pf-t--global--spacer--
|
|
76
|
+
--pf-v6-c-form--GridGap: var(--pf-t--global--spacer--sm);
|
|
77
|
+
|
|
78
|
+
.pf-v6-c-form__group.pf-m-action {
|
|
79
|
+
margin-block-start: var(--pf-t--global--spacer--sm);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.pf-v6-c-form-control {
|
|
83
|
+
font-size: var(--pf-t--global--font--size--body--sm);
|
|
84
|
+
}
|
|
58
85
|
}
|
|
59
86
|
}
|
|
60
87
|
|
|
@@ -74,6 +74,8 @@ export interface UserFeedbackProps extends Omit<CardProps, 'onSubmit'>, OUIAProp
|
|
|
74
74
|
textAreaProps?: TextAreaProps;
|
|
75
75
|
/** Additional props passed to action group */
|
|
76
76
|
actionGroupProps?: ActionGroupProps;
|
|
77
|
+
/** Optional privacy statement text displayed under text area */
|
|
78
|
+
privacyStatement?: string;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
@@ -102,6 +104,7 @@ const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
|
102
104
|
textAreaProps,
|
|
103
105
|
actionGroupProps,
|
|
104
106
|
submitButtonProps,
|
|
107
|
+
privacyStatement,
|
|
105
108
|
...props
|
|
106
109
|
}: UserFeedbackProps) => {
|
|
107
110
|
const [selectedResponse, setSelectedResponse] = useState<string>();
|
|
@@ -139,21 +142,28 @@ const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
|
139
142
|
/>
|
|
140
143
|
)}
|
|
141
144
|
{hasTextArea && (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
<>
|
|
146
|
+
<TextArea
|
|
147
|
+
value={value}
|
|
148
|
+
onChange={(_event, value) => {
|
|
149
|
+
setValue(value);
|
|
150
|
+
onTextAreaChange && onTextAreaChange(_event, value);
|
|
151
|
+
}}
|
|
152
|
+
placeholder={textAreaPlaceholder}
|
|
153
|
+
aria-label={textAreaAriaLabel}
|
|
154
|
+
resizeOrientation="vertical"
|
|
155
|
+
{...textAreaProps}
|
|
156
|
+
/>
|
|
157
|
+
</>
|
|
153
158
|
)}
|
|
159
|
+
{privacyStatement && <div className="pf-chatbot__feedback-card-privacy">{privacyStatement}</div>}
|
|
154
160
|
{children}
|
|
155
161
|
<ActionGroup {...actionGroupProps}>
|
|
156
|
-
<Button
|
|
162
|
+
<Button
|
|
163
|
+
onClick={() => onSubmit(selectedResponse, value)}
|
|
164
|
+
size={isCompact ? 'sm' : undefined}
|
|
165
|
+
{...submitButtonProps}
|
|
166
|
+
>
|
|
157
167
|
{submitWord}
|
|
158
168
|
</Button>
|
|
159
169
|
</ActionGroup>
|
|
@@ -147,13 +147,22 @@
|
|
|
147
147
|
.pf-chatbot__message-textarea {
|
|
148
148
|
font-size: var(--pf-t--global--font--size--sm) !important;
|
|
149
149
|
}
|
|
150
|
+
}
|
|
150
151
|
|
|
152
|
+
.pf-m-compact {
|
|
151
153
|
.pf-chatbot__message-bar-actions {
|
|
152
|
-
padding-block-start: var(--pf-t--global--spacer--
|
|
153
|
-
padding-block-end: var(--pf-t--global--spacer--
|
|
154
|
+
padding-block-start: var(--pf-t--global--spacer--sm);
|
|
155
|
+
padding-block-end: var(--pf-t--global--spacer--sm);
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
|
|
159
|
+
// ============================================================================
|
|
160
|
+
// Multiline textarea styles (2+ lines)
|
|
161
|
+
// ============================================================================
|
|
162
|
+
.pf-chatbot__message-bar.pf-m-multiline {
|
|
163
|
+
border-radius: calc(var(--pf-t--global--border--radius--small) * 2);
|
|
164
|
+
}
|
|
165
|
+
|
|
157
166
|
// ============================================================================
|
|
158
167
|
// High contrast styles
|
|
159
168
|
// ============================================================================
|