@microsoft/omnichannel-chat-components 1.1.16 → 1.1.17-main.05edfd3

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 (324) hide show
  1. package/lib/cjs/assets/Icons.js +21 -42
  2. package/lib/cjs/common/Constants.js +14 -31
  3. package/lib/cjs/common/decodeComponentString.js +0 -6
  4. package/lib/cjs/common/encodeComponentString.js +0 -2
  5. package/lib/cjs/common/utils.js +40 -46
  6. package/lib/cjs/components/callingcontainer/CallingContainer.js +3 -18
  7. package/lib/cjs/components/callingcontainer/common/defaultProps/defaultCallingContainerControlProps.js +2 -5
  8. package/lib/cjs/components/callingcontainer/common/defaultProps/defaultCallingContainerProps.js +2 -6
  9. package/lib/cjs/components/callingcontainer/common/defaultStyles/customizedCallingContainerStyles.js +2 -3
  10. package/lib/cjs/components/callingcontainer/common/defaultStyles/defaultCallingContainerStyles.js +2 -3
  11. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/CurrentCall.js +95 -135
  12. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/common/defaultProps/defaultCurrentCallControlProps.js +2 -5
  13. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/common/defaultProps/defaultCurrentCallControlPropsRtl.js +2 -6
  14. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/common/defaultProps/defaultCurrentCallProps.js +2 -6
  15. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/common/defaultStyles/componentOverridesStyleProps.js +3 -5
  16. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/common/defaultStyles/customizedCurrentCallStyleProps.js +2 -3
  17. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/common/defaultStyles/defaultCurrentCallStyleProps.js +2 -3
  18. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/IncomingCall.js +51 -78
  19. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultProps/componentOverrideProps.js +3 -11
  20. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultProps/componentOverridesControlProps.js +2 -7
  21. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultProps/defaultIncomingCallControlProps.js +2 -5
  22. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultProps/defaultIncomingCallControlPropsRtl.js +2 -6
  23. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultProps/defaultIncomingCallProps.js +2 -6
  24. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultStyles/componentOverridesStyleProps.js +2 -3
  25. package/lib/cjs/components/callingcontainer/subcomponents/IncomingCall/common/defaultStyles/defaultIncomingCallStyleProps.js +2 -3
  26. package/lib/cjs/components/callingcontainer/subcomponents/Timer/Timer.js +2 -11
  27. package/lib/cjs/components/chatbutton/ChatButton.blankAnnouncements.a11y.spec.js +162 -0
  28. package/lib/cjs/components/chatbutton/ChatButton.browseMode.a11y.spec.js +236 -0
  29. package/lib/cjs/components/chatbutton/ChatButton.browseMode.unfixed.a11y.spec.js +115 -0
  30. package/lib/cjs/components/chatbutton/ChatButton.js +67 -62
  31. package/lib/cjs/components/chatbutton/common/defaultProps/defaultChatButtonControlProps.js +2 -5
  32. package/lib/cjs/components/chatbutton/common/defaultProps/defaultChatButtonProps.js +2 -6
  33. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonGeneralStyles.js +2 -3
  34. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonIconContainerStyles.js +2 -5
  35. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonNotificationBubbleStyles.js +2 -3
  36. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonStyleProps.js +2 -10
  37. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonSubTitleStyles.js +2 -3
  38. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonTextContainerStyles.js +2 -3
  39. package/lib/cjs/components/chatbutton/common/defaultStyles/defaultChatButtonTitleStyles.js +2 -3
  40. package/lib/cjs/components/citationpane/CitationPane.js +19 -46
  41. package/lib/cjs/components/citationpane/ScalingTest.js +2 -8
  42. package/lib/cjs/components/citationpane/common/defaultProps/defaultCitationPaneControlProps.js +2 -3
  43. package/lib/cjs/components/citationpane/common/defaultProps/defaultCitationPaneProps.js +2 -6
  44. package/lib/cjs/components/citationpane/common/defaultProps/defaultCitationPaneStyleProps.js +2 -13
  45. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneCloseButtonFocusedStyles.js +2 -3
  46. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneCloseButtonHoveredStyles.js +2 -3
  47. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneCloseButtonStyles.js +2 -5
  48. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneContentStyles.js +2 -4
  49. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneGeneralStyles.js +2 -4
  50. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneStyles.js +2 -13
  51. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneTitleStyles.js +1 -2
  52. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneTopCloseButtonFocusedStyles.js +2 -3
  53. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneTopCloseButtonHoveredStyles.js +2 -3
  54. package/lib/cjs/components/citationpane/common/defaultStyles/defaultCitationPaneTopCloseButtonStyles.js +2 -4
  55. package/lib/cjs/components/common/commandbutton/CommandButton.js +16 -27
  56. package/lib/cjs/components/common/subcomponents/CloseButton.js +2 -9
  57. package/lib/cjs/components/confirmationpane/ConfirmationPane.js +26 -55
  58. package/lib/cjs/components/confirmationpane/common/defaultProps/defaultConfirmationPaneControlProps.js +3 -5
  59. package/lib/cjs/components/confirmationpane/common/defaultProps/defaultConfirmationPaneProps.js +2 -6
  60. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneButtonGroupStyles.js +2 -3
  61. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneCancelButtonFocusedStyles.js +2 -3
  62. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneCancelButtonHoveredStyles.js +2 -3
  63. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneCancelButtonStyles.js +2 -3
  64. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneConfirmButtonFocusedStyles.js +2 -3
  65. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneConfirmButtonHoveredStyles.js +2 -3
  66. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneConfirmButtonStyles.js +2 -3
  67. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneGeneralStyles.js +2 -3
  68. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneStyles.js +2 -10
  69. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneSubtitleStyles.js +2 -3
  70. package/lib/cjs/components/confirmationpane/common/defaultStyles/defaultConfirmationPaneTitleStyles.js +2 -3
  71. package/lib/cjs/components/footer/Footer.js +9 -28
  72. package/lib/cjs/components/footer/common/defaultProps/customFooterControlProps.js +2 -6
  73. package/lib/cjs/components/footer/common/defaultProps/defaultFooterComponentOverrides.js +2 -11
  74. package/lib/cjs/components/footer/common/defaultProps/defaultFooterControlProps.js +2 -5
  75. package/lib/cjs/components/footer/common/defaultProps/defaultFooterOverridesProps.js +2 -7
  76. package/lib/cjs/components/footer/common/defaultProps/defaultFooterProps.js +2 -6
  77. package/lib/cjs/components/footer/common/defaultStyles/defaultFooterStyleProps.js +2 -3
  78. package/lib/cjs/components/footer/subcomponents/AudioNotificationButton.js +13 -23
  79. package/lib/cjs/components/footer/subcomponents/DownloadTranscriptButton.js +2 -9
  80. package/lib/cjs/components/footer/subcomponents/EmailTranscriptButton.js +2 -9
  81. package/lib/cjs/components/header/Header.js +26 -32
  82. package/lib/cjs/components/header/common/defaultProps/azureHeaderControlProps.js +2 -6
  83. package/lib/cjs/components/header/common/defaultProps/azureHeaderProps.js +2 -7
  84. package/lib/cjs/components/header/common/defaultProps/customHeaderControlProps.js +2 -6
  85. package/lib/cjs/components/header/common/defaultProps/defaultHeaderComponentOverrides.js +3 -13
  86. package/lib/cjs/components/header/common/defaultProps/defaultHeaderControlProps.js +2 -6
  87. package/lib/cjs/components/header/common/defaultProps/defaultHeaderProps.js +2 -6
  88. package/lib/cjs/components/header/common/defaultProps/overridesDefaultHeaderProps.js +2 -7
  89. package/lib/cjs/components/header/common/defaultStyles/advancedHeaderStyleProps.js +2 -3
  90. package/lib/cjs/components/header/common/defaultStyles/defaultHeaderStyleProps.js +25 -3
  91. package/lib/cjs/components/header/subcomponents/MinimizeButton.js +2 -9
  92. package/lib/cjs/components/inputvalidationpane/InputValidationPane.js +55 -90
  93. package/lib/cjs/components/inputvalidationpane/common/default/defaultProps/defaultInputValidationPaneControlProps.js +3 -5
  94. package/lib/cjs/components/inputvalidationpane/common/default/defaultProps/defaultInputValidationPaneProps.js +2 -6
  95. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneButtonGroupStyles.js +2 -3
  96. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneCancelButtonHoveredStyles.js +1 -2
  97. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneCancelButtonStyles.js +2 -3
  98. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneGeneralStyles.js +2 -3
  99. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneHeaderGroupStyles.js +2 -3
  100. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneInputStyles.js +2 -3
  101. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneInvalidInputErrorMessageStyles.js +2 -3
  102. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneSendButtonHoveredStyles.js +1 -2
  103. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneSendButtonStyles.js +2 -3
  104. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneStyles.js +2 -15
  105. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneSubtitleStyles.js +2 -3
  106. package/lib/cjs/components/inputvalidationpane/common/default/defaultStyles/defaultInputValidationPaneTitleStyles.js +2 -3
  107. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoProps/presetTwoInputValidationPaneComponentOverrides.js +3 -8
  108. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoProps/presetTwoInputValidationPaneControlProps.js +2 -5
  109. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoProps/presetTwoInputValidationPaneProps.js +2 -7
  110. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoStyles/presetTwoInputValidationPaneCancelButtonStyles.js +2 -3
  111. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoStyles/presetTwoInputValidationPaneHeaderGroupStyles.js +2 -3
  112. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoStyles/presetTwoInputValidationPaneInputStyles.js +2 -3
  113. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoStyles/presetTwoInputValidationPaneSendButtonStyles.js +2 -3
  114. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoStyles/presetTwoInputValidationPaneStyles.js +2 -9
  115. package/lib/cjs/components/inputvalidationpane/common/presetTwo/presetTwoStyles/presetTwoInputValidationPaneTitleStyles.js +2 -3
  116. package/lib/cjs/components/loadingpane/LoadingPane.js +12 -28
  117. package/lib/cjs/components/loadingpane/common/defaultProps/defaultLoadingPaneControlProps.js +2 -5
  118. package/lib/cjs/components/loadingpane/common/defaultProps/defaultLoadingPaneProps.js +2 -6
  119. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneGeneralStyles.js +2 -3
  120. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneIconImageProps.js +2 -6
  121. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneIconStyles.js +2 -3
  122. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneSpinnerStyles.js +2 -3
  123. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneSpinnerTextStyles.js +2 -3
  124. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneStyles.js +2 -11
  125. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneSubtitleStyles.js +2 -3
  126. package/lib/cjs/components/loadingpane/common/defaultProps/defaultStyles/defaultLoadingPaneTitleStyles.js +2 -3
  127. package/lib/cjs/components/loadingpane/common/presetOneProps/presetOneLoadingPaneControlProps.js +3 -5
  128. package/lib/cjs/components/loadingpane/common/presetOneProps/presetOneLoadingPaneProps.js +2 -6
  129. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeLoadingPaneControlProps.js +3 -6
  130. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeLoadingPaneProps.js +2 -6
  131. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneGeneralStyles.js +2 -3
  132. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneIconImageProps.js +2 -6
  133. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneIconStyles.js +2 -3
  134. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneSpinnerStyles.js +2 -3
  135. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneSpinnerTextStyles.js +2 -3
  136. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneStyles.js +2 -11
  137. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneSubtitleStyles.js +2 -3
  138. package/lib/cjs/components/loadingpane/common/presetThreeProps/presetThreeStyles/presetThreeLoadingPaneTitleStyles.js +2 -3
  139. package/lib/cjs/components/loadingpane/common/presetTwoProps/presetTwoLoadingPaneControlProps.js +3 -6
  140. package/lib/cjs/components/loadingpane/common/presetTwoProps/presetTwoLoadingPaneProps.js +2 -6
  141. package/lib/cjs/components/loadingpane/common/presetTwoProps/presetTwoStyles/presetTwoLoadingPaneGeneralStyles.js +2 -5
  142. package/lib/cjs/components/loadingpane/common/presetTwoProps/presetTwoStyles/presetTwoLoadingPaneSpinnerStyles.js +2 -3
  143. package/lib/cjs/components/loadingpane/common/presetTwoProps/presetTwoStyles/presetTwoLoadingPaneStyles.js +2 -11
  144. package/lib/cjs/components/notificationpane/NotificationPane.js +3 -15
  145. package/lib/cjs/components/notificationpane/subcomponents/CloseChatButton.js +2 -9
  146. package/lib/cjs/components/notificationpane/subcomponents/DismissButton.js +2 -9
  147. package/lib/cjs/components/outofofficehourspane/OOOHPane.js +5 -17
  148. package/lib/cjs/components/outofofficehourspane/common/defaultProps/defaultOOOHPaneControlProps.js +2 -5
  149. package/lib/cjs/components/outofofficehourspane/common/defaultProps/defaultOOOHPaneProps.js +2 -6
  150. package/lib/cjs/components/outofofficehourspane/common/defaultProps/defaultStyles/defaultOOOHPaneGeneralStyles.js +2 -3
  151. package/lib/cjs/components/outofofficehourspane/common/defaultProps/defaultStyles/defaultOOOHPaneStyles.js +2 -6
  152. package/lib/cjs/components/outofofficehourspane/common/defaultProps/defaultStyles/defaultOOOHPaneTitleStyles.js +2 -3
  153. package/lib/cjs/components/outofofficehourspane/common/presetFourProps/presetFourOOOHPaneControlProps.js +3 -5
  154. package/lib/cjs/components/outofofficehourspane/common/presetFourProps/presetFourOOOHPaneProps.js +2 -6
  155. package/lib/cjs/components/outofofficehourspane/common/presetOneProps/presetOneOOOHPaneControlProps.js +3 -5
  156. package/lib/cjs/components/outofofficehourspane/common/presetOneProps/presetOneOOOHPaneProps.js +2 -6
  157. package/lib/cjs/components/outofofficehourspane/common/presetTwoProps/presetTwoOOOHPaneControlProps.js +3 -5
  158. package/lib/cjs/components/outofofficehourspane/common/presetTwoProps/presetTwoOOOHPaneProps.js +2 -6
  159. package/lib/cjs/components/outofofficehourspane/common/presetTwoProps/presetTwoStyles/presetTwoOOOHPaneGeneralStyles.js +2 -5
  160. package/lib/cjs/components/outofofficehourspane/common/presetTwoProps/presetTwoStyles/presetTwoOOOHPaneStyles.js +2 -6
  161. package/lib/cjs/components/outofofficehourspane/common/presetTwoProps/presetTwoStyles/presetTwoOOOHPaneTitleStyles.js +2 -3
  162. package/lib/cjs/components/postchatsurveypane/PostChatSurveyPane.js +4 -13
  163. package/lib/cjs/components/postchatsurveypane/common/defaultProps/defaultPostChatSurveyPaneControlProps.js +2 -5
  164. package/lib/cjs/components/postchatsurveypane/common/defaultProps/defaultPostChatSurveyPaneProps.js +2 -6
  165. package/lib/cjs/components/postchatsurveypane/common/defaultProps/defaultStyles/defaultPostChatSurveyPaneGeneralStyles.js +2 -3
  166. package/lib/cjs/components/postchatsurveypane/common/defaultProps/defaultStyles/defaultPostChatSurveyPaneStyles.js +2 -5
  167. package/lib/cjs/components/postchatsurveypane/common/presetOneProps/presetOnePostChatSurveyPaneControlProps.js +3 -5
  168. package/lib/cjs/components/postchatsurveypane/common/presetOneProps/presetOnePostChatSurveyPaneProps.js +2 -6
  169. package/lib/cjs/components/postchatsurveypane/common/presetOneProps/presetOneStyles/presetOnePostChatSurveyPaneGeneralStyles.js +2 -3
  170. package/lib/cjs/components/postchatsurveypane/common/presetOneProps/presetOneStyles/presetOnePostChatSurveyPaneStyles.js +2 -5
  171. package/lib/cjs/components/prechatsurveypane/PreChatSurveyPane.js +112 -56
  172. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultPreChatSurveyPaneControlProps.js +2 -5
  173. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultPreChatSurveyPaneProps.js +2 -6
  174. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneACContainerStyles.js +2 -3
  175. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneButtonStyles.js +2 -3
  176. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneGeneralStyles.js +2 -3
  177. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultichoiceInputStyles.js +3 -3
  178. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultilineTextInputStyles.js +3 -3
  179. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneStyles.js +2 -11
  180. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneTextInputStyles.js +3 -3
  181. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneToggleInputStyles.js +2 -3
  182. package/lib/cjs/components/prechatsurveypane/common/presetOneProps/presetOnePreChatSurveyPaneControlProps.js +3 -5
  183. package/lib/cjs/components/prechatsurveypane/common/presetOneProps/presetOnePreChatSurveyPaneProps.js +2 -6
  184. package/lib/cjs/components/prechatsurveypane/common/presetThreeProps/presetThreePreChatSurveyPaneControlProps.js +2 -3
  185. package/lib/cjs/components/prechatsurveypane/common/presetThreeProps/presetThreePreChatSurveyPaneProps.js +2 -6
  186. package/lib/cjs/components/prechatsurveypane/common/presetThreeProps/presetThreeStyles/presetThreePreChatSurveyPaneACContainerStyles.js +2 -3
  187. package/lib/cjs/components/prechatsurveypane/common/presetThreeProps/presetThreeStyles/presetThreePreChatSurveyPaneButtonStyles.js +2 -3
  188. package/lib/cjs/components/prechatsurveypane/common/presetThreeProps/presetThreeStyles/presetThreePreChatSurveyPaneGeneralStyles.js +2 -3
  189. package/lib/cjs/components/prechatsurveypane/common/presetThreeProps/presetThreeStyles/presetThreePreChatSurveyPaneStyles.js +2 -7
  190. package/lib/cjs/components/prechatsurveypane/common/presetTwoProps/presetTwoPreChatSurveyPaneControlProps.js +2 -3
  191. package/lib/cjs/components/prechatsurveypane/common/presetTwoProps/presetTwoPreChatSurveyPaneProps.js +2 -6
  192. package/lib/cjs/components/proactivechatpane/ProactiveChatPane.js +29 -65
  193. package/lib/cjs/components/proactivechatpane/common/default/defaultProps/defaultProactiveChatPaneControlProps.js +2 -5
  194. package/lib/cjs/components/proactivechatpane/common/default/defaultProps/defaultProactiveChatPaneProps.js +2 -6
  195. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneBodyContainerStyles.js +1 -2
  196. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneBodyTitleStyles.js +2 -3
  197. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneCloseButtonHoveredStyles.js +2 -3
  198. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneCloseButtonStyles.js +2 -3
  199. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneGeneralStyles.js +2 -3
  200. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneHeaderContainerStyles.js +2 -5
  201. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneStartButtonHoveredStyles.js +2 -3
  202. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneStartButtonStyles.js +2 -3
  203. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneStyles.js +2 -15
  204. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneSubtitleStyles.js +2 -3
  205. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneTextContainerStyles.js +2 -3
  206. package/lib/cjs/components/proactivechatpane/common/default/defaultStyles/defaultProactiveChatPaneTitleStyles.js +2 -3
  207. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneProps/presetOneProactiveChatPaneControlProps.js +2 -5
  208. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneProps/presetOneProactiveChatPaneProps.js +2 -6
  209. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneStyles/presetOneProactiveChatPaneBodyTitleStyles.js +2 -3
  210. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneStyles/presetOneProactiveChatPaneCloseButtonHoveredStyles.js +2 -3
  211. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneStyles/presetOneProactiveChatPaneCloseButtonStyles.js +2 -3
  212. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneStyles/presetOneProactiveChatPaneStartButtonHoveredStyles.js +2 -3
  213. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneStyles/presetOneProactiveChatPaneStartButtonStyles.js +2 -3
  214. package/lib/cjs/components/proactivechatpane/common/presetOne/presetOneStyles/presetOneProactiveChatPaneStyles.js +2 -9
  215. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeProps/presetThreeProactiveChatPaneControlProps.js +2 -5
  216. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeProps/presetThreeProactiveChatPaneProps.js +2 -6
  217. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneBodyContainerStyles.js +2 -3
  218. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneCloseButtonHoveredStyles.js +2 -3
  219. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneCloseButtonStyles.js +2 -3
  220. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneGeneralStyles.js +2 -3
  221. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneHeaderContainerStyles.js +2 -3
  222. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneStartButtonHoveredStyles.js +2 -3
  223. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneStartButtonStyles.js +2 -3
  224. package/lib/cjs/components/proactivechatpane/common/presetThree/presetThreeStyles/presetThreeProactiveChatPaneStyles.js +2 -11
  225. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoProps/presetTwoProactiveChatPaneComponentOverrides.js +4 -11
  226. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoProps/presetTwoProactiveChatPaneControlProps.js +2 -5
  227. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoProps/presetTwoProactiveChatPaneProps.js +2 -7
  228. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneBodyContainerStyles.js +2 -3
  229. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneGeneralStyles.js +2 -3
  230. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneHeaderContainerStyles.js +2 -3
  231. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneStartButtonHoveredStyles.js +2 -3
  232. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneStartButtonStyles.js +2 -3
  233. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneStyles.js +2 -10
  234. package/lib/cjs/components/proactivechatpane/common/presetTwo/presetTwoStyles/presetTwoProactiveChatPaneTextContainerStyles.js +2 -3
  235. package/lib/cjs/components/reconnectchatpane/ReconnectChatPane.js +33 -69
  236. package/lib/cjs/components/reconnectchatpane/common/default/defaultProps/defaultReconnectChatPaneControlProps.js +2 -5
  237. package/lib/cjs/components/reconnectchatpane/common/default/defaultProps/defaultReconnectChatPaneProps.js +2 -6
  238. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneButtonGroupStyles.js +2 -3
  239. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneContinueChatButtonFocusedStyles.js +2 -3
  240. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneContinueChatButtonHoveredStyles.js +2 -3
  241. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneContinueChatButtonStyles.js +2 -3
  242. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneGeneralStyles.js +2 -3
  243. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneIconStyles.js +2 -5
  244. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneStartChatButtonFocusedStyles.js +2 -3
  245. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneStartNewChatButtonHoveredStyles.js +2 -3
  246. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneStartNewChatButtonStyles.js +2 -3
  247. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneStyles.js +2 -14
  248. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneSubtitleStyles.js +2 -3
  249. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneTitleStyles.js +2 -3
  250. package/lib/cjs/components/reconnectchatpane/common/default/defaultStyles/defaultReconnectChatPaneWrapperStyles.js +2 -3
  251. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeProps/presetThreeReconnectChatPaneControlProps.js +2 -5
  252. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeProps/presetThreeReconnectChatPaneProps.js +2 -6
  253. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeStyles/presetThreeReconnectChatPaneButtonGroupStyles.js +2 -3
  254. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeStyles/presetThreeReconnectChatPaneContinueChatButtonStyles.js +2 -3
  255. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeStyles/presetThreeReconnectChatPaneGeneralStyles.js +2 -3
  256. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeStyles/presetThreeReconnectChatPaneStyles.js +2 -9
  257. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeStyles/presetThreeReconnectChatPaneTitleStyles.js +2 -3
  258. package/lib/cjs/components/reconnectchatpane/common/presetThree/presetThreeStyles/presetThreeReconnectChatPaneWrapperStyles.js +2 -3
  259. package/lib/cjs/index.js +1 -24
  260. package/lib/cjs/services/BroadcastService.js +15 -26
  261. package/lib/cjs/services/EventQueue.js +5 -27
  262. package/lib/esm/common/Constants.js +15 -17
  263. package/lib/esm/common/decodeComponentString.js +0 -1
  264. package/lib/esm/common/utils.js +42 -22
  265. package/lib/esm/components/callingcontainer/CallingContainer.js +0 -5
  266. package/lib/esm/components/callingcontainer/subcomponents/CurrentCall/CurrentCall.js +86 -109
  267. package/lib/esm/components/callingcontainer/subcomponents/CurrentCall/common/defaultStyles/componentOverridesStyleProps.js +2 -1
  268. package/lib/esm/components/callingcontainer/subcomponents/IncomingCall/IncomingCall.js +41 -57
  269. package/lib/esm/components/callingcontainer/subcomponents/Timer/Timer.js +0 -2
  270. package/lib/esm/components/chatbutton/ChatButton.blankAnnouncements.a11y.spec.js +159 -0
  271. package/lib/esm/components/chatbutton/ChatButton.browseMode.a11y.spec.js +233 -0
  272. package/lib/esm/components/chatbutton/ChatButton.browseMode.unfixed.a11y.spec.js +111 -0
  273. package/lib/esm/components/chatbutton/ChatButton.js +64 -40
  274. package/lib/esm/components/citationpane/CitationPane.js +17 -21
  275. package/lib/esm/components/citationpane/ScalingTest.js +1 -1
  276. package/lib/esm/components/citationpane/common/defaultStyles/defaultCitationPaneCloseButtonStyles.js +0 -2
  277. package/lib/esm/components/citationpane/common/defaultStyles/defaultCitationPaneContentStyles.js +0 -1
  278. package/lib/esm/components/citationpane/common/defaultStyles/defaultCitationPaneGeneralStyles.js +0 -1
  279. package/lib/esm/components/citationpane/common/defaultStyles/defaultCitationPaneTopCloseButtonStyles.js +0 -1
  280. package/lib/esm/components/common/commandbutton/CommandButton.js +14 -15
  281. package/lib/esm/components/common/subcomponents/CloseButton.js +0 -2
  282. package/lib/esm/components/confirmationpane/ConfirmationPane.js +24 -28
  283. package/lib/esm/components/confirmationpane/common/defaultProps/defaultConfirmationPaneControlProps.js +1 -0
  284. package/lib/esm/components/footer/Footer.js +6 -10
  285. package/lib/esm/components/footer/common/defaultProps/defaultFooterComponentOverrides.js +0 -2
  286. package/lib/esm/components/footer/subcomponents/AudioNotificationButton.js +11 -11
  287. package/lib/esm/components/footer/subcomponents/DownloadTranscriptButton.js +0 -2
  288. package/lib/esm/components/footer/subcomponents/EmailTranscriptButton.js +0 -2
  289. package/lib/esm/components/header/Header.js +23 -15
  290. package/lib/esm/components/header/common/defaultStyles/defaultHeaderStyleProps.js +23 -0
  291. package/lib/esm/components/header/subcomponents/MinimizeButton.js +0 -2
  292. package/lib/esm/components/inputvalidationpane/InputValidationPane.js +53 -61
  293. package/lib/esm/components/inputvalidationpane/common/default/defaultProps/defaultInputValidationPaneControlProps.js +1 -0
  294. package/lib/esm/components/loadingpane/LoadingPane.js +10 -13
  295. package/lib/esm/components/loadingpane/common/presetOneProps/presetOneLoadingPaneControlProps.js +2 -1
  296. package/lib/esm/components/loadingpane/common/presetThreeProps/presetThreeLoadingPaneControlProps.js +2 -1
  297. package/lib/esm/components/loadingpane/common/presetTwoProps/presetTwoLoadingPaneControlProps.js +2 -1
  298. package/lib/esm/components/notificationpane/NotificationPane.js +1 -5
  299. package/lib/esm/components/notificationpane/subcomponents/CloseChatButton.js +0 -2
  300. package/lib/esm/components/notificationpane/subcomponents/DismissButton.js +0 -2
  301. package/lib/esm/components/outofofficehourspane/OOOHPane.js +3 -6
  302. package/lib/esm/components/outofofficehourspane/common/presetFourProps/presetFourOOOHPaneControlProps.js +2 -1
  303. package/lib/esm/components/outofofficehourspane/common/presetOneProps/presetOneOOOHPaneControlProps.js +2 -1
  304. package/lib/esm/components/outofofficehourspane/common/presetTwoProps/presetTwoOOOHPaneControlProps.js +2 -1
  305. package/lib/esm/components/postchatsurveypane/PostChatSurveyPane.js +2 -4
  306. package/lib/esm/components/postchatsurveypane/common/presetOneProps/presetOnePostChatSurveyPaneControlProps.js +2 -1
  307. package/lib/esm/components/prechatsurveypane/PreChatSurveyPane.js +110 -37
  308. package/lib/esm/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultichoiceInputStyles.js +1 -0
  309. package/lib/esm/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultilineTextInputStyles.js +1 -0
  310. package/lib/esm/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneTextInputStyles.js +1 -0
  311. package/lib/esm/components/prechatsurveypane/common/presetOneProps/presetOnePreChatSurveyPaneControlProps.js +2 -1
  312. package/lib/esm/components/proactivechatpane/ProactiveChatPane.js +26 -35
  313. package/lib/esm/components/proactivechatpane/common/presetTwo/presetTwoProps/presetTwoProactiveChatPaneComponentOverrides.js +1 -1
  314. package/lib/esm/components/reconnectchatpane/ReconnectChatPane.js +31 -39
  315. package/lib/esm/services/BroadcastService.js +12 -13
  316. package/lib/esm/services/EventQueue.js +3 -20
  317. package/lib/types/common/Constants.d.ts +2 -0
  318. package/lib/types/components/chatbutton/ChatButton.blankAnnouncements.a11y.spec.d.ts +1 -0
  319. package/lib/types/components/chatbutton/ChatButton.browseMode.a11y.spec.d.ts +1 -0
  320. package/lib/types/components/chatbutton/ChatButton.browseMode.unfixed.a11y.spec.d.ts +1 -0
  321. package/lib/types/components/confirmationpane/interfaces/IConfirmationPaneControlProps.d.ts +1 -0
  322. package/lib/types/components/header/interfaces/IHeaderStyleProps.d.ts +12 -0
  323. package/lib/types/components/inputvalidationpane/interfaces/IInputValidationPaneControlProps.d.ts +1 -0
  324. package/package.json +35 -18
