@azure/communication-react 1.5.1-alpha-202306160013 → 1.5.1-alpha-202306180015

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 (41) hide show
  1. package/dist/communication-react.d.ts +24 -0
  2. package/dist/dist-cjs/communication-react/index.js +76 -19
  3. package/dist/dist-cjs/communication-react/index.js.map +1 -1
  4. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
  5. package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
  6. package/dist/dist-esm/calling-component-bindings/src/baseSelectors.d.ts +4 -0
  7. package/dist/dist-esm/calling-component-bindings/src/baseSelectors.js +5 -0
  8. package/dist/dist-esm/calling-component-bindings/src/baseSelectors.js.map +1 -1
  9. package/dist/dist-esm/calling-component-bindings/src/videoGallerySelector.d.ts +1 -0
  10. package/dist/dist-esm/calling-component-bindings/src/videoGallerySelector.js +11 -3
  11. package/dist/dist-esm/calling-component-bindings/src/videoGallerySelector.js.map +1 -1
  12. package/dist/dist-esm/calling-stateful-client/src/CallClientState.d.ts +15 -0
  13. package/dist/dist-esm/calling-stateful-client/src/CallClientState.js.map +1 -1
  14. package/dist/dist-esm/calling-stateful-client/src/CallContext.d.ts +1 -0
  15. package/dist/dist-esm/calling-stateful-client/src/CallContext.js +11 -0
  16. package/dist/dist-esm/calling-stateful-client/src/CallContext.js.map +1 -1
  17. package/dist/dist-esm/calling-stateful-client/src/CallSubscriber.d.ts +1 -0
  18. package/dist/dist-esm/calling-stateful-client/src/CallSubscriber.js +10 -0
  19. package/dist/dist-esm/calling-stateful-client/src/CallSubscriber.js.map +1 -1
  20. package/dist/dist-esm/calling-stateful-client/src/Converter.js +4 -0
  21. package/dist/dist-esm/calling-stateful-client/src/Converter.js.map +1 -1
  22. package/dist/dist-esm/calling-stateful-client/src/OptimalVideoCountSubscriber.d.ts +24 -0
  23. package/dist/dist-esm/calling-stateful-client/src/OptimalVideoCountSubscriber.js +28 -0
  24. package/dist/dist-esm/calling-stateful-client/src/OptimalVideoCountSubscriber.js.map +1 -0
  25. package/dist/dist-esm/calling-stateful-client/src/index-public.d.ts +1 -0
  26. package/dist/dist-esm/calling-stateful-client/src/index-public.js.map +1 -1
  27. package/dist/dist-esm/react-components/src/components/ParticipantItem.d.ts +5 -0
  28. package/dist/dist-esm/react-components/src/components/ParticipantItem.js +3 -2
  29. package/dist/dist-esm/react-components/src/components/ParticipantItem.js.map +1 -1
  30. package/dist/dist-esm/react-components/src/components/ParticipantList.d.ts +2 -0
  31. package/dist/dist-esm/react-components/src/components/ParticipantList.js +4 -4
  32. package/dist/dist-esm/react-components/src/components/ParticipantList.js.map +1 -1
  33. package/dist/dist-esm/react-components/src/components/VideoGallery/DefaultLayout.js +1 -3
  34. package/dist/dist-esm/react-components/src/components/VideoGallery/DefaultLayout.js.map +1 -1
  35. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideoLayout.js +1 -3
  36. package/dist/dist-esm/react-components/src/components/VideoGallery/FloatingLocalVideoLayout.js.map +1 -1
  37. package/dist/dist-esm/react-components/src/components/VideoGallery/utils/videoGalleryLayoutUtils.js +1 -2
  38. package/dist/dist-esm/react-components/src/components/VideoGallery/utils/videoGalleryLayoutUtils.js.map +1 -1
  39. package/dist/dist-esm/react-composites/src/composites/common/ParticipantContainer.js +4 -3
  40. package/dist/dist-esm/react-composites/src/composites/common/ParticipantContainer.js.map +1 -1
  41. package/package.json +8 -8
