botframework-webchat-component 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 (451) hide show
  1. package/.eslintignore +1 -9
  2. package/.eslintrc.yml +6 -0
  3. package/lib/Activity/Avatar.d.ts +10 -0
  4. package/lib/Activity/Avatar.d.ts.map +1 -0
  5. package/lib/Activity/Avatar.js +2 -1
  6. package/lib/Activity/Bubble.d.ts +11 -0
  7. package/lib/Activity/Bubble.d.ts.map +1 -0
  8. package/lib/Activity/Bubble.js +2 -2
  9. package/lib/Activity/CarouselFilmStrip.js +20 -30
  10. package/lib/Activity/CarouselFilmStripAttachment.js +120 -0
  11. package/lib/Activity/CarouselLayout.js +5 -5
  12. package/lib/Activity/Speak.d.ts +10 -0
  13. package/lib/Activity/Speak.d.ts.map +1 -0
  14. package/lib/Activity/Speak.js +10 -12
  15. package/lib/Activity/StackedLayout.d.ts +18 -0
  16. package/lib/Activity/StackedLayout.d.ts.map +1 -0
  17. package/lib/Activity/StackedLayout.js +18 -14
  18. package/lib/Assets/TypingAnimation.js +2 -2
  19. package/lib/Attachment/Assets/DownloadIcon.js +3 -1
  20. package/lib/Attachment/AudioAttachment.js +2 -2
  21. package/lib/Attachment/AudioContent.d.ts +11 -0
  22. package/lib/Attachment/AudioContent.d.ts.map +1 -0
  23. package/lib/Attachment/AudioContent.js +4 -4
  24. package/lib/Attachment/FileContent.d.ts +10 -0
  25. package/lib/Attachment/FileContent.d.ts.map +1 -0
  26. package/lib/Attachment/FileContent.js +4 -9
  27. package/lib/Attachment/HTMLVideoContent.d.ts +11 -0
  28. package/lib/Attachment/HTMLVideoContent.d.ts.map +1 -0
  29. package/lib/Attachment/HTMLVideoContent.js +2 -2
  30. package/lib/Attachment/ImageContent.d.ts +8 -0
  31. package/lib/Attachment/ImageContent.d.ts.map +1 -0
  32. package/lib/Attachment/ImageContent.js +2 -2
  33. package/lib/Attachment/TextContent.d.ts +8 -0
  34. package/lib/Attachment/TextContent.d.ts.map +1 -0
  35. package/lib/Attachment/TextContent.js +4 -4
  36. package/lib/Attachment/VideoAttachment.js +2 -2
  37. package/lib/Attachment/VideoContent.d.ts +11 -0
  38. package/lib/Attachment/VideoContent.d.ts.map +1 -0
  39. package/lib/Attachment/VideoContent.js +1 -1
  40. package/lib/Attachment/VimeoContent.d.ts +10 -0
  41. package/lib/Attachment/VimeoContent.d.ts.map +1 -0
  42. package/lib/Attachment/VimeoContent.js +8 -8
  43. package/lib/Attachment/YouTubeContent.d.ts +10 -0
  44. package/lib/Attachment/YouTubeContent.d.ts.map +1 -0
  45. package/lib/Attachment/YouTubeContent.js +5 -5
  46. package/lib/Avatar/ImageAvatar.js +2 -2
  47. package/lib/Avatar/InitialsAvatar.js +2 -2
  48. package/lib/BasicConnectivityStatus.js +2 -2
  49. package/lib/BasicSendBox.d.ts +9 -0
  50. package/lib/BasicSendBox.d.ts.map +1 -0
  51. package/lib/BasicSendBox.js +6 -5
  52. package/lib/BasicToast.js +4 -4
  53. package/lib/BasicToaster.js +4 -4
  54. package/lib/BasicTranscript.js +143 -123
  55. package/lib/BasicTypingIndicator.d.ts +5 -0
  56. package/lib/BasicTypingIndicator.d.ts.map +1 -0
  57. package/lib/BasicTypingIndicator.js +2 -2
  58. package/lib/BasicWebChat.d.ts +9 -0
  59. package/lib/BasicWebChat.d.ts.map +1 -0
  60. package/lib/BasicWebChat.js +6 -4
  61. package/lib/Composer.d.ts +23 -0
  62. package/lib/Composer.d.ts.map +1 -0
  63. package/lib/Composer.js +33 -55
  64. package/lib/ConnectivityStatus/Assets/ErrorNotificationIcon.js +2 -2
  65. package/lib/ConnectivityStatus/Assets/SpinnerAnimation.js +2 -2
  66. package/lib/ConnectivityStatus/Assets/WarningNotificationIcon.js +2 -2
  67. package/lib/ConnectivityStatus/Connected.js +1 -1
  68. package/lib/ConnectivityStatus/Connecting.js +4 -4
  69. package/lib/ConnectivityStatus/FailedToConnect.js +2 -2
  70. package/lib/ConnectivityStatus/JavaScriptError.js +2 -2
  71. package/lib/Dictation.js +13 -4
  72. package/lib/ErrorBox.d.ts +8 -0
  73. package/lib/ErrorBox.d.ts.map +1 -0
  74. package/lib/ErrorBox.js +2 -2
  75. package/lib/Middleware/Activity/createCoreMiddleware.d.ts +3 -0
  76. package/lib/Middleware/Activity/createCoreMiddleware.d.ts.map +1 -0
  77. package/lib/Middleware/Activity/createCoreMiddleware.js +1 -1
  78. package/lib/Middleware/ActivityStatus/AbsoluteTime.js +1 -1
  79. package/lib/Middleware/ActivityStatus/RelativeTime.js +1 -1
  80. package/lib/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js +3 -3
  81. package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.d.ts +11 -0
  82. package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.d.ts.map +1 -0
  83. package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.js +4 -4
  84. package/lib/Middleware/ActivityStatus/Timestamp.d.ts +9 -0
  85. package/lib/Middleware/ActivityStatus/Timestamp.d.ts.map +1 -0
  86. package/lib/Middleware/ActivityStatus/Timestamp.js +2 -2
  87. package/lib/Middleware/ActivityStatus/createCoreMiddleware.d.ts +3 -0
  88. package/lib/Middleware/ActivityStatus/createCoreMiddleware.d.ts.map +1 -0
  89. package/lib/Middleware/ActivityStatus/createCoreMiddleware.js +1 -1
  90. package/lib/Middleware/ActivityStatus/createSendStatusMiddleware.js +5 -3
  91. package/lib/Middleware/ActivityStatus/createTimestampMiddleware.js +1 -1
  92. package/lib/Middleware/Attachment/createCoreMiddleware.d.ts +3 -0
  93. package/lib/Middleware/Attachment/createCoreMiddleware.d.ts.map +1 -0
  94. package/lib/Middleware/Attachment/createCoreMiddleware.js +9 -9
  95. package/lib/Middleware/AttachmentForScreenReader/AudioAttachment.js +1 -1
  96. package/lib/Middleware/AttachmentForScreenReader/FileAttachment.js +1 -1
  97. package/lib/Middleware/AttachmentForScreenReader/ImageAttachment.js +1 -1
  98. package/lib/Middleware/AttachmentForScreenReader/TextAttachment.js +1 -1
  99. package/lib/Middleware/AttachmentForScreenReader/VideoAttachment.js +1 -1
  100. package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.d.ts +3 -0
  101. package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.d.ts.map +1 -0
  102. package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.js +9 -5
  103. package/lib/Middleware/Avatar/createCoreMiddleware.d.ts +11 -0
  104. package/lib/Middleware/Avatar/createCoreMiddleware.d.ts.map +1 -0
  105. package/lib/Middleware/Avatar/createCoreMiddleware.js +2 -2
  106. package/lib/Middleware/CardAction/createCoreMiddleware.js +2 -2
  107. package/lib/Middleware/GroupActivities/createCoreMiddleware.js +1 -1
  108. package/lib/Middleware/ScrollToEndButton/ScrollToEndButton.js +71 -0
  109. package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.d.ts +3 -0
  110. package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.d.ts.map +1 -0
  111. package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.js +27 -0
  112. package/lib/Middleware/Toast/createCoreMiddleware.d.ts +4 -0
  113. package/lib/Middleware/Toast/createCoreMiddleware.d.ts.map +1 -0
  114. package/lib/Middleware/Toast/createCoreMiddleware.js +1 -1
  115. package/lib/Middleware/TypingIndicator/createCoreMiddleware.d.ts +3 -0
  116. package/lib/Middleware/TypingIndicator/createCoreMiddleware.d.ts.map +1 -0
  117. package/lib/Middleware/TypingIndicator/createCoreMiddleware.js +3 -2
  118. package/lib/ReactWebChat.d.ts +10 -0
  119. package/lib/ReactWebChat.d.ts.map +1 -0
  120. package/lib/ReactWebChat.js +19 -7
  121. package/lib/ScreenReaderActivity.js +64 -45
  122. package/lib/SendBox/Assets/AttachmentIcon.js +3 -1
  123. package/lib/SendBox/Assets/MicrophoneIcon.js +3 -1
  124. package/lib/SendBox/Assets/SendIcon.js +2 -2
  125. package/lib/SendBox/AutoResizeTextArea.d.ts +23 -0
  126. package/lib/SendBox/AutoResizeTextArea.d.ts.map +1 -0
  127. package/lib/SendBox/AutoResizeTextArea.js +6 -6
  128. package/lib/SendBox/DictationInterims.d.ts +9 -0
  129. package/lib/SendBox/DictationInterims.d.ts.map +1 -0
  130. package/lib/SendBox/DictationInterims.js +2 -2
  131. package/lib/SendBox/IconButton.js +2 -2
  132. package/lib/SendBox/MicrophoneButton.d.ts +11 -0
  133. package/lib/SendBox/MicrophoneButton.d.ts.map +1 -0
  134. package/lib/SendBox/MicrophoneButton.js +25 -24
  135. package/lib/SendBox/SendButton.d.ts +9 -0
  136. package/lib/SendBox/SendButton.d.ts.map +1 -0
  137. package/lib/SendBox/SendButton.js +7 -5
  138. package/lib/SendBox/SuggestedAction.js +5 -9
  139. package/lib/SendBox/SuggestedActions.d.ts +5 -0
  140. package/lib/SendBox/SuggestedActions.d.ts.map +1 -0
  141. package/lib/SendBox/SuggestedActions.js +10 -7
  142. package/lib/SendBox/TextBox.d.ts +28 -0
  143. package/lib/SendBox/TextBox.d.ts.map +1 -0
  144. package/lib/SendBox/TextBox.js +12 -7
  145. package/lib/SendBox/UploadButton.d.ts +9 -0
  146. package/lib/SendBox/UploadButton.d.ts.map +1 -0
  147. package/lib/SendBox/UploadButton.js +5 -5
  148. package/lib/Styles/StyleSet/Activities.d.ts +5 -0
  149. package/lib/Styles/StyleSet/Activities.d.ts.map +1 -0
  150. package/lib/Styles/StyleSet/AudioAttachment.d.ts +6 -0
  151. package/lib/Styles/StyleSet/AudioAttachment.d.ts.map +1 -0
  152. package/lib/Styles/StyleSet/AudioContent.d.ts +4 -0
  153. package/lib/Styles/StyleSet/AudioContent.d.ts.map +1 -0
  154. package/lib/Styles/StyleSet/AutoResizeTextArea.d.ts +37 -0
  155. package/lib/Styles/StyleSet/AutoResizeTextArea.d.ts.map +1 -0
  156. package/lib/Styles/StyleSet/Avatar.d.ts +9 -0
  157. package/lib/Styles/StyleSet/Avatar.d.ts.map +1 -0
  158. package/lib/Styles/StyleSet/BasicTranscript.d.ts +77 -0
  159. package/lib/Styles/StyleSet/BasicTranscript.d.ts.map +1 -0
  160. package/lib/Styles/StyleSet/Bubble.d.ts +5 -0
  161. package/lib/Styles/StyleSet/Bubble.d.ts.map +1 -0
  162. package/lib/Styles/StyleSet/Bubble.js +1 -1
  163. package/lib/Styles/StyleSet/CarouselFilmStrip.d.ts +5 -0
  164. package/lib/Styles/StyleSet/CarouselFilmStrip.d.ts.map +1 -0
  165. package/lib/Styles/StyleSet/CarouselFilmStrip.js +2 -18
  166. package/lib/Styles/StyleSet/CarouselFilmStripAttachment.d.ts +3 -0
  167. package/lib/Styles/StyleSet/CarouselFilmStripAttachment.d.ts.map +1 -0
  168. package/lib/Styles/StyleSet/CarouselFilmStripAttachment.js +63 -0
  169. package/lib/Styles/StyleSet/CarouselFlipper.d.ts +27 -0
  170. package/lib/Styles/StyleSet/CarouselFlipper.d.ts.map +1 -0
  171. package/lib/Styles/StyleSet/ConnectivityNotification.d.ts +13 -0
  172. package/lib/Styles/StyleSet/ConnectivityNotification.d.ts.map +1 -0
  173. package/lib/Styles/StyleSet/DictationInterims.d.ts +13 -0
  174. package/lib/Styles/StyleSet/DictationInterims.d.ts.map +1 -0
  175. package/lib/Styles/StyleSet/ErrorBox.d.ts +33 -0
  176. package/lib/Styles/StyleSet/ErrorBox.d.ts.map +1 -0
  177. package/lib/Styles/StyleSet/ErrorNotification.d.ts +23 -0
  178. package/lib/Styles/StyleSet/ErrorNotification.d.ts.map +1 -0
  179. package/lib/Styles/StyleSet/FileContent.d.ts +32 -0
  180. package/lib/Styles/StyleSet/FileContent.d.ts.map +1 -0
  181. package/lib/Styles/StyleSet/ImageAvatar.d.ts +7 -0
  182. package/lib/Styles/StyleSet/ImageAvatar.d.ts.map +1 -0
  183. package/lib/Styles/StyleSet/InitialsAvatar.d.ts +19 -0
  184. package/lib/Styles/StyleSet/InitialsAvatar.d.ts.map +1 -0
  185. package/lib/Styles/StyleSet/MicrophoneButton.d.ts +13 -0
  186. package/lib/Styles/StyleSet/MicrophoneButton.d.ts.map +1 -0
  187. package/lib/Styles/StyleSet/Root.d.ts +8 -0
  188. package/lib/Styles/StyleSet/Root.d.ts.map +1 -0
  189. package/lib/Styles/StyleSet/ScrollToEndButton.d.ts +36 -0
  190. package/lib/Styles/StyleSet/ScrollToEndButton.d.ts.map +1 -0
  191. package/lib/Styles/StyleSet/ScrollToEndButton.js +36 -34
  192. package/lib/Styles/StyleSet/SendBox.d.ts +24 -0
  193. package/lib/Styles/StyleSet/SendBox.d.ts.map +1 -0
  194. package/lib/Styles/StyleSet/SendBoxButton.d.ts +33 -0
  195. package/lib/Styles/StyleSet/SendBoxButton.d.ts.map +1 -0
  196. package/lib/Styles/StyleSet/SendBoxTextBox.d.ts +41 -0
  197. package/lib/Styles/StyleSet/SendBoxTextBox.d.ts.map +1 -0
  198. package/lib/Styles/StyleSet/SendStatus.d.ts +8 -0
  199. package/lib/Styles/StyleSet/SendStatus.d.ts.map +1 -0
  200. package/lib/Styles/StyleSet/SingleAttachmentActivity.d.ts +11 -0
  201. package/lib/Styles/StyleSet/SingleAttachmentActivity.d.ts.map +1 -0
  202. package/lib/Styles/StyleSet/SpinnerAnimation.d.ts +15 -0
  203. package/lib/Styles/StyleSet/SpinnerAnimation.d.ts.map +1 -0
  204. package/lib/Styles/StyleSet/StackedLayout.d.ts +63 -0
  205. package/lib/Styles/StyleSet/StackedLayout.d.ts.map +1 -0
  206. package/lib/Styles/StyleSet/SuggestedAction.d.ts +49 -0
  207. package/lib/Styles/StyleSet/SuggestedAction.d.ts.map +1 -0
  208. package/lib/Styles/StyleSet/SuggestedAction.js +2 -2
  209. package/lib/Styles/StyleSet/SuggestedActions.d.ts +118 -0
  210. package/lib/Styles/StyleSet/SuggestedActions.d.ts.map +1 -0
  211. package/lib/Styles/StyleSet/TextContent.d.ts +28 -0
  212. package/lib/Styles/StyleSet/TextContent.d.ts.map +1 -0
  213. package/lib/Styles/StyleSet/Toast.d.ts +65 -0
  214. package/lib/Styles/StyleSet/Toast.d.ts.map +1 -0
  215. package/lib/Styles/StyleSet/Toaster.d.ts +111 -0
  216. package/lib/Styles/StyleSet/Toaster.d.ts.map +1 -0
  217. package/lib/Styles/StyleSet/TypingAnimation.d.ts +8 -0
  218. package/lib/Styles/StyleSet/TypingAnimation.d.ts.map +1 -0
  219. package/lib/Styles/StyleSet/TypingIndicator.d.ts +11 -0
  220. package/lib/Styles/StyleSet/TypingIndicator.d.ts.map +1 -0
  221. package/lib/Styles/StyleSet/UploadButton.d.ts +14 -0
  222. package/lib/Styles/StyleSet/UploadButton.d.ts.map +1 -0
  223. package/lib/Styles/StyleSet/VideoAttachment.d.ts +2 -0
  224. package/lib/Styles/StyleSet/VideoAttachment.d.ts.map +1 -0
  225. package/lib/Styles/StyleSet/VideoContent.d.ts +6 -0
  226. package/lib/Styles/StyleSet/VideoContent.d.ts.map +1 -0
  227. package/lib/Styles/StyleSet/VimeoContent.d.ts +7 -0
  228. package/lib/Styles/StyleSet/VimeoContent.d.ts.map +1 -0
  229. package/lib/Styles/StyleSet/WarningNotification.d.ts +22 -0
  230. package/lib/Styles/StyleSet/WarningNotification.d.ts.map +1 -0
  231. package/lib/Styles/StyleSet/YouTubeContent.d.ts +7 -0
  232. package/lib/Styles/StyleSet/YouTubeContent.d.ts.map +1 -0
  233. package/lib/Styles/createStyleSet.d.ts +1103 -0
  234. package/lib/Styles/createStyleSet.d.ts.map +1 -0
  235. package/lib/Styles/createStyleSet.js +44 -41
  236. package/lib/Styles/mirrorStyle.js +2 -2
  237. package/lib/Toast/CollapseIcon.js +3 -1
  238. package/lib/Toast/DismissIcon.js +3 -1
  239. package/lib/Toast/ExpandIcon.js +3 -1
  240. package/lib/Toast/NotificationIcon.js +1 -1
  241. package/lib/Toast/createToastMiddleware.d.ts +4 -0
  242. package/lib/Toast/createToastMiddleware.d.ts.map +1 -0
  243. package/lib/Toast/createToastMiddleware.js +2 -2
  244. package/lib/Utils/AccessKeySink/Surface.js +7 -5
  245. package/lib/Utils/AccessibleButton.js +6 -4
  246. package/lib/Utils/AccessibleInputText.d.ts +21 -0
  247. package/lib/Utils/AccessibleInputText.d.ts.map +1 -0
  248. package/lib/Utils/AccessibleInputText.js +29 -25
  249. package/lib/Utils/AccessibleTextArea.d.ts +20 -0
  250. package/lib/Utils/AccessibleTextArea.d.ts.map +1 -0
  251. package/lib/Utils/AccessibleTextArea.js +35 -24
  252. package/lib/Utils/CroppedImage.js +2 -2
  253. package/lib/Utils/Fade.js +2 -2
  254. package/lib/Utils/FocusRedirector.js +3 -3
  255. package/lib/Utils/InlineMarkdown.js +6 -6
  256. package/lib/Utils/TypeFocusSink/FocusBox.js +6 -4
  257. package/lib/Utils/TypeFocusSink/getTabIndex.d.ts +2 -0
  258. package/lib/Utils/TypeFocusSink/getTabIndex.d.ts.map +1 -0
  259. package/lib/Utils/TypeFocusSink/getTabIndex.js +1 -1
  260. package/lib/Utils/TypeFocusSink/navigableEvent.js +1 -1
  261. package/lib/Utils/activityAltText.js +100 -0
  262. package/lib/Utils/addTargetBlankToHyperlinksMarkdown.js +1 -1
  263. package/lib/Utils/createCustomEvent.js +1 -1
  264. package/lib/Utils/debounce.js +1 -1
  265. package/lib/Utils/detectBrowser.js +1 -1
  266. package/lib/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.js +2 -2
  267. package/lib/Utils/downscaleImageToDataURL/index.js +2 -2
  268. package/lib/Utils/filterMap.js +1 -1
  269. package/lib/Utils/findLastIndex.js +2 -2
  270. package/lib/Utils/mapMap.js +1 -1
  271. package/lib/Utils/readDataURIToBlob.js +2 -2
  272. package/lib/Utils/singleToArray.js +1 -1
  273. package/lib/connectToWebChat.js +5 -3
  274. package/lib/hooks/index.d.ts +21 -0
  275. package/lib/hooks/index.d.ts.map +1 -0
  276. package/lib/hooks/index.js +1 -1
  277. package/lib/hooks/internal/BypassSpeechSynthesisPonyfill.js +97 -39
  278. package/lib/hooks/internal/UITracker.js +2 -2
  279. package/lib/hooks/internal/useAcknowledgedActivity.js +2 -2
  280. package/lib/hooks/internal/useDispatchScrollPosition.js +1 -1
  281. package/lib/hooks/internal/useDispatchTranscriptFocus.js +1 -1
  282. package/lib/hooks/internal/useEnterKeyHint.js +1 -1
  283. package/lib/hooks/internal/useForceRender.js +2 -2
  284. package/lib/hooks/internal/useForceRenderAtInterval.js +2 -2
  285. package/lib/hooks/internal/useInternalRenderMarkdownInline.js +1 -1
  286. package/lib/hooks/internal/useLocalizeAccessKey.js +2 -2
  287. package/lib/hooks/internal/useMemoize.js +2 -2
  288. package/lib/hooks/internal/useNavigatorPlatform.js +1 -1
  289. package/lib/hooks/internal/useNonce.js +1 -1
  290. package/lib/hooks/internal/useRegisterFocusSendBox.js +1 -1
  291. package/lib/hooks/internal/useRegisterFocusTranscript.js +1 -1
  292. package/lib/hooks/internal/useRegisterScrollRelative.js +1 -1
  293. package/lib/hooks/internal/useRegisterScrollTo.js +1 -1
  294. package/lib/hooks/internal/useRegisterScrollToEnd.js +1 -1
  295. package/lib/hooks/internal/useReplaceEmoticon.js +2 -2
  296. package/lib/hooks/internal/useResumeAudioContext.js +33 -0
  297. package/lib/hooks/internal/useScrollRelative.js +1 -1
  298. package/lib/hooks/internal/useSettableDictateAbortable.js +1 -1
  299. package/lib/hooks/internal/useSuggestedActionsAccessKey.js +1 -1
  300. package/lib/hooks/internal/useUniqueId.d.ts +2 -0
  301. package/lib/hooks/internal/useUniqueId.d.ts.map +1 -0
  302. package/lib/hooks/internal/useUniqueId.js +1 -1
  303. package/lib/hooks/useDictateAbortable.d.ts +2 -0
  304. package/lib/hooks/useDictateAbortable.d.ts.map +1 -0
  305. package/lib/hooks/useDictateAbortable.js +2 -2
  306. package/lib/hooks/useFocus.d.ts +2 -0
  307. package/lib/hooks/useFocus.d.ts.map +1 -0
  308. package/lib/hooks/useFocus.js +1 -1
  309. package/lib/hooks/useFocusSendBox.d.ts +3 -0
  310. package/lib/hooks/useFocusSendBox.d.ts.map +1 -0
  311. package/lib/hooks/useFocusSendBox.js +2 -1
  312. package/lib/hooks/useObserveScrollPosition.d.ts +3 -0
  313. package/lib/hooks/useObserveScrollPosition.d.ts.map +1 -0
  314. package/lib/hooks/useObserveScrollPosition.js +2 -2
  315. package/lib/hooks/useObserveTranscriptFocus.d.ts +5 -0
  316. package/lib/hooks/useObserveTranscriptFocus.d.ts.map +1 -0
  317. package/lib/hooks/useObserveTranscriptFocus.js +2 -2
  318. package/lib/hooks/useRenderMarkdownAsHTML.d.ts +5 -0
  319. package/lib/hooks/useRenderMarkdownAsHTML.d.ts.map +1 -0
  320. package/lib/hooks/useRenderMarkdownAsHTML.js +2 -2
  321. package/lib/hooks/useScrollDown.d.ts +4 -0
  322. package/lib/hooks/useScrollDown.d.ts.map +1 -0
  323. package/lib/hooks/useScrollDown.js +1 -1
  324. package/lib/hooks/useScrollTo.d.ts +5 -0
  325. package/lib/hooks/useScrollTo.d.ts.map +1 -0
  326. package/lib/hooks/useScrollTo.js +1 -1
  327. package/lib/hooks/useScrollToEnd.d.ts +2 -0
  328. package/lib/hooks/useScrollToEnd.d.ts.map +1 -0
  329. package/lib/hooks/useScrollToEnd.js +1 -1
  330. package/lib/hooks/useScrollUp.d.ts +4 -0
  331. package/lib/hooks/useScrollUp.d.ts.map +1 -0
  332. package/lib/hooks/useScrollUp.js +1 -1
  333. package/lib/hooks/useSendFiles.d.ts +2 -0
  334. package/lib/hooks/useSendFiles.d.ts.map +1 -0
  335. package/lib/hooks/useSendFiles.js +3 -3
  336. package/lib/hooks/useStyleSet.d.ts +2 -0
  337. package/lib/hooks/useStyleSet.d.ts.map +1 -0
  338. package/lib/hooks/useStyleSet.js +1 -1
  339. package/lib/hooks/useWebSpeechPonyfill.d.ts +3 -0
  340. package/lib/hooks/useWebSpeechPonyfill.d.ts.map +1 -0
  341. package/lib/hooks/useWebSpeechPonyfill.js +1 -1
  342. package/lib/index.d.ts +209 -22
  343. package/lib/index.d.ts.map +1 -1
  344. package/lib/index.js +19 -19
  345. package/lib/tsconfig.json +1 -1
  346. package/lib/types/ScrollPosition.d.ts +6 -0
  347. package/lib/types/ScrollPosition.d.ts.map +1 -0
  348. package/lib/types/ScrollPosition.js +2 -0
  349. package/package.json +38 -38
  350. package/src/Activity/{Avatar.js → Avatar.tsx} +9 -2
  351. package/src/Activity/{Bubble.js → Bubble.tsx} +10 -2
  352. package/src/Activity/CarouselFilmStrip.js +20 -29
  353. package/src/Activity/CarouselFilmStripAttachment.js +92 -0
  354. package/src/Activity/{Speak.js → Speak.tsx} +12 -5
  355. package/src/Activity/{StackedLayout.js → StackedLayout.tsx} +36 -11
  356. package/src/Attachment/Assets/DownloadIcon.js +8 -1
  357. package/src/Attachment/{AudioContent.js → AudioContent.tsx} +12 -3
  358. package/src/Attachment/{FileContent.js → FileContent.tsx} +10 -7
  359. package/src/Attachment/{HTMLVideoContent.js → HTMLVideoContent.tsx} +10 -2
  360. package/src/Attachment/{ImageContent.js → ImageContent.tsx} +7 -2
  361. package/src/Attachment/{TextContent.js → TextContent.tsx} +14 -7
  362. package/src/Attachment/{VideoContent.js → VideoContent.tsx} +10 -2
  363. package/src/Attachment/{VimeoContent.js → VimeoContent.tsx} +15 -8
  364. package/src/Attachment/{YouTubeContent.js → YouTubeContent.tsx} +12 -5
  365. package/src/{BasicSendBox.js → BasicSendBox.tsx} +9 -5
  366. package/src/BasicToaster.js +4 -4
  367. package/src/BasicTranscript.js +114 -98
  368. package/src/{BasicTypingIndicator.js → BasicTypingIndicator.tsx} +1 -1
  369. package/src/{BasicWebChat.js → BasicWebChat.tsx} +13 -4
  370. package/src/{Composer.js → Composer.tsx} +41 -42
  371. package/src/Dictation.js +13 -4
  372. package/src/{ErrorBox.js → ErrorBox.tsx} +7 -2
  373. package/src/Middleware/Activity/{createCoreMiddleware.js → createCoreMiddleware.tsx} +2 -1
  374. package/src/Middleware/ActivityStatus/SendStatus/{SendStatus.js → SendStatus.tsx} +8 -3
  375. package/src/Middleware/ActivityStatus/{Timestamp.js → Timestamp.tsx} +8 -2
  376. package/src/Middleware/ActivityStatus/{createCoreMiddleware.js → createCoreMiddleware.tsx} +3 -1
  377. package/src/Middleware/ActivityStatus/createSendStatusMiddleware.js +8 -6
  378. package/src/Middleware/ActivityStatus/createTimestampMiddleware.js +10 -8
  379. package/src/Middleware/Attachment/{createCoreMiddleware.js → createCoreMiddleware.tsx} +8 -7
  380. package/src/Middleware/AttachmentForScreenReader/{createCoreMiddleware.js → createCoreMiddleware.tsx} +4 -3
  381. package/src/Middleware/Avatar/{createCoreMiddleware.js → createCoreMiddleware.tsx} +10 -3
  382. package/src/Middleware/CardAction/createCoreMiddleware.js +43 -41
  383. package/src/Middleware/GroupActivities/createCoreMiddleware.js +6 -4
  384. package/src/Middleware/ScrollToEndButton/ScrollToEndButton.js +45 -0
  385. package/src/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.ts +17 -0
  386. package/src/Middleware/Toast/{createCoreMiddleware.js → createCoreMiddleware.tsx} +3 -1
  387. package/src/Middleware/TypingIndicator/{createCoreMiddleware.js → createCoreMiddleware.tsx} +3 -4
  388. package/src/{ReactWebChat.js → ReactWebChat.tsx} +25 -7
  389. package/src/ScreenReaderActivity.js +47 -37
  390. package/src/SendBox/Assets/AttachmentIcon.js +1 -1
  391. package/src/SendBox/Assets/MicrophoneIcon.js +1 -1
  392. package/src/SendBox/{AutoResizeTextArea.js → AutoResizeTextArea.tsx} +30 -4
  393. package/src/SendBox/{DictationInterims.js → DictationInterims.tsx} +6 -2
  394. package/src/SendBox/{MicrophoneButton.js → MicrophoneButton.tsx} +35 -25
  395. package/src/SendBox/{SendButton.js → SendButton.tsx} +8 -3
  396. package/src/SendBox/SuggestedAction.js +1 -15
  397. package/src/SendBox/{SuggestedActions.js → SuggestedActions.tsx} +42 -21
  398. package/src/SendBox/{TextBox.js → TextBox.tsx} +21 -7
  399. package/src/SendBox/{UploadButton.js → UploadButton.tsx} +7 -3
  400. package/src/Styles/StyleSet/CarouselFilmStrip.ts +0 -20
  401. package/src/Styles/StyleSet/CarouselFilmStripAttachment.ts +56 -0
  402. package/src/Styles/StyleSet/ScrollToEndButton.ts +33 -31
  403. package/src/Styles/StyleSet/SuggestedAction.ts +1 -1
  404. package/src/Styles/createStyleSet.ts +41 -39
  405. package/src/Toast/CollapseIcon.js +9 -1
  406. package/src/Toast/DismissIcon.js +9 -1
  407. package/src/Toast/ExpandIcon.js +9 -1
  408. package/src/Toast/{createToastMiddleware.js → createToastMiddleware.tsx} +3 -2
  409. package/src/Utils/{AccessibleInputText.js → AccessibleInputText.tsx} +48 -5
  410. package/src/Utils/{AccessibleTextArea.js → AccessibleTextArea.tsx} +67 -6
  411. package/src/Utils/TypeFocusSink/FocusBox.js +4 -4
  412. package/src/Utils/TypeFocusSink/getTabIndex.ts +1 -1
  413. package/src/Utils/activityAltText.ts +135 -0
  414. package/src/Utils/findLastIndex.spec.js +2 -0
  415. package/src/Utils/intersectionOf.spec.js +2 -0
  416. package/src/Utils/mapMap.spec.js +2 -0
  417. package/src/Utils/removeInline.spec.js +2 -0
  418. package/src/Utils/{singleToArray.js → singleToArray.ts} +1 -1
  419. package/src/Utils/walkMarkdownTokens.spec.js +3 -3
  420. package/src/hooks/{index.js → index.ts} +1 -0
  421. package/src/hooks/internal/BypassSpeechSynthesisPonyfill.js +68 -17
  422. package/src/hooks/internal/useMemoize.spec.js +2 -0
  423. package/src/hooks/internal/useResumeAudioContext.ts +7 -0
  424. package/src/hooks/internal/useScrollRelative.js +4 -3
  425. package/src/hooks/internal/{useUniqueId.js → useUniqueId.ts} +1 -1
  426. package/src/hooks/{useDictateAbortable.js → useDictateAbortable.ts} +1 -1
  427. package/src/hooks/{useFocus.js → useFocus.ts} +1 -1
  428. package/src/hooks/{useFocusSendBox.js → useFocusSendBox.ts} +2 -1
  429. package/src/hooks/{useObserveScrollPosition.js → useObserveScrollPosition.ts} +6 -1
  430. package/src/hooks/{useObserveTranscriptFocus.js → useObserveTranscriptFocus.ts} +6 -1
  431. package/src/hooks/{useRenderMarkdownAsHTML.js → useRenderMarkdownAsHTML.ts} +6 -2
  432. package/src/hooks/{useScrollDown.js → useScrollDown.ts} +1 -1
  433. package/src/hooks/{useScrollTo.js → useScrollTo.ts} +5 -1
  434. package/src/hooks/{useScrollToEnd.js → useScrollToEnd.ts} +1 -1
  435. package/src/hooks/{useScrollUp.js → useScrollUp.ts} +1 -1
  436. package/src/hooks/{useSendFiles.js → useSendFiles.ts} +3 -2
  437. package/src/hooks/{useStyleSet.js → useStyleSet.ts} +1 -1
  438. package/src/hooks/useWebSpeechPonyfill.ts +7 -0
  439. package/src/index.ts +7 -11
  440. package/src/tsconfig.json +1 -1
  441. package/src/types/ScrollPosition.ts +6 -0
  442. package/lib/Activity/ScrollToEndButton.js +0 -81
  443. package/lib/Attachment/Assets/ErrorIcon.js +0 -22
  444. package/lib/Utils/remarkStripMarkdown.js +0 -26
  445. package/lib/hooks/internal/useStripMarkdown.js +0 -19
  446. package/src/Activity/ScrollToEndButton.js +0 -58
  447. package/src/Attachment/Assets/ErrorIcon.js +0 -9
  448. package/src/Utils/remarkStripMarkdown.js +0 -13
  449. package/src/hooks/internal/useStripMarkdown.js +0 -7
  450. package/src/hooks/useWebSpeechPonyfill.js +0 -5
  451. package/src/index.tsx +0 -35