@@ -0,0 +1,233 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import "@testing-library/jest-dom/extend-expect";
3
+ import { cleanup, render } from "@testing-library/react";
4
+ import { BroadcastServiceInitialize } from "../../services/BroadcastService";
5
+ import ChatButton from "./ChatButton";
6
+ import React from "react";
7
+ import { defaultChatButtonProps } from "./common/defaultProps/defaultChatButtonProps";
8
+
9
+ /**
10
+ * Repro / catcher for internal tracking — NVDA / JAWS in browse mode (virtual cursor)
11
+ * land on "Let's Chat, We're Online" multiple times when navigating with the
12
+ * down-arrow key.
13
+ *
14
+ * Root cause in code: `ChatButton` renders a Fluent UI `<Stack role="button">`
15
+ * with `tabIndex={0}` whose accessible name is computed from its visible
16
+ * children — a `<Label>` for the title (e.g. "Let's Chat!") and a `<Label>`
17
+ * for the subtitle (e.g. "We're online."). In browse mode, NVDA / JAWS treat
18
+ * the button itself AND each inner text node as separate virtual-cursor stops,
19
+ * each carrying the same announceable name fragments. There is no
20
+ * `aria-label` set by default, and the inner labels are not marked
21
+ * `aria-hidden="true"` (which is what would collapse them into a single
22
+ * announcement under the button container).
23
+ *
24
+ * Catcher contract: in the rendered chat-button subtree, at most ONE element
25
+ * may expose each of the title / subtitle strings as an announceable name
26
+ * source. An "announceable name source" here is:
27
+ * - an `aria-label` attribute on a focusable / role-bearing element, OR
28
+ * - a visible `<Label>` (or other text-bearing element) that is NOT
29
+ * `aria-hidden="true"` and is not nested inside an element that is
30
+ * `aria-hidden="true"`.
31
+ *
32
+ * Regression guard: in the rendered DOM, the parent role=button Stack owns a
33
+ * single consolidated aria-label (synthesized from title + subtitle, plus
34
+ * unread-count fragment when applicable) and the inner Labels live inside an
35
+ * aria-hidden text container so browse-mode lands on the button exactly once.
36
+ * Override paths (componentOverrides.title/subtitle/textContainer or a
37
+ * consumer-supplied controlProps.ariaLabel) are preserved unchanged so
38
+ * customers who manage their own accessible names are not affected.
39
+ */
40
+
41
+ beforeAll(() => {
42
+ BroadcastServiceInitialize("testChannel");
43
+ });
44
+ afterEach(() => {
45
+ cleanup();
46
+ });
47
+ const isInsideAriaHidden = el => {
48
+ let cursor = el;
49
+ while (cursor) {
50
+ if (cursor.getAttribute("aria-hidden") === "true") return true;
51
+ cursor = cursor.parentElement;
52
+ }
53
+ return false;
54
+ };
55
+ const visibleTextElementsMatching = (root, text) => {
56
+ return Array.from(root.querySelectorAll("*")).filter(el => {
57
+ if (isInsideAriaHidden(el)) return false;
58
+ // Only count leaf-ish text-bearing elements (don't double-count
59
+ // ancestors whose textContent obviously aggregates children).
60
+ const ownText = Array.from(el.childNodes).filter(n => n.nodeType === Node.TEXT_NODE).map(n => (n.textContent || "").trim()).join(" ").trim();
61
+ return ownText === text;
62
+ });
63
+ };
64
+
65
+ /**
66
+ * Regression guard for internal tracking — ChatButton must not produce duplicate
67
+ * NVDA / JAWS browse-mode stops. Visible title / subtitle text is excluded
68
+ * from the accessibility tree (aria-hidden) and the button container owns a
69
+ * single consolidated aria-label.
70
+ */
71
+ describe("ChatButton — browse-mode duplicate stops (internal tracking)", () => {
72
+ it("title text 'Let's Chat!' must NOT appear as a visible (non-aria-hidden) name source in the chat-button subtree", () => {
73
+ const {
74
+ container
75
+ } = render(/*#__PURE__*/React.createElement(ChatButton, defaultChatButtonProps));
76
+ const button = container.firstElementChild;
77
+ expect(button).not.toBeNull();
78
+ const titleStops = visibleTextElementsMatching(button, "Let's Chat!");
79
+ // The visible title should be excluded from the accessibility tree
80
+ // (e.g. via aria-hidden on the text container) so the announced name
81
+ // comes solely from the consolidated aria-label on the button. Any
82
+ // exposed text-bearing element with this exact text creates an
83
+ // additional browse-mode stop and reproduces internal tracking.
84
+ expect(titleStops.length).toBe(0);
85
+ });
86
+ it("subtitle text 'We're online.' must NOT appear as a visible (non-aria-hidden) name source in the chat-button subtree", () => {
87
+ const {
88
+ container
89
+ } = render(/*#__PURE__*/React.createElement(ChatButton, defaultChatButtonProps));
90
+ const button = container.firstElementChild;
91
+ expect(button).not.toBeNull();
92
+ const subtitleStops = visibleTextElementsMatching(button, "We're online.");
93
+ expect(subtitleStops.length).toBe(0);
94
+ });
95
+ it("the chat-button container must own a single consolidated aria-label so browse mode lands on it once", () => {
96
+ const {
97
+ container
98
+ } = render(/*#__PURE__*/React.createElement(ChatButton, defaultChatButtonProps));
99
+ const button = container.firstElementChild;
100
+ expect(button).not.toBeNull();
101
+ // Either the container has a non-empty aria-label, OR every inner
102
+ // text-bearing descendant is aria-hidden so the computed name comes
103
+ // from the inner text exactly once with no extra browse-mode stops.
104
+ const hasAriaLabel = !!(button.getAttribute("aria-label") || "").trim();
105
+ const innerVisibleText = visibleTextElementsMatching(button, "Let's Chat!").length + visibleTextElementsMatching(button, "We're online.").length;
106
+ // Today: hasAriaLabel === false (default ariaLabel is undefined) AND
107
+ // innerVisibleText > 0. The catcher requires at least one of these
108
+ // to flip.
109
+ expect(hasAriaLabel || innerVisibleText === 0).toBe(true);
110
+ });
111
+ it("the synthesized aria-label includes the unread-count fragment when hideNotificationBubble=false and unreadMessageCount > 0", () => {
112
+ const props = {
113
+ ...defaultChatButtonProps,
114
+ controlProps: {
115
+ ...defaultChatButtonProps.controlProps,
116
+ hideNotificationBubble: false,
117
+ unreadMessageCount: "3",
118
+ ariaLabelUnreadMessageString: "you have new messages",
119
+ titleText: "Let's Chat!",
120
+ subtitleText: "We're online."
121
+ }
122
+ };
123
+ const {
124
+ container
125
+ } = render(/*#__PURE__*/React.createElement(ChatButton, props));
126
+ const button = container.firstElementChild;
127
+ const ariaLabel = button.getAttribute("aria-label") || "";
128
+ expect(ariaLabel).toContain("3");
129
+ expect(ariaLabel).toContain("you have new messages");
130
+ expect(ariaLabel).toContain("Let's Chat!");
131
+ expect(ariaLabel).toContain("We're online.");
132
+ });
133
+ it("a consumer-supplied controlProps.ariaLabel wins over the synthesized label", () => {
134
+ const props = {
135
+ ...defaultChatButtonProps,
136
+ controlProps: {
137
+ ...defaultChatButtonProps.controlProps,
138
+ ariaLabel: "Talk to a live agent"
139
+ }
140
+ };
141
+ const {
142
+ container
143
+ } = render(/*#__PURE__*/React.createElement(ChatButton, props));
144
+ const button = container.firstElementChild;
145
+ expect(button.getAttribute("aria-label")).toBe("Talk to a live agent");
146
+ });
147
+ it("componentOverrides.textContainer preserves consumer-rendered visible text (synthesis is skipped)", () => {
148
+ const customText = "My custom chat text";
149
+ const props = {
150
+ ...defaultChatButtonProps,
151
+ componentOverrides: {
152
+ textContainer: /*#__PURE__*/React.createElement("div", {
153
+ id: "my-custom-text"
154
+ }, customText)
155
+ }
156
+ };
157
+ const {
158
+ container
159
+ } = render(/*#__PURE__*/React.createElement(ChatButton, props));
160
+ const button = container.firstElementChild;
161
+ // The custom text MUST remain visible in the a11y tree so consumers
162
+ // who replace the text container keep their announced text.
163
+ const customStops = visibleTextElementsMatching(button, customText);
164
+ expect(customStops.length).toBeGreaterThan(0);
165
+ // And the button must NOT carry a synthesized aria-label that would
166
+ // override the consumer's content.
167
+ const ariaLabel = (button.getAttribute("aria-label") || "").trim();
168
+ expect(ariaLabel).toBe("");
169
+ });
170
+ it("componentOverrides.title preserves consumer-rendered visible title (synthesis is skipped)", () => {
171
+ const customTitle = "Custom override title";
172
+ const props = {
173
+ ...defaultChatButtonProps,
174
+ componentOverrides: {
175
+ title: /*#__PURE__*/React.createElement("span", {
176
+ id: "my-custom-title"
177
+ }, customTitle)
178
+ }
179
+ };
180
+ const {
181
+ container
182
+ } = render(/*#__PURE__*/React.createElement(ChatButton, props));
183
+ const button = container.firstElementChild;
184
+ const customStops = visibleTextElementsMatching(button, customTitle);
185
+ expect(customStops.length).toBeGreaterThan(0);
186
+ const ariaLabel = (button.getAttribute("aria-label") || "").trim();
187
+ expect(ariaLabel).toBe("");
188
+ });
189
+
190
+ // Regression guard for the strict string-equality slip-throughs that
191
+ // brittle `unreadMessageCount !== "0"` allowed: values that coerce to
192
+ // numeric 0 (or non-numeric noise) must NOT render the bubble nor pollute
193
+ // the synthesized aria-label with a "0 you have new messages" fragment.
194
+ describe.each([["padded zero (' 0 ')", " 0 "], ["decimal zero ('0.0')", "0.0"], ["empty string ('')", ""], ["non-numeric ('abc')", "abc"]])("zero-equivalent unreadMessageCount: %s", (_label, value) => {
195
+ it("does NOT render the notification bubble", () => {
196
+ const props = {
197
+ ...defaultChatButtonProps,
198
+ controlProps: {
199
+ ...defaultChatButtonProps.controlProps,
200
+ hideNotificationBubble: false,
201
+ unreadMessageCount: value,
202
+ ariaLabelUnreadMessageString: "you have new messages"
203
+ }
204
+ };
205
+ const {
206
+ container
207
+ } = render(/*#__PURE__*/React.createElement(ChatButton, props));
208
+ const bubble = container.querySelector("[id$='-notification-bubble']");
209
+ expect(bubble).toBeNull();
210
+ });
211
+ it("does NOT inject the unread-count fragment into the synthesized aria-label", () => {
212
+ const props = {
213
+ ...defaultChatButtonProps,
214
+ controlProps: {
215
+ ...defaultChatButtonProps.controlProps,
216
+ hideNotificationBubble: false,
217
+ unreadMessageCount: value,
218
+ ariaLabelUnreadMessageString: "you have new messages"
219
+ }
220
+ };
221
+ const {
222
+ container
223
+ } = render(/*#__PURE__*/React.createElement(ChatButton, props));
224
+ const button = container.firstElementChild;
225
+ const ariaLabel = button.getAttribute("aria-label") || "";
226
+ expect(ariaLabel).not.toContain("you have new messages");
227
+ // and the raw zero-equivalent must not leak into the label
228
+ if (value.trim().length > 0) {
229
+ expect(ariaLabel).not.toContain(value.trim());
230
+ }
231
+ });
232
+ });
233
+ });
@@ -0,0 +1,111 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import "@testing-library/jest-dom/extend-expect";
3
+ import { cleanup, render } from "@testing-library/react";
4
+ import { BroadcastServiceInitialize } from "../../services/BroadcastService";
5
+ import ChatButton from "./ChatButton";
6
+ import React from "react";
7
+ import { defaultChatButtonControlProps } from "./common/defaultProps/defaultChatButtonControlProps";
8
+ import { defaultChatButtonProps } from "./common/defaultProps/defaultChatButtonProps";
9
+ const expectedTitle = defaultChatButtonControlProps.titleText;
10
+ const expectedSubtitle = defaultChatButtonControlProps.subtitleText;
11
+
12
+ /**
13
+ * Repro / catcher for internal tracking — NVDA / JAWS in browse mode (virtual cursor)
14
+ * land on "Let's Chat, We're Online" multiple times when navigating with the
15
+ * down-arrow key.
16
+ *
17
+ * Root cause in code: `ChatButton` renders a Fluent UI `<Stack role="button">`
18
+ * with `tabIndex={0}` whose accessible name is computed from its visible
19
+ * children — a `<Label>` for the title (e.g. "Let's Chat!") and a `<Label>`
20
+ * for the subtitle (e.g. "We're online."). In browse mode, NVDA / JAWS treat
21
+ * the button itself AND each inner text node as separate virtual-cursor stops,
22
+ * each carrying the same announceable name fragments. There is no
23
+ * `aria-label` set by default, and the inner labels are not marked
24
+ * `aria-hidden="true"` (which is what would collapse them into a single
25
+ * announcement under the button container).
26
+ *
27
+ * Catcher contract: the title / subtitle strings must NOT appear as
28
+ * additional announceable name sources in the chat-button subtree (only the
29
+ * single consolidated aria-label on the role=button container should name the
30
+ * button). An "announceable name source" here is:
31
+ * - an `aria-label` attribute on a focusable / role-bearing element, OR
32
+ * - a visible `<Label>` (or other text-bearing element) that is NOT
33
+ * `aria-hidden="true"` and is not nested inside an element that is
34
+ * `aria-hidden="true"`.
35
+ *
36
+ * Expected to FAIL today: the rendered DOM contains BOTH the title text node
37
+ * AND the subtitle text node as bare visible text, and the parent Stack has
38
+ * no `aria-label` to consolidate them. Browse-mode therefore sees three
39
+ * stops (button, title, subtitle) all carrying the same combined name.
40
+ */
41
+
42
+ beforeAll(() => {
43
+ BroadcastServiceInitialize("testChannel");
44
+ });
45
+ afterEach(() => {
46
+ cleanup();
47
+ });
48
+ const isInsideAriaHidden = el => {
49
+ let cursor = el;
50
+ while (cursor) {
51
+ if (cursor.getAttribute("aria-hidden") === "true") return true;
52
+ cursor = cursor.parentElement;
53
+ }
54
+ return false;
55
+ };
56
+ const visibleTextElementsMatching = (root, text) => {
57
+ return Array.from(root.querySelectorAll("*")).filter(el => {
58
+ if (isInsideAriaHidden(el)) return false;
59
+ // Only count leaf-ish text-bearing elements (don't double-count
60
+ // ancestors whose textContent obviously aggregates children).
61
+ const ownText = Array.from(el.childNodes).filter(n => n.nodeType === Node.TEXT_NODE).map(n => (n.textContent || "").trim()).join(" ").trim();
62
+ return ownText === text;
63
+ });
64
+ };
65
+
66
+ /**
67
+ * SKIPPED until the source fix lands. Un-skip the describe below to validate
68
+ * the fix to internal tracking; the suite is expected to FAIL today against unfixed
69
+ * source. Mirrors the chat-widget `*.unfixed.a11y.spec.tsx` convention.
70
+ */
71
+ describe.skip("ChatButton — browse-mode duplicate stops (internal tracking)", () => {
72
+ it(`title text '${expectedTitle}' must NOT appear as a visible (non-aria-hidden) name source in the chat-button subtree`, () => {
73
+ const {
74
+ container
75
+ } = render(/*#__PURE__*/React.createElement(ChatButton, defaultChatButtonProps));
76
+ const button = container.firstElementChild;
77
+ expect(button).not.toBeNull();
78
+ const titleStops = visibleTextElementsMatching(button, expectedTitle);
79
+ // The visible title should be excluded from the accessibility tree
80
+ // (e.g. via aria-hidden on the text container) so the announced name
81
+ // comes solely from the consolidated aria-label on the button. Any
82
+ // exposed text-bearing element with this exact text creates an
83
+ // additional browse-mode stop and reproduces internal tracking.
84
+ expect(titleStops.length).toBe(0);
85
+ });
86
+ it(`subtitle text '${expectedSubtitle}' must NOT appear as a visible (non-aria-hidden) name source in the chat-button subtree`, () => {
87
+ const {
88
+ container
89
+ } = render(/*#__PURE__*/React.createElement(ChatButton, defaultChatButtonProps));
90
+ const button = container.firstElementChild;
91
+ expect(button).not.toBeNull();
92
+ const subtitleStops = visibleTextElementsMatching(button, expectedSubtitle);
93
+ expect(subtitleStops.length).toBe(0);
94
+ });
95
+ it("the chat-button container must own a single consolidated aria-label so browse mode lands on it once", () => {
96
+ const {
97
+ container
98
+ } = render(/*#__PURE__*/React.createElement(ChatButton, defaultChatButtonProps));
99
+ const button = container.firstElementChild;
100
+ expect(button).not.toBeNull();
101
+ // Either the container has a non-empty aria-label, OR every inner
102
+ // text-bearing descendant is aria-hidden so the computed name comes
103
+ // from the inner text exactly once with no extra browse-mode stops.
104
+ const hasAriaLabel = !!(button.getAttribute("aria-label") || "").trim();
105
+ const innerVisibleText = visibleTextElementsMatching(button, expectedTitle).length + visibleTextElementsMatching(button, expectedSubtitle).length;
106
+ // Today: hasAriaLabel === false (default ariaLabel is undefined) AND
107
+ // innerVisibleText > 0. The catcher requires at least one of these
108
+ // to flip.
109
+ expect(hasAriaLabel || innerVisibleText === 0).toBe(true);
110
+ });
111
+ });
@@ -11,47 +11,50 @@ import { defaultChatButtonSubTitleStyles } from "./common/defaultStyles/defaultC
11
11
  import { defaultChatButtonTextContainerStyles } from "./common/defaultStyles/defaultChatButtonTextContainerStyles";
