@azure/communication-react 1.4.2-alpha-202211260013.0 → 1.4.2-alpha-202211300015.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.beta.md +47 -1
  2. package/CHANGELOG.json +507 -0
  3. package/dist/communication-react.d.ts +53 -17
  4. package/dist/dist-cjs/communication-react/index.js +168 -65
  5. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  6. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  7. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  8. package/dist/dist-esm/communication-react/src/index.d.ts +0 -1
  9. package/dist/dist-esm/communication-react/src/index.js.map +1 -1
  10. package/dist/dist-esm/react-components/src/components/VideoTile.d.ts +8 -16
  11. package/dist/dist-esm/react-components/src/components/VideoTile.js +21 -13
  12. package/dist/dist-esm/react-components/src/components/VideoTile.js.map +1 -1
  13. package/dist/dist-esm/react-components/src/components/styles/VideoTile.styles.d.ts +1 -1
  14. package/dist/dist-esm/react-components/src/components/styles/VideoTile.styles.js +11 -26
  15. package/dist/dist-esm/react-components/src/components/styles/VideoTile.styles.js.map +1 -1
  16. package/dist/dist-esm/react-components/src/components/utils.d.ts +1 -6
  17. package/dist/dist-esm/react-components/src/components/utils.js +0 -16
  18. package/dist/dist-esm/react-components/src/components/utils.js.map +1 -1
  19. package/dist/dist-esm/react-components/src/index.d.ts +0 -1
  20. package/dist/dist-esm/react-components/src/index.js.map +1 -1
  21. package/dist/dist-esm/react-components/src/theming/icons.d.ts +1 -0
  22. package/dist/dist-esm/react-components/src/theming/icons.js +3 -1
  23. package/dist/dist-esm/react-components/src/theming/icons.js.map +1 -1
  24. package/dist/dist-esm/react-composites/src/composites/CallComposite/Strings.d.ts +44 -0
  25. package/dist/dist-esm/react-composites/src/composites/CallComposite/Strings.js.map +1 -1
  26. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/MediaGallery.js +6 -2
  27. package/dist/dist-esm/react-composites/src/composites/CallComposite/components/MediaGallery.js.map +1 -1
  28. package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/mediaGallerySelector.d.ts +7 -0
  29. package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/mediaGallerySelector.js +9 -1
  30. package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/mediaGallerySelector.js.map +1 -1
  31. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/MediaGalleryUtils.d.ts +29 -0
  32. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/MediaGalleryUtils.js +119 -0
  33. package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/MediaGalleryUtils.js.map +1 -0
  34. package/dist/dist-esm/react-composites/src/composites/common/icons.d.ts +1 -0
  35. package/dist/dist-esm/react-composites/src/composites/localization/locales/en-US/strings.json +12 -1
  36. package/package.json +8 -8
@@ -50,10 +50,10 @@ import { IButtonProps } from '@fluentui/react';
50
50
  import { IButtonStyles } from '@fluentui/react';
51
51
  import { IContextualMenuItem } from '@fluentui/react';
52
52
  import { IContextualMenuItemStyles } from '@fluentui/react';
53
+ import { IContextualMenuProps } from '@fluentui/react';
53
54
  import { IContextualMenuStyles } from '@fluentui/react';
54
55
  import { IDropdownOption } from '@fluentui/react';
55
56
  import { IDropdownStyles } from '@fluentui/react';
56
- import { IIconProps } from '@fluentui/react';
57
57
  import { ILinkStyles } from '@fluentui/react';
58
58
  import { IMessageBarProps } from '@fluentui/react';
59
59
  import { IncomingCall } from '@azure/communication-calling';
@@ -1590,6 +1590,50 @@ export declare interface CallCompositeStrings {
1590
1590
  * Label disaplayed on the lobby screen during a 1:1 outbound call.
1591
1591
  */
1592
1592
  outboundCallingNoticeString: string;
1593
+ /**
1594
+ * Notice to be announced by narrator when a participant joins a call
1595
+ */
1596
+ participantJoinedNoticeString: string;
1597
+ /**
1598
+ * Notice to be announced by narrator when a participant joins a call
1599
+ */
1600
+ twoParticipantJoinedNoticeString: string;
1601
+ /**
1602
+ * Notice to be announced by narrator when a participant joins a call
1603
+ */
1604
+ threeParticipantJoinedNoticeString: string;
1605
+ /**
1606
+ * Notice to be announced by narrator when a participant leaves a call
1607
+ */
1608
+ participantLeftNoticeString: string;
1609
+ /**
1610
+ * Notice to be announced by narrator when 2 participants leave a call
1611
+ */
1612
+ twoParticipantLeftNoticeString: string;
1613
+ /**
1614
+ * Notice to be announced by narrator when 3 participants leave a call
1615
+ */
1616
+ threeParticipantLeftNoticeString: string;
1617
+ /**
1618
+ * string to be used to announce a change in participant if they have no displayName
1619
+ */
1620
+ unnamedParticipantString: string;
1621
+ /**
1622
+ * string to be used to announce when more than 3 participants have joined at the same time.
1623
+ */
1624
+ manyParticipantsJoined: string;
1625
+ /**
1626
+ * string to be used to announce when more than 3 participants have left at the same time.
1627
+ */
1628
+ manyParticipantsLeft: string;
1629
+ /**
1630
+ * string to be used to announce when multiple unnamed participants have joined at the same time.
1631
+ */
1632
+ manyUnnamedParticipantsJoined: string;
1633
+ /**
1634
+ * string to be used to announce when multiple unnamed participants have left at the same time.
1635
+ */
1636
+ manyUnnamedParticipantsLeft: string;
1593
1637
  }
