botframework-webchat-fluent-theme 4.17.0-main.20240411.ff34969 → 4.17.0-main.20240416.4ff01ae
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.development.css.map +1 -0
- package/dist/botframework-webchat-fluent-theme.development.js +384 -2081
- package/dist/botframework-webchat-fluent-theme.development.js.map +1 -1
- package/dist/botframework-webchat-fluent-theme.production.min.css.map +1 -0
- package/dist/botframework-webchat-fluent-theme.production.min.js +1 -3
- package/dist/botframework-webchat-fluent-theme.production.min.js.map +1 -1
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +360 -648
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1076 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
- package/src/components/Theme.module.css +60 -0
- package/src/components/Theme.tsx +4 -64
- package/src/components/dropZone/index.module.css +23 -0
- package/src/components/dropZone/index.tsx +6 -31
- package/src/components/sendbox/AddAttachmentButton.module.css +10 -0
- package/src/components/sendbox/AddAttachmentButton.tsx +5 -17
- package/src/components/sendbox/Attachments.module.css +7 -0
- package/src/components/sendbox/Attachments.tsx +3 -12
- package/src/components/sendbox/ErrorMessage.module.css +9 -0
- package/src/components/sendbox/ErrorMessage.tsx +2 -13
- package/src/components/sendbox/TelephoneKeypadToolbarButton.tsx +1 -1
- package/src/components/sendbox/TextArea.module.css +61 -0
- package/src/components/sendbox/TextArea.tsx +9 -70
- package/src/components/sendbox/Toolbar.module.css +49 -0
- package/src/components/sendbox/Toolbar.tsx +4 -55
- package/src/components/sendbox/index.module.css +58 -0
- package/src/components/sendbox/index.tsx +16 -81
- package/src/components/suggestedActions/SuggestedAction.module.css +34 -0
- package/src/components/suggestedActions/SuggestedAction.tsx +5 -47
- package/src/components/suggestedActions/index.module.css +23 -0
- package/src/components/suggestedActions/index.tsx +18 -23
- package/src/components/telephoneKeypad/private/Button.module.css +62 -0
- package/src/components/telephoneKeypad/private/Button.tsx +5 -67
- package/src/components/telephoneKeypad/private/TelephoneKeypad.module.css +30 -0
- package/src/components/telephoneKeypad/private/TelephoneKeypad.tsx +4 -35
- package/src/env.d.ts +7 -0
- package/src/index.ts +3 -0
- package/src/styles/injectStyle.ts +9 -0
- package/src/styles/useStyles.ts +19 -0
- package/src/styles.ts +4 -0
- package/src/tsconfig.json +2 -1
- package/src/private/useStyleToEmotionObject.ts +0 -32
- package/src/styles/index.ts +0 -15
|
@@ -3,7 +3,6 @@ import cx from 'classnames';
|
|
|
3
3
|
import React, { memo, useCallback, useRef, useState, type FormEventHandler, type MouseEventHandler } from 'react';
|
|
4
4
|
import { useRefFrom } from 'use-ref-from';
|
|
5
5
|
import { SendIcon } from '../../icons/SendIcon';
|
|
6
|
-
import { useStyles } from '../../styles';
|
|
7
6
|
import testIds from '../../testIds';
|
|
8
7
|
import DropZone from '../DropZone';
|
|
9
8
|
import SuggestedActions from '../SuggestedActions';
|
|
@@ -16,70 +15,11 @@ import TextArea from './TextArea';
|
|
|
16
15
|
import { Toolbar, ToolbarButton, ToolbarSeparator } from './Toolbar';
|
|
17
16
|
import useSubmitError from './private/useSubmitError';
|
|
18
17
|
import useUniqueId from './private/useUniqueId';
|
|
18
|
+
import styles from './index.module.css';
|
|
19
|
+
import { useStyles } from '../../styles';
|
|
19
20
|
|
|
20
21
|
const { useStyleOptions, useMakeThumbnail, useLocalizer, useSendBoxAttachments, useSendMessage } = hooks;
|
|
21
22
|
|
|
22
|
-
const styles = {
|
|
23
|
-
'webchat-fluent__sendbox': {
|
|
24
|
-
color: 'var(--webchat-colorNeutralForeground1)',
|
|
25
|
-
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
26
|
-
padding: '0 10px 10px',
|
|
27
|
-
textRendering: 'optimizeLegibility'
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
'webchat-fluent__sendbox__sendbox': {
|
|
31
|
-
backgroundColor: 'var(--webchat-colorNeutralBackground1)',
|
|
32
|
-
border: '1px solid var(--webchat-colorNeutralStroke1)',
|
|
33
|
-
borderRadius: 'var(--webchat-borderRadiusLarge)',
|
|
34
|
-
display: 'grid',
|
|
35
|
-
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
36
|
-
fontSize: '14px',
|
|
37
|
-
gap: '6px',
|
|
38
|
-
lineHeight: '20px',
|
|
39
|
-
padding: '8px',
|
|
40
|
-
position: 'relative',
|
|
41
|
-
|
|
42
|
-
'&:focus-within': {
|
|
43
|
-
borderColor: 'var(--webchat-colorNeutralStroke1Selected)',
|
|
44
|
-
// TODO clarify with design the color:
|
|
45
|
-
// - Teams is using colorCompoundBrandForeground1
|
|
46
|
-
// - Fluent is using colorCompoundBrandStroke
|
|
47
|
-
// - we are using colorCompoundBrandForeground1Hover
|
|
48
|
-
boxShadow: 'inset 0 -6px 0 -3px var(--webchat-colorCompoundBrandForeground1Hover)'
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
'webchat-fluent__sendbox__sendbox-text': {
|
|
53
|
-
backgroundColor: 'transparent',
|
|
54
|
-
border: 'none',
|
|
55
|
-
flex: 'auto',
|
|
56
|
-
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
57
|
-
fontSize: '14px',
|
|
58
|
-
lineHeight: '20px',
|
|
59
|
-
outline: 'none',
|
|
60
|
-
padding: '4px 4px 0',
|
|
61
|
-
resize: 'none'
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
'webchat-fluent__sendbox__sendbox-controls': {
|
|
65
|
-
alignItems: 'center',
|
|
66
|
-
display: 'flex',
|
|
67
|
-
paddingInlineStart: '4px'
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
'webchat-fluent__sendbox__text-counter': {
|
|
71
|
-
color: 'var(--webchat-colorNeutralForeground4)',
|
|
72
|
-
cursor: 'default',
|
|
73
|
-
fontFamily: 'var(--webchat-fontFamilyNumeric)',
|
|
74
|
-
fontSize: '10px',
|
|
75
|
-
lineHeight: '14px'
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
'webchat-fluent__sendbox__text-counter--error': {
|
|
79
|
-
color: 'var(--webchat-colorStatusDangerForeground1)'
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
23
|
function SendBox(
|
|
84
24
|
props: Readonly<{
|
|
85
25
|
className?: string | undefined;
|
|
@@ -89,15 +29,15 @@ function SendBox(
|
|
|
89
29
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
90
30
|
const [message, setMessage] = useState('');
|
|
91
31
|
const [attachments, setAttachments] = useSendBoxAttachments();
|
|
92
|
-
const [{ maxMessageLength }] = useStyleOptions();
|
|
32
|
+
const [{ hideTelephoneKeypadButton, hideUploadButton, maxMessageLength }] = useStyleOptions();
|
|
93
33
|
const isMessageLengthExceeded = !!maxMessageLength && message.length > maxMessageLength;
|
|
94
34
|
const classNames = useStyles(styles);
|
|
95
35
|
const localize = useLocalizer();
|
|
96
36
|
const sendMessage = useSendMessage();
|
|
97
37
|
const makeThumbnail = useMakeThumbnail();
|
|
98
|
-
const errorMessageId = useUniqueId('
|
|
38
|
+
const errorMessageId = useUniqueId('sendbox__error-message-id');
|
|
99
39
|
const [errorRef, errorMessage] = useSubmitError({ message, attachments });
|
|
100
|
-
const [telephoneKeypadShown
|
|
40
|
+
const [telephoneKeypadShown] = useTelephoneKeypadShown();
|
|
101
41
|
|
|
102
42
|
const attachmentsRef = useRefFrom(attachments);
|
|
103
43
|
const messageRef = useRefFrom(message);
|
|
@@ -162,14 +102,9 @@ function SendBox(
|
|
|
162
102
|
);
|
|
163
103
|
|
|
164
104
|
const handleTelephoneKeypadButtonClick = useCallback(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
// TODO: In the future when we work on input modality, it should manage the focus in a better way.
|
|
170
|
-
setTelephoneKeypadShown(false);
|
|
171
|
-
},
|
|
172
|
-
[sendMessage, setTelephoneKeypadShown]
|
|
105
|
+
// TODO: We need more official way of sending DTMF.
|
|
106
|
+
(dtmf: DTMF) => sendMessage(`/DTMF ${dtmf}`),
|
|
107
|
+
[sendMessage]
|
|
173
108
|
);
|
|
174
109
|
|
|
175
110
|
const aria = {
|
|
@@ -181,9 +116,9 @@ function SendBox(
|
|
|
181
116
|
};
|
|
182
117
|
|
|
183
118
|
return (
|
|
184
|
-
<form {...aria} className={cx(classNames['
|
|
119
|
+
<form {...aria} className={cx(classNames['sendbox'], props.className)} onSubmit={handleFormSubmit}>
|
|
185
120
|
<SuggestedActions />
|
|
186
|
-
<div className={cx(classNames['
|
|
121
|
+
<div className={cx(classNames['sendbox__sendbox'])} onClickCapture={handleSendBoxClick}>
|
|
187
122
|
<TelephoneKeypadSurrogate
|
|
188
123
|
autoFocus={true}
|
|
189
124
|
isHorizontal={false}
|
|
@@ -191,7 +126,7 @@ function SendBox(
|
|
|
191
126
|
/>
|
|
192
127
|
<TextArea
|
|
193
128
|
aria-label={isMessageLengthExceeded ? localize('TEXT_INPUT_LENGTH_EXCEEDED_ALT') : localize('TEXT_INPUT_ALT')}
|
|
194
|
-
className={classNames['
|
|
129
|
+
className={classNames['sendbox__sendbox-text']}
|
|
195
130
|
data-testid={testIds.sendBoxTextBox}
|
|
196
131
|
hidden={telephoneKeypadShown}
|
|
197
132
|
onInput={handleMessageChange}
|
|
@@ -200,19 +135,19 @@ function SendBox(
|
|
|
200
135
|
value={message}
|
|
201
136
|
/>
|
|
202
137
|
<Attachments attachments={attachments} />
|
|
203
|
-
<div className={cx(classNames['
|
|
138
|
+
<div className={cx(classNames['sendbox__sendbox-controls'])}>
|
|
204
139
|
{maxMessageLength && (
|
|
205
140
|
<div
|
|
206
|
-
className={cx(classNames['
|
|
207
|
-
[classNames['
|
|
141
|
+
className={cx(classNames['sendbox__text-counter'], {
|
|
142
|
+
[classNames['sendbox__text-counter--error']]: isMessageLengthExceeded
|
|
208
143
|
})}
|
|
209
144
|
>
|
|
210
145
|
{`${message.length}/${maxMessageLength}`}
|
|
211
146
|
</div>
|
|
212
147
|
)}
|
|
213
148
|
<Toolbar>
|
|
214
|
-
<TelephoneKeypadToolbarButton />
|
|
215
|
-
<AddAttachmentButton onFilesAdded={handleAddFiles} />
|
|
149
|
+
{!hideTelephoneKeypadButton && <TelephoneKeypadToolbarButton />}
|
|
150
|
+
{!hideUploadButton && <AddAttachmentButton onFilesAdded={handleAddFiles} />}
|
|
216
151
|
<ToolbarSeparator />
|
|
217
152
|
<ToolbarButton
|
|
218
153
|
aria-label={localize('TEXT_INPUT_SEND_BUTTON_ALT')}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
:global(.webchat-fluent) .suggested-action {
|
|
2
|
+
align-items: center;
|
|
3
|
+
background: transparent;
|
|
4
|
+
border-radius: 8px;
|
|
5
|
+
border: 1px solid var(--webchat-colorBrandStroke2);
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
display: flex;
|
|
8
|
+
font-size: 12px;
|
|
9
|
+
gap: 4px;
|
|
10
|
+
padding: 4px 8px 4px;
|
|
11
|
+
text-align: start;
|
|
12
|
+
transition: all .15s ease-out;
|
|
13
|
+
|
|
14
|
+
@media (hover: hover) {
|
|
15
|
+
&:not([aria-disabled="true"]):hover {
|
|
16
|
+
background-color: var(--webchat-colorBrandBackground2Hover);
|
|
17
|
+
color: var(--webchat-colorBrandForeground2Hover)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
&:not([aria-disabled="true"]):active {
|
|
21
|
+
background-color: var(--webchat-colorBrandBackground2Pressed);
|
|
22
|
+
color: var(--webchat-colorBrandForeground2Pressed)
|
|
23
|
+
}
|
|
24
|
+
&[aria-disabled="true"] {
|
|
25
|
+
color: var(--webchat-colorNeutralForegroundDisabled);
|
|
26
|
+
cursor: not-allowed
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:global(.webchat-fluent) .suggested-action__image {
|
|
31
|
+
font-size: 12px;
|
|
32
|
+
height: 1em;
|
|
33
|
+
width: 1em;
|
|
34
|
+
}
|
|
@@ -2,10 +2,11 @@ import { hooks } from 'botframework-webchat-component';
|
|
|
2
2
|
import { type DirectLineCardAction } from 'botframework-webchat-core';
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
import React, { MouseEventHandler, memo, useCallback, useRef } from 'react';
|
|
5
|
-
import
|
|
5
|
+
import styles from './SuggestedAction.module.css';
|
|
6
6
|
import { useStyles } from '../../styles';
|
|
7
|
+
import AccessibleButton from './AccessibleButton';
|
|
7
8
|
|
|
8
|
-
const {
|
|
9
|
+
const { useDisabled, useFocus, usePerformCardAction, useScrollToEnd, useStyleSet, useSuggestedActions } = hooks;
|
|
9
10
|
|
|
10
11
|
type SuggestedActionProps = Readonly<{
|
|
11
12
|
buttonText: string | undefined;
|
|
@@ -29,45 +30,6 @@ type SuggestedActionProps = Readonly<{
|
|
|
29
30
|
value?: any;
|
|
30
31
|
}>;
|
|
31
32
|
|
|
32
|
-
const styles = {
|
|
33
|
-
'webchat-fluent__suggested-action': {
|
|
34
|
-
background: 'transparent',
|
|
35
|
-
border: '1px solid var(--webchat-colorBrandStroke2)',
|
|
36
|
-
borderRadius: '8px',
|
|
37
|
-
cursor: 'pointer',
|
|
38
|
-
fontSize: '12px',
|
|
39
|
-
lineHeight: '14px',
|
|
40
|
-
padding: '6px 8px 4px',
|
|
41
|
-
textAlign: 'start',
|
|
42
|
-
display: 'flex',
|
|
43
|
-
gap: '4px',
|
|
44
|
-
alignItems: 'center',
|
|
45
|
-
transition: 'all .15s ease-out',
|
|
46
|
-
|
|
47
|
-
'@media (hover: hover)': {
|
|
48
|
-
'&:not([aria-disabled="true"]):hover': {
|
|
49
|
-
backgroundColor: 'var(--webchat-colorBrandBackground2Hover)',
|
|
50
|
-
color: 'var(--webchat-colorBrandForeground2Hover)'
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
'&:not([aria-disabled="true"]):active': {
|
|
54
|
-
backgroundColor: 'var(--webchat-colorBrandBackground2Pressed)',
|
|
55
|
-
color: 'var(--webchat-colorBrandForeground2Pressed)'
|
|
56
|
-
},
|
|
57
|
-
'&[aria-disabled="true"]': {
|
|
58
|
-
color: ' var(--webchat-colorNeutralForegroundDisabled)',
|
|
59
|
-
cursor: 'not-allowed'
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
'webchat-fluent__suggested-action__image': {
|
|
64
|
-
width: '1em',
|
|
65
|
-
height: '1em',
|
|
66
|
-
fontSize: '20px',
|
|
67
|
-
translate: '0 -1px'
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
33
|
function SuggestedAction({
|
|
72
34
|
buttonText,
|
|
73
35
|
className,
|
|
@@ -110,17 +72,13 @@ function SuggestedAction({
|
|
|
110
72
|
|
|
111
73
|
return (
|
|
112
74
|
<AccessibleButton
|
|
113
|
-
className={cx(
|
|
114
|
-
classNames['webchat-fluent__suggested-action'],
|
|
115
|
-
suggestedActionStyleSet + '',
|
|
116
|
-
(className || '') + ''
|
|
117
|
-
)}
|
|
75
|
+
className={cx(classNames['suggested-action'], suggestedActionStyleSet + '', (className || '') + '')}
|
|
118
76
|
disabled={disabled}
|
|
119
77
|
onClick={handleClick}
|
|
120
78
|
ref={focusRef}
|
|
121
79
|
type="button"
|
|
122
80
|
>
|
|
123
|
-
{image && <img alt={imageAlt} className={classNames['
|
|
81
|
+
{image && <img alt={imageAlt} className={classNames['suggested-action__image']} src={image} />}
|
|
124
82
|
<span>{buttonText}</span>
|
|
125
83
|
</AccessibleButton>
|
|
126
84
|
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
:global(.webchat-fluent) .suggested-actions {
|
|
3
|
+
align-items: flex-end;
|
|
4
|
+
align-self: flex-end;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: 8px;
|
|
8
|
+
|
|
9
|
+
&:not(:empty) {
|
|
10
|
+
padding-block-end: 8px;
|
|
11
|
+
padding-inline-start: 4px
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&.suggested-actions--flow {
|
|
15
|
+
flex-direction: row;
|
|
16
|
+
flex-wrap: wrap;
|
|
17
|
+
justify-content: flex-end;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&.suggested-actions--stacked {
|
|
21
|
+
flex-direction: column
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
import { hooks } from 'botframework-webchat-component';
|
|
2
2
|
import cx from 'classnames';
|
|
3
3
|
import React, { memo, type ReactNode } from 'react';
|
|
4
|
-
import { useStyles } from '../../styles';
|
|
5
|
-
import computeSuggestedActionText from './private/computeSuggestedActionText';
|
|
6
4
|
import SuggestedAction from './SuggestedAction';
|
|
5
|
+
import computeSuggestedActionText from './private/computeSuggestedActionText';
|
|
6
|
+
import styles from './index.module.css';
|
|
7
|
+
import { useStyles } from '../../styles';
|
|
7
8
|
|
|
8
|
-
const { useLocalizer, useStyleSet, useSuggestedActions } = hooks;
|
|
9
|
-
|
|
10
|
-
const styles = {
|
|
11
|
-
'webchat-fluent__suggested-actions': {
|
|
12
|
-
alignItems: 'flex-end',
|
|
13
|
-
alignSelf: 'flex-end',
|
|
14
|
-
display: 'flex',
|
|
15
|
-
flexDirection: 'column',
|
|
16
|
-
gap: '8px',
|
|
17
|
-
|
|
18
|
-
'&:not(:empty)': {
|
|
19
|
-
paddingBlockEnd: '8px',
|
|
20
|
-
paddingInlineStart: '4px'
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
};
|
|
9
|
+
const { useLocalizer, useStyleOptions, useStyleSet, useSuggestedActions } = hooks;
|
|
24
10
|
|
|
25
|
-
function
|
|
11
|
+
function SuggestedActionStackedOrFlowContainer(
|
|
26
12
|
props: Readonly<{
|
|
27
13
|
'aria-label'?: string | undefined;
|
|
28
14
|
children?: ReactNode | undefined;
|
|
29
15
|
className?: string | undefined;
|
|
30
16
|
}>
|
|
31
17
|
) {
|
|
18
|
+
const [{ suggestedActionLayout }] = useStyleOptions();
|
|
32
19
|
const [{ suggestedActions: suggestedActionsStyleSet }] = useStyleSet();
|
|
33
20
|
const classNames = useStyles(styles);
|
|
34
21
|
|
|
@@ -37,7 +24,15 @@ function SuggestedActionStackedContainer(
|
|
|
37
24
|
aria-label={props['aria-label']}
|
|
38
25
|
aria-live="polite"
|
|
39
26
|
aria-orientation="vertical"
|
|
40
|
-
className={cx(
|
|
27
|
+
className={cx(
|
|
28
|
+
classNames['suggested-actions'],
|
|
29
|
+
suggestedActionsStyleSet + '',
|
|
30
|
+
{
|
|
31
|
+
[classNames['suggested-actions--flow']]: suggestedActionLayout === 'flow',
|
|
32
|
+
[classNames['suggested-actions--stacked']]: suggestedActionLayout !== 'flow'
|
|
33
|
+
},
|
|
34
|
+
props.className
|
|
35
|
+
)}
|
|
41
36
|
role="toolbar"
|
|
42
37
|
>
|
|
43
38
|
{!!props.children && !!React.Children.count(props.children) && props.children}
|
|
@@ -91,12 +86,12 @@ function SuggestedActions() {
|
|
|
91
86
|
);
|
|
92
87
|
});
|
|
93
88
|
return (
|
|
94
|
-
<
|
|
89
|
+
<SuggestedActionStackedOrFlowContainer
|
|
95
90
|
aria-label={localize('SUGGESTED_ACTIONS_LABEL_ALT')}
|
|
96
|
-
className={classNames['
|
|
91
|
+
className={classNames['suggested-actions']}
|
|
97
92
|
>
|
|
98
93
|
{children}
|
|
99
|
-
</
|
|
94
|
+
</SuggestedActionStackedOrFlowContainer>
|
|
100
95
|
);
|
|
101
96
|
}
|
|
102
97
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
|
|
2
|
+
:global(.webchat-fluent) .telephone-keypad__button {
|
|
3
|
+
-webkit-user-select: none;
|
|
4
|
+
align-items: center;
|
|
5
|
+
appearance: none;
|
|
6
|
+
/* backgroundColor: isDarkTheme() || isHighContrastTheme() ? black : white, */
|
|
7
|
+
background-color: White;
|
|
8
|
+
border-radius: 100%;
|
|
9
|
+
|
|
10
|
+
/* Whitelabel styles */
|
|
11
|
+
/* border: `solid 1px ${isHighContrastTheme() ? white : isDarkTheme() ? gray160 : gray40}`, */
|
|
12
|
+
/* color: inherit; */
|
|
13
|
+
|
|
14
|
+
border: solid 1px var(--webchat-colorNeutralStroke1);
|
|
15
|
+
color: var(--webchat-colorGray200);
|
|
16
|
+
font-weight: var(--webchat-fontWeightSemibold);
|
|
17
|
+
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
height: 60px;
|
|
22
|
+
opacity: 0.7;
|
|
23
|
+
padding: 0;
|
|
24
|
+
position: relative;
|
|
25
|
+
touch-action: none;
|
|
26
|
+
user-select: none;
|
|
27
|
+
width: 60px;
|
|
28
|
+
|
|
29
|
+
&:hover {
|
|
30
|
+
/* backgroundColor: isHighContrastTheme() ? gray210 : isDarkTheme() ? gray150 : gray30 */
|
|
31
|
+
background-color: var(--webchat-colorGray30)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:global(.webchat-fluent) .telephone-keypad__button__ruby {
|
|
36
|
+
/* color: isHighContrastTheme() ? white : isDarkTheme() ? gray40 : gray160, */
|
|
37
|
+
color: var(--webchat-colorGray190);
|
|
38
|
+
font-size: 10px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
:global(.webchat-fluent) .telephone-keypad__button__text {
|
|
42
|
+
font-size: 24px;
|
|
43
|
+
margin-top: 8px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:global(.webchat-fluent) .telephone-keypad--horizontal {
|
|
47
|
+
& .telephone-keypad__button {
|
|
48
|
+
height: 32px;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
margin: 8px 4px;
|
|
51
|
+
width: 32px;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
.telephone-keypad__button__ruby {
|
|
55
|
+
display: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
& .telephone-keypad__button__text {
|
|
59
|
+
font-size: 20px;
|
|
60
|
+
margin-top: 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -2,72 +2,10 @@ import React, { forwardRef, memo, useCallback, type Ref } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { useRefFrom } from 'use-ref-from';
|
|
4
4
|
|
|
5
|
-
import { useStyles } from '../../../styles';
|
|
6
5
|
import { type DTMF } from '../types';
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
'-webkit-user-select': 'none',
|
|
11
|
-
alignItems: 'center',
|
|
12
|
-
appearance: 'none',
|
|
13
|
-
// backgroundColor: isDarkTheme() || isHighContrastTheme() ? black : white,
|
|
14
|
-
backgroundColor: 'White',
|
|
15
|
-
borderRadius: '100%',
|
|
16
|
-
|
|
17
|
-
// Whitelabel styles
|
|
18
|
-
// border: `solid 1px ${isHighContrastTheme() ? white : isDarkTheme() ? gray160 : gray40}`,
|
|
19
|
-
// color: 'inherit',
|
|
20
|
-
|
|
21
|
-
border: 'solid 1px var(--webchat-colorNeutralStroke1)',
|
|
22
|
-
color: 'var(--webchat-colorNeutralForeground1)',
|
|
23
|
-
fontWeight: 'var(--webchat-fontWeightSemibold)',
|
|
24
|
-
|
|
25
|
-
cursor: 'pointer',
|
|
26
|
-
display: 'flex',
|
|
27
|
-
flexDirection: 'column',
|
|
28
|
-
height: 60,
|
|
29
|
-
opacity: 0.7,
|
|
30
|
-
padding: 0,
|
|
31
|
-
position: 'relative',
|
|
32
|
-
touchAction: 'none',
|
|
33
|
-
userSelect: 'none',
|
|
34
|
-
width: 60,
|
|
35
|
-
|
|
36
|
-
'&:hover': {
|
|
37
|
-
// backgroundColor: isHighContrastTheme() ? gray210 : isDarkTheme() ? gray150 : gray30
|
|
38
|
-
backgroundColor: 'var(--webchat-colorGray30)'
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
'webchat__telephone-keypad__button__ruby': {
|
|
43
|
-
// color: isHighContrastTheme() ? white : isDarkTheme() ? gray40 : gray160,
|
|
44
|
-
color: 'var(--webchat-colorGray160)',
|
|
45
|
-
fontSize: 10
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
'webchat__telephone-keypad__button__text': {
|
|
49
|
-
fontSize: 24,
|
|
50
|
-
marginTop: 8
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
'webchat__telephone-keypad--horizontal': {
|
|
54
|
-
'& .webchat__telephone-keypad__button': {
|
|
55
|
-
height: 32,
|
|
56
|
-
width: 32,
|
|
57
|
-
margin: '8px 4px',
|
|
58
|
-
justifyContent: 'center'
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
'webchat__telephone-keypad__button__ruby': {
|
|
62
|
-
display: 'none'
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
'& .webchat__telephone-keypad__button__text': {
|
|
66
|
-
fontSize: 20,
|
|
67
|
-
marginTop: 0
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
7
|
+
import styles from './Button.module.css';
|
|
8
|
+
import { useStyles } from '../../../styles';
|
|
71
9
|
|
|
72
10
|
type Props = Readonly<{
|
|
73
11
|
button: DTMF;
|
|
@@ -87,16 +25,16 @@ const Button = memo(
|
|
|
87
25
|
|
|
88
26
|
return (
|
|
89
27
|
<button
|
|
90
|
-
className={classNames['
|
|
28
|
+
className={classNames['telephone-keypad__button']}
|
|
91
29
|
data-testid={dataTestId}
|
|
92
30
|
onClick={handleClick}
|
|
93
31
|
ref={ref}
|
|
94
32
|
type="button"
|
|
95
33
|
>
|
|
96
|
-
<span className={classNames['
|
|
34
|
+
<span className={classNames['telephone-keypad__button__text']}>
|
|
97
35
|
{button === 'star' ? '\u2217' : button === 'pound' ? '#' : button}
|
|
98
36
|
</span>
|
|
99
|
-
{!!ruby && <ruby className={classNames['
|
|
37
|
+
{!!ruby && <ruby className={classNames['telephone-keypad__button__ruby']}>{ruby}</ruby>}
|
|
100
38
|
</button>
|
|
101
39
|
);
|
|
102
40
|
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
:global(.webchat-fluent) .telephone-keypad {
|
|
3
|
+
/* Commented out whitelabel styles for now. */
|
|
4
|
+
/* background: getHighContrastDarkThemeColor(highContrastColor: black, darkThemeColor: gray190, string, defaultColor: gray10), */
|
|
5
|
+
/* borderRadius: '8px 8px 0px 0px; */
|
|
6
|
+
/* boxShadow: '-3px 0px 7px 0px rgba(0, 0, 0, 0.13), -0.6px 0px 1.8px 0px rgba(0, 0, 0, 0.10)', */
|
|
7
|
+
|
|
8
|
+
align-items: center;
|
|
9
|
+
background: var(--webchat-colorNeutralBackground1);
|
|
10
|
+
/* border: isHighContrastTheme() ? `1px solid ${white}` : none; */
|
|
11
|
+
border: none;
|
|
12
|
+
border-radius: var(--webchat-borderRadiusXLarge);
|
|
13
|
+
/* boxShadow: var(--shadow16); */
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
font-family: var(--webchat-fontFamilyBase);
|
|
17
|
+
justify-content: center;
|
|
18
|
+
/* margin: var(--spacingHorizontalMNudge)' */
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:global(.webchat-fluent) .telephone-keypad__box {
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
display: grid;
|
|
24
|
+
gap: 16px;
|
|
25
|
+
grid-template-columns: repeat(3, 1fr);
|
|
26
|
+
grid-template-rows: repeat(4, 1fr);
|
|
27
|
+
justify-items: center;
|
|
28
|
+
padding: 16px;
|
|
29
|
+
width: 100%;
|
|
30
|
+
}
|
|
@@ -1,44 +1,13 @@
|
|
|
1
1
|
import React, { KeyboardEventHandler, memo, useCallback, useEffect, useRef, type ReactNode } from 'react';
|
|
2
2
|
import { useRefFrom } from 'use-ref-from';
|
|
3
3
|
|
|
4
|
-
import { useStyles } from '../../../styles';
|
|
5
4
|
import Button from './Button';
|
|
6
5
|
// import HorizontalDialPadController from './HorizontalDialPadController';
|
|
7
6
|
import testIds from '../../../testIds';
|
|
8
7
|
import { type DTMF } from '../types';
|
|
9
8
|
import useShown from '../useShown';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'webchat__telephone-keypad': {
|
|
13
|
-
/* Commented out whitelabel styles for now. */
|
|
14
|
-
// background: getHighContrastDarkThemeColor(highContrastColor: black, darkThemeColor: gray190, string, defaultColor: gray10),
|
|
15
|
-
// borderRadius: '8px 8px 0px 0px',
|
|
16
|
-
// boxShadow: '-3px 0px 7px 0px rgba(0, 0, 0, 0.13), -0.6px 0px 1.8px 0px rgba(0, 0, 0, 0.10)',
|
|
17
|
-
|
|
18
|
-
alignItems: 'center',
|
|
19
|
-
background: 'var(--webchat-colorNeutralBackground1)',
|
|
20
|
-
// border: isHighContrastTheme() ? `1px solid ${white}` : 'none',
|
|
21
|
-
border: 'none',
|
|
22
|
-
borderRadius: 'var(--webchat-borderRadiusXLarge)',
|
|
23
|
-
// boxShadow: 'var(--shadow16)',
|
|
24
|
-
display: 'flex',
|
|
25
|
-
flexDirection: 'column',
|
|
26
|
-
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
27
|
-
justifyContent: 'center'
|
|
28
|
-
// margin: 'var(--spacingHorizontalMNudge)'
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
'webchat__telephone-keypad__box': {
|
|
32
|
-
boxSizing: 'border-box',
|
|
33
|
-
display: 'grid',
|
|
34
|
-
gap: '16px',
|
|
35
|
-
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
36
|
-
gridTemplateRows: 'repeat(4, 1fr)',
|
|
37
|
-
justifyItems: 'center',
|
|
38
|
-
padding: '16px',
|
|
39
|
-
width: '100%'
|
|
40
|
-
}
|
|
41
|
-
};
|
|
9
|
+
import styles from './TelephoneKeypad.module.css';
|
|
10
|
+
import { useStyles } from '../../../styles';
|
|
42
11
|
|
|
43
12
|
type Props = Readonly<{
|
|
44
13
|
autoFocus?: boolean | undefined;
|
|
@@ -54,7 +23,7 @@ const Orientation = memo(
|
|
|
54
23
|
// <HorizontalDialPadController>{children}</HorizontalDialPadController>
|
|
55
24
|
false
|
|
56
25
|
) : (
|
|
57
|
-
<div className={classNames['
|
|
26
|
+
<div className={classNames['telephone-keypad__box']}>{children}</div>
|
|
58
27
|
);
|
|
59
28
|
}
|
|
60
29
|
);
|
|
@@ -95,7 +64,7 @@ const TelephoneKeypad = memo(({ autoFocus, onButtonClick, isHorizontal }: Props)
|
|
|
95
64
|
}, [autoFocusRef, firstButtonRef]);
|
|
96
65
|
|
|
97
66
|
return (
|
|
98
|
-
<div className={classNames['
|
|
67
|
+
<div className={classNames['telephone-keypad']} onKeyDown={handleKeyDown}>
|
|
99
68
|
<Orientation isHorizontal={isHorizontal}>
|
|
100
69
|
<Button
|
|
101
70
|
button="1"
|
package/src/env.d.ts
ADDED
package/src/index.ts
CHANGED
|
@@ -2,9 +2,12 @@ import { injectMetaTag } from 'inject-meta-tag';
|
|
|
2
2
|
|
|
3
3
|
import FluentThemeProvider from './private/FluentThemeProvider';
|
|
4
4
|
import testIds from './testIds';
|
|
5
|
+
import { injectStyle } from './styles';
|
|
5
6
|
|
|
6
7
|
declare const NPM_PACKAGE_VERSION: string;
|
|
7
8
|
|
|
8
9
|
injectMetaTag('botframework-webchat-fluent-theme:version', NPM_PACKAGE_VERSION);
|
|
9
10
|
|
|
11
|
+
injectStyle();
|
|
12
|
+
|
|
10
13
|
export { FluentThemeProvider, testIds };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const injectedStyles = '@--INJECTED-STYLES-CONTENT--@';
|
|
2
|
+
|
|
3
|
+
export default function injectStyles() {
|
|
4
|
+
if (globalThis.document) {
|
|
5
|
+
const style = document.createElement('style');
|
|
6
|
+
style.append(document.createTextNode(injectedStyles));
|
|
7
|
+
document.head.appendChild(style);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
function useStyles<T extends CSSModuleClasses>(styles: T): T {
|
|
4
|
+
// @ts-expect-error: entries/fromEntries don't allow to specify keys type
|
|
5
|
+
return useMemo(
|
|
6
|
+
() =>
|
|
7
|
+
Object.freeze(
|
|
8
|
+
Object.fromEntries(
|
|
9
|
+
Object.entries(styles).map(([baseClassName, resultClassName]) => [
|
|
10
|
+
baseClassName,
|
|
11
|
+
`${baseClassName} ${resultClassName}`
|
|
12
|
+
])
|
|
13
|
+
)
|
|
14
|
+
),
|
|
15
|
+
[styles]
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default useStyles;
|