12
12
  import { defaultChatButtonTitleStyles } from "./common/defaultStyles/defaultChatButtonTitleStyles";
13
13
 
14
+ // Returns true when the unread-message count represents a positive number.
15
+ // Defensive against non-strict callers that may pass " 0 ", "0.0", "" or a
16
+ // stringified numeric 0; only a finite count strictly greater than zero counts
17
+ // as "unread" for both the notification bubble and the synthesized aria-label.
18
+ function hasUnreadMessages(unreadMessageCount) {
19
+ if (unreadMessageCount === undefined || unreadMessageCount === null) {
20
+ return false;
21
+ }
22
+ const parsed = Number(unreadMessageCount);
23
+ return Number.isFinite(parsed) && parsed > 0;
24
+ }
14
25
  function NotificationBubble(props, parentId) {
15
26
  var _props$styleProps, _props$controlProps;
16
-
17
27
  const notificationBubbleStyles = {
18
28
  root: Object.assign({}, defaultChatButtonNotificationBubbleStyles, (_props$styleProps = props.styleProps) === null || _props$styleProps === void 0 ? void 0 : _props$styleProps.notificationBubbleStyleProps)
19
29
  };
20
30
  const unreadMessageCount = ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.unreadMessageCount) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.unreadMessageCount);
21
-
22
- if (unreadMessageCount !== "0") {
23
- var _props$componentOverr, _props$controlProps2, _props$controlProps3, _props$styleProps2, _props$styleProps2$cl, _props$controlProps4, _props$controlProps5;
24
-
31
+ if (hasUnreadMessages(unreadMessageCount)) {
32
+ var _props$componentOverr, _props$controlProps2, _props$controlProps3, _props$styleProps2, _props$controlProps4, _props$controlProps5;
25
33
  return decodeComponentString((_props$componentOverr = props.componentOverrides) === null || _props$componentOverr === void 0 ? void 0 : _props$componentOverr.notificationBubble) || /*#__PURE__*/React.createElement(Stack, {
26
34
  "aria-live": "polite",
27
35
  styles: notificationBubbleStyles,
28
36
  "aria-label": (_props$controlProps2 = props.controlProps) !== null && _props$controlProps2 !== void 0 && _props$controlProps2.ariaLabelUnreadMessageString ? (_props$controlProps3 = props.controlProps) === null || _props$controlProps3 === void 0 ? void 0 : _props$controlProps3.ariaLabelUnreadMessageString : defaultChatButtonControlProps.ariaLabelUnreadMessageString,
29
- className: (_props$styleProps2 = props.styleProps) === null || _props$styleProps2 === void 0 ? void 0 : (_props$styleProps2$cl = _props$styleProps2.classNames) === null || _props$styleProps2$cl === void 0 ? void 0 : _props$styleProps2$cl.notificationBubbleClassName,
37
+ className: (_props$styleProps2 = props.styleProps) === null || _props$styleProps2 === void 0 || (_props$styleProps2 = _props$styleProps2.classNames) === null || _props$styleProps2 === void 0 ? void 0 : _props$styleProps2.notificationBubbleClassName,
30
38
  id: parentId + "-notification-bubble"
31
39
  }, unreadMessageCount, /*#__PURE__*/React.createElement("span", {
32
40
  style: HiddenTextStyles
33
41
  }, (_props$controlProps4 = props.controlProps) !== null && _props$controlProps4 !== void 0 && _props$controlProps4.unreadMessageString ? (_props$controlProps5 = props.controlProps) === null || _props$controlProps5 === void 0 ? void 0 : _props$controlProps5.unreadMessageString : defaultChatButtonControlProps.unreadMessageString));
34
42
  }
35
-
36
43
  return null;
37
44
  }