@@ -2200,6 +2200,10 @@ export declare interface CallState {
2200
2200
  * Proxy of {@link @azure/communication-calling#TranscriptionCallFeature}.
2201
2201
  */
2202
2202
  captionsFeature: CaptionsCallFeatureState;
2203
+ /**
2204
+ * Proxy of {@link @azure/communication-calling#OptimalVideoCountCallFeature}.
2205
+ */
2206
+ optimalVideoCount: OptimalVideoCountFeatureState;
2203
2207
  /**
2204
2208
  * Proxy of {@link @azure/communication-calling#RecordingCallFeature}.
2205
2209
  */
@@ -7410,6 +7414,18 @@ userId?: string, options?: CustomAvatarOptions,
7410
7414
  */
7411
7415
  defaultOnRender?: (props: CustomAvatarOptions) => JSX.Element) => JSX.Element;
7412
7416
 
7417
+ /**
7418
+ * State only version of Optimal Video Count Feature {@link @azure/communication-calling#OptimalVideoCountCallFeature}.
7419
+ *
7420
+ * @beta
7421
+ */
7422
+ export declare interface OptimalVideoCountFeatureState {
7423
+ /**
7424
+ * State of the current optimal video count.
7425
+ */
7426
+ maxRemoteVideoStreams: number;
7427
+ }
7428
+
7413
7429
  /**
7414
7430
  * A device, e.g. camera, microphone, or speaker, in the {@link DevicesButton} flyout.
7415
7431
  *
@@ -7498,6 +7514,11 @@ export declare interface ParticipantItemProps {
7498
7514
  * For example, `strings.participantStateConnecting` will be used if `participantState` is `Connecting`.
7499
7515
  */
7500
7516
  participantState?: ParticipantState;
7517
+ /**
7518
+ * Optional aria property that prefixes the ParticipantItems aria content
7519
+ * Takes in a unique id value of the element you would like to be read before the ParticipantItem.
7520
+ */
7521
+ ariaLabelledBy?: string;
7501
7522
  }
7502
7523
 
7503
7524
  /**
@@ -7601,6 +7622,8 @@ export declare type ParticipantListProps = {
7601
7622
  styles?: ParticipantListStyles;
7602
7623
  /** prop to determine if we should show tooltip for participants or not */
7603
7624
  showParticipantOverflowTooltip?: boolean;
7625
+ /** Optional aria-lablledby prop that prefixes each ParticipantItem aria-label */
7626
+ participantAriaLabelledBy?: string;
7604
7627
  };
7605
7628
 
7606
7629
  /**
@@ -9360,6 +9383,7 @@ export declare type VideoGallerySelector = (state: CallClientState, props: Calli
9360
9383
  localParticipant: VideoGalleryLocalParticipant;
9361
9384
  remoteParticipants: VideoGalleryRemoteParticipant[];
9362
9385
  dominantSpeakers?: string[];
9386
+ optimalVideoCount?: number;
9363
9387
  };
9364
9388
 
9365
9389
  /**
@@ -167,7 +167,7 @@ const _toCommunicationIdentifier = (id) => {
167
167
  // Copyright (c) Microsoft Corporation.
168
168
  // Licensed under the MIT license.
169
169
  // GENERATED FILE. DO NOT EDIT MANUALLY.
170
- var telemetryVersion = '1.5.1-alpha-202306160013';
170
+ var telemetryVersion = '1.5.1-alpha-202306180015';
171
171
 
172
172
  // Copyright (c) Microsoft Corporation.
173
173
  /**
@@ -344,6 +344,11 @@ const getIsScreenSharingOn = (state, props) => { var _a; return (_a = state.call
344
344
  * @private
345
345
  */
346
346
  const getIsMuted = (state, props) => { var _a; return (_a = state.calls[props.callId]) === null || _a === void 0 ? void 0 : _a.isMuted; };
