botframework-webchat-component 4.13.0 → 4.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.yml +4 -100
- package/.prettierrc.yml +1 -1
- package/lib/Activity/Avatar.d.ts +10 -0
- package/lib/Activity/Avatar.d.ts.map +1 -0
- package/lib/Activity/Avatar.js +2 -1
- package/lib/Activity/Bubble.d.ts +11 -0
- package/lib/Activity/Bubble.d.ts.map +1 -0
- package/lib/Activity/Bubble.js +2 -2
- package/lib/Activity/CarouselFilmStrip.js +21 -31
- package/lib/Activity/CarouselFilmStripAttachment.js +120 -0
- package/lib/Activity/CarouselLayout.js +5 -5
- package/lib/Activity/Speak.d.ts +10 -0
- package/lib/Activity/Speak.d.ts.map +1 -0
- package/lib/Activity/Speak.js +11 -13
- package/lib/Activity/StackedLayout.d.ts +18 -0
- package/lib/Activity/StackedLayout.d.ts.map +1 -0
- package/lib/Activity/StackedLayout.js +19 -15
- package/lib/Assets/TypingAnimation.js +2 -2
- package/lib/Attachment/Assets/DownloadIcon.js +3 -1
- package/lib/Attachment/AudioAttachment.js +2 -2
- package/lib/Attachment/AudioContent.d.ts +11 -0
- package/lib/Attachment/AudioContent.d.ts.map +1 -0
- package/lib/Attachment/AudioContent.js +4 -4
- package/lib/Attachment/FileAttachment.js +2 -2
- package/lib/Attachment/FileContent.d.ts +10 -0
- package/lib/Attachment/FileContent.d.ts.map +1 -0
- package/lib/Attachment/FileContent.js +14 -9
- package/lib/Attachment/HTMLVideoContent.d.ts +11 -0
- package/lib/Attachment/HTMLVideoContent.d.ts.map +1 -0
- package/lib/Attachment/HTMLVideoContent.js +2 -2
- package/lib/Attachment/ImageContent.d.ts +8 -0
- package/lib/Attachment/ImageContent.d.ts.map +1 -0
- package/lib/Attachment/ImageContent.js +2 -2
- package/lib/Attachment/TextContent.d.ts +8 -0
- package/lib/Attachment/TextContent.d.ts.map +1 -0
- package/lib/Attachment/TextContent.js +4 -4
- package/lib/Attachment/VideoAttachment.js +2 -2
- package/lib/Attachment/VideoContent.d.ts +11 -0
- package/lib/Attachment/VideoContent.d.ts.map +1 -0
- package/lib/Attachment/VideoContent.js +1 -1
- package/lib/Attachment/VimeoContent.d.ts +10 -0
- package/lib/Attachment/VimeoContent.d.ts.map +1 -0
- package/lib/Attachment/VimeoContent.js +8 -8
- package/lib/Attachment/YouTubeContent.d.ts +10 -0
- package/lib/Attachment/YouTubeContent.d.ts.map +1 -0
- package/lib/Attachment/YouTubeContent.js +5 -5
- package/lib/Avatar/ImageAvatar.js +2 -2
- package/lib/Avatar/InitialsAvatar.js +2 -2
- package/lib/BasicConnectivityStatus.js +2 -2
- package/lib/BasicSendBox.d.ts +9 -0
- package/lib/BasicSendBox.d.ts.map +1 -0
- package/lib/BasicSendBox.js +7 -6
- package/lib/BasicToast.js +4 -4
- package/lib/BasicToaster.js +8 -5
- package/lib/BasicTranscript.d.ts +7 -0
- package/lib/BasicTranscript.d.ts.map +1 -0
- package/lib/BasicTranscript.js +406 -743
- package/lib/BasicTypingIndicator.d.ts +6 -0
- package/lib/BasicTypingIndicator.d.ts.map +1 -0
- package/lib/BasicTypingIndicator.js +13 -5
- package/lib/BasicWebChat.d.ts +9 -0
- package/lib/BasicWebChat.d.ts.map +1 -0
- package/lib/BasicWebChat.js +6 -4
- package/lib/Composer.d.ts +23 -0
- package/lib/Composer.d.ts.map +1 -0
- package/lib/Composer.js +65 -82
- package/lib/ConnectivityStatus/Assets/ErrorNotificationIcon.js +2 -2
- package/lib/ConnectivityStatus/Assets/SpinnerAnimation.js +2 -2
- package/lib/ConnectivityStatus/Assets/WarningNotificationIcon.js +2 -2
- package/lib/ConnectivityStatus/Connected.js +1 -1
- package/lib/ConnectivityStatus/Connecting.js +4 -4
- package/lib/ConnectivityStatus/FailedToConnect.js +2 -2
- package/lib/ConnectivityStatus/JavaScriptError.js +2 -2
- package/lib/Dictation.js +13 -4
- package/lib/ErrorBox.d.ts +8 -0
- package/lib/ErrorBox.d.ts.map +1 -0
- package/lib/ErrorBox.js +2 -2
- package/lib/Middleware/Activity/createCoreMiddleware.d.ts +3 -0
- package/lib/Middleware/Activity/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/Activity/createCoreMiddleware.js +1 -1
- package/lib/Middleware/ActivityStatus/AbsoluteTime.js +1 -1
- package/lib/Middleware/ActivityStatus/RelativeTime.js +1 -1
- package/lib/Middleware/ActivityStatus/SendStatus/SendFailedRetry.js +3 -3
- package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.d.ts +11 -0
- package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.d.ts.map +1 -0
- package/lib/Middleware/ActivityStatus/SendStatus/SendStatus.js +5 -5
- package/lib/Middleware/ActivityStatus/Timestamp.d.ts +9 -0
- package/lib/Middleware/ActivityStatus/Timestamp.d.ts.map +1 -0
- package/lib/Middleware/ActivityStatus/Timestamp.js +2 -2
- package/lib/Middleware/ActivityStatus/createCoreMiddleware.d.ts +3 -0
- package/lib/Middleware/ActivityStatus/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/ActivityStatus/createCoreMiddleware.js +1 -1
- package/lib/Middleware/ActivityStatus/createSendStatusMiddleware.js +21 -16
- package/lib/Middleware/ActivityStatus/createTimestampMiddleware.js +1 -1
- package/lib/Middleware/Attachment/createCoreMiddleware.d.ts +3 -0
- package/lib/Middleware/Attachment/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/Attachment/createCoreMiddleware.js +10 -13
- package/lib/Middleware/AttachmentForScreenReader/AudioAttachment.js +1 -1
- package/lib/Middleware/AttachmentForScreenReader/FileAttachment.js +1 -1
- package/lib/Middleware/AttachmentForScreenReader/ImageAttachment.js +1 -1
- package/lib/Middleware/AttachmentForScreenReader/TextAttachment.js +1 -1
- package/lib/Middleware/AttachmentForScreenReader/VideoAttachment.js +1 -1
- package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.d.ts +3 -0
- package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/AttachmentForScreenReader/createCoreMiddleware.js +9 -5
- package/lib/Middleware/Avatar/createCoreMiddleware.d.ts +11 -0
- package/lib/Middleware/Avatar/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/Avatar/createCoreMiddleware.js +3 -4
- package/lib/Middleware/CardAction/createCoreMiddleware.js +11 -4
- package/lib/Middleware/GroupActivities/createCoreMiddleware.js +1 -1
- package/lib/Middleware/ScrollToEndButton/ScrollToEndButton.js +71 -0
- package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.d.ts +3 -0
- package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.d.ts.map +1 -0
- package/lib/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.js +27 -0
- package/lib/Middleware/Toast/createCoreMiddleware.d.ts +4 -0
- package/lib/Middleware/Toast/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/Toast/createCoreMiddleware.js +1 -1
- package/lib/Middleware/TypingIndicator/createCoreMiddleware.d.ts +3 -0
- package/lib/Middleware/TypingIndicator/createCoreMiddleware.d.ts.map +1 -0
- package/lib/Middleware/TypingIndicator/createCoreMiddleware.js +9 -6
- package/lib/ReactWebChat.d.ts +10 -0
- package/lib/ReactWebChat.d.ts.map +1 -0
- package/lib/ReactWebChat.js +19 -7
- package/lib/ScreenReaderActivity.js +76 -48
- package/lib/ScreenReaderText.d.ts +9 -0
- package/lib/ScreenReaderText.d.ts.map +1 -0
- package/lib/ScreenReaderText.js +22 -8
- package/lib/SendBox/Assets/AttachmentIcon.js +3 -1
- package/lib/SendBox/Assets/MicrophoneIcon.js +3 -1
- package/lib/SendBox/Assets/SendIcon.js +2 -2
- package/lib/SendBox/AutoResizeTextArea.d.ts +23 -0
- package/lib/SendBox/AutoResizeTextArea.d.ts.map +1 -0
- package/lib/SendBox/AutoResizeTextArea.js +6 -6
- package/lib/SendBox/DictationInterims.d.ts +9 -0
- package/lib/SendBox/DictationInterims.d.ts.map +1 -0
- package/lib/SendBox/DictationInterims.js +3 -3
- package/lib/SendBox/IconButton.d.ts +11 -0
- package/lib/SendBox/IconButton.d.ts.map +1 -0
- package/lib/SendBox/IconButton.js +27 -7
- package/lib/SendBox/MicrophoneButton.d.ts +11 -0
- package/lib/SendBox/MicrophoneButton.d.ts.map +1 -0
- package/lib/SendBox/MicrophoneButton.js +25 -24
- package/lib/SendBox/SendButton.d.ts +9 -0
- package/lib/SendBox/SendButton.d.ts.map +1 -0
- package/lib/SendBox/SendButton.js +8 -6
- package/lib/SendBox/SuggestedAction.d.ts +17 -0
- package/lib/SendBox/SuggestedAction.d.ts.map +1 -0
- package/lib/SendBox/SuggestedAction.js +29 -24
- package/lib/SendBox/SuggestedActions.d.ts +5 -0
- package/lib/SendBox/SuggestedActions.d.ts.map +1 -0
- package/lib/SendBox/SuggestedActions.js +33 -13
- package/lib/SendBox/TextBox.d.ts +28 -0
- package/lib/SendBox/TextBox.d.ts.map +1 -0
- package/lib/SendBox/TextBox.js +13 -8
- package/lib/SendBox/UploadButton.d.ts +9 -0
- package/lib/SendBox/UploadButton.d.ts.map +1 -0
- package/lib/SendBox/UploadButton.js +6 -6
- package/lib/Styles/StyleSet/Activities.d.ts +5 -0
- package/lib/Styles/StyleSet/Activities.d.ts.map +1 -0
- package/lib/Styles/StyleSet/AudioAttachment.d.ts +6 -0
- package/lib/Styles/StyleSet/AudioAttachment.d.ts.map +1 -0
- package/lib/Styles/StyleSet/AudioContent.d.ts +4 -0
- package/lib/Styles/StyleSet/AudioContent.d.ts.map +1 -0
- package/lib/Styles/StyleSet/AutoResizeTextArea.d.ts +37 -0
- package/lib/Styles/StyleSet/AutoResizeTextArea.d.ts.map +1 -0
- package/lib/Styles/StyleSet/Avatar.d.ts +9 -0
- package/lib/Styles/StyleSet/Avatar.d.ts.map +1 -0
- package/lib/Styles/StyleSet/BasicTranscript.d.ts +85 -0
- package/lib/Styles/StyleSet/BasicTranscript.d.ts.map +1 -0
- package/lib/Styles/StyleSet/BasicTranscript.js +21 -9
- package/lib/Styles/StyleSet/Bubble.d.ts +5 -0
- package/lib/Styles/StyleSet/Bubble.d.ts.map +1 -0
- package/lib/Styles/StyleSet/Bubble.js +2 -2
- package/lib/Styles/StyleSet/CarouselFilmStrip.d.ts +5 -0
- package/lib/Styles/StyleSet/CarouselFilmStrip.d.ts.map +1 -0
- package/lib/Styles/StyleSet/CarouselFilmStrip.js +2 -18
- package/lib/Styles/StyleSet/CarouselFilmStripAttachment.d.ts +3 -0
- package/lib/Styles/StyleSet/CarouselFilmStripAttachment.d.ts.map +1 -0
- package/lib/Styles/StyleSet/CarouselFilmStripAttachment.js +63 -0
- package/lib/Styles/StyleSet/CarouselFlipper.d.ts +27 -0
- package/lib/Styles/StyleSet/CarouselFlipper.d.ts.map +1 -0
- package/lib/Styles/StyleSet/ConnectivityNotification.d.ts +13 -0
- package/lib/Styles/StyleSet/ConnectivityNotification.d.ts.map +1 -0
- package/lib/Styles/StyleSet/DictationInterims.d.ts +13 -0
- package/lib/Styles/StyleSet/DictationInterims.d.ts.map +1 -0
- package/lib/Styles/StyleSet/ErrorBox.d.ts +33 -0
- package/lib/Styles/StyleSet/ErrorBox.d.ts.map +1 -0
- package/lib/Styles/StyleSet/ErrorNotification.d.ts +23 -0
- package/lib/Styles/StyleSet/ErrorNotification.d.ts.map +1 -0
- package/lib/Styles/StyleSet/FileContent.d.ts +32 -0
- package/lib/Styles/StyleSet/FileContent.d.ts.map +1 -0
- package/lib/Styles/StyleSet/ImageAvatar.d.ts +7 -0
- package/lib/Styles/StyleSet/ImageAvatar.d.ts.map +1 -0
- package/lib/Styles/StyleSet/InitialsAvatar.d.ts +19 -0
- package/lib/Styles/StyleSet/InitialsAvatar.d.ts.map +1 -0
- package/lib/Styles/StyleSet/KeyboardHelp.d.ts +123 -0
- package/lib/Styles/StyleSet/KeyboardHelp.d.ts.map +1 -0
- package/lib/Styles/StyleSet/KeyboardHelp.js +145 -0
- package/lib/Styles/StyleSet/MicrophoneButton.d.ts +13 -0
- package/lib/Styles/StyleSet/MicrophoneButton.d.ts.map +1 -0
- package/lib/Styles/StyleSet/Root.d.ts +8 -0
- package/lib/Styles/StyleSet/Root.d.ts.map +1 -0
- package/lib/Styles/StyleSet/ScrollToEndButton.d.ts +36 -0
- package/lib/Styles/StyleSet/ScrollToEndButton.d.ts.map +1 -0
- package/lib/Styles/StyleSet/ScrollToEndButton.js +36 -34
- package/lib/Styles/StyleSet/SendBox.d.ts +24 -0
- package/lib/Styles/StyleSet/SendBox.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SendBoxButton.d.ts +79 -0
- package/lib/Styles/StyleSet/SendBoxButton.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SendBoxButton.js +76 -12
- package/lib/Styles/StyleSet/SendBoxTextBox.d.ts +41 -0
- package/lib/Styles/StyleSet/SendBoxTextBox.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SendBoxTextBox.js +3 -3
- package/lib/Styles/StyleSet/SendStatus.d.ts +8 -0
- package/lib/Styles/StyleSet/SendStatus.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SingleAttachmentActivity.d.ts +11 -0
- package/lib/Styles/StyleSet/SingleAttachmentActivity.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SpinnerAnimation.d.ts +15 -0
- package/lib/Styles/StyleSet/SpinnerAnimation.d.ts.map +1 -0
- package/lib/Styles/StyleSet/StackedLayout.d.ts +63 -0
- package/lib/Styles/StyleSet/StackedLayout.d.ts.map +1 -0
- package/lib/Styles/StyleSet/StackedLayout.js +1 -1
- package/lib/Styles/StyleSet/SuggestedAction.d.ts +94 -0
- package/lib/Styles/StyleSet/SuggestedAction.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SuggestedAction.js +116 -41
- package/lib/Styles/StyleSet/SuggestedActions.d.ts +125 -0
- package/lib/Styles/StyleSet/SuggestedActions.d.ts.map +1 -0
- package/lib/Styles/StyleSet/SuggestedActions.js +13 -6
- package/lib/Styles/StyleSet/TextContent.d.ts +28 -0
- package/lib/Styles/StyleSet/TextContent.d.ts.map +1 -0
- package/lib/Styles/StyleSet/Toast.d.ts +65 -0
- package/lib/Styles/StyleSet/Toast.d.ts.map +1 -0
- package/lib/Styles/StyleSet/Toaster.d.ts +111 -0
- package/lib/Styles/StyleSet/Toaster.d.ts.map +1 -0
- package/lib/Styles/StyleSet/TypingAnimation.d.ts +8 -0
- package/lib/Styles/StyleSet/TypingAnimation.d.ts.map +1 -0
- package/lib/Styles/StyleSet/TypingIndicator.d.ts +11 -0
- package/lib/Styles/StyleSet/TypingIndicator.d.ts.map +1 -0
- package/lib/Styles/StyleSet/UploadButton.d.ts +14 -0
- package/lib/Styles/StyleSet/UploadButton.d.ts.map +1 -0
- package/lib/Styles/StyleSet/VideoAttachment.d.ts +2 -0
- package/lib/Styles/StyleSet/VideoAttachment.d.ts.map +1 -0
- package/lib/Styles/StyleSet/VideoContent.d.ts +6 -0
- package/lib/Styles/StyleSet/VideoContent.d.ts.map +1 -0
- package/lib/Styles/StyleSet/VimeoContent.d.ts +7 -0
- package/lib/Styles/StyleSet/VimeoContent.d.ts.map +1 -0
- package/lib/Styles/StyleSet/WarningNotification.d.ts +22 -0
- package/lib/Styles/StyleSet/WarningNotification.d.ts.map +1 -0
- package/lib/Styles/StyleSet/YouTubeContent.d.ts +7 -0
- package/lib/Styles/StyleSet/YouTubeContent.d.ts.map +1 -0
- package/lib/Styles/createStyleSet.d.ts +1372 -0
- package/lib/Styles/createStyleSet.d.ts.map +1 -0
- package/lib/Styles/createStyleSet.js +47 -41
- package/lib/Styles/mirrorStyle.js +13 -4
- package/lib/Toast/CollapseIcon.js +3 -1
- package/lib/Toast/DismissIcon.js +3 -1
- package/lib/Toast/ExpandIcon.js +3 -1
- package/lib/Toast/NotificationIcon.js +7 -3
- package/lib/Toast/createToastMiddleware.d.ts +4 -0
- package/lib/Toast/createToastMiddleware.d.ts.map +1 -0
- package/lib/Toast/createToastMiddleware.js +2 -2
- package/lib/Transcript/ActivityRow.d.ts +9 -0
- package/lib/Transcript/ActivityRow.d.ts.map +1 -0
- package/lib/Transcript/ActivityRow.js +157 -0
- package/lib/Transcript/ActivityTextAlt.js +57 -0
- package/lib/Transcript/FocusTrap.d.ts +8 -0
- package/lib/Transcript/FocusTrap.d.ts.map +1 -0
- package/lib/Transcript/FocusTrap.js +74 -0
- package/lib/Transcript/KeyboardHelp.d.ts +4 -0
- package/lib/Transcript/KeyboardHelp.d.ts.map +1 -0
- package/lib/Transcript/KeyboardHelp.js +550 -0
- package/lib/Transcript/LiveRegionTranscript.d.ts +8 -0
- package/lib/Transcript/LiveRegionTranscript.d.ts.map +1 -0
- package/lib/Transcript/LiveRegionTranscript.js +214 -0
- package/lib/Transcript/types.d.ts +2 -0
- package/lib/Transcript/types.d.ts.map +1 -0
- package/lib/Transcript/types.js +2 -0
- package/lib/Transcript/useActivityAccessibleName.d.ts +4 -0
- package/lib/Transcript/useActivityAccessibleName.d.ts.map +1 -0
- package/lib/Transcript/useActivityAccessibleName.js +97 -0
- package/lib/Utils/AccessKeySink/Surface.js +7 -5
- package/lib/Utils/AccessibleButton.d.ts +11 -0
- package/lib/Utils/AccessibleButton.d.ts.map +1 -0
- package/lib/Utils/AccessibleButton.js +15 -8
- package/lib/Utils/AccessibleInputText.d.ts +21 -0
- package/lib/Utils/AccessibleInputText.d.ts.map +1 -0
- package/lib/Utils/AccessibleInputText.js +29 -25
- package/lib/Utils/AccessibleTextArea.d.ts +20 -0
- package/lib/Utils/AccessibleTextArea.d.ts.map +1 -0
- package/lib/Utils/AccessibleTextArea.js +35 -24
- package/lib/Utils/CroppedImage.js +2 -2
- package/lib/Utils/Fade.js +2 -2
- package/lib/Utils/FocusRedirector.d.ts +9 -0
- package/lib/Utils/FocusRedirector.d.ts.map +1 -0
- package/lib/Utils/FocusRedirector.js +18 -15
- package/lib/Utils/InlineMarkdown.js +17 -10
- package/lib/Utils/TypeFocusSink/FocusBox.js +6 -4
- package/lib/Utils/TypeFocusSink/getTabIndex.d.ts +2 -0
- package/lib/Utils/TypeFocusSink/getTabIndex.d.ts.map +1 -0
- package/lib/Utils/TypeFocusSink/getTabIndex.js +1 -1
- package/lib/Utils/TypeFocusSink/inputtableKey.d.ts +2 -0
- package/lib/Utils/TypeFocusSink/inputtableKey.d.ts.map +1 -0
- package/lib/Utils/TypeFocusSink/inputtableKey.js +5 -2
- package/lib/Utils/TypeFocusSink/navigableEvent.js +1 -1
- package/lib/Utils/activityAltText.d.ts +8 -0
- package/lib/Utils/activityAltText.d.ts.map +1 -0
- package/lib/Utils/activityAltText.js +100 -0
- package/lib/Utils/addTargetBlankToHyperlinksMarkdown.js +1 -1
- package/lib/Utils/createCustomEvent.js +9 -3
- package/lib/Utils/debounce.js +1 -1
- package/lib/Utils/detectBrowser.js +4 -2
- package/lib/Utils/downscaleImageToDataURL/downscaleImageToDataURLUsingWorker.js +3 -3
- package/lib/Utils/downscaleImageToDataURL/index.js +2 -2
- package/lib/Utils/filterMap.js +1 -1
- package/lib/Utils/findAncestor.js +17 -0
- package/lib/Utils/getActivityUniqueId.js +4 -2
- package/lib/Utils/intersectionOf.d.ts +5 -0
- package/lib/Utils/intersectionOf.d.ts.map +1 -0
- package/lib/Utils/intersectionOf.js +17 -2
- package/lib/Utils/isZeroOrPositive.d.ts +5 -0
- package/lib/Utils/isZeroOrPositive.d.ts.map +1 -0
- package/lib/Utils/isZeroOrPositive.js +4 -1
- package/lib/Utils/mapMap.js +10 -3
- package/lib/Utils/readDataURIToBlob.js +3 -3
- package/lib/Utils/scrollIntoViewWithBlockNearest.d.ts +7 -0
- package/lib/Utils/scrollIntoViewWithBlockNearest.d.ts.map +1 -0
- package/lib/Utils/scrollIntoViewWithBlockNearest.js +48 -0
- package/lib/Utils/shallowEquals.js +7 -3
- package/lib/Utils/singleToArray.js +1 -1
- package/lib/Utils/supportPseudoClass.d.ts +2 -0
- package/lib/Utils/supportPseudoClass.d.ts.map +1 -0
- package/lib/Utils/supportPseudoClass.js +23 -0
- package/lib/Utils/tabbableElements.d.ts +2 -0
- package/lib/Utils/tabbableElements.d.ts.map +1 -0
- package/lib/Utils/tabbableElements.js +2 -2
- package/lib/connectToWebChat.js +17 -7
- package/lib/hooks/index.d.ts +21 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/index.js +25 -25
- package/lib/hooks/internal/BypassSpeechSynthesisPonyfill.js +100 -41
- package/lib/hooks/internal/UITracker.js +2 -2
- package/lib/hooks/internal/useChanged.js +8 -1
- package/lib/hooks/internal/useDispatchScrollPosition.js +3 -7
- package/lib/hooks/internal/useDispatchTranscriptFocusByActivityKey.d.ts +2 -0
- package/lib/hooks/internal/useDispatchTranscriptFocusByActivityKey.d.ts.map +1 -0
- package/lib/hooks/internal/useDispatchTranscriptFocusByActivityKey.js +15 -0
- package/lib/hooks/internal/useEnterKeyHint.js +1 -1
- package/lib/hooks/internal/useFocusVisible.d.ts +3 -0
- package/lib/hooks/internal/useFocusVisible.d.ts.map +1 -0
- package/lib/hooks/internal/useFocusVisible.js +48 -0
- package/lib/hooks/internal/useForceRender.js +2 -2
- package/lib/hooks/internal/useForceRenderAtInterval.js +2 -2
- package/lib/hooks/internal/useInternalRenderMarkdownInline.js +1 -1
- package/lib/hooks/internal/useLocalizeAccessKey.js +2 -2
- package/lib/hooks/internal/useMemoWithPrevious.d.ts +3 -0
- package/lib/hooks/internal/useMemoWithPrevious.d.ts.map +1 -0
- package/lib/hooks/internal/useMemoWithPrevious.js +22 -0
- package/lib/hooks/internal/useMemoize.d.ts +14 -0
- package/lib/hooks/internal/useMemoize.d.ts.map +1 -0
- package/lib/hooks/internal/useMemoize.js +12 -3
- package/lib/hooks/internal/useNavigatorPlatform.js +1 -1
- package/lib/hooks/internal/useNonce.js +1 -1
- package/lib/hooks/internal/useObserveFocusVisible.d.ts +3 -0
- package/lib/hooks/internal/useObserveFocusVisible.d.ts.map +1 -0
- package/lib/hooks/internal/useObserveFocusVisible.js +208 -0
- package/lib/hooks/internal/usePrevious.d.ts +2 -0
- package/lib/hooks/internal/usePrevious.d.ts.map +1 -0
- package/lib/hooks/internal/usePrevious.js +18 -0
- package/lib/hooks/internal/useRegisterFocusSendBox.js +1 -1
- package/lib/hooks/internal/useRegisterFocusTranscript.js +1 -1
- package/lib/hooks/internal/useRegisterScrollRelative.js +1 -1
- package/lib/hooks/internal/useRegisterScrollTo.js +1 -1
- package/lib/hooks/internal/useRegisterScrollToEnd.js +1 -1
- package/lib/hooks/internal/useReplaceEmoticon.js +2 -2
- package/lib/hooks/internal/useResumeAudioContext.js +33 -0
- package/lib/hooks/internal/useScrollRelative.js +1 -1
- package/lib/hooks/internal/useSettableDictateAbortable.js +1 -1
- package/lib/hooks/internal/useStateRef.d.ts +3 -0
- package/lib/hooks/internal/useStateRef.d.ts.map +1 -0
- package/lib/hooks/internal/useStateRef.js +40 -0
- package/lib/hooks/internal/useSuggestedActionsAccessKey.js +1 -1
- package/lib/hooks/internal/useUniqueId.d.ts +2 -0
- package/lib/hooks/internal/useUniqueId.d.ts.map +1 -0
- package/lib/hooks/internal/useUniqueId.js +1 -1
- package/lib/hooks/internal/useValueRef.d.ts +3 -0
- package/lib/hooks/internal/useValueRef.d.ts.map +1 -0
- package/lib/hooks/internal/useValueRef.js +25 -0
- package/lib/hooks/useDictateAbortable.d.ts +2 -0
- package/lib/hooks/useDictateAbortable.d.ts.map +1 -0
- package/lib/hooks/useDictateAbortable.js +2 -2
- package/lib/hooks/useFocus.d.ts +2 -0
- package/lib/hooks/useFocus.d.ts.map +1 -0
- package/lib/hooks/useFocus.js +1 -1
- package/lib/hooks/useFocusSendBox.d.ts +3 -0
- package/lib/hooks/useFocusSendBox.d.ts.map +1 -0
- package/lib/hooks/useFocusSendBox.js +2 -1
- package/lib/hooks/useObserveScrollPosition.d.ts +3 -0
- package/lib/hooks/useObserveScrollPosition.d.ts.map +1 -0
- package/lib/hooks/useObserveScrollPosition.js +2 -2
- package/lib/hooks/useObserveTranscriptFocus.d.ts +5 -0
- package/lib/hooks/useObserveTranscriptFocus.d.ts.map +1 -0
- package/lib/hooks/useObserveTranscriptFocus.js +2 -2
- package/lib/hooks/useRenderMarkdownAsHTML.d.ts +5 -0
- package/lib/hooks/useRenderMarkdownAsHTML.d.ts.map +1 -0
- package/lib/hooks/useRenderMarkdownAsHTML.js +2 -2
- package/lib/hooks/useScrollDown.d.ts +4 -0
- package/lib/hooks/useScrollDown.d.ts.map +1 -0
- package/lib/hooks/useScrollDown.js +1 -1
- package/lib/hooks/useScrollTo.d.ts +5 -0
- package/lib/hooks/useScrollTo.d.ts.map +1 -0
- package/lib/hooks/useScrollTo.js +1 -1
- package/lib/hooks/useScrollToEnd.d.ts +2 -0
- package/lib/hooks/useScrollToEnd.d.ts.map +1 -0
- package/lib/hooks/useScrollToEnd.js +1 -1
- package/lib/hooks/useScrollUp.d.ts +4 -0
- package/lib/hooks/useScrollUp.d.ts.map +1 -0
- package/lib/hooks/useScrollUp.js +1 -1
- package/lib/hooks/useSendFiles.d.ts +2 -0
- package/lib/hooks/useSendFiles.d.ts.map +1 -0
- package/lib/hooks/useSendFiles.js +3 -3
- package/lib/hooks/useStyleSet.d.ts +2 -0
- package/lib/hooks/useStyleSet.d.ts.map +1 -0
- package/lib/hooks/useStyleSet.js +1 -1
- package/lib/hooks/useWebSpeechPonyfill.d.ts +3 -0
- package/lib/hooks/useWebSpeechPonyfill.d.ts.map +1 -0
- package/lib/hooks/useWebSpeechPonyfill.js +1 -1
- package/lib/index.d.ts +219 -22
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +22 -20
- package/lib/providers/ActivityTree/ActivityTreeComposer.d.ts +5 -0
- package/lib/providers/ActivityTree/ActivityTreeComposer.d.ts.map +1 -0
- package/lib/providers/ActivityTree/ActivityTreeComposer.js +86 -0
- package/lib/providers/ActivityTree/private/Context.d.ts +9 -0
- package/lib/providers/ActivityTree/private/Context.d.ts.map +1 -0
- package/lib/providers/ActivityTree/private/Context.js +13 -0
- package/lib/providers/ActivityTree/private/types.d.ts +10 -0
- package/lib/providers/ActivityTree/private/types.d.ts.map +1 -0
- package/lib/providers/ActivityTree/private/types.js +2 -0
- package/lib/providers/ActivityTree/private/useActivitiesWithRenderer.d.ts +4 -0
- package/lib/providers/ActivityTree/private/useActivitiesWithRenderer.d.ts.map +1 -0
- package/lib/providers/ActivityTree/private/useActivitiesWithRenderer.js +58 -0
- package/lib/providers/ActivityTree/private/useActivityTreeWithRenderer.d.ts +5 -0
- package/lib/providers/ActivityTree/private/useActivityTreeWithRenderer.d.ts.map +1 -0
- package/lib/providers/ActivityTree/private/useActivityTreeWithRenderer.js +166 -0
- package/lib/providers/ActivityTree/private/useContext.d.ts +3 -0
- package/lib/providers/ActivityTree/private/useContext.d.ts.map +1 -0
- package/lib/providers/ActivityTree/private/useContext.js +24 -0
- package/lib/providers/ActivityTree/useActivityTreeWithRenderer.d.ts +8 -0
- package/lib/providers/ActivityTree/useActivityTreeWithRenderer.d.ts.map +1 -0
- package/lib/providers/ActivityTree/useActivityTreeWithRenderer.js +17 -0
- package/lib/providers/LiveRegionTwin/LiveRegionTwinComposer.d.ts +35 -0
- package/lib/providers/LiveRegionTwin/LiveRegionTwinComposer.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/LiveRegionTwinComposer.js +156 -0
- package/lib/providers/LiveRegionTwin/private/Context.d.ts +10 -0
- package/lib/providers/LiveRegionTwin/private/Context.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/private/Context.js +13 -0
- package/lib/providers/LiveRegionTwin/private/LiveRegionTwinContainer.d.ts +11 -0
- package/lib/providers/LiveRegionTwin/private/LiveRegionTwinContainer.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/private/LiveRegionTwinContainer.js +86 -0
- package/lib/providers/LiveRegionTwin/private/types.d.ts +8 -0
- package/lib/providers/LiveRegionTwin/private/types.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/private/types.js +2 -0
- package/lib/providers/LiveRegionTwin/private/useContext.d.ts +3 -0
- package/lib/providers/LiveRegionTwin/private/useContext.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/private/useContext.js +24 -0
- package/lib/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.d.ts +2 -0
- package/lib/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.js +24 -0
- package/lib/providers/LiveRegionTwin/private/useStaticElementEntries.d.ts +3 -0
- package/lib/providers/LiveRegionTwin/private/useStaticElementEntries.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/private/useStaticElementEntries.js +15 -0
- package/lib/providers/LiveRegionTwin/useQueueStaticElement.d.ts +8 -0
- package/lib/providers/LiveRegionTwin/useQueueStaticElement.d.ts.map +1 -0
- package/lib/providers/LiveRegionTwin/useQueueStaticElement.js +20 -0
- package/lib/providers/TranscriptFocus/TranscriptFocusComposer.d.ts +7 -0
- package/lib/providers/TranscriptFocus/TranscriptFocusComposer.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/TranscriptFocusComposer.js +184 -0
- package/lib/providers/TranscriptFocus/private/Context.d.ts +12 -0
- package/lib/providers/TranscriptFocus/private/Context.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/private/Context.js +13 -0
- package/lib/providers/TranscriptFocus/private/useContext.d.ts +2 -0
- package/lib/providers/TranscriptFocus/private/useContext.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/private/useContext.js +24 -0
- package/lib/providers/TranscriptFocus/useActiveDescendantId.d.ts +2 -0
- package/lib/providers/TranscriptFocus/useActiveDescendantId.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/useActiveDescendantId.js +15 -0
- package/lib/providers/TranscriptFocus/useFocusByActivityKey.d.ts +8 -0
- package/lib/providers/TranscriptFocus/useFocusByActivityKey.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/useFocusByActivityKey.js +21 -0
- package/lib/providers/TranscriptFocus/useFocusRelativeActivity.d.ts +2 -0
- package/lib/providers/TranscriptFocus/useFocusRelativeActivity.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/useFocusRelativeActivity.js +15 -0
- package/lib/providers/TranscriptFocus/useFocusedActivityKey.d.ts +2 -0
- package/lib/providers/TranscriptFocus/useFocusedActivityKey.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/useFocusedActivityKey.js +15 -0
- package/lib/providers/TranscriptFocus/useFocusedExplicitly.d.ts +2 -0
- package/lib/providers/TranscriptFocus/useFocusedExplicitly.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/useFocusedExplicitly.js +15 -0
- package/lib/providers/TranscriptFocus/useGetDescendantIdByActivityKey.d.ts +2 -0
- package/lib/providers/TranscriptFocus/useGetDescendantIdByActivityKey.d.ts.map +1 -0
- package/lib/providers/TranscriptFocus/useGetDescendantIdByActivityKey.js +15 -0
- package/lib/tsconfig.json +1 -1
- package/lib/types/ScrollPosition.d.ts +6 -0
- package/lib/types/ScrollPosition.d.ts.map +1 -0
- package/lib/types/ScrollPosition.js +2 -0
- package/package.json +33 -40
- package/src/Activity/{Avatar.js → Avatar.tsx} +9 -2
- package/src/Activity/{Bubble.js → Bubble.tsx} +10 -2
- package/src/Activity/CarouselFilmStrip.js +20 -29
- package/src/Activity/CarouselFilmStripAttachment.js +91 -0
- package/src/Activity/{Speak.js → Speak.tsx} +12 -5
- package/src/Activity/{StackedLayout.js → StackedLayout.tsx} +46 -20
- package/src/Attachment/Assets/DownloadIcon.js +8 -1
- package/src/Attachment/{AudioContent.js → AudioContent.tsx} +12 -3
- package/src/Attachment/FileAttachment.js +1 -1
- package/src/Attachment/{FileContent.js → FileContent.tsx} +22 -7
- package/src/Attachment/{HTMLVideoContent.js → HTMLVideoContent.tsx} +10 -2
- package/src/Attachment/{ImageContent.js → ImageContent.tsx} +7 -2
- package/src/Attachment/{TextContent.js → TextContent.tsx} +14 -7
- package/src/Attachment/{VideoContent.js → VideoContent.tsx} +10 -2
- package/src/Attachment/{VimeoContent.js → VimeoContent.tsx} +15 -8
- package/src/Attachment/{YouTubeContent.js → YouTubeContent.tsx} +12 -5
- package/src/{BasicSendBox.js → BasicSendBox.tsx} +9 -5
- package/src/BasicToaster.js +9 -5
- package/src/BasicTranscript.tsx +878 -0
- package/src/{BasicTypingIndicator.js → BasicTypingIndicator.tsx} +4 -3
- package/src/{BasicWebChat.js → BasicWebChat.tsx} +13 -4
- package/src/{Composer.js → Composer.tsx} +82 -71
- package/src/Dictation.js +13 -4
- package/src/{ErrorBox.js → ErrorBox.tsx} +7 -2
- package/src/Middleware/Activity/createCoreMiddleware.tsx +78 -0
- package/src/Middleware/ActivityStatus/SendStatus/{SendStatus.js → SendStatus.tsx} +8 -3
- package/src/Middleware/ActivityStatus/{Timestamp.js → Timestamp.tsx} +8 -2
- package/src/Middleware/ActivityStatus/{createCoreMiddleware.js → createCoreMiddleware.tsx} +3 -1
- package/src/Middleware/ActivityStatus/createSendStatusMiddleware.js +10 -6
- package/src/Middleware/ActivityStatus/createTimestampMiddleware.js +10 -8
- package/src/Middleware/Attachment/createCoreMiddleware.tsx +44 -0
- package/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.tsx +40 -0
- package/src/Middleware/Avatar/{createCoreMiddleware.js → createCoreMiddleware.tsx} +19 -11
- package/src/Middleware/CardAction/createCoreMiddleware.js +51 -42
- package/src/Middleware/GroupActivities/createCoreMiddleware.js +6 -4
- package/src/Middleware/ScrollToEndButton/ScrollToEndButton.js +45 -0
- package/src/Middleware/ScrollToEndButton/createScrollToEndButtonMiddleware.ts +19 -0
- package/src/Middleware/Toast/createCoreMiddleware.tsx +24 -0
- package/src/Middleware/TypingIndicator/{createCoreMiddleware.js → createCoreMiddleware.tsx} +10 -5
- package/src/{ReactWebChat.js → ReactWebChat.tsx} +25 -7
- package/src/ScreenReaderActivity.js +65 -40
- package/src/{ScreenReaderText.js → ScreenReaderText.tsx} +27 -9
- package/src/SendBox/Assets/AttachmentIcon.js +1 -1
- package/src/SendBox/Assets/MicrophoneIcon.js +1 -1
- package/src/SendBox/{AutoResizeTextArea.js → AutoResizeTextArea.tsx} +30 -4
- package/src/SendBox/{DictationInterims.js → DictationInterims.tsx} +6 -2
- package/src/SendBox/{IconButton.js → IconButton.tsx} +19 -3
- package/src/SendBox/{MicrophoneButton.js → MicrophoneButton.tsx} +35 -25
- package/src/SendBox/{SendButton.js → SendButton.tsx} +8 -3
- package/src/SendBox/{SuggestedAction.js → SuggestedAction.tsx} +62 -39
- package/src/SendBox/{SuggestedActions.js → SuggestedActions.tsx} +70 -22
- package/src/SendBox/{TextBox.js → TextBox.tsx} +21 -7
- package/src/SendBox/{UploadButton.js → UploadButton.tsx} +7 -3
- package/src/Styles/StyleSet/BasicTranscript.ts +34 -20
- package/src/Styles/StyleSet/Bubble.ts +0 -1
- package/src/Styles/StyleSet/CarouselFilmStrip.ts +12 -30
- package/src/Styles/StyleSet/CarouselFilmStripAttachment.ts +57 -0
- package/src/Styles/StyleSet/KeyboardHelp.ts +157 -0
- package/src/Styles/StyleSet/ScrollToEndButton.ts +33 -31
- package/src/Styles/StyleSet/SendBoxButton.ts +84 -13
- package/src/Styles/StyleSet/SendBoxTextBox.ts +1 -2
- package/src/Styles/StyleSet/StackedLayout.ts +13 -11
- package/src/Styles/StyleSet/SuggestedAction.ts +130 -43
- package/src/Styles/StyleSet/SuggestedActions.ts +13 -5
- package/src/Styles/createStyleSet.ts +43 -40
- package/src/Styles/mirrorStyle.js +10 -2
- package/src/Toast/CollapseIcon.js +9 -1
- package/src/Toast/DismissIcon.js +9 -1
- package/src/Toast/ExpandIcon.js +9 -1
- package/src/Toast/NotificationIcon.js +4 -1
- package/src/Toast/createToastMiddleware.tsx +15 -0
- package/src/Transcript/ActivityRow.tsx +124 -0
- package/src/Transcript/ActivityTextAlt.tsx +32 -0
- package/src/Transcript/FocusTrap.tsx +64 -0
- package/src/Transcript/KeyboardHelp.tsx +282 -0
- package/src/Transcript/LiveRegionTranscript.tsx +181 -0
- package/src/Transcript/types.ts +1 -0
- package/src/Transcript/useActivityAccessibleName.ts +85 -0
- package/src/Utils/{AccessibleButton.js → AccessibleButton.tsx} +19 -4
- package/src/Utils/{AccessibleInputText.js → AccessibleInputText.tsx} +48 -5
- package/src/Utils/{AccessibleTextArea.js → AccessibleTextArea.tsx} +67 -6
- package/src/Utils/{FocusRedirector.js → FocusRedirector.tsx} +21 -8
- package/src/Utils/InlineMarkdown.js +18 -2
- package/src/Utils/TypeFocusSink/FocusBox.js +4 -4
- package/src/Utils/TypeFocusSink/getTabIndex.ts +1 -1
- package/src/Utils/TypeFocusSink/inputtableKey.ts +5 -1
- package/src/Utils/activityAltText.ts +135 -0
- package/src/Utils/createCustomEvent.js +7 -1
- package/src/Utils/detectBrowser.js +2 -1
- package/src/Utils/findAncestor.ts +12 -0
- package/src/Utils/getActivityUniqueId.ts +5 -0
- package/src/Utils/intersectionOf.spec.js +2 -0
- package/src/Utils/intersectionOf.ts +14 -0
- package/src/Utils/isZeroOrPositive.ts +7 -0
- package/src/Utils/mapMap.js +7 -1
- package/src/Utils/mapMap.spec.js +2 -0
- package/src/Utils/removeInline.spec.js +2 -0
- package/src/Utils/scrollIntoViewWithBlockNearest.ts +20 -0
- package/src/Utils/shallowEquals.js +8 -1
- package/src/Utils/{singleToArray.js → singleToArray.ts} +1 -1
- package/src/Utils/supportPseudoClass.ts +17 -0
- package/src/Utils/{tabbableElements.js → tabbableElements.ts} +6 -5
- package/src/Utils/walkMarkdownTokens.spec.js +3 -3
- package/src/connectToWebChat.js +11 -4
- package/src/hooks/{index.js → index.ts} +1 -0
- package/src/hooks/internal/BypassSpeechSynthesisPonyfill.js +70 -17
- package/src/hooks/internal/useChanged.ts +17 -0
- package/src/hooks/internal/useDispatchScrollPosition.js +1 -3
- package/src/hooks/internal/useDispatchTranscriptFocusByActivityKey.ts +5 -0
- package/src/hooks/internal/useFocusVisible.ts +22 -0
- package/src/hooks/internal/useMemoWithPrevious.ts +16 -0
- package/src/hooks/internal/useMemoize.spec.js +3 -1
- package/src/hooks/internal/useMemoize.ts +53 -0
- package/src/hooks/internal/useObserveFocusVisible.ts +252 -0
- package/src/hooks/internal/usePrevious.ts +12 -0
- package/src/hooks/internal/useResumeAudioContext.ts +7 -0
- package/src/hooks/internal/useScrollRelative.js +4 -3
- package/src/hooks/internal/useStateRef.ts +31 -0
- package/src/hooks/internal/{useUniqueId.js → useUniqueId.ts} +1 -1
- package/src/hooks/internal/useValueRef.ts +22 -0
- package/src/hooks/{useDictateAbortable.js → useDictateAbortable.ts} +1 -1
- package/src/hooks/{useFocus.js → useFocus.ts} +1 -1
- package/src/hooks/{useFocusSendBox.js → useFocusSendBox.ts} +2 -1
- package/src/hooks/{useObserveScrollPosition.js → useObserveScrollPosition.ts} +6 -1
- package/src/hooks/{useObserveTranscriptFocus.js → useObserveTranscriptFocus.ts} +6 -1
- package/src/hooks/useRenderMarkdownAsHTML.ts +23 -0
- package/src/hooks/{useScrollDown.js → useScrollDown.ts} +1 -1
- package/src/hooks/useScrollTo.ts +16 -0
- package/src/hooks/useScrollToEnd.ts +12 -0
- package/src/hooks/{useScrollUp.js → useScrollUp.ts} +1 -1
- package/src/hooks/{useSendFiles.js → useSendFiles.ts} +3 -2
- package/src/hooks/{useStyleSet.js → useStyleSet.ts} +1 -1
- package/src/hooks/useWebSpeechPonyfill.ts +7 -0
- package/src/index.ts +7 -12
- package/src/providers/ActivityTree/ActivityTreeComposer.tsx +74 -0
- package/src/providers/ActivityTree/private/Context.ts +12 -0
- package/src/providers/ActivityTree/private/types.ts +12 -0
- package/src/providers/ActivityTree/private/useActivitiesWithRenderer.ts +66 -0
- package/src/providers/ActivityTree/private/useActivityTreeWithRenderer.ts +140 -0
- package/src/providers/ActivityTree/private/useContext.ts +15 -0
- package/src/providers/ActivityTree/useActivityTreeWithRenderer.ts +16 -0
- package/src/providers/LiveRegionTwin/LiveRegionTwinComposer.tsx +154 -0
- package/src/providers/LiveRegionTwin/private/Context.ts +15 -0
- package/src/providers/LiveRegionTwin/private/LiveRegionTwinContainer.tsx +64 -0
- package/src/providers/LiveRegionTwin/private/types.ts +10 -0
- package/src/providers/LiveRegionTwin/private/useContext.ts +15 -0
- package/src/providers/LiveRegionTwin/private/useMarkAllAsRenderedEffect.ts +13 -0
- package/src/providers/LiveRegionTwin/private/useStaticElementEntries.ts +7 -0
- package/src/providers/LiveRegionTwin/useQueueStaticElement.ts +12 -0
- package/src/providers/TranscriptFocus/TranscriptFocusComposer.tsx +180 -0
- package/src/providers/TranscriptFocus/private/Context.ts +16 -0
- package/src/providers/TranscriptFocus/private/useContext.ts +13 -0
- package/src/providers/TranscriptFocus/useActiveDescendantId.ts +5 -0
- package/src/providers/TranscriptFocus/useFocusByActivityKey.ts +14 -0
- package/src/providers/TranscriptFocus/useFocusRelativeActivity.ts +5 -0
- package/src/providers/TranscriptFocus/useFocusedActivityKey.ts +5 -0
- package/src/providers/TranscriptFocus/useFocusedExplicitly.ts +5 -0
- package/src/providers/TranscriptFocus/useGetDescendantIdByActivityKey.ts +5 -0
- package/src/tsconfig.json +1 -1
- package/src/types/ScrollPosition.ts +6 -0
- package/.eslintignore +0 -9
- package/lib/Activity/ScrollToEndButton.js +0 -81
- package/lib/Attachment/Assets/ErrorIcon.js +0 -22
- package/lib/Utils/findLastIndex.js +0 -32
- package/lib/Utils/remarkStripMarkdown.js +0 -26
- package/lib/hooks/internal/useAcknowledgedActivity.js +0 -90
- package/lib/hooks/internal/useDispatchTranscriptFocus.js +0 -19
- package/lib/hooks/internal/useStripMarkdown.js +0 -19
- package/src/Activity/ScrollToEndButton.js +0 -58
- package/src/Attachment/Assets/ErrorIcon.js +0 -9
- package/src/BasicTranscript.js +0 -1123
- package/src/Middleware/Activity/createCoreMiddleware.js +0 -71
- package/src/Middleware/Attachment/createCoreMiddleware.js +0 -43
- package/src/Middleware/AttachmentForScreenReader/createCoreMiddleware.js +0 -37
- package/src/Middleware/Toast/createCoreMiddleware.js +0 -20
- package/src/Toast/createToastMiddleware.js +0 -11
- package/src/Utils/findLastIndex.js +0 -11
- package/src/Utils/findLastIndex.spec.js +0 -29
- package/src/Utils/getActivityUniqueId.js +0 -3
- package/src/Utils/intersectionOf.js +0 -11
- package/src/Utils/isZeroOrPositive.js +0 -4
- package/src/Utils/remarkStripMarkdown.js +0 -13
- package/src/hooks/internal/useAcknowledgedActivity.js +0 -65
- package/src/hooks/internal/useChanged.js +0 -10
- package/src/hooks/internal/useDispatchTranscriptFocus.js +0 -7
- package/src/hooks/internal/useMemoize.js +0 -37
- package/src/hooks/internal/useStripMarkdown.js +0 -7
- package/src/hooks/useRenderMarkdownAsHTML.js +0 -20
- package/src/hooks/useScrollTo.js +0 -11
- package/src/hooks/useScrollToEnd.js +0 -11
- package/src/hooks/useWebSpeechPonyfill.js +0 -5
- package/src/index.tsx +0 -35
package/src/BasicTranscript.js
DELETED
|
@@ -1,1123 +0,0 @@
|
|
|
1
|
-
/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1, 2, 5, 36] }] */
|
|
2
|
-
|
|
3
|
-
import { hooks } from 'botframework-webchat-api';
|
|
4
|
-
import {
|
|
5
|
-
Composer as ReactScrollToBottomComposer,
|
|
6
|
-
Panel as ReactScrollToBottomPanel,
|
|
7
|
-
useAnimatingToEnd,
|
|
8
|
-
useObserveScrollPosition,
|
|
9
|
-
useScrollTo,
|
|
10
|
-
useScrollToEnd,
|
|
11
|
-
useSticky
|
|
12
|
-
} from 'react-scroll-to-bottom';
|
|
13
|
-
import classNames from 'classnames';
|
|
14
|
-
import PropTypes from 'prop-types';
|
|
15
|
-
import random from 'math-random';
|
|
16
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
17
|
-
|
|
18
|
-
import BasicTypingIndicator from './BasicTypingIndicator';
|
|
19
|
-
import Fade from './Utils/Fade';
|
|
20
|
-
import FocusRedirector from './Utils/FocusRedirector';
|
|
21
|
-
import getActivityUniqueId from './Utils/getActivityUniqueId';
|
|
22
|
-
import getTabIndex from './Utils/TypeFocusSink/getTabIndex';
|
|
23
|
-
import inputtableKey from './Utils/TypeFocusSink/inputtableKey';
|
|
24
|
-
import intersectionOf from './Utils/intersectionOf';
|
|
25
|
-
import isZeroOrPositive from './Utils/isZeroOrPositive';
|
|
26
|
-
import removeInline from './Utils/removeInline';
|
|
27
|
-
import ScreenReaderActivity from './ScreenReaderActivity';
|
|
28
|
-
import ScreenReaderText from './ScreenReaderText';
|
|
29
|
-
import ScrollToEndButton from './Activity/ScrollToEndButton';
|
|
30
|
-
import SpeakActivity from './Activity/Speak';
|
|
31
|
-
import tabbableElements from './Utils/tabbableElements';
|
|
32
|
-
import useAcknowledgedActivity from './hooks/internal/useAcknowledgedActivity';
|
|
33
|
-
import useDispatchScrollPosition from './hooks/internal/useDispatchScrollPosition';
|
|
34
|
-
import useDispatchTranscriptFocus from './hooks/internal/useDispatchTranscriptFocus';
|
|
35
|
-
import useFocus from './hooks/useFocus';
|
|
36
|
-
import useMemoize from './hooks/internal/useMemoize';
|
|
37
|
-
import useRegisterFocusTranscript from './hooks/internal/useRegisterFocusTranscript';
|
|
38
|
-
import useRegisterScrollRelative from './hooks/internal/useRegisterScrollRelative';
|
|
39
|
-
import useRegisterScrollTo from './hooks/internal/useRegisterScrollTo';
|
|
40
|
-
import useRegisterScrollToEnd from './hooks/internal/useRegisterScrollToEnd';
|
|
41
|
-
import useStyleSet from './hooks/useStyleSet';
|
|
42
|
-
import useStyleToEmotionObject from './hooks/internal/useStyleToEmotionObject';
|
|
43
|
-
import useUniqueId from './hooks/internal/useUniqueId';
|
|
44
|
-
|
|
45
|
-
const {
|
|
46
|
-
useActivities,
|
|
47
|
-
useCreateActivityRenderer,
|
|
48
|
-
useCreateActivityStatusRenderer,
|
|
49
|
-
useCreateAvatarRenderer,
|
|
50
|
-
useDirection,
|
|
51
|
-
useGroupActivities,
|
|
52
|
-
useLocalizer,
|
|
53
|
-
useStyleOptions
|
|
54
|
-
} = hooks;
|
|
55
|
-
|
|
56
|
-
const ROOT_STYLE = {
|
|
57
|
-
'&.webchat__basic-transcript': {
|
|
58
|
-
display: 'flex',
|
|
59
|
-
flexDirection: 'column',
|
|
60
|
-
overflow: 'hidden',
|
|
61
|
-
// Make sure to set "position: relative" here to form another stacking context for the scroll-to-end button.
|
|
62
|
-
// Stacking context help isolating elements that use "z-index" from global pollution.
|
|
63
|
-
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
|
|
64
|
-
position: 'relative',
|
|
65
|
-
|
|
66
|
-
'& .webchat__basic-transcript__filler': {
|
|
67
|
-
flex: 1
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
'& .webchat__basic-transcript__scrollable': {
|
|
71
|
-
display: 'flex',
|
|
72
|
-
flexDirection: 'column',
|
|
73
|
-
overflowX: 'hidden',
|
|
74
|
-
WebkitOverflowScrolling: 'touch'
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
'& .webchat__basic-transcript__transcript': {
|
|
78
|
-
listStyleType: 'none'
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
function validateAllActivitiesTagged(activities, bins) {
|
|
84
|
-
return activities.every(activity => bins.some(bin => bin.includes(activity)));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const InternalTranscript = ({ activityElementsRef, className }) => {
|
|
88
|
-
const [{ basicTranscript: basicTranscriptStyleSet }] = useStyleSet();
|
|
89
|
-
const [
|
|
90
|
-
{ bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, internalLiveRegionFadeAfter, showAvatarInGroup }
|
|
91
|
-
] = useStyleOptions();
|
|
92
|
-
const [focusedActivityKey, setFocusedActivityKey] = useState();
|
|
93
|
-
const [activities] = useActivities();
|
|
94
|
-
const [direction] = useDirection();
|
|
95
|
-
const createActivityRenderer = useCreateActivityRenderer();
|
|
96
|
-
const createActivityStatusRenderer = useCreateActivityStatusRenderer();
|
|
97
|
-
const createAvatarRenderer = useCreateAvatarRenderer();
|
|
98
|
-
const focus = useFocus();
|
|
99
|
-
const groupActivities = useGroupActivities();
|
|
100
|
-
const localize = useLocalizer();
|
|
101
|
-
const rootClassName = useStyleToEmotionObject()(ROOT_STYLE) + '';
|
|
102
|
-
const rootElementRef = useRef();
|
|
103
|
-
const terminatorRef = useRef();
|
|
104
|
-
|
|
105
|
-
const activityInteractiveAlt = localize('ACTIVITY_INTERACTIVE_LABEL_ALT');
|
|
106
|
-
const terminatorText = localize('TRANSCRIPT_TERMINATOR_TEXT');
|
|
107
|
-
const transcriptAriaLabel = localize('TRANSCRIPT_ARIA_LABEL_ALT');
|
|
108
|
-
const transcriptRoleDescription = localize('TRANSCRIPT_ARIA_ROLE_ALT');
|
|
109
|
-
|
|
110
|
-
const hideAllTimestamps = groupTimestamp === false;
|
|
111
|
-
|
|
112
|
-
// Gets renderer for every activity.
|
|
113
|
-
// Activities that are not visible will return a falsy renderer.
|
|
114
|
-
|
|
115
|
-
// Converted from createActivityRenderer({ activity, nextVisibleActivity }) to createActivityRenderer(activity, nextVisibleActivity).
|
|
116
|
-
// This is for the memoization function to cache the arguments. Memoizer can only cache literal arguments.
|
|
117
|
-
const createActivityRendererWithLiteralArgs = useCallback(
|
|
118
|
-
(activity, nextVisibleActivity) => createActivityRenderer({ activity, nextVisibleActivity }),
|
|
119
|
-
[createActivityRenderer]
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// Create a memoized context of the createActivityRenderer function.
|
|
123
|
-
const activitiesWithRenderer = useMemoize(
|
|
124
|
-
createActivityRendererWithLiteralArgs,
|
|
125
|
-
createActivityRendererWithLiteralArgsMemoized => {
|
|
126
|
-
// All calls to createActivityRendererWithLiteralArgsMemoized() in this function will be memoized (LRU = 1).
|
|
127
|
-
// In the next render cycle, calls to createActivityRendererWithLiteralArgsMemoized() might return the memoized result instead.
|
|
128
|
-
// This is an improvement to React useMemo(), because it only allows 1 memoization.
|
|
129
|
-
// useMemoize() allows any number of memoization.
|
|
130
|
-
|
|
131
|
-
const activitiesWithRenderer = [];
|
|
132
|
-
let nextVisibleActivity;
|
|
133
|
-
|
|
134
|
-
for (let index = activities.length - 1; index >= 0; index--) {
|
|
135
|
-
const activity = activities[index];
|
|
136
|
-
const renderActivity = createActivityRendererWithLiteralArgsMemoized(activity, nextVisibleActivity);
|
|
137
|
-
|
|
138
|
-
if (renderActivity) {
|
|
139
|
-
activitiesWithRenderer.splice(0, 0, {
|
|
140
|
-
activity,
|
|
141
|
-
renderActivity
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
nextVisibleActivity = activity;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return activitiesWithRenderer;
|
|
149
|
-
},
|
|
150
|
-
[activities]
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const visibleActivities = useMemo(() => activitiesWithRenderer.map(({ activity }) => activity), [
|
|
154
|
-
activitiesWithRenderer
|
|
155
|
-
]);
|
|
156
|
-
|
|
157
|
-
// Tag activities based on types.
|
|
158
|
-
// The default implementation tag into 2 types: sender and status.
|
|
159
|
-
|
|
160
|
-
const { activitiesGroupBySender, activitiesGroupByStatus } = useMemo(() => {
|
|
161
|
-
const { sender: activitiesGroupBySender, status: activitiesGroupByStatus } = groupActivities({
|
|
162
|
-
activities: visibleActivities
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
if (!validateAllActivitiesTagged(visibleActivities, activitiesGroupBySender)) {
|
|
166
|
-
console.warn(
|
|
167
|
-
'botframework-webchat: Not every activities are grouped in the "sender" property. Please fix "groupActivitiesMiddleware" and group every activities.'
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (!validateAllActivitiesTagged(visibleActivities, activitiesGroupByStatus)) {
|
|
172
|
-
console.warn(
|
|
173
|
-
'botframework-webchat: Not every activities are grouped in the "status" property. Please fix "groupActivitiesMiddleware" and group every activities.'
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
activitiesGroupBySender,
|
|
179
|
-
activitiesGroupByStatus
|
|
180
|
-
};
|
|
181
|
-
}, [groupActivities, visibleActivities]);
|
|
182
|
-
|
|
183
|
-
// Create a tree of activities with 2 dimensions: sender, followed by status.
|
|
184
|
-
|
|
185
|
-
const activityTree = useMemo(() => {
|
|
186
|
-
const visibleActivitiesPendingGrouping = [...visibleActivities];
|
|
187
|
-
const activityTree = [];
|
|
188
|
-
|
|
189
|
-
while (visibleActivitiesPendingGrouping.length) {
|
|
190
|
-
const [activity] = visibleActivitiesPendingGrouping;
|
|
191
|
-
const senderTree = [];
|
|
192
|
-
const activitiesWithSameSender = activitiesGroupBySender.find(activities => activities.includes(activity));
|
|
193
|
-
|
|
194
|
-
activityTree.push(senderTree);
|
|
195
|
-
|
|
196
|
-
activitiesWithSameSender.forEach(activity => {
|
|
197
|
-
const activitiesWithSameStatus = activitiesGroupByStatus.find(activities => activities.includes(activity));
|
|
198
|
-
|
|
199
|
-
const activitiesWithSameSenderAndStatus = intersectionOf(
|
|
200
|
-
visibleActivitiesPendingGrouping,
|
|
201
|
-
activitiesWithSameSender,
|
|
202
|
-
activitiesWithSameStatus
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
if (activitiesWithSameSenderAndStatus.length) {
|
|
206
|
-
senderTree.push(activitiesWithSameSenderAndStatus);
|
|
207
|
-
removeInline(visibleActivitiesPendingGrouping, ...activitiesWithSameSenderAndStatus);
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Assertion: All activities in visibleActivities, must be assigned to the activityTree
|
|
213
|
-
if (
|
|
214
|
-
!visibleActivities.every(activity =>
|
|
215
|
-
activityTree.some(activitiesWithSameSender =>
|
|
216
|
-
activitiesWithSameSender.some(activitiesWithSameSenderAndStatus =>
|
|
217
|
-
activitiesWithSameSenderAndStatus.includes(activity)
|
|
218
|
-
)
|
|
219
|
-
)
|
|
220
|
-
)
|
|
221
|
-
) {
|
|
222
|
-
console.warn('botframework-webchat internal: Not all visible activities are grouped in the activityTree.', {
|
|
223
|
-
visibleActivities,
|
|
224
|
-
activityTree
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return activityTree;
|
|
229
|
-
}, [activitiesGroupBySender, activitiesGroupByStatus, visibleActivities]);
|
|
230
|
-
|
|
231
|
-
// Flatten the tree back into an array with information related to rendering.
|
|
232
|
-
|
|
233
|
-
const renderingElements = useMemo(() => {
|
|
234
|
-
const renderingElements = [];
|
|
235
|
-
const topSideBotNub = isZeroOrPositive(bubbleNubOffset);
|
|
236
|
-
const topSideUserNub = isZeroOrPositive(bubbleFromUserNubOffset);
|
|
237
|
-
|
|
238
|
-
activityTree.forEach(activitiesWithSameSender => {
|
|
239
|
-
const [[firstActivity]] = activitiesWithSameSender;
|
|
240
|
-
const renderAvatar = createAvatarRenderer({ activity: firstActivity });
|
|
241
|
-
|
|
242
|
-
activitiesWithSameSender.forEach((activitiesWithSameSenderAndStatus, indexWithinSenderGroup) => {
|
|
243
|
-
const firstInSenderGroup = !indexWithinSenderGroup;
|
|
244
|
-
const lastInSenderGroup = indexWithinSenderGroup === activitiesWithSameSender.length - 1;
|
|
245
|
-
|
|
246
|
-
activitiesWithSameSenderAndStatus.forEach((activity, indexWithinSenderAndStatusGroup) => {
|
|
247
|
-
// We only show the timestamp at the end of the sender group. But we always show the "Send failed, retry" prompt.
|
|
248
|
-
const renderActivityStatus = createActivityStatusRenderer({
|
|
249
|
-
activity
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
const firstInSenderAndStatusGroup = !indexWithinSenderAndStatusGroup;
|
|
253
|
-
const lastInSenderAndStatusGroup =
|
|
254
|
-
indexWithinSenderAndStatusGroup === activitiesWithSameSenderAndStatus.length - 1;
|
|
255
|
-
|
|
256
|
-
const { renderActivity } = activitiesWithRenderer.find(entry => entry.activity === activity);
|
|
257
|
-
const key = getActivityUniqueId(activity) || renderingElements.length;
|
|
258
|
-
const {
|
|
259
|
-
channelData: { messageBack: { displayText: messageBackDisplayText } = {} } = {},
|
|
260
|
-
from: { role },
|
|
261
|
-
text
|
|
262
|
-
} = activity;
|
|
263
|
-
|
|
264
|
-
const topSideNub = role === 'user' ? topSideUserNub : topSideBotNub;
|
|
265
|
-
|
|
266
|
-
let showCallout;
|
|
267
|
-
|
|
268
|
-
// Depending on the "showAvatarInGroup" setting, the avatar will render in different positions.
|
|
269
|
-
if (showAvatarInGroup === 'sender') {
|
|
270
|
-
if (topSideNub) {
|
|
271
|
-
showCallout = firstInSenderGroup && firstInSenderAndStatusGroup;
|
|
272
|
-
} else {
|
|
273
|
-
showCallout = lastInSenderGroup && lastInSenderAndStatusGroup;
|
|
274
|
-
}
|
|
275
|
-
} else if (showAvatarInGroup === 'status') {
|
|
276
|
-
if (topSideNub) {
|
|
277
|
-
showCallout = firstInSenderAndStatusGroup;
|
|
278
|
-
} else {
|
|
279
|
-
showCallout = lastInSenderAndStatusGroup;
|
|
280
|
-
}
|
|
281
|
-
} else {
|
|
282
|
-
showCallout = true;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const focusActivity = () => {
|
|
286
|
-
setFocusedActivityKey(getActivityUniqueId(activity));
|
|
287
|
-
|
|
288
|
-
// IE11 need to manually focus on the transcript.
|
|
289
|
-
const { current: rootElement } = rootElementRef;
|
|
290
|
-
|
|
291
|
-
rootElement && rootElement.focus();
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
renderingElements.push({
|
|
295
|
-
activity,
|
|
296
|
-
|
|
297
|
-
// After the element is mounted, set it to activityElementsRef.
|
|
298
|
-
callbackRef: activityElement => {
|
|
299
|
-
const entry = activityElementsRef.current.find(({ activityID }) => activityID === activity.id);
|
|
300
|
-
|
|
301
|
-
if (entry) {
|
|
302
|
-
entry.element = activityElement;
|
|
303
|
-
}
|
|
304
|
-
},
|
|
305
|
-
|
|
306
|
-
// Calling this function will put the focus on the transcript and the activity.
|
|
307
|
-
focusActivity,
|
|
308
|
-
|
|
309
|
-
// When a child of the activity receives focus, notify the transcript to set the aria-activedescendant to this activity.
|
|
310
|
-
handleFocus: () => {
|
|
311
|
-
setFocusedActivityKey(getActivityUniqueId(activity));
|
|
312
|
-
},
|
|
313
|
-
|
|
314
|
-
handleKeyDown: event => {
|
|
315
|
-
if (event.key === 'Escape') {
|
|
316
|
-
event.preventDefault();
|
|
317
|
-
event.stopPropagation();
|
|
318
|
-
|
|
319
|
-
setFocusedActivityKey(getActivityUniqueId(activity));
|
|
320
|
-
|
|
321
|
-
const { current } = rootElementRef;
|
|
322
|
-
|
|
323
|
-
current && current.focus();
|
|
324
|
-
}
|
|
325
|
-
},
|
|
326
|
-
|
|
327
|
-
// For accessibility: when the user press up/down arrow keys, we put a visual focus indicator around the focused activity.
|
|
328
|
-
// We should do the same for mouse, that is why we have the click handler here.
|
|
329
|
-
// We are doing it in event capture phase to prevent other components from stopping event propagation to us.
|
|
330
|
-
handleMouseDownCapture: ({ target }) => {
|
|
331
|
-
const tabIndex = getTabIndex(target);
|
|
332
|
-
|
|
333
|
-
if (typeof tabIndex !== 'number' || tabIndex < 0 || target.getAttribute('aria-disabled') === 'true') {
|
|
334
|
-
focusActivity();
|
|
335
|
-
}
|
|
336
|
-
},
|
|
337
|
-
|
|
338
|
-
// "hideTimestamp" is a render-time parameter for renderActivityStatus().
|
|
339
|
-
// If true, it will hide the timestamp, but it will continue to show the
|
|
340
|
-
// retry prompt. And show the screen reader version of the timestamp.
|
|
341
|
-
hideTimestamp:
|
|
342
|
-
hideAllTimestamps || indexWithinSenderAndStatusGroup !== activitiesWithSameSenderAndStatus.length - 1,
|
|
343
|
-
key,
|
|
344
|
-
|
|
345
|
-
// When "liveRegionKey" changes, it will show up in the live region momentarily.
|
|
346
|
-
liveRegionKey: key + '|' + (messageBackDisplayText || text),
|
|
347
|
-
renderActivity,
|
|
348
|
-
renderActivityStatus,
|
|
349
|
-
renderAvatar,
|
|
350
|
-
role,
|
|
351
|
-
|
|
352
|
-
// TODO: [P2] #2858 We should use core/definitions/speakingActivity for this predicate instead
|
|
353
|
-
shouldSpeak: activity.channelData && activity.channelData.speak,
|
|
354
|
-
showCallout
|
|
355
|
-
});
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
const { current: activityElements } = activityElementsRef;
|
|
361
|
-
|
|
362
|
-
// Update activityElementRef with new sets of activity, while retaining the existing referencing element if exists.
|
|
363
|
-
activityElementsRef.current = renderingElements.map(({ activity, activity: { id }, elementId, key }) => {
|
|
364
|
-
const existingEntry = activityElements.find(entry => entry.key === key);
|
|
365
|
-
|
|
366
|
-
return {
|
|
367
|
-
activity,
|
|
368
|
-
activityID: id,
|
|
369
|
-
ariaLabelID: existingEntry
|
|
370
|
-
? existingEntry.ariaLabelID
|
|
371
|
-
: `webchat__basic-transcript__activity-label-${random().toString(36).substr(2, 5)}`,
|
|
372
|
-
element: existingEntry && existingEntry.element,
|
|
373
|
-
elementId,
|
|
374
|
-
key
|
|
375
|
-
};
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
// There must be one focused (a.k.a. aria-activedescendant) designated. We default it to the last one.
|
|
379
|
-
if (!renderingElements.find(({ focused }) => focused)) {
|
|
380
|
-
const lastElement = renderingElements[renderingElements.length - 1];
|
|
381
|
-
|
|
382
|
-
if (lastElement) {
|
|
383
|
-
lastElement.focused = true;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
return renderingElements;
|
|
388
|
-
}, [
|
|
389
|
-
activitiesWithRenderer,
|
|
390
|
-
activityElementsRef,
|
|
391
|
-
activityTree,
|
|
392
|
-
bubbleFromUserNubOffset,
|
|
393
|
-
bubbleNubOffset,
|
|
394
|
-
createActivityStatusRenderer,
|
|
395
|
-
createAvatarRenderer,
|
|
396
|
-
hideAllTimestamps,
|
|
397
|
-
rootElementRef,
|
|
398
|
-
showAvatarInGroup
|
|
399
|
-
]);
|
|
400
|
-
|
|
401
|
-
const renderingActivities = useMemo(() => renderingElements.map(({ activity }) => activity), [renderingElements]);
|
|
402
|
-
|
|
403
|
-
const scrollToBottomScrollTo = useScrollTo();
|
|
404
|
-
const scrollToBottomScrollToEnd = useScrollToEnd();
|
|
405
|
-
|
|
406
|
-
const scrollTo = useCallback(
|
|
407
|
-
(position, { behavior = 'auto' } = {}) => {
|
|
408
|
-
if (!position) {
|
|
409
|
-
throw new Error(
|
|
410
|
-
'botframework-webchat: First argument passed to "useScrollTo" must be a ScrollPosition object.'
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const { activityID, scrollTop } = position;
|
|
415
|
-
|
|
416
|
-
if (typeof scrollTop !== 'undefined') {
|
|
417
|
-
scrollToBottomScrollTo(scrollTop, { behavior });
|
|
418
|
-
} else if (typeof activityID !== 'undefined') {
|
|
419
|
-
const { current: rootElement } = rootElementRef;
|
|
420
|
-
const { element: activityElement } =
|
|
421
|
-
activityElementsRef.current.find(entry => entry.activityID === activityID) || {};
|
|
422
|
-
|
|
423
|
-
const scrollableElement = rootElement.querySelector('.webchat__basic-transcript__scrollable');
|
|
424
|
-
|
|
425
|
-
if (scrollableElement && activityElement) {
|
|
426
|
-
const [{ height: activityElementHeight, y: activityElementY }] = activityElement.getClientRects();
|
|
427
|
-
const [{ height: scrollableHeight }] = scrollableElement.getClientRects();
|
|
428
|
-
|
|
429
|
-
const activityElementOffsetTop = activityElementY + scrollableElement.scrollTop;
|
|
430
|
-
|
|
431
|
-
const scrollTop = Math.min(
|
|
432
|
-
activityElementOffsetTop,
|
|
433
|
-
activityElementOffsetTop - scrollableHeight + activityElementHeight
|
|
434
|
-
);
|
|
435
|
-
|
|
436
|
-
scrollToBottomScrollTo(scrollTop, { behavior });
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
},
|
|
440
|
-
[activityElementsRef, rootElementRef, scrollToBottomScrollTo]
|
|
441
|
-
);
|
|
442
|
-
|
|
443
|
-
const scrollRelative = useCallback(
|
|
444
|
-
(direction, { displacement } = {}) => {
|
|
445
|
-
const { current: rootElement } = rootElementRef;
|
|
446
|
-
|
|
447
|
-
if (!rootElement) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const scrollable = rootElement.querySelector('.webchat__basic-transcript__scrollable');
|
|
452
|
-
let nextScrollTop;
|
|
453
|
-
|
|
454
|
-
if (typeof displacement === 'number') {
|
|
455
|
-
nextScrollTop = scrollable.scrollTop + (direction === 'down' ? 1 : -1) * displacement;
|
|
456
|
-
} else {
|
|
457
|
-
nextScrollTop = scrollable.scrollTop + (direction === 'down' ? 1 : -1) * scrollable.offsetHeight;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
scrollTo(
|
|
461
|
-
{
|
|
462
|
-
scrollTop: Math.max(0, Math.min(scrollable.scrollHeight - scrollable.offsetHeight, nextScrollTop))
|
|
463
|
-
},
|
|
464
|
-
{ behavior: 'smooth' }
|
|
465
|
-
);
|
|
466
|
-
},
|
|
467
|
-
[rootElementRef, scrollTo]
|
|
468
|
-
);
|
|
469
|
-
|
|
470
|
-
// 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
|
-
// We call `useRegisterScrollXXX` to register a callback function, the `useScrollXXX` will multiplex the call into each instance of <BasicTranscript>.
|
|
472
|
-
useRegisterScrollTo(scrollTo);
|
|
473
|
-
useRegisterScrollToEnd(scrollToBottomScrollToEnd);
|
|
474
|
-
useRegisterScrollRelative(scrollRelative);
|
|
475
|
-
|
|
476
|
-
const dispatchScrollPosition = useDispatchScrollPosition();
|
|
477
|
-
const patchedDispatchScrollPosition = useMemo(() => {
|
|
478
|
-
if (!dispatchScrollPosition) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
return ({ scrollTop }) => {
|
|
483
|
-
const { current: rootElement } = rootElementRef;
|
|
484
|
-
|
|
485
|
-
if (!rootElement) {
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const scrollableElement = rootElement.querySelector('.webchat__basic-transcript__scrollable');
|
|
490
|
-
|
|
491
|
-
const [{ height: offsetHeight } = {}] = scrollableElement.getClientRects();
|
|
492
|
-
|
|
493
|
-
// Find the activity just above scroll view bottom.
|
|
494
|
-
// If the scroll view is already on top, get the first activity.
|
|
495
|
-
const entry = scrollableElement.scrollTop
|
|
496
|
-
? [...activityElementsRef.current].reverse().find(({ element }) => {
|
|
497
|
-
if (!element) {
|
|
498
|
-
return false;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const [{ y } = {}] = element.getClientRects();
|
|
502
|
-
|
|
503
|
-
return y < offsetHeight;
|
|
504
|
-
})
|
|
505
|
-
: activityElementsRef.current[0];
|
|
506
|
-
|
|
507
|
-
const { activityID } = entry || {};
|
|
508
|
-
|
|
509
|
-
dispatchScrollPosition({ ...(activityID ? { activityID } : {}), scrollTop });
|
|
510
|
-
};
|
|
511
|
-
}, [activityElementsRef, dispatchScrollPosition, rootElementRef]);
|
|
512
|
-
|
|
513
|
-
useObserveScrollPosition(patchedDispatchScrollPosition);
|
|
514
|
-
|
|
515
|
-
const [lastInteractedActivity] = useAcknowledgedActivity();
|
|
516
|
-
|
|
517
|
-
const indexOfLastInteractedActivity = activities.indexOf(lastInteractedActivity);
|
|
518
|
-
|
|
519
|
-
// Create a new ID for aria-activedescendant every time the active descendant change.
|
|
520
|
-
// In our design, the transcript will only have 1 focused activity and it has an ID. Other blurred activities will not have ID assigned.
|
|
521
|
-
// This help with performance.
|
|
522
|
-
// But browser usually do noop if the value of aria-activedescendant doesn't change.
|
|
523
|
-
// That means, if we assign the same ID to another element, browser will do noop.
|
|
524
|
-
// We need to generate a new ID so the browser see there is a change in aria-activedescendant value and perform accordingly.
|
|
525
|
-
const activeDescendantElementId = useMemo(
|
|
526
|
-
() => focusedActivityKey && `webchat__basic-transcript__active-descendant-${random().toString(36).substr(2, 5)}`,
|
|
527
|
-
[focusedActivityKey]
|
|
528
|
-
);
|
|
529
|
-
|
|
530
|
-
const scrollActiveDescendantIntoView = useCallback(() => {
|
|
531
|
-
const activeDescendant = activeDescendantElementId && document.getElementById(activeDescendantElementId);
|
|
532
|
-
|
|
533
|
-
// Don't scroll active descendant into view if the focus is already inside it.
|
|
534
|
-
// Otherwise, given the focus is on the send box, clicking on any <input> inside the Adaptive Cards may cause the view to move.
|
|
535
|
-
// This UX is not desirable because click should not cause scroll.
|
|
536
|
-
if (activeDescendant && !activeDescendant.contains(document.activeElement)) {
|
|
537
|
-
// Checks if scrollIntoView support options or not.
|
|
538
|
-
// - https://github.com/Modernizr/Modernizr/issues/1568#issuecomment-419457972
|
|
539
|
-
// - https://stackoverflow.com/questions/46919627/is-it-possible-to-test-for-scrollintoview-browser-compatibility
|
|
540
|
-
if ('scrollBehavior' in document.documentElement.style) {
|
|
541
|
-
activeDescendant.scrollIntoView({ block: 'nearest' });
|
|
542
|
-
} else {
|
|
543
|
-
// This is for browser that does not support options passed to scrollIntoView(), possibly IE11.
|
|
544
|
-
const scrollableElement = rootElementRef.current.querySelector('.webchat__basic-transcript__scrollable');
|
|
545
|
-
const scrollTopAtTopSide = activeDescendant.offsetTop;
|
|
546
|
-
const scrollTopAtBottomSide = activeDescendant.offsetTop + activeDescendant.offsetHeight;
|
|
547
|
-
|
|
548
|
-
if (scrollTopAtTopSide < scrollableElement.scrollTop) {
|
|
549
|
-
scrollableElement.scrollTop = scrollTopAtTopSide;
|
|
550
|
-
} else if (scrollTopAtBottomSide > scrollableElement.scrollTop + scrollableElement.offsetHeight) {
|
|
551
|
-
scrollableElement.scrollTop = scrollTopAtBottomSide - scrollableElement.offsetHeight;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}, [activeDescendantElementId, rootElementRef]);
|
|
556
|
-
|
|
557
|
-
const handleTranscriptFocus = useCallback(
|
|
558
|
-
event => {
|
|
559
|
-
const { currentTarget, target } = event;
|
|
560
|
-
|
|
561
|
-
// When focus is placed on the transcript, scroll active descendant into the view.
|
|
562
|
-
currentTarget === target && scrollActiveDescendantIntoView();
|
|
563
|
-
},
|
|
564
|
-
[scrollActiveDescendantIntoView]
|
|
565
|
-
);
|
|
566
|
-
|
|
567
|
-
// After new aria-activedescendant is assigned, we will need to scroll it into view.
|
|
568
|
-
// User agent will scroll automatically for focusing element, but not for aria-activedescendant.
|
|
569
|
-
// We need to do the scrolling manually.
|
|
570
|
-
useEffect(() => scrollActiveDescendantIntoView(), [scrollActiveDescendantIntoView]);
|
|
571
|
-
|
|
572
|
-
// If any activities has changed, reset the active descendant.
|
|
573
|
-
useEffect(() => setFocusedActivityKey(undefined), [activities, setFocusedActivityKey]);
|
|
574
|
-
|
|
575
|
-
const focusRelativeActivity = useCallback(
|
|
576
|
-
delta => {
|
|
577
|
-
if (isNaN(delta) || !renderingElements.length) {
|
|
578
|
-
return setFocusedActivityKey(undefined);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
const index = renderingElements.findIndex(({ key }) => key === focusedActivityKey);
|
|
582
|
-
const nextIndex = ~index
|
|
583
|
-
? Math.max(0, Math.min(renderingElements.length - 1, index + delta))
|
|
584
|
-
: renderingElements.length - 1;
|
|
585
|
-
const nextFocusedActivity = renderingElements[nextIndex];
|
|
586
|
-
|
|
587
|
-
setFocusedActivityKey(nextFocusedActivity.key);
|
|
588
|
-
rootElementRef.current && rootElementRef.current.focus();
|
|
589
|
-
},
|
|
590
|
-
[focusedActivityKey, renderingElements, rootElementRef, setFocusedActivityKey]
|
|
591
|
-
);
|
|
592
|
-
|
|
593
|
-
const handleTranscriptKeyDown = useCallback(
|
|
594
|
-
event => {
|
|
595
|
-
const { target } = event;
|
|
596
|
-
|
|
597
|
-
const fromEndOfTranscriptIndicator = target === terminatorRef.current;
|
|
598
|
-
const fromTranscript = target === event.currentTarget;
|
|
599
|
-
|
|
600
|
-
if (!fromEndOfTranscriptIndicator && !fromTranscript) {
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
let handled = true;
|
|
605
|
-
|
|
606
|
-
switch (event.key) {
|
|
607
|
-
case 'ArrowDown':
|
|
608
|
-
focusRelativeActivity(fromEndOfTranscriptIndicator ? 0 : 1);
|
|
609
|
-
break;
|
|
610
|
-
|
|
611
|
-
case 'ArrowUp':
|
|
612
|
-
focusRelativeActivity(fromEndOfTranscriptIndicator ? 0 : -1);
|
|
613
|
-
break;
|
|
614
|
-
|
|
615
|
-
case 'End':
|
|
616
|
-
focusRelativeActivity(Infinity);
|
|
617
|
-
break;
|
|
618
|
-
|
|
619
|
-
case 'Enter':
|
|
620
|
-
if (!fromEndOfTranscriptIndicator) {
|
|
621
|
-
const focusedActivityEntry = renderingElements.find(({ key }) => key === focusedActivityKey);
|
|
622
|
-
|
|
623
|
-
if (focusedActivityEntry) {
|
|
624
|
-
const { element: focusedActivityElement } =
|
|
625
|
-
activityElementsRef.current.find(({ activity }) => activity === focusedActivityEntry.activity) || {};
|
|
626
|
-
|
|
627
|
-
if (focusedActivityElement) {
|
|
628
|
-
const [firstTabbableElement] = tabbableElements(focusedActivityElement).filter(
|
|
629
|
-
({ className }) => className !== 'webchat__basic-transcript__activity-sentinel'
|
|
630
|
-
);
|
|
631
|
-
|
|
632
|
-
firstTabbableElement && firstTabbableElement.focus();
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
break;
|
|
638
|
-
|
|
639
|
-
case 'Escape':
|
|
640
|
-
focus('sendBoxWithoutKeyboard');
|
|
641
|
-
break;
|
|
642
|
-
|
|
643
|
-
case 'Home':
|
|
644
|
-
focusRelativeActivity(-Infinity);
|
|
645
|
-
break;
|
|
646
|
-
|
|
647
|
-
default:
|
|
648
|
-
handled = false;
|
|
649
|
-
break;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
if (handled) {
|
|
653
|
-
event.preventDefault();
|
|
654
|
-
|
|
655
|
-
// If a custom HTML control wants to handle up/down arrow, we will prevent them from listening to this event to prevent bugs due to handling arrow keys twice.
|
|
656
|
-
event.stopPropagation();
|
|
657
|
-
}
|
|
658
|
-
},
|
|
659
|
-
[focusedActivityKey, activityElementsRef, focusRelativeActivity, focus, terminatorRef, renderingElements]
|
|
660
|
-
);
|
|
661
|
-
|
|
662
|
-
const labelId = useUniqueId('webchat__basic-transcript__label');
|
|
663
|
-
|
|
664
|
-
// If SHIFT-TAB from "End of transcript" indicator, if focusedActivityKey is not set (or no longer exists), set it the the bottommost activity.
|
|
665
|
-
const setBottommostFocusedActivityKeyIfNeeded = useCallback(() => {
|
|
666
|
-
if (!~renderingElements.findIndex(({ key }) => key === focusedActivityKey)) {
|
|
667
|
-
const { key: lastActivityKey } = renderingElements[renderingElements.length - 1] || {};
|
|
668
|
-
|
|
669
|
-
setFocusedActivityKey(lastActivityKey);
|
|
670
|
-
}
|
|
671
|
-
}, [focusedActivityKey, renderingElements, setFocusedActivityKey]);
|
|
672
|
-
|
|
673
|
-
const handleTranscriptKeyDownCapture = useCallback(
|
|
674
|
-
event => {
|
|
675
|
-
const { altKey, ctrlKey, key, metaKey, target } = event;
|
|
676
|
-
|
|
677
|
-
if (altKey || (ctrlKey && key !== 'v') || metaKey || (!inputtableKey(key) && key !== 'Backspace')) {
|
|
678
|
-
// Ignore if one of the utility key (except SHIFT) is pressed
|
|
679
|
-
// E.g. CTRL-C on a link in one of the message should not jump to chat box
|
|
680
|
-
// E.g. "A" or "Backspace" should jump to chat box
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
// Send keystrokes to send box if we are focusing on the transcript or terminator.
|
|
685
|
-
if (target === event.currentTarget || target === terminatorRef.current) {
|
|
686
|
-
event.stopPropagation();
|
|
687
|
-
|
|
688
|
-
focus('sendBox');
|
|
689
|
-
}
|
|
690
|
-
},
|
|
691
|
-
[focus]
|
|
692
|
-
);
|
|
693
|
-
|
|
694
|
-
const focusTranscriptCallback = useCallback(() => rootElementRef.current && rootElementRef.current.focus(), [
|
|
695
|
-
rootElementRef
|
|
696
|
-
]);
|
|
697
|
-
|
|
698
|
-
useRegisterFocusTranscript(focusTranscriptCallback);
|
|
699
|
-
|
|
700
|
-
const handleFocusActivity = useCallback(
|
|
701
|
-
key => {
|
|
702
|
-
setFocusedActivityKey(key);
|
|
703
|
-
rootElementRef.current && rootElementRef.current.focus();
|
|
704
|
-
},
|
|
705
|
-
[setFocusedActivityKey]
|
|
706
|
-
);
|
|
707
|
-
|
|
708
|
-
// When the focusing activity has changed, dispatch an event to observers of "useObserveTranscriptFocus".
|
|
709
|
-
const dispatchTranscriptFocus = useDispatchTranscriptFocus();
|
|
710
|
-
const focusedActivity = useMemo(() => {
|
|
711
|
-
const { activity } = renderingElements.find(({ key }) => key === focusedActivityKey) || {};
|
|
712
|
-
|
|
713
|
-
return activity;
|
|
714
|
-
}, [focusedActivityKey, renderingElements]);
|
|
715
|
-
|
|
716
|
-
useMemo(() => dispatchTranscriptFocus && dispatchTranscriptFocus({ activity: focusedActivity }), [
|
|
717
|
-
dispatchTranscriptFocus,
|
|
718
|
-
focusedActivity
|
|
719
|
-
]);
|
|
720
|
-
|
|
721
|
-
// This is required by IE11.
|
|
722
|
-
// 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">,
|
|
723
|
-
// despite the fact there are no "tabIndex" attributes set on the filler.
|
|
724
|
-
// We need to artificially send the focus back to the transcript.
|
|
725
|
-
const handleFocusFiller = useCallback(() => {
|
|
726
|
-
const { current } = rootElementRef;
|
|
727
|
-
|
|
728
|
-
current && current.focus();
|
|
729
|
-
}, [rootElementRef]);
|
|
730
|
-
|
|
731
|
-
return (
|
|
732
|
-
<div
|
|
733
|
-
aria-activedescendant={focusedActivityKey ? activeDescendantElementId : undefined}
|
|
734
|
-
aria-labelledby={labelId}
|
|
735
|
-
className={classNames(
|
|
736
|
-
'webchat__basic-transcript',
|
|
737
|
-
basicTranscriptStyleSet + '',
|
|
738
|
-
rootClassName,
|
|
739
|
-
(className || '') + ''
|
|
740
|
-
)}
|
|
741
|
-
dir={direction}
|
|
742
|
-
onFocus={handleTranscriptFocus}
|
|
743
|
-
onKeyDown={handleTranscriptKeyDown}
|
|
744
|
-
onKeyDownCapture={handleTranscriptKeyDownCapture}
|
|
745
|
-
ref={rootElementRef}
|
|
746
|
-
// "aria-activedescendant" will only works with a number of roles and it must be explicitly set.
|
|
747
|
-
// https://www.w3.org/TR/wai-aria/#aria-activedescendant
|
|
748
|
-
role="group"
|
|
749
|
-
// For up/down arrow key navigation across activities, this component must be included in the tab sequence.
|
|
750
|
-
// Otherwise, "aria-activedescendant" will not be narrated when the user press up/down arrow keys.
|
|
751
|
-
// https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_focus_activedescendant
|
|
752
|
-
tabIndex={0}
|
|
753
|
-
>
|
|
754
|
-
<ScreenReaderText id={labelId} text={transcriptAriaLabel} />
|
|
755
|
-
{/* This <section> is for live region only. Content is made invisible through CSS. */}
|
|
756
|
-
<section
|
|
757
|
-
aria-atomic={false}
|
|
758
|
-
aria-live="polite"
|
|
759
|
-
aria-relevant="additions"
|
|
760
|
-
aria-roledescription={transcriptRoleDescription}
|
|
761
|
-
role="log"
|
|
762
|
-
>
|
|
763
|
-
{renderingElements.map(({ activity, liveRegionKey }) => (
|
|
764
|
-
<Fade fadeAfter={internalLiveRegionFadeAfter} key={liveRegionKey}>
|
|
765
|
-
{() => <ScreenReaderActivity activity={activity} />}
|
|
766
|
-
</Fade>
|
|
767
|
-
))}
|
|
768
|
-
</section>
|
|
769
|
-
{/* TODO: [P2] Fix ESLint error `no-use-before-define` */}
|
|
770
|
-
{/* eslint-disable-next-line @typescript-eslint/no-use-before-define */}
|
|
771
|
-
<InternalTranscriptScrollable
|
|
772
|
-
activities={renderingActivities}
|
|
773
|
-
onFocusActivity={handleFocusActivity}
|
|
774
|
-
onFocusFiller={handleFocusFiller}
|
|
775
|
-
terminatorRef={terminatorRef}
|
|
776
|
-
>
|
|
777
|
-
{renderingElements.map(
|
|
778
|
-
(
|
|
779
|
-
{
|
|
780
|
-
activity,
|
|
781
|
-
callbackRef,
|
|
782
|
-
focusActivity,
|
|
783
|
-
handleFocus,
|
|
784
|
-
handleKeyDown,
|
|
785
|
-
handleMouseDownCapture,
|
|
786
|
-
hideTimestamp,
|
|
787
|
-
key,
|
|
788
|
-
renderActivity,
|
|
789
|
-
renderActivityStatus,
|
|
790
|
-
renderAvatar,
|
|
791
|
-
role,
|
|
792
|
-
shouldSpeak,
|
|
793
|
-
showCallout
|
|
794
|
-
},
|
|
795
|
-
index
|
|
796
|
-
) => {
|
|
797
|
-
const { ariaLabelID, element } =
|
|
798
|
-
activityElementsRef.current.find(entry => entry.activity === activity) || {};
|
|
799
|
-
const activeDescendant = focusedActivityKey === key;
|
|
800
|
-
const isContentInteractive = !!(element
|
|
801
|
-
? tabbableElements(element.querySelector('.webchat__basic-transcript__activity-box')).length
|
|
802
|
-
: 0);
|
|
803
|
-
|
|
804
|
-
return (
|
|
805
|
-
<li
|
|
806
|
-
aria-labelledby={ariaLabelID}
|
|
807
|
-
className={classNames('webchat__basic-transcript__activity', {
|
|
808
|
-
'webchat__basic-transcript__activity--acknowledged': index <= indexOfLastInteractedActivity,
|
|
809
|
-
'webchat__basic-transcript__activity--from-bot': role !== 'user',
|
|
810
|
-
'webchat__basic-transcript__activity--from-user': role === 'user'
|
|
811
|
-
})}
|
|
812
|
-
// Set "id" for valid for accessibility.
|
|
813
|
-
/* eslint-disable-next-line react/forbid-dom-props */
|
|
814
|
-
id={activeDescendant ? activeDescendantElementId : undefined}
|
|
815
|
-
key={key}
|
|
816
|
-
onFocus={handleFocus}
|
|
817
|
-
onKeyDown={handleKeyDown}
|
|
818
|
-
onMouseDownCapture={handleMouseDownCapture}
|
|
819
|
-
ref={callbackRef}
|
|
820
|
-
>
|
|
821
|
-
<ScreenReaderActivity activity={activity} id={ariaLabelID} renderAttachments={false}>
|
|
822
|
-
{!!isContentInteractive && <p>{activityInteractiveAlt}</p>}
|
|
823
|
-
</ScreenReaderActivity>
|
|
824
|
-
<FocusRedirector
|
|
825
|
-
className="webchat__basic-transcript__activity-sentinel"
|
|
826
|
-
onFocus={focusActivity}
|
|
827
|
-
redirectRef={rootElementRef}
|
|
828
|
-
/>
|
|
829
|
-
<div className="webchat__basic-transcript__activity-box">
|
|
830
|
-
{renderActivity({
|
|
831
|
-
hideTimestamp,
|
|
832
|
-
renderActivityStatus,
|
|
833
|
-
renderAvatar,
|
|
834
|
-
showCallout
|
|
835
|
-
})}
|
|
836
|
-
</div>
|
|
837
|
-
{shouldSpeak && <SpeakActivity activity={activity} />}
|
|
838
|
-
<FocusRedirector
|
|
839
|
-
className="webchat__basic-transcript__activity-sentinel"
|
|
840
|
-
onFocus={focusActivity}
|
|
841
|
-
redirectRef={rootElementRef}
|
|
842
|
-
/>
|
|
843
|
-
<div
|
|
844
|
-
className={classNames('webchat__basic-transcript__activity-indicator', {
|
|
845
|
-
'webchat__basic-transcript__activity-indicator--first': !index,
|
|
846
|
-
'webchat__basic-transcript__activity-indicator--focus': activeDescendant
|
|
847
|
-
})}
|
|
848
|
-
/>
|
|
849
|
-
</li>
|
|
850
|
-
);
|
|
851
|
-
}
|
|
852
|
-
)}
|
|
853
|
-
</InternalTranscriptScrollable>
|
|
854
|
-
{!!renderingElements.length && (
|
|
855
|
-
<React.Fragment>
|
|
856
|
-
<FocusRedirector
|
|
857
|
-
className="webchat__basic-transcript__sentinel"
|
|
858
|
-
onFocus={setBottommostFocusedActivityKeyIfNeeded}
|
|
859
|
-
redirectRef={rootElementRef}
|
|
860
|
-
/>
|
|
861
|
-
<div className="webchat__basic-transcript__terminator" ref={terminatorRef} tabIndex={0}>
|
|
862
|
-
<div className="webchat__basic-transcript__terminator-body">
|
|
863
|
-
<div className="webchat__basic-transcript__terminator-text">{terminatorText}</div>
|
|
864
|
-
</div>
|
|
865
|
-
</div>
|
|
866
|
-
</React.Fragment>
|
|
867
|
-
)}
|
|
868
|
-
<div className="webchat__basic-transcript__focus-indicator" />
|
|
869
|
-
</div>
|
|
870
|
-
);
|
|
871
|
-
};
|
|
872
|
-
|
|
873
|
-
InternalTranscript.defaultProps = {
|
|
874
|
-
className: ''
|
|
875
|
-
};
|
|
876
|
-
|
|
877
|
-
InternalTranscript.propTypes = {
|
|
878
|
-
activityElementsRef: PropTypes.shape({
|
|
879
|
-
current: PropTypes.array.isRequired
|
|
880
|
-
}).isRequired,
|
|
881
|
-
className: PropTypes.string
|
|
882
|
-
};
|
|
883
|
-
|
|
884
|
-
const InternalScreenReaderTranscript = ({ renderingElements }) => {
|
|
885
|
-
const localize = useLocalizer();
|
|
886
|
-
const [internalLiveRegionFadeAfter] = useStyleOptions();
|
|
887
|
-
|
|
888
|
-
const transcriptRoleDescription = localize('TRANSCRIPT_ARIA_ROLE_ALT');
|
|
889
|
-
|
|
890
|
-
return (
|
|
891
|
-
<section
|
|
892
|
-
aria-atomic={false}
|
|
893
|
-
aria-live="polite"
|
|
894
|
-
aria-relevant="additions"
|
|
895
|
-
aria-roledescription={transcriptRoleDescription}
|
|
896
|
-
role="log"
|
|
897
|
-
>
|
|
898
|
-
{renderingElements.map(({ activity, liveRegionKey }) => (
|
|
899
|
-
<Fade fadeAfter={internalLiveRegionFadeAfter} key={liveRegionKey}>
|
|
900
|
-
{() => <ScreenReaderActivity activity={activity} />}
|
|
901
|
-
</Fade>
|
|
902
|
-
))}
|
|
903
|
-
</section>
|
|
904
|
-
);
|
|
905
|
-
};
|
|
906
|
-
|
|
907
|
-
InternalScreenReaderTranscript.propTypes = {
|
|
908
|
-
renderingElements: PropTypes.arrayOf(
|
|
909
|
-
PropTypes.shape({
|
|
910
|
-
activity: PropTypes.any,
|
|
911
|
-
liveRegionKey: PropTypes.string
|
|
912
|
-
})
|
|
913
|
-
).isRequired
|
|
914
|
-
};
|
|
915
|
-
|
|
916
|
-
// Separating high-frequency hooks to improve performance.
|
|
917
|
-
const InternalTranscriptScrollable = ({ activities, children, onFocusActivity, onFocusFiller, terminatorRef }) => {
|
|
918
|
-
const [{ activities: activitiesStyleSet }] = useStyleSet();
|
|
919
|
-
const [{ hideScrollToEndButton }] = useStyleOptions();
|
|
920
|
-
const [animatingToEnd] = useAnimatingToEnd();
|
|
921
|
-
const [sticky] = useSticky();
|
|
922
|
-
const lastVisibleActivityId = getActivityUniqueId(activities[activities.length - 1] || {}); // Activity ID of the last visible activity in the list.
|
|
923
|
-
const localize = useLocalizer();
|
|
924
|
-
const scrollToEndButtonRef = useRef();
|
|
925
|
-
|
|
926
|
-
const lastReadActivityIdRef = useRef(lastVisibleActivityId);
|
|
927
|
-
const transcriptRoleDescription = localize('TRANSCRIPT_ARIA_ROLE_ALT');
|
|
928
|
-
|
|
929
|
-
const allActivitiesRead = lastVisibleActivityId === lastReadActivityIdRef.current;
|
|
930
|
-
|
|
931
|
-
const handleScrollToEndButtonClick = useCallback(() => {
|
|
932
|
-
// After the "New message" button is clicked, focus on the first unread activity.
|
|
933
|
-
const index = activities.findIndex(({ id }) => id === lastReadActivityIdRef.current);
|
|
934
|
-
|
|
935
|
-
if (~index) {
|
|
936
|
-
const firstUnreadActivity = activities[index + 1];
|
|
937
|
-
|
|
938
|
-
if (firstUnreadActivity) {
|
|
939
|
-
return onFocusActivity(getActivityUniqueId(firstUnreadActivity));
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
const { current } = terminatorRef;
|
|
944
|
-
|
|
945
|
-
current && current.focus();
|
|
946
|
-
}, [activities, lastReadActivityIdRef, onFocusActivity, terminatorRef]);
|
|
947
|
-
|
|
948
|
-
if (sticky) {
|
|
949
|
-
// If it is sticky, the user is at the bottom of the transcript, everything is read.
|
|
950
|
-
// So mark the activity ID as read.
|
|
951
|
-
lastReadActivityIdRef.current = lastVisibleActivityId;
|
|
952
|
-
}
|
|
953
|
-
|
|
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
|
-
}
|
|
980
|
-
|
|
981
|
-
return activities.findIndex(activity => getActivityUniqueId(activity) === lastReadActivityIdRef.current);
|
|
982
|
-
}, [activities, allActivitiesRead, animatingToEnd, hideScrollToEndButton, lastReadActivityIdRef, sticky]);
|
|
983
|
-
|
|
984
|
-
return (
|
|
985
|
-
<React.Fragment>
|
|
986
|
-
{renderSeparatorAfterIndex !== -1 && (
|
|
987
|
-
<ScrollToEndButton onClick={handleScrollToEndButtonClick} ref={scrollToEndButtonRef} />
|
|
988
|
-
)}
|
|
989
|
-
{!!React.Children.count(children) && (
|
|
990
|
-
<FocusRedirector className="webchat__basic-transcript__sentinel" redirectRef={terminatorRef} />
|
|
991
|
-
)}
|
|
992
|
-
<ReactScrollToBottomPanel className="webchat__basic-transcript__scrollable">
|
|
993
|
-
<div aria-hidden={true} className="webchat__basic-transcript__filler" onFocus={onFocusFiller} />
|
|
994
|
-
<ul
|
|
995
|
-
aria-roledescription={transcriptRoleDescription}
|
|
996
|
-
className={classNames(activitiesStyleSet + '', 'webchat__basic-transcript__transcript')}
|
|
997
|
-
role="list"
|
|
998
|
-
>
|
|
999
|
-
{children}
|
|
1000
|
-
</ul>
|
|
1001
|
-
<BasicTypingIndicator />
|
|
1002
|
-
</ReactScrollToBottomPanel>
|
|
1003
|
-
</React.Fragment>
|
|
1004
|
-
);
|
|
1005
|
-
};
|
|
1006
|
-
|
|
1007
|
-
InternalTranscriptScrollable.propTypes = {
|
|
1008
|
-
activities: PropTypes.array.isRequired,
|
|
1009
|
-
children: PropTypes.any.isRequired,
|
|
1010
|
-
onFocusActivity: PropTypes.func.isRequired,
|
|
1011
|
-
onFocusFiller: PropTypes.func.isRequired,
|
|
1012
|
-
terminatorRef: PropTypes.any.isRequired
|
|
1013
|
-
};
|
|
1014
|
-
|
|
1015
|
-
const SetScroller = ({ activityElementsRef, scrollerRef }) => {
|
|
1016
|
-
const [
|
|
1017
|
-
{ autoScrollSnapOnActivity, autoScrollSnapOnActivityOffset, autoScrollSnapOnPage, autoScrollSnapOnPageOffset }
|
|
1018
|
-
] = useStyleOptions();
|
|
1019
|
-
const [lastAcknowledgedActivity] = useAcknowledgedActivity();
|
|
1020
|
-
|
|
1021
|
-
const lastAcknowledgedActivityRef = useRef(lastAcknowledgedActivity);
|
|
1022
|
-
|
|
1023
|
-
lastAcknowledgedActivityRef.current = lastAcknowledgedActivity;
|
|
1024
|
-
|
|
1025
|
-
scrollerRef.current = useCallback(
|
|
1026
|
-
({ offsetHeight, scrollTop }) => {
|
|
1027
|
-
const patchedAutoScrollSnapOnActivity =
|
|
1028
|
-
typeof autoScrollSnapOnActivity === 'number'
|
|
1029
|
-
? Math.max(0, autoScrollSnapOnActivity)
|
|
1030
|
-
: autoScrollSnapOnActivity
|
|
1031
|
-
? 1
|
|
1032
|
-
: 0;
|
|
1033
|
-
const patchedAutoScrollSnapOnPage =
|
|
1034
|
-
typeof autoScrollSnapOnPage === 'number'
|
|
1035
|
-
? Math.max(0, Math.min(1, autoScrollSnapOnPage))
|
|
1036
|
-
: autoScrollSnapOnPage
|
|
1037
|
-
? 1
|
|
1038
|
-
: 0;
|
|
1039
|
-
const patchedAutoScrollSnapOnActivityOffset =
|
|
1040
|
-
typeof autoScrollSnapOnActivityOffset === 'number' ? autoScrollSnapOnActivityOffset : 0;
|
|
1041
|
-
const patchedAutoScrollSnapOnPageOffset =
|
|
1042
|
-
typeof autoScrollSnapOnPageOffset === 'number' ? autoScrollSnapOnPageOffset : 0;
|
|
1043
|
-
|
|
1044
|
-
if (patchedAutoScrollSnapOnActivity || patchedAutoScrollSnapOnPage) {
|
|
1045
|
-
const { current: lastAcknowledgedActivity } = lastAcknowledgedActivityRef;
|
|
1046
|
-
|
|
1047
|
-
const values = [];
|
|
1048
|
-
|
|
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
|
-
);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
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
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
return values.reduce((minValue, value) => Math.min(minValue, value), Infinity);
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
return Infinity;
|
|
1087
|
-
},
|
|
1088
|
-
[
|
|
1089
|
-
activityElementsRef,
|
|
1090
|
-
autoScrollSnapOnActivity,
|
|
1091
|
-
autoScrollSnapOnActivityOffset,
|
|
1092
|
-
autoScrollSnapOnPage,
|
|
1093
|
-
autoScrollSnapOnPageOffset,
|
|
1094
|
-
lastAcknowledgedActivityRef
|
|
1095
|
-
]
|
|
1096
|
-
);
|
|
1097
|
-
|
|
1098
|
-
return false;
|
|
1099
|
-
};
|
|
1100
|
-
|
|
1101
|
-
const BasicTranscript = ({ className }) => {
|
|
1102
|
-
const activityElementsRef = useRef([]);
|
|
1103
|
-
const scrollerRef = useRef(() => Infinity);
|
|
1104
|
-
|
|
1105
|
-
const scroller = useCallback((...args) => scrollerRef.current(...args), [scrollerRef]);
|
|
1106
|
-
|
|
1107
|
-
return (
|
|
1108
|
-
<ReactScrollToBottomComposer scroller={scroller}>
|
|
1109
|
-
<SetScroller activityElementsRef={activityElementsRef} scrollerRef={scrollerRef} />
|
|
1110
|
-
<InternalTranscript activityElementsRef={activityElementsRef} className={className} />
|
|
1111
|
-
</ReactScrollToBottomComposer>
|
|
1112
|
-
);
|
|
1113
|
-
};
|
|
1114
|
-
|
|
1115
|
-
BasicTranscript.defaultProps = {
|
|
1116
|
-
className: ''
|
|
1117
|
-
};
|
|
1118
|
-
|
|
1119
|
-
BasicTranscript.propTypes = {
|
|
1120
|
-
className: PropTypes.string
|
|
1121
|
-
};
|
|
1122
|
-
|
|
1123
|
-
export default BasicTranscript;
|