38
-
39
45
  function IconContainer(props, parentId) {
40
- var _props$styleProps3, _props$componentOverr2, _props$styleProps4, _props$styleProps4$cl;
41
-
46
+ var _props$styleProps3, _props$componentOverr2, _props$styleProps4;
42
47
  const iconContainerStyles = {
43
48
  root: Object.assign({}, defaultChatButtonIconContainerStyles, (_props$styleProps3 = props.styleProps) === null || _props$styleProps3 === void 0 ? void 0 : _props$styleProps3.iconStyleProps)
44
49
  };
45
50
  return decodeComponentString((_props$componentOverr2 = props.componentOverrides) === null || _props$componentOverr2 === void 0 ? void 0 : _props$componentOverr2.iconContainer) || /*#__PURE__*/React.createElement(Icon, {
46
- className: (_props$styleProps4 = props.styleProps) === null || _props$styleProps4 === void 0 ? void 0 : (_props$styleProps4$cl = _props$styleProps4.classNames) === null || _props$styleProps4$cl === void 0 ? void 0 : _props$styleProps4$cl.iconContainerClassName,
51
+ className: (_props$styleProps4 = props.styleProps) === null || _props$styleProps4 === void 0 || (_props$styleProps4 = _props$styleProps4.classNames) === null || _props$styleProps4 === void 0 ? void 0 : _props$styleProps4.iconContainerClassName,
47
52
  styles: iconContainerStyles,
48
53
  id: parentId + "-icon-container"
49
54
  });
50
55
  }
