11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT license.
33
4+ import { IContextualMenuProps } from '@fluentui/react' ;
45import React , { useCallback , useState } from 'react' ;
56import { useLocale } from '../localization' ;
67import { VideoStreamOptions } from '../types' ;
78import { ControlBarButton , ControlBarButtonProps } from './ControlBarButton' ;
89import { HighContrastAwareIcon } from './HighContrastAwareIcon' ;
910
11+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
12+ import { IContextualMenuItemStyles , IContextualMenuStyles } from '@fluentui/react' ;
13+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
14+ import { ControlBarButtonStyles } from './ControlBarButton' ;
15+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
16+ import { OptionsDevice , generateDefaultDeviceMenuProps } from './DevicesButton' ;
17+
1018const defaultLocalVideoViewOptions = {
1119 scalingMode : 'Crop' ,
1220 isMirrored : true
@@ -30,8 +38,43 @@ export interface CameraButtonStrings {
3038 tooltipOffContent ?: string ;
3139 /** Tooltip content when the button is disabled due to video loading. */
3240 tooltipVideoLoadingContent ?: string ;
41+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
42+ /**
43+ * Title of camera menu
44+ */
45+ cameraMenuTitle : string ;
46+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
47+ /**
48+ * Tooltip of camera menu
49+ */
50+ cameraMenuTooltip : string ;
3351}
3452
53+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
54+ /**
55+ * Styles for {@link CameraButton}
56+ *
57+ * @public
58+ */
59+ export interface CameraButtonStyles extends ControlBarButtonStyles {
60+ /**
61+ * Styles for the {@link CameraButton} menu.
62+ */
63+ menuStyles ?: Partial < CameraButtonContextualMenuStyles > ;
64+ }
65+
66+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
67+ /**
68+ * Styles for the {@link CameraButton} menu.
69+ *
70+ * @public
71+ */
72+ export interface CameraButtonContextualMenuStyles extends IContextualMenuStyles {
73+ /**
74+ * Styles for the items inside the {@link CameraButton} button menu.
75+ */
76+ menuItemStyles ?: IContextualMenuItemStyles ;
77+ }
3578/**
3679 * Props for {@link CameraButton} component.
3780 *
@@ -48,11 +91,37 @@ export interface CameraButtonProps extends ControlBarButtonProps {
4891 * Options for rendering local video view.
4992 */
5093 localVideoViewOptions ?: VideoStreamOptions ;
51-
94+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
95+ /**
96+ * Available cameras for selection
97+ */
98+ cameras ?: OptionsDevice [ ] ;
99+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
100+ /**
101+ * Camera that is shown as currently selected
102+ */
103+ selectedCamera ?: OptionsDevice ;
104+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
105+ /**
106+ * Callback when a camera is selected
107+ */
108+ onSelectCamera ?: ( device : OptionsDevice ) => Promise < void > ;
109+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
110+ /**
111+ * Whether to use a {@link SplitButton} with a {@link IContextualMenu} for device selection.
112+ *
113+ * default: false
114+ */
115+ enableDeviceSelectionMenu ?: boolean ;
52116 /**
53117 * Optional strings to override in component
54118 */
55119 strings ?: Partial < CameraButtonStrings > ;
120+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
121+ /**
122+ * Styles for {@link CameraButton} and the device selection flyout.
123+ */
124+ styles ?: Partial < CameraButtonStyles > ;
56125}
57126
58127/**
@@ -98,6 +167,28 @@ export const CameraButton = (props: CameraButtonProps): JSX.Element => {
98167 onRenderOffIcon = { props . onRenderOffIcon ?? onRenderCameraOffIcon }
99168 strings = { strings }
100169 labelKey = { props . labelKey ?? 'cameraButtonLabel' }
170+ menuProps = { props . menuProps ?? generateDefaultDeviceMenuPropsTrampoline ( props , strings ) }
171+ menuIconProps = { props . menuIconProps ?? ! enableDeviceSelectionMenuTrampoline ( props ) ? { hidden : true } : undefined }
172+ split = { props . split ?? enableDeviceSelectionMenuTrampoline ( props ) }
101173 />
102174 ) ;
103175} ;
176+
177+ const generateDefaultDeviceMenuPropsTrampoline = (
178+ props : CameraButtonProps ,
179+ strings : CameraButtonStrings
180+ ) : IContextualMenuProps | undefined => {
181+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
182+ if ( props . enableDeviceSelectionMenu ) {
183+ return generateDefaultDeviceMenuProps ( { ...props , styles : props . styles ?. menuStyles } , strings ) ;
184+ }
185+ return undefined ;
186+ } ;
187+
188+ const enableDeviceSelectionMenuTrampoline = ( props : CameraButtonProps ) : boolean => {
189+ /* @conditional -compile-remove-from(stable) meeting-composite control-bar-split-buttons */
190+ if ( props . enableDeviceSelectionMenu ) {
191+ return true ;
192+ }
193+ return false ;
194+ } ;
0 commit comments