botframework-webchat-fluent-theme 4.18.1-main.20240823.c5330cc → 4.18.1-main.20240831.f4058ce
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/botframework-webchat-fluent-theme.css.map +1 -1
- package/dist/botframework-webchat-fluent-theme.development.css.map +1 -1
- package/dist/botframework-webchat-fluent-theme.development.js +8 -8
- package/dist/botframework-webchat-fluent-theme.development.js.map +1 -1
- package/dist/botframework-webchat-fluent-theme.js +1 -1
- package/dist/botframework-webchat-fluent-theme.js.map +1 -1
- package/dist/botframework-webchat-fluent-theme.mjs +1 -1
- package/dist/botframework-webchat-fluent-theme.mjs.map +1 -1
- package/dist/botframework-webchat-fluent-theme.production.min.css.map +1 -1
- package/dist/botframework-webchat-fluent-theme.production.min.js +8 -8
- package/dist/botframework-webchat-fluent-theme.production.min.js.map +1 -1
- package/package.json +4 -4
- package/src/components/activity/ActivityDecorator.tsx +1 -1
- package/src/components/decorator/index.ts +1 -1
- package/src/components/decorator/private/BorderFlair.module.css +548 -0
- package/src/components/decorator/private/BorderFlair.tsx +17 -0
- package/src/components/decorator/private/BorderLoader.module.css +49 -0
- package/src/components/decorator/private/BorderLoader.tsx +19 -0
- package/src/components/decorator/private/Decorator.tsx +20 -0
- package/src/components/linerActivity/index.ts +2 -0
- package/src/components/linerActivity/private/LinerActivity.tsx +20 -0
- package/src/components/linerActivity/private/LinerMessageActivity.module.css +24 -0
- package/src/components/linerActivity/private/isLinerMessageActivity.ts +7 -0
- package/src/components/preChatActivity/PreChatMessageActivity.module.css +4 -0
- package/src/components/preChatActivity/PreChatMessageActivity.tsx +24 -5
- package/src/components/preChatActivity/StarterPromptsCardAction.module.css +26 -2
- package/src/components/preChatActivity/StarterPromptsCardAction.tsx +26 -21
- package/src/components/preChatActivity/StarterPromptsToolbar.tsx +9 -10
- package/src/components/sendBox/ErrorMessage.tsx +15 -4
- package/src/components/sendBox/SendBox.tsx +16 -5
- package/src/components/sendBox/private/useSubmitError.ts +17 -4
- package/src/components/suggestedActions/SuggestedActions.tsx +0 -1
- package/src/components/theme/Theme.module.css +11 -0
- package/src/external.umd/botframework-webchat-component/internal.ts +1 -0
- package/src/private/FluentThemeProvider.tsx +7 -2
- package/src/components/decorator/Decorator.module.css +0 -3
- package/src/components/decorator/Decorator.tsx +0 -31
- package/src/components/decorator/Flair.module.css +0 -4
- package/src/components/decorator/Flair.tsx +0 -12
- package/src/components/decorator/Loader.module.css +0 -3
- package/src/components/decorator/Loader.tsx +0 -17
- /package/src/external.umd/{botframework-webchat-component.ts → botframework-webchat-component/index.ts} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type WebChatActivity } from 'botframework-webchat-core';
|
|
2
|
+
import React, { memo } from 'react';
|
|
3
|
+
import { useStyles } from '../../../styles/index.js';
|
|
4
|
+
import styles from './LinerMessageActivity.module.css';
|
|
5
|
+
|
|
6
|
+
type Props = Readonly<{ activity: WebChatActivity & { type: 'message' } }>;
|
|
7
|
+
|
|
8
|
+
const LinerMessageActivity = ({ activity }: Props) => {
|
|
9
|
+
const classNames = useStyles(styles);
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<div className={classNames['liner-message-activity']} role="separator">
|
|
13
|
+
{activity.text}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
LinerMessageActivity.displayName = 'LinerMessageActivity';
|
|
19
|
+
|
|
20
|
+
export default memo(LinerMessageActivity);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
:global(.webchat-fluent) .liner-message-activity {
|
|
3
|
+
align-items: center;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
color: var(--webchat-colorNeutralForeground3);
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: row;
|
|
8
|
+
font-family: var(--webchat__font--primary);
|
|
9
|
+
font-size: var(--webchat-fontSizeBase200);
|
|
10
|
+
font-weight: var(--webchat-fontWeightRegular);
|
|
11
|
+
gap: var(--webchat-spacingHorizontalM);
|
|
12
|
+
line-height: var(--webchat-lineHeightBase200);
|
|
13
|
+
padding: var(--webchat-spacingVerticalSNudge) var(--webchat-spacingHorizontalM);
|
|
14
|
+
text-align: center;
|
|
15
|
+
width: 100%;
|
|
16
|
+
|
|
17
|
+
&::before, &::after {
|
|
18
|
+
border-top: var(--webchat-strokeWidthThin) solid var(--webchat-colorNeutralStroke2);
|
|
19
|
+
content: "";
|
|
20
|
+
display: flex;
|
|
21
|
+
flex: auto;
|
|
22
|
+
min-width: 8px;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type WebChatActivity } from 'botframework-webchat-core';
|
|
2
|
+
|
|
3
|
+
export default function isLinerMessageActivity(
|
|
4
|
+
activity: undefined | WebChatActivity
|
|
5
|
+
): activity is WebChatActivity & { type: 'message'; from: { role: 'channel' } } {
|
|
6
|
+
return !!(activity && activity.from.role === 'channel' && activity.type === 'message' && 'text' in activity);
|
|
7
|
+
}
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
text-align: center;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
:global(.webchat-fluent) .pre-chat-message-activity__body--placeholder {
|
|
21
|
+
opacity: 60%;
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
:global(.webchat-fluent) .pre-chat-message-activity__body h2 {
|
|
21
25
|
color: var(--webchat-colorNeutralForeground1);
|
|
22
26
|
font-family: inherit;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
/* eslint-disable react/no-danger */
|
|
1
2
|
import { hooks } from 'botframework-webchat-component';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
3
|
+
import cx from 'classnames';
|
|
4
|
+
import { getOrgSchemaMessage, type WebChatActivity } from 'botframework-webchat-core';
|
|
5
|
+
import React, { Fragment, memo, useMemo } from 'react';
|
|
4
6
|
import { useStyles } from '../../styles/index.js';
|
|
5
7
|
import styles from './PreChatMessageActivity.module.css';
|
|
6
8
|
import StarterPromptsToolbar from './StarterPromptsToolbar.js';
|
|
9
|
+
import StarterPromptsCardAction from './StarterPromptsCardAction.js';
|
|
7
10
|
|
|
8
11
|
type Props = Readonly<{ activity: WebChatActivity & { type: 'message' } }>;
|
|
9
12
|
|
|
@@ -18,14 +21,30 @@ const PreChatMessageActivity = ({ activity }: Props) => {
|
|
|
18
21
|
[activity.text, renderMarkdownAsHTML]
|
|
19
22
|
);
|
|
20
23
|
|
|
24
|
+
const entity = getOrgSchemaMessage(activity?.entities || []);
|
|
25
|
+
const isPlaceHolder = entity?.keywords?.includes('PreChatMessage') && entity.creativeWorkStatus === 'Placeholder';
|
|
26
|
+
|
|
21
27
|
return (
|
|
22
28
|
<div className={classNames['pre-chat-message-activity']}>
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
<div
|
|
30
|
+
className={cx(
|
|
31
|
+
classNames['pre-chat-message-activity__body'],
|
|
32
|
+
isPlaceHolder && classNames['pre-chat-message-activity__body--placeholder']
|
|
33
|
+
)}
|
|
34
|
+
dangerouslySetInnerHTML={html}
|
|
35
|
+
/>
|
|
25
36
|
<StarterPromptsToolbar
|
|
26
37
|
cardActions={activity.suggestedActions?.actions || []}
|
|
27
38
|
className={classNames['pre-chat-message-activity__toolbar']}
|
|
28
|
-
|
|
39
|
+
>
|
|
40
|
+
{isPlaceHolder && (
|
|
41
|
+
<Fragment>
|
|
42
|
+
<StarterPromptsCardAction />
|
|
43
|
+
<StarterPromptsCardAction />
|
|
44
|
+
<StarterPromptsCardAction />
|
|
45
|
+
</Fragment>
|
|
46
|
+
)}
|
|
47
|
+
</StarterPromptsToolbar>
|
|
29
48
|
</div>
|
|
30
49
|
);
|
|
31
50
|
};
|
|
@@ -22,14 +22,18 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
&:disabled {
|
|
25
|
+
cursor: default;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:disabled:not(:empty) {
|
|
25
29
|
background-color: var(--webchat-colorNeutralBackgroundDisabled);
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
&:hover {
|
|
32
|
+
&:hover:not(:disabled) {
|
|
29
33
|
background-color: var(--webchat-colorNeutralBackground1Hover);
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
&:active {
|
|
36
|
+
&:active:not(:disabled) {
|
|
33
37
|
background-color: var(--webchat-colorNeutralBackground1Pressed);
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -37,6 +41,26 @@
|
|
|
37
41
|
outline: solid 2px var(--webchat-colorStrokeFocus2);
|
|
38
42
|
outline-offset: -2px;
|
|
39
43
|
}
|
|
44
|
+
|
|
45
|
+
&:empty::before {
|
|
46
|
+
content: '';
|
|
47
|
+
display: block;
|
|
48
|
+
width: 66%;
|
|
49
|
+
height: 18px;
|
|
50
|
+
background-color: var(--webchat-colorNeutralBackground6);
|
|
51
|
+
border-radius: 18px;
|
|
52
|
+
opacity: 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&:empty::after {
|
|
56
|
+
content: '';
|
|
57
|
+
display: block;
|
|
58
|
+
width: 100%;
|
|
59
|
+
height: 16px;
|
|
60
|
+
background-color: var(--webchat-colorNeutralBackground6);
|
|
61
|
+
border-radius: 16px;
|
|
62
|
+
opacity: 0.8;
|
|
63
|
+
}
|
|
40
64
|
}
|
|
41
65
|
|
|
42
66
|
:global(.webchat-fluent) .pre-chat-message-activity__card-action-image {
|
|
@@ -12,18 +12,18 @@ const { MonochromeImageMasker } = Components;
|
|
|
12
12
|
|
|
13
13
|
type Props = Readonly<{
|
|
14
14
|
className?: string | undefined;
|
|
15
|
-
messageBackAction
|
|
15
|
+
messageBackAction?: (DirectLineCardAction & { type: 'messageBack' }) | undefined;
|
|
16
16
|
}>;
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const StarterPromptsCardAction = ({ className, messageBackAction }: Props) => {
|
|
19
19
|
const [_, setSendBoxValue] = useSendBoxValue();
|
|
20
20
|
const classNames = useStyles(styles);
|
|
21
21
|
const focus = useFocus();
|
|
22
|
-
const inputTextRef = useRefFrom(messageBackAction
|
|
22
|
+
const inputTextRef = useRefFrom(messageBackAction?.displayText || messageBackAction?.text || '');
|
|
23
23
|
const renderMarkdownAsHTML = useRenderMarkdownAsHTML('message activity');
|
|
24
24
|
const subtitleHTML = useMemo(
|
|
25
|
-
() => (renderMarkdownAsHTML ? { __html: renderMarkdownAsHTML(messageBackAction
|
|
26
|
-
[messageBackAction
|
|
25
|
+
() => (renderMarkdownAsHTML ? { __html: renderMarkdownAsHTML(messageBackAction?.text || '') } : { __html: '' }),
|
|
26
|
+
[messageBackAction?.text, renderMarkdownAsHTML]
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
const handleClick = useCallback(() => {
|
|
@@ -37,28 +37,33 @@ const StarterPromptAction = ({ className, messageBackAction }: Props) => {
|
|
|
37
37
|
<button
|
|
38
38
|
className={cx(className, classNames['pre-chat-message-activity__card-action-box'])}
|
|
39
39
|
data-testid={testIds.preChatMessageActivityStarterPromptsCardAction}
|
|
40
|
+
disabled={!messageBackAction}
|
|
40
41
|
onClick={handleClick}
|
|
41
42
|
type="button"
|
|
42
43
|
>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
{messageBackAction && (
|
|
45
|
+
<React.Fragment>
|
|
46
|
+
<div className={classNames['pre-chat-message-activity__card-action-title']}>
|
|
47
|
+
{'title' in messageBackAction && messageBackAction.title}
|
|
48
|
+
</div>
|
|
49
|
+
{'image' in messageBackAction && messageBackAction.image && (
|
|
50
|
+
<MonochromeImageMasker
|
|
51
|
+
className={classNames['pre-chat-message-activity__card-action-image']}
|
|
52
|
+
src={messageBackAction.image}
|
|
53
|
+
/>
|
|
54
|
+
// <img className="pre-chat-message-activity__card-action-image" src={messageBackAction.image} />
|
|
55
|
+
)}
|
|
56
|
+
<div
|
|
57
|
+
className={classNames['pre-chat-message-activity__card-action-subtitle']}
|
|
58
|
+
// eslint-disable-next-line react/no-danger
|
|
59
|
+
dangerouslySetInnerHTML={subtitleHTML}
|
|
60
|
+
/>
|
|
61
|
+
</React.Fragment>
|
|
52
62
|
)}
|
|
53
|
-
<div
|
|
54
|
-
className={classNames['pre-chat-message-activity__card-action-subtitle']}
|
|
55
|
-
// eslint-disable-next-line react/no-danger
|
|
56
|
-
dangerouslySetInnerHTML={subtitleHTML}
|
|
57
|
-
/>
|
|
58
63
|
</button>
|
|
59
64
|
);
|
|
60
65
|
};
|
|
61
66
|
|
|
62
|
-
|
|
67
|
+
StarterPromptsCardAction.displayName = 'StarterPromptsCardAction';
|
|
63
68
|
|
|
64
|
-
export default memo(
|
|
69
|
+
export default memo(StarterPromptsCardAction);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DirectLineCardAction } from 'botframework-webchat-core';
|
|
2
2
|
import cx from 'classnames';
|
|
3
|
-
import React, { memo } from 'react';
|
|
3
|
+
import React, { memo, type ReactNode } from 'react';
|
|
4
4
|
import { useStyles } from '../../styles/index.js';
|
|
5
5
|
import StarterPromptsCardAction from './StarterPromptsCardAction.js';
|
|
6
6
|
import styles from './StarterPromptsToolbar.module.css';
|
|
@@ -8,23 +8,22 @@ import styles from './StarterPromptsToolbar.module.css';
|
|
|
8
8
|
type Props = Readonly<{
|
|
9
9
|
cardActions: readonly DirectLineCardAction[];
|
|
10
10
|
className?: string | undefined;
|
|
11
|
+
children?: ReactNode | undefined;
|
|
11
12
|
}>;
|
|
12
13
|
|
|
13
|
-
const StarterPrompts = ({ cardActions, className }: Props) => {
|
|
14
|
+
const StarterPrompts = ({ cardActions, children, className }: Props) => {
|
|
14
15
|
const classNames = useStyles(styles);
|
|
15
16
|
|
|
16
17
|
return (
|
|
17
18
|
// TODO: Accessibility-wise, this should be role="toolbar" with keyboard navigation.
|
|
18
19
|
<div className={cx(className, classNames['pre-chat-message-activity__card-action-toolbar'])}>
|
|
19
20
|
<div className={classNames['pre-chat-message-activity__card-action-toolbar-grid']}>
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<StarterPromptsCardAction key={cardAction.text} messageBackAction={cardAction} />
|
|
27
|
-
))}
|
|
21
|
+
{children ||
|
|
22
|
+
cardActions
|
|
23
|
+
.filter<
|
|
24
|
+
DirectLineCardAction & { type: 'messageBack' }
|
|
25
|
+
>((card: DirectLineCardAction): card is DirectLineCardAction & { type: 'messageBack' } => card.type === 'messageBack')
|
|
26
|
+
.map(cardAction => <StarterPromptsCardAction key={cardAction.text} messageBackAction={cardAction} />)}
|
|
28
27
|
</div>
|
|
29
28
|
</div>
|
|
30
29
|
);
|
|
@@ -1,15 +1,26 @@
|
|
|
1
|
+
import { useLiveRegion } from 'botframework-webchat-component/internal';
|
|
1
2
|
import React, { memo } from 'react';
|
|
2
|
-
import styles from './ErrorMessage.module.css';
|
|
3
3
|
import { useStyles } from '../../styles';
|
|
4
|
+
import styles from './ErrorMessage.module.css';
|
|
5
|
+
|
|
6
|
+
type ErrorMessageProps = Readonly<{
|
|
7
|
+
error?: string | undefined;
|
|
8
|
+
id: string;
|
|
9
|
+
}>;
|
|
4
10
|
|
|
5
|
-
function ErrorMessage(
|
|
11
|
+
function ErrorMessage({ error, id }: ErrorMessageProps) {
|
|
6
12
|
const classNames = useStyles(styles);
|
|
13
|
+
|
|
14
|
+
useLiveRegion(() => error && <div className="sendbox__error-message__status">{error}</div>, [error]);
|
|
15
|
+
|
|
7
16
|
return (
|
|
8
17
|
// eslint-disable-next-line react/forbid-dom-props
|
|
9
|
-
<span className={classNames['sendbox__error-message']} id={
|
|
10
|
-
{
|
|
18
|
+
<span className={classNames['sendbox__error-message']} id={id}>
|
|
19
|
+
{error}
|
|
11
20
|
</span>
|
|
12
21
|
);
|
|
13
22
|
}
|
|
14
23
|
|
|
24
|
+
ErrorMessage.displayName = 'ErrorMessage';
|
|
25
|
+
|
|
15
26
|
export default memo(ErrorMessage);
|
|
@@ -50,7 +50,7 @@ function SendBox(props: Props) {
|
|
|
50
50
|
const sendMessage = useSendMessage();
|
|
51
51
|
const makeThumbnail = useMakeThumbnail();
|
|
52
52
|
const errorMessageId = useUniqueId('sendbox__error-message-id');
|
|
53
|
-
const [
|
|
53
|
+
const [errorMessage, commitLatestError] = useSubmitError({ message, attachments });
|
|
54
54
|
const [telephoneKeypadShown] = useTelephoneKeypadShown();
|
|
55
55
|
const setFocus = useFocus();
|
|
56
56
|
|
|
@@ -133,8 +133,9 @@ function SendBox(props: Props) {
|
|
|
133
133
|
const handleFormSubmit: FormEventHandler<HTMLFormElement> = useCallback(
|
|
134
134
|
event => {
|
|
135
135
|
event.preventDefault();
|
|
136
|
+
const error = commitLatestError();
|
|
136
137
|
|
|
137
|
-
if (
|
|
138
|
+
if (error !== 'empty' && !isMessageLengthExceeded) {
|
|
138
139
|
sendMessage(messageRef.current, undefined, { attachments: attachmentsRef.current });
|
|
139
140
|
|
|
140
141
|
setMessage('');
|
|
@@ -143,7 +144,16 @@ function SendBox(props: Props) {
|
|
|
143
144
|
|
|
144
145
|
setFocus('sendBox');
|
|
145
146
|
},
|
|
146
|
-
[
|
|
147
|
+
[
|
|
148
|
+
commitLatestError,
|
|
149
|
+
isMessageLengthExceeded,
|
|
150
|
+
setFocus,
|
|
151
|
+
sendMessage,
|
|
152
|
+
setMessage,
|
|
153
|
+
messageRef,
|
|
154
|
+
attachmentsRef,
|
|
155
|
+
setAttachments
|
|
156
|
+
]
|
|
147
157
|
);
|
|
148
158
|
|
|
149
159
|
const handleTelephoneKeypadButtonClick = useCallback(
|
|
@@ -157,8 +167,9 @@ function SendBox(props: Props) {
|
|
|
157
167
|
const aria = {
|
|
158
168
|
'aria-invalid': 'false' as const,
|
|
159
169
|
...(errorMessage && {
|
|
160
|
-
'aria-
|
|
161
|
-
'aria-errormessage': errorMessageId
|
|
170
|
+
'aria-describedby': errorMessageId,
|
|
171
|
+
'aria-errormessage': errorMessageId,
|
|
172
|
+
'aria-invalid': 'true' as const
|
|
162
173
|
})
|
|
163
174
|
};
|
|
164
175
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hooks } from 'botframework-webchat-component';
|
|
2
|
-
import {
|
|
2
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
3
3
|
import { useRefFrom } from 'use-ref-from';
|
|
4
4
|
|
|
5
5
|
const { useConnectivityStatus, useLocalizer } = hooks;
|
|
@@ -16,6 +16,7 @@ const useSubmitError = ({
|
|
|
16
16
|
message: string;
|
|
17
17
|
}>) => {
|
|
18
18
|
const [connectivityStatus] = useConnectivityStatus();
|
|
19
|
+
const [error, setError] = useState<SendError | undefined>();
|
|
19
20
|
const localize = useLocalizer();
|
|
20
21
|
|
|
21
22
|
const submitErrorRef = useRefFrom<'empty' | 'offline' | undefined>(
|
|
@@ -37,9 +38,21 @@ const useSubmitError = ({
|
|
|
37
38
|
[localize]
|
|
38
39
|
);
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
// TODO: we may want to improve this later e.g. to avoid re-render
|
|
42
|
+
// Reset visible error if there is a value
|
|
43
|
+
const hasValue = !!message?.trim();
|
|
44
|
+
if (error === 'empty' && hasValue) {
|
|
45
|
+
setError(undefined);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const commitLatestError = useCallback(() => {
|
|
49
|
+
setError(submitErrorRef.current);
|
|
50
|
+
return submitErrorRef.current;
|
|
51
|
+
}, [submitErrorRef]);
|
|
52
|
+
|
|
53
|
+
return useMemo<Readonly<[string | undefined, () => typeof submitErrorRef.current]>>(
|
|
54
|
+
() => Object.freeze([error && errorMessageStringMap.get(error), commitLatestError]),
|
|
55
|
+
[error, errorMessageStringMap, commitLatestError]
|
|
43
56
|
);
|
|
44
57
|
};
|
|
45
58
|
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
--webchat-colorNeutralBackground3: var(--colorNeutralBackground3, #f5f5f5);
|
|
21
21
|
--webchat-colorNeutralBackground4: var(--colorNeutralBackground4, #f0f0f0);
|
|
22
22
|
--webchat-colorNeutralBackground5: var(--colorNeutralBackground5, #ebebeb);
|
|
23
|
+
--webchat-colorNeutralBackground6: var(--colorNeutralBackground6, #e6e6e6);
|
|
23
24
|
|
|
24
25
|
--webchat-colorTransparentBackground: var(--colorTransparentBackground, rgba(0, 0, 0, 0.4));
|
|
25
26
|
|
|
@@ -167,6 +168,10 @@
|
|
|
167
168
|
var(--webchat-spacingVerticalNone)
|
|
168
169
|
var(--webchat-spacingHorizontalMNudge)
|
|
169
170
|
var(--webchat-spacingHorizontalMNudge);
|
|
171
|
+
|
|
172
|
+
--webchat__border-animation--color-1: #464FEB;
|
|
173
|
+
--webchat__border-animation--color-2: #47CFFA;
|
|
174
|
+
--webchat__border-animation--color-3: #B47CF8;
|
|
170
175
|
}
|
|
171
176
|
|
|
172
177
|
:global(.webchat-fluent).theme.variant-copilot :global(.webchat__css-custom-properties) {
|
|
@@ -267,6 +272,12 @@
|
|
|
267
272
|
}
|
|
268
273
|
}
|
|
269
274
|
|
|
275
|
+
/* Transcript filer in copilot variant */
|
|
276
|
+
:global(.webchat-fluent).theme.variant-copilot :global(.webchat__basic-transcript .webchat__basic-transcript__filler) {
|
|
277
|
+
/* No filler unless pre-chat activity, see next rule */
|
|
278
|
+
flex-grow: 0;
|
|
279
|
+
}
|
|
280
|
+
|
|
270
281
|
/* Transcript with a single pre-chat activity */
|
|
271
282
|
:global(.webchat-fluent).theme :global(.webchat__basic-transcript:has(.webchat__basic-transcript__activity:only-child):has(.pre-chat-message-activity) .webchat__basic-transcript__filler) {
|
|
272
283
|
/* limit grow to half of the size to center the activity */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = (globalThis as any).WebChat.internal;
|
|
@@ -8,6 +8,8 @@ import { PrimarySendBox } from '../components/sendBox';
|
|
|
8
8
|
import { TelephoneKeypadProvider } from '../components/telephoneKeypad';
|
|
9
9
|
import { WebChatTheme } from '../components/theme';
|
|
10
10
|
import VariantComposer, { VariantList } from './VariantComposer';
|
|
11
|
+
import { FluentThemeDecorator } from '../components/decorator';
|
|
12
|
+
import { isLinerMessageActivity, LinerMessageActivity } from '../components/linerActivity';
|
|
11
13
|
|
|
12
14
|
const { ThemeProvider } = Components;
|
|
13
15
|
|
|
@@ -19,9 +21,12 @@ const activityMiddleware: readonly ActivityMiddleware[] = Object.freeze([
|
|
|
19
21
|
(...args) => {
|
|
20
22
|
const activity = args[0]?.activity;
|
|
21
23
|
|
|
22
|
-
if (
|
|
24
|
+
if (isPreChatMessageActivity(activity)) {
|
|
23
25
|
return () => <PreChatMessageActivity activity={activity} />;
|
|
24
26
|
}
|
|
27
|
+
if (isLinerMessageActivity(activity)) {
|
|
28
|
+
return () => <LinerMessageActivity activity={activity} />;
|
|
29
|
+
}
|
|
25
30
|
|
|
26
31
|
const renderActivity = next(...args);
|
|
27
32
|
|
|
@@ -38,7 +43,7 @@ const FluentThemeProvider = ({ children, variant = 'fluent' }: Props) => (
|
|
|
38
43
|
<WebChatTheme>
|
|
39
44
|
<TelephoneKeypadProvider>
|
|
40
45
|
<ThemeProvider activityMiddleware={activityMiddleware} sendBoxMiddleware={sendBoxMiddleware}>
|
|
41
|
-
{children}
|
|
46
|
+
<FluentThemeDecorator>{children}</FluentThemeDecorator>
|
|
42
47
|
</ThemeProvider>
|
|
43
48
|
</TelephoneKeypadProvider>
|
|
44
49
|
</WebChatTheme>
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { DecoratorComposer, type DecoratorMiddleware } from 'botframework-webchat-api/decorator';
|
|
2
|
-
import cx from 'classnames';
|
|
3
|
-
import React, { memo, type ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
import { useStyles } from '../../styles';
|
|
6
|
-
import styles from './Decorator.module.css';
|
|
7
|
-
import Flair from './Flair';
|
|
8
|
-
import Loader from './Loader';
|
|
9
|
-
|
|
10
|
-
export const rootClassName = 'webchat-fluent-decorator';
|
|
11
|
-
|
|
12
|
-
const middleware: DecoratorMiddleware[] = [
|
|
13
|
-
init =>
|
|
14
|
-
init === 'activity border' &&
|
|
15
|
-
(next => request => (request.livestreamingState === 'completing' ? Flair : next(request))),
|
|
16
|
-
init =>
|
|
17
|
-
init === 'activity border' &&
|
|
18
|
-
(next => request => (request.livestreamingState === 'preparing' ? Loader : next(request)))
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
function WebChatDecorator(props: Readonly<{ readonly children?: ReactNode | undefined }>) {
|
|
22
|
-
const classNames = useStyles(styles);
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<div className={cx(rootClassName, classNames['decorator'])}>
|
|
26
|
-
<DecoratorComposer middleware={middleware}>{props.children}</DecoratorComposer>
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export default memo(WebChatDecorator);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React, { memo, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
import { useStyles } from '../../styles';
|
|
4
|
-
import styles from './Flair.module.css';
|
|
5
|
-
|
|
6
|
-
function Flair({ children }: Readonly<{ children?: ReactNode | undefined }>) {
|
|
7
|
-
const classNames = useStyles(styles);
|
|
8
|
-
|
|
9
|
-
return <div className={classNames['flair']}>{children}</div>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default memo(Flair);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import React, { memo, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
import { useStyles } from '../../styles';
|
|
4
|
-
import styles from './Loader.module.css';
|
|
5
|
-
|
|
6
|
-
function Loader({ children }: Readonly<{ children?: ReactNode | undefined }>) {
|
|
7
|
-
const classNames = useStyles(styles);
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<React.Fragment>
|
|
11
|
-
{children}
|
|
12
|
-
<div className={classNames['loader']} />
|
|
13
|
-
</React.Fragment>
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default memo(Loader);
|
|
File without changes
|