packages/react-components/src/components/styles/TogetherMode.styles.ts (178 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/* @conditional-compile-remove(together-mode) */
import { _pxToRem } from '@internal/acs-ui-common';
/* @conditional-compile-remove(together-mode) */
import { VideoGalleryTogetherModeSeatingInfo } from '../../types/TogetherModeTypes';
/* @conditional-compile-remove(together-mode) */
import { IStackStyles } from '@fluentui/react';
/* @conditional-compile-remove(together-mode) */
import { CSSProperties } from 'react';
/* @conditional-compile-remove(together-mode) */
/**
* Multiplier to convert rem units to pixels.
*/
export const REM_TO_PX_MULTIPLIER = 16;
/* @conditional-compile-remove(together-mode) */
/**
* The travel height for reactions in Together Mode.
* The reaction move overlay uses pixel units, so the seat position height, defined in rem, needs to be converted to pixels
*/
export const REACTION_TRAVEL_HEIGHT = 0.35 * REM_TO_PX_MULTIPLIER;
/* @conditional-compile-remove(together-mode) */
/**
* Defines the maximum travel height for reactions in Together Mode.
* Ensures the reaction animation does not exceed the center point from the top.
* Since the reaction move overlay uses pixel units, the seat position height (defined in rem) must be converted to pixels.
*/
export const REACTION_MAX_TRAVEL_HEIGHT = 0.5 * REM_TO_PX_MULTIPLIER;
/* @conditional-compile-remove(together-mode) */
/**
* The maximum width for displaying the participant's display name.
*/
export const MAX_DISPLAY_NAME_WIDTH = 150;
/* @conditional-compile-remove(together-mode) */
/**
* Interface for defining the coordinates of a seat in Together Mode.
*/
export interface TogetherModeParticipantSeatPosition {
height: string;
width: string;
left: string;
top: string;
}
/* @conditional-compile-remove(together-mode) */
/**
* Interface for defining the style of a seat position in Together Mode.
*/
export interface TogetherModeSeatStyle {
seatPosition: TogetherModeParticipantSeatPosition;
}
/* @conditional-compile-remove(together-mode) */
/**
* Sets the seating position for a participant in Together Mode.
*
* @param seatingPosition - The seating position information.
* @returns The style object for the seating position.
*/
export function setParticipantSeatingPosition(
seatingPosition: VideoGalleryTogetherModeSeatingInfo
): TogetherModeParticipantSeatPosition {
return {
width: _pxToRem(seatingPosition.width),
height: _pxToRem(seatingPosition.height),
left: _pxToRem(seatingPosition.left),
top: _pxToRem(seatingPosition.top)
};
}
/* @conditional-compile-remove(together-mode) */
/**
* Return a style bucket based on the number of active sprites.
* For example, the first three reactions should appear at maximum
* height, width, and opacity.
* @private
*/
export function setTogetherModeSeatPositionStyle(
seatingPosition: VideoGalleryTogetherModeSeatingInfo
): TogetherModeSeatStyle {
return {
seatPosition: setParticipantSeatingPosition(seatingPosition)
};
}
/* @conditional-compile-remove(together-mode) */
/**
* The style for the Together Mode meeting overlay.
*/
export const togetherModeMeetingOverlayStyle: CSSProperties = {
width: '100%',
height: '100%',
position: 'absolute',
top: '0',
left: '0'
};
/* @conditional-compile-remove(together-mode) */
/**
* Generates the overlay style for a participant in Together Mode.
*
* @param seatingPosition - The seating position information.
* @returns The style object for the participant overlay.
*/
export function getTogetherModeParticipantOverlayStyle(seatingPositionStyle: TogetherModeSeatStyle): CSSProperties {
return {
...seatingPositionStyle.seatPosition,
position: 'absolute'
};
}
/* @conditional-compile-remove(together-mode) */
// Function to map a value from one range to another
const mapRange = (value: number, inMin: number, inMax: number, outMin: number, outMax: number): number => {
return outMin + ((value - inMin) * (outMax - outMin)) / (inMax - inMin);
};
/* @conditional-compile-remove(together-mode) */
/**
* Calculate the reaction emoji scaled size based on width and height of the participant seat width and height.
* This is needed when the browser is resized and the participant seat width and height changes.
*
* @param width - The width of the element.
* @param height - The height of the element.
* @returns The scaled size.
*/
export const calculateScaledSize = (width: number, height: number): number => {
// Maximum participant seat width and height
const maxSize = 600;
// Minimum participant seat width and height
const minSize = 200;
// Minimum scaled width and height of the reaction emoji
const minScaledSize = 35;
// Maximum scaled width and height of the reaction emoji
const maxScaledSize = 70;
// Use width or height to determine scaling factor
const size = Math.min(width, height);
// Map the size to the desired range
return mapRange(size, minSize, maxSize, minScaledSize, maxScaledSize);
};
/* @conditional-compile-remove(together-mode) */
/**
* @private
*/
export const togetherModeStreamRootStyle: IStackStyles = {
root: {
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
top: 0,
left: 0
}
};
/* @conditional-compile-remove(together-mode) */
/**
* @private
*/
export const togetherModeIconStyle = (): CSSProperties => {
return {
width: _pxToRem(20),
flexShrink: 0
};
};
/* @conditional-compile-remove(together-mode) */
/**
* The style for the container holding the display name, raiseHand, spotlight and mute icons.
* @private
*/
export const togetherModeParticipantStatusContainer = (
backgroundColor: string,
borderRadius: string
): CSSProperties => {
return {
backgroundColor,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: _pxToRem(2),
margin: '0 auto', // Centers the container
padding: `0 ${_pxToRem(5)}`,
borderRadius,
width: 'fit-content'
};
};
/* @conditional-compile-remove(together-mode) */
/**
* @private
*/
export const togetherModeParticipantDisplayName = (
isParticipantHovered: boolean,
participantSeatingWidth: number,
color: string
): React.CSSProperties => {
// expands the display name width when participant is hovered or clicked on else make it 70% of the participant seating width
const width =
isParticipantHovered || participantSeatingWidth * REM_TO_PX_MULTIPLIER > MAX_DISPLAY_NAME_WIDTH
? 'fit-content'
: _pxToRem(0.7 * participantSeatingWidth * REM_TO_PX_MULTIPLIER);
// For smaller displays, the display name is hidden only participant is hovered or clicked on for mobile view
const showDisplayName =
isParticipantHovered || participantSeatingWidth * REM_TO_PX_MULTIPLIER > MAX_DISPLAY_NAME_WIDTH
? 'inline-block'
: 'none';
return {
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
textAlign: 'center',
color,
overflow: isParticipantHovered ? 'visible' : 'hidden',
width,
display: showDisplayName,
fontSize: `${_pxToRem(13)}`,
lineHeight: `${_pxToRem(20)}`,
maxWidth: isParticipantHovered ? 'fit-content' : _pxToRem(0.7 * participantSeatingWidth * REM_TO_PX_MULTIPLIER)
};
};
/* @conditional-compile-remove(together-mode) */
/**
* @private
*/
export const togetherModeParticipantEmojiSpriteStyle = (
emojiSize: number,
emojiScaledSize: number,
participantSeatWidth: string
): CSSProperties => {
const participantSeatWidthInPixel = parseFloat(participantSeatWidth) * REM_TO_PX_MULTIPLIER;
const emojiScaledSizeInPercent = 100 - (emojiScaledSize / participantSeatWidthInPixel) * 100;
return {
width: `${emojiSize}`,
position: 'absolute',
// Center the emoji sprite within the participant seat
left: `${emojiScaledSizeInPercent / 2}%`
};
};
/* @conditional-compile-remove(together-mode) */
/**
* The style for the transition of the participant status container in Together Mode.
* @private
*/
export const participantStatusTransitionStyle: CSSProperties = {
position: 'absolute',
bottom: `${_pxToRem(2)}`,
width: 'fit-content',
textAlign: 'center',
transform: 'translate(-50%)',
transition: 'width 0.3s ease, transform 0.3s ease',
left: '50%'
};