1594
1638
 
1595
1639
  /**
@@ -4509,6 +4553,7 @@ export declare const DEFAULT_COMPONENT_ICONS: {
4509
4553
  UnsupportedBrowserWarning: JSX.Element;
4510
4554
  BrowserPermissionDeniedError: JSX.Element;
4511
4555
  VideoTilePinned: JSX.Element;
4556
+ VideoTileMoreOptions: JSX.Element;
4512
4557
  };
4513
4558
 
4514
4559
  /**
@@ -4605,6 +4650,7 @@ export declare const DEFAULT_COMPOSITE_ICONS: {
4605
4650
  UnsupportedBrowserWarning: JSX.Element;
4606
4651
  BrowserPermissionDeniedError: JSX.Element;
4607
4652
  VideoTilePinned: JSX.Element;
4653
+ VideoTileMoreOptions: JSX.Element;
4608
4654
  };
4609
4655
 
4610
4656
  /**
@@ -8251,18 +8297,6 @@ export declare interface VideoStreamRendererViewState {
8251
8297
  */
8252
8298
  export declare const VideoTile: (props: VideoTileProps) => JSX.Element;
8253
8299
 
8254
- /**
8255
- * @beta
8256
- * MenuItems to be diplayed in video tile in the contextual/drawer menu
8257
- */
8258
- export declare type VideoTileMenuItems = Array<{
8259
- key: string;
8260
- ariaLabel?: string;
8261
- text: string;
8262
- onClick: () => void;
8263
- iconProps: IIconProps;
8264
- }>;
8265
-
8266
8300
  /**
8267
8301
  * Props for {@link VideoTile}.
8268
8302
  *
@@ -8301,10 +8335,6 @@ export declare interface VideoTileProps {
8301
8335
  * Whether the video is muted or not.
8302
8336
  */
8303
8337
  isMuted?: boolean;
8304
- /**
8305
- * Display custom menu items in the VideoTile's contextual menu.
8306
- */
8307
- menuItems?: VideoTileMenuItems;
8308
8338
  /**
8309
8339
  * If true, the video tile will show the pin icon.
8310
8340
  */
