@microsoft/omnichannel-chat-components 1.1.19 → 1.2.0-main.5692126

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 (58) hide show
  1. package/lib/cjs/common/Constants.js +8 -11
  2. package/lib/cjs/components/callingcontainer/subcomponents/CurrentCall/CurrentCall.js +10 -3
  3. package/lib/cjs/components/callingcontainer/subcomponents/Timer/Timer.js +10 -1
  4. package/lib/cjs/components/chatbutton/ChatButton.blankAnnouncements.a11y.spec.js +158 -0
  5. package/lib/cjs/components/chatbutton/ChatButton.browseMode.a11y.spec.js +227 -0
  6. package/lib/cjs/components/chatbutton/ChatButton.browseMode.unfixed.a11y.spec.js +112 -0
  7. package/lib/cjs/components/chatbutton/ChatButton.js +52 -16
  8. package/lib/cjs/components/common/subcomponents/CloseButton.js +1 -3
  9. package/lib/cjs/components/confirmationpane/ConfirmationPane.js +10 -8
  10. package/lib/cjs/components/confirmationpane/common/defaultProps/defaultConfirmationPaneControlProps.js +1 -0
  11. package/lib/cjs/components/footer/subcomponents/AudioNotificationButton.js +11 -4
  12. package/lib/cjs/components/footer/subcomponents/DownloadTranscriptButton.js +1 -3
  13. package/lib/cjs/components/footer/subcomponents/EmailTranscriptButton.js +1 -3
  14. package/lib/cjs/components/header/Header.js +16 -4
  15. package/lib/cjs/components/header/common/defaultStyles/defaultHeaderStyleProps.js +23 -0
  16. package/lib/cjs/components/header/subcomponents/MinimizeButton.js +1 -3
  17. package/lib/cjs/components/inputvalidationpane/InputValidationPane.js +34 -14
  18. package/lib/cjs/components/inputvalidationpane/common/default/defaultProps/defaultInputValidationPaneControlProps.js +1 -0
  19. package/lib/cjs/components/notificationpane/subcomponents/CloseChatButton.js +1 -3
  20. package/lib/cjs/components/notificationpane/subcomponents/DismissButton.js +1 -3
  21. package/lib/cjs/components/prechatsurveypane/PreChatSurveyPane.js +94 -17
  22. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultichoiceInputStyles.js +1 -0
  23. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultilineTextInputStyles.js +1 -0
  24. package/lib/cjs/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneTextInputStyles.js +1 -0
  25. package/lib/cjs/package.json +1 -0
  26. package/lib/cjs/services/EventQueue.js +4 -7
  27. package/lib/esm/common/Constants.js +1 -1
  28. package/lib/esm/components/callingcontainer/subcomponents/CurrentCall/CurrentCall.js +10 -3
  29. package/lib/esm/components/callingcontainer/subcomponents/Timer/Timer.js +10 -1
  30. package/lib/esm/components/chatbutton/ChatButton.blankAnnouncements.a11y.spec.js +155 -0
  31. package/lib/esm/components/chatbutton/ChatButton.browseMode.a11y.spec.js +224 -0
  32. package/lib/esm/components/chatbutton/ChatButton.browseMode.unfixed.a11y.spec.js +108 -0
  33. package/lib/esm/components/chatbutton/ChatButton.js +53 -16
  34. package/lib/esm/components/common/subcomponents/CloseButton.js +1 -3
  35. package/lib/esm/components/confirmationpane/ConfirmationPane.js +10 -8
  36. package/lib/esm/components/confirmationpane/common/defaultProps/defaultConfirmationPaneControlProps.js +1 -0
  37. package/lib/esm/components/footer/subcomponents/AudioNotificationButton.js +11 -4
  38. package/lib/esm/components/footer/subcomponents/DownloadTranscriptButton.js +1 -3
  39. package/lib/esm/components/footer/subcomponents/EmailTranscriptButton.js +1 -3
  40. package/lib/esm/components/header/Header.js +16 -4
  41. package/lib/esm/components/header/common/defaultStyles/defaultHeaderStyleProps.js +23 -0
  42. package/lib/esm/components/header/subcomponents/MinimizeButton.js +1 -3
  43. package/lib/esm/components/inputvalidationpane/InputValidationPane.js +34 -14
  44. package/lib/esm/components/inputvalidationpane/common/default/defaultProps/defaultInputValidationPaneControlProps.js +1 -0
  45. package/lib/esm/components/notificationpane/subcomponents/CloseChatButton.js +1 -3
  46. package/lib/esm/components/notificationpane/subcomponents/DismissButton.js +1 -3
  47. package/lib/esm/components/prechatsurveypane/PreChatSurveyPane.js +94 -16
  48. package/lib/esm/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultichoiceInputStyles.js +1 -0
  49. package/lib/esm/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneMultilineTextInputStyles.js +1 -0
  50. package/lib/esm/components/prechatsurveypane/common/defaultProps/defaultStyles/defaultPreChatSurveyPaneTextInputStyles.js +1 -0
  51. package/lib/types/common/Constants.d.ts +2 -0
  52. package/lib/types/components/chatbutton/ChatButton.blankAnnouncements.a11y.spec.d.ts +1 -0
  53. package/lib/types/components/chatbutton/ChatButton.browseMode.a11y.spec.d.ts +1 -0
  54. package/lib/types/components/chatbutton/ChatButton.browseMode.unfixed.a11y.spec.d.ts +1 -0
  55. package/lib/types/components/confirmationpane/interfaces/IConfirmationPaneControlProps.d.ts +1 -0
  56. package/lib/types/components/header/interfaces/IHeaderStyleProps.d.ts +12 -0
  57. package/lib/types/components/inputvalidationpane/interfaces/IInputValidationPaneControlProps.d.ts +1 -0
  58. package/package.json +39 -31
@@ -5,9 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Texts = exports.Regex = exports.KeyCodes = exports.Ids = exports.IconNames = exports.HiddenTextStyles = exports.EventNames = exports.ElementType = exports.ButtonTypes = exports.AriaLabels = exports.AccessibilityBrightnessRatio = void 0;
7
7
  var _Class, _Class2, _Class3, _Class4, _Class5, _Class6, _Class7, _Class8;
8
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
9
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
10
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
11
8
  /* CSS Constants */
12
9
  const AccessibilityBrightnessRatio = exports.AccessibilityBrightnessRatio = 1.2;