51
-
52
56
  function TextContainer(props, parentId) {
53
- var _props$styleProps5, _props$styleProps6, _props$styleProps7, _props$controlProps6, _props$controlProps7, _props$controlProps8, _props$controlProps9, _props$controlProps10, _props$controlProps11, _props$componentOverr3, _props$styleProps8, _props$styleProps8$cl, _props$componentOverr4, _props$styleProps9, _props$styleProps9$cl, _props$componentOverr5, _props$styleProps10, _props$styleProps10$c;
54
-
57
+ var _props$styleProps5, _props$styleProps6, _props$styleProps7, _props$controlProps6, _props$controlProps7, _props$controlProps8, _props$controlProps9, _props$controlProps0, _props$controlProps1, _props$componentOverr3, _props$componentOverr4, _props$componentOverr5, _props$styleProps8, _props$componentOverr6, _props$styleProps9, _props$componentOverr7, _props$styleProps0;
55
58
  const textContainerStyles = {
56
59
  root: Object.assign({}, defaultChatButtonTextContainerStyles, (_props$styleProps5 = props.styleProps) === null || _props$styleProps5 === void 0 ? void 0 : _props$styleProps5.textContainerStyleProps)
57
60
  };
@@ -65,43 +68,65 @@ function TextContainer(props, parentId) {
65
68
  const hideChatSubtitle = ((_props$controlProps7 = props.controlProps) === null || _props$controlProps7 === void 0 ? void 0 : _props$controlProps7.hideChatSubtitle) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatSubtitle);
66
69
  const titleDir = ((_props$controlProps8 = props.controlProps) === null || _props$controlProps8 === void 0 ? void 0 : _props$controlProps8.dir) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.dir);
