botframework-webchat-fluent-theme 4.17.1-main.20240516.aaff0e6 → 4.17.1-main.20240625.336dd7c
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 +1 -1
- 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 +1 -1
- package/dist/botframework-webchat-fluent-theme.production.min.js.map +1 -1
- package/package.json +4 -4
- package/src/components/decorator/Decorator.module.css +3 -0
- package/src/components/decorator/Decorator.tsx +27 -0
- package/src/components/decorator/Flair.module.css +4 -0
- package/src/components/decorator/Flair.tsx +12 -0
- package/src/components/decorator/Loader.module.css +3 -0
- package/src/components/decorator/Loader.tsx +17 -0
- package/src/components/decorator/index.ts +1 -0
- package/src/components/sendBox/SendBox.module.css +7 -0
- package/src/components/sendBox/SendBox.tsx +9 -2
- package/src/components/sendBox/private/useTranscriptNavigation.ts +53 -0
- package/src/components/telephoneKeypad/private/Button.tsx +1 -3
- package/src/components/telephoneKeypad/private/TelephoneKeypad.tsx +4 -8
- package/src/components/telephoneKeypad/types.ts +1 -1
- package/src/external.umd/botframework-webchat-api/decorator.ts +1 -0
- /package/src/external.umd/{botframework-webchat-api.ts → botframework-webchat-api/index.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botframework-webchat-fluent-theme",
|
|
3
|
-
"version": "4.17.1-main.
|
|
3
|
+
"version": "4.17.1-main.20240625.336dd7c",
|
|
4
4
|
"description": "Fluent theme for Bot Framework Web Chat",
|
|
5
5
|
"main": "./dist/botframework-webchat-fluent-theme.js",
|
|
6
6
|
"types": "./dist/botframework-webchat-fluent-theme.d.ts",
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
"typescript": "^5.4.5"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"botframework-webchat-api": "4.17.1-main.
|
|
73
|
-
"botframework-webchat-component": "4.17.1-main.
|
|
74
|
-
"botframework-webchat-core": "4.17.1-main.
|
|
72
|
+
"botframework-webchat-api": "4.17.1-main.20240625.336dd7c",
|
|
73
|
+
"botframework-webchat-component": "4.17.1-main.20240625.336dd7c",
|
|
74
|
+
"botframework-webchat-core": "4.17.1-main.20240625.336dd7c",
|
|
75
75
|
"classnames": "2.5.1",
|
|
76
76
|
"inject-meta-tag": "0.0.1",
|
|
77
77
|
"math-random": "2.0.1",
|
|
@@ -0,0 +1,27 @@
|
|
|
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 => init === 'activity border' && (next => request => (request.state === 'completion' ? Flair : next(request))),
|
|
14
|
+
init => init === 'activity border' && (next => request => (request.state === 'informative' ? Loader : next(request)))
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
function WebChatDecorator(props: Readonly<{ readonly children?: ReactNode | undefined }>) {
|
|
18
|
+
const classNames = useStyles(styles);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className={cx(rootClassName, classNames['decorator'])}>
|
|
22
|
+
<DecoratorComposer middleware={middleware}>{props.children}</DecoratorComposer>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default memo(WebChatDecorator);
|
|
@@ -0,0 +1,12 @@
|
|
|
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);
|
|
@@ -0,0 +1,17 @@
|
|
|
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);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as WebChatDecorator } from './Decorator';
|
|
@@ -79,6 +79,13 @@
|
|
|
79
79
|
outline: none;
|
|
80
80
|
padding: 4px 4px 0;
|
|
81
81
|
resize: none;
|
|
82
|
+
|
|
83
|
+
/* Prevent zoom on focus on iOS */
|
|
84
|
+
@media only screen and (hover: none) and (pointer: coarse) {
|
|
85
|
+
&:focus-within {
|
|
86
|
+
font-size: 16px;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
:global(.webchat-fluent) .sendbox__sendbox-controls {
|
|
@@ -17,6 +17,7 @@ import useSubmitError from './private/useSubmitError';
|
|
|
17
17
|
import useUniqueId from './private/useUniqueId';
|
|
18
18
|
import styles from './SendBox.module.css';
|
|
19
19
|
import { useStyles } from '../../styles';
|
|
20
|
+
import useTranscriptNavigation from './private/useTranscriptNavigation';
|
|
20
21
|
|
|
21
22
|
const {
|
|
22
23
|
useFocus,
|
|
@@ -142,10 +143,12 @@ function SendBox(
|
|
|
142
143
|
|
|
143
144
|
const handleTelephoneKeypadButtonClick = useCallback(
|
|
144
145
|
// TODO: We need more official way of sending DTMF.
|
|
145
|
-
(dtmf: DTMF) => sendMessage(`/
|
|
146
|
+
(dtmf: DTMF) => sendMessage(`/DTMFKey ${dtmf}`),
|
|
146
147
|
[sendMessage]
|
|
147
148
|
);
|
|
148
149
|
|
|
150
|
+
const handleTranscriptNavigation = useTranscriptNavigation();
|
|
151
|
+
|
|
149
152
|
const aria = {
|
|
150
153
|
'aria-invalid': 'false' as const,
|
|
151
154
|
...(errorMessage && {
|
|
@@ -157,7 +160,11 @@ function SendBox(
|
|
|
157
160
|
return (
|
|
158
161
|
<form {...aria} className={cx(classNames['sendbox'], props.className)} onSubmit={handleFormSubmit}>
|
|
159
162
|
<SuggestedActions />
|
|
160
|
-
<div
|
|
163
|
+
<div
|
|
164
|
+
className={cx(classNames['sendbox__sendbox'])}
|
|
165
|
+
onClickCapture={handleSendBoxClick}
|
|
166
|
+
onKeyDown={handleTranscriptNavigation}
|
|
167
|
+
>
|
|
161
168
|
<TextArea
|
|
162
169
|
aria-label={isMessageLengthExceeded ? localize('TEXT_INPUT_LENGTH_EXCEEDED_ALT') : localize('TEXT_INPUT_ALT')}
|
|
163
170
|
className={cx(classNames['sendbox__sendbox-text'], classNames['sendbox__text-area--in-grid'])}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useCallback, type KeyboardEvent } from 'react';
|
|
2
|
+
import { hooks } from 'botframework-webchat-component';
|
|
3
|
+
|
|
4
|
+
const { useScrollDown, useScrollUp } = hooks;
|
|
5
|
+
|
|
6
|
+
export default function useTranscriptNavigation() {
|
|
7
|
+
const scrollDown = useScrollDown();
|
|
8
|
+
const scrollUp = useScrollUp();
|
|
9
|
+
|
|
10
|
+
return useCallback(
|
|
11
|
+
(event: KeyboardEvent<unknown>) => {
|
|
12
|
+
if (event.target instanceof HTMLTextAreaElement && event.target.value) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { ctrlKey, metaKey, shiftKey } = event;
|
|
17
|
+
|
|
18
|
+
if (ctrlKey || metaKey || shiftKey) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let handled = true;
|
|
23
|
+
|
|
24
|
+
switch (event.key) {
|
|
25
|
+
case 'End':
|
|
26
|
+
scrollDown({ displacement: Infinity });
|
|
27
|
+
break;
|
|
28
|
+
|
|
29
|
+
case 'Home':
|
|
30
|
+
scrollUp({ displacement: Infinity });
|
|
31
|
+
break;
|
|
32
|
+
|
|
33
|
+
case 'PageDown':
|
|
34
|
+
scrollDown();
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case 'PageUp':
|
|
38
|
+
scrollUp();
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
default:
|
|
42
|
+
handled = false;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (handled) {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
event.stopPropagation();
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
[scrollDown, scrollUp]
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -29,9 +29,7 @@ const Button = memo(
|
|
|
29
29
|
ref={ref}
|
|
30
30
|
type="button"
|
|
31
31
|
>
|
|
32
|
-
<span className={classNames['telephone-keypad__button__text']}>
|
|
33
|
-
{button === 'star' ? '\u2217' : button === 'pound' ? '#' : button}
|
|
34
|
-
</span>
|
|
32
|
+
<span className={classNames['telephone-keypad__button__text']}>{button === '*' ? '\u2217' : button}</span>
|
|
35
33
|
{!!ruby && <ruby className={classNames['telephone-keypad__button__ruby']}>{ruby}</ruby>}
|
|
36
34
|
</button>
|
|
37
35
|
);
|
|
@@ -50,8 +50,8 @@ const TelephoneKeypad = memo(({ autoFocus, className, onButtonClick, isHorizonta
|
|
|
50
50
|
const handleButton8Click = useCallback(() => onButtonClickRef.current?.('8'), [onButtonClickRef]);
|
|
51
51
|
const handleButton9Click = useCallback(() => onButtonClickRef.current?.('9'), [onButtonClickRef]);
|
|
52
52
|
const handleButton0Click = useCallback(() => onButtonClickRef.current?.('0'), [onButtonClickRef]);
|
|
53
|
-
const handleButtonStarClick = useCallback(() => onButtonClickRef.current?.('
|
|
54
|
-
const handleButtonPoundClick = useCallback(() => onButtonClickRef.current?.('
|
|
53
|
+
const handleButtonStarClick = useCallback(() => onButtonClickRef.current?.('*'), [onButtonClickRef]);
|
|
54
|
+
const handleButtonPoundClick = useCallback(() => onButtonClickRef.current?.('#'), [onButtonClickRef]);
|
|
55
55
|
const handleKeyDown = useCallback<KeyboardEventHandler<HTMLDivElement>>(
|
|
56
56
|
event => {
|
|
57
57
|
if (event.key === 'Escape') {
|
|
@@ -123,13 +123,9 @@ const TelephoneKeypad = memo(({ autoFocus, className, onButtonClick, isHorizonta
|
|
|
123
123
|
onClick={handleButton9Click}
|
|
124
124
|
ruby="WXYZ"
|
|
125
125
|
/>
|
|
126
|
-
<Button button="
|
|
126
|
+
<Button button="*" data-testid={testIds.sendBoxTelephoneKeypadButtonStar} onClick={handleButtonStarClick} />
|
|
127
127
|
<Button button="0" data-testid={testIds.sendBoxTelephoneKeypadButton0} onClick={handleButton0Click} ruby="+" />
|
|
128
|
-
<Button
|
|
129
|
-
button="pound"
|
|
130
|
-
data-testid={testIds.sendBoxTelephoneKeypadButtonPound}
|
|
131
|
-
onClick={handleButtonPoundClick}
|
|
132
|
-
/>
|
|
128
|
+
<Button button="#" data-testid={testIds.sendBoxTelephoneKeypadButtonPound} onClick={handleButtonPoundClick} />
|
|
133
129
|
</Orientation>
|
|
134
130
|
<div className={classNames['telephone-keypad__info-message']}>
|
|
135
131
|
<InfoSmallIcon />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type DTMF = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0' | '
|
|
1
|
+
export type DTMF = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0' | '*' | '#';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = (globalThis as any).WebChat.decorator;
|
|
File without changes
|