13
10
  const HiddenTextStyles = exports.HiddenTextStyles = {
@@ -18,8 +15,8 @@ const HiddenTextStyles = exports.HiddenTextStyles = {
18
15
  clip: "rect(1px, 1px, 1px, 1px)",
19
16
  whiteSpace: "nowrap"
20
17
  };
21
- const KeyCodes = exports.KeyCodes = (_Class = class KeyCodes {}, _defineProperty(_Class, "ENTER", "Enter"), _defineProperty(_Class, "ESCAPE", "Escape"), _defineProperty(_Class, "SPACE", "Space"), _defineProperty(_Class, "DeclineCallHotKey", "D"), _defineProperty(_Class, "AcceptAudioCallHotKey", "S"), _defineProperty(_Class, "AcceptVideoCallHotKey", "A"), _defineProperty(_Class, "ToggleMicHotKey", "M"), _defineProperty(_Class, "ToggleCameraHotKey", "O"), _defineProperty(_Class, "EndCallHotKey", "H"), _Class);
22
- const Regex = exports.Regex = (_Class2 = class Regex {}, _defineProperty(_Class2, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _defineProperty(_Class2, "URLRegex", /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}|mailto:[^\s]+|tel:[^\s]+|sms:[^\s]+)/gi), _Class2);
18
+ const KeyCodes = exports.KeyCodes = (_Class = class KeyCodes {}, _Class.ENTER = "Enter", _Class.ESCAPE = "Escape", _Class.SPACE = "Space", _Class.DeclineCallHotKey = "D", _Class.AcceptAudioCallHotKey = "S", _Class.AcceptVideoCallHotKey = "A", _Class.ToggleMicHotKey = "M", _Class.ToggleCameraHotKey = "O", _Class.EndCallHotKey = "H", _Class);
19
+ const Regex = exports.Regex = (_Class2 = class Regex {}, _Class2.EmailRegex = "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])", _Class2.URLRegex = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}|mailto:[^\s]+|tel:[^\s]+|sms:[^\s]+)/gi, _Class2);
23
20
  let ElementType = exports.ElementType = /*#__PURE__*/function (ElementType) {
24
21
  ElementType["ChatButton"] = "ChatButton";
25
22
  ElementType["CloseButton"] = "CloseButton";
@@ -47,9 +44,9 @@ let ElementType = exports.ElementType = /*#__PURE__*/function (ElementType) {
47
44
  ElementType["Custom"] = "Custom";
48
45
  return ElementType;
49
46
  }({});
50
- const Ids = exports.Ids = (_Class3 = class Ids {}, _defineProperty(_Class3, "DefaultCallingContainerId", "lcw-calling-container"), _defineProperty(_Class3, "DefaultCurrentCallId", "lcw-current-call-container"), _defineProperty(_Class3, "CurrentCallActionGroupId", "lcw-current-call-action-icons"), _defineProperty(_Class3, "CurrentCallFooterId", "lcw-current-call-footer"), _defineProperty(_Class3, "RemoteVideoTileId", "lcw-remote-video"), _defineProperty(_Class3, "SelfVideoTileId", "lcw-self-video"), _defineProperty(_Class3, "VideoTileGroupId", "lcw-current-call-body"), _defineProperty(_Class3, "EndCallButtonId", "lcw-call-reject-button"), _defineProperty(_Class3, "MicButtonId", "lcw-toggle-audio"), _defineProperty(_Class3, "VideoButtonId", "lcw-toggle-video"), _defineProperty(_Class3, "CallTimerId", "lcw-current-call-timer"), _defineProperty(_Class3, "CurrentCallLeftGroupId", "lcw-current-call-left-group"), _defineProperty(_Class3, "CurrentCallMiddleGroupId", "lcw-current-call-middle-group"), _defineProperty(_Class3, "CurrentCallRightGroupId", "lcw-current-call-right-group"), _defineProperty(_Class3, "DefaultIncomingCallId", "lcw-incoming-call"), _defineProperty(_Class3, "DeclineCallButtonId", "lcw-call-reject-button"), _defineProperty(_Class3, "AudioCallButtonId", "lcw-call-accept-button"), _defineProperty(_Class3, "VideoCallButtonId", "lcw-video-call-accept-button"), _defineProperty(_Class3, "IncomingCallTitleId", "lcw-incoming-call-message"), _defineProperty(_Class3, "DefaultIncomingCallPopupId", "lcw-incoming-call-popup"), _defineProperty(_Class3, "IncomingCallLeftGroupId", "lcw-incoming-call-left-group"), _defineProperty(_Class3, "IncomingCallMiddleGroupId", "lcw-incoming-call-middle-group"), _defineProperty(_Class3, "IncomingCallRightGroupId", "lcw-incoming-call-right-group"), _defineProperty(_Class3, "DefaultChatButtonId", "lcw-components-chat-button"), _defineProperty(_Class3, "DefaultConfirmationPaneId", "lcw-components-confirmation-pane"), _defineProperty(_Class3, "CustomFooterId", "lcw-footer"), _defineProperty(_Class3, "DownloadTranscriptButtonId", "lcw-footer-download-transcript-button"), _defineProperty(_Class3, "EmailTranscriptButtonId", "lcw-footer-email-transcript-button"), _defineProperty(_Class3, "AudioNotificationButtonId", "lcw-footer-audio-notification-button"), _defineProperty(_Class3, "DefaultFooterId", "lcw-components-footer"), _defineProperty(_Class3, "FooterLeftGroupId", "lcw-footer-left-group"), _defineProperty(_Class3, "FooterMiddleGroupId", "lcw-footer-middle-group"), _defineProperty(_Class3, "FooterRightGroupId", "lcw-footer-right-group"), _defineProperty(_Class3, "DefaultHeaderId", "lcw-header"), _defineProperty(_Class3, "MinimizeButtonId", "lcw-header-minimize-button"), _defineProperty(_Class3, "CloseButtonId", "lcw-header-close-button"), _defineProperty(_Class3, "HeaderIconId", "lcw-header-icon"), _defineProperty(_Class3, "HeaderTitleId", "lcw-header-title"), _defineProperty(_Class3, "HeaderLeftGroupId", "lcw-header-left-group"), _defineProperty(_Class3, "HeaderMiddleGroupId", "lcw-header-middle-group"), _defineProperty(_Class3, "HeaderRightGroupId", "lcw-header-right-group"), _defineProperty(_Class3, "DefaultInputValidationPaneId", "lcw-email-transcript-dialog-container"), _defineProperty(_Class3, "DefaultInputValidationPaneInputId", "lcw-email-transcript-dialog-text-field"), _defineProperty(_Class3, "DefaultLoadingPaneId", "lcw-loading-pane"), _defineProperty(_Class3, "DefaultNotificationPaneId", "lcw-notification-pane"), _defineProperty(_Class3, "DefaultOOOHPaneId", "lcw-out-of-office-hours-pane"), _defineProperty(_Class3, "DefaultPostChatSurveyPaneId", "lcw-postchat-survey-pane"), _defineProperty(_Class3, "DefaultPreChatSurveyPaneId", "lcw-prechat-survey-pane-default"), _defineProperty(_Class3, "DefaultProactiveChatPaneId", "lcw-proactive-chat"), _defineProperty(_Class3, "DefaultReconnectChatPaneId", "lcw-reconnect-chat-pane"), _Class3);
51
- const ButtonTypes = exports.ButtonTypes = (_Class4 = class ButtonTypes {}, _defineProperty(_Class4, "Icon", "icon"), _defineProperty(_Class4, "Text", "text"), _Class4);
52
- const IconNames = exports.IconNames = (_Class5 = class IconNames {}, _defineProperty(_Class5, "DeclineCall", "DeclineCall"), _defineProperty(_Class5, "Microphone", "Microphone"), _defineProperty(_Class5, "MicOff2", "MicOff2"), _defineProperty(_Class5, "Video", "Video"), _defineProperty(_Class5, "VideoOff", "VideoOff"), _defineProperty(_Class5, "IncomingCall", "IncomingCall"), _defineProperty(_Class5, "ChromeClose", "ChromeClose"), _defineProperty(_Class5, "Download", "Download"), _defineProperty(_Class5, "Mail", "Mail"), _defineProperty(_Class5, "Volume3", "Volume3"), _defineProperty(_Class5, "Volume0", "Volume0"), _defineProperty(_Class5, "ChromeMinimize", "ChromeMinimize"), _Class5);
53
- const AriaLabels = exports.AriaLabels = (_Class6 = class AriaLabels {}, _defineProperty(_Class6, "EndCall", "End Call"), _defineProperty(_Class6, "MicMute", "Mute"), _defineProperty(_Class6, "MicUnmute", "Unmute"), _defineProperty(_Class6, "VideoTurnCameraOn", "Turn camera on"), _defineProperty(_Class6, "VideoTurnCameraOff", "Turn camera off"), _defineProperty(_Class6, "IncomingCallArea", "Incoming call area"), _defineProperty(_Class6, "RejectCall", "Reject call"), _defineProperty(_Class6, "AcceptVoiceCall", "Accept voice call"), _defineProperty(_Class6, "AcceptVideoCall", "Accept video Call"), _defineProperty(_Class6, "DeclineCall", "Decline Call"), _defineProperty(_Class6, "AudioCall", "Audio Call"), _defineProperty(_Class6, "VideoCall", "Video Call"), _defineProperty(_Class6, "LetsChatWeAreOnline", "Let's chat we are online"), _defineProperty(_Class6, "UnreadMessageString", "you have new messages"), _defineProperty(_Class6, "Close", "Close"), _defineProperty(_Class6, "ConfirmationPaneConfirm", "Close Chat"), _defineProperty(_Class6, "ConfirmationPaneCancel", "Cancel. Return to Chat"), _defineProperty(_Class6, "DownloadChatTranscript", "Download chat transcript"), _defineProperty(_Class6, "EmailTranscript", "Email Transcript"), _defineProperty(_Class6, "TurnSoundOff", "Turn sound off"), _defineProperty(_Class6, "TurnSoundOn", "Turn sound on"), _defineProperty(_Class6, "Minimize", "Minimize"), _defineProperty(_Class6, "EmailChatTranscriptPane", "Email Chat Transcript Pane"), _defineProperty(_Class6, "InputValidationPaneInput", "Please provide e-mail address to send transcript. The transcript will be sent after the chat ends. Email address text area"), _defineProperty(_Class6, "Save", "Save"), _defineProperty(_Class6, "Cancel", "Cancel"), _defineProperty(_Class6, "ProactiveChatPane", "Proactive Chat Pane"), _defineProperty(_Class6, "ChatNow", "Chat Now"), _defineProperty(_Class6, "ReconnectChatPane", "Reconnect Chat Pane"), _defineProperty(_Class6, "ReconnectChatPaneIcon", "Reconnect Chat Pane Icon"), _defineProperty(_Class6, "ContinueConversation", "Continue conversation"), _defineProperty(_Class6, "StartNewConversation", "Start new conversation"), _Class6);
54
- const EventNames = exports.EventNames = (_Class7 = class EventNames {}, _defineProperty(_Class7, "OnClick", "OnClick"), _defineProperty(_Class7, "OnEscapeKeyDown", "OnEscapeKeyDown"), _defineProperty(_Class7, "IncomingCallEnded", "IncomingCallEnded"), _Class7);
55
- const Texts = exports.Texts = (_Class8 = class Texts {}, _defineProperty(_Class8, "IncomingCallTitle", "Incoming Call"), _defineProperty(_Class8, "ChatButtonTitle", "Let's Chat!"), _defineProperty(_Class8, "ChatButtonSubtitle", "We're online."), _defineProperty(_Class8, "ChatButtonUnreadMessageString", "new messages"), _defineProperty(_Class8, "ChatButtonLargeUnreadMessageString", "99+"), _defineProperty(_Class8, "CloseButtonText", "Close"), _defineProperty(_Class8, "ConfirmationPaneTitle", "Close chat"), _defineProperty(_Class8, "ConfirmationPaneSubtitle", "Do you really want to close this chat?"), _defineProperty(_Class8, "ConfirmButtonText", "Close"), _defineProperty(_Class8, "EmailPlaceHolderText", "johnsmith@outlook.com"), _defineProperty(_Class8, "CancelButtonText", "Cancel"), _defineProperty(_Class8, "DownloadChatTranscriptText", "Download chat transcript"), _defineProperty(_Class8, "EmailTranscriptText", "Email Transcript"), _defineProperty(_Class8, "HeaderIcon", "Chat Icon"), _defineProperty(_Class8, "HeaderTitle", "Let's Chat"), _defineProperty(_Class8, "MinimizeText", "Minimize"), _defineProperty(_Class8, "InputValidationPaneTitleText", "Please provide e-mail address to send transcript."), _defineProperty(_Class8, "InputValidationPaneSubtitleText", "The transcript will be sent after the chat ends."), _defineProperty(_Class8, "InvalidInputErrorMessageText", "Enter a valid email address."), _defineProperty(_Class8, "SendButtonText", "Send"), _defineProperty(_Class8, "SaveButtonText", "Save"), _defineProperty(_Class8, "LoadingPaneTitleText", "Welcome to"), _defineProperty(_Class8, "LoadingPaneSubtitleText", "live chat support ..."), _defineProperty(_Class8, "LoadingPaneSpinnerText", "Loading ..."), _defineProperty(_Class8, "OOOHPaneTitleText", "Thanks for contacting us. You have reached us outside of our operating hours. An agent will respond when we open."), _defineProperty(_Class8, "PostChatSurveyPaneTitleText", "Post chat survey pane"), _defineProperty(_Class8, "ProactiveChatPaneTitleText", "Welcome to"), _defineProperty(_Class8, "ProactiveChatPaneSubtitleText", "Live chat support!"), _defineProperty(_Class8, "ProactiveChatPaneBodyTitleText", "Hi! Have any questions? I am here to help."), _defineProperty(_Class8, "ProactiveChatPaneStartButtonText", "Chat Now"), _defineProperty(_Class8, "ReconnectChatPaneTitleText", "Previous session detected"), _defineProperty(_Class8, "ReconnectChatPaneSubtitleText", "We have detected a previous chat session. Would you like to continue with your previous session?"), _defineProperty(_Class8, "ReconnectChatPaneContinueChatButtonText", "Continue conversation"), _defineProperty(_Class8, "ReconnectChatPaneStartNewChatButtonText", "Start new conversation"), _Class8);
47
+ const Ids = exports.Ids = (_Class3 = class Ids {}, _Class3.DefaultCallingContainerId = "lcw-calling-container", _Class3.DefaultCurrentCallId = "lcw-current-call-container", _Class3.CurrentCallActionGroupId = "lcw-current-call-action-icons", _Class3.CurrentCallFooterId = "lcw-current-call-footer", _Class3.RemoteVideoTileId = "lcw-remote-video", _Class3.SelfVideoTileId = "lcw-self-video", _Class3.VideoTileGroupId = "lcw-current-call-body", _Class3.EndCallButtonId = "lcw-call-reject-button", _Class3.MicButtonId = "lcw-toggle-audio", _Class3.VideoButtonId = "lcw-toggle-video", _Class3.CallTimerId = "lcw-current-call-timer", _Class3.CurrentCallLeftGroupId = "lcw-current-call-left-group", _Class3.CurrentCallMiddleGroupId = "lcw-current-call-middle-group", _Class3.CurrentCallRightGroupId = "lcw-current-call-right-group", _Class3.DefaultIncomingCallId = "lcw-incoming-call", _Class3.DeclineCallButtonId = "lcw-call-reject-button", _Class3.AudioCallButtonId = "lcw-call-accept-button", _Class3.VideoCallButtonId = "lcw-video-call-accept-button", _Class3.IncomingCallTitleId = "lcw-incoming-call-message", _Class3.DefaultIncomingCallPopupId = "lcw-incoming-call-popup", _Class3.IncomingCallLeftGroupId = "lcw-incoming-call-left-group", _Class3.IncomingCallMiddleGroupId = "lcw-incoming-call-middle-group", _Class3.IncomingCallRightGroupId = "lcw-incoming-call-right-group", _Class3.DefaultChatButtonId = "lcw-components-chat-button", _Class3.DefaultConfirmationPaneId = "lcw-components-confirmation-pane", _Class3.CustomFooterId = "lcw-footer", _Class3.DownloadTranscriptButtonId = "lcw-footer-download-transcript-button", _Class3.EmailTranscriptButtonId = "lcw-footer-email-transcript-button", _Class3.AudioNotificationButtonId = "lcw-footer-audio-notification-button", _Class3.DefaultFooterId = "lcw-components-footer", _Class3.FooterLeftGroupId = "lcw-footer-left-group", _Class3.FooterMiddleGroupId = "lcw-footer-middle-group", _Class3.FooterRightGroupId = "lcw-footer-right-group", _Class3.DefaultHeaderId = "lcw-header", _Class3.MinimizeButtonId = "lcw-header-minimize-button", _Class3.CloseButtonId = "lcw-header-close-button", _Class3.HeaderIconId = "lcw-header-icon", _Class3.HeaderTitleId = "lcw-header-title", _Class3.HeaderLeftGroupId = "lcw-header-left-group", _Class3.HeaderMiddleGroupId = "lcw-header-middle-group", _Class3.HeaderRightGroupId = "lcw-header-right-group", _Class3.DefaultInputValidationPaneId = "lcw-email-transcript-dialog-container", _Class3.DefaultInputValidationPaneInputId = "lcw-email-transcript-dialog-text-field", _Class3.DefaultLoadingPaneId = "lcw-loading-pane", _Class3.DefaultNotificationPaneId = "lcw-notification-pane", _Class3.DefaultOOOHPaneId = "lcw-out-of-office-hours-pane", _Class3.DefaultPostChatSurveyPaneId = "lcw-postchat-survey-pane", _Class3.DefaultPreChatSurveyPaneId = "lcw-prechat-survey-pane-default", _Class3.DefaultProactiveChatPaneId = "lcw-proactive-chat", _Class3.DefaultReconnectChatPaneId = "lcw-reconnect-chat-pane", _Class3);
48
+ const ButtonTypes = exports.ButtonTypes = (_Class4 = class ButtonTypes {}, _Class4.Icon = "icon", _Class4.Text = "text", _Class4);
49
+ const IconNames = exports.IconNames = (_Class5 = class IconNames {}, _Class5.DeclineCall = "DeclineCall", _Class5.Microphone = "Microphone", _Class5.MicOff2 = "MicOff2", _Class5.Video = "Video", _Class5.VideoOff = "VideoOff", _Class5.IncomingCall = "IncomingCall", _Class5.ChromeClose = "ChromeClose", _Class5.Download = "Download", _Class5.Mail = "Mail", _Class5.Volume3 = "Volume3", _Class5.Volume0 = "Volume0", _Class5.ChromeMinimize = "ChromeMinimize", _Class5);
50
+ const AriaLabels = exports.AriaLabels = (_Class6 = class AriaLabels {}, _Class6.EndCall = "End Call", _Class6.MicMute = "Mute", _Class6.MicUnmute = "Unmute", _Class6.VideoTurnCameraOn = "Turn camera on", _Class6.VideoTurnCameraOff = "Turn camera off", _Class6.IncomingCallArea = "Incoming call area", _Class6.RejectCall = "Reject call", _Class6.AcceptVoiceCall = "Accept voice call", _Class6.AcceptVideoCall = "Accept video Call", _Class6.DeclineCall = "Decline Call", _Class6.AudioCall = "Audio Call", _Class6.VideoCall = "Video Call", _Class6.LetsChatWeAreOnline = "Let's chat we are online", _Class6.UnreadMessageString = "you have new messages", _Class6.Close = "Close", _Class6.ConfirmationPaneConfirm = "Close Chat", _Class6.ConfirmationPaneCancel = "Cancel. Return to Chat", _Class6.DownloadChatTranscript = "Download chat transcript", _Class6.EmailTranscript = "Email Transcript", _Class6.TurnSoundOff = "Turn sound off", _Class6.TurnSoundOn = "Turn sound on", _Class6.Minimize = "Minimize", _Class6.EmailChatTranscriptPane = "Email Chat Transcript Pane", _Class6.InputValidationPaneInput = "Please provide e-mail address to send transcript. The transcript will be sent after the chat ends. Email address text area", _Class6.Save = "Save", _Class6.Cancel = "Cancel", _Class6.ProactiveChatPane = "Proactive Chat Pane", _Class6.ChatNow = "Chat Now", _Class6.ReconnectChatPane = "Reconnect Chat Pane", _Class6.ReconnectChatPaneIcon = "Reconnect Chat Pane Icon", _Class6.ContinueConversation = "Continue conversation", _Class6.StartNewConversation = "Start new conversation", _Class6.InputValidationPaneButtonGroup = "Actions", _Class6.ConfirmationPaneButtonGroup = "Actions", _Class6);
51
+ const EventNames = exports.EventNames = (_Class7 = class EventNames {}, _Class7.OnClick = "OnClick", _Class7.OnEscapeKeyDown = "OnEscapeKeyDown", _Class7.IncomingCallEnded = "IncomingCallEnded", _Class7);
52
+ const Texts = exports.Texts = (_Class8 = class Texts {}, _Class8.IncomingCallTitle = "Incoming Call", _Class8.ChatButtonTitle = "Let's Chat!", _Class8.ChatButtonSubtitle = "We're online.", _Class8.ChatButtonUnreadMessageString = "new messages", _Class8.ChatButtonLargeUnreadMessageString = "99+", _Class8.CloseButtonText = "Close", _Class8.ConfirmationPaneTitle = "Close chat", _Class8.ConfirmationPaneSubtitle = "Do you really want to close this chat?", _Class8.ConfirmButtonText = "Close", _Class8.EmailPlaceHolderText = "johnsmith@outlook.com", _Class8.CancelButtonText = "Cancel", _Class8.DownloadChatTranscriptText = "Download chat transcript", _Class8.EmailTranscriptText = "Email Transcript", _Class8.HeaderIcon = "Chat Icon", _Class8.HeaderTitle = "Let's Chat", _Class8.MinimizeText = "Minimize", _Class8.InputValidationPaneTitleText = "Please provide e-mail address to send transcript.", _Class8.InputValidationPaneSubtitleText = "The transcript will be sent after the chat ends.", _Class8.InvalidInputErrorMessageText = "Enter a valid email address.", _Class8.SendButtonText = "Send", _Class8.SaveButtonText = "Save", _Class8.LoadingPaneTitleText = "Welcome to", _Class8.LoadingPaneSubtitleText = "live chat support ...", _Class8.LoadingPaneSpinnerText = "Loading ...", _Class8.OOOHPaneTitleText = "Thanks for contacting us. You have reached us outside of our operating hours. An agent will respond when we open.", _Class8.PostChatSurveyPaneTitleText = "Post chat survey pane", _Class8.ProactiveChatPaneTitleText = "Welcome to", _Class8.ProactiveChatPaneSubtitleText = "Live chat support!", _Class8.ProactiveChatPaneBodyTitleText = "Hi! Have any questions? I am here to help.", _Class8.ProactiveChatPaneStartButtonText = "Chat Now", _Class8.ReconnectChatPaneTitleText = "Previous session detected", _Class8.ReconnectChatPaneSubtitleText = "We have detected a previous chat session. Would you like to continue with your previous session?", _Class8.ReconnectChatPaneContinueChatButtonText = "Continue conversation", _Class8.ReconnectChatPaneStartNewChatButtonText = "Start new conversation", _Class8);
@@ -17,6 +17,12 @@ var _reactHooks = require("@fluentui/react-hooks");
17
17
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
18
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
19
19
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
20
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
21
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
22
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
23
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
24
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
25
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
20
26
  function CurrentCall(props) {
21
27
  var _props$controlProps, _defaultCurrentCallPr, _props$controlProps2, _defaultCurrentCallPr2, _props$controlProps3, _defaultCurrentCallPr3, _props$controlProps4, _defaultCurrentCallPr4, _props$controlProps5, _defaultCurrentCallPr5, _props$controlProps6, _defaultCurrentCallPr6, _props$controlProps7, _defaultCurrentCallPr7, _props$controlProps8, _defaultCurrentCallPr8, _props$controlProps9, _props$controlProps0, _defaultCurrentCallPr9, _defaultCurrentCallPr0, _props$styleProps, _props$controlProps1, _defaultCurrentCallPr1, _props$controlProps10, _defaultCurrentCallPr10, _props$controlProps11, _defaultCurrentCallPr11, _props$controlProps12, _props$controlProps13, _defaultCurrentCallPr12, _props$controlProps14, _defaultCurrentCallPr13, _props$controlProps15, _defaultCurrentCallPr14, _props$controlProps16, _defaultCurrentCallPr15, _props$controlProps17, _props$controlProps18, _defaultCurrentCallPr16, _props$controlProps19, _defaultCurrentCallPr17, _props$controlProps20, _defaultCurrentCallPr18, _props$controlProps21, _defaultCurrentCallPr19, _props$controlProps22, _defaultCurrentCallPr20, _props$controlProps23, _defaultCurrentCallPr21, _props$controlProps24, _defaultCurrentCallPr22, _props$controlProps25, _props$controlProps26, _defaultCurrentCallPr23, _props$controlProps27, _defaultCurrentCallPr24, _props$controlProps28, _defaultCurrentCallPr25, _props$controlProps29, _defaultCurrentCallPr26, _props$controlProps30, _props$controlProps31, _defaultCurrentCallPr27, _props$controlProps32, _defaultCurrentCallPr28, _props$controlProps33, _defaultCurrentCallPr29, _props$controlProps34, _defaultCurrentCallPr30, _defaultCurrentCallPr31, _props$controlProps35, _defaultCurrentCallPr32, _props$controlProps36, _defaultCurrentCallPr33, _props$styleProps2, _defaultCurrentCallPr34, _props$styleProps3, _defaultCurrentCallPr35, _props$styleProps4, _defaultCurrentCallPr36, _props$styleProps5, _defaultCurrentCallPr40, _props$styleProps9, _defaultCurrentCallPr41, _props$styleProps0, _defaultCurrentCallPr42, _props$styleProps1, _defaultCurrentCallPr43, _props$styleProps10, _defaultCurrentCallPr44, _props$styleProps11, _props$controlProps43, _defaultCurrentCallPr45, _props$styleProps12, _props$styleProps13, _props$styleProps14, _props$styleProps15, _props$styleProps16, _props$controlProps44, _props$controlProps45, _props$controlProps46, _props$controlProps47, _props$controlProps48, _defaultCurrentCallPr46, _props$controlProps49, _defaultCurrentCallPr47, _props$controlProps50, _props$controlProps51, _defaultCurrentCallPr48, _props$controlProps52, _defaultCurrentCallPr49, _props$controlProps53, _props$controlProps54, _props$controlProps55, _defaultCurrentCallPr50, _props$controlProps56, _defaultCurrentCallPr51, _props$controlProps57, _props$controlProps58, _defaultCurrentCallPr52, _props$controlProps59, _defaultCurrentCallPr53, _props$controlProps60, _props$controlProps61;
22
28
  const currentCallId = ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.id) ?? ((_defaultCurrentCallPr = _defaultCurrentCallProps.defaultCurrentCallProps.controlProps) === null || _defaultCurrentCallPr === void 0 ? void 0 : _defaultCurrentCallPr.id);
@@ -103,9 +109,10 @@ function CurrentCall(props) {
103
109
  }
104
110
  }