347
+ /* @conditional-compile-remove(optimal-video-count) */
348
+ /**
349
+ * @private
350
+ */
351
+ const getOptimalVideoCount = (state, props) => { var _a; return (_a = state.calls[props.callId]) === null || _a === void 0 ? void 0 : _a.optimalVideoCount.maxRemoteVideoStreams; };
347
352
  /**
348
353
  * @private
349
354
  */
@@ -1500,6 +1505,10 @@ function convertSdkCallToDeclarativeCall(call) {
1500
1505
  /* @conditional-compile-remove(call-transfer) */
1501
1506
  transfer: {
1502
1507
  acceptedTransfers: {}
1508
+ },
1509
+ /* @conditional-compile-remove(optimal-video-count) */
1510
+ optimalVideoCount: {
1511
+ maxRemoteVideoStreams: call.feature(communicationCalling.Features.OptimalVideoCount).optimalVideoCount
1503
1512
  }
1504
1513
  };
1505
1514
  }
@@ -1653,6 +1662,8 @@ class CallContext$2 {
1653
1662
  existingCall.localVideoStreams = call.localVideoStreams;
1654
1663
  existingCall.remoteParticipants = call.remoteParticipants;
1655
1664
  existingCall.transcription.isTranscriptionActive = call.transcription.isTranscriptionActive;
1665
+ /* @conditional-compile-remove(optimal-video-count) */
1666
+ existingCall.optimalVideoCount.maxRemoteVideoStreams = call.optimalVideoCount.maxRemoteVideoStreams;
1656
1667
  existingCall.recording.isRecordingActive = call.recording.isRecordingActive;
1657
1668
  /* @conditional-compile-remove(rooms) */
1658
1669
  existingCall.role = call.role;
@@ -1861,6 +1872,15 @@ class CallContext$2 {
1861
1872
  }
1862
1873
  });
1863
1874
  }
1875
+ /* @conditional-compile-remove(optimal-video-count) */
1876
+ setOptimalVideoCount(callId, optimalVideoCount) {
1877
+ this.modifyState((draft) => {
1878
+ const call = draft.calls[this._callIdHistory.latestCallId(callId)];
1879
+ if (call) {
1880
+ call.optimalVideoCount.maxRemoteVideoStreams = optimalVideoCount;
1881
+ }
1882
+ });
1883
+ }
1864
1884
  /* @conditional-compile-remove(rooms) */
