@patternfly/chatbot 6.4.0-prerelease.2 → 6.4.0-prerelease.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Chatbot/Chatbot.js +1 -7
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +15 -9
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +40 -2
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
- package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/index.js +1 -0
- package/dist/cjs/DeepThinking/DeepThinking.d.ts +18 -0
- package/dist/cjs/DeepThinking/DeepThinking.js +18 -0
- package/dist/cjs/DeepThinking/DeepThinking.test.d.ts +1 -0
- package/dist/cjs/DeepThinking/DeepThinking.test.js +48 -0
- package/dist/cjs/DeepThinking/index.d.ts +2 -0
- package/dist/cjs/DeepThinking/index.js +23 -0
- package/dist/cjs/FileDetails/FileDetails.d.ts +22 -3
- package/dist/cjs/FileDetails/FileDetails.js +27 -912
- package/dist/cjs/FileDetails/FileDetails.test.js +16 -0
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +8 -2
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.js +14 -2
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.test.js +19 -1
- package/dist/cjs/FilePreview/FilePreview.d.ts +26 -0
- package/dist/cjs/FilePreview/FilePreview.js +26 -0
- package/dist/cjs/FilePreview/FilePreview.test.d.ts +1 -0
- package/dist/cjs/FilePreview/FilePreview.test.js +97 -0
- package/dist/cjs/FilePreview/index.d.ts +2 -0
- package/dist/cjs/FilePreview/index.js +23 -0
- package/dist/cjs/ImagePreview/ImagePreview.d.ts +53 -0
- package/dist/cjs/ImagePreview/ImagePreview.js +47 -0
- package/dist/cjs/ImagePreview/ImagePreview.test.d.ts +1 -0
- package/dist/cjs/ImagePreview/ImagePreview.test.js +225 -0
- package/dist/cjs/ImagePreview/index.d.ts +2 -0
- package/dist/cjs/ImagePreview/index.js +23 -0
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +3 -3
- package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +2 -1
- package/dist/cjs/Message/LinkMessage/LinkMessage.js +7 -3
- package/dist/cjs/Message/ListMessage/ListItemMessage.d.ts +1 -1
- package/dist/cjs/Message/ListMessage/ListItemMessage.js +16 -1
- package/dist/cjs/Message/Message.d.ts +15 -0
- package/dist/cjs/Message/Message.js +129 -32
- package/dist/cjs/Message/Message.test.js +71 -0
- package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
- package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.js +5 -0
- package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +15 -1
- package/dist/cjs/Message/UserFeedback/UserFeedback.js +4 -4
- package/dist/cjs/Message/UserFeedback/UserFeedback.test.js +44 -0
- package/dist/cjs/MessageBar/MessageBar.js +19 -4
- package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
- package/dist/cjs/MessageBox/JumpButton.js +1 -1
- package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
- package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
- package/dist/cjs/MessageBox/MessageBox.js +2 -2
- package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
- package/dist/cjs/SourcesCard/SourcesCard.d.ts +13 -1
- package/dist/cjs/SourcesCard/SourcesCard.js +6 -6
- package/dist/cjs/SourcesCard/SourcesCard.test.js +49 -0
- package/dist/cjs/ToolResponse/ToolResponse.d.ts +30 -0
- package/dist/cjs/ToolResponse/ToolResponse.js +18 -0
- package/dist/cjs/ToolResponse/ToolResponse.test.d.ts +1 -0
- package/dist/cjs/ToolResponse/ToolResponse.test.js +60 -0
- package/dist/cjs/ToolResponse/index.d.ts +2 -0
- package/dist/cjs/ToolResponse/index.js +23 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.js +13 -1
- package/dist/css/main.css +339 -27
- package/dist/css/main.css.map +1 -1
- package/dist/dynamic/DeepThinking/package.json +1 -0
- package/dist/dynamic/FilePreview/package.json +1 -0
- package/dist/dynamic/ImagePreview/package.json +1 -0
- package/dist/dynamic/ToolResponse/package.json +1 -0
- package/dist/esm/Chatbot/Chatbot.js +1 -7
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +17 -11
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +41 -3
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
- package/dist/esm/ChatbotHeader/index.d.ts +1 -0
- package/dist/esm/ChatbotHeader/index.js +1 -0
- package/dist/esm/DeepThinking/DeepThinking.d.ts +18 -0
- package/dist/esm/DeepThinking/DeepThinking.js +14 -0
- package/dist/esm/DeepThinking/DeepThinking.test.d.ts +1 -0
- package/dist/esm/DeepThinking/DeepThinking.test.js +43 -0
- package/dist/esm/DeepThinking/index.d.ts +2 -0
- package/dist/esm/DeepThinking/index.js +2 -0
- package/dist/esm/FileDetails/FileDetails.d.ts +22 -3
- package/dist/esm/FileDetails/FileDetails.js +27 -912
- package/dist/esm/FileDetails/FileDetails.test.js +16 -0
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +8 -2
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.js +14 -2
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.test.js +19 -1
- package/dist/esm/FilePreview/FilePreview.d.ts +26 -0
- package/dist/esm/FilePreview/FilePreview.js +21 -0
- package/dist/esm/FilePreview/FilePreview.test.d.ts +1 -0
- package/dist/esm/FilePreview/FilePreview.test.js +92 -0
- package/dist/esm/FilePreview/index.d.ts +2 -0
- package/dist/esm/FilePreview/index.js +2 -0
- package/dist/esm/ImagePreview/ImagePreview.d.ts +53 -0
- package/dist/esm/ImagePreview/ImagePreview.js +42 -0
- package/dist/esm/ImagePreview/ImagePreview.test.d.ts +1 -0
- package/dist/esm/ImagePreview/ImagePreview.test.js +220 -0
- package/dist/esm/ImagePreview/index.d.ts +2 -0
- package/dist/esm/ImagePreview/index.js +2 -0
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +5 -5
- package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +2 -1
- package/dist/esm/Message/LinkMessage/LinkMessage.js +7 -3
- package/dist/esm/Message/ListMessage/ListItemMessage.d.ts +1 -1
- package/dist/esm/Message/ListMessage/ListItemMessage.js +16 -1
- package/dist/esm/Message/Message.d.ts +15 -0
- package/dist/esm/Message/Message.js +129 -32
- package/dist/esm/Message/Message.test.js +71 -0
- package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
- package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.js +3 -0
- package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +15 -1
- package/dist/esm/Message/UserFeedback/UserFeedback.js +4 -4
- package/dist/esm/Message/UserFeedback/UserFeedback.test.js +45 -1
- package/dist/esm/MessageBar/MessageBar.js +19 -4
- package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
- package/dist/esm/MessageBox/JumpButton.js +1 -1
- package/dist/esm/MessageBox/JumpButton.test.js +4 -4
- package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
- package/dist/esm/MessageBox/MessageBox.js +2 -2
- package/dist/esm/MessageBox/MessageBox.test.js +2 -2
- package/dist/esm/SourcesCard/SourcesCard.d.ts +13 -1
- package/dist/esm/SourcesCard/SourcesCard.js +6 -6
- package/dist/esm/SourcesCard/SourcesCard.test.js +50 -1
- package/dist/esm/ToolResponse/ToolResponse.d.ts +30 -0
- package/dist/esm/ToolResponse/ToolResponse.js +14 -0
- package/dist/esm/ToolResponse/ToolResponse.test.d.ts +1 -0
- package/dist/esm/ToolResponse/ToolResponse.test.js +55 -0
- package/dist/esm/ToolResponse/index.d.ts +2 -0
- package/dist/esm/ToolResponse/index.js +2 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +8 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/AttachmentEdit.tsx +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +101 -3
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/FilePreview.tsx +33 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/ImagePreview.tsx +53 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +17 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +111 -85
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +70 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +135 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +38 -4
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/PreviewAttachment.tsx +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +107 -2
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +616 -3
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/file-preview.svg +9 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +36 -5
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +12 -2
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +22 -3
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +1 -1
- package/patternfly-docs/patternfly-docs.config.js +1 -1
- package/src/Chatbot/Chatbot.scss +9 -2
- package/src/Chatbot/Chatbot.tsx +18 -31
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +16 -10
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +132 -3
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +80 -33
- package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
- package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
- package/src/ChatbotHeader/index.ts +1 -0
- package/src/ChatbotModal/ChatbotModal.scss +1 -1
- package/src/DeepThinking/DeepThinking.scss +24 -0
- package/src/DeepThinking/DeepThinking.test.tsx +61 -0
- package/src/DeepThinking/DeepThinking.tsx +68 -0
- package/src/DeepThinking/index.ts +3 -0
- package/src/FileDetails/FileDetails.scss +10 -0
- package/src/FileDetails/FileDetails.test.tsx +16 -0
- package/src/FileDetails/FileDetails.tsx +89 -32
- package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +20 -14
- package/src/FileDetailsLabel/FileDetailsLabel.test.tsx +21 -1
- package/src/FileDetailsLabel/FileDetailsLabel.tsx +16 -3
- package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +20 -14
- package/src/FilePreview/FilePreview.scss +22 -0
- package/src/FilePreview/FilePreview.test.tsx +112 -0
- package/src/FilePreview/FilePreview.tsx +58 -0
- package/src/FilePreview/index.ts +3 -0
- package/src/ImagePreview/ImagePreview.scss +61 -0
- package/src/ImagePreview/ImagePreview.test.tsx +253 -0
- package/src/ImagePreview/ImagePreview.tsx +200 -0
- package/src/ImagePreview/index.ts +3 -0
- package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +2 -1
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +6 -5
- package/src/Message/LinkMessage/LinkMessage.tsx +6 -2
- package/src/Message/ListMessage/ListItemMessage.tsx +5 -1
- package/src/Message/ListMessage/ListMessage.scss +17 -0
- package/src/Message/Message.scss +44 -0
- package/src/Message/Message.test.tsx +90 -0
- package/src/Message/Message.tsx +171 -46
- package/src/Message/SuperscriptMessage/SuperscriptMessage.scss +8 -0
- package/src/Message/SuperscriptMessage/SuperscriptMessage.tsx +13 -0
- package/src/Message/TextMessage/TextMessage.scss +46 -5
- package/src/Message/UserFeedback/UserFeedback.test.tsx +107 -0
- package/src/Message/UserFeedback/UserFeedback.tsx +41 -6
- package/src/MessageBar/MessageBar.tsx +23 -3
- package/src/MessageBox/JumpButton.test.tsx +4 -4
- package/src/MessageBox/JumpButton.tsx +20 -4
- package/src/MessageBox/MessageBox.scss +0 -12
- package/src/MessageBox/MessageBox.test.tsx +2 -2
- package/src/MessageBox/MessageBox.tsx +23 -2
- package/src/SourcesCard/SourcesCard.scss +17 -0
- package/src/SourcesCard/SourcesCard.test.tsx +93 -0
- package/src/SourcesCard/SourcesCard.tsx +116 -80
- package/src/ToolResponse/ToolResponse.scss +36 -0
- package/src/ToolResponse/ToolResponse.test.tsx +78 -0
- package/src/ToolResponse/ToolResponse.tsx +95 -0
- package/src/ToolResponse/index.ts +3 -0
- package/src/index.ts +12 -0
- package/src/main.scss +16 -0
|
@@ -8,15 +8,21 @@ import { useState, useRef, useEffect } from 'react';
|
|
|
8
8
|
// Import PatternFly components
|
|
9
9
|
import {
|
|
10
10
|
ActionGroup,
|
|
11
|
+
ActionGroupProps,
|
|
11
12
|
Button,
|
|
13
|
+
ButtonProps,
|
|
12
14
|
Card,
|
|
13
15
|
CardBody,
|
|
16
|
+
CardBodyProps,
|
|
14
17
|
CardHeader,
|
|
18
|
+
CardHeaderProps,
|
|
15
19
|
CardProps,
|
|
16
20
|
Form,
|
|
21
|
+
FormProps,
|
|
17
22
|
LabelGroupProps,
|
|
18
23
|
OUIAProps,
|
|
19
|
-
TextArea
|
|
24
|
+
TextArea,
|
|
25
|
+
TextAreaProps
|
|
20
26
|
} from '@patternfly/react-core';
|
|
21
27
|
import QuickResponse from '../QuickResponse/QuickResponse';
|
|
22
28
|
import CloseButton from './CloseButton';
|
|
@@ -54,6 +60,20 @@ export interface UserFeedbackProps extends Omit<CardProps, 'onSubmit'>, OUIAProp
|
|
|
54
60
|
focusOnLoad?: boolean;
|
|
55
61
|
/** Timestamp passed in by Message for more context in aria announcements */
|
|
56
62
|
timestamp?: string;
|
|
63
|
+
/** Additional props passed to submit button */
|
|
64
|
+
submitButtonProps?: ButtonProps;
|
|
65
|
+
/** Additional props passed to card header */
|
|
66
|
+
cardHeaderProps?: CardHeaderProps;
|
|
67
|
+
/** Additional props passed to card body */
|
|
68
|
+
cardBodyProps?: CardBodyProps;
|
|
69
|
+
/** Additional props passed to title heading */
|
|
70
|
+
headingLevelProps?: React.HTMLAttributes<HTMLHeadingElement>;
|
|
71
|
+
/** Additional props passed to form */
|
|
72
|
+
formProps?: FormProps;
|
|
73
|
+
/** Additional props passed to text area */
|
|
74
|
+
textAreaProps?: TextAreaProps;
|
|
75
|
+
/** Additional props passed to action group */
|
|
76
|
+
actionGroupProps?: ActionGroupProps;
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
@@ -74,6 +94,14 @@ const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
|
74
94
|
headingLevel: HeadingLevel = 'h1',
|
|
75
95
|
focusOnLoad = true,
|
|
76
96
|
isCompact,
|
|
97
|
+
children,
|
|
98
|
+
cardHeaderProps,
|
|
99
|
+
cardBodyProps,
|
|
100
|
+
headingLevelProps,
|
|
101
|
+
formProps,
|
|
102
|
+
textAreaProps,
|
|
103
|
+
actionGroupProps,
|
|
104
|
+
submitButtonProps,
|
|
77
105
|
...props
|
|
78
106
|
}: UserFeedbackProps) => {
|
|
79
107
|
const [selectedResponse, setSelectedResponse] = useState<string>();
|
|
@@ -94,11 +122,14 @@ const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
|
94
122
|
actions={{
|
|
95
123
|
actions: <CloseButton onClose={onClose} ariaLabel={closeButtonAriaLabel} />
|
|
96
124
|
}}
|
|
125
|
+
{...cardHeaderProps}
|
|
97
126
|
>
|
|
98
|
-
<HeadingLevel className="pf-chatbot__feedback-card-title"
|
|
127
|
+
<HeadingLevel className="pf-chatbot__feedback-card-title" {...headingLevelProps}>
|
|
128
|
+
{title}
|
|
129
|
+
</HeadingLevel>
|
|
99
130
|
</CardHeader>
|
|
100
|
-
<CardBody>
|
|
101
|
-
<Form className={`pf-chatbot__feedback-card-form ${isCompact ? 'pf-m-compact' : ''}`}>
|
|
131
|
+
<CardBody {...cardBodyProps}>
|
|
132
|
+
<Form className={`pf-chatbot__feedback-card-form ${isCompact ? 'pf-m-compact' : ''}`} {...formProps}>
|
|
102
133
|
{quickResponses && (
|
|
103
134
|
<QuickResponse
|
|
104
135
|
quickResponses={quickResponses}
|
|
@@ -117,10 +148,14 @@ const UserFeedback: FunctionComponent<UserFeedbackProps> = ({
|
|
|
117
148
|
placeholder={textAreaPlaceholder}
|
|
118
149
|
aria-label={textAreaAriaLabel}
|
|
119
150
|
resizeOrientation="vertical"
|
|
151
|
+
{...textAreaProps}
|
|
120
152
|
/>
|
|
121
153
|
)}
|
|
122
|
-
|
|
123
|
-
|
|
154
|
+
{children}
|
|
155
|
+
<ActionGroup {...actionGroupProps}>
|
|
156
|
+
<Button onClick={() => onSubmit(selectedResponse, value)} {...submitButtonProps}>
|
|
157
|
+
{submitWord}
|
|
158
|
+
</Button>
|
|
124
159
|
</ActionGroup>
|
|
125
160
|
</Form>
|
|
126
161
|
</CardBody>
|
|
@@ -141,6 +141,7 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
|
|
|
141
141
|
const [message, setMessage] = useState<string | number>(value ?? '');
|
|
142
142
|
const [isListeningMessage, setIsListeningMessage] = useState<boolean>(false);
|
|
143
143
|
const [hasSentMessage, setHasSentMessage] = useState(false);
|
|
144
|
+
const [isComposing, setIsComposing] = useState(false);
|
|
144
145
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
145
146
|
const textareaRef = (innerRef as React.RefObject<HTMLTextAreaElement>) ?? inputRef;
|
|
146
147
|
const attachButtonRef = useRef<HTMLButtonElement>(null);
|
|
@@ -285,21 +286,38 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
|
|
|
285
286
|
|
|
286
287
|
const handleKeyDown = useCallback(
|
|
287
288
|
(event: ReactKeyboardEvent) => {
|
|
288
|
-
|
|
289
|
+
// Japanese and other languages may use IME for character input.
|
|
290
|
+
// In these cases, enter is used to select the final input, so we need to check for composition end instead.
|
|
291
|
+
// See more info at https://www.stum.de/2016/06/24/handling-ime-events-in-javascript/
|
|
292
|
+
// Chrome, Edge, and Firefox seem to work well with just the compose event.
|
|
293
|
+
// Safari is a little bit special. We need to handle 229 as well in this case.
|
|
294
|
+
const nativeEvent = event.nativeEvent as KeyboardEvent;
|
|
295
|
+
const isCompositionKey = nativeEvent.which === 229;
|
|
296
|
+
const isCurrentlyComposing = isComposing || isCompositionKey;
|
|
297
|
+
|
|
298
|
+
if (event.key === 'Enter' && !isCurrentlyComposing && !event.shiftKey) {
|
|
289
299
|
event.preventDefault();
|
|
290
300
|
if (!isSendButtonDisabled && !hasStopButton) {
|
|
291
301
|
handleSend(message);
|
|
292
302
|
}
|
|
293
303
|
}
|
|
294
|
-
if (event.key === 'Enter' && event.shiftKey) {
|
|
304
|
+
if (event.key === 'Enter' && !isCurrentlyComposing && event.shiftKey) {
|
|
295
305
|
if (textareaRef.current) {
|
|
296
306
|
handleNewLine(textareaRef.current);
|
|
297
307
|
}
|
|
298
308
|
}
|
|
299
309
|
},
|
|
300
|
-
[isSendButtonDisabled, hasStopButton, handleSend, message]
|
|
310
|
+
[isSendButtonDisabled, hasStopButton, handleSend, message, isComposing]
|
|
301
311
|
);
|
|
302
312
|
|
|
313
|
+
const handleCompositionStart = useCallback(() => {
|
|
314
|
+
setIsComposing(true);
|
|
315
|
+
}, []);
|
|
316
|
+
|
|
317
|
+
const handleCompositionEnd = useCallback(() => {
|
|
318
|
+
setIsComposing(false);
|
|
319
|
+
}, []);
|
|
320
|
+
|
|
303
321
|
const handleAttachMenuToggle = () => {
|
|
304
322
|
attachMenuProps?.setIsAttachMenuOpen && attachMenuProps?.setIsAttachMenuOpen(!attachMenuProps?.isAttachMenuOpen);
|
|
305
323
|
attachMenuProps?.onAttachMenuToggleClick();
|
|
@@ -402,6 +420,8 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
|
|
|
402
420
|
placeholder={isListeningMessage ? listeningText : placeholder}
|
|
403
421
|
ref={textareaRef}
|
|
404
422
|
onKeyDown={handleKeyDown}
|
|
423
|
+
onCompositionStart={handleCompositionStart}
|
|
424
|
+
onCompositionEnd={handleCompositionEnd}
|
|
405
425
|
{...props}
|
|
406
426
|
/>
|
|
407
427
|
</div>
|
|
@@ -6,20 +6,20 @@ import userEvent from '@testing-library/user-event';
|
|
|
6
6
|
describe('JumpButton', () => {
|
|
7
7
|
it('should render top button correctly', () => {
|
|
8
8
|
render(<JumpButton position="top" onClick={jest.fn()} />);
|
|
9
|
-
expect(screen.getByRole('button', { name: /
|
|
9
|
+
expect(screen.getByRole('button', { name: /Back to top/i })).toBeTruthy();
|
|
10
10
|
});
|
|
11
11
|
it('should render bottom button correctly', () => {
|
|
12
12
|
render(<JumpButton position="bottom" onClick={jest.fn()} />);
|
|
13
|
-
expect(screen.getByRole('button', { name: /
|
|
13
|
+
expect(screen.getByRole('button', { name: /Back to bottom/i })).toBeTruthy();
|
|
14
14
|
});
|
|
15
15
|
it('should call onClick appropriately', async () => {
|
|
16
16
|
const spy = jest.fn();
|
|
17
17
|
render(<JumpButton position="bottom" onClick={spy} />);
|
|
18
|
-
await userEvent.click(screen.getByRole('button', { name: /
|
|
18
|
+
await userEvent.click(screen.getByRole('button', { name: /Back to bottom/i }));
|
|
19
19
|
expect(spy).toHaveBeenCalledTimes(1);
|
|
20
20
|
});
|
|
21
21
|
it('should be hidden if isHidden prop is used', async () => {
|
|
22
22
|
render(<JumpButton position="bottom" onClick={jest.fn()} isHidden />);
|
|
23
|
-
expect(screen.queryByRole('button', { name: /
|
|
23
|
+
expect(screen.queryByRole('button', { name: /Back to bottom/i })).toBeFalsy();
|
|
24
24
|
});
|
|
25
25
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { FunctionComponent } from 'react';
|
|
5
5
|
|
|
6
6
|
// Import PatternFly components
|
|
7
|
-
import { Button, Tooltip, Icon } from '@patternfly/react-core';
|
|
7
|
+
import { Button, Tooltip, Icon, TooltipProps, ButtonProps } from '@patternfly/react-core';
|
|
8
8
|
|
|
9
9
|
import { ArrowUpIcon } from '@patternfly/react-icons/dist/esm/icons/arrow-up-icon';
|
|
10
10
|
import { ArrowDownIcon } from '@patternfly/react-icons/dist/esm/icons/arrow-down-icon';
|
|
@@ -16,16 +16,32 @@ export interface JumpButtonProps {
|
|
|
16
16
|
onClick: () => void;
|
|
17
17
|
/** Flag to change the visibilty of the button */
|
|
18
18
|
isHidden?: boolean;
|
|
19
|
+
/** Additional props passed to jump buttons */
|
|
20
|
+
jumpButtonProps?: ButtonProps;
|
|
21
|
+
/** Additional props passed to tooltip */
|
|
22
|
+
jumpButtonTooltipProps?: TooltipProps;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
const JumpButton: FunctionComponent<JumpButtonProps> = ({
|
|
25
|
+
const JumpButton: FunctionComponent<JumpButtonProps> = ({
|
|
26
|
+
position,
|
|
27
|
+
isHidden,
|
|
28
|
+
onClick,
|
|
29
|
+
jumpButtonProps,
|
|
30
|
+
jumpButtonTooltipProps
|
|
31
|
+
}: JumpButtonProps) =>
|
|
22
32
|
isHidden ? null : (
|
|
23
|
-
<Tooltip
|
|
33
|
+
<Tooltip
|
|
34
|
+
id={`pf-chatbot__tooltip--jump-${position}`}
|
|
35
|
+
content={`Back to ${position}`}
|
|
36
|
+
position="top"
|
|
37
|
+
{...jumpButtonTooltipProps}
|
|
38
|
+
>
|
|
24
39
|
<Button
|
|
25
40
|
variant="plain"
|
|
26
41
|
className={`pf-chatbot__jump pf-chatbot__jump--${position}`}
|
|
27
|
-
aria-label={`
|
|
42
|
+
aria-label={`Back to ${position}`}
|
|
28
43
|
onClick={onClick}
|
|
44
|
+
{...jumpButtonProps}
|
|
29
45
|
>
|
|
30
46
|
<Icon iconSize="lg" isInline>
|
|
31
47
|
{position === 'top' ? <ArrowUpIcon /> : <ArrowDownIcon />}
|
|
@@ -23,18 +23,6 @@
|
|
|
23
23
|
margin-top: auto !important;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// hide from view but not assistive technologies
|
|
27
|
-
// https://css-tricks.com/inclusively-hidden/
|
|
28
|
-
.pf-chatbot__messagebox-announcement {
|
|
29
|
-
clip: rect(0 0 0 0);
|
|
30
|
-
clip-path: inset(50%);
|
|
31
|
-
height: 1px;
|
|
32
|
-
overflow: hidden;
|
|
33
|
-
position: absolute;
|
|
34
|
-
white-space: nowrap;
|
|
35
|
-
width: 1px;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
26
|
@media screen and (min-width: 64rem) {
|
|
39
27
|
.pf-chatbot--embedded,
|
|
40
28
|
.pf-chatbot--drawer,
|
|
@@ -61,7 +61,7 @@ describe('MessageBox', () => {
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
await waitFor(() => {
|
|
64
|
-
userEvent.click(screen.getByRole('button', { name: /
|
|
64
|
+
userEvent.click(screen.getByRole('button', { name: /Back to bottom/i }));
|
|
65
65
|
expect(spy).toHaveBeenCalled();
|
|
66
66
|
});
|
|
67
67
|
});
|
|
@@ -85,7 +85,7 @@ describe('MessageBox', () => {
|
|
|
85
85
|
region.dispatchEvent(new Event('scroll'));
|
|
86
86
|
});
|
|
87
87
|
await waitFor(() => {
|
|
88
|
-
userEvent.click(screen.getByRole('button', { name: /
|
|
88
|
+
userEvent.click(screen.getByRole('button', { name: /Back to top/i }));
|
|
89
89
|
expect(spy).toHaveBeenCalled();
|
|
90
90
|
});
|
|
91
91
|
});
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
WheelEventHandler
|
|
19
19
|
} from 'react';
|
|
20
20
|
import JumpButton from './JumpButton';
|
|
21
|
+
import { ButtonProps, TooltipProps } from '@patternfly/react-core';
|
|
21
22
|
|
|
22
23
|
export interface MessageBoxProps extends HTMLProps<HTMLDivElement> {
|
|
23
24
|
/** Content that can be announced, such as a new message, for screen readers */
|
|
@@ -38,6 +39,14 @@ export interface MessageBoxProps extends HTMLProps<HTMLDivElement> {
|
|
|
38
39
|
onScrollToBottomClick?: () => void;
|
|
39
40
|
/** Flag to enable automatic scrolling when new messages are added */
|
|
40
41
|
enableSmartScroll?: boolean;
|
|
42
|
+
/** Props passed to top jump button */
|
|
43
|
+
jumpButtonTopProps?: ButtonProps;
|
|
44
|
+
/** Props passed to bottom jump button */
|
|
45
|
+
jumpButtonBottomProps?: ButtonProps;
|
|
46
|
+
/** Props passed to top jump button tooltip */
|
|
47
|
+
jumpButtonTopTooltipProps?: TooltipProps;
|
|
48
|
+
/** Props passed to top jump button tooltip */
|
|
49
|
+
jumpButtonBottomTooltipProps?: TooltipProps;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
52
|
export interface MessageBoxHandle extends HTMLDivElement {
|
|
@@ -60,6 +69,10 @@ export const MessageBox = forwardRef(
|
|
|
60
69
|
onScrollToTopClick,
|
|
61
70
|
onScrollToBottomClick,
|
|
62
71
|
enableSmartScroll = false,
|
|
72
|
+
jumpButtonTopProps,
|
|
73
|
+
jumpButtonBottomProps,
|
|
74
|
+
jumpButtonBottomTooltipProps,
|
|
75
|
+
jumpButtonTopTooltipProps,
|
|
63
76
|
...props
|
|
64
77
|
}: MessageBoxProps,
|
|
65
78
|
ref: ForwardedRef<MessageBoxHandle | null>
|
|
@@ -305,7 +318,13 @@ export const MessageBox = forwardRef(
|
|
|
305
318
|
|
|
306
319
|
return (
|
|
307
320
|
<>
|
|
308
|
-
<JumpButton
|
|
321
|
+
<JumpButton
|
|
322
|
+
position="top"
|
|
323
|
+
isHidden={isOverflowing && atTop}
|
|
324
|
+
onClick={scrollToTop}
|
|
325
|
+
jumpButtonProps={jumpButtonTopProps}
|
|
326
|
+
jumpButtonTooltipProps={jumpButtonTopTooltipProps}
|
|
327
|
+
/>
|
|
309
328
|
<div
|
|
310
329
|
role="region"
|
|
311
330
|
tabIndex={0}
|
|
@@ -316,7 +335,7 @@ export const MessageBox = forwardRef(
|
|
|
316
335
|
{...(enableSmartScroll ? { ...smartScrollHandlers } : {})}
|
|
317
336
|
>
|
|
318
337
|
{children}
|
|
319
|
-
<div className="pf-chatbot__messagebox-announcement" aria-live="polite">
|
|
338
|
+
<div className="pf-chatbot__messagebox-announcement pf-chatbot-m-hidden" aria-live="polite">
|
|
320
339
|
{announcement}
|
|
321
340
|
</div>
|
|
322
341
|
</div>
|
|
@@ -324,6 +343,8 @@ export const MessageBox = forwardRef(
|
|
|
324
343
|
position="bottom"
|
|
325
344
|
isHidden={isOverflowing && atBottom}
|
|
326
345
|
onClick={() => scrollToBottom({ resumeSmartScroll: true })}
|
|
346
|
+
jumpButtonProps={jumpButtonBottomProps}
|
|
347
|
+
jumpButtonTooltipProps={jumpButtonBottomTooltipProps}
|
|
327
348
|
/>
|
|
328
349
|
</>
|
|
329
350
|
);
|
|
@@ -16,6 +16,17 @@
|
|
|
16
16
|
box-shadow: var(--pf-t--global--box-shadow--sm);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
.pf-chatbot__compact-sources-card-body {
|
|
20
|
+
--pf-v6-c-card--child--PaddingBlockEnd: var(--pf-t--global--spacer--xs);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.pf-chatbot__sources-card-subtitle,
|
|
24
|
+
.pf-chatbot__sources-card-subtle {
|
|
25
|
+
color: var(--pf-t--global--text--color--subtle);
|
|
26
|
+
font-size: var(--pf-t--global--font--size--body--sm);
|
|
27
|
+
font-weight: var(--pf-t--global--font--weight--body--default);
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
.pf-chatbot__sources-card-body-text {
|
|
20
31
|
display: block;
|
|
21
32
|
display: -webkit-box;
|
|
@@ -27,6 +38,12 @@
|
|
|
27
38
|
text-overflow: ellipsis;
|
|
28
39
|
}
|
|
29
40
|
|
|
41
|
+
.pf-chatbot__sources-card-title-container {
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
gap: var(--pf-t--global--spacer--xs);
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
.pf-chatbot__sources-card-footer-container {
|
|
31
48
|
border-top: var(--pf-t--global--border--width--regular) solid var(--pf-t--global--border--color--default);
|
|
32
49
|
padding: var(--pf-t--global--spacer--sm) var(--pf-t--global--spacer--md) var(--pf-t--global--spacer--sm)
|
|
@@ -256,4 +256,97 @@ describe('SourcesCard', () => {
|
|
|
256
256
|
);
|
|
257
257
|
expect(screen.getByRole('link', { name: /How to make an apple pie/i })).toHaveClass('test');
|
|
258
258
|
});
|
|
259
|
+
|
|
260
|
+
it('should apply cardTitleProps appropriately', () => {
|
|
261
|
+
render(
|
|
262
|
+
<SourcesCard
|
|
263
|
+
cardTitleProps={{ 'data-testid': 'card-title', className: 'test' } as any}
|
|
264
|
+
sources={[{ title: 'How to make an apple pie', link: '' }]}
|
|
265
|
+
/>
|
|
266
|
+
);
|
|
267
|
+
expect(screen.getByTestId('card-title')).toHaveClass('test');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should apply cardBodyProps appropriately', () => {
|
|
271
|
+
render(
|
|
272
|
+
<SourcesCard
|
|
273
|
+
cardBodyProps={
|
|
274
|
+
{ 'data-testid': 'card-body', body: 'To make an apple pie, you must first...', className: 'test' } as any
|
|
275
|
+
}
|
|
276
|
+
sources={[{ title: 'How to make an apple pie', link: '', body: 'To make an apple pie, you must first...' }]}
|
|
277
|
+
/>
|
|
278
|
+
);
|
|
279
|
+
expect(screen.getByTestId('card-body')).toHaveClass('test');
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('should apply cardFooterProps appropriately', () => {
|
|
283
|
+
render(
|
|
284
|
+
<SourcesCard
|
|
285
|
+
cardFooterProps={{ 'data-testid': 'card-footer', className: 'test' } as any}
|
|
286
|
+
sources={[
|
|
287
|
+
{ title: 'How to make an apple pie', link: '' },
|
|
288
|
+
{ title: 'How to make cookies', link: '' }
|
|
289
|
+
]}
|
|
290
|
+
/>
|
|
291
|
+
);
|
|
292
|
+
expect(screen.getByTestId('card-footer')).toHaveClass('test');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should apply truncateProps appropriately', () => {
|
|
296
|
+
render(
|
|
297
|
+
<SourcesCard
|
|
298
|
+
sources={[
|
|
299
|
+
{
|
|
300
|
+
title: 'How to make an apple pie',
|
|
301
|
+
link: '',
|
|
302
|
+
truncateProps: { 'data-testid': 'card-truncate', className: 'test' } as any
|
|
303
|
+
}
|
|
304
|
+
]}
|
|
305
|
+
/>
|
|
306
|
+
);
|
|
307
|
+
expect(screen.getByTestId('card-truncate')).toHaveClass('test');
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('should apply custom footer appropriately when there is one source', () => {
|
|
311
|
+
render(
|
|
312
|
+
<SourcesCard sources={[{ title: 'How to make an apple pie', link: '', footer: <>I am a custom footer</> }]} />
|
|
313
|
+
);
|
|
314
|
+
expect(screen.getByText('I am a custom footer'));
|
|
315
|
+
expect(screen.queryByText('1/1')).toBeFalsy();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should apply custom footer appropriately when are multiple sources', () => {
|
|
319
|
+
render(
|
|
320
|
+
<SourcesCard
|
|
321
|
+
sources={[
|
|
322
|
+
{ title: 'How to make an apple pie', link: '', footer: <>I am a custom footer</> },
|
|
323
|
+
{ title: 'How to bake bread', link: '' }
|
|
324
|
+
]}
|
|
325
|
+
/>
|
|
326
|
+
);
|
|
327
|
+
expect(screen.getByText('I am a custom footer'));
|
|
328
|
+
// does not show navigation bar
|
|
329
|
+
expect(screen.queryByText('1/2')).toBeFalsy();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('should apply footer props to custom footer appropriately', () => {
|
|
333
|
+
render(
|
|
334
|
+
<SourcesCard
|
|
335
|
+
cardFooterProps={{ 'data-testid': 'card-footer', className: 'test' } as any}
|
|
336
|
+
sources={[{ title: 'How to make an apple pie', link: '', footer: <>I am a custom footer</> }]}
|
|
337
|
+
/>
|
|
338
|
+
);
|
|
339
|
+
expect(screen.getByText('I am a custom footer'));
|
|
340
|
+
expect(screen.getByTestId('card-footer')).toHaveClass('test');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('should apply subtitle appropriately', () => {
|
|
344
|
+
render(
|
|
345
|
+
<SourcesCard
|
|
346
|
+
sources={[{ title: 'How to make an apple pie', link: '', subtitle: 'You must first create the universe' }]}
|
|
347
|
+
/>
|
|
348
|
+
);
|
|
349
|
+
expect(screen.getByText('How to make an apple pie'));
|
|
350
|
+
expect(screen.getByText('You must first create the universe'));
|
|
351
|
+
});
|
|
259
352
|
});
|