@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
|
@@ -10,14 +10,18 @@ import {
|
|
|
10
10
|
ButtonVariant,
|
|
11
11
|
Card,
|
|
12
12
|
CardBody,
|
|
13
|
+
CardBodyProps,
|
|
13
14
|
CardFooter,
|
|
15
|
+
CardFooterProps,
|
|
14
16
|
CardProps,
|
|
15
17
|
CardTitle,
|
|
18
|
+
CardTitleProps,
|
|
16
19
|
ExpandableSection,
|
|
17
20
|
ExpandableSectionVariant,
|
|
18
21
|
Icon,
|
|
19
22
|
pluralize,
|
|
20
|
-
Truncate
|
|
23
|
+
Truncate,
|
|
24
|
+
TruncateProps
|
|
21
25
|
} from '@patternfly/react-core';
|
|
22
26
|
import { ExternalLinkSquareAltIcon } from '@patternfly/react-icons';
|
|
23
27
|
|
|
@@ -34,6 +38,8 @@ export interface SourcesCardProps extends CardProps {
|
|
|
34
38
|
sources: {
|
|
35
39
|
/** Title of sources card */
|
|
36
40
|
title?: string;
|
|
41
|
+
/** Subtitle of sources card */
|
|
42
|
+
subtitle?: string;
|
|
37
43
|
/** Link to source */
|
|
38
44
|
link: string;
|
|
39
45
|
/** Body of sources card */
|
|
@@ -46,6 +52,10 @@ export interface SourcesCardProps extends CardProps {
|
|
|
46
52
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
47
53
|
/** Any additional props applied to the title of the Sources card */
|
|
48
54
|
titleProps?: ButtonProps;
|
|
55
|
+
/** Custom footer applied to the Sources card */
|
|
56
|
+
footer?: React.ReactNode;
|
|
57
|
+
/** Additional props passed to Truncate component */
|
|
58
|
+
truncateProps?: TruncateProps;
|
|
49
59
|
}[];
|
|
50
60
|
/** Label for the English word "source" */
|
|
51
61
|
sourceWord?: string;
|
|
@@ -65,6 +75,12 @@ export interface SourcesCardProps extends CardProps {
|
|
|
65
75
|
showMoreWords?: string;
|
|
66
76
|
/** Label for English words "show less" */
|
|
67
77
|
showLessWords?: string;
|
|
78
|
+
/** Additional props passed to card title */
|
|
79
|
+
cardTitleProps?: CardTitleProps;
|
|
80
|
+
/** Additional props passed to card body */
|
|
81
|
+
cardBodyProps?: CardBodyProps;
|
|
82
|
+
/** Additional props passed to card footer */
|
|
83
|
+
cardFooterProps?: CardFooterProps;
|
|
68
84
|
}
|
|
69
85
|
|
|
70
86
|
const SourcesCard: FunctionComponent<SourcesCardProps> = ({
|
|
@@ -82,6 +98,9 @@ const SourcesCard: FunctionComponent<SourcesCardProps> = ({
|
|
|
82
98
|
showMoreWords = 'show more',
|
|
83
99
|
showLessWords = 'show less',
|
|
84
100
|
isCompact,
|
|
101
|
+
cardTitleProps,
|
|
102
|
+
cardBodyProps,
|
|
103
|
+
cardFooterProps,
|
|
85
104
|
...props
|
|
86
105
|
}: SourcesCardProps) => {
|
|
87
106
|
const [page, setPage] = useState(1);
|
|
@@ -96,9 +115,9 @@ const SourcesCard: FunctionComponent<SourcesCardProps> = ({
|
|
|
96
115
|
onSetPage && onSetPage(_evt, newPage);
|
|
97
116
|
};
|
|
98
117
|
|
|
99
|
-
const renderTitle = (title?: string) => {
|
|
118
|
+
const renderTitle = (title?: string, truncateProps?: TruncateProps) => {
|
|
100
119
|
if (title) {
|
|
101
|
-
return <Truncate content={title} />;
|
|
120
|
+
return <Truncate content={title} {...truncateProps} />;
|
|
102
121
|
}
|
|
103
122
|
return `Source ${page}`;
|
|
104
123
|
};
|
|
@@ -107,24 +126,32 @@ const SourcesCard: FunctionComponent<SourcesCardProps> = ({
|
|
|
107
126
|
<div className="pf-chatbot__source">
|
|
108
127
|
<span>{pluralize(sources.length, sourceWord, sourceWordPlural)}</span>
|
|
109
128
|
<Card isCompact={isCompact} className="pf-chatbot__sources-card" {...props}>
|
|
110
|
-
<CardTitle className="pf-chatbot__sources-card-title">
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
<CardTitle className="pf-chatbot__sources-card-title" {...cardTitleProps}>
|
|
130
|
+
<div className="pf-chatbot__sources-card-title-container">
|
|
131
|
+
<Button
|
|
132
|
+
component="a"
|
|
133
|
+
variant={ButtonVariant.link}
|
|
134
|
+
href={sources[page - 1].link}
|
|
135
|
+
icon={sources[page - 1].isExternal ? <ExternalLinkSquareAltIcon /> : undefined}
|
|
136
|
+
iconPosition="end"
|
|
137
|
+
isInline
|
|
138
|
+
rel={sources[page - 1].isExternal ? 'noreferrer' : undefined}
|
|
139
|
+
target={sources[page - 1].isExternal ? '_blank' : undefined}
|
|
140
|
+
onClick={sources[page - 1].onClick ?? undefined}
|
|
141
|
+
{...sources[page - 1].titleProps}
|
|
142
|
+
>
|
|
143
|
+
{renderTitle(sources[page - 1].title, sources[page - 1].truncateProps)}
|
|
144
|
+
</Button>
|
|
145
|
+
{sources[page - 1].subtitle && (
|
|
146
|
+
<span className="pf-chatbot__sources-card-subtitle">{sources[page - 1].subtitle}</span>
|
|
147
|
+
)}
|
|
148
|
+
</div>
|
|
125
149
|
</CardTitle>
|
|
126
150
|
{sources[page - 1].body && (
|
|
127
|
-
<CardBody
|
|
151
|
+
<CardBody
|
|
152
|
+
className={`pf-chatbot__sources-card-body ${sources[page - 1].footer ? 'pf-chatbot__compact-sources-card-body' : undefined}`}
|
|
153
|
+
{...cardBodyProps}
|
|
154
|
+
>
|
|
128
155
|
{sources[page - 1].hasShowMore ? (
|
|
129
156
|
// prevents extra VO announcements of button text - parent Message has aria-live
|
|
130
157
|
<div aria-live="off">
|
|
@@ -143,68 +170,77 @@ const SourcesCard: FunctionComponent<SourcesCardProps> = ({
|
|
|
143
170
|
)}
|
|
144
171
|
</CardBody>
|
|
145
172
|
)}
|
|
146
|
-
{sources
|
|
147
|
-
<CardFooter className="pf-chatbot__sources-card-footer
|
|
148
|
-
|
|
149
|
-
<nav className={`pf-chatbot__sources-card-footer-buttons ${className}`} aria-label={paginationAriaLabel}>
|
|
150
|
-
<Button
|
|
151
|
-
variant={ButtonVariant.plain}
|
|
152
|
-
isDisabled={isDisabled || page === 1}
|
|
153
|
-
data-action="previous"
|
|
154
|
-
onClick={(event) => {
|
|
155
|
-
const newPage = page >= 1 ? page - 1 : 1;
|
|
156
|
-
onPreviousClick && onPreviousClick(event, newPage);
|
|
157
|
-
handleNewPage(event, newPage);
|
|
158
|
-
}}
|
|
159
|
-
aria-label={toPreviousPageAriaLabel}
|
|
160
|
-
>
|
|
161
|
-
<Icon iconSize="lg">
|
|
162
|
-
{/* these are inline because the viewBox that works in a round icon is different than the PatternFly default */}
|
|
163
|
-
<svg
|
|
164
|
-
className="pf-v6-svg"
|
|
165
|
-
viewBox="0 0 280 500"
|
|
166
|
-
fill="currentColor"
|
|
167
|
-
aria-hidden="true"
|
|
168
|
-
role="img"
|
|
169
|
-
width="1em"
|
|
170
|
-
height="1em"
|
|
171
|
-
>
|
|
172
|
-
<path d="M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z"></path>
|
|
173
|
-
</svg>
|
|
174
|
-
</Icon>
|
|
175
|
-
</Button>
|
|
176
|
-
<span aria-hidden="true">
|
|
177
|
-
{page}/{sources.length}
|
|
178
|
-
</span>
|
|
179
|
-
<Button
|
|
180
|
-
variant={ButtonVariant.plain}
|
|
181
|
-
isDisabled={isDisabled || page === sources.length}
|
|
182
|
-
aria-label={toNextPageAriaLabel}
|
|
183
|
-
data-action="next"
|
|
184
|
-
onClick={(event) => {
|
|
185
|
-
const newPage = page + 1 <= sources.length ? page + 1 : sources.length;
|
|
186
|
-
onNextClick && onNextClick(event, newPage);
|
|
187
|
-
handleNewPage(event, newPage);
|
|
188
|
-
}}
|
|
189
|
-
>
|
|
190
|
-
<Icon isInline iconSize="lg">
|
|
191
|
-
{/* these are inline because the viewBox that works in a round icon is different than the PatternFly default */}
|
|
192
|
-
<svg
|
|
193
|
-
className="pf-v6-svg"
|
|
194
|
-
viewBox="0 0 180 500"
|
|
195
|
-
fill="currentColor"
|
|
196
|
-
aria-hidden="true"
|
|
197
|
-
role="img"
|
|
198
|
-
width="1em"
|
|
199
|
-
height="1em"
|
|
200
|
-
>
|
|
201
|
-
<path d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path>
|
|
202
|
-
</svg>
|
|
203
|
-
</Icon>
|
|
204
|
-
</Button>
|
|
205
|
-
</nav>
|
|
206
|
-
</div>
|
|
173
|
+
{sources[page - 1].footer ? (
|
|
174
|
+
<CardFooter className="pf-chatbot__sources-card-footer" {...cardFooterProps}>
|
|
175
|
+
{sources[page - 1].footer}
|
|
207
176
|
</CardFooter>
|
|
177
|
+
) : (
|
|
178
|
+
sources.length > 1 && (
|
|
179
|
+
<CardFooter className="pf-chatbot__sources-card-footer-container" {...cardFooterProps}>
|
|
180
|
+
<div className="pf-chatbot__sources-card-footer">
|
|
181
|
+
<nav
|
|
182
|
+
className={`pf-chatbot__sources-card-footer-buttons ${className}`}
|
|
183
|
+
aria-label={paginationAriaLabel}
|
|
184
|
+
>
|
|
185
|
+
<Button
|
|
186
|
+
variant={ButtonVariant.plain}
|
|
187
|
+
isDisabled={isDisabled || page === 1}
|
|
188
|
+
data-action="previous"
|
|
189
|
+
onClick={(event) => {
|
|
190
|
+
const newPage = page >= 1 ? page - 1 : 1;
|
|
191
|
+
onPreviousClick && onPreviousClick(event, newPage);
|
|
192
|
+
handleNewPage(event, newPage);
|
|
193
|
+
}}
|
|
194
|
+
aria-label={toPreviousPageAriaLabel}
|
|
195
|
+
>
|
|
196
|
+
<Icon iconSize="lg">
|
|
197
|
+
{/* these are inline because the viewBox that works in a round icon is different than the PatternFly default */}
|
|
198
|
+
<svg
|
|
199
|
+
className="pf-v6-svg"
|
|
200
|
+
viewBox="0 0 280 500"
|
|
201
|
+
fill="currentColor"
|
|
202
|
+
aria-hidden="true"
|
|
203
|
+
role="img"
|
|
204
|
+
width="1em"
|
|
205
|
+
height="1em"
|
|
206
|
+
>
|
|
207
|
+
<path d="M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z"></path>
|
|
208
|
+
</svg>
|
|
209
|
+
</Icon>
|
|
210
|
+
</Button>
|
|
211
|
+
<span aria-hidden="true">
|
|
212
|
+
{page}/{sources.length}
|
|
213
|
+
</span>
|
|
214
|
+
<Button
|
|
215
|
+
variant={ButtonVariant.plain}
|
|
216
|
+
isDisabled={isDisabled || page === sources.length}
|
|
217
|
+
aria-label={toNextPageAriaLabel}
|
|
218
|
+
data-action="next"
|
|
219
|
+
onClick={(event) => {
|
|
220
|
+
const newPage = page + 1 <= sources.length ? page + 1 : sources.length;
|
|
221
|
+
onNextClick && onNextClick(event, newPage);
|
|
222
|
+
handleNewPage(event, newPage);
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
<Icon isInline iconSize="lg">
|
|
226
|
+
{/* these are inline because the viewBox that works in a round icon is different than the PatternFly default */}
|
|
227
|
+
<svg
|
|
228
|
+
className="pf-v6-svg"
|
|
229
|
+
viewBox="0 0 180 500"
|
|
230
|
+
fill="currentColor"
|
|
231
|
+
aria-hidden="true"
|
|
232
|
+
role="img"
|
|
233
|
+
width="1em"
|
|
234
|
+
height="1em"
|
|
235
|
+
>
|
|
236
|
+
<path d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path>
|
|
237
|
+
</svg>
|
|
238
|
+
</Icon>
|
|
239
|
+
</Button>
|
|
240
|
+
</nav>
|
|
241
|
+
</div>
|
|
242
|
+
</CardFooter>
|
|
243
|
+
)
|
|
208
244
|
)}
|
|
209
245
|
</Card>
|
|
210
246
|
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.pf-chatbot__tool-response {
|
|
2
|
+
--pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--control--read-only);
|
|
3
|
+
overflow: unset;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.pf-chatbot__tool-response-expandable-section {
|
|
7
|
+
--pf-v6-c-expandable-section--Gap: var(--pf-t--global--spacer--xs);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.pf-chatbot__tool-response-section {
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
gap: var(--pf-t--global--spacer--xs);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.pf-chatbot__tool-response-subheading {
|
|
17
|
+
font-size: var(--pf-t--global--font--size--body--sm);
|
|
18
|
+
font-weight: var(--pf-t--global--font--weight--body--default);
|
|
19
|
+
color: var(--pf-t--global--text--color--subtle);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.pf-chatbot__tool-response-body {
|
|
23
|
+
color: var(--pf-t--global--text--color--subtle);
|
|
24
|
+
margin-block-end: var(--pf-t--global--spacer--xs);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.pf-chatbot__tool-response-card {
|
|
28
|
+
--pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--control--read-only);
|
|
29
|
+
--pf-v6-c-card--first-child--PaddingBlockStart: var(--pf-t--global--spacer--sm);
|
|
30
|
+
--pf-v6-c-card__title--not--last-child--PaddingBlockEnd: var(--pf-t--global--spacer--sm);
|
|
31
|
+
--pf-v6-c-card--c-divider--child--PaddingBlockStart: var(--pf-t--global--spacer--sm);
|
|
32
|
+
|
|
33
|
+
.pf-v6-c-divider {
|
|
34
|
+
--pf-v6-c-divider--Color: var(--pf-t--global--border--color--control--read-only);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import ToolResponse from './ToolResponse';
|
|
4
|
+
|
|
5
|
+
describe('ToolResponse', () => {
|
|
6
|
+
const defaultProps = {
|
|
7
|
+
toggleContent: 'Tool response: toolName',
|
|
8
|
+
cardTitle: 'Title',
|
|
9
|
+
cardBody: 'Body'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
it('should render with required props only', () => {
|
|
13
|
+
render(<ToolResponse {...defaultProps} />);
|
|
14
|
+
expect(screen.getByText('Title')).toBeTruthy();
|
|
15
|
+
expect(screen.getByText('Body')).toBeTruthy();
|
|
16
|
+
expect(screen.getByText('Tool response: toolName')).toBeTruthy();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should render subheading when provided', () => {
|
|
20
|
+
const subheading = 'Tool execution result';
|
|
21
|
+
render(<ToolResponse {...defaultProps} subheading={subheading} />);
|
|
22
|
+
expect(screen.getByText(subheading)).toBeTruthy();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should render body content when provided', () => {
|
|
26
|
+
const body = 'This is the tool response body content';
|
|
27
|
+
render(<ToolResponse {...defaultProps} body={body} />);
|
|
28
|
+
expect(screen.getByText(body)).toBeTruthy();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should render with complex content including React elements', () => {
|
|
32
|
+
const body = (
|
|
33
|
+
<div>
|
|
34
|
+
<p>Complex body content</p>
|
|
35
|
+
<ul>
|
|
36
|
+
<li>Item 1</li>
|
|
37
|
+
<li>Item 2</li>
|
|
38
|
+
</ul>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
const cardTitle = <strong>API Response</strong>;
|
|
42
|
+
const cardBody = (
|
|
43
|
+
<div>
|
|
44
|
+
<code>{"{ status: 'success' }"}</code>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
render(<ToolResponse {...defaultProps} body={body} cardTitle={cardTitle} cardBody={cardBody} />);
|
|
49
|
+
expect(screen.getByText('Complex body content')).toBeTruthy();
|
|
50
|
+
expect(screen.getByText('Item 1')).toBeTruthy();
|
|
51
|
+
expect(screen.getByText('Item 2')).toBeTruthy();
|
|
52
|
+
expect(screen.getByText('API Response')).toBeTruthy();
|
|
53
|
+
expect(screen.getByText("{ status: 'success' }")).toBeTruthy();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should apply custom className from cardProps', () => {
|
|
57
|
+
const { container } = render(
|
|
58
|
+
<ToolResponse {...defaultProps} cardProps={{ className: 'custom-tool-response-class' }} />
|
|
59
|
+
);
|
|
60
|
+
expect(container.querySelector('.custom-tool-response-class')).toBeTruthy();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should pass through expandableSectionProps', () => {
|
|
64
|
+
render(<ToolResponse {...defaultProps} expandableSectionProps={{ className: 'custom-expandable-class' }} />);
|
|
65
|
+
expect(document.querySelector('.custom-expandable-class')).toBeTruthy();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should pass through toolResponseCardProps', () => {
|
|
69
|
+
render(<ToolResponse {...defaultProps} toolResponseCardProps={{ className: 'custom-card-class' }} />);
|
|
70
|
+
expect(document.querySelector('.custom-card-class')).toBeTruthy();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should not render subheading span when subheading is not provided', () => {
|
|
74
|
+
const { container } = render(<ToolResponse {...defaultProps} />);
|
|
75
|
+
const subheadingContainer = container.querySelector('.pf-chatbot__tool-response-subheading');
|
|
76
|
+
expect(subheadingContainer).toBeFalsy();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tool Response Card
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import {
|
|
5
|
+
Card,
|
|
6
|
+
CardBody,
|
|
7
|
+
CardBodyProps,
|
|
8
|
+
CardProps,
|
|
9
|
+
CardTitle,
|
|
10
|
+
CardTitleProps,
|
|
11
|
+
Divider,
|
|
12
|
+
DividerProps,
|
|
13
|
+
ExpandableSection,
|
|
14
|
+
ExpandableSectionProps
|
|
15
|
+
} from '@patternfly/react-core';
|
|
16
|
+
import { useState, type FunctionComponent } from 'react';
|
|
17
|
+
|
|
18
|
+
export interface ToolResponseProps {
|
|
19
|
+
/** Toggle content shown for expandable section */
|
|
20
|
+
toggleContent: React.ReactNode;
|
|
21
|
+
/** Additional props passed to expandable section */
|
|
22
|
+
expandableSectionProps?: Omit<ExpandableSectionProps, 'ref'>;
|
|
23
|
+
/** Subheading rendered inside expandable section */
|
|
24
|
+
subheading?: string;
|
|
25
|
+
/** Body text rendered inside expandable section */
|
|
26
|
+
body?: React.ReactNode | string;
|
|
27
|
+
/** Content passed into tool response card body */
|
|
28
|
+
cardBody: React.ReactNode;
|
|
29
|
+
/** Content passed into tool response card title */
|
|
30
|
+
cardTitle: React.ReactNode;
|
|
31
|
+
/** Additional props passed to main card */
|
|
32
|
+
cardProps?: CardProps;
|
|
33
|
+
/** Additional props passed to main card body */
|
|
34
|
+
cardBodyProps?: CardBodyProps;
|
|
35
|
+
/** Additional props passed to tool response card */
|
|
36
|
+
toolResponseCardProps?: CardProps;
|
|
37
|
+
/** Additional props passed to tool response card body */
|
|
38
|
+
toolResponseCardBodyProps?: CardBodyProps;
|
|
39
|
+
/** Additional props passed to tool response card divider */
|
|
40
|
+
toolResponseCardDividerProps?: DividerProps;
|
|
41
|
+
/** Additional props passed to tool response card title */
|
|
42
|
+
toolResponseCardTitleProps?: CardTitleProps;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const ToolResponse: FunctionComponent<ToolResponseProps> = ({
|
|
46
|
+
body,
|
|
47
|
+
cardProps,
|
|
48
|
+
expandableSectionProps,
|
|
49
|
+
subheading,
|
|
50
|
+
cardBody,
|
|
51
|
+
cardTitle,
|
|
52
|
+
cardBodyProps,
|
|
53
|
+
toggleContent,
|
|
54
|
+
toolResponseCardBodyProps,
|
|
55
|
+
toolResponseCardDividerProps,
|
|
56
|
+
toolResponseCardProps,
|
|
57
|
+
toolResponseCardTitleProps
|
|
58
|
+
}: ToolResponseProps) => {
|
|
59
|
+
const [isExpanded, setIsExpanded] = useState(true);
|
|
60
|
+
|
|
61
|
+
const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => {
|
|
62
|
+
setIsExpanded(isExpanded);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Card isCompact className="pf-chatbot__tool-response" {...cardProps}>
|
|
67
|
+
<CardBody {...cardBodyProps}>
|
|
68
|
+
<ExpandableSection
|
|
69
|
+
toggleContent={toggleContent}
|
|
70
|
+
onToggle={onToggle}
|
|
71
|
+
isExpanded={isExpanded}
|
|
72
|
+
isIndented
|
|
73
|
+
className="pf-chatbot__tool-response-expandable-section"
|
|
74
|
+
{...expandableSectionProps}
|
|
75
|
+
>
|
|
76
|
+
<div className="pf-chatbot__tool-response-section">
|
|
77
|
+
{subheading && (
|
|
78
|
+
<div className="pf-chatbot__tool-response-subheading">
|
|
79
|
+
<span>{subheading}</span>
|
|
80
|
+
</div>
|
|
81
|
+
)}
|
|
82
|
+
{body && <div className="pf-chatbot__tool-response-body">{body}</div>}
|
|
83
|
+
<Card isCompact className="pf-chatbot__tool-response-card" {...toolResponseCardProps}>
|
|
84
|
+
<CardTitle {...toolResponseCardTitleProps}>{cardTitle}</CardTitle>
|
|
85
|
+
<Divider {...toolResponseCardDividerProps} />
|
|
86
|
+
<CardBody {...toolResponseCardBodyProps}>{cardBody}</CardBody>
|
|
87
|
+
</Card>
|
|
88
|
+
</div>
|
|
89
|
+
</ExpandableSection>
|
|
90
|
+
</CardBody>
|
|
91
|
+
</Card>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default ToolResponse;
|
package/src/index.ts
CHANGED
|
@@ -42,6 +42,9 @@ export * from './CodeModal';
|
|
|
42
42
|
export { default as Compare } from './Compare';
|
|
43
43
|
export * from './Compare';
|
|
44
44
|
|
|
45
|
+
export { default as DeepThinking } from './DeepThinking';
|
|
46
|
+
export * from './DeepThinking';
|
|
47
|
+
|
|
45
48
|
export { default as FileDetails } from './FileDetails';
|
|
46
49
|
export * from './FileDetails';
|
|
47
50
|
|
|
@@ -51,6 +54,12 @@ export * from './FileDetailsLabel';
|
|
|
51
54
|
export { default as FileDropZone } from './FileDropZone';
|
|
52
55
|
export * from './FileDropZone';
|
|
53
56
|
|
|
57
|
+
export { default as FilePreview } from './FilePreview';
|
|
58
|
+
export * from './FilePreview';
|
|
59
|
+
|
|
60
|
+
export { default as ImagePreview } from './ImagePreview';
|
|
61
|
+
export * from './ImagePreview';
|
|
62
|
+
|
|
54
63
|
export { default as LoadingMessage } from './LoadingMessage';
|
|
55
64
|
export * from './LoadingMessage';
|
|
56
65
|
|
|
@@ -84,5 +93,8 @@ export * from './SourcesCard';
|
|
|
84
93
|
export { default as TermsOfUse } from './TermsOfUse';
|
|
85
94
|
export * from './TermsOfUse';
|
|
86
95
|
|
|
96
|
+
export { default as ToolResponse } from './ToolResponse';
|
|
97
|
+
export * from './ToolResponse';
|
|
98
|
+
|
|
87
99
|
export { default as tracking } from './tracking';
|
|
88
100
|
export * from './tracking';
|
package/src/main.scss
CHANGED
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
@import './ChatbotWelcomePrompt/ChatbotWelcomePrompt';
|
|
12
12
|
@import './CodeModal/CodeModal';
|
|
13
13
|
@import './Compare/Compare';
|
|
14
|
+
@import './DeepThinking/DeepThinking';
|
|
14
15
|
@import './FileDetails/FileDetails';
|
|
15
16
|
@import './FileDetailsLabel/FileDetailsLabel';
|
|
16
17
|
@import './FileDropZone/FileDropZone';
|
|
18
|
+
@import './FilePreview/FilePreview.scss';
|
|
19
|
+
@import './ImagePreview/ImagePreview';
|
|
17
20
|
@import './Message/Message';
|
|
18
21
|
@import './Message/CodeBlockMessage/CodeBlockMessage';
|
|
19
22
|
@import './Message/ImageMessage/ImageMessage';
|
|
@@ -33,8 +36,21 @@
|
|
|
33
36
|
@import './SourcesCard/SourcesCard.scss';
|
|
34
37
|
@import './SourceDetailsMenuItem/SourceDetailsMenuItem';
|
|
35
38
|
@import './TermsOfUse/TermsOfUse';
|
|
39
|
+
@import './ToolResponse/ToolResponse';
|
|
36
40
|
|
|
37
41
|
.ws-full-page-utils {
|
|
38
42
|
left: 0 !important;
|
|
39
43
|
right: auto !important;
|
|
40
44
|
}
|
|
45
|
+
|
|
46
|
+
// hide from view but not assistive technologies
|
|
47
|
+
// https://css-tricks.com/inclusively-hidden/
|
|
48
|
+
.pf-chatbot-m-hidden {
|
|
49
|
+
clip: rect(0 0 0 0);
|
|
50
|
+
clip-path: inset(50%);
|
|
51
|
+
height: 1px;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
position: absolute;
|
|
54
|
+
white-space: nowrap;
|
|
55
|
+
width: 1px;
|
|
56
|
+
}
|