1865
1885
  setParticipantRole(callId, participantKey, role) {
1866
1886
  this.modifyState((draft) => {
@@ -3207,6 +3227,32 @@ const latestFromEvent = (args) => ({
3207
3227
  valueType: args.valueType
3208
3228
  });
3209
3229
 
3230
+ /* @conditional-compile-remove(optimal-video-count) */
3231
+ /**
3232
+ * Subscribes to a Optimal Video Count Feature events and updates the call context appropriately.
3233
+ * @private
3234
+ */
3235
+ class OptimalVideoCountSubscriber {
3236
+ constructor(args) {
3237
+ this.subscribe = () => {
3238
+ this._localOptimalVideoCountFeature.on('optimalVideoCountChanged', this.optimalVideoCountChanged);
3239
+ };
3240
+ this.unsubscribe = () => {
3241
+ this._localOptimalVideoCountFeature.off('optimalVideoCountChanged', this.optimalVideoCountChanged);
3242
+ };
3243
+ this.optimalVideoCountChanged = () => {
3244
+ this.updateOptimalVideoCountState({ maxRemoteVideoStreams: this._localOptimalVideoCountFeature.optimalVideoCount });
3245
+ };
3246
+ this.updateOptimalVideoCountState = (newOptimalVideoCountState) => {
3247
+ this._context.setOptimalVideoCount(this._callIdRef.callId, newOptimalVideoCountState.maxRemoteVideoStreams);
3248
+ };
3249
+ this._callIdRef = args.callIdRef;
3250
+ this._context = args.context;
3251
+ this._localOptimalVideoCountFeature = args.localOptimalVideoCountFeature;
3252
+ this.subscribe();
3253
+ }
3254
+ }
3255
+
3210
3256
  // Copyright (c) Microsoft Corporation.
3211
3257
  /**
3212
3258
  * Keeps track of the listeners assigned to a particular call because when we get an event from SDK, it doesn't tell us
@@ -3267,6 +3313,8 @@ class CallSubscriber {
3267
3313
  this._diagnosticsSubscriber.unsubscribe();
3268
3314
  this._recordingSubscriber.unsubscribe();
3269
3315
  this._transcriptionSubscriber.unsubscribe();
3316
+ /* @conditional-compile-remove(optimal-video-count) */
3317
+ this._optimalVideoCountSubscriber.unsubscribe();
3270
3318
  /* @conditional-compile-remove(close-captions) */
3271
3319
  (_a = this._captionsSubscriber) === null || _a === void 0 ? void 0 : _a.unsubscribe();
3272
3320
  };
@@ -3362,6 +3410,12 @@ class CallSubscriber {
3362
3410
  this._participantSubscribers = new Map();
3363
3411
  this._recordingSubscriber = new RecordingSubscriber(this._callIdRef, this._context, this._call.feature(communicationCalling.Features.Recording));
3364
3412
  this._transcriptionSubscriber = new TranscriptionSubscriber(this._callIdRef, this._context, this._call.feature(communicationCalling.Features.Transcription));
3413
+ /* @conditional-compile-remove(optimal-video-count) */
3414
+ this._optimalVideoCountSubscriber = new OptimalVideoCountSubscriber({
3415
+ callIdRef: this._callIdRef,
3416
+ context: this._context,
3417
+ localOptimalVideoCountFeature: this._call.feature(communicationCalling.Features.OptimalVideoCount)
3418
+ });
3365
3419
  /* @conditional-compile-remove(video-background-effects) */
3366
3420
  this._localVideoStreamVideoEffectsSubscribers = new Map();
3367
3421
  this.subscribe();
@@ -10229,6 +10283,7 @@ const ParticipantItem = (props) => {
10229
10283
  const theme = useTheme();
10230
10284
  const localeStrings = useLocale$1().strings.participantItem;
10231
10285
  const ids = useIdentifiers();
10286
+ const uniqueId = React.useId();
10232
10287
  const strings = Object.assign(Object.assign({}, localeStrings), props.strings);
10233
10288
  // For 'me' show empty name so avatar will get 'Person' icon, when there is no name
10234
10289
  const meAvatarText = (displayName === null || displayName === void 0 ? void 0 : displayName.trim()) || '';
@@ -10268,7 +10323,7 @@ const ParticipantItem = (props) => {
10268
10323
  React__default['default'].createElement(react.Stack, { horizontal: true, className: react.mergeStyles({
10269
10324
  width: `calc(100% - ${!me && participantStateString ? participantStateMaxWidth : menuButtonContainerStyle.width})`,
10270
10325
  alignItems: 'center'
10271
- }) },
10326
+ }), id: uniqueId, "aria-labelledby": `${props.ariaLabelledBy} ${uniqueId}` },
10272
10327
  avatar,
10273
10328
  me && React__default['default'].createElement(react.Text, { className: meTextStyle }, strings.isMeText),
10274
10329
  React__default['default'].createElement(react.Stack, { horizontal: true, className: react.mergeStyles(infoContainerStyle) }, onRenderIcon && onRenderIcon(props))),
@@ -10390,7 +10445,7 @@ const iconStyles$2 = react.mergeStyles({
10390
10445
  });
10391
10446
 
10392
10447
  // Copyright (c) Microsoft Corporation.
10393
- const onRenderParticipantDefault = (participant, strings, myUserId, onRenderAvatar, createParticipantMenuItems, styles, onParticipantClick, showParticipantOverflowTooltip) => {
10448
+ const onRenderParticipantDefault = (participant, strings, myUserId, onRenderAvatar, createParticipantMenuItems, styles, onParticipantClick, showParticipantOverflowTooltip, participantAriaLabelledBy) => {
10394
10449
  const callingParticipant = participant;
10395
10450
  let presence = undefined;
10396
10451
  if (callingParticipant) {
@@ -10410,7 +10465,7 @@ const onRenderParticipantDefault = (participant, strings, myUserId, onRenderAvat
10410
10465
  return (React__default['default'].createElement(ParticipantItem, { styles: styles, key: participant.userId, userId: participant.userId, displayName: participant.displayName, me: myUserId ? participant.userId === myUserId : false, menuItems: menuItems, presence: presence, onRenderIcon: onRenderIcon, onRenderAvatar: onRenderAvatar, onClick: () => onParticipantClick === null || onParticipantClick === void 0 ? void 0 : onParticipantClick(participant), showParticipantOverflowTooltip: showParticipantOverflowTooltip,
10411
10466
  /* @conditional-compile-remove(one-to-n-calling) */
10412
10467
  /* @conditional-compile-remove(PSTN-calls) */
10413
- participantState: callingParticipant.state }));
10468
+ participantState: callingParticipant.state, ariaLabelledBy: participantAriaLabelledBy }));
10414
10469
  };
10415
10470
  const getParticipantsForDefaultRender = (participants, excludeMe, myUserId) => {
10416
10471
  if (!excludeMe || !myUserId) {
@@ -10433,7 +10488,7 @@ const getParticipantsForDefaultRender = (participants, excludeMe, myUserId) => {
10433
10488
  */
10434
10489
  const ParticipantList = (props) => {
10435
10490
  var _a, _b, _c, _d;
10436
- const { excludeMe = false, myUserId, participants, onRemoveParticipant, onRenderAvatar, onRenderParticipant, onFetchParticipantMenuItems, showParticipantOverflowTooltip } = props;
10491
+ const { excludeMe = false, myUserId, participants, onRemoveParticipant, onRenderAvatar, onRenderParticipant, onFetchParticipantMenuItems, showParticipantOverflowTooltip, participantAriaLabelledBy } = props;
10437
10492
  const ids = useIdentifiers();
10438
10493
  const strings = useLocale$1().strings.participantItem;
10439
10494
  const displayedParticipants = React.useMemo(() => {
@@ -10471,7 +10526,7 @@ const ParticipantList = (props) => {
10471
10526
  const participantItemStyles = React.useMemo(() => { var _a; return react.merge(participantListItemStyle, (_a = props.styles) === null || _a === void 0 ? void 0 : _a.participantItemStyles); }, [(_c = props.styles) === null || _c === void 0 ? void 0 : _c.participantItemStyles]);
10472
10527
  return (React__default['default'].createElement(react.Stack, { "data-ui-id": ids.participantList, className: react.mergeStyles(participantListStyle$1, (_d = props.styles) === null || _d === void 0 ? void 0 : _d.root) }, displayedParticipants.map((participant) => onRenderParticipant
10473
10528
  ? onRenderParticipant(participant)
10474
- : onRenderParticipantDefault(participant, strings, myUserId, onRenderAvatar, createParticipantMenuItems, participantItemStyles, props.onParticipantClick, showParticipantOverflowTooltip))));
10529
+ : onRenderParticipantDefault(participant, strings, myUserId, onRenderAvatar, createParticipantMenuItems, participantItemStyles, props.onParticipantClick, showParticipantOverflowTooltip, participantAriaLabelledBy))));
10475
10530
  };
10476
10531
 
10477
10532
  // Copyright (c) Microsoft Corporation.
@@ -11713,12 +11768,11 @@ const participantsById = (participants) => {
11713
11768
  };
11714
11769
 
11715
11770
  // Copyright (c) Microsoft Corporation.
11716
- const DEFAULT_MAX_REMOTE_VIDEOSTREAMS = 4;
11717
11771
  const DEFAULT_MAX_OVERFLOW_GALLERY_DOMINANT_SPEAKERS = 6;
11718
11772
  const _useOrganizedParticipants = (props) => {
11719
11773
  const visibleGridParticipants = React.useRef([]);
11720
11774
  const visibleOverflowGalleryParticipants = React.useRef([]);
11721
- const { remoteParticipants = [], dominantSpeakers = [], maxRemoteVideoStreams = DEFAULT_MAX_REMOTE_VIDEOSTREAMS, maxOverflowGalleryDominantSpeakers = DEFAULT_MAX_OVERFLOW_GALLERY_DOMINANT_SPEAKERS, isScreenShareActive = false, pinnedParticipantUserIds = [] } = props;
11775
+ const { remoteParticipants = [], dominantSpeakers = [], maxRemoteVideoStreams, maxOverflowGalleryDominantSpeakers = DEFAULT_MAX_OVERFLOW_GALLERY_DOMINANT_SPEAKERS, isScreenShareActive = false, pinnedParticipantUserIds = [] } = props;
11722
11776
  const videoParticipants = remoteParticipants.filter((p) => { var _a; return (_a = p.videoStream) === null || _a === void 0 ? void 0 : _a.isAvailable; });
11723
11777
  visibleGridParticipants.current =
11724
11778
  pinnedParticipantUserIds.length > 0 || isScreenShareActive
@@ -12621,9 +12675,7 @@ const DefaultLayout = (props) => {
12621
12675
  * re-render the initial tiles -> dispose them -> create new tiles, we need to take care of
12622
12676
  * this case when those components are here
12623
12677
  */
12624
- const [indexesToRender, setIndexesToRender] = React.useState([
12625
- ...Array(maxRemoteVideoStreams - activeVideoStreams).keys()
12626
- ]);
12678
+ const [indexesToRender, setIndexesToRender] = React.useState([]);
12627
12679
  const overflowGalleryTiles = overflowGalleryParticipants.map((p, i) => {
12628
12680
  var _a, _b;
12629
12681
  return onRenderRemoteParticipant(p, maxRemoteVideoStreams && maxRemoteVideoStreams >= 0
@@ -13446,9 +13498,7 @@ const FloatingLocalVideoLayout = (props) => {
13446
13498
  * re-render the initial tiles -> dispose them -> create new tiles, we need to take care of
13447
13499
  * this case when those components are here
13448
13500
  */
13449
- const [indexesToRender, setIndexesToRender] = React.useState([
13450
- ...Array(maxRemoteVideoStreams - activeVideoStreams).keys()
13451
- ]);
13501
+ const [indexesToRender, setIndexesToRender] = React.useState([]);
13452
13502
  const overflowGalleryTiles = overflowGalleryParticipants.map((p, i) => {
13453
13503
  var _a, _b;
13454
13504
  return onRenderRemoteParticipant(p, maxRemoteVideoStreams && maxRemoteVideoStreams >= 0
@@ -16313,8 +16363,12 @@ const videoGallerySelector = reselect.createSelector([
16313
16363
  getIsScreenSharingOn,
16314
16364
  getDisplayName$2,
16315
16365
  getIdentifier,
16316
- getDominantSpeakers
16317
- ], (screenShareRemoteParticipantId, remoteParticipants, localVideoStreams, isMuted, isScreenSharingOn, displayName, identifier, dominantSpeakers) => {
16366
+ getDominantSpeakers,
16367
+ /* @conditional-compile-remove(optimal-video-count) */
16368
+ getOptimalVideoCount
16369
+ ], (screenShareRemoteParticipantId, remoteParticipants, localVideoStreams, isMuted, isScreenSharingOn, displayName, identifier, dominantSpeakers,
16370
+ /* @conditional-compile-remove(optimal-video-count) */
16371
+ optimalVideoCount) => {
16318
16372
  const screenShareRemoteParticipant = screenShareRemoteParticipantId && remoteParticipants
16319
16373
  ? remoteParticipants[screenShareRemoteParticipantId]
16320
16374
  : undefined;
@@ -16328,7 +16382,9 @@ const videoGallerySelector = reselect.createSelector([
16328
16382
  : undefined,
16329
16383
  localParticipant: memoizeLocalParticipant(identifier, displayName, isMuted, isScreenSharingOn, localVideoStream),
16330
16384
  remoteParticipants: _videoGalleryRemoteParticipantsMemo(updateUserDisplayNamesTrampoline$2(remoteParticipants ? Object.values(remoteParticipants) : noRemoteParticipants)),
16331
- dominantSpeakers: dominantSpeakerIds
16385
+ dominantSpeakers: dominantSpeakerIds,
16386
+ /* @conditional-compile-remove(optimal-video-count) */
16387
+ maxRemoteVideoStreams: optimalVideoCount
16332
16388
  };
16333
16389
  });
16334
16390
  const updateUserDisplayNamesTrampoline$2 = (remoteParticipants) => {
@@ -20632,6 +20688,7 @@ const ParticipantContainer = (props) => {
20632
20688
  */
20633
20689
  const ParticipantListWithHeading = (props) => {
20634
20690
  const { onFetchAvatarPersonaData, onFetchParticipantMenuItems, title, participantListProps } = props;
20691
+ const subheadingUniqueId = React.useId();
20635
20692
  const theme = react.useTheme();
20636
20693
  const subheadingStyleThemed = React.useMemo(() => ({
20637
20694
  root: {
@@ -20641,11 +20698,11 @@ const ParticipantListWithHeading = (props) => {
20641
20698
  }
20642
20699
  }), [theme.palette.neutralSecondary, theme.fonts.smallPlus.fontSize, props.isMobile]);
20643
20700
  return (React__default['default'].createElement(react.Stack, { className: participantListStack },
20644
- React__default['default'].createElement(react.Stack.Item, { styles: subheadingStyleThemed, "aria-label": title }, title),
20701
+ React__default['default'].createElement(react.Stack.Item, { styles: subheadingStyleThemed, "aria-label": title, id: subheadingUniqueId }, title),
20645
20702
  React__default['default'].createElement(react.FocusZone, { className: participantListContainerStyle, shouldFocusOnMount: true },
20646
20703
  React__default['default'].createElement(ParticipantList, Object.assign({}, participantListProps, { styles: props.isMobile ? participantListMobileStyle : participantListStyle, onRenderAvatar: (userId, options) => (React__default['default'].createElement(React__default['default'].Fragment, null,
20647
20704
  React__default['default'].createElement(AvatarPersona, Object.assign({ "data-ui-id": "chat-composite-participant-custom-avatar", userId: userId }, options, { hidePersonaDetails: !!(options === null || options === void 0 ? void 0 : options.text) }, { dataProvider: onFetchAvatarPersonaData })),
20648
- (options === null || options === void 0 ? void 0 : options.text) && (React__default['default'].createElement(react.Text, { nowrap: true, styles: displayNameStyles$1 }, options === null || options === void 0 ? void 0 : options.text)))), onFetchParticipantMenuItems: onFetchParticipantMenuItems, showParticipantOverflowTooltip: !props.isMobile })))));
20705
+ (options === null || options === void 0 ? void 0 : options.text) && (React__default['default'].createElement(react.Text, { nowrap: true, styles: displayNameStyles$1 }, options === null || options === void 0 ? void 0 : options.text)))), onFetchParticipantMenuItems: onFetchParticipantMenuItems, showParticipantOverflowTooltip: !props.isMobile, participantAriaLabelledBy: subheadingUniqueId })))));
20649
20706
  };
20650
20707
 
20651
20708
  // Copyright (c) Microsoft Corporation.