botframework-webchat 4.13.0 → 4.14.2

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.
Files changed (253) hide show
  1. package/.eslintignore +1 -9
  2. package/.eslintrc.yml +5 -0
  3. package/README.md +33 -36
  4. package/babel.config.json +2 -2
  5. package/babel.sanitize-html.config.json +10 -0
  6. package/lib/AddFullBundle.d.ts +30 -0
  7. package/lib/AddFullBundle.d.ts.map +1 -0
  8. package/lib/AddFullBundle.js +77 -0
  9. package/lib/FullComposer.d.ts +8 -0
  10. package/lib/FullComposer.d.ts.map +1 -0
  11. package/lib/FullComposer.js +6 -16
  12. package/lib/FullReactWebChat.d.ts +8 -0
  13. package/lib/FullReactWebChat.d.ts.map +1 -0
  14. package/lib/FullReactWebChat.js +8 -23
  15. package/lib/adaptiveCards/AdaptiveCardsComposer.d.ts +10 -0
  16. package/lib/adaptiveCards/AdaptiveCardsComposer.d.ts.map +1 -0
  17. package/lib/adaptiveCards/AdaptiveCardsComposer.js +6 -2
  18. package/lib/adaptiveCards/AdaptiveCardsContext.d.ts +8 -0
  19. package/lib/adaptiveCards/AdaptiveCardsContext.d.ts.map +1 -0
  20. package/lib/adaptiveCards/AdaptiveCardsContext.js +3 -3
  21. package/lib/adaptiveCards/AdaptiveCardsStyleOptions.d.ts +5 -3
  22. package/lib/adaptiveCards/AdaptiveCardsStyleOptions.d.ts.map +1 -1
  23. package/lib/adaptiveCards/AdaptiveCardsStyleSet.d.ts +7 -0
  24. package/lib/adaptiveCards/AdaptiveCardsStyleSet.d.ts.map +1 -0
  25. package/lib/{FullBundleStyleOptions.js → adaptiveCards/AdaptiveCardsStyleSet.js} +0 -0
  26. package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.d.ts +9 -0
  27. package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.d.ts.map +1 -0
  28. package/lib/adaptiveCards/Attachment/AdaptiveCardAttachment.js +1 -1
  29. package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.d.ts +28 -0
  30. package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.d.ts.map +1 -0
  31. package/lib/adaptiveCards/Attachment/AdaptiveCardBuilder.js +4 -4
  32. package/lib/adaptiveCards/Attachment/AdaptiveCardContent.d.ts +9 -0
  33. package/lib/adaptiveCards/Attachment/AdaptiveCardContent.d.ts.map +1 -0
  34. package/lib/adaptiveCards/Attachment/AdaptiveCardContent.js +8 -4
  35. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts +11 -0
  36. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.d.ts.map +1 -0
  37. package/lib/adaptiveCards/Attachment/AdaptiveCardRenderer.js +210 -49
  38. package/lib/adaptiveCards/Attachment/AnimationCardContent.d.ts +10 -0
  39. package/lib/adaptiveCards/Attachment/AnimationCardContent.d.ts.map +1 -0
  40. package/lib/adaptiveCards/Attachment/AnimationCardContent.js +1 -1
  41. package/lib/adaptiveCards/Attachment/AudioCardContent.d.ts +10 -0
  42. package/lib/adaptiveCards/Attachment/AudioCardContent.d.ts.map +1 -0
  43. package/lib/adaptiveCards/Attachment/AudioCardContent.js +1 -1
  44. package/lib/adaptiveCards/Attachment/CommonCard.js +11 -6
  45. package/lib/adaptiveCards/Attachment/HeroCardContent.d.ts +10 -0
  46. package/lib/adaptiveCards/Attachment/HeroCardContent.d.ts.map +1 -0
  47. package/lib/adaptiveCards/Attachment/HeroCardContent.js +11 -6
  48. package/lib/adaptiveCards/Attachment/OAuthCardContent.d.ts +10 -0
  49. package/lib/adaptiveCards/Attachment/OAuthCardContent.d.ts.map +1 -0
  50. package/lib/adaptiveCards/Attachment/OAuthCardContent.js +11 -6
  51. package/lib/adaptiveCards/Attachment/ReceiptCardContent.d.ts +10 -0
  52. package/lib/adaptiveCards/Attachment/ReceiptCardContent.d.ts.map +1 -0
  53. package/lib/adaptiveCards/Attachment/ReceiptCardContent.js +11 -6
  54. package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts +10 -0
  55. package/lib/adaptiveCards/Attachment/SignInCardContent.d.ts.map +1 -0
  56. package/lib/adaptiveCards/Attachment/SignInCardContent.js +1 -1
  57. package/lib/adaptiveCards/Attachment/ThumbnailCardContent.d.ts +10 -0
  58. package/lib/adaptiveCards/Attachment/ThumbnailCardContent.d.ts.map +1 -0
  59. package/lib/adaptiveCards/Attachment/ThumbnailCardContent.js +11 -6
  60. package/lib/adaptiveCards/Attachment/VideoCardContent.d.ts +20 -0
  61. package/lib/adaptiveCards/Attachment/VideoCardContent.d.ts.map +1 -0
  62. package/lib/adaptiveCards/Attachment/VideoCardContent.js +7 -5
  63. package/lib/adaptiveCards/AttachmentForScreenReader/AdaptiveCardAttachment.js +7 -3
  64. package/lib/adaptiveCards/AttachmentForScreenReader/RichCardAttachment.js +1 -1
  65. package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.d.ts +56 -0
  66. package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.d.ts.map +1 -0
  67. package/lib/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.js +1 -1
  68. package/lib/adaptiveCards/Styles/adaptiveCardHostConfig.d.ts +126 -0
  69. package/lib/adaptiveCards/Styles/adaptiveCardHostConfig.d.ts.map +1 -0
  70. package/lib/adaptiveCards/Styles/adaptiveCardHostConfig.js +29 -9
  71. package/lib/adaptiveCards/Styles/createAdaptiveCardsStyleSet.d.ts +5 -0
  72. package/lib/adaptiveCards/Styles/createAdaptiveCardsStyleSet.d.ts.map +1 -0
  73. package/lib/adaptiveCards/Styles/createAdaptiveCardsStyleSet.js +2 -2
  74. package/lib/adaptiveCards/createAdaptiveCardsAttachmentForScreenReaderMiddleware.d.ts +3 -0
  75. package/lib/adaptiveCards/createAdaptiveCardsAttachmentForScreenReaderMiddleware.d.ts.map +1 -0
  76. package/lib/adaptiveCards/createAdaptiveCardsAttachmentForScreenReaderMiddleware.js +5 -11
  77. package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.d.ts +3 -0
  78. package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.d.ts.map +1 -0
  79. package/lib/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js +29 -39
  80. package/lib/adaptiveCards/defaultStyleOptions.d.ts +4 -0
  81. package/lib/adaptiveCards/defaultStyleOptions.d.ts.map +1 -0
  82. package/lib/adaptiveCards/defaultStyleOptions.js +3 -2
  83. package/lib/adaptiveCards/hooks/internal/useAdaptiveCardsContext.d.ts +3 -0
  84. package/lib/adaptiveCards/hooks/internal/useAdaptiveCardsContext.d.ts.map +1 -0
  85. package/lib/adaptiveCards/hooks/internal/useAdaptiveCardsContext.js +1 -1
  86. package/lib/adaptiveCards/hooks/internal/useParseAdaptiveCardJSON.d.ts +2 -0
  87. package/lib/adaptiveCards/hooks/internal/useParseAdaptiveCardJSON.d.ts.map +1 -0
  88. package/lib/adaptiveCards/hooks/internal/useParseAdaptiveCardJSON.js +7 -5
  89. package/lib/adaptiveCards/hooks/internal/useUniqueId.js +1 -1
  90. package/lib/adaptiveCards/hooks/useAdaptiveCardsHostConfig.d.ts +2 -0
  91. package/lib/adaptiveCards/hooks/useAdaptiveCardsHostConfig.d.ts.map +1 -0
  92. package/lib/adaptiveCards/hooks/useAdaptiveCardsHostConfig.js +3 -5
  93. package/lib/adaptiveCards/hooks/useAdaptiveCardsPackage.d.ts +3 -0
  94. package/lib/adaptiveCards/hooks/useAdaptiveCardsPackage.d.ts.map +1 -0
  95. package/lib/adaptiveCards/hooks/useAdaptiveCardsPackage.js +1 -1
  96. package/lib/adaptiveCards/normalizeStyleOptions.d.ts +3 -0
  97. package/lib/adaptiveCards/normalizeStyleOptions.d.ts.map +1 -0
  98. package/lib/adaptiveCards/normalizeStyleOptions.js +1 -1
  99. package/lib/addVersion.js +2 -2
  100. package/lib/createBrowserWebSpeechPonyfillFactory.d.ts +3 -0
  101. package/lib/createBrowserWebSpeechPonyfillFactory.d.ts.map +1 -0
  102. package/lib/createBrowserWebSpeechPonyfillFactory.js +7 -4
  103. package/lib/createCognitiveServicesSpeechServicesPonyfillFactory.d.ts +17 -0
  104. package/lib/createCognitiveServicesSpeechServicesPonyfillFactory.d.ts.map +1 -0
  105. package/lib/createCognitiveServicesSpeechServicesPonyfillFactory.js +17 -11
  106. package/lib/createDirectLine.d.ts +17 -0
  107. package/lib/createDirectLine.d.ts.map +1 -0
  108. package/lib/createDirectLine.js +3 -2
  109. package/lib/createDirectLineAppServiceExtension.d.ts +7 -0
  110. package/lib/createDirectLineAppServiceExtension.d.ts.map +1 -0
  111. package/lib/createDirectLineAppServiceExtension.js +1 -1
  112. package/lib/createDirectLineSpeechAdapters.d.ts +25 -0
  113. package/lib/createDirectLineSpeechAdapters.d.ts.map +1 -0
  114. package/lib/createDirectLineSpeechAdapters.js +57 -3
  115. package/lib/createFullStyleSet.d.ts +1106 -0
  116. package/lib/createFullStyleSet.d.ts.map +1 -0
  117. package/lib/createFullStyleSet.js +2 -2
  118. package/lib/fullBundleDefaultStyleOptions.js +4 -4
  119. package/lib/hooks/useStyleOptions.d.ts +3 -0
  120. package/lib/hooks/useStyleOptions.d.ts.map +1 -0
  121. package/lib/hooks/useStyleOptions.js +21 -0
  122. package/lib/index-es5.d.ts +24 -20
  123. package/lib/index-es5.d.ts.map +1 -1
  124. package/lib/index-es5.js +2 -2
  125. package/lib/index-minimal.d.ts +9 -6
  126. package/lib/index-minimal.d.ts.map +1 -1
  127. package/lib/index-minimal.js +8 -4
  128. package/lib/index.d.ts +154 -18
  129. package/lib/index.d.ts.map +1 -1
  130. package/lib/index.js +11 -7
  131. package/lib/renderMarkdown.d.ts +6 -0
  132. package/lib/renderMarkdown.d.ts.map +1 -0
  133. package/lib/renderMarkdown.js +5 -2
  134. package/lib/renderWebChat.d.ts +3 -0
  135. package/lib/renderWebChat.d.ts.map +1 -0
  136. package/lib/renderWebChat.js +1 -1
  137. package/lib/speech/CustomAudioInputStream.d.ts +94 -0
  138. package/lib/speech/CustomAudioInputStream.d.ts.map +1 -0
  139. package/lib/speech/CustomAudioInputStream.js +416 -0
  140. package/lib/speech/bytesPerSample.d.ts +2 -0
  141. package/lib/speech/bytesPerSample.d.ts.map +1 -0
  142. package/lib/speech/bytesPerSample.js +12 -0
  143. package/lib/speech/createAudioConfig.d.ts +23 -0
  144. package/lib/speech/createAudioConfig.d.ts.map +1 -0
  145. package/lib/speech/createAudioConfig.js +84 -0
  146. package/lib/speech/createAudioContext.d.ts +3 -0
  147. package/lib/speech/createAudioContext.d.ts.map +1 -0
  148. package/lib/speech/createAudioContext.js +22 -0
  149. package/lib/speech/createMicrophoneAudioConfigAndAudioContext.d.ts +9 -0
  150. package/lib/speech/createMicrophoneAudioConfigAndAudioContext.d.ts.map +1 -0
  151. package/lib/speech/createMicrophoneAudioConfigAndAudioContext.js +161 -0
  152. package/lib/speech/getUserMedia.d.ts +2 -0
  153. package/lib/speech/getUserMedia.d.ts.map +1 -0
  154. package/lib/speech/getUserMedia.js +25 -0
  155. package/lib/types/AdaptiveCardsPackage.d.ts +13 -0
  156. package/lib/types/AdaptiveCardsPackage.d.ts.map +1 -0
  157. package/lib/types/AdaptiveCardsPackage.js +2 -0
  158. package/lib/types/CognitiveServicesAudioOutputFormat.d.ts +3 -0
  159. package/lib/types/CognitiveServicesAudioOutputFormat.d.ts.map +1 -0
  160. package/lib/types/CognitiveServicesAudioOutputFormat.js +2 -0
  161. package/lib/types/CognitiveServicesCredentials.d.ts +18 -0
  162. package/lib/types/CognitiveServicesCredentials.d.ts.map +1 -0
  163. package/lib/types/CognitiveServicesCredentials.js +2 -0
  164. package/lib/types/CognitiveServicesTextNormalization.d.ts +3 -0
  165. package/lib/types/CognitiveServicesTextNormalization.d.ts.map +1 -0
  166. package/lib/types/CognitiveServicesTextNormalization.js +2 -0
  167. package/lib/{FullBundleStyleOptions.d.ts → types/FullBundleStyleOptions.d.ts} +1 -1
  168. package/lib/types/FullBundleStyleOptions.d.ts.map +1 -0
  169. package/lib/types/FullBundleStyleOptions.js +2 -0
  170. package/lib/useComposerProps.d.ts +22 -0
  171. package/lib/useComposerProps.d.ts.map +1 -0
  172. package/lib/useComposerProps.js +6 -8
  173. package/package.json +51 -46
  174. package/src/AddFullBundle.tsx +94 -0
  175. package/src/FullComposer.tsx +38 -0
  176. package/src/FullReactWebChat.tsx +32 -0
  177. package/src/__tests__/createDirectLine.spec.js +2 -0
  178. package/src/__tests__/renderMarkdown.spec.js +1 -1
  179. package/src/__tests__/versionTag.es5.spec.js +3 -0
  180. package/src/__tests__/versionTag.full.spec.js +3 -0
  181. package/src/__tests__/versionTag.minimal.spec.js +3 -0
  182. package/src/adaptiveCards/{AdaptiveCardsComposer.js → AdaptiveCardsComposer.tsx} +17 -5
  183. package/src/adaptiveCards/AdaptiveCardsContext.ts +12 -0
  184. package/src/adaptiveCards/AdaptiveCardsStyleOptions.ts +5 -3
  185. package/src/adaptiveCards/AdaptiveCardsStyleSet.ts +7 -0
  186. package/src/adaptiveCards/Attachment/{AdaptiveCardAttachment.js → AdaptiveCardAttachment.tsx} +8 -2
  187. package/src/adaptiveCards/Attachment/AdaptiveCardBuilder.ts +21 -15
  188. package/src/adaptiveCards/Attachment/{AdaptiveCardContent.js → AdaptiveCardContent.tsx} +8 -2
  189. package/src/adaptiveCards/Attachment/{AdaptiveCardRenderer.js → AdaptiveCardRenderer.tsx} +228 -46
  190. package/src/adaptiveCards/Attachment/{AnimationCardContent.js → AnimationCardContent.tsx} +9 -2
  191. package/src/adaptiveCards/Attachment/{AudioCardContent.js → AudioCardContent.tsx} +9 -2
  192. package/src/adaptiveCards/Attachment/CommonCard.js +2 -1
  193. package/src/adaptiveCards/Attachment/{HeroCardContent.js → HeroCardContent.tsx} +12 -3
  194. package/src/adaptiveCards/Attachment/{OAuthCardContent.js → OAuthCardContent.tsx} +11 -3
  195. package/src/adaptiveCards/Attachment/{ReceiptCardContent.js → ReceiptCardContent.tsx} +58 -28
  196. package/src/adaptiveCards/Attachment/{SignInCardContent.js → SignInCardContent.tsx} +9 -2
  197. package/src/adaptiveCards/Attachment/{ThumbnailCardContent.js → ThumbnailCardContent.tsx} +12 -3
  198. package/src/adaptiveCards/Attachment/{VideoCardContent.js → VideoCardContent.tsx} +15 -3
  199. package/src/adaptiveCards/Styles/StyleSet/AdaptiveCardRenderer.ts +1 -1
  200. package/src/adaptiveCards/Styles/adaptiveCardHostConfig.ts +28 -8
  201. package/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.spec.js +2 -0
  202. package/src/adaptiveCards/Styles/createAdaptiveCardsStyleSet.ts +7 -4
  203. package/src/adaptiveCards/{createAdaptiveCardsAttachmentForScreenReaderMiddleware.js → createAdaptiveCardsAttachmentForScreenReaderMiddleware.tsx} +16 -15
  204. package/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.tsx +45 -0
  205. package/src/adaptiveCards/defaultStyleOptions.ts +2 -1
  206. package/src/adaptiveCards/hooks/internal/{useAdaptiveCardsContext.js → useAdaptiveCardsContext.ts} +1 -1
  207. package/src/adaptiveCards/hooks/internal/{useParseAdaptiveCardJSON.js → useParseAdaptiveCardJSON.ts} +5 -2
  208. package/src/adaptiveCards/hooks/internal/{useUniqueId.js → useUniqueId.ts} +1 -1
  209. package/src/adaptiveCards/hooks/{useAdaptiveCardsHostConfig.js → useAdaptiveCardsHostConfig.ts} +6 -8
  210. package/src/adaptiveCards/hooks/{useAdaptiveCardsPackage.js → useAdaptiveCardsPackage.ts} +2 -1
  211. package/src/createBrowserWebSpeechPonyfillFactory.ts +21 -0
  212. package/src/createCognitiveServicesSpeechServicesPonyfillFactory.spec.js +37 -6
  213. package/src/createCognitiveServicesSpeechServicesPonyfillFactory.ts +78 -0
  214. package/src/createDirectLine.ts +65 -0
  215. package/src/createDirectLineAppServiceExtension.ts +22 -0
  216. package/src/createDirectLineSpeechAdapters.ts +84 -0
  217. package/src/createFullStyleSet.ts +2 -2
  218. package/src/fullBundleDefaultStyleOptions.ts +3 -3
  219. package/src/hooks/useStyleOptions.ts +9 -0
  220. package/src/index-es5.ts +0 -2
  221. package/src/index-minimal.ts +3 -2
  222. package/src/index.ts +22 -10
  223. package/src/{renderMarkdown.js → renderMarkdown.ts} +8 -1
  224. package/src/renderWebChat.tsx +6 -0
  225. package/src/speech/CustomAudioInputStream.ts +325 -0
  226. package/src/speech/bytesPerSample.ts +4 -0
  227. package/src/speech/createAudioConfig.spec.js +23 -0
  228. package/src/speech/createAudioConfig.ts +70 -0
  229. package/src/speech/createAudioContext.ts +16 -0
  230. package/src/speech/createMicrophoneAudioConfigAndAudioContext.ts +146 -0
  231. package/src/speech/getUserMedia.ts +14 -0
  232. package/src/tsconfig.json +1 -1
  233. package/src/types/AdaptiveCardsPackage.ts +23 -0
  234. package/src/types/CognitiveServicesAudioOutputFormat.ts +28 -0
  235. package/src/types/CognitiveServicesCredentials.ts +28 -0
  236. package/src/types/CognitiveServicesTextNormalization.ts +3 -0
  237. package/src/{FullBundleStyleOptions.ts → types/FullBundleStyleOptions.ts} +1 -1
  238. package/src/{useComposerProps.js → useComposerProps.ts} +21 -11
  239. package/webpack.config.js +46 -6
  240. package/lib/FullBundleStyleOptions.d.ts.map +0 -1
  241. package/src/FullComposer.js +0 -40
  242. package/src/FullReactWebChat.js +0 -47
  243. package/src/adaptiveCards/AdaptiveCardsContext.js +0 -5
  244. package/src/adaptiveCards/createAdaptiveCardsAttachmentMiddleware.js +0 -41
  245. package/src/createBrowserWebSpeechPonyfillFactory.js +0 -16
  246. package/src/createCognitiveServicesSpeechServicesPonyfillFactory.js +0 -58
  247. package/src/createDirectLine.js +0 -38
  248. package/src/createDirectLineAppServiceExtension.js +0 -12
  249. package/src/createDirectLineSpeechAdapters.js +0 -5
  250. package/src/index-es5.tsx +0 -49
  251. package/src/index-minimal.tsx +0 -9
  252. package/src/index.tsx +0 -45
  253. package/src/renderWebChat.js +0 -6
