botframework-webchat 4.14.1 → 4.15.2-main.20220413.af6e8a3
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/.eslintrc.yml +5 -109
- package/.prettierrc.yml +1 -1
- package/README.md +1 -1
- package/lib/AddFullBundle.d.ts.map +1 -1
- package/lib/AddFullBundle.js +1 -2
- package/lib/FullComposer.d.ts.map +1 -1
- package/lib/FullComposer.js +3 -3
- package/lib/FullReactWebChat.js +2 -2
- package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.js +3 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.js +10 -3
- package/lib/adaptiveCards/Attachment/AdaptiveCardContent.js +2 -2
- package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts +3 -2
- package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.js +138 -74
- package/lib/adaptiveCards/Attachment/AnimationCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/AnimationCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/AnimationCardContent.js +3 -1
- package/lib/adaptiveCards/Attachment/AudioCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/AudioCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/AudioCardContent.js +3 -1
- package/lib/adaptiveCards/Attachment/HeroCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/HeroCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/HeroCardContent.js +4 -2
- package/lib/adaptiveCards/Attachment/OAuthCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/OAuthCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/OAuthCardContent.js +3 -1
- package/lib/adaptiveCards/Attachment/ReceiptCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/ReceiptCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/ReceiptCardContent.js +3 -1
- package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/SignInCardContent.js +1 -1
- package/lib/adaptiveCards/Attachment/ThumbnailCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/ThumbnailCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/ThumbnailCardContent.js +3 -1
- package/lib/adaptiveCards/Attachment/VideoCardContent.d.ts +1 -1
- package/lib/adaptiveCards/Attachment/VideoCardContent.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/VideoCardContent.js +5 -3
- package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.d.ts +3 -0
- package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.d.ts.map +1 -1
- package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.js +8 -1
- package/lib/adaptiveCards/Styles/adaptiveCardHostConfig.js +2 -2
- package/lib/adaptiveCards/Styles/createAdaptiveCardsStyleSet.js +2 -2
- package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.d.ts.map +1 -1
- package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js +26 -29
- package/lib/adaptiveCards/normalizeStyleOptions.js +2 -2
- package/lib/addVersion.js +2 -2
- package/lib/createDirectLineSpeechAdapters.d.ts +1 -1
- package/lib/createDirectLineSpeechAdapters.d.ts.map +1 -1
- package/lib/createDirectLineSpeechAdapters.js +1 -1
- package/lib/createFullStyleSet.d.ts +325 -56
- package/lib/createFullStyleSet.d.ts.map +1 -1
- package/lib/createFullStyleSet.js +2 -2
- package/lib/fullBundleDefaultStyleOptions.js +2 -2
- package/lib/index-es5.d.ts +1 -21
- package/lib/index-es5.d.ts.map +1 -1
- package/lib/index-es5.js +4 -44
- package/lib/index-minimal.js +22 -20
- package/lib/index.d.ts +30 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +11 -8
- package/lib/polyfill.d.ts +23 -0
- package/lib/polyfill.d.ts.map +1 -0
- package/lib/polyfill.js +46 -0
- package/lib/renderMarkdown.d.ts.map +1 -1
- package/lib/renderMarkdown.js +34 -6
- package/lib/speech/CustomAudioInputStream.d.ts.map +1 -1
- package/lib/speech/CustomAudioInputStream.js +40 -15
- package/lib/speech/bytesPerSample.d.ts.map +1 -1
- package/lib/speech/bytesPerSample.js +3 -1
- package/lib/speech/createAudioConfig.d.ts.map +1 -1
- package/lib/speech/createAudioConfig.js +9 -3
- package/lib/speech/createMicrophoneAudioConfigAndAudioContext.d.ts.map +1 -1
- package/lib/speech/createMicrophoneAudioConfigAndAudioContext.js +3 -1
- package/lib/speech/getUserMedia.d.ts.map +1 -1
- package/lib/speech/getUserMedia.js +5 -2
- package/package.json +43 -43
- package/src/AddFullBundle.tsx +0 -1
- package/src/FullComposer.tsx +2 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardAttachment.tsx +3 -1
- package/src/adaptiveCards/Attachment/AdaptiveCardBuilder.ts +8 -3
- package/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx +183 -89
- package/src/adaptiveCards/Attachment/AnimationCardContent.tsx +3 -1
- package/src/adaptiveCards/Attachment/AudioCardContent.tsx +3 -1
- package/src/adaptiveCards/Attachment/HeroCardContent.tsx +4 -2
- package/src/adaptiveCards/Attachment/OAuthCardContent.tsx +3 -1
- package/src/adaptiveCards/Attachment/ReceiptCardContent.tsx +28 -48
- package/src/adaptiveCards/Attachment/SignInCardContent.tsx +1 -1
- package/src/adaptiveCards/Attachment/ThumbnailCardContent.tsx +3 -1
- package/src/adaptiveCards/Attachment/VideoCardContent.tsx +5 -3
- package/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.ts +8 -0
- package/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.tsx +0 -1
- package/src/createCognitiveServicesSpeechServicesPonyfillFactory.spec.js +2 -3
- package/src/createDirectLineSpeechAdapters.ts +1 -1
- package/src/index-es5.ts +3 -26
- package/src/polyfill.ts +29 -0
- package/src/renderMarkdown.ts +40 -4
- package/src/speech/CustomAudioInputStream.ts +38 -7
- package/src/speech/bytesPerSample.ts +2 -0
- package/src/speech/createAudioConfig.spec.js +1 -1
- package/src/speech/createAudioConfig.ts +7 -0
- package/src/speech/createMicrophoneAudioConfigAndAudioContext.ts +2 -0
- package/src/speech/getUserMedia.ts +4 -1
- package/.eslintignore +0 -1
|
@@ -1,37 +1,65 @@
|
|
|
1
1
|
/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 2] }] */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Action as AdaptiveCardAction,
|
|
5
|
+
AdaptiveCard,
|
|
6
|
+
IMarkdownProcessingResult,
|
|
7
|
+
OpenUrlAction,
|
|
8
|
+
SubmitAction
|
|
9
|
+
} from 'adaptivecards';
|
|
4
10
|
import { Components, getTabIndex, hooks } from 'botframework-webchat-component';
|
|
5
|
-
import { DirectLineCardAction } from 'botframework-webchat-core';
|
|
6
11
|
import classNames from 'classnames';
|
|
7
12
|
import PropTypes from 'prop-types';
|
|
8
|
-
import React, {
|
|
13
|
+
import React, {
|
|
14
|
+
KeyboardEventHandler,
|
|
15
|
+
MouseEventHandler,
|
|
16
|
+
useCallback,
|
|
17
|
+
useEffect,
|
|
18
|
+
useLayoutEffect,
|
|
19
|
+
useRef,
|
|
20
|
+
useState,
|
|
21
|
+
VFC
|
|
22
|
+
} from 'react';
|
|
23
|
+
import type { DirectLineCardAction } from 'botframework-webchat-core';
|
|
9
24
|
|
|
25
|
+
import { BotFrameworkCardAction } from './AdaptiveCardBuilder';
|
|
10
26
|
import useAdaptiveCardsHostConfig from '../hooks/useAdaptiveCardsHostConfig';
|
|
11
27
|
import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
|
|
12
|
-
import { BotFrameworkCardAction } from './AdaptiveCardBuilder';
|
|
13
28
|
|
|
14
29
|
const { ErrorBox } = Components;
|
|
15
30
|
const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd, useStyleSet } = hooks;
|
|
16
31
|
|
|
17
|
-
// eslint-disable-next-line no-undef
|
|
18
32
|
const node_env = process.env.node_env || process.env.NODE_ENV;
|
|
19
33
|
|
|
20
|
-
|
|
21
|
-
const classNames = new Set(element.className.split(' '));
|
|
34
|
+
type UndoFunction = (() => void) | undefined;
|
|
22
35
|
|
|
23
|
-
|
|
24
|
-
|
|
36
|
+
function bunchUndos(...fns: UndoFunction[]): UndoFunction {
|
|
37
|
+
return () => fns.forEach(fn => fn?.());
|
|
38
|
+
}
|
|
25
39
|
|
|
26
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Adds a class to the `HTMLElement`. Returns `true` if the class is added, otherwise, `undefined`.
|
|
42
|
+
*/
|
|
43
|
+
function addClass(element: HTMLElement, className: string): true | undefined {
|
|
44
|
+
const { classList } = element;
|
|
45
|
+
|
|
46
|
+
if (!classList.contains(className)) {
|
|
47
|
+
classList.add(className);
|
|
27
48
|
|
|
28
49
|
return true;
|
|
29
50
|
}
|
|
30
|
-
|
|
31
|
-
return false;
|
|
32
51
|
}
|
|
33
52
|
|
|
34
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Adds a class to the `HTMLElement` and re-add on mutations.
|
|
55
|
+
*
|
|
56
|
+
* @returns {function} A function, when called, will restore to previous state.
|
|
57
|
+
*/
|
|
58
|
+
function addPersistentClassWithUndo(element: HTMLElement | undefined, className: string): UndoFunction {
|
|
59
|
+
if (!element) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
35
63
|
if (addClass(element, className)) {
|
|
36
64
|
// After we add the class, keep observing the element to make sure the class is not removed.
|
|
37
65
|
const observer = new MutationObserver(() => addClass(element, className));
|
|
@@ -49,11 +77,27 @@ function addPersistentClassWithUndo(element, className) {
|
|
|
49
77
|
}
|
|
50
78
|
}
|
|
51
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Returns `true`, if the object is a plain object and not a class, otherwise, `false`.
|
|
82
|
+
*/
|
|
52
83
|
function isPlainObject(obj) {
|
|
53
84
|
return Object.getPrototypeOf(obj) === Object.prototype;
|
|
54
85
|
}
|
|
55
86
|
|
|
56
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Sets an attribute.
|
|
89
|
+
*
|
|
90
|
+
* @returns {function} A function, when called, will restore to previous state.
|
|
91
|
+
*/
|
|
92
|
+
function setAttributeWithUndo(
|
|
93
|
+
element: HTMLElement | undefined,
|
|
94
|
+
qualifiedName: string,
|
|
95
|
+
nextValue: string
|
|
96
|
+
): UndoFunction {
|
|
97
|
+
if (!element) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
57
101
|
const value = element.getAttribute(qualifiedName);
|
|
58
102
|
|
|
59
103
|
if (value !== nextValue) {
|
|
@@ -63,15 +107,29 @@ function setAttributeWithUndo(element, qualifiedName, nextValue) {
|
|
|
63
107
|
}
|
|
64
108
|
}
|
|
65
109
|
|
|
66
|
-
|
|
110
|
+
/**
|
|
111
|
+
* An event handler for disabling event bubbling and propagation.
|
|
112
|
+
*/
|
|
113
|
+
const disabledHandler = (event: Event) => {
|
|
67
114
|
event.preventDefault();
|
|
68
115
|
event.stopImmediatePropagation();
|
|
69
116
|
event.stopPropagation();
|
|
70
117
|
};
|
|
71
118
|
|
|
72
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Listens to event once. Returns a function, when called, will stop listening.
|
|
121
|
+
*/
|
|
122
|
+
function addEventListenerOnceWithUndo(
|
|
123
|
+
element: HTMLElement | undefined,
|
|
124
|
+
name: string,
|
|
125
|
+
handler: EventListener
|
|
126
|
+
): UndoFunction {
|
|
127
|
+
if (!element) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
73
131
|
/* eslint-disable-next-line prefer-const */
|
|
74
|
-
let detach;
|
|
132
|
+
let detach: () => void;
|
|
75
133
|
const detachingHandler = event => {
|
|
76
134
|
try {
|
|
77
135
|
handler(event);
|
|
@@ -88,14 +146,34 @@ function addEventListenerOnceWithUndo(element, name, handler) {
|
|
|
88
146
|
return detach;
|
|
89
147
|
}
|
|
90
148
|
|
|
91
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Listens to event. Returns a function, when called, will stop listening.
|
|
151
|
+
*/
|
|
152
|
+
function addEventListenerWithUndo(
|
|
153
|
+
element: HTMLElement | undefined,
|
|
154
|
+
name: string,
|
|
155
|
+
handler: EventListener
|
|
156
|
+
): UndoFunction {
|
|
157
|
+
if (!element) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
92
161
|
element.addEventListener(name, handler);
|
|
93
162
|
|
|
94
163
|
return () => element.removeEventListener(name, handler);
|
|
95
164
|
}
|
|
96
165
|
|
|
97
|
-
|
|
98
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Disables an element with undo function.
|
|
168
|
+
*
|
|
169
|
+
* @returns {function} A function, when called, will restore to previous state.
|
|
170
|
+
*/
|
|
171
|
+
function disableElementWithUndo(element: HTMLElement | undefined): UndoFunction {
|
|
172
|
+
if (!element) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const undoStack: UndoFunction[] = [];
|
|
99
177
|
const isActive = element === document.activeElement;
|
|
100
178
|
const tag = element.nodeName.toLowerCase();
|
|
101
179
|
|
|
@@ -131,11 +209,23 @@ function disableElementWithUndo(element) {
|
|
|
131
209
|
break;
|
|
132
210
|
}
|
|
133
211
|
|
|
134
|
-
return (
|
|
212
|
+
return bunchUndos(...undoStack);
|
|
135
213
|
}
|
|
136
214
|
|
|
137
|
-
|
|
138
|
-
|
|
215
|
+
/**
|
|
216
|
+
* Disables all inputtable descendants.
|
|
217
|
+
*
|
|
218
|
+
* @param {HTMLElement | undefined} element Container element to start looking for inputtable descendants.
|
|
219
|
+
* @param {boolean} observeSubtree `true` to applies to all future inputtable descendants, otherwise, `false`.
|
|
220
|
+
*
|
|
221
|
+
* @returns {function} A function, when called, will restore to previous state.
|
|
222
|
+
*/
|
|
223
|
+
function disableInputElementsWithUndo(element: HTMLElement | undefined, observeSubtree = true): UndoFunction {
|
|
224
|
+
if (!element) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const undoStack: (() => void)[] = [].map.call(element.querySelectorAll('button, input, select, textarea'), element =>
|
|
139
229
|
disableElementWithUndo(element)
|
|
140
230
|
);
|
|
141
231
|
|
|
@@ -157,18 +247,7 @@ function disableInputElementsWithUndo(element: HTMLElement, observeSubtree = tru
|
|
|
157
247
|
undoStack.push(() => observer.disconnect());
|
|
158
248
|
}
|
|
159
249
|
|
|
160
|
-
return (
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Checks if an element contains a class.
|
|
165
|
-
*
|
|
166
|
-
* @param {HTMLElement} element - The element to check for the class.
|
|
167
|
-
* @param {string} className - The name of the class to check for.
|
|
168
|
-
* @returns {boolean} `true` if the element contains the class, otherwise, `false`.
|
|
169
|
-
*/
|
|
170
|
-
function containsClassName(element: HTMLElement, className: string): boolean {
|
|
171
|
-
return (element.className || '').split(' ').includes(className);
|
|
250
|
+
return bunchUndos(...undoStack);
|
|
172
251
|
}
|
|
173
252
|
|
|
174
253
|
/**
|
|
@@ -177,7 +256,7 @@ function containsClassName(element: HTMLElement, className: string): boolean {
|
|
|
177
256
|
* @returns {false | string} The value of the attribute. `false` if the attribute was not set.
|
|
178
257
|
*/
|
|
179
258
|
function getAttribute(element: HTMLElement, qualifiedName: string): false | string {
|
|
180
|
-
return element.hasAttribute(qualifiedName) && element.getAttribute(qualifiedName);
|
|
259
|
+
return !!element && element.hasAttribute(qualifiedName) && (element.getAttribute(qualifiedName) || '');
|
|
181
260
|
}
|
|
182
261
|
|
|
183
262
|
/**
|
|
@@ -187,11 +266,11 @@ function getAttribute(element: HTMLElement, qualifiedName: string): false | stri
|
|
|
187
266
|
* @param {string} qualifiedName - The name of the attribute.
|
|
188
267
|
* @param {false | string} value - The value of the attribute. When passing `false`, remove the attribute.
|
|
189
268
|
*/
|
|
190
|
-
function setOrRemoveAttribute(element: HTMLElement, qualifiedName: string, value: false | string): void {
|
|
269
|
+
function setOrRemoveAttribute(element: HTMLElement | undefined, qualifiedName: string, value: false | string): void {
|
|
191
270
|
if (value === false) {
|
|
192
|
-
element
|
|
271
|
+
element?.removeAttribute(qualifiedName);
|
|
193
272
|
} else {
|
|
194
|
-
element
|
|
273
|
+
element?.setAttribute(qualifiedName, value);
|
|
195
274
|
}
|
|
196
275
|
}
|
|
197
276
|
|
|
@@ -204,7 +283,15 @@ function setOrRemoveAttribute(element: HTMLElement, qualifiedName: string, value
|
|
|
204
283
|
*
|
|
205
284
|
* @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
|
|
206
285
|
*/
|
|
207
|
-
function setOrRemoveAttributeWithUndo(
|
|
286
|
+
function setOrRemoveAttributeWithUndo(
|
|
287
|
+
element: HTMLElement | undefined,
|
|
288
|
+
qualifiedName: string,
|
|
289
|
+
value: false | string
|
|
290
|
+
): UndoFunction {
|
|
291
|
+
if (!element) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
208
295
|
const prevValue = getAttribute(element, qualifiedName);
|
|
209
296
|
|
|
210
297
|
setOrRemoveAttribute(element, qualifiedName, value);
|
|
@@ -221,14 +308,12 @@ function setOrRemoveAttributeWithUndo(element: HTMLElement, qualifiedName: strin
|
|
|
221
308
|
* @returns {HTMLElement | undefined} The first ancestor that fulfill the predicate, otherwise, `undefined`.
|
|
222
309
|
*/
|
|
223
310
|
function findAncestor(element: HTMLElement, predicate: (ancestor: HTMLElement) => boolean): HTMLElement | undefined {
|
|
224
|
-
let current = element
|
|
311
|
+
let current = element;
|
|
225
312
|
|
|
226
|
-
while (current) {
|
|
313
|
+
while ((current = current.parentElement)) {
|
|
227
314
|
if (predicate.call(element, current)) {
|
|
228
315
|
return current;
|
|
229
316
|
}
|
|
230
|
-
|
|
231
|
-
current = current.parentElement;
|
|
232
317
|
}
|
|
233
318
|
}
|
|
234
319
|
|
|
@@ -244,15 +329,15 @@ function findAncestor(element: HTMLElement, predicate: (ancestor: HTMLElement) =
|
|
|
244
329
|
* @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
|
|
245
330
|
*/
|
|
246
331
|
function indicateActionSelectionWithUndo(
|
|
247
|
-
selectedActionElements: HTMLElement[],
|
|
332
|
+
selectedActionElements: HTMLElement[] | undefined,
|
|
248
333
|
actionPerformedClassName?: string
|
|
249
|
-
):
|
|
250
|
-
if (!selectedActionElements
|
|
334
|
+
): UndoFunction {
|
|
335
|
+
if (!selectedActionElements?.length) {
|
|
251
336
|
return;
|
|
252
337
|
}
|
|
253
338
|
|
|
254
339
|
// Verify all input elements are "ac-pushButton", could belongs to ActionSet or "card actions".
|
|
255
|
-
if (selectedActionElements.some(actionElement => !
|
|
340
|
+
if (selectedActionElements.some(actionElement => !actionElement.classList.contains('ac-pushButton'))) {
|
|
256
341
|
console.warn(
|
|
257
342
|
'botframework-webchat: Cannot mark selected action in the card, some elements are not an "ac-pushButton".'
|
|
258
343
|
);
|
|
@@ -299,7 +384,7 @@ function indicateActionSelectionWithUndo(
|
|
|
299
384
|
);
|
|
300
385
|
});
|
|
301
386
|
|
|
302
|
-
return (
|
|
387
|
+
return bunchUndos(...undoStack);
|
|
303
388
|
}
|
|
304
389
|
|
|
305
390
|
/**
|
|
@@ -307,21 +392,21 @@ function indicateActionSelectionWithUndo(
|
|
|
307
392
|
*
|
|
308
393
|
* @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
|
|
309
394
|
*/
|
|
310
|
-
function fixAccessibilityIssuesWithUndo(element: HTMLElement):
|
|
311
|
-
|
|
312
|
-
|
|
395
|
+
function fixAccessibilityIssuesWithUndo(element: HTMLElement): UndoFunction {
|
|
396
|
+
if (!element) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
313
399
|
|
|
400
|
+
// These hacks should be done in Adaptive Cards library instead.
|
|
314
401
|
// Related to #3949: All action buttons inside role="menubar" should be role="menuitem".
|
|
315
|
-
undoStack.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
)
|
|
319
|
-
);
|
|
402
|
+
const undoStack: UndoFunction[] = Array.from(
|
|
403
|
+
element.querySelectorAll('.ac-actionSet[role="menubar"] [role="button"]') as NodeListOf<HTMLElement>
|
|
404
|
+
).map(actionButton => setAttributeWithUndo(actionButton, 'role', 'menuitem'));
|
|
320
405
|
|
|
321
|
-
return () => undoStack.forEach(undo => undo());
|
|
406
|
+
return () => undoStack.forEach(undo => undo?.());
|
|
322
407
|
}
|
|
323
408
|
|
|
324
|
-
function getFocusableElements(element) {
|
|
409
|
+
function getFocusableElements(element: HTMLElement) {
|
|
325
410
|
return [].filter.call(
|
|
326
411
|
element.querySelectorAll(
|
|
327
412
|
[
|
|
@@ -338,7 +423,7 @@ function getFocusableElements(element) {
|
|
|
338
423
|
'textarea',
|
|
339
424
|
'[tabindex]'
|
|
340
425
|
].join(', ')
|
|
341
|
-
)
|
|
426
|
+
) as NodeListOf<HTMLElement>,
|
|
342
427
|
element => {
|
|
343
428
|
const tabIndex = getTabIndex(element);
|
|
344
429
|
|
|
@@ -347,49 +432,55 @@ function getFocusableElements(element) {
|
|
|
347
432
|
);
|
|
348
433
|
}
|
|
349
434
|
|
|
350
|
-
function restoreActiveElementIndex(element, activeElementIndex) {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
focusable && focusable.focus();
|
|
435
|
+
function restoreActiveElementIndex(element: HTMLElement, activeElementIndex: number) {
|
|
436
|
+
getFocusableElements(element)[+activeElementIndex]?.focus();
|
|
354
437
|
}
|
|
355
438
|
|
|
356
|
-
function saveActiveElementIndex(element) {
|
|
439
|
+
function saveActiveElementIndex(element: HTMLElement) {
|
|
357
440
|
return getFocusableElements(element).indexOf(document.activeElement);
|
|
358
441
|
}
|
|
359
442
|
|
|
360
|
-
function restoreInputValues(element, inputValues) {
|
|
361
|
-
const inputs = element.querySelectorAll('input, select, textarea')
|
|
443
|
+
function restoreInputValues(element: HTMLElement, inputValues: (boolean | string)[]) {
|
|
444
|
+
const inputs = element.querySelectorAll('input, select, textarea') as NodeListOf<
|
|
445
|
+
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
446
|
+
>;
|
|
362
447
|
|
|
363
|
-
[].forEach.call(inputs, (input, index) => {
|
|
364
|
-
const value = inputValues[index];
|
|
448
|
+
[].forEach.call(inputs, (input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, index: number) => {
|
|
449
|
+
const value = inputValues[+index];
|
|
365
450
|
|
|
366
451
|
if (typeof value !== 'undefined') {
|
|
367
452
|
const { tagName, type } = input;
|
|
368
453
|
|
|
369
454
|
if (tagName === 'INPUT' && (type === 'checkbox' || type === 'radio')) {
|
|
370
|
-
|
|
371
|
-
|
|
455
|
+
if (typeof value === 'boolean') {
|
|
456
|
+
(input as HTMLInputElement).checked = value;
|
|
457
|
+
}
|
|
458
|
+
} else if (typeof value === 'string') {
|
|
372
459
|
input.value = value;
|
|
373
460
|
}
|
|
374
461
|
}
|
|
375
462
|
});
|
|
376
463
|
}
|
|
377
464
|
|
|
378
|
-
function saveInputValues(element) {
|
|
379
|
-
const inputs = element.querySelectorAll('input, select, textarea')
|
|
465
|
+
function saveInputValues(element: HTMLElement): (boolean | string)[] {
|
|
466
|
+
const inputs = element.querySelectorAll('input, select, textarea') as NodeListOf<
|
|
467
|
+
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
468
|
+
>;
|
|
469
|
+
|
|
470
|
+
return [].map.call(inputs, (input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement) => {
|
|
471
|
+
const { type } = input;
|
|
380
472
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
return checked;
|
|
473
|
+
if (input.tagName === 'INPUT' && (type === 'checkbox' || type === 'radio')) {
|
|
474
|
+
return (input as HTMLInputElement).checked;
|
|
384
475
|
}
|
|
385
476
|
|
|
386
|
-
return value;
|
|
477
|
+
return input.value;
|
|
387
478
|
});
|
|
388
479
|
}
|
|
389
480
|
|
|
390
481
|
type AdaptiveCardRendererProps = {
|
|
391
482
|
actionPerformedClassName?: string;
|
|
392
|
-
adaptiveCard:
|
|
483
|
+
adaptiveCard: AdaptiveCard;
|
|
393
484
|
disabled?: boolean;
|
|
394
485
|
tapAction?: DirectLineCardAction;
|
|
395
486
|
};
|
|
@@ -402,7 +493,7 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
402
493
|
}) => {
|
|
403
494
|
const [{ adaptiveCardRenderer: adaptiveCardRendererStyleSet }] = useStyleSet();
|
|
404
495
|
const [{ GlobalSettings, HostConfig }] = useAdaptiveCardsPackage();
|
|
405
|
-
const [actionsPerformed, setActionsPerformed] = useState([]);
|
|
496
|
+
const [actionsPerformed, setActionsPerformed] = useState<AdaptiveCardAction[]>([]);
|
|
406
497
|
const [adaptiveCardsHostConfig] = useAdaptiveCardsHostConfig();
|
|
407
498
|
const [disabledFromComposer] = useDisabled();
|
|
408
499
|
const [errors, setErrors] = useState([]);
|
|
@@ -410,7 +501,7 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
410
501
|
const activeElementIndexRef = useRef(-1);
|
|
411
502
|
const adaptiveCardElementRef = useRef<HTMLElement>();
|
|
412
503
|
const contentRef = useRef<HTMLDivElement>();
|
|
413
|
-
const inputValuesRef = useRef([]);
|
|
504
|
+
const inputValuesRef = useRef<(boolean | string)[]>([]);
|
|
414
505
|
const localize = useLocalizer();
|
|
415
506
|
const performCardAction = usePerformCardAction();
|
|
416
507
|
const renderMarkdownAsHTML = useRenderMarkdownAsHTML();
|
|
@@ -421,8 +512,9 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
421
512
|
// TODO: [P2] #3199 We should consider using `adaptiveCard.selectAction` instead.
|
|
422
513
|
// The null check for "tapAction" is in "handleClickAndKeyPressForTapAction".
|
|
423
514
|
const handleClickAndKeyPress = useCallback(
|
|
424
|
-
event => {
|
|
425
|
-
const { key,
|
|
515
|
+
(event: KeyboardEvent | MouseEvent): void => {
|
|
516
|
+
const { key, type } = event as KeyboardEvent;
|
|
517
|
+
const target = event.target as HTMLDivElement;
|
|
426
518
|
|
|
427
519
|
// Some items, e.g. tappable text, cannot be disabled thru DOM attributes
|
|
428
520
|
const { current } = contentRef;
|
|
@@ -466,12 +558,13 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
466
558
|
const handleClickAndKeyPressForTapAction = !disabled && tapAction ? handleClickAndKeyPress : undefined;
|
|
467
559
|
|
|
468
560
|
const addActionsPerformed = useCallback(
|
|
469
|
-
action
|
|
561
|
+
(action: AdaptiveCardAction): void =>
|
|
562
|
+
!~actionsPerformed.indexOf(action) && setActionsPerformed([...actionsPerformed, action]),
|
|
470
563
|
[actionsPerformed, setActionsPerformed]
|
|
471
564
|
);
|
|
472
565
|
|
|
473
566
|
const handleExecuteAction = useCallback(
|
|
474
|
-
(action:
|
|
567
|
+
(action: AdaptiveCardAction): void => {
|
|
475
568
|
// Some items, e.g. tappable image, cannot be disabled thru DOM attributes
|
|
476
569
|
if (disabled) {
|
|
477
570
|
return;
|
|
@@ -541,7 +634,9 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
541
634
|
// This could be limitations from Adaptive Cards package (not supported as of 1.2.5)
|
|
542
635
|
// Because there could be timing difference between .parse and .render, we could be using wrong Markdown engine
|
|
543
636
|
|
|
544
|
-
|
|
637
|
+
// "onProcessMarkdown" is a static function but we are trying to scope it to the current object instead.
|
|
638
|
+
// eslint-disable-next-line dot-notation
|
|
639
|
+
adaptiveCard.constructor['onProcessMarkdown'] = (text: string, result: IMarkdownProcessingResult) => {
|
|
545
640
|
if (renderMarkdownAsHTML) {
|
|
546
641
|
result.outputHtml = renderMarkdownAsHTML(text);
|
|
547
642
|
result.didProcess = true;
|
|
@@ -563,7 +658,7 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
563
658
|
return setErrors(validationEvents.reduce((items, { message }) => [...items, new Error(message)], []));
|
|
564
659
|
}
|
|
565
660
|
|
|
566
|
-
let element;
|
|
661
|
+
let element: HTMLElement;
|
|
567
662
|
|
|
568
663
|
try {
|
|
569
664
|
element = adaptiveCard.render();
|
|
@@ -642,8 +737,8 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
642
737
|
) : (
|
|
643
738
|
<div
|
|
644
739
|
className={classNames(adaptiveCardRendererStyleSet + '', 'webchat__adaptive-card-renderer')}
|
|
645
|
-
onClick={handleClickAndKeyPressForTapAction}
|
|
646
|
-
onKeyPress={handleClickAndKeyPressForTapAction}
|
|
740
|
+
onClick={handleClickAndKeyPressForTapAction as unknown as MouseEventHandler<HTMLDivElement>}
|
|
741
|
+
onKeyPress={handleClickAndKeyPressForTapAction as unknown as KeyboardEventHandler<HTMLDivElement>}
|
|
647
742
|
ref={contentRef}
|
|
648
743
|
/>
|
|
649
744
|
);
|
|
@@ -661,7 +756,6 @@ AdaptiveCardRenderer.propTypes = {
|
|
|
661
756
|
disabled: PropTypes.bool,
|
|
662
757
|
|
|
663
758
|
// TypeScript class is not mappable to PropTypes.func
|
|
664
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
665
759
|
// @ts-ignore
|
|
666
760
|
tapAction: PropTypes.shape({
|
|
667
761
|
image: PropTypes.string,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint react/no-array-index-key: "off" */
|
|
2
2
|
|
|
3
|
-
import { DirectLineAnimationCard } from 'botframework-webchat-core';
|
|
4
3
|
import { Components, hooks } from 'botframework-webchat-component';
|
|
5
4
|
import PropTypes from 'prop-types';
|
|
6
5
|
import React, { FC } from 'react';
|
|
6
|
+
import type { DirectLineAnimationCard } from 'botframework-webchat-core';
|
|
7
7
|
|
|
8
8
|
import CommonCard from './CommonCard';
|
|
9
9
|
|
|
@@ -41,6 +41,8 @@ AnimationCardContent.defaultProps = {
|
|
|
41
41
|
|
|
42
42
|
AnimationCardContent.propTypes = {
|
|
43
43
|
actionPerformedClassName: PropTypes.string,
|
|
44
|
+
// PropTypes cannot fully capture TypeScript types.
|
|
45
|
+
// @ts-ignore
|
|
44
46
|
content: PropTypes.shape({
|
|
45
47
|
media: PropTypes.arrayOf(
|
|
46
48
|
PropTypes.shape({
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* eslint react/no-array-index-key: "off" */
|
|
2
2
|
|
|
3
|
-
import { DirectLineAudioCard } from 'botframework-webchat-core';
|
|
4
3
|
import { Components, hooks } from 'botframework-webchat-component';
|
|
5
4
|
import PropTypes from 'prop-types';
|
|
6
5
|
import React, { FC } from 'react';
|
|
6
|
+
import type { DirectLineAudioCard } from 'botframework-webchat-core';
|
|
7
7
|
|
|
8
8
|
import CommonCard from './CommonCard';
|
|
9
9
|
|
|
@@ -41,6 +41,8 @@ AudioCardContent.defaultProps = {
|
|
|
41
41
|
|
|
42
42
|
AudioCardContent.propTypes = {
|
|
43
43
|
actionPerformedClassName: PropTypes.string,
|
|
44
|
+
// PropTypes cannot fully capture TypeScript types.
|
|
45
|
+
// @ts-ignore
|
|
44
46
|
content: PropTypes.shape({
|
|
45
47
|
autostart: PropTypes.bool,
|
|
46
48
|
autoloop: PropTypes.bool,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DirectLineHeroCard } from 'botframework-webchat-core';
|
|
2
1
|
import { hooks } from 'botframework-webchat-component';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
3
|
import React, { FC, useMemo } from 'react';
|
|
4
|
+
import type { DirectLineHeroCard } from 'botframework-webchat-core';
|
|
5
5
|
|
|
6
6
|
import AdaptiveCardBuilder from './AdaptiveCardBuilder';
|
|
7
7
|
import AdaptiveCardRenderer from './AdaptiveCardRenderer';
|
|
@@ -50,10 +50,12 @@ HeroCardContent.defaultProps = {
|
|
|
50
50
|
|
|
51
51
|
HeroCardContent.propTypes = {
|
|
52
52
|
actionPerformedClassName: PropTypes.string,
|
|
53
|
+
// PropTypes cannot fully capture TypeScript types.
|
|
54
|
+
// @ts-ignore
|
|
53
55
|
content: PropTypes.shape({
|
|
54
56
|
images: PropTypes.arrayOf(
|
|
55
57
|
PropTypes.shape({
|
|
56
|
-
alt: PropTypes.string,
|
|
58
|
+
alt: PropTypes.string.isRequired,
|
|
57
59
|
tap: PropTypes.any,
|
|
58
60
|
url: PropTypes.string.isRequired
|
|
59
61
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DirectLineOAuthCard } from 'botframework-webchat-core';
|
|
2
1
|
import { hooks } from 'botframework-webchat-component';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
3
|
import React, { FC, useMemo } from 'react';
|
|
4
|
+
import type { DirectLineOAuthCard } from 'botframework-webchat-core';
|
|
5
5
|
|
|
6
6
|
import AdaptiveCardBuilder from './AdaptiveCardBuilder';
|
|
7
7
|
import AdaptiveCardRenderer from './AdaptiveCardRenderer';
|
|
@@ -48,6 +48,8 @@ OAuthCardContent.defaultProps = {
|
|
|
48
48
|
|
|
49
49
|
OAuthCardContent.propTypes = {
|
|
50
50
|
actionPerformedClassName: PropTypes.string,
|
|
51
|
+
// PropTypes cannot fully capture TypeScript types.
|
|
52
|
+
// @ts-ignore
|
|
51
53
|
content: PropTypes.shape({
|
|
52
54
|
buttons: PropTypes.array
|
|
53
55
|
}).isRequired,
|