botframework-webchat-component 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.
Files changed (411) hide show
  1. package/.eslintrc.yml +4 -106
  2. package/.prettierrc.yml +1 -1
  3. package/lib/Activity/CarouselFilmStrip.js +1 -1
  4. package/lib/Activity/CarouselFilmStripAttachment.js +1 -1
  5. package/lib/Activity/CarouselLayout.js +3 -3
  6. package/lib/Activity/Speak.d.ts +2 -2
  7. package/lib/Activity/Speak.d.ts.map +1 -1
  8. package/lib/Activity/Speak.js +15 -8
  9. package/lib/Activity/StackedLayout.d.ts +5 -3
  10. package/lib/Activity/StackedLayout.d.ts.map +1 -1
  11. package/lib/Activity/StackedLayout.js +16 -21
  12. package/lib/Attachment/FileAttachment.js +2 -2
  13. package/lib/Attachment/FileContent.d.ts.map +1 -1
  14. package/lib/Attachment/FileContent.js +11 -1
  15. package/lib/BasicSendBox.d.ts.map +1 -1
  16. package/lib/BasicSendBox.js +8 -9
  17. package/lib/BasicToast.js +1 -1
  18. package/lib/BasicToaster.js +6 -3
  19. package/lib/BasicTranscript.d.ts +7 -0
  20. package/lib/BasicTranscript.d.ts.map +1 -0
  21. package/lib/BasicTranscript.js +386 -728
  22. package/lib/BasicTypingIndicator.d.ts +2 -1
  23. package/lib/BasicTypingIndicator.d.ts.map +1 -1
  24. package/lib/BasicTypingIndicator.js +12 -4
  25. package/lib/Composer.d.ts.map +1 -1
  26. package/lib/Composer.js +37 -32
  27. package/lib/ConnectivityStatus/Connecting.js +1 -1
  28. package/lib/Dictation.js +1 -1
  29. package/lib/Middleware/Activity/createCoreMiddleware.d.ts.map +1 -1
  30. package/lib/Middleware/Activity/createCoreMiddleware.js +9 -12
  31. package/lib/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js +1 -1
  32. package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.d.ts +2 -2
  33. package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.d.ts.map +1 -1
  34. package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.js +5 -4
  35. package/lib/Middleware/ActivityStatus/Timestamp.d.ts +2 -2
  36. package/lib/Middleware/ActivityStatus/Timestamp.d.ts.map +1 -1
  37. package/lib/Middleware/ActivityStatus/Timestamp.js +4 -2
  38. package/lib/Middleware/ActivityStatus/createSendStatusMiddleware.js +20 -17
  39. package/lib/Middleware/Attachment/createCoreMiddleware.js +2 -5
  40. package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.d.ts.map +1 -1
  41. package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.js +1 -1
  42. package/lib/Middleware/Avatar/createCoreMiddleware.d.ts.map +1 -1
  43. package/lib/Middleware/Avatar/createCoreMiddleware.js +2 -3
  44. package/lib/Middleware/CardAction/createCoreMiddleware.js +10 -3
  45. package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.d.ts.map +1 -1
  46. package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.js +1 -1
  47. package/lib/Middleware/Toast/createCoreMiddleware.d.ts.map +1 -1
  48. package/lib/Middleware/Toast/createCoreMiddleware.js +1 -1
  49. package/lib/Middleware/TypingIndicator/createCoreMiddleware.d.ts.map +1 -1
  50. package/lib/Middleware/TypingIndicator/createCoreMiddleware.js +8 -6
  51. package/lib/ReactWebChat.js +2 -2
  52. package/lib/ScreenReaderActivity.js +15 -6
  53. package/lib/ScreenReaderText.d.ts +9 -0
  54. package/lib/ScreenReaderText.d.ts.map +1 -0
  55. package/lib/ScreenReaderText.js +22 -8
  56. package/lib/SendBox/AutoResizeTextArea.js +1 -1
  57. package/lib/SendBox/DictationInterims.js +1 -1
  58. package/lib/SendBox/IconButton.d.ts +11 -0
  59. package/lib/SendBox/IconButton.d.ts.map +1 -0
  60. package/lib/SendBox/IconButton.js +26 -6
  61. package/lib/SendBox/MicrophoneButton.js +2 -2
  62. package/lib/SendBox/SendButton.js +2 -2
  63. package/lib/SendBox/SuggestedAction.d.ts +17 -0
  64. package/lib/SendBox/SuggestedAction.d.ts.map +1 -0
  65. package/lib/SendBox/SuggestedAction.js +26 -17
  66. package/lib/SendBox/SuggestedActions.d.ts.map +1 -1
  67. package/lib/SendBox/SuggestedActions.js +26 -9
  68. package/lib/SendBox/TextBox.js +4 -4
  69. package/lib/SendBox/UploadButton.js +4 -4
  70. package/lib/Styles/StyleSet/BasicTranscript.d.ts +13 -5
  71. package/lib/Styles/StyleSet/BasicTranscript.d.ts.map +1 -1
  72. package/lib/Styles/StyleSet/BasicTranscript.js +21 -9
  73. package/lib/Styles/StyleSet/Bubble.d.ts.map +1 -1
  74. package/lib/Styles/StyleSet/Bubble.js +3 -3
  75. package/lib/Styles/StyleSet/CarouselFilmStrip.d.ts.map +1 -1
  76. package/lib/Styles/StyleSet/CarouselFilmStrip.js +3 -3
  77. package/lib/Styles/StyleSet/CarouselFilmStripAttachment.d.ts.map +1 -1
  78. package/lib/Styles/StyleSet/CarouselFilmStripAttachment.js +3 -3
  79. package/lib/Styles/StyleSet/KeyboardHelp.d.ts +123 -0
  80. package/lib/Styles/StyleSet/KeyboardHelp.d.ts.map +1 -0
  81. package/lib/Styles/StyleSet/KeyboardHelp.js +145 -0
  82. package/lib/Styles/StyleSet/ScrollToEndButton.d.ts +1 -1
  83. package/lib/Styles/StyleSet/ScrollToEndButton.js +2 -2
  84. package/lib/Styles/StyleSet/SendBoxButton.d.ts +56 -10
  85. package/lib/Styles/StyleSet/SendBoxButton.d.ts.map +1 -1
  86. package/lib/Styles/StyleSet/SendBoxButton.js +76 -12
  87. package/lib/Styles/StyleSet/SendBoxTextBox.d.ts +1 -1
  88. package/lib/Styles/StyleSet/SendBoxTextBox.d.ts.map +1 -1
  89. package/lib/Styles/StyleSet/SendBoxTextBox.js +3 -3
  90. package/lib/Styles/StyleSet/StackedLayout.d.ts.map +1 -1
  91. package/lib/Styles/StyleSet/StackedLayout.js +1 -1
  92. package/lib/Styles/StyleSet/SuggestedAction.d.ts +73 -28
  93. package/lib/Styles/StyleSet/SuggestedAction.d.ts.map +1 -1
  94. package/lib/Styles/StyleSet/SuggestedAction.js +116 -41
  95. package/lib/Styles/StyleSet/SuggestedActions.d.ts +13 -6
  96. package/lib/Styles/StyleSet/SuggestedActions.d.ts.map +1 -1
  97. package/lib/Styles/StyleSet/SuggestedActions.js +13 -6
  98. package/lib/Styles/createStyleSet.d.ts +324 -55
  99. package/lib/Styles/createStyleSet.d.ts.map +1 -1
  100. package/lib/Styles/createStyleSet.js +6 -3
  101. package/lib/Styles/mirrorStyle.js +12 -3
  102. package/lib/Toast/NotificationIcon.js +7 -3
  103. package/lib/Toast/createToastMiddleware.d.ts.map +1 -1
  104. package/lib/Toast/createToastMiddleware.js +1 -1
  105. package/lib/Transcript/ActivityRow.d.ts +9 -0
  106. package/lib/Transcript/ActivityRow.d.ts.map +1 -0
  107. package/lib/Transcript/ActivityRow.js +159 -0
  108. package/lib/Transcript/ActivityTextAlt.js +57 -0
  109. package/lib/Transcript/FocusTrap.d.ts +8 -0
  110. package/lib/Transcript/FocusTrap.d.ts.map +1 -0
  111. package/lib/Transcript/FocusTrap.js +74 -0
  112. package/lib/Transcript/KeyboardHelp.d.ts +4 -0
  113. package/lib/Transcript/KeyboardHelp.d.ts.map +1 -0
  114. package/lib/Transcript/KeyboardHelp.js +550 -0
  115. package/lib/Transcript/LiveRegionTranscript.d.ts +8 -0
  116. package/lib/Transcript/LiveRegionTranscript.d.ts.map +1 -0
  117. package/lib/Transcript/LiveRegionTranscript.js +229 -0
  118. package/lib/Transcript/types.d.ts +2 -0
  119. package/lib/Transcript/types.d.ts.map +1 -0
  120. package/lib/Transcript/types.js +2 -0
  121. package/lib/Transcript/useActivityAccessibleName.d.ts +4 -0
  122. package/lib/Transcript/useActivityAccessibleName.d.ts.map +1 -0
  123. package/lib/Transcript/useActivityAccessibleName.js +97 -0
  124. package/lib/Transcript/useTypistNames.d.ts +3 -0
  125. package/lib/Transcript/useTypistNames.d.ts.map +1 -0
  126. package/lib/Transcript/useTypistNames.js +61 -0
  127. package/lib/Utils/AccessKeySink/Surface.js +1 -1
  128. package/lib/Utils/AccessibleButton.d.ts +11 -0
  129. package/lib/Utils/AccessibleButton.d.ts.map +1 -0
  130. package/lib/Utils/AccessibleButton.js +12 -7
  131. package/lib/Utils/AccessibleInputText.js +1 -1
  132. package/lib/Utils/AccessibleTextArea.js +1 -1
  133. package/lib/Utils/CroppedImage.js +1 -1
  134. package/lib/Utils/FocusRedirector.d.ts +9 -0
  135. package/lib/Utils/FocusRedirector.d.ts.map +1 -0
  136. package/lib/Utils/FocusRedirector.js +17 -14
  137. package/lib/Utils/InlineMarkdown.js +15 -8
  138. package/lib/Utils/TypeFocusSink/FocusBox.js +1 -1
  139. package/lib/Utils/TypeFocusSink/inputtableKey.d.ts +2 -0
  140. package/lib/Utils/TypeFocusSink/inputtableKey.d.ts.map +1 -0
  141. package/lib/Utils/TypeFocusSink/inputtableKey.js +5 -2
  142. package/lib/Utils/activityAltText.d.ts +8 -0
  143. package/lib/Utils/activityAltText.d.ts.map +1 -0
  144. package/lib/Utils/addTargetBlankToHyperlinksMarkdown.js +2 -2
  145. package/lib/Utils/createCustomEvent.js +8 -2
  146. package/lib/Utils/detectBrowser.js +4 -2
  147. package/lib/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.js +1 -1
  148. package/lib/Utils/downscaleImageToDataURL/index.js +1 -1
  149. package/lib/Utils/findAncestor.js +17 -0
  150. package/lib/Utils/getActivityUniqueId.js +4 -2
  151. package/lib/Utils/intersectionOf.d.ts +5 -0
  152. package/lib/Utils/intersectionOf.d.ts.map +1 -0
  153. package/lib/Utils/intersectionOf.js +17 -2
  154. package/lib/Utils/isZeroOrPositive.d.ts +5 -0
  155. package/lib/Utils/isZeroOrPositive.d.ts.map +1 -0
  156. package/lib/Utils/isZeroOrPositive.js +4 -1
  157. package/lib/Utils/mapMap.js +9 -2
  158. package/lib/Utils/readDataURIToBlob.js +1 -1
  159. package/lib/Utils/scrollIntoViewWithBlockNearest.d.ts +7 -0
  160. package/lib/Utils/scrollIntoViewWithBlockNearest.d.ts.map +1 -0
  161. package/lib/Utils/scrollIntoViewWithBlockNearest.js +48 -0
  162. package/lib/Utils/shallowEquals.js +7 -3
  163. package/lib/Utils/supportPseudoClass.d.ts +2 -0
  164. package/lib/Utils/supportPseudoClass.d.ts.map +1 -0
  165. package/lib/Utils/supportPseudoClass.js +23 -0
  166. package/lib/Utils/tabbableElements.d.ts +2 -0
  167. package/lib/Utils/tabbableElements.d.ts.map +1 -0
  168. package/lib/Utils/tabbableElements.js +2 -2
  169. package/lib/connectToWebChat.js +15 -7
  170. package/lib/hooks/index.js +24 -24
  171. package/lib/hooks/internal/BypassSpeechSynthesisPonyfill.js +8 -7
  172. package/lib/hooks/internal/useChanged.js +8 -1
  173. package/lib/hooks/internal/useDispatchScrollPosition.js +3 -7
  174. package/lib/hooks/internal/useDispatchTranscriptFocusByActivityKey.d.ts +2 -0
  175. package/lib/hooks/internal/useDispatchTranscriptFocusByActivityKey.d.ts.map +1 -0
  176. package/lib/hooks/internal/useDispatchTranscriptFocusByActivityKey.js +15 -0
  177. package/lib/hooks/internal/useFocusVisible.d.ts +3 -0
  178. package/lib/hooks/internal/useFocusVisible.d.ts.map +1 -0
  179. package/lib/hooks/internal/useFocusVisible.js +48 -0
  180. package/lib/hooks/internal/useMemoWithPrevious.d.ts +3 -0
  181. package/lib/hooks/internal/useMemoWithPrevious.d.ts.map +1 -0
  182. package/lib/hooks/internal/useMemoWithPrevious.js +22 -0
  183. package/lib/hooks/internal/useMemoize.d.ts +14 -0
  184. package/lib/hooks/internal/useMemoize.d.ts.map +1 -0
  185. package/lib/hooks/internal/useMemoize.js +11 -2
  186. package/lib/hooks/internal/useObserveFocusVisible.d.ts +3 -0
  187. package/lib/hooks/internal/useObserveFocusVisible.d.ts.map +1 -0
  188. package/lib/hooks/internal/useObserveFocusVisible.js +208 -0
  189. package/lib/hooks/internal/usePrevious.d.ts +2 -0
  190. package/lib/hooks/internal/usePrevious.d.ts.map +1 -0
  191. package/lib/hooks/internal/usePrevious.js +18 -0
  192. package/lib/hooks/internal/useStateRef.d.ts +3 -0
  193. package/lib/hooks/internal/useStateRef.d.ts.map +1 -0
  194. package/lib/hooks/internal/useStateRef.js +40 -0
  195. package/lib/hooks/internal/useValueRef.d.ts +3 -0
  196. package/lib/hooks/internal/useValueRef.d.ts.map +1 -0
  197. package/lib/hooks/internal/useValueRef.js +25 -0
  198. package/lib/hooks/useFocus.d.ts +1 -1
  199. package/lib/hooks/useFocus.d.ts.map +1 -1
  200. package/lib/hooks/useFocus.js +1 -1
  201. package/lib/hooks/useObserveTranscriptFocus.d.ts +2 -2
  202. package/lib/hooks/useObserveTranscriptFocus.d.ts.map +1 -1
  203. package/lib/hooks/useObserveTranscriptFocus.js +1 -1
  204. package/lib/hooks/useRenderMarkdownAsHTML.d.ts.map +1 -1
  205. package/lib/hooks/useRenderMarkdownAsHTML.js +1 -1
  206. package/lib/hooks/useScrollTo.d.ts.map +1 -1
  207. package/lib/hooks/useScrollTo.js +1 -1
  208. package/lib/hooks/useScrollToEnd.d.ts.map +1 -1
  209. package/lib/hooks/useScrollToEnd.js +1 -1
  210. package/lib/hooks/useSendFiles.d.ts.map +1 -1
  211. package/lib/hooks/useSendFiles.js +4 -4
  212. package/lib/index.d.ts +13 -3
  213. package/lib/index.d.ts.map +1 -1
  214. package/lib/index.js +20 -18
  215. package/lib/providers/ActivityTree/ActivityTreeComposer.d.ts +5 -0
  216. package/lib/providers/ActivityTree/ActivityTreeComposer.d.ts.map +1 -0
  217. package/lib/providers/ActivityTree/ActivityTreeComposer.js +86 -0
  218. package/lib/providers/ActivityTree/private/Context.d.ts +9 -0
  219. package/lib/providers/ActivityTree/private/Context.d.ts.map +1 -0
  220. package/lib/providers/ActivityTree/private/Context.js +13 -0
  221. package/lib/providers/ActivityTree/private/types.d.ts +10 -0
  222. package/lib/providers/ActivityTree/private/types.d.ts.map +1 -0
  223. package/lib/providers/ActivityTree/private/types.js +2 -0
  224. package/lib/providers/ActivityTree/private/useActivitiesWithRenderer.d.ts +4 -0
  225. package/lib/providers/ActivityTree/private/useActivitiesWithRenderer.d.ts.map +1 -0
  226. package/lib/providers/ActivityTree/private/useActivitiesWithRenderer.js +58 -0
  227. package/lib/providers/ActivityTree/private/useActivityTreeWithRenderer.d.ts +5 -0
  228. package/lib/providers/ActivityTree/private/useActivityTreeWithRenderer.d.ts.map +1 -0
  229. package/lib/providers/ActivityTree/private/useActivityTreeWithRenderer.js +166 -0
  230. package/lib/providers/ActivityTree/private/useContext.d.ts +3 -0
  231. package/lib/providers/ActivityTree/private/useContext.d.ts.map +1 -0
  232. package/lib/providers/ActivityTree/private/useContext.js +24 -0
  233. package/lib/providers/ActivityTree/useActivityTreeWithRenderer.d.ts +8 -0
  234. package/lib/providers/ActivityTree/useActivityTreeWithRenderer.d.ts.map +1 -0
  235. package/lib/providers/ActivityTree/useActivityTreeWithRenderer.js +17 -0
  236. package/lib/providers/LiveRegionTwin/LiveRegionTwinComposer.d.ts +37 -0
  237. package/lib/providers/LiveRegionTwin/LiveRegionTwinComposer.d.ts.map +1 -0
  238. package/lib/providers/LiveRegionTwin/LiveRegionTwinComposer.js +160 -0
  239. package/lib/providers/LiveRegionTwin/private/Context.d.ts +10 -0
  240. package/lib/providers/LiveRegionTwin/private/Context.d.ts.map +1 -0
  241. package/lib/providers/LiveRegionTwin/private/Context.js +13 -0
  242. package/lib/providers/LiveRegionTwin/private/LiveRegionTwinContainer.d.ts +12 -0
  243. package/lib/providers/LiveRegionTwin/private/LiveRegionTwinContainer.d.ts.map +1 -0
  244. package/lib/providers/LiveRegionTwin/private/LiveRegionTwinContainer.js +100 -0
  245. package/lib/providers/LiveRegionTwin/private/types.d.ts +8 -0
  246. package/lib/providers/LiveRegionTwin/private/types.d.ts.map +1 -0
  247. package/lib/providers/LiveRegionTwin/private/types.js +2 -0
  248. package/lib/providers/LiveRegionTwin/private/useContext.d.ts +3 -0
  249. package/lib/providers/LiveRegionTwin/private/useContext.d.ts.map +1 -0
  250. package/lib/providers/LiveRegionTwin/private/useContext.js +24 -0
  251. package/lib/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.d.ts +2 -0
  252. package/lib/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.d.ts.map +1 -0
  253. package/lib/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.js +24 -0
  254. package/lib/providers/LiveRegionTwin/private/useStaticElementEntries.d.ts +3 -0
  255. package/lib/providers/LiveRegionTwin/private/useStaticElementEntries.d.ts.map +1 -0
  256. package/lib/providers/LiveRegionTwin/private/useStaticElementEntries.js +15 -0
  257. package/lib/providers/LiveRegionTwin/useQueueStaticElement.d.ts +8 -0
  258. package/lib/providers/LiveRegionTwin/useQueueStaticElement.d.ts.map +1 -0
  259. package/lib/providers/LiveRegionTwin/useQueueStaticElement.js +20 -0
  260. package/lib/providers/TranscriptFocus/TranscriptFocusComposer.d.ts +7 -0
  261. package/lib/providers/TranscriptFocus/TranscriptFocusComposer.d.ts.map +1 -0
  262. package/lib/providers/TranscriptFocus/TranscriptFocusComposer.js +184 -0
  263. package/lib/providers/TranscriptFocus/private/Context.d.ts +12 -0
  264. package/lib/providers/TranscriptFocus/private/Context.d.ts.map +1 -0
  265. package/lib/providers/TranscriptFocus/private/Context.js +13 -0
  266. package/lib/providers/TranscriptFocus/private/useContext.d.ts +2 -0
  267. package/lib/providers/TranscriptFocus/private/useContext.d.ts.map +1 -0
  268. package/lib/providers/TranscriptFocus/private/useContext.js +24 -0
  269. package/lib/providers/TranscriptFocus/useActiveDescendantId.d.ts +2 -0
  270. package/lib/providers/TranscriptFocus/useActiveDescendantId.d.ts.map +1 -0
  271. package/lib/providers/TranscriptFocus/useActiveDescendantId.js +15 -0
  272. package/lib/providers/TranscriptFocus/useFocusByActivityKey.d.ts +8 -0
  273. package/lib/providers/TranscriptFocus/useFocusByActivityKey.d.ts.map +1 -0
  274. package/lib/providers/TranscriptFocus/useFocusByActivityKey.js +21 -0
  275. package/lib/providers/TranscriptFocus/useFocusRelativeActivity.d.ts +2 -0
  276. package/lib/providers/TranscriptFocus/useFocusRelativeActivity.d.ts.map +1 -0
  277. package/lib/providers/TranscriptFocus/useFocusRelativeActivity.js +15 -0
  278. package/lib/providers/TranscriptFocus/useFocusedActivityKey.d.ts +2 -0
  279. package/lib/providers/TranscriptFocus/useFocusedActivityKey.d.ts.map +1 -0
  280. package/lib/providers/TranscriptFocus/useFocusedActivityKey.js +15 -0
  281. package/lib/providers/TranscriptFocus/useFocusedExplicitly.d.ts +2 -0
  282. package/lib/providers/TranscriptFocus/useFocusedExplicitly.d.ts.map +1 -0
  283. package/lib/providers/TranscriptFocus/useFocusedExplicitly.js +15 -0
  284. package/lib/providers/TranscriptFocus/useGetDescendantIdByActivityKey.d.ts +2 -0
  285. package/lib/providers/TranscriptFocus/useGetDescendantIdByActivityKey.d.ts.map +1 -0
  286. package/lib/providers/TranscriptFocus/useGetDescendantIdByActivityKey.js +15 -0
  287. package/package.json +30 -33
  288. package/src/Activity/CarouselFilmStripAttachment.js +0 -1
  289. package/src/Activity/Speak.tsx +21 -18
  290. package/src/Activity/StackedLayout.tsx +30 -35
  291. package/src/Attachment/FileAttachment.js +1 -1
  292. package/src/Attachment/FileContent.tsx +12 -0
  293. package/src/BasicSendBox.tsx +3 -2
  294. package/src/BasicToaster.js +5 -1
  295. package/src/BasicTranscript.tsx +894 -0
  296. package/src/BasicTypingIndicator.tsx +3 -2
  297. package/src/Composer.tsx +41 -29
  298. package/src/Middleware/Activity/createCoreMiddleware.tsx +47 -46
  299. package/src/Middleware/ActivityStatus/SendStatus/SendStatus.tsx +5 -3
  300. package/src/Middleware/ActivityStatus/Timestamp.tsx +5 -3
  301. package/src/Middleware/ActivityStatus/createSendStatusMiddleware.js +2 -0
  302. package/src/Middleware/Attachment/createCoreMiddleware.tsx +28 -28
  303. package/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.tsx +25 -23
  304. package/src/Middleware/Avatar/createCoreMiddleware.tsx +9 -8
  305. package/src/Middleware/CardAction/createCoreMiddleware.js +9 -2
  306. package/src/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.ts +11 -9
  307. package/src/Middleware/Toast/createCoreMiddleware.tsx +12 -10
  308. package/src/Middleware/TypingIndicator/createCoreMiddleware.tsx +8 -2
  309. package/src/ScreenReaderActivity.js +18 -3
  310. package/src/{ScreenReaderText.js → ScreenReaderText.tsx} +27 -9
  311. package/src/SendBox/{IconButton.js → IconButton.tsx} +19 -3
  312. package/src/SendBox/{SuggestedAction.js → SuggestedAction.tsx} +72 -35
  313. package/src/SendBox/SuggestedActions.tsx +48 -21
  314. package/src/Styles/StyleSet/BasicTranscript.ts +34 -20
  315. package/src/Styles/StyleSet/Bubble.ts +0 -1
  316. package/src/Styles/StyleSet/CarouselFilmStrip.ts +12 -10
  317. package/src/Styles/StyleSet/CarouselFilmStripAttachment.ts +4 -3
  318. package/src/Styles/StyleSet/KeyboardHelp.ts +157 -0
  319. package/src/Styles/StyleSet/ScrollToEndButton.ts +1 -1
  320. package/src/Styles/StyleSet/SendBoxButton.ts +84 -13
  321. package/src/Styles/StyleSet/SendBoxTextBox.ts +1 -2
  322. package/src/Styles/StyleSet/StackedLayout.ts +13 -11
  323. package/src/Styles/StyleSet/SuggestedAction.ts +129 -42
  324. package/src/Styles/StyleSet/SuggestedActions.ts +13 -5
  325. package/src/Styles/createStyleSet.ts +2 -1
  326. package/src/Styles/mirrorStyle.js +10 -2
  327. package/src/Toast/NotificationIcon.js +4 -1
  328. package/src/Toast/createToastMiddleware.tsx +4 -1
  329. package/src/Transcript/ActivityRow.tsx +123 -0
  330. package/src/Transcript/ActivityTextAlt.tsx +31 -0
  331. package/src/Transcript/FocusTrap.tsx +64 -0
  332. package/src/Transcript/KeyboardHelp.tsx +282 -0
  333. package/src/Transcript/LiveRegionTranscript.tsx +196 -0
  334. package/src/Transcript/types.ts +1 -0
  335. package/src/Transcript/useActivityAccessibleName.ts +84 -0
  336. package/src/Transcript/useTypistNames.ts +37 -0
  337. package/src/Utils/{AccessibleButton.js → AccessibleButton.tsx} +19 -4
  338. package/src/Utils/{FocusRedirector.js → FocusRedirector.tsx} +21 -8
  339. package/src/Utils/InlineMarkdown.js +18 -2
  340. package/src/Utils/TypeFocusSink/inputtableKey.ts +5 -1
  341. package/src/Utils/createCustomEvent.js +7 -1
  342. package/src/Utils/detectBrowser.js +2 -1
  343. package/src/Utils/findAncestor.ts +12 -0
  344. package/src/Utils/getActivityUniqueId.ts +5 -0
  345. package/src/Utils/intersectionOf.ts +14 -0
  346. package/src/Utils/isZeroOrPositive.ts +7 -0
  347. package/src/Utils/mapMap.js +7 -1
  348. package/src/Utils/scrollIntoViewWithBlockNearest.ts +20 -0
  349. package/src/Utils/shallowEquals.js +8 -1
  350. package/src/Utils/supportPseudoClass.ts +17 -0
  351. package/src/Utils/{tabbableElements.js → tabbableElements.ts} +6 -5
  352. package/src/connectToWebChat.js +11 -4
  353. package/src/hooks/internal/BypassSpeechSynthesisPonyfill.js +3 -1
  354. package/src/hooks/internal/useChanged.ts +17 -0
  355. package/src/hooks/internal/useDispatchScrollPosition.js +1 -3
  356. package/src/hooks/internal/useDispatchTranscriptFocusByActivityKey.ts +5 -0
  357. package/src/hooks/internal/useFocusVisible.ts +22 -0
  358. package/src/hooks/internal/useMemoWithPrevious.ts +16 -0
  359. package/src/hooks/internal/useMemoize.spec.js +1 -1
  360. package/src/hooks/internal/useMemoize.ts +53 -0
  361. package/src/hooks/internal/useObserveFocusVisible.ts +252 -0
  362. package/src/hooks/internal/usePrevious.ts +12 -0
  363. package/src/hooks/internal/useStateRef.ts +31 -0
  364. package/src/hooks/internal/useValueRef.ts +22 -0
  365. package/src/hooks/useFocus.ts +1 -1
  366. package/src/hooks/useObserveTranscriptFocus.ts +2 -2
  367. package/src/hooks/useRenderMarkdownAsHTML.ts +4 -5
  368. package/src/hooks/useScrollTo.ts +4 -3
  369. package/src/hooks/useScrollToEnd.ts +4 -3
  370. package/src/hooks/useSendFiles.ts +7 -5
  371. package/src/index.ts +0 -1
  372. package/src/providers/ActivityTree/ActivityTreeComposer.tsx +74 -0
  373. package/src/providers/ActivityTree/private/Context.ts +12 -0
  374. package/src/providers/ActivityTree/private/types.ts +12 -0
  375. package/src/providers/ActivityTree/private/useActivitiesWithRenderer.ts +64 -0
  376. package/src/providers/ActivityTree/private/useActivityTreeWithRenderer.ts +135 -0
  377. package/src/providers/ActivityTree/private/useContext.ts +15 -0
  378. package/src/providers/ActivityTree/useActivityTreeWithRenderer.ts +16 -0
  379. package/src/providers/LiveRegionTwin/LiveRegionTwinComposer.tsx +161 -0
  380. package/src/providers/LiveRegionTwin/private/Context.ts +15 -0
  381. package/src/providers/LiveRegionTwin/private/LiveRegionTwinContainer.tsx +80 -0
  382. package/src/providers/LiveRegionTwin/private/types.ts +10 -0
  383. package/src/providers/LiveRegionTwin/private/useContext.ts +15 -0
  384. package/src/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.ts +13 -0
  385. package/src/providers/LiveRegionTwin/private/useStaticElementEntries.ts +7 -0
  386. package/src/providers/LiveRegionTwin/useQueueStaticElement.ts +12 -0
  387. package/src/providers/TranscriptFocus/TranscriptFocusComposer.tsx +180 -0
  388. package/src/providers/TranscriptFocus/private/Context.ts +16 -0
  389. package/src/providers/TranscriptFocus/private/useContext.ts +13 -0
  390. package/src/providers/TranscriptFocus/useActiveDescendantId.ts +5 -0
  391. package/src/providers/TranscriptFocus/useFocusByActivityKey.ts +14 -0
  392. package/src/providers/TranscriptFocus/useFocusRelativeActivity.ts +5 -0
  393. package/src/providers/TranscriptFocus/useFocusedActivityKey.ts +5 -0
  394. package/src/providers/TranscriptFocus/useFocusedExplicitly.ts +5 -0
  395. package/src/providers/TranscriptFocus/useGetDescendantIdByActivityKey.ts +5 -0
  396. package/.eslintignore +0 -1
  397. package/lib/Middleware/GroupActivities/createCoreMiddleware.js +0 -69
  398. package/lib/Utils/findLastIndex.js +0 -32
  399. package/lib/hooks/internal/useAcknowledgedActivity.js +0 -90
  400. package/lib/hooks/internal/useDispatchTranscriptFocus.js +0 -19
  401. package/src/BasicTranscript.js +0 -1139
  402. package/src/Middleware/GroupActivities/createCoreMiddleware.js +0 -57
  403. package/src/Utils/findLastIndex.js +0 -11
  404. package/src/Utils/findLastIndex.spec.js +0 -31
  405. package/src/Utils/getActivityUniqueId.js +0 -3
  406. package/src/Utils/intersectionOf.js +0 -11
  407. package/src/Utils/isZeroOrPositive.js +0 -4
  408. package/src/hooks/internal/useAcknowledgedActivity.js +0 -65
  409. package/src/hooks/internal/useChanged.js +0 -10
  410. package/src/hooks/internal/useDispatchTranscriptFocus.js +0 -7
  411. package/src/hooks/internal/useMemoize.js +0 -37