@@ -1,12 +1,15 @@
1
1
  /* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 2] }] */
2
2
 
3
+ import { Action, OpenUrlAction, SubmitAction } from 'adaptivecards';
3
4
  import { Components, getTabIndex, hooks } from 'botframework-webchat-component';
5
+ import { DirectLineCardAction } from 'botframework-webchat-core';
4
6
  import classNames from 'classnames';
5
7
  import PropTypes from 'prop-types';
6
- import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
8
+ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState, VFC } from 'react';
7
9
 
8
10
  import useAdaptiveCardsHostConfig from '../hooks/useAdaptiveCardsHostConfig';
9
11
  import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
12
+ import { BotFrameworkCardAction } from './AdaptiveCardBuilder';
10
13
 
11
14
  const { ErrorBox } = Components;
12
15
  const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd, useStyleSet } = hooks;
@@ -131,7 +134,7 @@ function disableElementWithUndo(element) {
131
134
  return () => undoStack.forEach(undo => undo && undo());
132
135
  }
133
136
 
134
- function disableInputElementsWithUndo(element, observeSubtree = true) {
137
+ function disableInputElementsWithUndo(element: HTMLElement, observeSubtree = true) {
135
138
  const undoStack = [].map.call(element.querySelectorAll('button, input, select, textarea'), element =>
136
139
  disableElementWithUndo(element)
137
140
  );
@@ -145,7 +148,7 @@ function disableInputElementsWithUndo(element, observeSubtree = true) {
145
148
  if (observeSubtree) {
146
149
  const observer = new MutationObserver(mutations =>
147
150
  mutations.forEach(({ addedNodes }) =>
148
- undoStack.push(...addedNodes.map(addedNode => disableInputElementsWithUndo(addedNode, false)))
151
+ undoStack.push(...[].map.call(addedNodes, addedNode => disableInputElementsWithUndo(addedNode, false)))
149
152
  )
150
153
  );
151
154
 
@@ -157,6 +160,167 @@ function disableInputElementsWithUndo(element, observeSubtree = true) {
157
160
  return () => undoStack.forEach(undo => undo && undo());
158
161
  }
159
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);
172
+ }
173
+
174
+ /**
175
+ * Gets the value of an attribute from an element.
176
+ *
177
+ * @returns {false | string} The value of the attribute. `false` if the attribute was not set.
178
+ */
179
+ function getAttribute(element: HTMLElement, qualifiedName: string): false | string {
180
+ return element.hasAttribute(qualifiedName) && element.getAttribute(qualifiedName);
181
+ }
182
+
183
+ /**
184
+ * Sets or removes an attribute from an element.
185
+ *
186
+ * @param {HTMLElement} element - The element to set or remove attribute from.
187
+ * @param {string} qualifiedName - The name of the attribute.
188
+ * @param {false | string} value - The value of the attribute. When passing `false`, remove the attribute.
189
+ */
190
+ function setOrRemoveAttribute(element: HTMLElement, qualifiedName: string, value: false | string): void {
191
+ if (value === false) {
192
+ element.removeAttribute(qualifiedName);
193
+ } else {
194
+ element.setAttribute(qualifiedName, value);
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Sets or removes an attribute from an element with an undo function.
200
+ *
201
+ * @param {HTMLElement} element - The element to set or remove attribute from.
202
+ * @param {string} qualifiedName - The name of the attribute.
203
+ * @param {false | string} value - The value of the attribute. When passing `false`, remove the attribute.
204
+ *
205
+ * @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
206
+ */
207
+ function setOrRemoveAttributeWithUndo(element: HTMLElement, qualifiedName: string, value: false | string): () => void {
208
+ const prevValue = getAttribute(element, qualifiedName);
209
+
210
+ setOrRemoveAttribute(element, qualifiedName, value);
211
+
212
+ return () => setOrRemoveAttribute(element, qualifiedName, prevValue);
213
+ }
214
+
215
+ /**
216
+ * Finds the first ancestor that fulfill the predicate.
217
+ *
218
+ * @param {HTMLElement} element - The starting element. This element will not be checked against the predicate.
219
+ * @param {(ancestor: HTMLElement) => boolean} predicate - The predicate to fulfill.
220
+ *
221
+ * @returns {HTMLElement | undefined} The first ancestor that fulfill the predicate, otherwise, `undefined`.
222
+ */
223
+ function findAncestor(element: HTMLElement, predicate: (ancestor: HTMLElement) => boolean): HTMLElement | undefined {
224
+ let current = element.parentElement;
225
+
226
+ while (current) {
227
+ if (predicate.call(element, current)) {
228
+ return current;
229
+ }
230
+
231
+ current = current.parentElement;
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Indicates the action selected by performing a series of manipulations, with undo:
237
+ *
238
+ * - Accessibility: set `aria-pressed` to `true`
239
+ * - Applies `styleOptions.actionPerformedClassName`
240
+ *
241
+ * @param {HTMLElement[]} selectedActionElements - An array of elements that are representing the action and is selected.
242
+ * @param {string?} actionPerformedClassName - The name of the class to apply to all elements.
243
+ *
244
+ * @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
245
+ */
246
+ function indicateActionSelectionWithUndo(
247
+ selectedActionElements: HTMLElement[],
248
+ actionPerformedClassName?: string
249
+ ): (() => void) | undefined {
250
+ if (!selectedActionElements.length) {
251
+ return;
252
+ }
253
+
254
+ // Verify all input elements are "ac-pushButton", could belongs to ActionSet or "card actions".
255
+ if (selectedActionElements.some(actionElement => !containsClassName(actionElement, 'ac-pushButton'))) {
256
+ console.warn(
257
+ 'botframework-webchat: Cannot mark selected action in the card, some elements are not an "ac-pushButton".'
258
+ );
259
+
260
+ return;
261
+ }
262
+
263
+ // A distinct set of action set containers which has selections, excluding containers without actions.
264
+ // Multiple submission in an Adaptive Card is still a vague area and TBD.
265
+ // We might want to disable the whole card, just buttons in same container, or do nothing (today).
266
+ const actionSetElements = new Set<HTMLElement>();
267
+
268
+ selectedActionElements.forEach(selectedActionElement => {
269
+ const actionSetElement = findAncestor(
270
+ selectedActionElement,
271
+ ancestor => ancestor.getAttribute('role') === 'menubar'
272
+ );
273
+
274
+ actionSetElement && actionSetElements.add(actionSetElement);
275
+ });
276
+
277
+ const undoStack: (() => void)[] = [];
278
+
279
+ actionSetElements.forEach(actionSetElement => {
280
+ // Remove "role" from every "ac-actionSet" container.
281
+ undoStack.push(setOrRemoveAttributeWithUndo(actionSetElement, 'role', false));
282
+
283
+ // Modify "role" of every actions in the container.
284
+ Array.from(actionSetElement.querySelectorAll('.ac-pushButton') as NodeListOf<HTMLElement>).forEach(
285
+ actionElement => {
286
+ if (selectedActionElements.includes(actionElement)) {
287
+ // Add "aria-pressed" and set "role" attribute to "button" (which is required by "aria-pressed").
288
+ undoStack.push(setOrRemoveAttributeWithUndo(actionElement, 'aria-pressed', 'true'));
289
+ undoStack.push(setOrRemoveAttributeWithUndo(actionElement, 'role', 'button'));
290
+
291
+ // Highlight actions by applying `styleOptions.actionPerformedClassName`.
292
+ actionPerformedClassName &&
293
+ undoStack.push(addPersistentClassWithUndo(actionElement, actionPerformedClassName));
294
+ } else {
295
+ // We removed "role=menubar" from the container, we must remove "role=menuitem" from unselected actions.
296
+ undoStack.push(setOrRemoveAttributeWithUndo(actionElement, 'role', false));
297
+ }
298
+ }
299
+ );
300
+ });
301
+
302
+ return () => undoStack.forEach(undo => undo());
303
+ }
304
+
305
+ /**
306
+ * Fixes accessibility issues from Adaptive Card, with undo.
307
+ *
308
+ * @returns {() => void} The undo function, when called, will undo all manipulations by restoring values recorded at the time of the function call.
309
+ */
310
+ function fixAccessibilityIssuesWithUndo(element: HTMLElement): () => void {
311
+ // These hacks should be done in Adaptive Cards library instead.
312
+ const undoStack: (() => void)[] = [];
313
+
314
+ // Related to #3949: All action buttons inside role="menubar" should be role="menuitem".
315
+ undoStack.push(
316
+ ...Array.from(element.querySelectorAll('.ac-actionSet[role="menubar"] [role="button"]')).map(actionButton =>
317
+ setAttributeWithUndo(actionButton, 'role', 'menuitem')
318
+ )
319
+ );
320
+
321
+ return () => undoStack.forEach(undo => undo());
322
+ }
323
+
160
324
  function getFocusableElements(element) {
161
325
  return [].filter.call(
162
326
  element.querySelectorAll(
@@ -223,7 +387,19 @@ function saveInputValues(element) {
223
387
  });
224
388
  }
225
389
 
226
- const AdaptiveCardRenderer = ({ actionPerformedClassName, adaptiveCard, disabled: disabledFromProps, tapAction }) => {
390
+ type AdaptiveCardRendererProps = {
391
+ actionPerformedClassName?: string;
392
+ adaptiveCard: any;
393
+ disabled?: boolean;
394
+ tapAction?: DirectLineCardAction;
395
+ };
396
+
397
+ const AdaptiveCardRenderer: VFC<AdaptiveCardRendererProps> = ({
398
+ actionPerformedClassName,
399
+ adaptiveCard,
400
+ disabled: disabledFromProps,
401
+ tapAction
402
+ }) => {
227
403
  const [{ adaptiveCardRenderer: adaptiveCardRendererStyleSet }] = useStyleSet();
228
404
  const [{ GlobalSettings, HostConfig }] = useAdaptiveCardsPackage();
229
405
  const [actionsPerformed, setActionsPerformed] = useState([]);
@@ -232,8 +408,8 @@ const AdaptiveCardRenderer = ({ actionPerformedClassName, adaptiveCard, disabled
232
408
  const [errors, setErrors] = useState([]);
233
409
  const [lastRender, setLastRender] = useState(0);
234
410
  const activeElementIndexRef = useRef(-1);
235
- const adaptiveCardElementRef = useRef();
236
- const contentRef = useRef();
411
+ const adaptiveCardElementRef = useRef<HTMLElement>();
412
+ const contentRef = useRef<HTMLDivElement>();
237
413
  const inputValuesRef = useRef([]);
238
414
  const localize = useLocalizer();
239
415
  const performCardAction = usePerformCardAction();
@@ -295,7 +471,7 @@ const AdaptiveCardRenderer = ({ actionPerformedClassName, adaptiveCard, disabled
295
471
  );
296
472
 
297
473
  const handleExecuteAction = useCallback(
298
- action => {
474
+ (action: Action) => {
299
475
  // Some items, e.g. tappable image, cannot be disabled thru DOM attributes
300
476
  if (disabled) {
301
477
  return;
@@ -304,25 +480,40 @@ const AdaptiveCardRenderer = ({ actionPerformedClassName, adaptiveCard, disabled
304
480
  addActionsPerformed(action);
305
481
 
306
482
  const actionTypeName = action.getJsonTypeName();
483
+ const { iconUrl: image, title } = action;
307
484
 
485
+ // We cannot use "instanceof" check here, because web devs may bring their own version of Adaptive Cards package.
486
+ // We need to check using "getJsonTypeName()" instead.
308
487
  if (actionTypeName === 'Action.OpenUrl') {
488
+ const { url: value } = action as OpenUrlAction;
489
+
309
490
  performCardAction({
491
+ image,
492
+ title,
310
493
  type: 'openUrl',
311
- value: action.url
494
+ value
312
495
  });
313
496
  } else if (actionTypeName === 'Action.Submit') {
314
- if (typeof action.data !== 'undefined') {
315
- const { data: actionData } = action;
316
-
317
- if (actionData && actionData.__isBotFrameworkCardAction) {
318
- const { cardAction } = actionData;
319
- const { displayText, text, type, value } = cardAction;
497
+ const { data } = action as SubmitAction as {
498
+ data: string | BotFrameworkCardAction;
499
+ };
320
500
 
321
- performCardAction({ displayText, text, type, value });
501
+ if (typeof data !== 'undefined') {
502
+ if (typeof data === 'string') {
503
+ performCardAction({
504
+ image,
505
+ title,
506
+ type: 'imBack',
507
+ value: data
508
+ });
509
+ } else if (data.__isBotFrameworkCardAction) {
510
+ performCardAction(data.cardAction);
322
511
  } else {
323
512
  performCardAction({
324
- type: typeof action.data === 'string' ? 'imBack' : 'postBack',
325
- value: action.data
513
+ image,
514
+ title,
515
+ type: 'postBack',
516
+ value: data
326
517
  });
327
518
  }
328
519
  }
@@ -421,48 +612,33 @@ const AdaptiveCardRenderer = ({ actionPerformedClassName, adaptiveCard, disabled
421
612
  adaptiveCard.onExecuteAction = disabled ? undefined : handleExecuteAction;
422
613
  }, [adaptiveCard, disabled, handleExecuteAction]);
423
614
 
615
+ useEffect(() => fixAccessibilityIssuesWithUndo(adaptiveCardElementRef.current), [adaptiveCardElementRef, lastRender]);
616
+
424
617
  useEffect(() => {
425
618
  // If the Adaptive Card get re-rendered, re-disable elements as needed.
426
619
  if (disabled) {
427
620
  return disableInputElementsWithUndo(adaptiveCardElementRef.current);
428
621
  }
429
- }, [disabled, lastRender]);
622
+ }, [adaptiveCardElementRef, disabled, lastRender]);
430
623
 
431
624
  useEffect(() => {
432
625
  // If the Adaptive Card changed, reset all actions performed.
433
626
  setActionsPerformed([]);
434
627
  }, [adaptiveCard]);
435
628
 
436
- useEffect(() => {
437
- // Add aria-pressed and role attribute to the AC action button selected by the user.
438
- actionsPerformed.forEach(({ renderedElement }) => {
439
- if (renderedElement && adaptiveCardElementRef.current.contains(renderedElement)) {
440
- setAttributeWithUndo(renderedElement, 'aria-pressed', 'true');
441
- setAttributeWithUndo(renderedElement, 'role', 'button');
442
- }
443
- });
444
-
445
- // Add developers to highlight actions when they have been clicked.
446
- if (!actionPerformedClassName) {
447
- return;
448
- }
449
-
450
- const undoStack = actionsPerformed.map(
451
- ({ renderedElement }) =>
452
- renderedElement &&
453
- adaptiveCardElementRef.current.contains(renderedElement) &&
454
- addPersistentClassWithUndo(renderedElement, actionPerformedClassName)
455
- );
456
-
457
- return () => undoStack.forEach(undo => undo && undo());
458
- }, [actionsPerformed, actionPerformedClassName, lastRender]);
629
+ useEffect(
630
+ () =>
631
+ indicateActionSelectionWithUndo(
632
+ // Actions that do not have "renderedElement" means it is the Adaptive Card itself, such as "selectAction" (AC) or "tapAction" (rich cards).
633
+ // We do not need to mark the whole card as performed.
634
+ actionsPerformed.map(({ renderedElement }) => renderedElement).filter(renderedElement => renderedElement),
635
+ actionPerformedClassName
636
+ ),
637
+ [actionsPerformed, actionPerformedClassName, lastRender]
638
+ );
459
639
 
460
640
  return errors.length ? (
461
- node_env === 'development' ? (
462
- <ErrorBox error={errors[0]} type={localize('ADAPTIVE_CARD_ERROR_BOX_TITLE_RENDER')} />
463
- ) : (
464
- false
465
- )
641
+ node_env === 'development' && <ErrorBox error={errors[0]} type={localize('ADAPTIVE_CARD_ERROR_BOX_TITLE_RENDER')} />
466
642
  ) : (
467
643
  <div
468
644
  className={classNames(adaptiveCardRendererStyleSet + '', 'webchat__adaptive-card-renderer')}
@@ -483,7 +659,13 @@ AdaptiveCardRenderer.propTypes = {
483
659
  actionPerformedClassName: PropTypes.string,
484
660
  adaptiveCard: PropTypes.any.isRequired,
485
661
  disabled: PropTypes.bool,
662
+
663
+ // TypeScript class is not mappable to PropTypes.func
664
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
665
+ // @ts-ignore
486
666
  tapAction: PropTypes.shape({
667
+ image: PropTypes.string,
668
+ title: PropTypes.string,
487
669
  type: PropTypes.string.isRequired,
488
670
  value: PropTypes.string
489
671
  })
@@ -1,15 +1,22 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
+ import { DirectLineAnimationCard } from 'botframework-webchat-core';
3
4
  import { Components, hooks } from 'botframework-webchat-component';
4
5
  import PropTypes from 'prop-types';
5
- import React from 'react';
6
+ import React, { FC } from 'react';
6
7
 
7
8
  import CommonCard from './CommonCard';
8
9
 
9
10
  const { ImageContent, VideoContent } = Components;
10
11
  const { useStyleSet } = hooks;
11
12
 
12
- const AnimationCardContent = ({ actionPerformedClassName, content, disabled }) => {
13
+ type AnimationCardContentProps = {
14
+ actionPerformedClassName?: string;
15
+ content: DirectLineAnimationCard;
16
+ disabled?: boolean;
17
+ };
18
+
19
+ const AnimationCardContent: FC<AnimationCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
13
20
  const { media = [] } = content;
14
21
  const [{ animationCardAttachment: animationCardAttachmentStyleSet }] = useStyleSet();
15
22
 
@@ -1,15 +1,22 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
+ import { DirectLineAudioCard } from 'botframework-webchat-core';
3
4
  import { Components, hooks } from 'botframework-webchat-component';
4
5
  import PropTypes from 'prop-types';
5
- import React from 'react';
6
+ import React, { FC } from 'react';
6
7
 
7
8
  import CommonCard from './CommonCard';
8
9
 
9
10
  const { AudioContent } = Components;
10
11
  const { useStyleSet } = hooks;
11
12
 
12
- const AudioCardContent = ({ actionPerformedClassName, content, disabled }) => {
13
+ type AudioCardContentProps = {
14
+ actionPerformedClassName?: string;
15
+ content: DirectLineAudioCard;
16
+ disabled?: boolean;
17
+ };
18
+
19
+ const AudioCardContent: FC<AudioCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
13
20
  const [{ audioCardAttachment: audioCardAttachmentStyleSet }] = useStyleSet();
14
21
  const { autostart = false, autoloop = false, image: { url: imageURL = '' } = {}, media = [] } = content;
15
22
 
@@ -6,8 +6,9 @@ import { hooks } from 'botframework-webchat-component';
6
6
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
7
7
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
8
8
  import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
9
+ import useStyleOptions from '../../hooks/useStyleOptions';
9
10
 
10
- const { useDirection, useStyleOptions } = hooks;
11
+ const { useDirection } = hooks;
11
12
 
12
13
  const CommonCard = ({ actionPerformedClassName, content, disabled }) => {
13
14
  const [adaptiveCardsPackage] = useAdaptiveCardsPackage();
@@ -1,17 +1,26 @@
1
+ import { DirectLineHeroCard } from 'botframework-webchat-core';
1
2
  import { hooks } from 'botframework-webchat-component';
2
3
  import PropTypes from 'prop-types';
3
- import React, { useMemo } from 'react';
4
+ import React, { FC, useMemo } from 'react';
4
5
 
5
6
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
6
7
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
7
8
  import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
9
+ import useStyleOptions from '../../hooks/useStyleOptions';
8
10
 
9
- const { useDirection, useStyleOptions } = hooks;
11
+ const { useDirection } = hooks;
10
12
 
11
- const HeroCardContent = ({ actionPerformedClassName, content, disabled }) => {
13
+ type HeroCardContentProps = {
14
+ actionPerformedClassName?: string;
15
+ content: DirectLineHeroCard;
16
+ disabled?: boolean;
17
+ };
18
+
19
+ const HeroCardContent: FC<HeroCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
12
20
  const [adaptiveCardsPackage] = useAdaptiveCardsPackage();
13
21
  const [styleOptions] = useStyleOptions();
14
22
  const [direction] = useDirection();
23
+
15
24
  const builtCard = useMemo(() => {
16
25
  const builder = new AdaptiveCardBuilder(adaptiveCardsPackage, styleOptions, direction);
17
26
 
@@ -1,14 +1,22 @@
1
+ import { DirectLineOAuthCard } from 'botframework-webchat-core';
1
2
  import { hooks } from 'botframework-webchat-component';
2
3
  import PropTypes from 'prop-types';
3
- import React, { useMemo } from 'react';
4
+ import React, { FC, useMemo } from 'react';
4
5
 
5
6
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
6
7
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
7
8
  import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
9
+ import useStyleOptions from '../../hooks/useStyleOptions';
8
10
 
9
- const { useDirection, useStyleOptions } = hooks;
11
+ const { useDirection } = hooks;
10
12
 
11
- const OAuthCardContent = ({ actionPerformedClassName, content, disabled }) => {
13
+ type OAuthCardContentProps = {
14
+ actionPerformedClassName?: string;
15
+ content: DirectLineOAuthCard;
16
+ disabled?: boolean;
17
+ };
18
+
19
+ const OAuthCardContent: FC<OAuthCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
12
20
  const [adaptiveCardsPackage] = useAdaptiveCardsPackage();
13
21
  const [direction] = useDirection();
14
22
  const [styleOptions] = useStyleOptions();
@@ -1,20 +1,28 @@
1
1
  /* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 10, 15, 25, 50, 75] }] */
2
2
 
3
+ import { DirectLineReceiptCard } from 'botframework-webchat-core';
3
4
  import { hooks } from 'botframework-webchat-component';
4
5
  import PropTypes from 'prop-types';
5
- import React, { useMemo } from 'react';
6
+ import React, { FC, useMemo } from 'react';
6
7
 
7
8
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
8
9
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
9
10
  import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
11
+ import useStyleOptions from '../../hooks/useStyleOptions';
10
12
 
11
- const { useDirection, useLocalizer, useStyleOptions } = hooks;
13
+ const { useDirection, useLocalizer } = hooks;
12
14
 
13
15
  function nullOrUndefined(obj) {
14
16
  return obj === null || typeof obj === 'undefined';
15
17
  }
16
18
 
17
- const ReceiptCardContent = ({ actionPerformedClassName, content, disabled }) => {
19
+ type ReceiptCardContentProps = {
20
+ actionPerformedClassName?: string;
21
+ content: DirectLineReceiptCard;
22
+ disabled?: boolean;
23
+ };
24
+
25
+ const ReceiptCardContent: FC<ReceiptCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
18
26
  const [adaptiveCardsPackage] = useAdaptiveCardsPackage();
19
27
  const [direction] = useDirection();
20
28
  const [styleOptions] = useStyleOptions();
@@ -47,32 +55,54 @@ const ReceiptCardContent = ({ actionPerformedClassName, content, disabled }) =>
47
55
  }
48
56
 
49
57
  items &&
50
- items.map(({ image: { alt, tap: imageTap, url } = {}, price, quantity, subtitle, tap, text, title }) => {
51
- let itemColumns;
52
-
53
- if (url) {
54
- const [itemImageColumn, ...columns] = builder.addColumnSet([15, 75, 10]);
55
-
56
- itemColumns = columns;
57
- builder.addImage(url, itemImageColumn, imageTap, alt);
58
- } else {
59
- itemColumns = builder.addColumnSet([75, 25], undefined, tap && tap);
60
- }
61
-
62
- const [itemTitleColumn, itemPriceColumn] = itemColumns;
63
-
64
- builder.addTextBlock(
65
- quantity ? `${title} &times; ${quantity}` : title,
66
- { size: TextSize.Medium, weight: TextWeight.Bolder, wrap: richCardWrapTitle },
67
- itemTitleColumn
68
- );
69
- builder.addTextBlock(subtitle, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
70
- builder.addTextBlock(price, { horizontalAlignment: HorizontalAlignment.Right }, itemPriceColumn);
71
-
72
- if (text) {
73
- builder.addTextBlock(text, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
58
+ items.map(
59
+ ({
60
+ image: { alt, tap: imageTap, url } = {},
61
+ price,
62
+ quantity,
63
+ subtitle,
64
+ tap,
65
+ text,
66
+ title
67
+ }: {
68
+ image: {
69
+ alt?: string;
70
+ tap?: any;
71
+ url?: string;
72
+ };
73
+ price: string;
74
+ quantity: string;
75
+ subtitle: string;
76
+ tap: any;
77
+ text: string;
78
+ title: string;
79
+ }) => {
80
+ let itemColumns;
81
+
82
+ if (url) {
83
+ const [itemImageColumn, ...columns] = builder.addColumnSet([15, 75, 10]);
84
+
85
+ itemColumns = columns;
86
+ builder.addImage(url, itemImageColumn, imageTap, alt);
87
+ } else {
88
+ itemColumns = builder.addColumnSet([75, 25], undefined, tap && tap);
89
+ }
90
+
91
+ const [itemTitleColumn, itemPriceColumn] = itemColumns;
92
+
93
+ builder.addTextBlock(
94
+ quantity ? `${title} &times; ${quantity}` : title,
95
+ { size: TextSize.Medium, weight: TextWeight.Bolder, wrap: richCardWrapTitle },
96
+ itemTitleColumn
97
+ );
98
+ builder.addTextBlock(subtitle, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
99
+ builder.addTextBlock(price, { horizontalAlignment: HorizontalAlignment.Right }, itemPriceColumn);
100
+
101
+ if (text) {
102
+ builder.addTextBlock(text, { size: TextSize.Medium, wrap: richCardWrapTitle }, itemTitleColumn);
103
+ }
74
104
  }
75
- });
105
+ );
76
106
 
77
107
  if (!nullOrUndefined(vat)) {
78
108
  const vatCol = builder.addColumnSet([75, 25]);
@@ -1,12 +1,19 @@
1
+ import { DirectLineSignInCard } from 'botframework-webchat-core';
1
2
  import { hooks } from 'botframework-webchat-component';
2
3
  import PropTypes from 'prop-types';
3
- import React from 'react';
4
+ import React, { FC } from 'react';
4
5
 
5
6
  import CommonCard from './CommonCard';
6
7
 
7
8
  const { useStyleSet } = hooks;
8
9
 
9
- const SignInCardContent = ({ actionPerformedClassName, content, disabled }) => {
10
+ type SignInCardContentProps = {
11
+ actionPerformedClassName?: string;
12
+ content: DirectLineSignInCard;
13
+ disabled?: boolean;
14
+ };
15
+
16
+ const SignInCardContent: FC<SignInCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
10
17
  const [{ animationCardAttachment: animationCardAttachmentStyleSet }] = useStyleSet();
11
18
 
12
19
  return (
@@ -1,19 +1,28 @@
1
1
  /* eslint no-magic-numbers: ["error", { "ignore": [25, 75] }] */
2
2
 
3
+ import { DirectLineThumbnailCard } from 'botframework-webchat-core';
3
4
  import { hooks } from 'botframework-webchat-component';
4
5
  import PropTypes from 'prop-types';
5
- import React, { useMemo } from 'react';
6
+ import React, { FC, useMemo } from 'react';
6
7
 
7
8
  import AdaptiveCardBuilder from './AdaptiveCardBuilder';
8
9
  import AdaptiveCardRenderer from './AdaptiveCardRenderer';
9
10
  import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
11
+ import useStyleOptions from '../../hooks/useStyleOptions';
10
12
 
11
- const { useDirection, useStyleOptions } = hooks;
13
+ const { useDirection } = hooks;
12
14
 
13
- const ThumbnailCardContent = ({ actionPerformedClassName, content, disabled }) => {
15
+ type ThumbnailCardContentProps = {
16
+ actionPerformedClassName?: string;
17
+ content: DirectLineThumbnailCard;
18
+ disabled?: boolean;
19
+ };
20
+
21
+ const ThumbnailCardContent: FC<ThumbnailCardContentProps> = ({ actionPerformedClassName, content, disabled }) => {
14
22
  const [adaptiveCardsPackage] = useAdaptiveCardsPackage();
15
23
  const [direction] = useDirection();
16
24
  const [styleOptions] = useStyleOptions();
25
+
17
26
  const builtCard = useMemo(() => {
18
27
  if (content) {
19
28
  const builder = new AdaptiveCardBuilder(adaptiveCardsPackage, styleOptions, direction);