67
70
  const titleText = ((_props$controlProps9 = props.controlProps) === null || _props$controlProps9 === void 0 ? void 0 : _props$controlProps9.titleText) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.titleText);
68
- const subtitleDir = ((_props$controlProps10 = props.controlProps) === null || _props$controlProps10 === void 0 ? void 0 : _props$controlProps10.dir) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.dir);
69
- const subtitleText = ((_props$controlProps11 = props.controlProps) === null || _props$controlProps11 === void 0 ? void 0 : _props$controlProps11.subtitleText) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.subtitleText);
70
- return decodeComponentString((_props$componentOverr3 = props.componentOverrides) === null || _props$componentOverr3 === void 0 ? void 0 : _props$componentOverr3.textContainer) || /*#__PURE__*/React.createElement(Stack, {
71
+ const subtitleDir = ((_props$controlProps0 = props.controlProps) === null || _props$controlProps0 === void 0 ? void 0 : _props$controlProps0.dir) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.dir);
72
+ const subtitleText = ((_props$controlProps1 = props.controlProps) === null || _props$controlProps1 === void 0 ? void 0 : _props$controlProps1.subtitleText) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.subtitleText);
73
+
74
+ // internal tracking: when the default title / subtitle Labels are used, hide the
75
+ // text container subtree from the accessibility tree. The button container
76
+ // owns a consolidated aria-label that already announces the same text, so
77
+ // exposing the inner Labels causes NVDA / JAWS browse-mode to land on the
78
+ // same announcement multiple times. Customer overrides for title /
79
+ // subtitle keep their default a11y behavior so they can manage their own
80
+ // accessible names.
81
+ const hideTextFromA11yTree = !((_props$componentOverr3 = props.componentOverrides) !== null && _props$componentOverr3 !== void 0 && _props$componentOverr3.title) && !((_props$componentOverr4 = props.componentOverrides) !== null && _props$componentOverr4 !== void 0 && _props$componentOverr4.subtitle);
82
+ return decodeComponentString((_props$componentOverr5 = props.componentOverrides) === null || _props$componentOverr5 === void 0 ? void 0 : _props$componentOverr5.textContainer) || /*#__PURE__*/React.createElement(Stack, {
71
83
  styles: textContainerStyles,
72
- className: (_props$styleProps8 = props.styleProps) === null || _props$styleProps8 === void 0 ? void 0 : (_props$styleProps8$cl = _props$styleProps8.classNames) === null || _props$styleProps8$cl === void 0 ? void 0 : _props$styleProps8$cl.textContainerClassName,
73
- id: parentId + "-text-container"
74
- }, !hideChatTitle && (decodeComponentString((_props$componentOverr4 = props.componentOverrides) === null || _props$componentOverr4 === void 0 ? void 0 : _props$componentOverr4.title) || /*#__PURE__*/React.createElement(Label, {
84
+ className: (_props$styleProps8 = props.styleProps) === null || _props$styleProps8 === void 0 || (_props$styleProps8 = _props$styleProps8.classNames) === null || _props$styleProps8 === void 0 ? void 0 : _props$styleProps8.textContainerClassName,
85
+ id: parentId + "-text-container",
86
+ "aria-hidden": hideTextFromA11yTree || undefined
87
+ }, !hideChatTitle && (decodeComponentString((_props$componentOverr6 = props.componentOverrides) === null || _props$componentOverr6 === void 0 ? void 0 : _props$componentOverr6.title) || /*#__PURE__*/React.createElement(Label, {
75
88
  styles: titleStyles,
76
89
  dir: titleDir,
77
- className: (_props$styleProps9 = props.styleProps) === null || _props$styleProps9 === void 0 ? void 0 : (_props$styleProps9$cl = _props$styleProps9.classNames) === null || _props$styleProps9$cl === void 0 ? void 0 : _props$styleProps9$cl.titleClassName,
90
+ className: (_props$styleProps9 = props.styleProps) === null || _props$styleProps9 === void 0 || (_props$styleProps9 = _props$styleProps9.classNames) === null || _props$styleProps9 === void 0 ? void 0 : _props$styleProps9.titleClassName,
78
91
  id: parentId + "-title"
79
- }, titleText)), !hideChatSubtitle && (decodeComponentString((_props$componentOverr5 = props.componentOverrides) === null || _props$componentOverr5 === void 0 ? void 0 : _props$componentOverr5.subtitle) || /*#__PURE__*/React.createElement(Label, {
92
+ }, titleText)), !hideChatSubtitle && (decodeComponentString((_props$componentOverr7 = props.componentOverrides) === null || _props$componentOverr7 === void 0 ? void 0 : _props$componentOverr7.subtitle) || /*#__PURE__*/React.createElement(Label, {
80
93
  styles: subtitleStyles,
81
94
  dir: subtitleDir,
82
- className: (_props$styleProps10 = props.styleProps) === null || _props$styleProps10 === void 0 ? void 0 : (_props$styleProps10$c = _props$styleProps10.classNames) === null || _props$styleProps10$c === void 0 ? void 0 : _props$styleProps10$c.subtitleClassName,
95
+ className: (_props$styleProps0 = props.styleProps) === null || _props$styleProps0 === void 0 || (_props$styleProps0 = _props$styleProps0.classNames) === null || _props$styleProps0 === void 0 ? void 0 : _props$styleProps0.subtitleClassName,
83
96
  id: parentId + "-subtitle"
84
97
  }, subtitleText)));
85
98
  }
86
-
87
99
  function ChatButton(props) {
88
- var _props$controlProps12, _props$controlProps13, _props$controlProps14, _props$controlProps15, _props$controlProps16, _props$controlProps17, _props$controlProps18, _props$controlProps19, _props$styleProps11;
100
+ var _props$controlProps10, _props$controlProps11, _props$controlProps12, _props$controlProps13, _props$controlProps14, _props$controlProps15, _props$controlProps16, _props$controlProps17, _props$controlProps18, _props$controlProps19, _props$controlProps20, _props$controlProps21, _props$controlProps22, _props$componentOverr8, _props$componentOverr9, _props$componentOverr0, _props$controlProps23, _props$styleProps1;
101
+ const elementId = ((_props$controlProps10 = props.controlProps) === null || _props$controlProps10 === void 0 ? void 0 : _props$controlProps10.id) ?? Ids.DefaultChatButtonId;
102
+ const defaultRole = ((_props$controlProps11 = props.controlProps) === null || _props$controlProps11 === void 0 ? void 0 : _props$controlProps11.role) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.role);
103
+ const containersDir = ((_props$controlProps12 = props.controlProps) === null || _props$controlProps12 === void 0 ? void 0 : _props$controlProps12.dir) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.dir);
104
+ const hideChatButton = ((_props$controlProps13 = props.controlProps) === null || _props$controlProps13 === void 0 ? void 0 : _props$controlProps13.hideChatButton) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatButton);
105
+ const hideChatIcon = ((_props$controlProps14 = props.controlProps) === null || _props$controlProps14 === void 0 ? void 0 : _props$controlProps14.hideChatIcon) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatIcon);
106
+ const hideChatTextContainer = ((_props$controlProps15 = props.controlProps) === null || _props$controlProps15 === void 0 ? void 0 : _props$controlProps15.hideChatTextContainer) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatTextContainer);
107
+ const hideNotificationBubble = ((_props$controlProps16 = props.controlProps) === null || _props$controlProps16 === void 0 ? void 0 : _props$controlProps16.hideNotificationBubble) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideNotificationBubble);
89
108
 