105
111
  };
106
- const [micState, {
107
- toggle: setMicState
108
- }] = (0, _reactHooks.useBoolean)(false);
112
+ const _useBoolean = (0, _reactHooks.useBoolean)(false),
113
+ _useBoolean2 = _slicedToArray(_useBoolean, 2),
114
+ micState = _useBoolean2[0],
115
+ setMicState = _useBoolean2[1].toggle;
109
116
  const endCallButtonProps = Object.assign({}, (_defaultCurrentCallPr31 = _defaultCurrentCallProps.defaultCurrentCallProps.controlProps) === null || _defaultCurrentCallPr31 === void 0 ? void 0 : _defaultCurrentCallPr31.endCallButtonProps, (_props$controlProps35 = props.controlProps) === null || _props$controlProps35 === void 0 ? void 0 : _props$controlProps35.endCallButtonProps);
110
117
  const callTimerProps = Object.assign({}, (_defaultCurrentCallPr32 = _defaultCurrentCallProps.defaultCurrentCallProps.controlProps) === null || _defaultCurrentCallPr32 === void 0 ? void 0 : _defaultCurrentCallPr32.callTimerProps, (_props$controlProps36 = props.controlProps) === null || _props$controlProps36 === void 0 ? void 0 : _props$controlProps36.callTimerProps);