@@ -2,7 +2,7 @@ import { Constants } from 'botframework-webchat-core';
2
2
  import { hooks } from 'botframework-webchat-api';
3
3
  import classNames from 'classnames';
4
4
  import PropTypes from 'prop-types';
5
- import React from 'react';
5
+ import React, { FC } from 'react';
6
6
 
7
7
  import DictationInterims from './SendBox/DictationInterims';
8
8
  import MicrophoneButton from './SendBox/MicrophoneButton';
@@ -31,11 +31,11 @@ const ROOT_STYLE = {
31
31
  };
32
32
 
33
33
  // TODO: [P3] We should consider exposing core/src/definitions and use it instead
34
- function activityIsSpeakingOrQueuedToSpeak({ channelData: { speak } = {} }) {
34
+ function activityIsSpeakingOrQueuedToSpeak({ channelData: { speak } = {} }: { channelData: { speak?: any } }) {
35
35
  return !!speak;
36
36
  }
37
37
 
38
- function useSendBoxSpeechInterimsVisible() {
38
+ function useSendBoxSpeechInterimsVisible(): [boolean] {
39
39
  const [activities] = useActivities();
40
40
  const [dictateState] = useDictateState();
41
41
 
@@ -45,10 +45,14 @@ function useSendBoxSpeechInterimsVisible() {
45
45
  ];
46
46
  }
47
47
 
48
- const BasicSendBox = ({ className }) => {
48
+ type BasicSendBoxProps = {
49
+ className?: string;
50
+ };
51
+
52
+ const BasicSendBox: FC<BasicSendBoxProps> = ({ className }) => {
49
53
  const [{ hideUploadButton, sendBoxButtonAlignment }] = useStyleOptions();
50
54
  const [{ sendBox: sendBoxStyleSet }] = useStyleSet();
51
- const [{ SpeechRecognition } = {}] = useWebSpeechPonyfill();
55
+ const [{ SpeechRecognition = undefined } = {}] = useWebSpeechPonyfill();
52
56
  const [direction] = useDirection();
53
57
  const [speechInterimsVisible] = useSendBoxSpeechInterimsVisible();
54
58
  const styleToEmotionObject = useStyleToEmotionObject();
@@ -94,10 +94,10 @@ const BasicToaster = () => {
94
94
  () => (!expandable || expanded ? `webchat__toaster__list__${instanceId}` : undefined),
95
95
  [expandable, expanded, instanceId]
96
96
  );
97
- const headerElementId = useMemo(() => (expandable ? `webchat__toaster__header__${instanceId}` : undefined), [
98
- expandable,
99
- instanceId
100
- ]);
97
+ const headerElementId = useMemo(
98
+ () => (expandable ? `webchat__toaster__header__${instanceId}` : undefined),
99
+ [expandable, instanceId]
100
+ );
101
101
 
102
102
  useEffect(() => {
103
103
  !expandable && setExpanded(false);
@@ -5,6 +5,7 @@ import {
5
5
  Composer as ReactScrollToBottomComposer,
6
6
  Panel as ReactScrollToBottomPanel,
7
7
  useAnimatingToEnd,
8
+ useAtEnd,
8
9
  useObserveScrollPosition,
9
10
  useScrollTo,
10
11
  useScrollToEnd,
@@ -26,7 +27,6 @@ import isZeroOrPositive from './Utils/isZeroOrPositive';
26
27
  import removeInline from './Utils/removeInline';
27
28
  import ScreenReaderActivity from './ScreenReaderActivity';
28
29
  import ScreenReaderText from './ScreenReaderText';
29
- import ScrollToEndButton from './Activity/ScrollToEndButton';
30
30
  import SpeakActivity from './Activity/Speak';
31
31
  import tabbableElements from './Utils/tabbableElements';
32
32
  import useAcknowledgedActivity from './hooks/internal/useAcknowledgedActivity';
@@ -47,6 +47,7 @@ const {
47
47
  useCreateActivityRenderer,
48
48
  useCreateActivityStatusRenderer,
49
49
  useCreateAvatarRenderer,
50
+ useCreateScrollToEndButtonRenderer,
50
51
  useDirection,
51
52
  useGroupActivities,
52
53
  useLocalizer,
@@ -86,9 +87,8 @@ function validateAllActivitiesTagged(activities, bins) {
86
87
 
87
88
  const InternalTranscript = ({ activityElementsRef, className }) => {
88
89
  const [{ basicTranscript: basicTranscriptStyleSet }] = useStyleSet();
89
- const [
90
- { bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, internalLiveRegionFadeAfter, showAvatarInGroup }
91
- ] = useStyleOptions();
90
+ const [{ bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, internalLiveRegionFadeAfter, showAvatarInGroup }] =
91
+ useStyleOptions();
92
92
  const [focusedActivityKey, setFocusedActivityKey] = useState();
93
93
  const [activities] = useActivities();
94
94
  const [direction] = useDirection();
@@ -150,9 +150,10 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
150
150
  [activities]
151
151
  );
152
152
 
153
- const visibleActivities = useMemo(() => activitiesWithRenderer.map(({ activity }) => activity), [
154
- activitiesWithRenderer
155
- ]);
153
+ const visibleActivities = useMemo(
154
+ () => activitiesWithRenderer.map(({ activity }) => activity),
155
+ [activitiesWithRenderer]
156
+ );
156
157
 
157
158
  // Tag activities based on types.
158
159
  // The default implementation tag into 2 types: sender and status.
@@ -255,10 +256,16 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
255
256
 
256
257
  const { renderActivity } = activitiesWithRenderer.find(entry => entry.activity === activity);
257
258
  const key = getActivityUniqueId(activity) || renderingElements.length;
259
+ const baseAltText =
260
+ typeof activity?.channelData?.['webchat:fallback-text'] === 'string'
261
+ ? activity?.channelData?.['webchat:fallback-text']
262
+ : activity?.channelData?.messageBack?.displayText || activity.text;
263
+
264
+ // If "webchat:fallback-text" field is set to empty string, the activity must not be narrated.
265
+ const supportScreenReader = activity?.channelData?.['webchat:fallback-text'] !== '';
266
+
258
267
  const {
259
- channelData: { messageBack: { displayText: messageBackDisplayText } = {} } = {},
260
- from: { role },
261
- text
268
+ from: { role }
262
269
  } = activity;
263
270
 
264
271
  const topSideNub = role === 'user' ? topSideUserNub : topSideBotNub;
@@ -342,8 +349,8 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
342
349
  hideAllTimestamps || indexWithinSenderAndStatusGroup !== activitiesWithSameSenderAndStatus.length - 1,
343
350
  key,
344
351
 
345
- // When "liveRegionKey" changes, it will show up in the live region momentarily.
346
- liveRegionKey: key + '|' + (messageBackDisplayText || text),
352
+ // When "liveRegionKey" changes or contents that made up the alt text changed, it will show up in the live region momentarily.
353
+ liveRegionKey: key + '|' + baseAltText,
347
354
  renderActivity,
348
355
  renderActivityStatus,
349
356
  renderAvatar,
@@ -351,7 +358,8 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
351
358
 
352
359
  // TODO: [P2] #2858 We should use core/definitions/speakingActivity for this predicate instead
353
360
  shouldSpeak: activity.channelData && activity.channelData.speak,
354
- showCallout
361
+ showCallout,
362
+ supportScreenReader
355
363
  });
356
364
  });
357
365
  });
@@ -440,6 +448,8 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
440
448
  [activityElementsRef, rootElementRef, scrollToBottomScrollTo]
441
449
  );
442
450
 
451
+ const scrollToEnd = useCallback(() => scrollToBottomScrollToEnd({ behavior: 'smooth' }), [scrollToBottomScrollToEnd]);
452
+
443
453
  const scrollRelative = useCallback(
444
454
  (direction, { displacement } = {}) => {
445
455
  const { current: rootElement } = rootElementRef;
@@ -470,7 +480,7 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
470
480
  // Since there could be multiple instances of <BasicTranscript> inside the <Composer>, when the developer calls `scrollXXX`, we need to call it on all instances.
471
481
  // We call `useRegisterScrollXXX` to register a callback function, the `useScrollXXX` will multiplex the call into each instance of <BasicTranscript>.
472
482
  useRegisterScrollTo(scrollTo);
473
- useRegisterScrollToEnd(scrollToBottomScrollToEnd);
483
+ useRegisterScrollToEnd(scrollToEnd);
474
484
  useRegisterScrollRelative(scrollRelative);
475
485
 
476
486
  const dispatchScrollPosition = useDispatchScrollPosition();
@@ -691,9 +701,10 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
691
701
  [focus]
692
702
  );
693
703
 
694
- const focusTranscriptCallback = useCallback(() => rootElementRef.current && rootElementRef.current.focus(), [
695
- rootElementRef
696
- ]);
704
+ const focusTranscriptCallback = useCallback(
705
+ () => rootElementRef.current && rootElementRef.current.focus(),
706
+ [rootElementRef]
707
+ );
697
708
 
698
709
  useRegisterFocusTranscript(focusTranscriptCallback);
699
710
 
@@ -713,10 +724,10 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
713
724
  return activity;
714
725
  }, [focusedActivityKey, renderingElements]);
715
726
 
716
- useMemo(() => dispatchTranscriptFocus && dispatchTranscriptFocus({ activity: focusedActivity }), [
717
- dispatchTranscriptFocus,
718
- focusedActivity
719
- ]);
727
+ useMemo(
728
+ () => dispatchTranscriptFocus && dispatchTranscriptFocus({ activity: focusedActivity }),
729
+ [dispatchTranscriptFocus, focusedActivity]
730
+ );
720
731
 
721
732
  // This is required by IE11.
722
733
  // When the user clicks on and empty space (a.k.a. filler) in an empty transcript, IE11 says the focus is on the <div className="filler">,
@@ -760,11 +771,13 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
760
771
  aria-roledescription={transcriptRoleDescription}
761
772
  role="log"
762
773
  >
763
- {renderingElements.map(({ activity, liveRegionKey }) => (
764
- <Fade fadeAfter={internalLiveRegionFadeAfter} key={liveRegionKey}>
765
- {() => <ScreenReaderActivity activity={activity} />}
766
- </Fade>
767
- ))}
774
+ {renderingElements
775
+ .filter(({ supportScreenReader }) => supportScreenReader)
776
+ .map(({ activity, liveRegionKey }) => (
777
+ <Fade fadeAfter={internalLiveRegionFadeAfter} key={liveRegionKey}>
778
+ {() => <ScreenReaderActivity activity={activity} />}
779
+ </Fade>
780
+ ))}
768
781
  </section>
769
782
  {/* TODO: [P2] Fix ESLint error `no-use-before-define` */}
770
783
  {/* eslint-disable-next-line @typescript-eslint/no-use-before-define */}
@@ -790,7 +803,8 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
790
803
  renderAvatar,
791
804
  role,
792
805
  shouldSpeak,
793
- showCallout
806
+ showCallout,
807
+ supportScreenReader
794
808
  },