@@ -8343,6 +8373,12 @@ export declare interface VideoTileProps {
8343
8373
  */
8344
8374
  participantState?: ParticipantState;
8345
8375
  strings?: VideoTileStrings;
8376
+ /**
8377
+ * Display custom menu items in the VideoTile's contextual menu.
8378
+ * Uses Fluent UI ContextualMenu.
8379
+ * An ellipses icon will be displayed to open the contextual menu if this prop is defined.
8380
+ */
8381
+ contextualMenu?: IContextualMenuProps;
8346
8382
  /**
8347
8383
  * Callback triggered by video tile on touch and hold.
8348
8384
  */
@@ -202,7 +202,7 @@ const _toCommunicationIdentifier = (id) => {
202
202
  // Copyright (c) Microsoft Corporation.
203
203
  // Licensed under the MIT license.
204
204
  // GENERATED FILE. DO NOT EDIT MANUALLY.
205
- var telemetryVersion = '1.4.2-alpha-202211260013.0';
205
+ var telemetryVersion = '1.4.2-alpha-202211300015.0';
206
206
 
207
207
  // Copyright (c) Microsoft Corporation.
208
208
  /**
@@ -4382,22 +4382,6 @@ const messageBarType = (errorType) => {
4382
4382
  return react.MessageBarType.error;
4383
4383
  }
4384
4384
  };
4385
- /**
4386
- * @private
4387
- */
4388
- const mapMenuItemsToContextualMenuItems = (menuItems) => {
4389
- const contextualMenuItems = [];
4390
- menuItems.map((item) => {
4391
- contextualMenuItems.push({
4392
- key: item.key,
4393
- text: item.text,
4394
- ariaLabel: item.ariaLabel,
4395
- onClick: item.onClick,
4396
- iconProps: item.iconProps
4397
- });
4398
- });
4399
- return contextualMenuItems;
4400
- };
4401
4385
  /**
4402
4386
  * @private
4403
4387
  * @param errorType
@@ -5071,7 +5055,9 @@ const DEFAULT_COMPONENT_ICONS = {
5071
5055
  /* @conditional-compile-remove(call-readiness) */
5072
5056
  BrowserPermissionDeniedError: React__default['default'].createElement(BrowserPermissionDenied20Filled, null),
5073
5057
  /* @conditional-compile-remove(pinned-participants) */
5074
- VideoTilePinned: React__default['default'].createElement(reactIcons.Pin16Filled, null)
5058
+ VideoTilePinned: React__default['default'].createElement(reactIcons.Pin16Filled, null),
5059
+ /* @conditional-compile-remove(pinned-participants) */
5060
+ VideoTileMoreOptions: React__default['default'].createElement(reactIcons.MoreHorizontal20Filled, null)
5075
5061
  };
5076
5062
 
5077
5063
  // Copyright (c) Microsoft Corporation.
@@ -8001,36 +7987,21 @@ const participantStateStringStyles = (theme) => {
8001
7987
  /**
8002
7988
  * @private
8003
7989
  */
8004
- const menuButtonStyles = {
7990
+ const moreButtonStyles = {
8005
7991
  root: {
8006
- background: 'none',
8007
- border: 'none',
8008
- borderRadius: 0,
8009
- minHeight: '0.125rem',
8010
- minWidth: '2rem',
8011
- width: '100%',
8012
- maxWidth: '3rem',
8013
- svg: {
8014
- verticalAlign: 'text-top'
8015
- }
7992
+ // To ensure that the button is clickable when there is a floating video tile
7993
+ zIndex: 1,
7994
+ color: 'inherit',
7995
+ height: '100%'
8016
7996
  },
8017
- splitButtonMenuButton: {
8018
- border: 'none'
7997
+ rootHovered: {
7998
+ background: 'none'
8019
7999
  },
8020
- flexContainer: {
8021
- flexFlow: 'column',
8022
- display: 'contents'
8000
+ rootPressed: {
8001
+ background: 'none'
8023
8002
  },
8024
- label: {
8025
- fontSize: '0.625rem',
8026
- fontWeight: '400',
8027
- lineHeight: '1rem',
8028
- cursor: 'pointer',
8029
- display: 'block',
8030
- margin: '0rem 0.25rem',
8031
- overflow: 'hidden',
8032
- textOverflow: 'ellipsis',
8033
- whiteSpace: 'nowrap'
8003
+ rootExpanded: {
8004
+ background: 'none'
8034
8005
  }
8035
8006
  };
8036
8007
 
@@ -8141,16 +8112,24 @@ const DefaultPlaceholder = (props) => {
8141
8112
  React__default['default'].createElement(react.Stack, { styles: defaultPersonaStyles },
8142
8113
  React__default['default'].createElement(react.Persona, { coinSize: coinSize, hidePersonaDetails: hidePersonaDetails, text: text !== null && text !== void 0 ? text : '', initialsTextColor: "white", "aria-label": noVideoAvailableAriaLabel !== null && noVideoAvailableAriaLabel !== void 0 ? noVideoAvailableAriaLabel : '', showOverflowTooltip: false }))));
8143
8114
  };
8144
- /* @conditional-compile-remove(pinned-participants) */
8145
- const menuIcon = () => React__default['default'].createElement(reactIcons.MoreHorizontal20Filled, { primaryFill: "currentColor" });
8146
8115
  const defaultPersonaStyles = { root: { margin: 'auto', maxHeight: '100%' } };
8147
8116
  /* @conditional-compile-remove(pinned-participants) */
8117
+ const videoTileMoreIconProps = { iconName: 'VideoTileMoreOptions' };
8118
+ /* @conditional-compile-remove(pinned-participants) */
8119
+ const videoTileMoreMenuIconProps = { iconName: undefined, style: { display: 'none' } };
8120
+ /* @conditional-compile-remove(pinned-participants) */
8121
+ const videoTileMoreMenuProps = {
8122
+ directionalHint: react.DirectionalHint.topLeftEdge,
8123
+ isBeakVisible: false,
8124
+ styles: { container: { maxWidth: '8rem' } }
8125
+ };
8126
+ /* @conditional-compile-remove(pinned-participants) */
8148
8127
  const VideoTileMoreOptionsButton = (props) => {
8149
- const { menuItems, menuStyles } = props;
8150
- if (!menuItems || menuItems.length === 0) {
8128
+ const { contextualMenu } = props;
8129
+ if (!contextualMenu) {
8151
8130
  return React__default['default'].createElement(React__default['default'].Fragment, null);
8152
8131
  }
8153
- return (React__default['default'].createElement(react.DefaultButton, { styles: react.concatStyleSets(menuButtonStyles, menuStyles !== null && menuStyles !== void 0 ? menuStyles : {}), onRenderIcon: menuIcon, menuIconProps: { hidden: true }, menuProps: { items: mapMenuItemsToContextualMenuItems(menuItems), directionalHint: react.DirectionalHint.topRightEdge } }));
8132
+ return (React__default['default'].createElement(react.IconButton, { styles: moreButtonStyles, iconProps: videoTileMoreIconProps, menuIconProps: videoTileMoreMenuIconProps, menuProps: Object.assign(Object.assign({}, videoTileMoreMenuProps), contextualMenu) }));
8154
8133
  };
8155
8134
  /**
8156
8135
  * A component to render the video stream for a single call participant.
@@ -8162,9 +8141,9 @@ const VideoTileMoreOptionsButton = (props) => {
8162
8141
  const VideoTile = (props) => {
8163
8142
  const { children, displayName, initialsName, isMirrored, isMuted,
8164
8143
  /* @conditional-compile-remove(pinned-participants) */
8165
- isPinned, onRenderPlaceholder, renderElement, showLabel = true, showMuteIndicator = true, styles, userId, noVideoAvailableAriaLabel, isSpeaking,
8144
+ isPinned, onRenderPlaceholder, renderElement, showLabel = true, showMuteIndicator = true, styles, userId, noVideoAvailableAriaLabel, isSpeaking, personaMinSize = DEFAULT_PERSONA_MIN_SIZE_PX, personaMaxSize = DEFAULT_PERSONA_MAX_SIZE_PX,
8166
8145
  /* @conditional-compile-remove(pinned-participants) */
8167
- menuItems, personaMinSize = DEFAULT_PERSONA_MIN_SIZE_PX, personaMaxSize = DEFAULT_PERSONA_MAX_SIZE_PX } = props;
8146
+ contextualMenu } = props;
8168
8147
  const [personaSize, setPersonaSize] = React.useState(100);
8169
8148
  const videoTileRef = React.useRef(null);
8170
8149
  const locale = useLocale$1();
@@ -8238,7 +8217,7 @@ const VideoTile = (props) => {
8238
8217
  showMuteIndicator && isMuted && (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(iconContainerStyle) },
8239
8218
  React__default['default'].createElement(react.Icon, { iconName: "VideoTileMicOff" }))),
8240
8219
  /* @conditional-compile-remove(pinned-participants) */
8241
- React__default['default'].createElement(VideoTileMoreOptionsButton, { menuItems: menuItems, menuStyles: props.styles }),
8220
+ React__default['default'].createElement(VideoTileMoreOptionsButton, { contextualMenu: contextualMenu }),
8242
8221
  /* @conditional-compile-remove(pinned-participants) */
8243
8222
  isPinned && (React__default['default'].createElement(react.Stack, { className: react.mergeStyles(iconContainerStyle) },
8244
8223
  React__default['default'].createElement(react.Icon, { iconName: "VideoTilePinned", className: react.mergeStyles(pinIconStyle) })))))),