111
118
  const endCallButtonStyles = Object.assign({}, (_defaultCurrentCallPr33 = _defaultCurrentCallProps.defaultCurrentCallProps.styleProps) === null || _defaultCurrentCallPr33 === void 0 ? void 0 : _defaultCurrentCallPr33.endCallButtonStyleProps, (_props$styleProps2 = props.styleProps) === null || _props$styleProps2 === void 0 ? void 0 : _props$styleProps2.endCallButtonStyleProps);
@@ -8,8 +8,17 @@ var _react = require("@fluentui/react");
8
8
  var _react2 = _interopRequireWildcard(require("react"));
9
9
  var _utils = require("../../../../common/utils");
10
10
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
12
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
13
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
14
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
15
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
16
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
11
17
  function Timer(props) {
12
- const [time, setTime] = (0, _react2.useState)(0);
18
+ const _useState = (0, _react2.useState)(0),
19
+ _useState2 = _slicedToArray(_useState, 2),
20
+ time = _useState2[0],
21
+ setTime = _useState2[1];
13
22
  const running = true;
14
23
  const timerStyles = {
15
24
  root: props.timerStyles
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+
3
+ require("@testing-library/jest-dom/extend-expect");
4
+ var _react = require("@testing-library/react");
5
+ var _BroadcastService = require("../../services/BroadcastService");
6
+ var _ChatButton = _interopRequireDefault(require("./ChatButton"));
7
+ var _LoadingPane = _interopRequireDefault(require("../loadingpane/LoadingPane"));
8
+ var _react2 = _interopRequireDefault(require("react"));
9
+ var _defaultChatButtonProps = require("./common/defaultProps/defaultChatButtonProps");
10
+ var _defaultLoadingPaneProps = require("../loadingpane/common/defaultProps/defaultLoadingPaneProps");
11
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
+
14
+ /**
15
+ * Repro / catcher for internal tracking — screen reader announces hidden / irrelevant
16
+ * text such as "blank" while navigating the chat surface. NVDA / JAWS announce
17
+ * "blank" when they encounter:
18
+ * - an element with an announceable role (button, link, textbox, listitem,
19
+ * progressbar, etc.) that has an empty accessible name (no aria-label, no
20
+ * aria-labelledby, no associated <label>, and no own text content), OR
21
+ * - a live region (`aria-live="polite"` / `aria-live="assertive"`) that is
22
+ * mounted with empty text content (each tick announces "blank").
23
+ *
24
+ * This catcher walks several rendered LCW surfaces and asserts neither pattern
25
+ * is present. Deterministic DOM contract — no SR needed.
26
+ *
27
+ * Surfaces covered today:
28
+ * - ChatButton (default props) — regression guard; passes today.
29
+ * - ChatButton with notification bubble forced visible at unreadCount=0 —
30
+ * regression guard for the empty-live-region path; passes today.
31
+ * - LoadingPane (default props) — regression guard; passes today.
32
+ *
33
+ * Scope note: the original bug surfaces inside WebChat-rendered chat session
34
+ * content (message bubbles, attachments, agent-supplied HTML), which is not
35
+ * reachable from chat-components unit tests. The Playwright catcher
36
+ * `automation_tests/e2e/areas/accessibility/blankAnnouncements.spec.ts` on
37
+ * `chore/a11y-tooling-foundation` walks the full a11y tree of a built
38
+ * `dist/out.js` and is the right vehicle for enumerating per-offender fixes.
39
+ * Promote additional surfaces here as they are wired into the catcher harness.
40
+ */
41
+
42
+ beforeAll(() => {
43
+ (0, _BroadcastService.BroadcastServiceInitialize)("testChannel");
44
+ });
45
+ afterEach(() => {
46
+ (0, _react.cleanup)();
47
+ });
48
+ const ANNOUNCEABLE_ROLES = new Set(["button", "link", "textbox", "combobox", "listbox", "listitem", "menu", "menuitem", "checkbox", "radio", "switch", "tab", "treeitem", "option", "searchbox", "progressbar", "alert", "status"]);
49
+ const ANNOUNCEABLE_TAGS = new Set(["button", "a", "input", "select", "textarea"]);
50
+ const isInsideAriaHidden = el => {
51
+ let cursor = el;
52
+ while (cursor) {
53
+ if (cursor.getAttribute("aria-hidden") === "true") return true;
54
+ cursor = cursor.parentElement;
55
+ }
56
+ return false;
57
+ };
58
+ const accessibleNameOf = el => {
59
+ const ariaLabel = (el.getAttribute("aria-label") || "").trim();
60
+ if (ariaLabel) return ariaLabel;
61
+ const labelledBy = (el.getAttribute("aria-labelledby") || "").trim();
62
+ if (labelledBy) {
63
+ const referenced = labelledBy.split(/\s+/).map(id => {
64
+ var _document$getElementB;
65
+ return ((_document$getElementB = document.getElementById(id)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.textContent) || "";
66
+ }).join(" ").trim();
67
+ if (referenced) return referenced;
68
+ }
69
+ if (el.tagName.toLowerCase() === "input") {
70
+ const id = el.id;
71
+ if (id) {
72
+ var _label$textContent;
73
+ const label = document.querySelector(`label[for="${CSS.escape(id)}"]`);
74
+ const labelText = label === null || label === void 0 || (_label$textContent = label.textContent) === null || _label$textContent === void 0 ? void 0 : _label$textContent.trim();
75
+ if (labelText) return labelText;
76
+ }
77
+ const placeholder = (el.getAttribute("placeholder") || "").trim();
78
+ if (placeholder) return placeholder;
79
+ }
80
+ if (el.tagName.toLowerCase() === "a") {
81
+ const title = (el.getAttribute("title") || "").trim();
82
+ if (title) return title;
83
+ }
84
+ return (el.textContent || "").trim();
85
+ };
86
+ const isAnnounceable = el => {
87
+ if (isInsideAriaHidden(el)) return false;
88
+ const role = (el.getAttribute("role") || "").toLowerCase();
89
+ if (role === "presentation" || role === "none") return false;
90
+ if (role && ANNOUNCEABLE_ROLES.has(role)) return true;
91
+ if (ANNOUNCEABLE_TAGS.has(el.tagName.toLowerCase())) {
92
+ // <input type="hidden"> is not announceable.
93
+ if (el.tagName.toLowerCase() === "input" && (el.getAttribute("type") || "").toLowerCase() === "hidden") {
94
+ return false;
95
+ }
96
+ return true;
97
+ }
98
+ return false;
99
+ };
100
+ const findEmptyAnnounceable = root => {
101
+ return Array.from(root.querySelectorAll("*")).filter(el => isAnnounceable(el) && accessibleNameOf(el) === "");
102
+ };
103
+ const findEmptyLiveRegions = root => {
104
+ return Array.from(root.querySelectorAll("[aria-live]")).filter(el => {
105
+ if (isInsideAriaHidden(el)) return false;
106
+ const live = (el.getAttribute("aria-live") || "").toLowerCase();
107
+ if (live !== "polite" && live !== "assertive") return false;
108
+ return (el.textContent || "").trim() === "";
109
+ });
110
+ };
111
+ const summarize = offenders => offenders.map(el => ({
112
+ tag: el.tagName.toLowerCase(),
113
+ id: el.id,
114
+ role: el.getAttribute("role"),
115
+ ariaLabel: el.getAttribute("aria-label"),
116
+ ariaLabelledBy: el.getAttribute("aria-labelledby"),
117
+ classes: el.className
118
+ }));
119
+ describe("ChatButton — 'blank' / empty-name announcements (internal tracking regression guard)", () => {
120
+ it("no announceable role/tag in the chat-button subtree may have an empty accessible name", () => {
121
+ const _render = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, _defaultChatButtonProps.defaultChatButtonProps)),
122
+ container = _render.container;
123
+ const button = container.firstElementChild;
124
+ expect(button).not.toBeNull();
125
+ expect(summarize(findEmptyAnnounceable(button))).toEqual([]);
126
+ });
127
+ it("no live region (aria-live=polite/assertive) in the chat-button subtree may be mounted with empty text", () => {
128
+ const props = {
129
+ ..._defaultChatButtonProps.defaultChatButtonProps,
130
+ controlProps: {
131
+ ..._defaultChatButtonProps.defaultChatButtonProps.controlProps,
132
+ unreadMessageCount: "0",
133
+ hideNotificationBubble: false
134
+ }
135
+ };
136
+ const _render2 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
137
+ container = _render2.container;
138
+ const button = container.firstElementChild;
139
+ expect(button).not.toBeNull();
140
+ expect(summarize(findEmptyLiveRegions(button))).toEqual([]);
141
+ });
142
+ });
143
+ describe("LoadingPane — 'blank' / empty-name announcements (internal tracking regression guard)", () => {
144
+ it("no announceable role/tag in the loading-pane subtree may have an empty accessible name", () => {
145
+ const _render3 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_LoadingPane.default, _defaultLoadingPaneProps.defaultLoadingPaneProps)),
146
+ container = _render3.container;
147
+ const pane = container.firstElementChild;
148
+ expect(pane).not.toBeNull();
149
+ expect(summarize(findEmptyAnnounceable(pane))).toEqual([]);
150
+ });
151
+ it("no live region (aria-live=polite/assertive) in the loading-pane subtree may be mounted with empty text", () => {
152
+ const _render4 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_LoadingPane.default, _defaultLoadingPaneProps.defaultLoadingPaneProps)),
153
+ container = _render4.container;
154
+ const pane = container.firstElementChild;
155
+ expect(pane).not.toBeNull();
156
+ expect(summarize(findEmptyLiveRegions(pane))).toEqual([]);
157
+ });
158
+ });
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+
3
+ require("@testing-library/jest-dom/extend-expect");
4
+ var _react = require("@testing-library/react");
5
+ var _BroadcastService = require("../../services/BroadcastService");
6
+ var _ChatButton = _interopRequireDefault(require("./ChatButton"));
7
+ var _react2 = _interopRequireDefault(require("react"));
8
+ var _defaultChatButtonProps = require("./common/defaultProps/defaultChatButtonProps");
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ /* eslint-disable @typescript-eslint/no-explicit-any */
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: in the rendered chat-button subtree, at most ONE element
28
+ * may expose each of the title / subtitle strings as an announceable name
29
+ * source. An "announceable name source" here is:
30
+ * - an `aria-label` attribute on a focusable / role-bearing element, OR
31
+ * - a visible `<Label>` (or other text-bearing element) that is NOT
32
+ * `aria-hidden="true"` and is not nested inside an element that is
33
+ * `aria-hidden="true"`.
34
+ *
35
+ * Regression guard: in the rendered DOM, the parent role=button Stack owns a
36
+ * single consolidated aria-label (synthesized from title + subtitle, plus
37
+ * unread-count fragment when applicable) and the inner Labels live inside an
38
+ * aria-hidden text container so browse-mode lands on the button exactly once.
39
+ * Override paths (componentOverrides.title/subtitle/textContainer or a
40
+ * consumer-supplied controlProps.ariaLabel) are preserved unchanged so
41
+ * customers who manage their own accessible names are not affected.
42
+ */
43
+
44
+ beforeAll(() => {
45
+ (0, _BroadcastService.BroadcastServiceInitialize)("testChannel");
46
+ });
47
+ afterEach(() => {
48
+ (0, _react.cleanup)();
49
+ });
50
+ const isInsideAriaHidden = el => {
51
+ let cursor = el;
52
+ while (cursor) {
53
+ if (cursor.getAttribute("aria-hidden") === "true") return true;
54
+ cursor = cursor.parentElement;
55
+ }
56
+ return false;
57
+ };
58
+ const visibleTextElementsMatching = (root, text) => {
59
+ return Array.from(root.querySelectorAll("*")).filter(el => {
60
+ if (isInsideAriaHidden(el)) return false;
61
+ // Only count leaf-ish text-bearing elements (don't double-count
62
+ // ancestors whose textContent obviously aggregates children).
63
+ const ownText = Array.from(el.childNodes).filter(n => n.nodeType === Node.TEXT_NODE).map(n => (n.textContent || "").trim()).join(" ").trim();
64
+ return ownText === text;
65
+ });
66
+ };
67
+
68
+ /**
69
+ * Regression guard for internal tracking — ChatButton must not produce duplicate
70
+ * NVDA / JAWS browse-mode stops. Visible title / subtitle text is excluded
71
+ * from the accessibility tree (aria-hidden) and the button container owns a
72
+ * single consolidated aria-label.
73
+ */
74
+ describe("ChatButton — browse-mode duplicate stops (internal tracking)", () => {
75
+ it("title text 'Let's Chat!' must NOT appear as a visible (non-aria-hidden) name source in the chat-button subtree", () => {
76
+ const _render = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, _defaultChatButtonProps.defaultChatButtonProps)),
77
+ container = _render.container;
78
+ const button = container.firstElementChild;
79
+ expect(button).not.toBeNull();
80
+ const titleStops = visibleTextElementsMatching(button, "Let's Chat!");
81
+ // The visible title should be excluded from the accessibility tree
82
+ // (e.g. via aria-hidden on the text container) so the announced name
83
+ // comes solely from the consolidated aria-label on the button. Any
84
+ // exposed text-bearing element with this exact text creates an
85
+ // additional browse-mode stop and reproduces internal tracking.
86
+ expect(titleStops.length).toBe(0);
87
+ });
88
+ it("subtitle text 'We're online.' must NOT appear as a visible (non-aria-hidden) name source in the chat-button subtree", () => {
89
+ const _render2 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, _defaultChatButtonProps.defaultChatButtonProps)),
90
+ container = _render2.container;
91
+ const button = container.firstElementChild;
92
+ expect(button).not.toBeNull();
93
+ const subtitleStops = visibleTextElementsMatching(button, "We're online.");
94
+ expect(subtitleStops.length).toBe(0);
95
+ });
96
+ it("the chat-button container must own a single consolidated aria-label so browse mode lands on it once", () => {
97
+ const _render3 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, _defaultChatButtonProps.defaultChatButtonProps)),
98
+ container = _render3.container;
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.defaultChatButtonProps,
114
+ controlProps: {
115
+ ..._defaultChatButtonProps.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 _render4 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
124
+ container = _render4.container;
125
+ const button = container.firstElementChild;
126
+ const ariaLabel = button.getAttribute("aria-label") || "";
127
+ expect(ariaLabel).toContain("3");
128
+ expect(ariaLabel).toContain("you have new messages");
129
+ expect(ariaLabel).toContain("Let's Chat!");
130
+ expect(ariaLabel).toContain("We're online.");
131
+ });
132
+ it("a consumer-supplied controlProps.ariaLabel wins over the synthesized label", () => {
133
+ const props = {
134
+ ..._defaultChatButtonProps.defaultChatButtonProps,
135
+ controlProps: {
136
+ ..._defaultChatButtonProps.defaultChatButtonProps.controlProps,
137
+ ariaLabel: "Talk to a live agent"
138
+ }
139
+ };
140
+ const _render5 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
141
+ container = _render5.container;
142
+ const button = container.firstElementChild;
143
+ expect(button.getAttribute("aria-label")).toBe("Talk to a live agent");
144
+ });
145
+ it("componentOverrides.textContainer preserves consumer-rendered visible text (synthesis is skipped)", () => {
146
+ const customText = "My custom chat text";
147
+ const props = {
148
+ ..._defaultChatButtonProps.defaultChatButtonProps,
149
+ componentOverrides: {
150
+ textContainer: /*#__PURE__*/_react2.default.createElement("div", {
151
+ id: "my-custom-text"
152
+ }, customText)
153
+ }
154
+ };
155
+ const _render6 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
156
+ container = _render6.container;
157
+ const button = container.firstElementChild;
158
+ // The custom text MUST remain visible in the a11y tree so consumers
159
+ // who replace the text container keep their announced text.
160
+ const customStops = visibleTextElementsMatching(button, customText);
161
+ expect(customStops.length).toBeGreaterThan(0);
162
+ // And the button must NOT carry a synthesized aria-label that would
163
+ // override the consumer's content.
164
+ const ariaLabel = (button.getAttribute("aria-label") || "").trim();
165
+ expect(ariaLabel).toBe("");
166
+ });
167
+ it("componentOverrides.title preserves consumer-rendered visible title (synthesis is skipped)", () => {
168
+ const customTitle = "Custom override title";
169
+ const props = {
170
+ ..._defaultChatButtonProps.defaultChatButtonProps,
171
+ componentOverrides: {
172
+ title: /*#__PURE__*/_react2.default.createElement("span", {
173
+ id: "my-custom-title"
174
+ }, customTitle)
175
+ }
176
+ };
177
+ const _render7 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
178
+ container = _render7.container;
179
+ const button = container.firstElementChild;
180
+ const customStops = visibleTextElementsMatching(button, customTitle);
181
+ expect(customStops.length).toBeGreaterThan(0);
182
+ const ariaLabel = (button.getAttribute("aria-label") || "").trim();
183
+ expect(ariaLabel).toBe("");
184
+ });
185
+
186
+ // Regression guard for the strict string-equality slip-throughs that
187
+ // brittle `unreadMessageCount !== "0"` allowed: values that coerce to
188
+ // numeric 0 (or non-numeric noise) must NOT render the bubble nor pollute
189
+ // the synthesized aria-label with a "0 you have new messages" fragment.
190
+ describe.each([["padded zero (' 0 ')", " 0 "], ["decimal zero ('0.0')", "0.0"], ["empty string ('')", ""], ["non-numeric ('abc')", "abc"]])("zero-equivalent unreadMessageCount: %s", (_label, value) => {
191
+ it("does NOT render the notification bubble", () => {
192
+ const props = {
193
+ ..._defaultChatButtonProps.defaultChatButtonProps,
194
+ controlProps: {
195
+ ..._defaultChatButtonProps.defaultChatButtonProps.controlProps,
196
+ hideNotificationBubble: false,
197
+ unreadMessageCount: value,
198
+ ariaLabelUnreadMessageString: "you have new messages"
199
+ }
200
+ };
201
+ const _render8 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
202
+ container = _render8.container;
203
+ const bubble = container.querySelector("[id$='-notification-bubble']");
204
+ expect(bubble).toBeNull();
205
+ });
206
+ it("does NOT inject the unread-count fragment into the synthesized aria-label", () => {
207
+ const props = {
208
+ ..._defaultChatButtonProps.defaultChatButtonProps,
209
+ controlProps: {
210
+ ..._defaultChatButtonProps.defaultChatButtonProps.controlProps,
211
+ hideNotificationBubble: false,
212
+ unreadMessageCount: value,
213
+ ariaLabelUnreadMessageString: "you have new messages"
214
+ }
215
+ };
216
+ const _render9 = (0, _react.render)(/*#__PURE__*/_react2.default.createElement(_ChatButton.default, props)),
217
+ container = _render9.container;
218
+ const button = container.firstElementChild;
219
+ const ariaLabel = button.getAttribute("aria-label") || "";
220
+ expect(ariaLabel).not.toContain("you have new messages");
221
+ // and the raw zero-equivalent must not leak into the label
222
+ if (value.trim().length > 0) {
223
+ expect(ariaLabel).not.toContain(value.trim());
224
+ }
225
+ });
226
+ });
227
+ });