@patternfly/chatbot 6.3.0 → 6.3.2
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 +1 -10
- package/dist/cjs/MessageBar/MessageBar.js +19 -4
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +1 -7
- package/dist/esm/MessageBar/MessageBar.js +19 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -2
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +3 -27
- package/src/MessageBar/MessageBar.tsx +23 -3
- package/dist/cjs/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.d.ts +0 -62
- package/dist/cjs/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.js +0 -139
- package/dist/esm/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.d.ts +0 -62
- package/dist/esm/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.js +0 -133
- package/src/Message/CodeBlockMessage/ExpandableSectionForSyntaxHighlighter.tsx +0 -223
|
@@ -10,22 +10,16 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
}
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
-
};
|
|
16
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
14
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
18
15
|
// ============================================================================
|
|
19
16
|
// Chatbot Main - Message - Content - Code Block
|
|
20
17
|
// ============================================================================
|
|
21
18
|
const react_1 = require("react");
|
|
22
|
-
const react_syntax_highlighter_1 = __importDefault(require("react-syntax-highlighter"));
|
|
23
|
-
const hljs_1 = require("react-syntax-highlighter/dist/esm/styles/hljs");
|
|
24
19
|
// Import PatternFly components
|
|
25
20
|
const react_core_1 = require("@patternfly/react-core");
|
|
26
21
|
const check_icon_1 = require("@patternfly/react-icons/dist/esm/icons/check-icon");
|
|
27
22
|
const copy_icon_1 = require("@patternfly/react-icons/dist/esm/icons/copy-icon");
|
|
28
|
-
const ExpandableSectionForSyntaxHighlighter_1 = require("./ExpandableSectionForSyntaxHighlighter");
|
|
29
23
|
const DEFAULT_EXPANDED_TEXT = 'Show less';
|
|
30
24
|
const DEFAULT_COLLAPSED_TEXT = 'Show more';
|
|
31
25
|
const CodeBlockMessage = (_a) => {
|
|
@@ -71,9 +65,6 @@ const CodeBlockMessage = (_a) => {
|
|
|
71
65
|
}
|
|
72
66
|
// Setup code block header
|
|
73
67
|
const actions = ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)(react_core_1.CodeBlockAction, { children: [language && (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-code-block-language", children: language }), (0, jsx_runtime_1.jsx)(react_core_1.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 ? (0, jsx_runtime_1.jsx)(check_icon_1.CheckIcon, {}) : (0, jsx_runtime_1.jsx)(copy_icon_1.CopyIcon, {}) }), (0, jsx_runtime_1.jsx)(react_core_1.Tooltip, { id: tooltipID, content: "Copy", position: "top", triggerRef: buttonRef })] }) }));
|
|
74
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-code-block", ref: codeBlockRef, children: (0, jsx_runtime_1.jsxs)(react_core_1.CodeBlock, { actions: actions, children: [(0, jsx_runtime_1.jsx)(react_core_1.CodeBlockCode, { children: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children:
|
|
75
|
-
// SyntaxHighlighter doesn't work with ExpandableSection because it targets the direct child
|
|
76
|
-
// Forked for now and adjusted to match what we need
|
|
77
|
-
(0, jsx_runtime_1.jsx)(ExpandableSectionForSyntaxHighlighter_1.ExpandableSectionForSyntaxHighlighter, Object.assign({ variant: react_core_1.ExpandableSectionVariant.truncate, isExpanded: isExpanded, isDetached: true, toggleId: toggleId, contentId: contentId, language: language }, expandableSectionProps, { children: (0, jsx_runtime_1.jsx)(react_syntax_highlighter_1.default, Object.assign({}, props, { language: language, style: hljs_1.obsidian, PreTag: "div", CodeTag: "div", wrapLongLines: true, children: String(children).replace(/\n$/, '') })) }))) : ((0, jsx_runtime_1.jsx)(react_core_1.ExpandableSection, Object.assign({ variant: react_core_1.ExpandableSectionVariant.truncate, isExpanded: isExpanded, isDetached: true, toggleId: toggleId, contentId: contentId }, expandableSectionProps, { children: children }))) }) }), isExpandable && ((0, jsx_runtime_1.jsx)(react_core_1.ExpandableSectionToggle, Object.assign({ isExpanded: isExpanded, onToggle: onToggle, direction: "up", toggleId: toggleId, contentId: contentId, hasTruncatedContent: true, className: "pf-chatbot__message-code-toggle" }, expandableSectionToggleProps, { children: isExpanded ? finalExpandedText : finalCollapsedText })))] }) }));
|
|
68
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-code-block", ref: codeBlockRef, children: (0, jsx_runtime_1.jsxs)(react_core_1.CodeBlock, { actions: actions, children: [(0, jsx_runtime_1.jsx)(react_core_1.CodeBlockCode, { children: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: isExpandable ? ((0, jsx_runtime_1.jsx)(react_core_1.ExpandableSection, Object.assign({ variant: react_core_1.ExpandableSectionVariant.truncate, isExpanded: isExpanded, isDetached: true, toggleId: toggleId, contentId: contentId }, expandableSectionProps, { children: children }))) : (children) }) }), isExpandable && ((0, jsx_runtime_1.jsx)(react_core_1.ExpandableSectionToggle, Object.assign({ isExpanded: isExpanded, onToggle: onToggle, direction: "up", toggleId: toggleId, contentId: contentId, hasTruncatedContent: true, className: "pf-chatbot__message-code-toggle" }, expandableSectionToggleProps, { children: isExpanded ? finalExpandedText : finalCollapsedText })))] }) }));
|
|
78
69
|
};
|
|
79
70
|
exports.default = CodeBlockMessage;
|
|
@@ -32,6 +32,7 @@ const MessageBarBase = (_a) => {
|
|
|
32
32
|
const [message, setMessage] = (0, react_1.useState)(value !== null && value !== void 0 ? value : '');
|
|
33
33
|
const [isListeningMessage, setIsListeningMessage] = (0, react_1.useState)(false);
|
|
34
34
|
const [hasSentMessage, setHasSentMessage] = (0, react_1.useState)(false);
|
|
35
|
+
const [isComposing, setIsComposing] = (0, react_1.useState)(false);
|
|
35
36
|
const inputRef = (0, react_1.useRef)(null);
|
|
36
37
|
const textareaRef = (_b = innerRef) !== null && _b !== void 0 ? _b : inputRef;
|
|
37
38
|
const attachButtonRef = (0, react_1.useRef)(null);
|
|
@@ -157,18 +158,32 @@ const MessageBarBase = (_a) => {
|
|
|
157
158
|
setMessage('');
|
|
158
159
|
}, [onSendMessage]);
|
|
159
160
|
const handleKeyDown = (0, react_1.useCallback)((event) => {
|
|
160
|
-
|
|
161
|
+
// Japanese and other languages may use IME for character input.
|
|
162
|
+
// In these cases, enter is used to select the final input, so we need to check for composition end instead.
|
|
163
|
+
// See more info at https://www.stum.de/2016/06/24/handling-ime-events-in-javascript/
|
|
164
|
+
// Chrome, Edge, and Firefox seem to work well with just the compose event.
|
|
165
|
+
// Safari is a little bit special. We need to handle 229 as well in this case.
|
|
166
|
+
const nativeEvent = event.nativeEvent;
|
|
167
|
+
const isCompositionKey = nativeEvent.which === 229;
|
|
168
|
+
const isCurrentlyComposing = isComposing || isCompositionKey;
|
|
169
|
+
if (event.key === 'Enter' && !isCurrentlyComposing && !event.shiftKey) {
|
|
161
170
|
event.preventDefault();
|
|
162
171
|
if (!isSendButtonDisabled && !hasStopButton) {
|
|
163
172
|
handleSend(message);
|
|
164
173
|
}
|
|
165
174
|
}
|
|
166
|
-
if (event.key === 'Enter' && event.shiftKey) {
|
|
175
|
+
if (event.key === 'Enter' && !isCurrentlyComposing && event.shiftKey) {
|
|
167
176
|
if (textareaRef.current) {
|
|
168
177
|
handleNewLine(textareaRef.current);
|
|
169
178
|
}
|
|
170
179
|
}
|
|
171
|
-
}, [isSendButtonDisabled, hasStopButton, handleSend, message]);
|
|
180
|
+
}, [isSendButtonDisabled, hasStopButton, handleSend, message, isComposing]);
|
|
181
|
+
const handleCompositionStart = (0, react_1.useCallback)(() => {
|
|
182
|
+
setIsComposing(true);
|
|
183
|
+
}, []);
|
|
184
|
+
const handleCompositionEnd = (0, react_1.useCallback)(() => {
|
|
185
|
+
setIsComposing(false);
|
|
186
|
+
}, []);
|
|
172
187
|
const handleAttachMenuToggle = () => {
|
|
173
188
|
(attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen) && (attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen(!(attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.isAttachMenuOpen)));
|
|
174
189
|
attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuToggleClick();
|
|
@@ -184,7 +199,7 @@ const MessageBarBase = (_a) => {
|
|
|
184
199
|
}
|
|
185
200
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [attachMenuProps && ((0, jsx_runtime_1.jsx)(AttachButton_1.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 }, (_f = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _f === void 0 ? void 0 : _f.props))), !attachMenuProps && hasAttachButton && ((0, jsx_runtime_1.jsx)(AttachButton_1.AttachButton, Object.assign({ onAttachAccepted: handleAttach, isDisabled: isListeningMessage, tooltipContent: (_g = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _g === void 0 ? void 0 : _g.tooltipContent, inputTestId: (_h = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _h === void 0 ? void 0 : _h.inputTestId, isCompact: isCompact, tooltipProps: (_j = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _j === void 0 ? void 0 : _j.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, (_k = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _k === void 0 ? void 0 : _k.props))), hasMicrophoneButton && ((0, jsx_runtime_1.jsx)(MicrophoneButton_1.default, Object.assign({ isListening: isListeningMessage, onIsListeningChange: setIsListeningMessage, onSpeechRecognition: handleSpeechRecognition, tooltipContent: (_l = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _l === void 0 ? void 0 : _l.tooltipContent, language: (_m = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _m === void 0 ? void 0 : _m.language, isCompact: isCompact, tooltipProps: (_o = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _o === void 0 ? void 0 : _o.tooltipProps }, (_p = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _p === void 0 ? void 0 : _p.props))), (alwayShowSendButton || message) && ((0, jsx_runtime_1.jsx)(SendButton_1.default, Object.assign({ value: message, onClick: () => handleSend(message), isDisabled: isSendButtonDisabled, tooltipContent: (_q = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _q === void 0 ? void 0 : _q.tooltipContent, isCompact: isCompact, tooltipProps: (_r = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _r === void 0 ? void 0 : _r.tooltipProps }, (_s = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _s === void 0 ? void 0 : _s.props)))] }));
|
|
186
201
|
};
|
|
187
|
-
const messageBarContents = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__message-bar-input ${isCompact ? 'pf-m-compact' : ''}`, children: (0, jsx_runtime_1.jsx)(react_core_1.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 }, props)) }), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-bar-actions", children: renderButtons() })] }));
|
|
202
|
+
const messageBarContents = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__message-bar-input ${isCompact ? 'pf-m-compact' : ''}`, children: (0, jsx_runtime_1.jsx)(react_core_1.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)) }), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-bar-actions", children: renderButtons() })] }));
|
|
188
203
|
if (attachMenuProps) {
|
|
189
204
|
return ((0, jsx_runtime_1.jsx)(AttachMenu_1.default, Object.assign({ toggle: (toggleRef) => ((0, jsx_runtime_1.jsx)("div", { ref: toggleRef, className: `pf-chatbot__message-bar ${className !== null && className !== void 0 ? className : ''}`, children: messageBarContents })), filteredItems: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuItems }, (attachMenuProps && { isOpen: attachMenuProps.isAttachMenuOpen }), { onOpenChange: (isAttachMenuOpen) => {
|
|
190
205
|
var _a;
|
|
@@ -14,13 +14,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
14
14
|
// Chatbot Main - Message - Content - Code Block
|
|
15
15
|
// ============================================================================
|
|
16
16
|
import { useState, useRef, useId, useCallback, useEffect } from 'react';
|
|
17
|
-
import SyntaxHighlighter from 'react-syntax-highlighter';
|
|
18
|
-
import { obsidian } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
|
19
17
|
// Import PatternFly components
|
|
20
18
|
import { CodeBlock, CodeBlockAction, CodeBlockCode, Button, Tooltip, ExpandableSection, ExpandableSectionToggle, ExpandableSectionVariant } from '@patternfly/react-core';
|
|
21
19
|
import { CheckIcon } from '@patternfly/react-icons/dist/esm/icons/check-icon';
|
|
22
20
|
import { CopyIcon } from '@patternfly/react-icons/dist/esm/icons/copy-icon';
|
|
23
|
-
import { ExpandableSectionForSyntaxHighlighter } from './ExpandableSectionForSyntaxHighlighter';
|
|
24
21
|
const DEFAULT_EXPANDED_TEXT = 'Show less';
|
|
25
22
|
const DEFAULT_COLLAPSED_TEXT = 'Show more';
|
|
26
23
|
const CodeBlockMessage = (_a) => {
|
|
@@ -66,9 +63,6 @@ const CodeBlockMessage = (_a) => {
|
|
|
66
63
|
}
|
|
67
64
|
// Setup code block header
|
|
68
65
|
const actions = (_jsx(_Fragment, { children: _jsxs(CodeBlockAction, { 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 })] }) }));
|
|
69
|
-
return (_jsx("div", { className: "pf-chatbot__message-code-block", ref: codeBlockRef, children: _jsxs(CodeBlock, { actions: actions, children: [_jsx(CodeBlockCode, { children: _jsx(_Fragment, { children:
|
|
70
|
-
// SyntaxHighlighter doesn't work with ExpandableSection because it targets the direct child
|
|
71
|
-
// Forked for now and adjusted to match what we need
|
|
72
|
-
_jsx(ExpandableSectionForSyntaxHighlighter, Object.assign({ variant: ExpandableSectionVariant.truncate, isExpanded: isExpanded, isDetached: true, toggleId: toggleId, contentId: contentId, language: language }, expandableSectionProps, { children: _jsx(SyntaxHighlighter, Object.assign({}, props, { language: language, style: obsidian, PreTag: "div", CodeTag: "div", wrapLongLines: true, children: String(children).replace(/\n$/, '') })) }))) : (_jsx(ExpandableSection, Object.assign({ variant: ExpandableSectionVariant.truncate, isExpanded: isExpanded, isDetached: true, toggleId: toggleId, contentId: contentId }, expandableSectionProps, { children: children }))) }) }), isExpandable && (_jsx(ExpandableSectionToggle, Object.assign({ isExpanded: isExpanded, onToggle: onToggle, direction: "up", toggleId: toggleId, contentId: contentId, hasTruncatedContent: true, className: "pf-chatbot__message-code-toggle" }, expandableSectionToggleProps, { children: isExpanded ? finalExpandedText : finalCollapsedText })))] }) }));
|
|
66
|
+
return (_jsx("div", { className: "pf-chatbot__message-code-block", ref: codeBlockRef, children: _jsxs(CodeBlock, { actions: actions, children: [_jsx(CodeBlockCode, { children: _jsx(_Fragment, { children: isExpandable ? (_jsx(ExpandableSection, Object.assign({ variant: ExpandableSectionVariant.truncate, isExpanded: isExpanded, isDetached: true, toggleId: toggleId, contentId: contentId }, expandableSectionProps, { children: children }))) : (children) }) }), isExpandable && (_jsx(ExpandableSectionToggle, Object.assign({ isExpanded: isExpanded, onToggle: onToggle, direction: "up", toggleId: toggleId, contentId: contentId, hasTruncatedContent: true, className: "pf-chatbot__message-code-toggle" }, expandableSectionToggleProps, { children: isExpanded ? finalExpandedText : finalCollapsedText })))] }) }));
|
|
73
67
|
};
|
|
74
68
|
export default CodeBlockMessage;
|
|
@@ -26,6 +26,7 @@ export const MessageBarBase = (_a) => {
|
|
|
26
26
|
const [message, setMessage] = useState(value !== null && value !== void 0 ? value : '');
|
|
27
27
|
const [isListeningMessage, setIsListeningMessage] = useState(false);
|
|
28
28
|
const [hasSentMessage, setHasSentMessage] = useState(false);
|
|
29
|
+
const [isComposing, setIsComposing] = useState(false);
|
|
29
30
|
const inputRef = useRef(null);
|
|
30
31
|
const textareaRef = (_b = innerRef) !== null && _b !== void 0 ? _b : inputRef;
|
|
31
32
|
const attachButtonRef = useRef(null);
|
|
@@ -151,18 +152,32 @@ export const MessageBarBase = (_a) => {
|
|
|
151
152
|
setMessage('');
|
|
152
153
|
}, [onSendMessage]);
|
|
153
154
|
const handleKeyDown = useCallback((event) => {
|
|
154
|
-
|
|
155
|
+
// Japanese and other languages may use IME for character input.
|
|
156
|
+
// In these cases, enter is used to select the final input, so we need to check for composition end instead.
|
|
157
|
+
// See more info at https://www.stum.de/2016/06/24/handling-ime-events-in-javascript/
|
|
158
|
+
// Chrome, Edge, and Firefox seem to work well with just the compose event.
|
|
159
|
+
// Safari is a little bit special. We need to handle 229 as well in this case.
|
|
160
|
+
const nativeEvent = event.nativeEvent;
|
|
161
|
+
const isCompositionKey = nativeEvent.which === 229;
|
|
162
|
+
const isCurrentlyComposing = isComposing || isCompositionKey;
|
|
163
|
+
if (event.key === 'Enter' && !isCurrentlyComposing && !event.shiftKey) {
|
|
155
164
|
event.preventDefault();
|
|
156
165
|
if (!isSendButtonDisabled && !hasStopButton) {
|
|
157
166
|
handleSend(message);
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
|
-
if (event.key === 'Enter' && event.shiftKey) {
|
|
169
|
+
if (event.key === 'Enter' && !isCurrentlyComposing && event.shiftKey) {
|
|
161
170
|
if (textareaRef.current) {
|
|
162
171
|
handleNewLine(textareaRef.current);
|
|
163
172
|
}
|
|
164
173
|
}
|
|
165
|
-
}, [isSendButtonDisabled, hasStopButton, handleSend, message]);
|
|
174
|
+
}, [isSendButtonDisabled, hasStopButton, handleSend, message, isComposing]);
|
|
175
|
+
const handleCompositionStart = useCallback(() => {
|
|
176
|
+
setIsComposing(true);
|
|
177
|
+
}, []);
|
|
178
|
+
const handleCompositionEnd = useCallback(() => {
|
|
179
|
+
setIsComposing(false);
|
|
180
|
+
}, []);
|
|
166
181
|
const handleAttachMenuToggle = () => {
|
|
167
182
|
(attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen) && (attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen(!(attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.isAttachMenuOpen)));
|
|
168
183
|
attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuToggleClick();
|
|
@@ -178,7 +193,7 @@ export const MessageBarBase = (_a) => {
|
|
|
178
193
|
}
|
|
179
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 }, (_f = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _f === void 0 ? void 0 : _f.props))), !attachMenuProps && hasAttachButton && (_jsx(AttachButton, Object.assign({ onAttachAccepted: handleAttach, isDisabled: isListeningMessage, tooltipContent: (_g = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _g === void 0 ? void 0 : _g.tooltipContent, inputTestId: (_h = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _h === void 0 ? void 0 : _h.inputTestId, isCompact: isCompact, tooltipProps: (_j = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _j === void 0 ? void 0 : _j.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, (_k = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _k === void 0 ? void 0 : _k.props))), hasMicrophoneButton && (_jsx(MicrophoneButton, Object.assign({ isListening: isListeningMessage, onIsListeningChange: setIsListeningMessage, onSpeechRecognition: handleSpeechRecognition, tooltipContent: (_l = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _l === void 0 ? void 0 : _l.tooltipContent, language: (_m = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _m === void 0 ? void 0 : _m.language, isCompact: isCompact, tooltipProps: (_o = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _o === void 0 ? void 0 : _o.tooltipProps }, (_p = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _p === void 0 ? void 0 : _p.props))), (alwayShowSendButton || message) && (_jsx(SendButton, Object.assign({ value: message, onClick: () => handleSend(message), isDisabled: isSendButtonDisabled, tooltipContent: (_q = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _q === void 0 ? void 0 : _q.tooltipContent, isCompact: isCompact, tooltipProps: (_r = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _r === void 0 ? void 0 : _r.tooltipProps }, (_s = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _s === void 0 ? void 0 : _s.props)))] }));
|
|
180
195
|
};
|
|
181
|
-
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 }, props)) }), _jsx("div", { className: "pf-chatbot__message-bar-actions", children: renderButtons() })] }));
|
|
196
|
+
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() })] }));
|
|
182
197
|
if (attachMenuProps) {
|
|
183
198
|
return (_jsx(AttachMenu, Object.assign({ toggle: (toggleRef) => (_jsx("div", { ref: toggleRef, className: `pf-chatbot__message-bar ${className !== null && className !== void 0 ? className : ''}`, children: messageBarContents })), filteredItems: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuItems }, (attachMenuProps && { isOpen: attachMenuProps.isAttachMenuOpen }), { onOpenChange: (isAttachMenuOpen) => {
|
|
184
199
|
var _a;
|
|
@@ -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/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/FileDetails/FileDetails.test.tsx","../src/FileDetails/FileDetails.tsx","../src/FileDetails/index.ts","../src/FileDetailsLabel/FileDetailsLabel.test.tsx","../src/FileDetailsLabel/FileDetailsLabel.tsx","../src/FileDetailsLabel/index.ts","../src/FileDropZone/FileDropZone.test.tsx","../src/FileDropZone/FileDropZone.tsx","../src/FileDropZone/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/Message/Message.test.tsx","../src/Message/Message.tsx","../src/Message/MessageInput.tsx","../src/Message/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/
|
|
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/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/FileDetails/FileDetails.test.tsx","../src/FileDetails/FileDetails.tsx","../src/FileDetails/index.ts","../src/FileDetailsLabel/FileDetailsLabel.test.tsx","../src/FileDetailsLabel/FileDetailsLabel.tsx","../src/FileDetailsLabel/index.ts","../src/FileDropZone/FileDropZone.test.tsx","../src/FileDropZone/FileDropZone.tsx","../src/FileDropZone/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/Message/Message.test.tsx","../src/Message/Message.tsx","../src/Message/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/TableMessage/TableMessage.tsx","../src/Message/TableMessage/TbodyMessage.tsx","../src/Message/TableMessage/TdMessage.tsx","../src/Message/TableMessage/ThMessage.tsx","../src/Message/TableMessage/TheadMessage.tsx","../src/Message/TableMessage/TrMessage.tsx","../src/Message/TextMessage/TextMessage.tsx","../src/Message/UserFeedback/CloseButton.tsx","../src/Message/UserFeedback/UserFeedback.test.tsx","../src/Message/UserFeedback/UserFeedback.tsx","../src/Message/UserFeedback/UserFeedbackComplete.test.tsx","../src/Message/UserFeedback/UserFeedbackComplete.tsx","../src/MessageBar/AttachButton.test.tsx","../src/MessageBar/AttachButton.tsx","../src/MessageBar/MessageBar.test.tsx","../src/MessageBar/MessageBar.tsx","../src/MessageBar/MicrophoneButton.tsx","../src/MessageBar/SendButton.test.tsx","../src/MessageBar/SendButton.tsx","../src/MessageBar/StopButton.test.tsx","../src/MessageBar/StopButton.tsx","../src/MessageBar/index.ts","../src/MessageBox/JumpButton.test.tsx","../src/MessageBox/JumpButton.tsx","../src/MessageBox/MessageBox.test.tsx","../src/MessageBox/MessageBox.tsx","../src/MessageBox/index.ts","../src/PreviewAttachment/PreviewAttachment.test.tsx","../src/PreviewAttachment/PreviewAttachment.tsx","../src/PreviewAttachment/index.ts","../src/ResponseActions/ResponseActionButton.test.tsx","../src/ResponseActions/ResponseActionButton.tsx","../src/ResponseActions/ResponseActions.test.tsx","../src/ResponseActions/ResponseActions.tsx","../src/ResponseActions/index.ts","../src/Settings/SettingsForm.test.tsx","../src/Settings/SettingsForm.tsx","../src/Settings/index.ts","../src/SourceDetailsMenuItem/SourceDetailsMenuItem.tsx","../src/SourceDetailsMenuItem/index.ts","../src/SourcesCard/SourcesCard.test.tsx","../src/SourcesCard/SourcesCard.tsx","../src/SourcesCard/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/__mocks__/rehype-external-links.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.3.
|
|
3
|
+
"version": "6.3.2",
|
|
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",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"clsx": "^2.1.0",
|
|
41
41
|
"framer-motion": "^11.3.28",
|
|
42
42
|
"react-markdown": "^9.0.1",
|
|
43
|
-
"react-syntax-highlighter": "^15.5.0",
|
|
44
43
|
"remark-gfm": "^4.0.0",
|
|
45
44
|
"rehype-unwrap-images": "^1.0.0",
|
|
46
45
|
"rehype-external-links": "^3.0.0",
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
// Chatbot Main - Message - Content - Code Block
|
|
3
3
|
// ============================================================================
|
|
4
4
|
import { useState, useRef, useId, useCallback, useEffect } from 'react';
|
|
5
|
-
import SyntaxHighlighter from 'react-syntax-highlighter';
|
|
6
|
-
import { obsidian } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
|
7
5
|
// Import PatternFly components
|
|
8
6
|
import {
|
|
9
7
|
CodeBlock,
|
|
@@ -20,7 +18,6 @@ import {
|
|
|
20
18
|
|
|
21
19
|
import { CheckIcon } from '@patternfly/react-icons/dist/esm/icons/check-icon';
|
|
22
20
|
import { CopyIcon } from '@patternfly/react-icons/dist/esm/icons/copy-icon';
|
|
23
|
-
import { ExpandableSectionForSyntaxHighlighter } from './ExpandableSectionForSyntaxHighlighter';
|
|
24
21
|
|
|
25
22
|
export interface CodeBlockMessageProps {
|
|
26
23
|
/** Content rendered in code block */
|
|
@@ -137,30 +134,7 @@ const CodeBlockMessage = ({
|
|
|
137
134
|
<CodeBlock actions={actions}>
|
|
138
135
|
<CodeBlockCode>
|
|
139
136
|
<>
|
|
140
|
-
{
|
|
141
|
-
// SyntaxHighlighter doesn't work with ExpandableSection because it targets the direct child
|
|
142
|
-
// Forked for now and adjusted to match what we need
|
|
143
|
-
<ExpandableSectionForSyntaxHighlighter
|
|
144
|
-
variant={ExpandableSectionVariant.truncate}
|
|
145
|
-
isExpanded={isExpanded}
|
|
146
|
-
isDetached
|
|
147
|
-
toggleId={toggleId}
|
|
148
|
-
contentId={contentId}
|
|
149
|
-
language={language}
|
|
150
|
-
{...expandableSectionProps}
|
|
151
|
-
>
|
|
152
|
-
<SyntaxHighlighter
|
|
153
|
-
{...props}
|
|
154
|
-
language={language}
|
|
155
|
-
style={obsidian}
|
|
156
|
-
PreTag="div"
|
|
157
|
-
CodeTag="div"
|
|
158
|
-
wrapLongLines
|
|
159
|
-
>
|
|
160
|
-
{String(children).replace(/\n$/, '')}
|
|
161
|
-
</SyntaxHighlighter>
|
|
162
|
-
</ExpandableSectionForSyntaxHighlighter>
|
|
163
|
-
) : (
|
|
137
|
+
{isExpandable ? (
|
|
164
138
|
<ExpandableSection
|
|
165
139
|
variant={ExpandableSectionVariant.truncate}
|
|
166
140
|
isExpanded={isExpanded}
|
|
@@ -171,6 +145,8 @@ const CodeBlockMessage = ({
|
|
|
171
145
|
>
|
|
172
146
|
{children}
|
|
173
147
|
</ExpandableSection>
|
|
148
|
+
) : (
|
|
149
|
+
children
|
|
174
150
|
)}
|
|
175
151
|
</>
|
|
176
152
|
</CodeBlockCode>
|
|
@@ -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>
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Component } from 'react';
|
|
2
|
-
import { PickOptional } from '@patternfly/react-core';
|
|
3
|
-
export declare enum ExpandableSectionVariant {
|
|
4
|
-
default = "default",
|
|
5
|
-
truncate = "truncate"
|
|
6
|
-
}
|
|
7
|
-
/** The main expandable section component. */
|
|
8
|
-
export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onToggle'> {
|
|
9
|
-
/** Content rendered inside the expandable section. */
|
|
10
|
-
children?: React.ReactNode;
|
|
11
|
-
/** Additional classes added to the expandable section. */
|
|
12
|
-
className?: string;
|
|
13
|
-
/** Id of the content of the expandable section. When passing in the isDetached property, this
|
|
14
|
-
* property's value should match the contentId property of the expandable section toggle sub-component.
|
|
15
|
-
*/
|
|
16
|
-
contentId?: string;
|
|
17
|
-
/** Id of the toggle of the expandable section, which provides an accessible name to the
|
|
18
|
-
* expandable section content via the aria-labelledby attribute. When the isDetached property
|
|
19
|
-
* is also passed in, the value of this property must match the toggleId property of the
|
|
20
|
-
* expandable section toggle sub-component.
|
|
21
|
-
*/
|
|
22
|
-
toggleId?: string;
|
|
23
|
-
/** Display size variant. Set to "lg" for disclosure styling. */
|
|
24
|
-
displaySize?: 'default' | 'lg';
|
|
25
|
-
/** Indicates the expandable section has a detached toggle. */
|
|
26
|
-
isDetached?: boolean;
|
|
27
|
-
/** Flag to indicate if the content is expanded. */
|
|
28
|
-
isExpanded?: boolean;
|
|
29
|
-
/** Flag to indicate if the content is indented. */
|
|
30
|
-
isIndented?: boolean;
|
|
31
|
-
/** Flag to indicate the width of the component is limited. Set to "true" for disclosure styling. */
|
|
32
|
-
isWidthLimited?: boolean;
|
|
33
|
-
/** Truncates the expandable content to the specified number of lines when using the
|
|
34
|
-
* "truncate" variant.
|
|
35
|
-
*/
|
|
36
|
-
truncateMaxLines?: number;
|
|
37
|
-
/** Determines the variant of the expandable section. When passing in "truncate" as the
|
|
38
|
-
* variant, the expandable content will be truncated after 3 lines by default.
|
|
39
|
-
*/
|
|
40
|
-
variant?: 'default' | 'truncate';
|
|
41
|
-
language?: string;
|
|
42
|
-
}
|
|
43
|
-
interface ExpandableSectionState {
|
|
44
|
-
isExpanded: boolean;
|
|
45
|
-
hasToggle: boolean;
|
|
46
|
-
previousWidth: number | undefined;
|
|
47
|
-
}
|
|
48
|
-
declare class ExpandableSectionForSyntaxHighlighter extends Component<ExpandableSectionProps, ExpandableSectionState> {
|
|
49
|
-
static displayName: string;
|
|
50
|
-
constructor(props: ExpandableSectionProps);
|
|
51
|
-
expandableContentRef: import("react").RefObject<HTMLDivElement>;
|
|
52
|
-
observer: any;
|
|
53
|
-
static defaultProps: PickOptional<ExpandableSectionProps>;
|
|
54
|
-
componentDidMount(): void;
|
|
55
|
-
componentDidUpdate(prevProps: ExpandableSectionProps): void;
|
|
56
|
-
componentWillUnmount(): void;
|
|
57
|
-
checkToggleVisibility: () => void;
|
|
58
|
-
resize: () => void;
|
|
59
|
-
handleResize: (...args: any[]) => void;
|
|
60
|
-
render(): import("react/jsx-runtime").JSX.Element;
|
|
61
|
-
}
|
|
62
|
-
export { ExpandableSectionForSyntaxHighlighter };
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
-
var t = {};
|
|
4
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
-
t[p] = s[p];
|
|
6
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
-
t[p[i]] = s[p[i]];
|
|
10
|
-
}
|
|
11
|
-
return t;
|
|
12
|
-
};
|
|
13
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.ExpandableSectionForSyntaxHighlighter = exports.ExpandableSectionVariant = void 0;
|
|
18
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
|
-
const react_1 = require("react");
|
|
20
|
-
const expandable_section_1 = __importDefault(require("@patternfly/react-styles/css/components/ExpandableSection/expandable-section"));
|
|
21
|
-
const react_styles_1 = require("@patternfly/react-styles");
|
|
22
|
-
const c_expandable_section_m_truncate__content_LineClamp_1 = __importDefault(require("@patternfly/react-tokens/dist/esm/c_expandable_section_m_truncate__content_LineClamp"));
|
|
23
|
-
const react_core_1 = require("@patternfly/react-core");
|
|
24
|
-
var ExpandableSectionVariant;
|
|
25
|
-
(function (ExpandableSectionVariant) {
|
|
26
|
-
ExpandableSectionVariant["default"] = "default";
|
|
27
|
-
ExpandableSectionVariant["truncate"] = "truncate";
|
|
28
|
-
})(ExpandableSectionVariant || (exports.ExpandableSectionVariant = ExpandableSectionVariant = {}));
|
|
29
|
-
const setLineClamp = (element, lines, language, isExpanded) => {
|
|
30
|
-
if (!element || !lines || lines < 1 || typeof isExpanded === 'undefined') {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (language) {
|
|
34
|
-
const selector = `.language-${language.toLowerCase()}`;
|
|
35
|
-
const childElement = element.querySelector(selector);
|
|
36
|
-
if (!childElement) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (isExpanded) {
|
|
40
|
-
// Reset all truncation-related styles to their default values
|
|
41
|
-
childElement.style.removeProperty('-webkit-line-clamp');
|
|
42
|
-
childElement.style.removeProperty('display');
|
|
43
|
-
childElement.style.removeProperty('-webkit-box-orient');
|
|
44
|
-
childElement.style.removeProperty('overflow');
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
childElement.style.setProperty('-webkit-line-clamp', lines.toString());
|
|
48
|
-
childElement.style.setProperty('display', '-webkit-box');
|
|
49
|
-
childElement.style.setProperty('-webkit-box-orient', 'vertical');
|
|
50
|
-
childElement.style.setProperty('overflow', 'hidden');
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
class ExpandableSectionForSyntaxHighlighter extends react_1.Component {
|
|
55
|
-
constructor(props) {
|
|
56
|
-
var _a;
|
|
57
|
-
super(props);
|
|
58
|
-
this.expandableContentRef = (0, react_1.createRef)();
|
|
59
|
-
/* eslint-disable-next-line */
|
|
60
|
-
this.observer = () => { };
|
|
61
|
-
this.checkToggleVisibility = () => {
|
|
62
|
-
var _a;
|
|
63
|
-
if ((_a = this.expandableContentRef) === null || _a === void 0 ? void 0 : _a.current) {
|
|
64
|
-
const maxLines = this.props.truncateMaxLines || parseInt(c_expandable_section_m_truncate__content_LineClamp_1.default.value);
|
|
65
|
-
const totalLines = this.expandableContentRef.current.scrollHeight /
|
|
66
|
-
parseInt(getComputedStyle(this.expandableContentRef.current).lineHeight);
|
|
67
|
-
this.setState({
|
|
68
|
-
hasToggle: totalLines > maxLines
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
this.resize = () => {
|
|
73
|
-
if (this.expandableContentRef.current) {
|
|
74
|
-
const { offsetWidth } = this.expandableContentRef.current;
|
|
75
|
-
if (this.state.previousWidth !== offsetWidth) {
|
|
76
|
-
this.setState({ previousWidth: offsetWidth });
|
|
77
|
-
this.checkToggleVisibility();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
this.handleResize = (0, react_core_1.debounce)(this.resize, 250);
|
|
82
|
-
this.state = {
|
|
83
|
-
isExpanded: (_a = props.isExpanded) !== null && _a !== void 0 ? _a : false,
|
|
84
|
-
hasToggle: true,
|
|
85
|
-
previousWidth: undefined
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
componentDidMount() {
|
|
89
|
-
if (this.props.variant === ExpandableSectionVariant.truncate) {
|
|
90
|
-
const expandableContent = this.expandableContentRef.current;
|
|
91
|
-
if (expandableContent) {
|
|
92
|
-
this.setState({ previousWidth: expandableContent.offsetWidth });
|
|
93
|
-
this.observer = (0, react_core_1.getResizeObserver)(expandableContent, this.handleResize, false);
|
|
94
|
-
if (this.props.truncateMaxLines) {
|
|
95
|
-
setLineClamp(expandableContent, this.props.truncateMaxLines, this.props.language, this.state.isExpanded);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
this.checkToggleVisibility();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
componentDidUpdate(prevProps) {
|
|
102
|
-
if (this.props.variant === ExpandableSectionVariant.truncate &&
|
|
103
|
-
(prevProps.truncateMaxLines !== this.props.truncateMaxLines ||
|
|
104
|
-
prevProps.children !== this.props.children ||
|
|
105
|
-
prevProps.isExpanded !== this.props.isExpanded)) {
|
|
106
|
-
const expandableContent = this.expandableContentRef.current;
|
|
107
|
-
setLineClamp(expandableContent, this.props.truncateMaxLines, this.props.language, this.props.isExpanded);
|
|
108
|
-
this.checkToggleVisibility();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
componentWillUnmount() {
|
|
112
|
-
if (this.props.variant === ExpandableSectionVariant.truncate) {
|
|
113
|
-
this.observer();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
render() {
|
|
117
|
-
const _a = this.props, { className, children, isExpanded, isDetached, displaySize, isWidthLimited, isIndented, contentId, toggleId, variant,
|
|
118
|
-
// Gets rid of console error about it being on a DOM element
|
|
119
|
-
// eslint-disable-next-line
|
|
120
|
-
truncateMaxLines } = _a, props = __rest(_a, ["className", "children", "isExpanded", "isDetached", "displaySize", "isWidthLimited", "isIndented", "contentId", "toggleId", "variant", "truncateMaxLines"]);
|
|
121
|
-
if (isDetached && !toggleId) {
|
|
122
|
-
/* eslint-disable no-console */
|
|
123
|
-
console.warn('ExpandableSection: The toggleId value must be passed in and must match the toggleId of the ExpandableSectionToggle.');
|
|
124
|
-
}
|
|
125
|
-
const uniqueContentId = contentId || (0, react_core_1.getUniqueId)('expandable-section-content');
|
|
126
|
-
const uniqueToggleId = toggleId || (0, react_core_1.getUniqueId)('expandable-section-toggle');
|
|
127
|
-
return ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, react_styles_1.css)(expandable_section_1.default.expandableSection, isExpanded && expandable_section_1.default.modifiers.expanded, displaySize === 'lg' && expandable_section_1.default.modifiers.displayLg, isWidthLimited && expandable_section_1.default.modifiers.limitWidth, isIndented && expandable_section_1.default.modifiers.indented, variant === ExpandableSectionVariant.truncate && expandable_section_1.default.modifiers.truncate, className) }, props, { children: (0, jsx_runtime_1.jsx)("div", { ref: this.expandableContentRef, className: (0, react_styles_1.css)(expandable_section_1.default.expandableSectionContent), hidden: variant !== ExpandableSectionVariant.truncate && !isExpanded, id: uniqueContentId, "aria-labelledby": uniqueToggleId, role: "region", children: children }) })));
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
exports.ExpandableSectionForSyntaxHighlighter = ExpandableSectionForSyntaxHighlighter;
|
|
131
|
-
ExpandableSectionForSyntaxHighlighter.displayName = 'ExpandableSection';
|
|
132
|
-
ExpandableSectionForSyntaxHighlighter.defaultProps = {
|
|
133
|
-
className: '',
|
|
134
|
-
isDetached: false,
|
|
135
|
-
displaySize: 'default',
|
|
136
|
-
isWidthLimited: false,
|
|
137
|
-
isIndented: false,
|
|
138
|
-
variant: 'default'
|
|
139
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Component } from 'react';
|
|
2
|
-
import { PickOptional } from '@patternfly/react-core';
|
|
3
|
-
export declare enum ExpandableSectionVariant {
|
|
4
|
-
default = "default",
|
|
5
|
-
truncate = "truncate"
|
|
6
|
-
}
|
|
7
|
-
/** The main expandable section component. */
|
|
8
|
-
export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onToggle'> {
|
|
9
|
-
/** Content rendered inside the expandable section. */
|
|
10
|
-
children?: React.ReactNode;
|
|
11
|
-
/** Additional classes added to the expandable section. */
|
|
12
|
-
className?: string;
|
|
13
|
-
/** Id of the content of the expandable section. When passing in the isDetached property, this
|
|
14
|
-
* property's value should match the contentId property of the expandable section toggle sub-component.
|
|
15
|
-
*/
|
|
16
|
-
contentId?: string;
|
|
17
|
-
/** Id of the toggle of the expandable section, which provides an accessible name to the
|
|
18
|
-
* expandable section content via the aria-labelledby attribute. When the isDetached property
|
|
19
|
-
* is also passed in, the value of this property must match the toggleId property of the
|
|
20
|
-
* expandable section toggle sub-component.
|
|
21
|
-
*/
|
|
22
|
-
toggleId?: string;
|
|
23
|
-
/** Display size variant. Set to "lg" for disclosure styling. */
|
|
24
|
-
displaySize?: 'default' | 'lg';
|
|
25
|
-
/** Indicates the expandable section has a detached toggle. */
|
|
26
|
-
isDetached?: boolean;
|
|
27
|
-
/** Flag to indicate if the content is expanded. */
|
|
28
|
-
isExpanded?: boolean;
|
|
29
|
-
/** Flag to indicate if the content is indented. */
|
|
30
|
-
isIndented?: boolean;
|
|
31
|
-
/** Flag to indicate the width of the component is limited. Set to "true" for disclosure styling. */
|
|
32
|
-
isWidthLimited?: boolean;
|
|
33
|
-
/** Truncates the expandable content to the specified number of lines when using the
|
|
34
|
-
* "truncate" variant.
|
|
35
|
-
*/
|
|
36
|
-
truncateMaxLines?: number;
|
|
37
|
-
/** Determines the variant of the expandable section. When passing in "truncate" as the
|
|
38
|
-
* variant, the expandable content will be truncated after 3 lines by default.
|
|
39
|
-
*/
|
|
40
|
-
variant?: 'default' | 'truncate';
|
|
41
|
-
language?: string;
|
|
42
|
-
}
|
|
43
|
-
interface ExpandableSectionState {
|
|
44
|
-
isExpanded: boolean;
|
|
45
|
-
hasToggle: boolean;
|
|
46
|
-
previousWidth: number | undefined;
|
|
47
|
-
}
|
|
48
|
-
declare class ExpandableSectionForSyntaxHighlighter extends Component<ExpandableSectionProps, ExpandableSectionState> {
|
|
49
|
-
static displayName: string;
|
|
50
|
-
constructor(props: ExpandableSectionProps);
|
|
51
|
-
expandableContentRef: import("react").RefObject<HTMLDivElement>;
|
|
52
|
-
observer: any;
|
|
53
|
-
static defaultProps: PickOptional<ExpandableSectionProps>;
|
|
54
|
-
componentDidMount(): void;
|
|
55
|
-
componentDidUpdate(prevProps: ExpandableSectionProps): void;
|
|
56
|
-
componentWillUnmount(): void;
|
|
57
|
-
checkToggleVisibility: () => void;
|
|
58
|
-
resize: () => void;
|
|
59
|
-
handleResize: (...args: any[]) => void;
|
|
60
|
-
render(): import("react/jsx-runtime").JSX.Element;
|
|
61
|
-
}
|
|
62
|
-
export { ExpandableSectionForSyntaxHighlighter };
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
-
var t = {};
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
-
import { Component, createRef } from 'react';
|
|
14
|
-
import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section';
|
|
15
|
-
import { css } from '@patternfly/react-styles';
|
|
16
|
-
import lineClamp from '@patternfly/react-tokens/dist/esm/c_expandable_section_m_truncate__content_LineClamp';
|
|
17
|
-
import { debounce, getResizeObserver, getUniqueId } from '@patternfly/react-core';
|
|
18
|
-
export var ExpandableSectionVariant;
|
|
19
|
-
(function (ExpandableSectionVariant) {
|
|
20
|
-
ExpandableSectionVariant["default"] = "default";
|
|
21
|
-
ExpandableSectionVariant["truncate"] = "truncate";
|
|
22
|
-
})(ExpandableSectionVariant || (ExpandableSectionVariant = {}));
|
|
23
|
-
const setLineClamp = (element, lines, language, isExpanded) => {
|
|
24
|
-
if (!element || !lines || lines < 1 || typeof isExpanded === 'undefined') {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (language) {
|
|
28
|
-
const selector = `.language-${language.toLowerCase()}`;
|
|
29
|
-
const childElement = element.querySelector(selector);
|
|
30
|
-
if (!childElement) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (isExpanded) {
|
|
34
|
-
// Reset all truncation-related styles to their default values
|
|
35
|
-
childElement.style.removeProperty('-webkit-line-clamp');
|
|
36
|
-
childElement.style.removeProperty('display');
|
|
37
|
-
childElement.style.removeProperty('-webkit-box-orient');
|
|
38
|
-
childElement.style.removeProperty('overflow');
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
childElement.style.setProperty('-webkit-line-clamp', lines.toString());
|
|
42
|
-
childElement.style.setProperty('display', '-webkit-box');
|
|
43
|
-
childElement.style.setProperty('-webkit-box-orient', 'vertical');
|
|
44
|
-
childElement.style.setProperty('overflow', 'hidden');
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
class ExpandableSectionForSyntaxHighlighter extends Component {
|
|
49
|
-
constructor(props) {
|
|
50
|
-
var _a;
|
|
51
|
-
super(props);
|
|
52
|
-
this.expandableContentRef = createRef();
|
|
53
|
-
/* eslint-disable-next-line */
|
|
54
|
-
this.observer = () => { };
|
|
55
|
-
this.checkToggleVisibility = () => {
|
|
56
|
-
var _a;
|
|
57
|
-
if ((_a = this.expandableContentRef) === null || _a === void 0 ? void 0 : _a.current) {
|
|
58
|
-
const maxLines = this.props.truncateMaxLines || parseInt(lineClamp.value);
|
|
59
|
-
const totalLines = this.expandableContentRef.current.scrollHeight /
|
|
60
|
-
parseInt(getComputedStyle(this.expandableContentRef.current).lineHeight);
|
|
61
|
-
this.setState({
|
|
62
|
-
hasToggle: totalLines > maxLines
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
this.resize = () => {
|
|
67
|
-
if (this.expandableContentRef.current) {
|
|
68
|
-
const { offsetWidth } = this.expandableContentRef.current;
|
|
69
|
-
if (this.state.previousWidth !== offsetWidth) {
|
|
70
|
-
this.setState({ previousWidth: offsetWidth });
|
|
71
|
-
this.checkToggleVisibility();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
this.handleResize = debounce(this.resize, 250);
|
|
76
|
-
this.state = {
|
|
77
|
-
isExpanded: (_a = props.isExpanded) !== null && _a !== void 0 ? _a : false,
|
|
78
|
-
hasToggle: true,
|
|
79
|
-
previousWidth: undefined
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
componentDidMount() {
|
|
83
|
-
if (this.props.variant === ExpandableSectionVariant.truncate) {
|
|
84
|
-
const expandableContent = this.expandableContentRef.current;
|
|
85
|
-
if (expandableContent) {
|
|
86
|
-
this.setState({ previousWidth: expandableContent.offsetWidth });
|
|
87
|
-
this.observer = getResizeObserver(expandableContent, this.handleResize, false);
|
|
88
|
-
if (this.props.truncateMaxLines) {
|
|
89
|
-
setLineClamp(expandableContent, this.props.truncateMaxLines, this.props.language, this.state.isExpanded);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
this.checkToggleVisibility();
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
componentDidUpdate(prevProps) {
|
|
96
|
-
if (this.props.variant === ExpandableSectionVariant.truncate &&
|
|
97
|
-
(prevProps.truncateMaxLines !== this.props.truncateMaxLines ||
|
|
98
|
-
prevProps.children !== this.props.children ||
|
|
99
|
-
prevProps.isExpanded !== this.props.isExpanded)) {
|
|
100
|
-
const expandableContent = this.expandableContentRef.current;
|
|
101
|
-
setLineClamp(expandableContent, this.props.truncateMaxLines, this.props.language, this.props.isExpanded);
|
|
102
|
-
this.checkToggleVisibility();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
componentWillUnmount() {
|
|
106
|
-
if (this.props.variant === ExpandableSectionVariant.truncate) {
|
|
107
|
-
this.observer();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
render() {
|
|
111
|
-
const _a = this.props, { className, children, isExpanded, isDetached, displaySize, isWidthLimited, isIndented, contentId, toggleId, variant,
|
|
112
|
-
// Gets rid of console error about it being on a DOM element
|
|
113
|
-
// eslint-disable-next-line
|
|
114
|
-
truncateMaxLines } = _a, props = __rest(_a, ["className", "children", "isExpanded", "isDetached", "displaySize", "isWidthLimited", "isIndented", "contentId", "toggleId", "variant", "truncateMaxLines"]);
|
|
115
|
-
if (isDetached && !toggleId) {
|
|
116
|
-
/* eslint-disable no-console */
|
|
117
|
-
console.warn('ExpandableSection: The toggleId value must be passed in and must match the toggleId of the ExpandableSectionToggle.');
|
|
118
|
-
}
|
|
119
|
-
const uniqueContentId = contentId || getUniqueId('expandable-section-content');
|
|
120
|
-
const uniqueToggleId = toggleId || getUniqueId('expandable-section-toggle');
|
|
121
|
-
return (_jsx("div", Object.assign({ className: css(styles.expandableSection, isExpanded && styles.modifiers.expanded, displaySize === 'lg' && styles.modifiers.displayLg, isWidthLimited && styles.modifiers.limitWidth, isIndented && styles.modifiers.indented, variant === ExpandableSectionVariant.truncate && styles.modifiers.truncate, className) }, props, { children: _jsx("div", { ref: this.expandableContentRef, className: css(styles.expandableSectionContent), hidden: variant !== ExpandableSectionVariant.truncate && !isExpanded, id: uniqueContentId, "aria-labelledby": uniqueToggleId, role: "region", children: children }) })));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
ExpandableSectionForSyntaxHighlighter.displayName = 'ExpandableSection';
|
|
125
|
-
ExpandableSectionForSyntaxHighlighter.defaultProps = {
|
|
126
|
-
className: '',
|
|
127
|
-
isDetached: false,
|
|
128
|
-
displaySize: 'default',
|
|
129
|
-
isWidthLimited: false,
|
|
130
|
-
isIndented: false,
|
|
131
|
-
variant: 'default'
|
|
132
|
-
};
|
|
133
|
-
export { ExpandableSectionForSyntaxHighlighter };
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { Component, createRef } from 'react';
|
|
2
|
-
import styles from '@patternfly/react-styles/css/components/ExpandableSection/expandable-section';
|
|
3
|
-
import { css } from '@patternfly/react-styles';
|
|
4
|
-
import lineClamp from '@patternfly/react-tokens/dist/esm/c_expandable_section_m_truncate__content_LineClamp';
|
|
5
|
-
import { debounce, getResizeObserver, getUniqueId, PickOptional } from '@patternfly/react-core';
|
|
6
|
-
|
|
7
|
-
export enum ExpandableSectionVariant {
|
|
8
|
-
default = 'default',
|
|
9
|
-
truncate = 'truncate'
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** The main expandable section component. */
|
|
13
|
-
|
|
14
|
-
export interface ExpandableSectionProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onToggle'> {
|
|
15
|
-
/** Content rendered inside the expandable section. */
|
|
16
|
-
children?: React.ReactNode;
|
|
17
|
-
/** Additional classes added to the expandable section. */
|
|
18
|
-
className?: string;
|
|
19
|
-
/** Id of the content of the expandable section. When passing in the isDetached property, this
|
|
20
|
-
* property's value should match the contentId property of the expandable section toggle sub-component.
|
|
21
|
-
*/
|
|
22
|
-
contentId?: string;
|
|
23
|
-
/** Id of the toggle of the expandable section, which provides an accessible name to the
|
|
24
|
-
* expandable section content via the aria-labelledby attribute. When the isDetached property
|
|
25
|
-
* is also passed in, the value of this property must match the toggleId property of the
|
|
26
|
-
* expandable section toggle sub-component.
|
|
27
|
-
*/
|
|
28
|
-
toggleId?: string;
|
|
29
|
-
/** Display size variant. Set to "lg" for disclosure styling. */
|
|
30
|
-
displaySize?: 'default' | 'lg';
|
|
31
|
-
/** Indicates the expandable section has a detached toggle. */
|
|
32
|
-
isDetached?: boolean;
|
|
33
|
-
/** Flag to indicate if the content is expanded. */
|
|
34
|
-
isExpanded?: boolean;
|
|
35
|
-
/** Flag to indicate if the content is indented. */
|
|
36
|
-
isIndented?: boolean;
|
|
37
|
-
/** Flag to indicate the width of the component is limited. Set to "true" for disclosure styling. */
|
|
38
|
-
isWidthLimited?: boolean;
|
|
39
|
-
/** Truncates the expandable content to the specified number of lines when using the
|
|
40
|
-
* "truncate" variant.
|
|
41
|
-
*/
|
|
42
|
-
truncateMaxLines?: number;
|
|
43
|
-
/** Determines the variant of the expandable section. When passing in "truncate" as the
|
|
44
|
-
* variant, the expandable content will be truncated after 3 lines by default.
|
|
45
|
-
*/
|
|
46
|
-
variant?: 'default' | 'truncate';
|
|
47
|
-
language?: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface ExpandableSectionState {
|
|
51
|
-
isExpanded: boolean;
|
|
52
|
-
hasToggle: boolean;
|
|
53
|
-
previousWidth: number | undefined;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const setLineClamp = (element: HTMLDivElement | null, lines?: number, language?: string, isExpanded?: boolean) => {
|
|
57
|
-
if (!element || !lines || lines < 1 || typeof isExpanded === 'undefined') {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (language) {
|
|
62
|
-
const selector = `.language-${language.toLowerCase()}`;
|
|
63
|
-
const childElement = element.querySelector(selector) as HTMLDivElement;
|
|
64
|
-
|
|
65
|
-
if (!childElement) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (isExpanded) {
|
|
69
|
-
// Reset all truncation-related styles to their default values
|
|
70
|
-
childElement.style.removeProperty('-webkit-line-clamp');
|
|
71
|
-
childElement.style.removeProperty('display');
|
|
72
|
-
childElement.style.removeProperty('-webkit-box-orient');
|
|
73
|
-
childElement.style.removeProperty('overflow');
|
|
74
|
-
} else {
|
|
75
|
-
childElement.style.setProperty('-webkit-line-clamp', lines.toString());
|
|
76
|
-
childElement.style.setProperty('display', '-webkit-box');
|
|
77
|
-
childElement.style.setProperty('-webkit-box-orient', 'vertical');
|
|
78
|
-
childElement.style.setProperty('overflow', 'hidden');
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
class ExpandableSectionForSyntaxHighlighter extends Component<ExpandableSectionProps, ExpandableSectionState> {
|
|
84
|
-
static displayName = 'ExpandableSection';
|
|
85
|
-
constructor(props: ExpandableSectionProps) {
|
|
86
|
-
super(props);
|
|
87
|
-
|
|
88
|
-
this.state = {
|
|
89
|
-
isExpanded: props.isExpanded ?? false,
|
|
90
|
-
hasToggle: true,
|
|
91
|
-
previousWidth: undefined
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
expandableContentRef = createRef<HTMLDivElement>();
|
|
96
|
-
/* eslint-disable-next-line */
|
|
97
|
-
observer: any = () => {};
|
|
98
|
-
|
|
99
|
-
static defaultProps: PickOptional<ExpandableSectionProps> = {
|
|
100
|
-
className: '',
|
|
101
|
-
isDetached: false,
|
|
102
|
-
displaySize: 'default',
|
|
103
|
-
isWidthLimited: false,
|
|
104
|
-
isIndented: false,
|
|
105
|
-
variant: 'default'
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
componentDidMount() {
|
|
109
|
-
if (this.props.variant === ExpandableSectionVariant.truncate) {
|
|
110
|
-
const expandableContent = this.expandableContentRef.current;
|
|
111
|
-
if (expandableContent) {
|
|
112
|
-
this.setState({ previousWidth: expandableContent.offsetWidth });
|
|
113
|
-
this.observer = getResizeObserver(expandableContent, this.handleResize, false);
|
|
114
|
-
|
|
115
|
-
if (this.props.truncateMaxLines) {
|
|
116
|
-
setLineClamp(expandableContent, this.props.truncateMaxLines, this.props.language, this.state.isExpanded);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
this.checkToggleVisibility();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
componentDidUpdate(prevProps: ExpandableSectionProps) {
|
|
125
|
-
if (
|
|
126
|
-
this.props.variant === ExpandableSectionVariant.truncate &&
|
|
127
|
-
(prevProps.truncateMaxLines !== this.props.truncateMaxLines ||
|
|
128
|
-
prevProps.children !== this.props.children ||
|
|
129
|
-
prevProps.isExpanded !== this.props.isExpanded)
|
|
130
|
-
) {
|
|
131
|
-
const expandableContent = this.expandableContentRef.current;
|
|
132
|
-
setLineClamp(expandableContent, this.props.truncateMaxLines, this.props.language, this.props.isExpanded);
|
|
133
|
-
this.checkToggleVisibility();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
componentWillUnmount() {
|
|
138
|
-
if (this.props.variant === ExpandableSectionVariant.truncate) {
|
|
139
|
-
this.observer();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
checkToggleVisibility = () => {
|
|
144
|
-
if (this.expandableContentRef?.current) {
|
|
145
|
-
const maxLines = this.props.truncateMaxLines || parseInt(lineClamp.value);
|
|
146
|
-
const totalLines =
|
|
147
|
-
this.expandableContentRef.current.scrollHeight /
|
|
148
|
-
parseInt(getComputedStyle(this.expandableContentRef.current).lineHeight);
|
|
149
|
-
|
|
150
|
-
this.setState({
|
|
151
|
-
hasToggle: totalLines > maxLines
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
resize = () => {
|
|
157
|
-
if (this.expandableContentRef.current) {
|
|
158
|
-
const { offsetWidth } = this.expandableContentRef.current;
|
|
159
|
-
if (this.state.previousWidth !== offsetWidth) {
|
|
160
|
-
this.setState({ previousWidth: offsetWidth });
|
|
161
|
-
this.checkToggleVisibility();
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
handleResize = debounce(this.resize, 250);
|
|
166
|
-
|
|
167
|
-
render() {
|
|
168
|
-
const {
|
|
169
|
-
className,
|
|
170
|
-
children,
|
|
171
|
-
isExpanded,
|
|
172
|
-
isDetached,
|
|
173
|
-
displaySize,
|
|
174
|
-
isWidthLimited,
|
|
175
|
-
isIndented,
|
|
176
|
-
contentId,
|
|
177
|
-
toggleId,
|
|
178
|
-
variant,
|
|
179
|
-
// Gets rid of console error about it being on a DOM element
|
|
180
|
-
// eslint-disable-next-line
|
|
181
|
-
truncateMaxLines,
|
|
182
|
-
...props
|
|
183
|
-
} = this.props;
|
|
184
|
-
|
|
185
|
-
if (isDetached && !toggleId) {
|
|
186
|
-
/* eslint-disable no-console */
|
|
187
|
-
console.warn(
|
|
188
|
-
'ExpandableSection: The toggleId value must be passed in and must match the toggleId of the ExpandableSectionToggle.'
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const uniqueContentId = contentId || getUniqueId('expandable-section-content');
|
|
193
|
-
const uniqueToggleId = toggleId || getUniqueId('expandable-section-toggle');
|
|
194
|
-
|
|
195
|
-
return (
|
|
196
|
-
<div
|
|
197
|
-
className={css(
|
|
198
|
-
styles.expandableSection,
|
|
199
|
-
isExpanded && styles.modifiers.expanded,
|
|
200
|
-
displaySize === 'lg' && styles.modifiers.displayLg,
|
|
201
|
-
isWidthLimited && styles.modifiers.limitWidth,
|
|
202
|
-
isIndented && styles.modifiers.indented,
|
|
203
|
-
variant === ExpandableSectionVariant.truncate && styles.modifiers.truncate,
|
|
204
|
-
className
|
|
205
|
-
)}
|
|
206
|
-
{...props}
|
|
207
|
-
>
|
|
208
|
-
<div
|
|
209
|
-
ref={this.expandableContentRef}
|
|
210
|
-
className={css(styles.expandableSectionContent)}
|
|
211
|
-
hidden={variant !== ExpandableSectionVariant.truncate && !isExpanded}
|
|
212
|
-
id={uniqueContentId}
|
|
213
|
-
aria-labelledby={uniqueToggleId}
|
|
214
|
-
role="region"
|
|
215
|
-
>
|
|
216
|
-
{children}
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export { ExpandableSectionForSyntaxHighlighter };
|