@@ -13996,7 +13975,7 @@ const CallCompositeIcon = (props) => (React__default['default'].createElement(re
13996
13975
  */
13997
13976
  const CallWithChatCompositeIcon = (props) => (React__default['default'].createElement(react.FontIcon, Object.assign({}, props)));
13998
13977
 
13999
- var call$d={cameraLabel:"Camera",cameraPermissionDenied:"Your browser is blocking access to your camera",cameraTurnedOff:"Your camera is turned off",chatButtonLabel:"Chat",close:"Close",complianceBannerNowOnlyRecording:"You are now only recording this meeting.",complianceBannerNowOnlyTranscription:"You are now only transcribing this meeting.",complianceBannerRecordingAndTranscriptionSaved:"Recording and transcription are being saved.",complianceBannerRecordingAndTranscriptionStarted:"Recording and transcription have started.",complianceBannerRecordingAndTranscriptionStopped:"Recording and transcription have stopped.",complianceBannerRecordingSaving:"Recording is being saved.",complianceBannerRecordingStarted:"Recording has started.",complianceBannerRecordingStopped:"Recording has stopped.",complianceBannerTranscriptionStarted:"Transcription has started.",complianceBannerTranscriptionConsent:"By joining, you are giving consent for this meeting to be transcribed.",complianceBannerTranscriptionSaving:"Transcription is being saved.",complianceBannerTranscriptionStopped:"Transcription has stopped.",configurationPageTitle:"Start a call",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",defaultPlaceHolder:"Select an option",dismissSidePaneButtonLabel:"Close",failedToJoinCallDueToNoNetworkMoreDetails:"Call was disconnected due to a network issue. Check your connection and join again.",failedToJoinCallDueToNoNetworkTitle:"Call disconnected",failedToJoinTeamsMeetingReasonAccessDeniedMoreDetails:"You were not granted entry in the call. If this was a mistake, re-join the call.",failedToJoinTeamsMeetingReasonAccessDeniedTitle:"Dismissed from lobby",learnMore:"Learn more",leftCallMoreDetails:"If this was a mistake, re-join the call.",leftCallTitle:"You left the call",lobbyScreenConnectingToCallTitle:"Joining call",lobbyScreenWaitingToBeAdmittedTitle:"Waiting to be admitted",microphonePermissionDenied:"Your browser is blocking access to your microphone",microphoneToggleInLobbyNotAllowed:"Cannot mute or unmute while in lobby.",mutedMessage:"You're muted",networkReconnectMoreDetails:"Looks like something went wrong. We're trying to get back into the call.",networkReconnectTitle:"Hold on",deniedPermissionToRoomDetails:"You do not have permission to join this room.",deniedPermissionToRoomTitle:"Permission denied to room",peopleButtonLabel:"People",peoplePaneTitle:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",privacyPolicy:"Privacy policy",rejoinCallButtonLabel:"Re-join call",removedFromCallMoreDetails:"Another participant removed you from the call.",removedFromCallTitle:"You were removed",removeMenuLabel:"Remove",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",roomNotFoundDetails:"Room ID provided is not valid.",roomNotFoundTitle:"Room not found",soundLabel:"Sound",startCallButtonLabel:"Start call",openDialpadButtonLabel:"Dial phone number",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",moreButtonCallingLabel:"More",resumeCallButtonLabel:"Resume",resumingCallButtonLabel:"Resuming...",resumeCallButtonAriaLabel:"Resume call",resumingCallButtonAriaLabel:"Resume call",holdScreenLabel:"You're on hold",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number",outboundCallingNoticeString:"Calling..."};var chat$d={chatListHeader:"In this chat",uploadFile:"Upload File"};var callWithChat$d={chatButtonLabel:"Chat",chatButtonNewMessageNotificationLabel:"New Message",chatButtonTooltipClosedWithMessageCount:"Show chat ({unreadMessagesCount} unread)",chatButtonTooltipClose:"Hide chat",chatButtonTooltipOpen:"Show chat",chatPaneTitle:"Chat",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",dismissSidePaneButtonLabel:"Close",moreDrawerAudioDeviceMenuTitle:"Audio Device",moreDrawerButtonLabel:"More options",moreDrawerButtonTooltip:"More options",moreDrawerMicrophoneMenuTitle:"Microphone",moreDrawerSpeakerMenuTitle:"Speaker",peopleButtonLabel:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",peoplePaneTitle:"People",pictureInPictureTileAriaLabel:"Video Feeds. Click to return to call screen.",removeMenuLabel:"Remove",openDialpadButtonLabel:"Dial phone number",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number"};var en_US = {call:call$d,chat:chat$d,callWithChat:callWithChat$d};
13978
+ var call$d={cameraLabel:"Camera",cameraPermissionDenied:"Your browser is blocking access to your camera",cameraTurnedOff:"Your camera is turned off",chatButtonLabel:"Chat",close:"Close",complianceBannerNowOnlyRecording:"You are now only recording this meeting.",complianceBannerNowOnlyTranscription:"You are now only transcribing this meeting.",complianceBannerRecordingAndTranscriptionSaved:"Recording and transcription are being saved.",complianceBannerRecordingAndTranscriptionStarted:"Recording and transcription have started.",complianceBannerRecordingAndTranscriptionStopped:"Recording and transcription have stopped.",complianceBannerRecordingSaving:"Recording is being saved.",complianceBannerRecordingStarted:"Recording has started.",complianceBannerRecordingStopped:"Recording has stopped.",complianceBannerTranscriptionStarted:"Transcription has started.",complianceBannerTranscriptionConsent:"By joining, you are giving consent for this meeting to be transcribed.",complianceBannerTranscriptionSaving:"Transcription is being saved.",complianceBannerTranscriptionStopped:"Transcription has stopped.",configurationPageTitle:"Start a call",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",defaultPlaceHolder:"Select an option",dismissSidePaneButtonLabel:"Close",failedToJoinCallDueToNoNetworkMoreDetails:"Call was disconnected due to a network issue. Check your connection and join again.",failedToJoinCallDueToNoNetworkTitle:"Call disconnected",failedToJoinTeamsMeetingReasonAccessDeniedMoreDetails:"You were not granted entry in the call. If this was a mistake, re-join the call.",failedToJoinTeamsMeetingReasonAccessDeniedTitle:"Dismissed from lobby",learnMore:"Learn more",leftCallMoreDetails:"If this was a mistake, re-join the call.",leftCallTitle:"You left the call",lobbyScreenConnectingToCallTitle:"Joining call",lobbyScreenWaitingToBeAdmittedTitle:"Waiting to be admitted",microphonePermissionDenied:"Your browser is blocking access to your microphone",microphoneToggleInLobbyNotAllowed:"Cannot mute or unmute while in lobby.",mutedMessage:"You're muted",networkReconnectMoreDetails:"Looks like something went wrong. We're trying to get back into the call.",networkReconnectTitle:"Hold on",deniedPermissionToRoomDetails:"You do not have permission to join this room.",deniedPermissionToRoomTitle:"Permission denied to room",peopleButtonLabel:"People",peoplePaneTitle:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",privacyPolicy:"Privacy policy",rejoinCallButtonLabel:"Re-join call",removedFromCallMoreDetails:"Another participant removed you from the call.",removedFromCallTitle:"You were removed",removeMenuLabel:"Remove",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",roomNotFoundDetails:"Room ID provided is not valid.",roomNotFoundTitle:"Room not found",soundLabel:"Sound",startCallButtonLabel:"Start call",openDialpadButtonLabel:"Dial phone number",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",moreButtonCallingLabel:"More",resumeCallButtonLabel:"Resume",resumingCallButtonLabel:"Resuming...",resumeCallButtonAriaLabel:"Resume call",resumingCallButtonAriaLabel:"Resume call",holdScreenLabel:"You're on hold",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number",outboundCallingNoticeString:"Calling...",participantJoinedNoticeString:"{displayName} joined",twoParticipantJoinedNoticeString:"{displayName1} and {displayName2} have joined",threeParticipantJoinedNoticeString:"{displayName1}, {displayName2} and {displayName3} have joined",participantLeftNoticeString:"{displayName} left",twoParticipantLeftNoticeString:"{displayName1} and {displayName2} have left",threeParticipantLeftNoticeString:"{displayName1}, {displayName2} and {displayName3} have left",unnamedParticipantString:"unnamed participant",manyUnnamedParticipantsJoined:"unnamed participant and {numOfParticipants} other participants joined",manyUnnamedParticipantsLeft:"unnamed participant and {numOfParticipants} other participants left",manyParticipantsJoined:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants joined",manyParticipantsLeft:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants left"};var chat$d={chatListHeader:"In this chat",uploadFile:"Upload File"};var callWithChat$d={chatButtonLabel:"Chat",chatButtonNewMessageNotificationLabel:"New Message",chatButtonTooltipClosedWithMessageCount:"Show chat ({unreadMessagesCount} unread)",chatButtonTooltipClose:"Hide chat",chatButtonTooltipOpen:"Show chat",chatPaneTitle:"Chat",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",dismissSidePaneButtonLabel:"Close",moreDrawerAudioDeviceMenuTitle:"Audio Device",moreDrawerButtonLabel:"More options",moreDrawerButtonTooltip:"More options",moreDrawerMicrophoneMenuTitle:"Microphone",moreDrawerSpeakerMenuTitle:"Speaker",peopleButtonLabel:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",peoplePaneTitle:"People",pictureInPictureTileAriaLabel:"Video Feeds. Click to return to call screen.",removeMenuLabel:"Remove",openDialpadButtonLabel:"Dial phone number",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number"};var en_US = {call:call$d,chat:chat$d,callWithChat:callWithChat$d};
14000
13979
 
14001
13980
  var call$c={cameraLabel:"Camera",cameraPermissionDenied:"Your browser is blocking access to your camera",cameraTurnedOff:"Your camera is turned off",chatButtonLabel:"Chat",close:"Close",complianceBannerNowOnlyRecording:"You are now only recording this meeting.",complianceBannerNowOnlyTranscription:"You are now only transcribing this meeting.",complianceBannerRecordingAndTranscriptionSaved:"Recording and transcription are being saved.",complianceBannerRecordingAndTranscriptionStarted:"Recording and transcription have started.",complianceBannerRecordingAndTranscriptionStopped:"Recording and transcription have stopped.",complianceBannerRecordingSaving:"Recording is being saved.",complianceBannerRecordingStarted:"Recording has started.",complianceBannerRecordingStopped:"Recording has stopped.",complianceBannerTranscriptionStarted:"Transcription has started.",complianceBannerTranscriptionConsent:"By joining, you are giving consent for this meeting to be transcribed.",complianceBannerTranscriptionSaving:"Transcription is being saved.",complianceBannerTranscriptionStopped:"Transcription has stopped.",configurationPageTitle:"Start a call",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",defaultPlaceHolder:"Select an option",dismissSidePaneButtonLabel:"Close",failedToJoinCallDueToNoNetworkMoreDetails:"Call was disconnected due to a network issue. Check your connection and join again.",failedToJoinCallDueToNoNetworkTitle:"Call disconnected",failedToJoinTeamsMeetingReasonAccessDeniedMoreDetails:"You were not granted entry in the call. If this was a mistake, re-join the call.",failedToJoinTeamsMeetingReasonAccessDeniedTitle:"Dismissed from lobby",learnMore:"Learn more",leftCallMoreDetails:"If this was a mistake, re-join the call.",leftCallTitle:"You left the call",lobbyScreenConnectingToCallTitle:"Joining call",lobbyScreenWaitingToBeAdmittedTitle:"Waiting to be admitted",microphonePermissionDenied:"Your browser is blocking access to your microphone",microphoneToggleInLobbyNotAllowed:"Cannot mute or unmute while in lobby.",mutedMessage:"You're muted",networkReconnectMoreDetails:"Looks like something went wrong. We're trying to get back into the call.",networkReconnectTitle:"Hold on",deniedPermissionToRoomDetails:"You do not have permission to join this room.",deniedPermissionToRoomTitle:"Permission denied to room",peopleButtonLabel:"People",peoplePaneTitle:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",privacyPolicy:"Privacy policy",rejoinCallButtonLabel:"Re-join call",removedFromCallMoreDetails:"Another participant removed you from the call.",removedFromCallTitle:"You were removed",removeMenuLabel:"Remove",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",roomNotFoundDetails:"Room ID provided is not valid.",roomNotFoundTitle:"Room not found",soundLabel:"Sound",startCallButtonLabel:"Start call",openDialpadButtonLabel:"Dial phone number",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",moreButtonCallingLabel:"More",resumeCallButtonLabel:"Resume",resumingCallButtonLabel:"Resuming...",resumeCallButtonAriaLabel:"Resume call",resumingCallButtonAriaLabel:"Resume call",holdScreenLabel:"You're on hold",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceHolderText:"Enter number",outboundCallingNoticeString:"Calling..."};var chat$c={chatListHeader:"In this chat",uploadFile:"Upload File"};var callWithChat$c={chatButtonLabel:"Chat",chatButtonNewMessageNotificationLabel:"New Message",chatButtonTooltipClosedWithMessageCount:"Show chat ({unreadMessagesCount} unread)",chatButtonTooltipClose:"Hide chat",chatButtonTooltipOpen:"Show chat",chatPaneTitle:"Chat",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",dismissSidePaneButtonLabel:"Close",moreDrawerAudioDeviceMenuTitle:"Audio Device",moreDrawerButtonLabel:"More options",moreDrawerButtonTooltip:"More options",moreDrawerMicrophoneMenuTitle:"Microphone",moreDrawerSpeakerMenuTitle:"Speaker",peopleButtonLabel:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",peoplePaneTitle:"People",pictureInPictureTileAriaLabel:"Video Feeds. Click to return to call screen.",removeMenuLabel:"Remove",openDialpadButtonLabel:"Dial phone number",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceHolderText:"Enter number"};var en_GB = {call:call$c,chat:chat$c,callWithChat:callWithChat$c};
14002
13981
 
@@ -17765,6 +17744,138 @@ const localVideoCameraCycleButtonSelector = reselect.createSelector([getDeviceMa
17765
17744
  };
17766
17745
  });
17767
17746
 
17747
+ // Copyright (c) Microsoft Corporation.
17748
+ /**
17749
+ * @private
17750
+ */
17751
+ const mediaGallerySelector = reselect__namespace.createSelector([getLocalVideoStreams], (localVideoStreams) => {
17752
+ var _a, _b;
17753
+ return {
17754
+ isVideoStreamOn: !!((_b = (_a = localVideoStreams === null || localVideoStreams === void 0 ? void 0 : localVideoStreams.find((stream) => stream.mediaStreamType === 'Video')) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.target)
17755
+ };
17756
+ });
17757
+ /**
17758
+ * Custom selector for this hook to retrieve all the participants that are currently
17759
+ * connected to the call.
17760
+ */
17761
+ const getRemoteParticipantsConnectedSelector = reselect__namespace.createSelector([getRemoteParticipants], (remoteParticipants) => {
17762
+ const participants = Object.values(remoteParticipants !== null && remoteParticipants !== void 0 ? remoteParticipants : {});
17763
+ return participants.filter((p) => p.state === 'Connected');
17764
+ });
17765
+
17766
+ // Copyright (c) Microsoft Corporation.
17767
+ /**
17768
+ * sets the announcement string whenever a Participant comes or goes from a call to be
17769
+ * used by the system narrator.
17770
+ *
17771
+ * @returns string to be used by the narrator and Announcer component
17772
+ *
17773
+ * @internal
17774
+ */
17775
+ const useParticipantChangedAnnouncement = () => {
17776
+ const locale = useLocale().strings.call;
17777
+ const strings = React.useMemo(() => {
17778
+ return {
17779
+ participantJoinedNoticeString: locale.participantJoinedNoticeString,
17780
+ twoParticipantJoinedNoticeString: locale.twoParticipantJoinedNoticeString,
17781
+ threeParticipantJoinedNoticeString: locale.threeParticipantJoinedNoticeString,
17782
+ participantLeftNoticeString: locale.participantLeftNoticeString,
17783
+ twoParticipantLeftNoticeString: locale.twoParticipantLeftNoticeString,
17784
+ threeParticipantLeftNoticeString: locale.threeParticipantLeftNoticeString,
17785
+ unnamedParticipantString: locale.unnamedParticipantString,
17786
+ manyParticipantsJoined: locale.manyParticipantsJoined,
17787
+ manyParticipantsLeft: locale.manyParticipantsLeft,
17788
+ manyUnnamedParticipantsJoined: locale.manyUnnamedParticipantsJoined,
17789
+ manyUnnamedParticipantsLeft: locale.manyUnnamedParticipantsLeft
17790
+ };
17791
+ }, [locale]);
17792
+ const [announcerString, setAnnouncerString] = React.useState('');
17793
+ const currentParticipants = useSelector$1(getRemoteParticipantsConnectedSelector);
17794
+ /**
17795
+ * We want to use a useRef here since we want to not fire this hook based on the previous participants
17796
+ * this allows this value to be used in the hook without being in the dependency array.
17797
+ *
17798
+ * Note: By definition if this hook is used in another component it is not pure anymore.
17799
+ */
17800
+ const previousParticipants = React.useRef(currentParticipants);
17801
+ const resetAnnoucement = (string) => {
17802
+ setAnnouncerString(string);
17803
+ };
17804
+ React.useMemo(() => {
17805
+ const currentIds = currentParticipants.map((p) => toFlatCommunicationIdentifier(p.identifier));
17806
+ const previousIds = previousParticipants.current.map((p) => toFlatCommunicationIdentifier(p.identifier));
17807
+ const whoJoined = currentParticipants.filter((p) => !previousIds.includes(toFlatCommunicationIdentifier(p.identifier)));
17808
+ const whoLeft = previousParticipants.current.filter((p) => !currentIds.includes(toFlatCommunicationIdentifier(p.identifier)));
17809
+ if (whoJoined.length > 0) {
17810
+ resetAnnoucement(createAnnouncmentString('joined', whoJoined, strings));
17811
+ }
17812
+ if (whoLeft.length > 0) {
17813
+ resetAnnoucement(createAnnouncmentString('left', whoLeft, strings));
17814
+ }
17815
+ // Update cached value at the end.
17816
+ previousParticipants.current = currentParticipants;
17817
+ }, [currentParticipants, strings]);
17818
+ return announcerString;
17819
+ };
17820
+ /**
17821
+ * Generates the announcement string for when a participant joins or leaves a call.
17822
+ */
17823
+ const createAnnouncmentString = (direction, participants, strings) => {
17824
+ var _a, _b, _c;
17825
+ /**
17826
+ * If there are no participants return empty string.
17827
+ */
17828
+ if (participants.length === 0) {
17829
+ return '';
17830
+ }
17831
+ /**
17832
+ * Filter participants into two arrays to put all the unnamed participants at the back of the
17833
+ * names being announced.
17834
+ */
17835
+ const unnamedParticipants = participants.filter((p) => p.displayName === undefined);
17836
+ const namedParicipants = participants.filter((p) => p.displayName);
17837
+ const sortedParticipants = namedParicipants.concat(unnamedParticipants);
17838
+ /**
17839
+ * if there are only unnamed participants present in the array announce a special unnamed participants
17840
+ * only string.
17841
+ */
17842
+ if (sortedParticipants.filter((p) => p.displayName).length === 0 && sortedParticipants.length > 1) {
17843
+ return _formatString(direction === 'joined' ? strings.manyUnnamedParticipantsJoined : strings.manyUnnamedParticipantsLeft, {
17844
+ numOfParticipants: (sortedParticipants.length - 1).toString()
17845
+ });
17846
+ }
17847
+ const participantNames = sortedParticipants.map((p) => { var _a; return (_a = p.displayName) !== null && _a !== void 0 ? _a : strings.unnamedParticipantString; });
17848
+ switch (sortedParticipants.length) {
17849
+ case 1:
17850
+ return _formatString(direction === 'joined' ? strings.participantJoinedNoticeString : strings.participantLeftNoticeString, { displayName: participantNames[0] });
17851
+ case 2:
17852
+ return _formatString(direction === 'joined' ? strings.twoParticipantJoinedNoticeString : strings.twoParticipantLeftNoticeString, {
17853
+ displayName1: participantNames[0],
17854
+ displayName2: participantNames[1]
17855
+ });
17856
+ case 3:
17857
+ return _formatString(direction === 'joined' ? strings.threeParticipantJoinedNoticeString : strings.threeParticipantLeftNoticeString, {
17858
+ displayName1: participantNames[0],
17859
+ displayName2: participantNames[1],
17860
+ displayName3: participantNames[2]
17861
+ });
17862
+ }
17863
+ /**
17864
+ * If we have more than 3 participants joining we need to do something more to announce them
17865
+ * appropriately.
17866
+ *
17867
+ * We don't want to announce every name when more than 3 participants join at once so
17868
+ * we parse out the first 3 names we have and announce those with the number of others.
17869
+ */
17870
+ const numberOfExtraParticipants = sortedParticipants.length - 3;
17871
+ return _formatString(direction === 'joined' ? strings.manyParticipantsJoined : strings.manyParticipantsLeft, {
17872
+ displayName1: (_a = sortedParticipants[0].displayName) !== null && _a !== void 0 ? _a : strings.unnamedParticipantString,
17873
+ displayName2: (_b = sortedParticipants[1].displayName) !== null && _b !== void 0 ? _b : strings.unnamedParticipantString,
17874
+ displayName3: (_c = sortedParticipants[2].displayName) !== null && _c !== void 0 ? _c : strings.unnamedParticipantString,
17875
+ numOfParticipants: numberOfExtraParticipants.toString()
17876
+ });
17877
+ };
17878
+
17768
17879
  // Copyright (c) Microsoft Corporation.
17769
17880
  const VideoGalleryStyles = {
17770
17881
  root: {
@@ -17787,6 +17898,7 @@ const MediaGallery = (props) => {
17787
17898
  const videoGalleryProps = usePropsFor$1(VideoGallery);
17788
17899
  const cameraSwitcherCameras = useSelector$1(localVideoCameraCycleButtonSelector);
17789
17900
  const cameraSwitcherCallback = useHandlers();
17901
+ const announcerString = useParticipantChangedAnnouncement();
17790
17902
  const cameraSwitcherProps = React.useMemo(() => {
17791
17903
  return Object.assign(Object.assign({}, cameraSwitcherCallback), cameraSwitcherCameras);
17792
17904
  }, [cameraSwitcherCallback, cameraSwitcherCameras]);
@@ -17799,7 +17911,9 @@ const MediaGallery = (props) => {
17799
17911
  const VideoGalleryMemoized = React.useMemo(() => {
17800
17912
  return (React__default['default'].createElement(VideoGallery, Object.assign({}, videoGalleryProps, { localVideoViewOptions: localVideoViewOptions$2, remoteVideoViewOptions: remoteVideoViewOptions, styles: VideoGalleryStyles, layout: "floatingLocalVideo", showCameraSwitcherInLocalPreview: props.isMobile, localVideoCameraCycleButtonProps: cameraSwitcherProps, onRenderAvatar: onRenderAvatar })));
17801
17913
  }, [videoGalleryProps, props.isMobile, onRenderAvatar, cameraSwitcherProps]);
17802
- return VideoGalleryMemoized;
17914
+ return (React__default['default'].createElement(React__default['default'].Fragment, null,
17915
+ React__default['default'].createElement(Announcer, { announcementString: announcerString, ariaLive: 'polite' }),
17916
+ VideoGalleryMemoized));
17803
17917
  };
17804
17918
  /**
17805
17919
  * @private
@@ -17964,17 +18078,6 @@ const complianceBannerSelector = reselect__namespace.createSelector([getIsTransc
17964
18078
  };
17965
18079
  });
17966
18080
 
17967
- // Copyright (c) Microsoft Corporation.
17968
- /**
17969
- * @private
17970
- */
17971
- const mediaGallerySelector = reselect__namespace.createSelector([getLocalVideoStreams], (localVideoStreams) => {
17972
- var _a, _b;
17973
- return {
17974
- isVideoStreamOn: !!((_b = (_a = localVideoStreams === null || localVideoStreams === void 0 ? void 0 : localVideoStreams.find((stream) => stream.mediaStreamType === 'Video')) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.target)
17975
- };
17976
- });
17977
-
17978
18081
  // Copyright (c) Microsoft Corporation.
17979
18082
  /**
17980
18083
  * @private