90
- const elementId = ((_props$controlProps12 = props.controlProps) === null || _props$controlProps12 === void 0 ? void 0 : _props$controlProps12.id) ?? Ids.DefaultChatButtonId;
91
- const defaultAriaLabel = ((_props$controlProps13 = props.controlProps) === null || _props$controlProps13 === void 0 ? void 0 : _props$controlProps13.ariaLabel) ?? defaultChatButtonControlProps.ariaLabel;
92
- const defaultRole = ((_props$controlProps14 = props.controlProps) === null || _props$controlProps14 === void 0 ? void 0 : _props$controlProps14.role) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.role);
93
- const containersDir = ((_props$controlProps15 = props.controlProps) === null || _props$controlProps15 === void 0 ? void 0 : _props$controlProps15.dir) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.dir);
94
- const hideChatButton = ((_props$controlProps16 = props.controlProps) === null || _props$controlProps16 === void 0 ? void 0 : _props$controlProps16.hideChatButton) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatButton);
95
- const hideChatIcon = ((_props$controlProps17 = props.controlProps) === null || _props$controlProps17 === void 0 ? void 0 : _props$controlProps17.hideChatIcon) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatIcon);
96
- const hideChatTextContainer = ((_props$controlProps18 = props.controlProps) === null || _props$controlProps18 === void 0 ? void 0 : _props$controlProps18.hideChatTextContainer) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatTextContainer);
97
- const hideNotificationBubble = ((_props$controlProps19 = props.controlProps) === null || _props$controlProps19 === void 0 ? void 0 : _props$controlProps19.hideNotificationBubble) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideNotificationBubble);
109
+ // internal tracking: when the consumer has not supplied a custom aria-label and
110
+ // the default title / subtitle Labels are in play, synthesize a single
111
+ // consolidated aria-label from the visible text so NVDA / JAWS browse
112
+ // mode lands on the role=button container exactly once. The text
113
+ // container is also marked aria-hidden in TextContainer so the inner
114
+ // labels do not produce additional virtual-cursor stops.
115
+ const titleText = ((_props$controlProps17 = props.controlProps) === null || _props$controlProps17 === void 0 ? void 0 : _props$controlProps17.titleText) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.titleText);
116
+ const subtitleText = ((_props$controlProps18 = props.controlProps) === null || _props$controlProps18 === void 0 ? void 0 : _props$controlProps18.subtitleText) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.subtitleText);
117
+ const hideChatTitle = ((_props$controlProps19 = props.controlProps) === null || _props$controlProps19 === void 0 ? void 0 : _props$controlProps19.hideChatTitle) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatTitle);
118
+ const hideChatSubtitle = ((_props$controlProps20 = props.controlProps) === null || _props$controlProps20 === void 0 ? void 0 : _props$controlProps20.hideChatSubtitle) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.hideChatSubtitle);
119
+ const unreadMessageCount = ((_props$controlProps21 = props.controlProps) === null || _props$controlProps21 === void 0 ? void 0 : _props$controlProps21.unreadMessageCount) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.unreadMessageCount);
120
+ const ariaLabelUnreadMessageString = ((_props$controlProps22 = props.controlProps) === null || _props$controlProps22 === void 0 ? void 0 : _props$controlProps22.ariaLabelUnreadMessageString) ?? (defaultChatButtonControlProps === null || defaultChatButtonControlProps === void 0 ? void 0 : defaultChatButtonControlProps.ariaLabelUnreadMessageString);
121
+ const canSynthesizeAriaLabel = !hideChatTextContainer && !((_props$componentOverr8 = props.componentOverrides) !== null && _props$componentOverr8 !== void 0 && _props$componentOverr8.textContainer) && !((_props$componentOverr9 = props.componentOverrides) !== null && _props$componentOverr9 !== void 0 && _props$componentOverr9.title) && !((_props$componentOverr0 = props.componentOverrides) !== null && _props$componentOverr0 !== void 0 && _props$componentOverr0.subtitle);
122
+ const synthesizedAriaLabel = canSynthesizeAriaLabel ? [!hideNotificationBubble && hasUnreadMessages(unreadMessageCount) ? `${unreadMessageCount} ${ariaLabelUnreadMessageString ?? ""}`.trim() : "", !hideChatTitle ? titleText : "", !hideChatSubtitle ? subtitleText : ""].filter(Boolean).join(" ").trim() : "";
123
+ const defaultAriaLabel = ((_props$controlProps23 = props.controlProps) === null || _props$controlProps23 === void 0 ? void 0 : _props$controlProps23.ariaLabel) ?? defaultChatButtonControlProps.ariaLabel ?? (synthesizedAriaLabel || undefined);
98
124
  const chatButtonGroupStyles = {
99
- root: Object.assign({}, defaultChatButtonGeneralStyles, (_props$styleProps11 = props.styleProps) === null || _props$styleProps11 === void 0 ? void 0 : _props$styleProps11.generalStyleProps)
125
+ root: Object.assign({}, defaultChatButtonGeneralStyles, (_props$styleProps1 = props.styleProps) === null || _props$styleProps1 === void 0 ? void 0 : _props$styleProps1.generalStyleProps)
100
126
  };