@@ -9,7 +9,13 @@ import activityAltText from './Utils/activityAltText';
9
9
  import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject';
10
10
  import useRenderMarkdownAsHTML from './hooks/useRenderMarkdownAsHTML';
11
11
 
12
- const { useAvatarForBot, useCreateAttachmentForScreenReaderRenderer, useDateFormatter, useLocalizer } = hooks;
12
+ const {
13
+ useAvatarForBot,
14
+ useCreateAttachmentForScreenReaderRenderer,
15
+ useDateFormatter,
16
+ useGetKeyByActivity,
17
+ useLocalizer
18
+ } = hooks;
13
19
 
14
20
  const ROOT_STYLE = {
15
21
  '&.webchat__screen-reader-activity': {
@@ -76,6 +82,7 @@ ScreenReaderAttachments.propTypes = {
76
82
  const ScreenReaderActivity = ({ activity, children, id, renderAttachments }) => {
77
83
  const [{ initials: botInitials }] = useAvatarForBot();
78
84
  const formatDate = useDateFormatter();
85
+ const getKeyByActivity = useGetKeyByActivity();
79
86
  const localize = useLocalizer();
80
87
  const renderMarkdownAsHTML = useRenderMarkdownAsHTML();
81
88
  const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + '';
@@ -90,18 +97,26 @@ const ScreenReaderActivity = ({ activity, children, id, renderAttachments }) =>
90
97
  ).replace(/\s{2,}/gu, ' ');
91
98
 
92
99
  const timestampAlt = localize('ACTIVITY_STATUS_SEND_STATUS_ALT_SENT_AT', formatDate(timestamp));
100
+ const labelId = useMemo(
101
+ () => `webchat__screen-reader-activity__label-${getKeyByActivity(activity)}`,
102
+ [activity, getKeyByActivity]
103
+ );
93
104
 
94
105
  return (
95
106
  <article
96
107
  aria-atomic={true}
108
+ // Narrator requires the "aria-labelledby" attribute, otherwise, it will only read "aria-roledescription".
109
+ // However, iOS VoiceOver and NVDA both ignore the "aria-labelledby" and read out the whole content, including timestamp.
110
+ aria-labelledby={labelId}
97
111
  aria-roledescription="message"
98
112
  className={classNames('webchat__screen-reader-activity', rootClassName)}
99
113
  // "id" attribute is used by `aria-labelledby`.
100
114
  // eslint-disable-next-line react/forbid-dom-props
101
115
  id={id}
102
- role="region"
103
116
  >
104
- <p>
117
+ {/* "id" attribute is used by `aria-labelledby`. */}
118
+ {/* eslint-disable-next-line react/forbid-dom-props */}
119
+ <p id={labelId}>
105
120
  <span>{greetingAlt}</span>
106
121
  <span>{textAlt}</span>
107
122
  </p>
@@ -1,7 +1,9 @@
1
1
  /* eslint react/forbid-dom-props: ["off"] */
2
2
 
3
3
  import PropTypes from 'prop-types';
4
- import React from 'react';
4
+ import React, { forwardRef } from 'react';
5
+
6
+ import type { VFC } from 'react';
5
7
 
6
8
  import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject';
7
9
 
@@ -21,21 +23,37 @@ const ROOT_STYLE = {
21
23
  width: 1
22
24
  };
23
25
 
24
- const ScreenReaderText = ({ id, text }) => {
25
- const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + '';
26
-
27
- return (
28
- <div className={rootClassName} id={id}>
29
- {text}
30
- </div>
31
- );
26
+ type ScreenReaderTextProps = {
27
+ 'aria-hidden'?: boolean;
28
+ id?: string;
29
+ text: string;
32
30
  };
33
31
 
32
+ const ScreenReaderText: VFC<ScreenReaderTextProps> = forwardRef<HTMLDivElement, ScreenReaderTextProps>(
33
+ ({ 'aria-hidden': ariaHidden, id, text }, ref) => {
34
+ const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + '';
35
+
36
+ if (ariaHidden && !id) {
37
+ console.warn(
38
+ 'botframework-webchat assertion: when "aria-hidden" is set, the screen reader text should be read by "aria-labelledby". Thus, "id" must be set.'
39
+ );
40
+ }
41
+
42
+ return (
43
+ <div aria-hidden={ariaHidden} className={rootClassName} id={id} ref={ref}>
44
+ {text}
45
+ </div>
46
+ );
47
+ }
48
+ );
49
+
34
50
  ScreenReaderText.defaultProps = {
51
+ 'aria-hidden': undefined,
35
52
  id: undefined
36
53
  };
37
54
 
38
55
  ScreenReaderText.propTypes = {
56
+ 'aria-hidden': PropTypes.bool,
39
57
  id: PropTypes.string,
40
58
  text: PropTypes.string.isRequired
41
59
  };
@@ -1,16 +1,28 @@
1
1
  import { hooks } from 'botframework-webchat-api';
2
2
  import classNames from 'classnames';
3
3
  import PropTypes from 'prop-types';
4
- import React from 'react';
4
+ import React, { FC, MouseEventHandler, ReactNode, useRef } from 'react';
5
5
 
6
6
  import AccessibleButton from '../Utils/AccessibleButton';
7
+ import useFocusVisible from '../hooks/internal/useFocusVisible';
7
8
  import useStyleSet from '../hooks/useStyleSet';
8
9
 
9
10
  const { useStyleOptions } = hooks;
10
11
 
11
- const IconButton = ({ alt, children, className, disabled, onClick }) => {
12
- const [{ sendBoxButtonAlignment }] = useStyleOptions();
12
+ type IconButtonProps = {
13
+ alt?: string;
14
+ children?: ReactNode;
15
+ className?: string;
16
+ disabled?: boolean;
17
+ onClick?: MouseEventHandler<HTMLButtonElement>;
18
+ };
19
+
20
+ const IconButton: FC<IconButtonProps> = ({ alt, children, className, disabled, onClick }) => {
13
21
  const [{ sendBoxButton: sendBoxButtonStyleSet }] = useStyleSet();
22
+ const [{ sendBoxButtonAlignment }] = useStyleOptions();
23
+ const buttonRef = useRef<HTMLButtonElement>();
24
+
25
+ const [focusVisible] = useFocusVisible(buttonRef);
14
26
 
15
27
  return (
16
28
  <AccessibleButton
@@ -18,16 +30,20 @@ const IconButton = ({ alt, children, className, disabled, onClick }) => {
18
30
  sendBoxButtonStyleSet + '',
19
31
  'webchat__icon-button',
20
32
  {
33
+ 'webchat__icon-button--focus-visible': focusVisible,
21
34
  'webchat__icon-button--stretch': sendBoxButtonAlignment !== 'bottom' && sendBoxButtonAlignment !== 'top'
22
35
  },
23
36
  className + ''
24
37
  )}
25
38
  disabled={disabled}
26
39
  onClick={disabled ? undefined : onClick}
40
+ ref={buttonRef}
27
41
  title={alt}
28
42
  type="button"
29
43
  >
44
+ <div className="webchat__icon-button__shade" />
30
45
  {children}
46
+ <div className="webchat__icon-button__keyboard-focus-indicator" />
31
47
  </AccessibleButton>
32
48
  );
33
49
  };
@@ -1,12 +1,14 @@
1
1
  import { hooks } from 'botframework-webchat-api';
2
2
  import classNames from 'classnames';
3
3
  import PropTypes from 'prop-types';
4
- import React, { useCallback, useRef } from 'react';
4
+ import React, { MouseEventHandler, useCallback, useRef, VFC } from 'react';
5
+ import type { DirectLineCardAction } from 'botframework-webchat-core';
5
6
 
6
7
  import AccessibleButton from '../Utils/AccessibleButton';
7
8
  import connectToWebChat from '../connectToWebChat';
8
9
  import useFocus from '../hooks/useFocus';
9
10
  import useFocusAccessKeyEffect from '../Utils/AccessKeySink/useFocusAccessKeyEffect';
11
+ import useFocusVisible from '../hooks/internal/useFocusVisible';
10
12
  import useLocalizeAccessKey from '../hooks/internal/useLocalizeAccessKey';
11
13
  import useScrollToEnd from '../hooks/useScrollToEnd';
12
14
  import useSuggestedActionsAccessKey from '../hooks/internal/useSuggestedActionsAccessKey';
@@ -17,10 +19,8 @@ const { useDirection, useDisabled, usePerformCardAction, useStyleOptions, useSug
17
19
 
18
20
  const ROOT_STYLE = {
19
21
  '&.webchat__suggested-action': {
20
- '& .webchat__suggested-action__button': {
21
- display: 'flex',
22
- overflow: 'hidden' // Prevent image from leaking; object-fit does not work with IE11
23
- }
22
+ display: 'flex',
23
+ overflow: 'hidden' // Prevent image from leaking; object-fit does not work with IE11
24
24
  }
25
25
  };
26
26
 
@@ -37,7 +37,39 @@ const connectSuggestedAction = (...selectors) =>
37
37
  ...selectors
38
38
  );
39
39
 
40
- const SuggestedAction = ({ buttonText, className, displayText, image, imageAlt, text, textClassName, type, value }) => {
40
+ type SuggestedActionProps = {
41
+ buttonText: string;
42
+ className?: string;
43
+ displayText?: string;
44
+ image?: string;
45
+ imageAlt?: string;
46
+ text?: string;
47
+ textClassName?: string;
48
+ type?:
49
+ | 'call'
50
+ | 'downloadFile'
51
+ | 'imBack'
52
+ | 'messageBack'
53
+ | 'openUrl'
54
+ | 'playAudio'
55
+ | 'playVideo'
56
+ | 'postBack'
57
+ | 'showImage'
58
+ | 'signin';
59
+ value?: any;
60
+ };
61
+
62
+ const SuggestedAction: VFC<SuggestedActionProps> = ({
63
+ buttonText,
64
+ className,
65
+ displayText,
66
+ image,
67
+ imageAlt,
68
+ text,
69
+ textClassName,
70
+ type,
71
+ value
72
+ }) => {
41
73
  const [_, setSuggestedActions] = useSuggestedActions();
42
74
  const [{ suggestedActionsStackedLayoutButtonTextWrap }] = useStyleOptions();
43
75
  const [{ suggestedAction: suggestedActionStyleSet }] = useStyleSet();
@@ -48,12 +80,16 @@ const SuggestedAction = ({ buttonText, className, displayText, image, imageAlt,
48
80
  const focusRef = useRef();
49
81
  const localizeAccessKey = useLocalizeAccessKey();
50
82
  const performCardAction = usePerformCardAction();
51
- const scrollToEnd = useScrollToEnd();
52
83
  const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + '';
84
+ const scrollToEnd = useScrollToEnd();
53
85
 
54
- const handleClick = useCallback(
86
+ const [focusVisible] = useFocusVisible(focusRef);
87
+
88
+ const handleClick = useCallback<MouseEventHandler<HTMLButtonElement>>(
55
89
  ({ target }) => {
56
- performCardAction({ displayText, text, type, value }, { target });
90
+ // TODO: [P3] #XXX We should not destruct DirectLineCardAction into React props and pass them in. It makes typings difficult.
91
+ // Instead, we should pass a "cardAction" props.
92
+ performCardAction({ displayText, text, type, value } as DirectLineCardAction, { target });
57
93
 
58
94
  // Since "openUrl" action do not submit, the suggested action buttons do not hide after click.
59
95
  type === 'openUrl' && setSuggestedActions([]);
@@ -67,38 +103,37 @@ const SuggestedAction = ({ buttonText, className, displayText, image, imageAlt,
67
103
  useFocusAccessKeyEffect(accessKey, focusRef);
68
104
 
69
105
  return (
70
- <div
106
+ <AccessibleButton
107
+ {...(accessKey ? { 'aria-keyshortcuts': localizeAccessKey(accessKey) } : {})}
71
108
  className={classNames(
72
109
  'webchat__suggested-action',
73
- { 'webchat__suggested-action--rtl': direction === 'rtl' },
110
+ {
111
+ 'webchat__suggested-action--focus-visible': focusVisible,
112
+ 'webchat__suggested-action--rtl': direction === 'rtl',
113
+ 'webchat__suggested-action--wrapping': suggestedActionsStackedLayoutButtonTextWrap
114
+ },
74
115
  rootClassName,
75
116
  suggestedActionStyleSet + '',
76
117
  (className || '') + ''
77
118
  )}
119
+ disabled={disabled}
120
+ onClick={handleClick}
121
+ ref={focusRef}
122
+ type="button"
78
123
  >
79
- <AccessibleButton
80
- {...(accessKey ? { 'aria-keyshortcuts': localizeAccessKey(accessKey) } : {})}
81
- className={classNames('webchat__suggested-action__button', {
82
- 'webchat__suggested-action--wrapping': suggestedActionsStackedLayoutButtonTextWrap
83
- })}
84
- disabled={disabled}
85
- onClick={handleClick}
86
- ref={focusRef}
87
- type="button"
88
- >
89
- {image && (
90
- <img
91
- alt={imageAlt}
92
- className={classNames(
93
- 'webchat__suggested-action__image',
94
- direction === 'rtl' && 'webchat__suggested-action__image--rtl'
95
- )}
96
- src={image}
97
- />
98
- )}
99
- <span className={classNames('webchat__suggested-action__text', (textClassName || '') + '')}>{buttonText}</span>
100
- </AccessibleButton>
101
- </div>
124
+ {image && (
125
+ <img
126
+ alt={imageAlt}
127
+ className={classNames(
128
+ 'webchat__suggested-action__image',
129
+ direction === 'rtl' && 'webchat__suggested-action__image--rtl'
130
+ )}
131
+ src={image}
132
+ />
133
+ )}
134
+ <span className={classNames('webchat__suggested-action__text', (textClassName || '') + '')}>{buttonText}</span>
135
+ <div className="webchat__suggested-action__keyboard-focus-indicator" />
136
+ </AccessibleButton>
102
137
  );
103
138
  };
104
139
 
@@ -109,7 +144,7 @@ SuggestedAction.defaultProps = {
109
144
  imageAlt: undefined,
110
145
  text: '',
111
146
  textClassName: '',
112
- type: '',
147
+ type: undefined,
113
148
  value: undefined
114
149
  };
115
150
 
@@ -121,6 +156,8 @@ SuggestedAction.propTypes = {
121
156
  imageAlt: PropTypes.string,
122
157
  text: PropTypes.string,
123
158
  textClassName: PropTypes.string,
159
+ // TypeScript class is not mappable to PropTypes.
160
+ // @ts-ignore
124
161
  type: PropTypes.string,
125
162
  value: PropTypes.any
126
163
  };
@@ -1,11 +1,11 @@
1
1
  /* eslint react/no-array-index-key: "off" */
2
2
 
3
- import { DirectLineCardAction } from 'botframework-webchat-core';
4
3
  import { hooks } from 'botframework-webchat-api';
5
4
  import BasicFilm, { createBasicStyleSet as createBasicStyleSetForReactFilm } from 'react-film';
6
5
  import classNames from 'classnames';
7
6
  import PropTypes from 'prop-types';
8
- import React, { FC, useMemo } from 'react';
7
+ import React, { FC, useMemo, useRef } from 'react';
8
+ import type { DirectLineCardAction } from 'botframework-webchat-core';
9
9
 
10
10
  import connectToWebChat from '../connectToWebChat';
11
11
  import ScreenReaderText from '../ScreenReaderText';
@@ -151,7 +151,7 @@ const SuggestedActionFlowContainer = ({ children, className, screenReaderText })
151
151
  {!!children && !!React.Children.count(children) && (
152
152
  <div className="webchat__suggested-actions__flow-box">
153
153
  {React.Children.map(children, child => (
154
- <div className="webchat__suggested-actions__item">{child}</div>
154
+ <div className="webchat__suggested-actions__flow-item-box">{child}</div>
155
155
  ))}
156
156
  </div>
157
157
  )}
@@ -215,6 +215,7 @@ type SuggestedActionsProps = {
215
215
  const SuggestedActions: FC<SuggestedActionsProps> = ({ className, suggestedActions = [] }) => {
216
216
  const [{ suggestedActionLayout, suggestedActionsStackedLayoutButtonTextWrap }] = useStyleOptions();
217
217
  const [accessKey] = useSuggestedActionsAccessKey();
218
+ const hideEmptyRef = useRef(true);
218
219
  const localize = useLocalizer();
219
220
  const localizeAccessKey = useLocalizeAccessKey();
220
221
 
@@ -234,30 +235,57 @@ const SuggestedActions: FC<SuggestedActionsProps> = ({ className, suggestedActio
234
235
  imageAltText?: string;
235
236
  text?: string;
236
237
  title?: string;
237
- type: string;
238
+ type:
239
+ | 'call'
240
+ | 'downloadFile'
241
+ | 'imBack'
242
+ | 'messageBack'
243
+ | 'openUrl'
244
+ | 'playAudio'
245
+ | 'playVideo'
246
+ | 'postBack'
247
+ | 'showImage'
248
+ | 'signin';
238
249
  value?: { [key: string]: any } | string;
239
250
  };
240
251
 
241
252
  return (
242
- <SuggestedAction
243
- buttonText={suggestedActionText({ displayText, title, type, value })}
244
- className="webchat__suggested-actions__button"
245
- displayText={displayText}
246
- image={image}
247
- imageAlt={imageAltText}
248
- key={index}
249
- text={text}
250
- textClassName={
251
- suggestedActionLayout === 'stacked' && suggestedActionsStackedLayoutButtonTextWrap
252
- ? 'webchat__suggested-actions__button-text-stacked-text-wrap'
253
- : 'webchat__suggested-actions__button-text'
254
- }
255
- type={type}
256
- value={value}
257
- />
253
+ <div className="webchat__suggested-actions__item-box" key={index}>
254
+ <SuggestedAction
255
+ buttonText={suggestedActionText({ displayText, title, type, value })}
256
+ className="webchat__suggested-actions__button"
257
+ displayText={displayText}
258
+ image={image}
259
+ imageAlt={imageAltText}
260
+ text={text}
261
+ textClassName={
262
+ suggestedActionLayout === 'stacked' && suggestedActionsStackedLayoutButtonTextWrap
263
+ ? 'webchat__suggested-actions__button-text-stacked-text-wrap'
264
+ : 'webchat__suggested-actions__button-text'
265
+ }
266
+ type={type}
267
+ value={value}
268
+ />
269
+ </div>
258
270
  );
259
271
  });
260
272
 
273
+ // (Related to #4021)
274
+ //
275
+ // To improve accessibility UX, if there are no suggested actions, and this container was never shown.
276
+ // Then, avoid rendering the alt-text "Suggested Actions Container: Is empty".
277
+ //
278
+ // This is to reduce the narration of "Is empty".
279
+ //
280
+ // After any suggested actions were shown during the lifetime of this container, then we will
281
+ // continue to start showing "Suggested Actions Container: Is empty" when the container is empty.
282
+ if (!children.length && hideEmptyRef.current) {
283
+ return null;
284
+ }
285
+
286
+ // Otherwise, if we have rendered once, we will continue to render "Is empty".
287
+ hideEmptyRef.current = false;
288
+
261
289
  if (suggestedActionLayout === 'flow') {
262
290
  return (
263
291
  <SuggestedActionFlowContainer className={className} screenReaderText={screenReaderText}>
@@ -287,7 +315,6 @@ SuggestedActions.propTypes = {
287
315
  className: PropTypes.string,
288
316
 
289
317
  // TypeScript class is not mappable to PropTypes.func
290
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
291
318
  // @ts-ignore
292
319
  suggestedActions: PropTypes.arrayOf(
293
320
  PropTypes.shape({
@@ -26,9 +26,12 @@ export default function createBasicTranscriptStyleSet({
26
26
  borderStyle: transcriptActivityVisualKeyboardIndicatorStyle,
27
27
  borderWidth: transcriptActivityVisualKeyboardIndicatorWidth,
28
28
  boxSizing: 'border-box',
29
- height: `calc(100% - ${paddingRegular}px)`,
29
+ height: `calc(100% - ${paddingRegular / 2}px)`,
30
30
  left: 0,
31
- margin: paddingRegular / 2,
31
+ marginBottom: 0,
32
+ marginLeft: paddingRegular / 2,
33
+ marginRight: paddingRegular / 2,
34
+ marginTop: 0,
32
35
  pointerEvents: 'none',
33
36
  position: 'absolute',
34
37
  top: 0,
@@ -36,40 +39,51 @@ export default function createBasicTranscriptStyleSet({
36
39
  }
37
40
  },
38
41
 
39
- '&:focus .webchat__basic-transcript__focus-indicator, .webchat__basic-transcript__terminator:focus + .webchat__basic-transcript__focus-indicator': {
40
- height: '100%',
41
- borderColor: transcriptVisualKeyboardIndicatorColor,
42
- borderStyle: transcriptVisualKeyboardIndicatorStyle,
43
- borderWidth: transcriptVisualKeyboardIndicatorWidth,
44
- boxSizing: 'border-box',
45
- pointerEvents: 'none',
46
- position: 'absolute',
47
- top: 0,
48
- width: '100%'
49
- },
42
+ '&:focus .webchat__basic-transcript__focus-indicator, .webchat__basic-transcript__terminator:focus + .webchat__basic-transcript__focus-indicator':
43
+ {
44
+ height: '100%',
45
+ borderColor: transcriptVisualKeyboardIndicatorColor,
46
+ borderStyle: transcriptVisualKeyboardIndicatorStyle,
47
+ borderWidth: transcriptVisualKeyboardIndicatorWidth,
48
+ boxSizing: 'border-box',
49
+ pointerEvents: 'none',
50
+ position: 'absolute',
51
+ top: 0,
52
+ width: '100%'
53
+ },
50
54
 
51
55
  '& .webchat__basic-transcript__activity': {
52
- paddingTop: paddingRegular,
56
+ paddingTop: paddingRegular / 2,
53
57
  position: 'relative',
54
58
 
59
+ '&:first-child': {
60
+ marginTop: paddingRegular / 2
61
+ },
62
+
55
63
  '&:not(:first-child)': {
56
- marginTop: -paddingRegular
64
+ marginTop: -paddingRegular / 2
57
65
  }
58
66
  },
59
67
 
60
- '& .webchat__basic-transcript__activity-box:not(:empty)': {
61
- paddingBottom: paddingRegular
62
- },
63
-
64
- '& .webchat__basic-transcript__activity-sentinel': {
68
+ // When the activity is focused as active descendant, `scrollIntoView()` will scroll this invisible <div> into view.
69
+ '& .webchat__basic-transcript__activity-active-descendant': {
65
70
  height: '100%',
66
71
  left: 0,
72
+ marginTop: -paddingRegular / 2,
73
+ paddingBottom: paddingRegular / 2,
74
+ // The bounding box is expanded to both top and bottom to scroll focus indicator into view.
75
+ // We should ignore clicks to make sure this expansion don't register click as focus.
76
+ // Otherwise, when clicking on the very bottom edge of the activity, it will focus on next activity instead.
67
77
  pointerEvents: 'none',
68
78
  position: 'absolute',
69
79
  top: 0,
70
80
  width: '100%'
71
81
  },
72
82
 
83
+ '& .webchat__basic-transcript__activity-body:not(:empty)': {
84
+ paddingBottom: paddingRegular
85
+ },
86
+
73
87
  '& .webchat__basic-transcript__terminator': {
74
88
  bottom: 0,
75
89
  height: 0,
@@ -1,4 +1,3 @@
1
- /* eslint-disable prettier/prettier */
2
1
  /* eslint no-magic-numbers: ["error", { "ignore": [0, 1, 2] }] */
3
2
  import { StrictStyleOptions } from 'botframework-webchat-api';
4
3
 
@@ -23,11 +23,12 @@ export default function CarouselFilmStrip({
23
23
  transitionProperty: 'max-width'
24
24
  },
25
25
 
26
- '&.webchat__carousel-filmstrip--hide-nub, &.webchat__carousel-filmstrip--show-nub, &.webchat__carousel-filmstrip--hide-avatar, &.webchat__carousel-filmstrip--show-avatar': {
27
- '& .webchat__carousel-filmstrip__message': {
28
- maxWidth: bubbleMaxWidth + paddingRegular
29
- }
30
- },
26
+ '&.webchat__carousel-filmstrip--hide-nub, &.webchat__carousel-filmstrip--show-nub, &.webchat__carousel-filmstrip--hide-avatar, &.webchat__carousel-filmstrip--show-avatar':
27
+ {
28
+ '& .webchat__carousel-filmstrip__message': {
29
+ maxWidth: bubbleMaxWidth + paddingRegular
30
+ }
31
+ },
31
32
 
32
33
  '& .webchat__carousel-filmstrip__alignment-pad': {
33
34
  transitionDuration,
@@ -61,11 +62,12 @@ export default function CarouselFilmStrip({
61
62
  }
62
63
  },
63
64
 
64
- '&.webchat__carousel-filmstrip--hide-avatar, &.webchat__carousel-filmstrip--show-avatar, &.webchat__carousel-filmstrip--hide-nub, &.webchat__carousel-filmstrip--show-nub': {
65
- '& .webchat__carousel-filmstrip__nub-pad': {
66
- width: paddingRegular
67
- }
68
- },
65
+ '&.webchat__carousel-filmstrip--hide-avatar, &.webchat__carousel-filmstrip--show-avatar, &.webchat__carousel-filmstrip--hide-nub, &.webchat__carousel-filmstrip--show-nub':
66
+ {
67
+ '& .webchat__carousel-filmstrip__nub-pad': {
68
+ width: paddingRegular
69
+ }
70
+ },
69
71
 
70
72
  '&:not(.webchat__carousel-filmstrip--top-callout) .webchat__carousel-filmstrip__avatar-gutter': {
71
73
  justifyContent: 'flex-end'
@@ -47,9 +47,10 @@ export default function CarouselFilmStripAttachment({
47
47
  },
48
48
 
49
49
  '&.webchat__carousel-filmstrip-attachment--hide-nub, &.webchat__carousel-filmstrip-attachment--show-nub': {
50
- '&:not(.webchat__carousel-filmstrip-attachment--hide-avatar.webchat__carousel-filmstrip-attachment--show-avatar):first-child': {
51
- paddingLeft: paddingRegular * 2
52
- }
50
+ '&:not(.webchat__carousel-filmstrip-attachment--hide-avatar.webchat__carousel-filmstrip-attachment--show-avatar):first-child':
51
+ {
52
+ paddingLeft: paddingRegular * 2
53
+ }
53
54
  }
54
55
  })
55
56
  };