795
809
  index
796
810
  ) => {
@@ -818,9 +832,11 @@ const InternalTranscript = ({ activityElementsRef, className }) => {
818
832
  onMouseDownCapture={handleMouseDownCapture}
819
833
  ref={callbackRef}
820
834
  >
821
- <ScreenReaderActivity activity={activity} id={ariaLabelID} renderAttachments={false}>
822
- {!!isContentInteractive && <p>{activityInteractiveAlt}</p>}
823
- </ScreenReaderActivity>
835
+ {supportScreenReader && (
836
+ <ScreenReaderActivity activity={activity} id={ariaLabelID} renderAttachments={false}>
837
+ {!!isContentInteractive && <p>{activityInteractiveAlt}</p>}
838
+ </ScreenReaderActivity>
839
+ )}
824
840
  <FocusRedirector
825
841
  className="webchat__basic-transcript__activity-sentinel"
826
842
  onFocus={focusActivity}
@@ -916,19 +932,20 @@ InternalScreenReaderTranscript.propTypes = {
916
932
  // Separating high-frequency hooks to improve performance.
917
933
  const InternalTranscriptScrollable = ({ activities, children, onFocusActivity, onFocusFiller, terminatorRef }) => {
918
934
  const [{ activities: activitiesStyleSet }] = useStyleSet();
919
- const [{ hideScrollToEndButton }] = useStyleOptions();
920
935
  const [animatingToEnd] = useAnimatingToEnd();
936
+ const [atEnd] = useAtEnd();
921
937
  const [sticky] = useSticky();
938
+ const [styleOptions] = useStyleOptions();
922
939
  const lastVisibleActivityId = getActivityUniqueId(activities[activities.length - 1] || {}); // Activity ID of the last visible activity in the list.
923
940
  const localize = useLocalizer();
924
- const scrollToEndButtonRef = useRef();
941
+ const scrollToEnd = useScrollToEnd();
925
942
 
926
943
  const lastReadActivityIdRef = useRef(lastVisibleActivityId);
927
944
  const transcriptRoleDescription = localize('TRANSCRIPT_ARIA_ROLE_ALT');
928
945
 
929
- const allActivitiesRead = lastVisibleActivityId === lastReadActivityIdRef.current;
930
-
931
946
  const handleScrollToEndButtonClick = useCallback(() => {
947
+ scrollToEnd({ behavior: 'smooth' });
948
+
932
949
  // After the "New message" button is clicked, focus on the first unread activity.
933
950
  const index = activities.findIndex(({ id }) => id === lastReadActivityIdRef.current);
934
951
 
@@ -943,49 +960,29 @@ const InternalTranscriptScrollable = ({ activities, children, onFocusActivity, o
943
960
  const { current } = terminatorRef;
944
961
 
945
962
  current && current.focus();
946
- }, [activities, lastReadActivityIdRef, onFocusActivity, terminatorRef]);
963
+ }, [activities, lastReadActivityIdRef, onFocusActivity, scrollToEnd, terminatorRef]);
947
964
 
948
- if (sticky) {
949
- // If it is sticky, the user is at the bottom of the transcript, everything is read.
965
+ if (atEnd || sticky) {
966
+ // If it is sticky or at the end, the user is at the bottom of the transcript, everything is read.
950
967
  // So mark the activity ID as read.
951
968
  lastReadActivityIdRef.current = lastVisibleActivityId;
952
969
  }
953
970
 
954
- // Finds where we should render the "New messages" button, in index. Returns -1 to hide the button.
955
- const renderSeparatorAfterIndex = useMemo(() => {
956
- // Don't show the button if:
957
- // - All activities have been read
958
- // - Currently animating towards bottom
959
- // - "New messages" button must not flash when: 1. Type "help", 2. Scroll to top, 3. Type "help" again, 4. Expect the "New messages" button not flashy
960
- // - Hidden by style options
961
- // - It is already at the bottom (sticky)
962
-
963
- // Any changes to this logic, verify:
964
- // - "New messages" button should persist while programmatically scrolling to mid-point of the transcript:
965
- // 1. Type "help"
966
- // 2. Type "proactive", then immediately scroll to top
967
- // Expect: the "New messages" button should appear
968
- // 3. Run hook "useScrollTo({ scrollTop: 500 })"
969
- // Expect: when the scroll is animating to 500px, the "New messages" button should kept on the screen
970
- // - "New messages" button must not flashy:
971
- // 1. Type "help"
972
- // 2. Scroll to top
973
- // Expect: no "New messages" button is shown
974
- // 3. Type "help" again
975
- // Expect: "New messages" button must not flash-appear
976
-
977
- if (allActivitiesRead || animatingToEnd || hideScrollToEndButton || sticky) {
978
- return -1;
979
- }
971
+ const ScrollToEndButton = useCreateScrollToEndButtonRenderer()({
972
+ atEnd: animatingToEnd || atEnd || sticky,
973
+ styleOptions,
980
974
 
981
- return activities.findIndex(activity => getActivityUniqueId(activity) === lastReadActivityIdRef.current);
982
- }, [activities, allActivitiesRead, animatingToEnd, hideScrollToEndButton, lastReadActivityIdRef, sticky]);
975
+ // Unread means:
976
+ // 1. Last read is not the last one in the transcript, and;
977
+ // 2. Last read is still in the transcript.
978
+ unread:
979
+ lastVisibleActivityId !== lastReadActivityIdRef.current &&
980
+ !!~activities.findIndex(activity => getActivityUniqueId(activity) === lastReadActivityIdRef.current)
981
+ });
983
982
 
984
983
  return (
985
984
  <React.Fragment>
986
- {renderSeparatorAfterIndex !== -1 && (
987
- <ScrollToEndButton onClick={handleScrollToEndButtonClick} ref={scrollToEndButtonRef} />
988
- )}
985
+ {ScrollToEndButton && <ScrollToEndButton onClick={handleScrollToEndButtonClick} />}
989
986
  {!!React.Children.count(children) && (
990
987
  <FocusRedirector className="webchat__basic-transcript__sentinel" redirectRef={terminatorRef} />
991
988
  )}
@@ -1016,10 +1013,13 @@ const SetScroller = ({ activityElementsRef, scrollerRef }) => {
1016
1013
  const [
1017
1014
  { autoScrollSnapOnActivity, autoScrollSnapOnActivityOffset, autoScrollSnapOnPage, autoScrollSnapOnPageOffset }
1018
1015
  ] = useStyleOptions();
1016
+ const [activities] = useActivities();
1019
1017
  const [lastAcknowledgedActivity] = useAcknowledgedActivity();
1020
1018
 
1019
+ const activitiesRef = useRef(activities);
1021
1020
  const lastAcknowledgedActivityRef = useRef(lastAcknowledgedActivity);
1022
1021
 
1022
+ activitiesRef.current = activities;
1023
1023
  lastAcknowledgedActivityRef.current = lastAcknowledgedActivity;
1024
1024
 
1025
1025
  scrollerRef.current = useCallback(
@@ -1042,41 +1042,56 @@ const SetScroller = ({ activityElementsRef, scrollerRef }) => {
1042
1042
  typeof autoScrollSnapOnPageOffset === 'number' ? autoScrollSnapOnPageOffset : 0;
1043
1043
 
1044
1044
  if (patchedAutoScrollSnapOnActivity || patchedAutoScrollSnapOnPage) {
1045
+ const { current: activities } = activitiesRef;
1046
+ const { current: activityElements } = activityElementsRef;
1045
1047
  const { current: lastAcknowledgedActivity } = lastAcknowledgedActivityRef;
1046
-
1047
1048
  const values = [];
1048
1049
 
1049
- if (patchedAutoScrollSnapOnActivity) {
1050
- const { element: nthUnacknowledgedActivityElement } =
1051
- activityElementsRef.current[
1052
- activityElementsRef.current.findIndex(({ activity }) => activity === lastAcknowledgedActivity) +
1053
- patchedAutoScrollSnapOnActivity
1054
- ] || {};
1055
-
1056
- if (nthUnacknowledgedActivityElement) {
1057
- values.push(
1058
- nthUnacknowledgedActivityElement.offsetTop +
1059
- nthUnacknowledgedActivityElement.offsetHeight -
1060
- offsetHeight -
1061
- scrollTop +
1062
- patchedAutoScrollSnapOnActivityOffset
1063
- );
1050
+ const lastAcknowledgedActivityIndex = activities.indexOf(lastAcknowledgedActivity);
1051
+
1052
+ if (~lastAcknowledgedActivityIndex) {
1053
+ // The activity that we acknowledged could be not rendered, such as post back activity.
1054
+ // When calculating scroll snap, we can only base on the first unacknowledged-and-rendering activity.
1055
+ let firstUnacknowledgedActivityElementIndex = -1;
1056
+
1057
+ for (let index = lastAcknowledgedActivityIndex + 1, { length } = activities; index < length; index++) {
1058
+ const activity = activities[index];
1059
+ const activityElementIndex = activityElements.findIndex(entry => entry.activity === activity);
1060
+
1061
+ if (~activityElementIndex) {
1062
+ firstUnacknowledgedActivityElementIndex = activityElementIndex;
1063
+ break;
1064
+ }
1064
1065
  }
1065
- }
1066
1066
 
1067
- if (patchedAutoScrollSnapOnPage) {
1068
- const { element: firstUnacknowledgedActivityElement } =
1069
- activityElementsRef.current[
1070
- activityElementsRef.current.findIndex(({ activity }) => activity === lastAcknowledgedActivity) + 1
1071
- ] || {};
1072
-
1073
- if (firstUnacknowledgedActivityElement) {
1074
- values.push(
1075
- firstUnacknowledgedActivityElement.offsetTop -
1076
- scrollTop -
1077
- offsetHeight * (1 - patchedAutoScrollSnapOnPage) +
1078
- patchedAutoScrollSnapOnPageOffset
1079
- );
1067
+ if (~firstUnacknowledgedActivityElementIndex) {
1068
+ if (patchedAutoScrollSnapOnActivity) {
1069
+ // Gets the activity element which we should snap to.
1070
+ const { element: nthUnacknowledgedActivityElement } =
1071
+ activityElements[firstUnacknowledgedActivityElementIndex + patchedAutoScrollSnapOnActivity - 1];
1072
+
1073
+ if (nthUnacknowledgedActivityElement) {
1074
+ values.push(
1075
+ nthUnacknowledgedActivityElement.offsetTop +
1076
+ nthUnacknowledgedActivityElement.offsetHeight -
1077
+ offsetHeight -
1078
+ scrollTop +
1079
+ patchedAutoScrollSnapOnActivityOffset
1080
+ );
1081
+ }
1082
+ }
1083
+
1084
+ if (patchedAutoScrollSnapOnPage) {
1085
+ const { element: firstUnacknowledgedActivityElement } =
1086
+ activityElements[firstUnacknowledgedActivityElementIndex];
1087
+
1088
+ values.push(
1089
+ firstUnacknowledgedActivityElement.offsetTop -
1090
+ scrollTop -
1091
+ offsetHeight * (1 - patchedAutoScrollSnapOnPage) +
1092
+ patchedAutoScrollSnapOnPageOffset
1093
+ );
1094
+ }
1080
1095
  }
1081
1096
  }
1082
1097
 
@@ -1086,6 +1101,7 @@ const SetScroller = ({ activityElementsRef, scrollerRef }) => {
1086
1101
  return Infinity;
1087
1102
  },
1088
1103
  [
1104
+ activitiesRef,
1089
1105
  activityElementsRef,
1090
1106
  autoScrollSnapOnActivity,
1091
1107
  autoScrollSnapOnActivityOffset,
@@ -2,7 +2,7 @@ import { hooks } from 'botframework-webchat-api';
2
2
 
3
3
  const { useActiveTyping, useRenderTypingIndicator } = hooks;
4
4
 
5
- function useTypingIndicatorVisible() {
5
+ function useTypingIndicatorVisible(): [boolean] {
6
6
  const [activeTyping] = useActiveTyping();
7
7
 
8
8
  return [!!Object.values(activeTyping).filter(({ role }) => role !== 'user').length];
@@ -4,7 +4,7 @@
4
4
  import { hooks } from 'botframework-webchat-api';
5
5
  import classNames from 'classnames';
6
6
  import PropTypes from 'prop-types';
7
- import React from 'react';
7
+ import React, { FC } from 'react';
8
8
 
9
9
  import AccessKeySinkSurface from './Utils/AccessKeySink/Surface';
10
10
  import BasicConnectivityStatus from './BasicConnectivityStatus';
@@ -40,7 +40,12 @@ const TRANSCRIPT_STYLE = {
40
40
  // Subset of landmark roles: https://w3.org/TR/wai-aria/#landmark_roles
41
41
  const ARIA_LANDMARK_ROLES = ['complementary', 'contentinfo', 'form', 'main', 'region'];
42
42
 
43
- const BasicWebChat = ({ className, role }) => {
43
+ type BasicWebChatProps = {
44
+ className?: string;
45
+ role?: 'complementary' | 'contentinfo' | 'form' | 'main' | 'region';
46
+ };
47
+
48
+ const BasicWebChat: FC<BasicWebChatProps> = ({ className, role }) => {
44
49
  const [{ root: rootStyleSet }] = useStyleSet();
45
50
  const [options] = useStyleOptions();
46
51
  const styleToEmotionObject = useStyleToEmotionObject();
@@ -66,8 +71,6 @@ const BasicWebChat = ({ className, role }) => {
66
71
  );
67
72
  };
68
73
 
69
- export default BasicWebChat;
70
-
71
74
  BasicWebChat.defaultProps = {
72
75
  className: '',
73
76
  role: 'complementary'
@@ -75,5 +78,11 @@ BasicWebChat.defaultProps = {
75
78
 
76
79
  BasicWebChat.propTypes = {
77
80
  className: PropTypes.string,
81
+ // Ignoring deficiencies with TypeScript/PropTypes inference.
82
+ // @ts-ignore
78
83
  role: PropTypes.oneOf(ARIA_LANDMARK_ROLES)
79
84
  };
85
+
86
+ export default BasicWebChat;
87
+
88
+ export type { BasicWebChatProps };
@@ -1,10 +1,16 @@
1
- import { Composer as APIComposer, hooks } from 'botframework-webchat-api';
1
+ import {
2
+ Composer as APIComposer,
3
+ ComposerProps as APIComposerProps,
4
+ hooks,
5
+ WebSpeechPonyfillFactory
6
+ } from 'botframework-webchat-api';
2
7
  import { Composer as SayComposer } from 'react-say';
3
- import createEmotion from 'create-emotion';
8
+ import { singleToArray } from 'botframework-webchat-core';
9
+ import createEmotion from '@emotion/css/create-instance';
4
10
  import createStyleSet from './Styles/createStyleSet';
5
11
  import MarkdownIt from 'markdown-it';
6
12
  import PropTypes from 'prop-types';
7
- import React, { useCallback, useMemo, useRef, useState } from 'react';
13
+ import React, { FC, ReactNode, useCallback, useMemo, useRef, useState } from 'react';
8
14
 
9
15
  import {
10
16
  speechSynthesis as bypassSpeechSynthesis,
@@ -18,13 +24,13 @@ import createDefaultAttachmentForScreenReaderMiddleware from './Middleware/Attac
18
24
  import createDefaultAttachmentMiddleware from './Middleware/Attachment/createCoreMiddleware';
19
25
  import createDefaultAvatarMiddleware from './Middleware/Avatar/createCoreMiddleware';
20
26
  import createDefaultCardActionMiddleware from './Middleware/CardAction/createCoreMiddleware';
27
+ import createDefaultScrollToEndButtonMiddleware from './Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware';
21
28
  import createDefaultToastMiddleware from './Middleware/Toast/createCoreMiddleware';
22
29
  import createDefaultTypingIndicatorMiddleware from './Middleware/TypingIndicator/createCoreMiddleware';
23
30
  import Dictation from './Dictation';
24
31
  import downscaleImageToDataURL from './Utils/downscaleImageToDataURL';
25
32
  import ErrorBox from './ErrorBox';
26
33
  import mapMap from './Utils/mapMap';
27
- import singleToArray from './Utils/singleToArray';
28
34
  import UITracker from './hooks/internal/UITracker';
29
35
  import WebChatUIContext from './hooks/internal/WebChatUIContext';
30
36
 
@@ -39,7 +45,17 @@ function styleSetToEmotionObjects(styleToEmotionObject, styleSet) {
39
45
  return mapMap(styleSet, (style, key) => (key === 'options' ? style : styleToEmotionObject(style)));
40
46
  }
41
47
 
42
- const ComposerCore = ({
48
+ type ComposerCoreProps = {
49
+ children?: ReactNode;
50
+ extraStyleSet?: any;
51
+ nonce?: string;
52
+ renderMarkdown?: (markdown: string, { markdownRespectCRLF: boolean }, { externalLinkAlt: string }) => string;
53
+ styleSet?: any;
54
+ suggestedActionsAccessKey?: boolean | string;
55
+ webSpeechPonyfillFactory?: WebSpeechPonyfillFactory;
56
+ };
57
+
58
+ const ComposerCore: FC<ComposerCoreProps> = ({
43
59
  children,
44
60
  extraStyleSet,
45
61
  nonce,
@@ -226,7 +242,13 @@ ComposerCore.propTypes = {
226
242
  webSpeechPonyfillFactory: PropTypes.func
227
243
  };
228
244
 
229
- const Composer = ({
245
+ type ComposerProps = APIComposerProps &
246
+ ComposerCoreProps & {
247
+ nonce?: string;
248
+ webSpeechPonyfillFactory?: WebSpeechPonyfillFactory;
249
+ };
250
+
251
+ const Composer: FC<ComposerProps> = ({
230
252
  activityMiddleware,
231
253
  activityStatusMiddleware,
232
254
  attachmentForScreenReaderMiddleware,
@@ -236,6 +258,7 @@ const Composer = ({
236
258
  children,
237
259
  extraStyleSet,
238
260
  renderMarkdown,
261
+ scrollToEndButtonMiddleware,
239
262
  styleSet,
240
263
  suggestedActionsAccessKey,
241
264
  toastMiddleware,
@@ -287,6 +310,13 @@ const Composer = ({
287
310
  [typingIndicatorMiddleware]
288
311
  );
289
312
 
313
+ const defaultScrollToEndButtonMiddleware = useMemo(() => createDefaultScrollToEndButtonMiddleware(), []);
314
+
315
+ const patchedScrollToEndButtonMiddleware = useMemo(
316
+ () => [...singleToArray(scrollToEndButtonMiddleware), ...defaultScrollToEndButtonMiddleware],
317
+ [defaultScrollToEndButtonMiddleware, scrollToEndButtonMiddleware]
318
+ );
319
+
290
320
  return (
291
321
  <React.Fragment>
292
322
  <APIComposer
@@ -300,6 +330,7 @@ const Composer = ({
300
330
  // Under dev server of create-react-app, "NODE_ENV" will be set to "development".
301
331
  internalErrorBoxClass={node_env === 'development' ? ErrorBox : undefined}
302
332
  nonce={nonce}
333
+ scrollToEndButtonMiddleware={patchedScrollToEndButtonMiddleware}
303
334
  toastMiddleware={patchedToastMiddleware}
304
335
  typingIndicatorMiddleware={patchedTypingIndicatorMiddleware}
305
336
  {...composerProps}
@@ -323,47 +354,15 @@ const Composer = ({
323
354
  Composer.defaultProps = {
324
355
  ...APIComposer.defaultProps,
325
356
  ...ComposerCore.defaultProps,
326
- activityMiddleware: undefined,
327
- activityRenderer: undefined,
328
- activityStatusMiddleware: undefined,
329
- activityStatusRenderer: undefined,
330
- attachmentForScreenReaderMiddleware: undefined,
331
- attachmentMiddleware: undefined,
332
- attachmentRenderer: undefined,
333
- avatarMiddleware: undefined,
334
- avatarRenderer: undefined,
335
- cardActionMiddleware: undefined,
336
- children: undefined,
337
- nonce: undefined,
338
- renderMarkdown: undefined,
339
- toastMiddleware: undefined,
340
- toastRenderer: undefined,
341
- typingIndicatorMiddleware: undefined,
342
- typingIndicatorRenderer: undefined,
343
- webSpeechPonyfillFactory: undefined
357
+ children: undefined
344
358
  };
345
359
 
346
360
  Composer.propTypes = {
347
361
  ...APIComposer.propTypes,
348
362
  ...ComposerCore.propTypes,
349
- activityMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
350
- activityRenderer: PropTypes.func,
351
- activityStatusMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
352
- activityStatusRenderer: PropTypes.func,
353
- attachmentForScreenReaderMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
354
- attachmentMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
355
- attachmentRenderer: PropTypes.func,
356
- avatarMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
357
- avatarRenderer: PropTypes.func,
358
- cardActionMiddleware: PropTypes.func,
359
- children: PropTypes.any,
360
- nonce: PropTypes.string,
361
- renderMarkdown: PropTypes.func,
362
- toastMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
363
- toastRenderer: PropTypes.func,
364
- typingIndicatorMiddleware: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.func), PropTypes.func]),
365
- typingIndicatorRenderer: PropTypes.func,
366
- webSpeechPonyfillFactory: PropTypes.func
363
+ children: PropTypes.any
367
364
  };
368
365
 
369
366
  export default Composer;
367
+
368
+ export type { ComposerProps };