101
127
  const handleInitiateChatClick = useCallback(() => {
102
- var _props$controlProps20;
103
-
104
- if ((_props$controlProps20 = props.controlProps) !== null && _props$controlProps20 !== void 0 && _props$controlProps20.onClick) {
128
+ var _props$controlProps24;
129
+ if ((_props$controlProps24 = props.controlProps) !== null && _props$controlProps24 !== void 0 && _props$controlProps24.onClick) {
105
130
  const customEvent = {
106
131
  elementType: ElementType.ChatButton,
107
132
  elementId: elementId,
@@ -110,14 +135,14 @@ function ChatButton(props) {
110
135
  BroadcastService.postMessage(customEvent);
111
136
  props.controlProps.onClick();
112
137
  }
113
- }, []); // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
+ }, []);
114
139
 
140
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
115
141
  const handleInputKeyDown = e => {
116
142
  if (e.code === KeyCodes.ENTER || e.code === KeyCodes.SPACE) {
117
143
  handleInitiateChatClick();
118
144
  }
119
145
  };
120
-
121
146
  return /*#__PURE__*/React.createElement(React.Fragment, null, !hideChatButton && /*#__PURE__*/React.createElement(Stack, {
122
147
  horizontal: true,
123
148
  id: elementId,
@@ -130,5 +155,4 @@ function ChatButton(props) {
130
155
  "aria-label": defaultAriaLabel
131
156
  }, !hideChatIcon && IconContainer(props, elementId), !hideNotificationBubble && NotificationBubble(props, elementId), !hideChatTextContainer && TextContainer(props, elementId)));
132
157
  }
133
-
134
158
  export default ChatButton;