botframework-webchat 4.15.3-main.20220628.9428638 → 4.15.3-main.20220720.8c4b995
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/webchat-es5.js +1 -1
- package/dist/webchat-minimal.js +1 -1
- package/dist/webchat.js +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/closest.d.ts +2 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/closest.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/closest.js +25 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/findDOMNodeOwner.d.ts +3 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/findDOMNodeOwner.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/findDOMNodeOwner.js +32 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useAdaptiveCardModEffect.d.ts +13 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useAdaptiveCardModEffect.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useAdaptiveCardModEffect.js +132 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useLazyRef.d.ts +3 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useLazyRef.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useLazyRef.js +21 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/usePrevious.d.ts +2 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/usePrevious.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/usePrevious.js +18 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useValueRef.d.ts +3 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useValueRef.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/private/useValueRef.js +15 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActionSetShouldNotBeMenuBarModEffect.d.ts +16 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActionSetShouldNotBeMenuBarModEffect.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActionSetShouldNotBeMenuBarModEffect.js +45 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActionShouldBePushButtonModEffect.d.ts +15 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActionShouldBePushButtonModEffect.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActionShouldBePushButtonModEffect.js +93 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActiveElementModEffect.d.ts +6 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActiveElementModEffect.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useActiveElementModEffect.js +44 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useDisabledModEffect.d.ts +9 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useDisabledModEffect.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/useDisabledModEffect.js +50 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/usePersistValuesModEffect.d.ts +6 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/usePersistValuesModEffect.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardHacks/usePersistValuesModEffect.js +103 -0
- package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts.map +1 -1
- package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.js +97 -557
- package/lib/adaptiveCards/Attachment/private/renderAdaptiveCard.d.ts +15 -0
- package/lib/adaptiveCards/Attachment/private/renderAdaptiveCard.d.ts.map +1 -0
- package/lib/adaptiveCards/Attachment/private/renderAdaptiveCard.js +79 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/addEventListenerWithUndo.d.ts +6 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/addEventListenerWithUndo.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/addEventListenerWithUndo.js +25 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/bunchUndos.d.ts +3 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/bunchUndos.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/bunchUndos.js +23 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/durableAddClassWithUndo.d.ts +8 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/durableAddClassWithUndo.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/durableAddClassWithUndo.js +38 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/durableDisableInputElementAccessiblyWithUndo.d.ts +22 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/durableDisableInputElementAccessiblyWithUndo.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/durableDisableInputElementAccessiblyWithUndo.js +96 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/addClass.d.ts +5 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/addClass.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/addClass.js +19 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/getAttributeOrFalse.d.ts +7 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/getAttributeOrFalse.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/getAttributeOrFalse.js +16 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/noOp.d.ts +3 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/noOp.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/noOp.js +14 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/setOrRemoveAttributeIfFalse.d.ts +9 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/setOrRemoveAttributeIfFalse.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/private/setOrRemoveAttributeIfFalse.js +22 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/setOrRemoveAttributeIfFalseWithUndo.d.ts +12 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/setOrRemoveAttributeIfFalseWithUndo.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/setOrRemoveAttributeIfFalseWithUndo.js +41 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/types/UndoFunction.d.ts +3 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/types/UndoFunction.d.ts.map +1 -0
- package/lib/adaptiveCards/DOMManipulationWithUndo/types/UndoFunction.js +2 -0
- package/lib/addVersion.js +1 -1
- package/lib/createFullStyleSet.d.ts +2 -2
- package/package.json +11 -10
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/private/closest.ts +17 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/private/findDOMNodeOwner.ts +25 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/private/useAdaptiveCardModEffect.ts +93 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/private/useLazyRef.ts +15 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/private/usePrevious.ts +12 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/private/useValueRef.ts +11 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/useActionSetShouldNotBeMenuBarModEffect.ts +39 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/useActionShouldBePushButtonModEffect.ts +105 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/useActiveElementModEffect.ts +35 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/useDisabledModEffect.ts +45 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardHacks/usePersistValuesModEffect.ts +110 -0
- package/src/adaptiveCards/Attachment/AdaptiveCardRenderer.tsx +83 -582
- package/src/adaptiveCards/Attachment/private/renderAdaptiveCard.ts +75 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/addEventListenerWithUndo.ts +21 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/bunchUndos.tsx +12 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/durableAddClassWithUndo.ts +28 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/durableDisableInputElementAccessiblyWithUndo.ts +84 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/private/addClass.tsx +13 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/private/getAttributeOrFalse.ts +8 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/private/noOp.ts +5 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/private/setOrRemoveAttributeIfFalse.ts +18 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/setOrRemoveAttributeIfFalseWithUndo.ts +34 -0
- package/src/adaptiveCards/DOMManipulationWithUndo/types/UndoFunction.ts +3 -0
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 2] }] */
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
Action as AdaptiveCardAction,
|
|
5
|
-
AdaptiveCard,
|
|
6
|
-
IMarkdownProcessingResult,
|
|
7
|
-
OpenUrlAction,
|
|
8
|
-
SubmitAction
|
|
9
|
-
} from 'adaptivecards';
|
|
3
|
+
import { Action as AdaptiveCardAction, AdaptiveCard, OpenUrlAction, SubmitAction } from 'adaptivecards';
|
|
10
4
|
import { Components, getTabIndex, hooks } from 'botframework-webchat-component';
|
|
11
5
|
import classNames from 'classnames';
|
|
12
6
|
import PropTypes from 'prop-types';
|
|
@@ -14,470 +8,29 @@ import React, {
|
|
|
14
8
|
KeyboardEventHandler,
|
|
15
9
|
MouseEventHandler,
|
|
16
10
|
useCallback,
|
|
17
|
-
useEffect,
|
|
18
11
|
useLayoutEffect,
|
|
12
|
+
useMemo,
|
|
19
13
|
useRef,
|
|
20
|
-
useState,
|
|
21
14
|
VFC
|
|
22
15
|
} from 'react';
|
|
23
16
|
import type { DirectLineCardAction } from 'botframework-webchat-core';
|
|
24
17
|
|
|
25
18
|
import { BotFrameworkCardAction } from './AdaptiveCardBuilder';
|
|
19
|
+
import renderAdaptiveCard from './private/renderAdaptiveCard';
|
|
20
|
+
import useActionSetShouldNotBeMenuBarModEffect from './AdaptiveCardHacks/useActionSetShouldNotBeMenuBarModEffect';
|
|
21
|
+
import useActionShouldBePushButtonModEffect from './AdaptiveCardHacks/useActionShouldBePushButtonModEffect';
|
|
22
|
+
import useActiveElementModEffect from './AdaptiveCardHacks/useActiveElementModEffect';
|
|
26
23
|
import useAdaptiveCardsHostConfig from '../hooks/useAdaptiveCardsHostConfig';
|
|
27
24
|
import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
|
|
25
|
+
import useDisabledModEffect from './AdaptiveCardHacks/useDisabledModEffect';
|
|
26
|
+
import usePersistValuesModEffect from './AdaptiveCardHacks/usePersistValuesModEffect';
|
|
27
|
+
import useValueRef from './AdaptiveCardHacks/private/useValueRef';
|
|
28
28
|
|
|
29
29
|
const { ErrorBox } = Components;
|
|
30
30
|
const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd, useStyleSet } = hooks;
|
|
31
31
|
|
|
32
32
|
const node_env = process.env.node_env || process.env.NODE_ENV;
|
|
33
33
|
|
|
34
|
-
type UndoFunction = (() => void) | undefined;
|
|
35
|
-
|
|
36
|
-
function bunchUndos(...fns: UndoFunction[]): UndoFunction {
|
|
37
|
-
return () => fns.forEach(fn => fn?.());
|
|
38
|
-
}
|
|
39
|
-
|
|
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);
|
|
48
|
-
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
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
|
-
|
|
63
|
-
if (addClass(element, className)) {
|
|
64
|
-
// After we add the class, keep observing the element to make sure the class is not removed.
|
|
65
|
-
const observer = new MutationObserver(() => addClass(element, className));
|
|
66
|
-
|
|
67
|
-
observer.observe(element, { attributes: true, attributeFilter: ['class'] });
|
|
68
|
-
|
|
69
|
-
return () => {
|
|
70
|
-
const classNames = new Set(element.className.split(' '));
|
|
71
|
-
|
|
72
|
-
classNames.delete(className);
|
|
73
|
-
|
|
74
|
-
element.className = Array.from(classNames).join(' ');
|
|
75
|
-
observer.disconnect();
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Returns `true`, if the object is a plain object and not a class, otherwise, `false`.
|
|
82
|
-
*/
|
|
83
|
-
function isPlainObject(obj) {
|
|
84
|
-
return Object.getPrototypeOf(obj) === Object.prototype;
|
|
85
|
-
}
|
|
86
|
-
|
|
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
|
-
|
|
101
|
-
const value = element.getAttribute(qualifiedName);
|
|
102
|
-
|
|
103
|
-
if (value !== nextValue) {
|
|
104
|
-
element.setAttribute(qualifiedName, nextValue);
|
|
105
|
-
|
|
106
|
-
return () => (value ? element.setAttribute(qualifiedName, value) : element.removeAttribute(qualifiedName));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* An event handler for disabling event bubbling and propagation.
|
|
112
|
-
*/
|
|
113
|
-
const disabledHandler = (event: Event) => {
|
|
114
|
-
event.preventDefault();
|
|
115
|
-
event.stopImmediatePropagation();
|
|
116
|
-
event.stopPropagation();
|
|
117
|
-
};
|
|
118
|
-
|
|
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
|
-
|
|
131
|
-
/* eslint-disable-next-line prefer-const */
|
|
132
|
-
let detach: () => void;
|
|
133
|
-
const detachingHandler = event => {
|
|
134
|
-
try {
|
|
135
|
-
handler(event);
|
|
136
|
-
} finally {
|
|
137
|
-
// IE11 does not support { once: true }, so we need to detach manually.
|
|
138
|
-
detach();
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
detach = () => element.removeEventListener(name, detachingHandler);
|
|
143
|
-
|
|
144
|
-
element.addEventListener(name, detachingHandler, { once: true });
|
|
145
|
-
|
|
146
|
-
return detach;
|
|
147
|
-
}
|
|
148
|
-
|
|
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
|
-
|
|
161
|
-
element.addEventListener(name, handler);
|
|
162
|
-
|
|
163
|
-
return () => element.removeEventListener(name, handler);
|
|
164
|
-
}
|
|
165
|
-
|
|
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[] = [];
|
|
177
|
-
const isActive = element === document.activeElement;
|
|
178
|
-
const tag = element.nodeName.toLowerCase();
|
|
179
|
-
|
|
180
|
-
/* eslint-disable-next-line default-case */
|
|
181
|
-
switch (tag) {
|
|
182
|
-
case 'button':
|
|
183
|
-
case 'input':
|
|
184
|
-
case 'select':
|
|
185
|
-
case 'textarea':
|
|
186
|
-
undoStack.push(setAttributeWithUndo(element, 'aria-disabled', 'true'));
|
|
187
|
-
|
|
188
|
-
if (isActive) {
|
|
189
|
-
undoStack.push(
|
|
190
|
-
addEventListenerOnceWithUndo(element, 'blur', () =>
|
|
191
|
-
undoStack.push(setAttributeWithUndo(element, 'disabled', 'disabled'))
|
|
192
|
-
)
|
|
193
|
-
);
|
|
194
|
-
} else {
|
|
195
|
-
undoStack.push(setAttributeWithUndo(element, 'disabled', 'disabled'));
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (tag === 'input' || tag === 'textarea') {
|
|
199
|
-
undoStack.push(addEventListenerWithUndo(element, 'click', disabledHandler));
|
|
200
|
-
undoStack.push(setAttributeWithUndo(element, 'readonly', 'readonly'));
|
|
201
|
-
} else if (tag === 'select') {
|
|
202
|
-
undoStack.push(
|
|
203
|
-
...[].map.call(element.querySelectorAll('option'), option =>
|
|
204
|
-
setAttributeWithUndo(option, 'disabled', 'disabled')
|
|
205
|
-
)
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return bunchUndos(...undoStack);
|
|
213
|
-
}
|
|
214
|
-
|
|
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 =>
|
|
229
|
-
disableElementWithUndo(element)
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
const tag = element.nodeName.toLowerCase();
|
|
233
|
-
|
|
234
|
-
// Only set tabindex="-1" on focusable element. Otherwise, we will make <div> focusable by mouse.
|
|
235
|
-
(tag === 'a' || tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea') &&
|
|
236
|
-
undoStack.push(setAttributeWithUndo(element, 'tabindex', '-1'));
|
|
237
|
-
|
|
238
|
-
if (observeSubtree) {
|
|
239
|
-
const observer = new MutationObserver(mutations =>
|
|
240
|
-
mutations.forEach(({ addedNodes }) =>
|
|
241
|
-
undoStack.push(...[].map.call(addedNodes, addedNode => disableInputElementsWithUndo(addedNode, false)))
|
|
242
|
-
)
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
observer.observe(element, { childList: true, subtree: true });
|
|
246
|
-
|
|
247
|
-
undoStack.push(() => observer.disconnect());
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return bunchUndos(...undoStack);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Gets the value of an attribute from an element.
|
|
255
|
-
*
|
|
256
|
-
* @returns {false | string} The value of the attribute. `false` if the attribute was not set.
|
|
257
|
-
*/
|
|
258
|
-
function getAttribute(element: HTMLElement, qualifiedName: string): false | string {
|
|
259
|
-
return !!element && element.hasAttribute(qualifiedName) && (element.getAttribute(qualifiedName) || '');
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Sets or removes an attribute from an element.
|
|
264
|
-
*
|
|
265
|
-
* @param {HTMLElement} element - The element to set or remove attribute from.
|
|
266
|
-
* @param {string} qualifiedName - The name of the attribute.
|
|
267
|
-
* @param {false | string} value - The value of the attribute. When passing `false`, remove the attribute.
|
|
268
|
-
*/
|
|
269
|
-
function setOrRemoveAttribute(element: HTMLElement | undefined, qualifiedName: string, value: false | string): void {
|
|
270
|
-
if (value === false) {
|
|
271
|
-
element?.removeAttribute(qualifiedName);
|
|
272
|
-
} else {
|
|
273
|
-
element?.setAttribute(qualifiedName, value);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Sets or removes an attribute from an element with an undo function.
|
|
279
|
-
*
|
|
280
|
-
* @param {HTMLElement} element - The element to set or remove attribute from.
|
|
281
|
-
* @param {string} qualifiedName - The name of the attribute.
|
|
282
|
-
* @param {false | string} value - The value of the attribute. When passing `false`, remove the attribute.
|
|
283
|
-
*
|
|
284
|
-
* @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
|
|
285
|
-
*/
|
|
286
|
-
function setOrRemoveAttributeWithUndo(
|
|
287
|
-
element: HTMLElement | undefined,
|
|
288
|
-
qualifiedName: string,
|
|
289
|
-
value: false | string
|
|
290
|
-
): UndoFunction {
|
|
291
|
-
if (!element) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const prevValue = getAttribute(element, qualifiedName);
|
|
296
|
-
|
|
297
|
-
setOrRemoveAttribute(element, qualifiedName, value);
|
|
298
|
-
|
|
299
|
-
return () => setOrRemoveAttribute(element, qualifiedName, prevValue);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Finds the first ancestor that fulfill the predicate.
|
|
304
|
-
*
|
|
305
|
-
* @param {HTMLElement} element - The starting element. This element will not be checked against the predicate.
|
|
306
|
-
* @param {(ancestor: HTMLElement) => boolean} predicate - The predicate to fulfill.
|
|
307
|
-
*
|
|
308
|
-
* @returns {HTMLElement | undefined} The first ancestor that fulfill the predicate, otherwise, `undefined`.
|
|
309
|
-
*/
|
|
310
|
-
function findAncestor(element: HTMLElement, predicate: (ancestor: HTMLElement) => boolean): HTMLElement | undefined {
|
|
311
|
-
let current = element;
|
|
312
|
-
|
|
313
|
-
while ((current = current.parentElement)) {
|
|
314
|
-
if (predicate.call(element, current)) {
|
|
315
|
-
return current;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Indicates the action selected by performing a series of manipulations, with undo:
|
|
322
|
-
*
|
|
323
|
-
* - Accessibility: set `aria-pressed` to `true`
|
|
324
|
-
* - Applies `styleOptions.actionPerformedClassName`
|
|
325
|
-
*
|
|
326
|
-
* @param {HTMLElement[]} selectedActionElements - An array of elements that are representing the action and is selected.
|
|
327
|
-
* @param {string?} actionPerformedClassName - The name of the class to apply to all elements.
|
|
328
|
-
*
|
|
329
|
-
* @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
|
|
330
|
-
*/
|
|
331
|
-
function indicateActionSelectionWithUndo(
|
|
332
|
-
selectedActionElements: HTMLElement[] | undefined,
|
|
333
|
-
actionPerformedClassName?: string
|
|
334
|
-
): UndoFunction {
|
|
335
|
-
if (!selectedActionElements?.length) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Verify all input elements are "ac-pushButton", could belongs to ActionSet or "card actions".
|
|
340
|
-
if (selectedActionElements.some(actionElement => !actionElement.classList.contains('ac-pushButton'))) {
|
|
341
|
-
console.warn(
|
|
342
|
-
'botframework-webchat: Cannot mark selected action in the card, some elements are not an "ac-pushButton".'
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// A distinct set of action set containers which has selections, excluding containers without actions.
|
|
349
|
-
// Multiple submission in an Adaptive Card is still a vague area and TBD.
|
|
350
|
-
// We might want to disable the whole card, just buttons in same container, or do nothing (today).
|
|
351
|
-
const actionSetElements = new Set<HTMLElement>();
|
|
352
|
-
|
|
353
|
-
selectedActionElements.forEach(selectedActionElement => {
|
|
354
|
-
const actionSetElement = findAncestor(
|
|
355
|
-
selectedActionElement,
|
|
356
|
-
ancestor => ancestor.getAttribute('role') === 'menubar'
|
|
357
|
-
);
|
|
358
|
-
|
|
359
|
-
actionSetElement && actionSetElements.add(actionSetElement);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
const undoStack: (() => void)[] = [];
|
|
363
|
-
|
|
364
|
-
actionSetElements.forEach(actionSetElement => {
|
|
365
|
-
// Remove "role" from every "ac-actionSet" container.
|
|
366
|
-
undoStack.push(setOrRemoveAttributeWithUndo(actionSetElement, 'role', false));
|
|
367
|
-
|
|
368
|
-
// Modify "role" of every actions in the container.
|
|
369
|
-
Array.from(actionSetElement.querySelectorAll('.ac-pushButton') as NodeListOf<HTMLElement>).forEach(
|
|
370
|
-
actionElement => {
|
|
371
|
-
if (selectedActionElements.includes(actionElement)) {
|
|
372
|
-
// Add "aria-pressed" and set "role" attribute to "button" (which is required by "aria-pressed").
|
|
373
|
-
undoStack.push(setOrRemoveAttributeWithUndo(actionElement, 'aria-pressed', 'true'));
|
|
374
|
-
undoStack.push(setOrRemoveAttributeWithUndo(actionElement, 'role', 'button'));
|
|
375
|
-
|
|
376
|
-
// Highlight actions by applying `styleOptions.actionPerformedClassName`.
|
|
377
|
-
actionPerformedClassName &&
|
|
378
|
-
undoStack.push(addPersistentClassWithUndo(actionElement, actionPerformedClassName));
|
|
379
|
-
} else {
|
|
380
|
-
// We removed "role=menubar" from the container, we must remove "role=menuitem" from unselected actions.
|
|
381
|
-
undoStack.push(setOrRemoveAttributeWithUndo(actionElement, 'role', false));
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
);
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
return bunchUndos(...undoStack);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Fixes accessibility issues from Adaptive Card, with undo.
|
|
392
|
-
*
|
|
393
|
-
* @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
|
|
394
|
-
*/
|
|
395
|
-
function fixAccessibilityIssuesWithUndo(element: HTMLElement): UndoFunction {
|
|
396
|
-
if (!element) {
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// These hacks should be done in Adaptive Cards library instead.
|
|
401
|
-
// Related to #3949: All action buttons inside role="menubar" should be role="menuitem".
|
|
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'));
|
|
405
|
-
|
|
406
|
-
return () => undoStack.forEach(undo => undo?.());
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
function getFocusableElements(element: HTMLElement) {
|
|
410
|
-
return [].filter.call(
|
|
411
|
-
element.querySelectorAll(
|
|
412
|
-
[
|
|
413
|
-
'a',
|
|
414
|
-
'body',
|
|
415
|
-
'button',
|
|
416
|
-
'frame',
|
|
417
|
-
'iframe',
|
|
418
|
-
'img',
|
|
419
|
-
'input',
|
|
420
|
-
'isindex',
|
|
421
|
-
'object',
|
|
422
|
-
'select',
|
|
423
|
-
'textarea',
|
|
424
|
-
'[tabindex]'
|
|
425
|
-
].join(', ')
|
|
426
|
-
) as NodeListOf<HTMLElement>,
|
|
427
|
-
element => {
|
|
428
|
-
const tabIndex = getTabIndex(element);
|
|
429
|
-
|
|
430
|
-
return typeof tabIndex === 'number' && tabIndex >= 0;
|
|
431
|
-
}
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
function restoreActiveElementIndex(element: HTMLElement, activeElementIndex: number) {
|
|
436
|
-
getFocusableElements(element)[+activeElementIndex]?.focus();
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
function saveActiveElementIndex(element: HTMLElement) {
|
|
440
|
-
return getFocusableElements(element).indexOf(document.activeElement);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
function restoreInputValues(element: HTMLElement, inputValues: (boolean | string)[]) {
|
|
444
|
-
const inputs = element.querySelectorAll('input, select, textarea') as NodeListOf<
|
|
445
|
-
HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
446
|
-
>;
|
|
447
|
-
|
|
448
|
-
[].forEach.call(inputs, (input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, index: number) => {
|
|
449
|
-
const value = inputValues[+index];
|
|
450
|
-
|
|
451
|
-
if (typeof value !== 'undefined') {
|
|
452
|
-
const { tagName, type } = input;
|
|
453
|
-
|
|
454
|
-
if (tagName === 'INPUT' && (type === 'checkbox' || type === 'radio')) {
|
|
455
|
-
if (typeof value === 'boolean') {
|
|
456
|
-
(input as HTMLInputElement).checked = value;
|
|
457
|
-
}
|
|
458
|
-
} else if (typeof value === 'string') {
|
|
459
|
-
input.value = value;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
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;
|
|
472
|
-
|
|
473
|
-
if (input.tagName === 'INPUT' && (type === 'checkbox' || type === 'radio')) {
|
|
474
|
-
return (input as HTMLInputElement).checked;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
return input.value;
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
|
|
481
34
|
type AdaptiveCardRendererProps = {
|
|
482
35
|
actionPerformedClassName?: string;
|
|
483
36
|
adaptiveCard: AdaptiveCard;
|
|
@@ -493,26 +46,23 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
493
46
|
}) => {
|
|
494
47
|
const [{ adaptiveCardRenderer: adaptiveCardRendererStyleSet }] = useStyleSet();
|
|
495
48
|
const [{ GlobalSettings, HostConfig }] = useAdaptiveCardsPackage();
|
|
496
|
-
const [actionsPerformed, setActionsPerformed] = useState<AdaptiveCardAction[]>([]);
|
|
497
49
|
const [adaptiveCardsHostConfig] = useAdaptiveCardsHostConfig();
|
|
498
50
|
const [disabledFromComposer] = useDisabled();
|
|
499
|
-
const [errors, setErrors] = useState([]);
|
|
500
|
-
const [lastRender, setLastRender] = useState(0);
|
|
501
|
-
const activeElementIndexRef = useRef(-1);
|
|
502
|
-
const adaptiveCardElementRef = useRef<HTMLElement>();
|
|
503
51
|
const contentRef = useRef<HTMLDivElement>();
|
|
504
|
-
const inputValuesRef = useRef<(boolean | string)[]>([]);
|
|
505
52
|
const localize = useLocalizer();
|
|
506
53
|
const performCardAction = usePerformCardAction();
|
|
507
54
|
const renderMarkdownAsHTML = useRenderMarkdownAsHTML();
|
|
508
55
|
const scrollToEnd = useScrollToEnd();
|
|
509
56
|
|
|
510
57
|
const disabled = disabledFromComposer || disabledFromProps;
|
|
58
|
+
const tapActionRef = useValueRef(tapAction);
|
|
59
|
+
|
|
60
|
+
const disabledRef = useValueRef(disabled);
|
|
511
61
|
|
|
512
62
|
// TODO: [P2] #3199 We should consider using `adaptiveCard.selectAction` instead.
|
|
513
63
|
// The null check for "tapAction" is in "handleClickAndKeyPressForTapAction".
|
|
514
|
-
const handleClickAndKeyPress = useCallback(
|
|
515
|
-
(event
|
|
64
|
+
const handleClickAndKeyPress = useCallback<KeyboardEventHandler<HTMLDivElement> | MouseEventHandler<HTMLDivElement>>(
|
|
65
|
+
(event): void => {
|
|
516
66
|
const { key, type } = event as KeyboardEvent;
|
|
517
67
|
const target = event.target as HTMLDivElement;
|
|
518
68
|
|
|
@@ -548,30 +98,22 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
548
98
|
}
|
|
549
99
|
}
|
|
550
100
|
|
|
551
|
-
performCardAction(
|
|
101
|
+
performCardAction(tapActionRef.current);
|
|
552
102
|
scrollToEnd();
|
|
553
103
|
},
|
|
554
|
-
[contentRef, performCardAction, scrollToEnd,
|
|
104
|
+
[contentRef, performCardAction, scrollToEnd, tapActionRef]
|
|
555
105
|
);
|
|
556
106
|
|
|
557
107
|
// Only listen to event if it is not disabled and have "tapAction" prop.
|
|
558
108
|
const handleClickAndKeyPressForTapAction = !disabled && tapAction ? handleClickAndKeyPress : undefined;
|
|
559
109
|
|
|
560
|
-
const addActionsPerformed = useCallback(
|
|
561
|
-
(action: AdaptiveCardAction): void =>
|
|
562
|
-
!~actionsPerformed.indexOf(action) && setActionsPerformed([...actionsPerformed, action]),
|
|
563
|
-
[actionsPerformed, setActionsPerformed]
|
|
564
|
-
);
|
|
565
|
-
|
|
566
110
|
const handleExecuteAction = useCallback(
|
|
567
111
|
(action: AdaptiveCardAction): void => {
|
|
568
112
|
// Some items, e.g. tappable image, cannot be disabled thru DOM attributes
|
|
569
|
-
if (
|
|
113
|
+
if (disabledRef.current) {
|
|
570
114
|
return;
|
|
571
115
|
}
|
|
572
116
|
|
|
573
|
-
addActionsPerformed(action);
|
|
574
|
-
|
|
575
117
|
const actionTypeName = action.getJsonTypeName();
|
|
576
118
|
const { iconUrl: image, title } = action;
|
|
577
119
|
|
|
@@ -617,128 +159,87 @@ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
|
|
|
617
159
|
console.error(action);
|
|
618
160
|
}
|
|
619
161
|
},
|
|
620
|
-
[
|
|
162
|
+
[disabledRef, performCardAction, scrollToEnd]
|
|
621
163
|
);
|
|
622
164
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
adaptiveCard.hostConfig = isPlainObject(adaptiveCardsHostConfig)
|
|
648
|
-
? new HostConfig(adaptiveCardsHostConfig)
|
|
649
|
-
: adaptiveCardsHostConfig;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
// For accessibility issue #1340, `tabindex="0"` must not be set for the root container if it is not interactive.
|
|
653
|
-
GlobalSettings.setTabIndexAtCardRoot = !!tapAction;
|
|
654
|
-
|
|
655
|
-
const { validationEvents } = adaptiveCard.validateProperties();
|
|
656
|
-
|
|
657
|
-
if (validationEvents.length) {
|
|
658
|
-
return setErrors(validationEvents.reduce((items, { message }) => [...items, new Error(message)], []));
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
let element: HTMLElement;
|
|
662
|
-
|
|
663
|
-
try {
|
|
664
|
-
element = adaptiveCard.render();
|
|
665
|
-
} catch (error) {
|
|
666
|
-
return setErrors([error]);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
if (!element) {
|
|
670
|
-
return setErrors([new Error('Adaptive Card rendered as empty element')]);
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
// Clear errors on next render
|
|
674
|
-
setErrors([]);
|
|
675
|
-
|
|
676
|
-
restoreInputValues(element, inputValuesRef.current);
|
|
677
|
-
|
|
678
|
-
current.appendChild(element);
|
|
679
|
-
adaptiveCardElementRef.current = element;
|
|
680
|
-
|
|
681
|
-
// Focus can only be restored after the DOM is attached.
|
|
682
|
-
restoreActiveElementIndex(element, activeElementIndexRef.current);
|
|
683
|
-
|
|
684
|
-
setLastRender(Date.now());
|
|
685
|
-
|
|
686
|
-
return () => {
|
|
687
|
-
activeElementIndexRef.current = saveActiveElementIndex(element);
|
|
688
|
-
inputValuesRef.current = saveInputValues(element);
|
|
689
|
-
|
|
690
|
-
current.removeChild(adaptiveCardElementRef.current);
|
|
691
|
-
|
|
692
|
-
adaptiveCardElementRef.current = undefined;
|
|
693
|
-
};
|
|
165
|
+
// For accessibility issue #1340, `tabindex="0"` must not be set for the root container if it is not interactive.
|
|
166
|
+
const setTabIndexAtCardRoot = !!tapAction;
|
|
167
|
+
|
|
168
|
+
const [applyActionShouldBePushButtonMod, undoActionShouldBePushButtonMod] =
|
|
169
|
+
useActionShouldBePushButtonModEffect(adaptiveCard);
|
|
170
|
+
const [applyActionSetShouldNotBeMenuBarMod, undoActionSetShouldNotBeMenuBarMod] =
|
|
171
|
+
useActionSetShouldNotBeMenuBarModEffect(adaptiveCard);
|
|
172
|
+
const [applyActiveElementMod, undoActiveElementMod] = useActiveElementModEffect(adaptiveCard);
|
|
173
|
+
const [applyDisabledMod, undoDisabledMod] = useDisabledModEffect(adaptiveCard);
|
|
174
|
+
const [applyPersistValuesMod, undoPersistValuesMod] = usePersistValuesModEffect(adaptiveCard);
|
|
175
|
+
|
|
176
|
+
const { element, errors }: { element?: HTMLElement; errors?: Error[] } = useMemo(() => {
|
|
177
|
+
undoActionShouldBePushButtonMod();
|
|
178
|
+
undoActionSetShouldNotBeMenuBarMod();
|
|
179
|
+
undoActiveElementMod();
|
|
180
|
+
undoDisabledMod();
|
|
181
|
+
undoPersistValuesMod();
|
|
182
|
+
|
|
183
|
+
return renderAdaptiveCard(adaptiveCard, {
|
|
184
|
+
adaptiveCardsHostConfig,
|
|
185
|
+
adaptiveCardsPackage: { GlobalSettings, HostConfig },
|
|
186
|
+
renderMarkdownAsHTML,
|
|
187
|
+
setTabIndexAtCardRoot
|
|
188
|
+
});
|
|
694
189
|
}, [
|
|
695
190
|
adaptiveCard,
|
|
696
191
|
adaptiveCardsHostConfig,
|
|
697
|
-
contentRef,
|
|
698
192
|
GlobalSettings,
|
|
699
193
|
HostConfig,
|
|
700
194
|
renderMarkdownAsHTML,
|
|
701
|
-
|
|
702
|
-
|
|
195
|
+
setTabIndexAtCardRoot,
|
|
196
|
+
undoActionShouldBePushButtonMod,
|
|
197
|
+
undoActionSetShouldNotBeMenuBarMod,
|
|
198
|
+
undoActiveElementMod,
|
|
199
|
+
undoDisabledMod,
|
|
200
|
+
undoPersistValuesMod
|
|
703
201
|
]);
|
|
704
202
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
}
|
|
717
|
-
}, [
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
()
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
203
|
+
useMemo(() => {
|
|
204
|
+
adaptiveCard.onExecuteAction = handleExecuteAction;
|
|
205
|
+
}, [adaptiveCard, handleExecuteAction]);
|
|
206
|
+
|
|
207
|
+
useLayoutEffect(() => {
|
|
208
|
+
const { current } = contentRef;
|
|
209
|
+
|
|
210
|
+
current?.appendChild(element);
|
|
211
|
+
|
|
212
|
+
return () => {
|
|
213
|
+
current?.removeChild(element);
|
|
214
|
+
};
|
|
215
|
+
}, [contentRef, element]);
|
|
216
|
+
|
|
217
|
+
// Apply all mods regardless whether the element changed or not.
|
|
218
|
+
// This is because we have undoed mods when we call the `useXXXModEffect` hook.
|
|
219
|
+
useLayoutEffect(() => {
|
|
220
|
+
applyActionShouldBePushButtonMod(element, actionPerformedClassName);
|
|
221
|
+
applyActionSetShouldNotBeMenuBarMod(element);
|
|
222
|
+
applyActiveElementMod(element);
|
|
223
|
+
applyDisabledMod(element, disabled);
|
|
224
|
+
applyPersistValuesMod(element);
|
|
225
|
+
}, [
|
|
226
|
+
actionPerformedClassName,
|
|
227
|
+
applyActionShouldBePushButtonMod,
|
|
228
|
+
applyActionSetShouldNotBeMenuBarMod,
|
|
229
|
+
applyActiveElementMod,
|
|
230
|
+
applyDisabledMod,
|
|
231
|
+
applyPersistValuesMod,
|
|
232
|
+
disabled,
|
|
233
|
+
element
|
|
234
|
+
]);
|
|
734
235
|
|
|
735
|
-
return errors
|
|
236
|
+
return errors?.length ? (
|
|
736
237
|
node_env === 'development' && <ErrorBox error={errors[0]} type={localize('ADAPTIVE_CARD_ERROR_BOX_TITLE_RENDER')} />
|
|
737
238
|
) : (
|
|
738
239
|
<div
|
|
739
240
|
className={classNames(adaptiveCardRendererStyleSet + '', 'webchat__adaptive-card-renderer')}
|
|
740
|
-
onClick={handleClickAndKeyPressForTapAction as
|
|
741
|
-
onKeyPress={handleClickAndKeyPressForTapAction as
|
|
241
|
+
onClick={handleClickAndKeyPressForTapAction as MouseEventHandler<HTMLDivElement>}
|
|
242
|
+
onKeyPress={handleClickAndKeyPressForTapAction as KeyboardEventHandler<HTMLDivElement>}
|
|
742
243
|
ref={contentRef}
|
|
743
244
|
/>
|
|
744
245
|
);
|