jiti-meet/react/features/base/icons/components/Icon.tsx

190 lines
4.1 KiB
TypeScript
Raw Normal View History

/* eslint-disable import/order */
import React, { useCallback } from 'react';
2019-08-30 16:39:06 +00:00
// @ts-ignore
2019-08-30 16:39:06 +00:00
import { Container } from '../../react/base';
// @ts-ignore
2020-05-20 10:57:03 +00:00
import { styleTypeToObject } from '../../styles';
2019-08-30 16:39:06 +00:00
type Props = {
/**
2022-07-20 08:47:01 +00:00
* The id of the element this button icon controls.
2019-08-30 16:39:06 +00:00
*/
2022-07-20 08:47:01 +00:00
ariaControls?: string,
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Id of description label.
2019-08-30 16:39:06 +00:00
*/
2022-07-20 08:47:01 +00:00
ariaDescribedBy?: string,
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Aria disabled flag for the Icon.
2019-08-30 16:39:06 +00:00
*/
2022-07-20 08:47:01 +00:00
ariaDisabled?: boolean,
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Whether the element popup is expanded.
*/
2022-07-20 08:47:01 +00:00
ariaExpanded?: boolean,
/**
2022-07-20 08:47:01 +00:00
* Whether the element has a popup.
*/
2022-07-20 08:47:01 +00:00
ariaHasPopup?: boolean,
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Aria label for the Icon.
2019-08-30 16:39:06 +00:00
*/
2022-07-20 08:47:01 +00:00
ariaLabel?: string,
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Whether the element has a pressed.
2019-08-30 16:39:06 +00:00
*/
2022-07-20 08:47:01 +00:00
ariaPressed?: boolean,
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Class name for the web platform, if any.
2019-08-30 16:39:06 +00:00
*/
2022-07-20 08:47:01 +00:00
className?: string,
/**
2022-07-20 08:47:01 +00:00
* Color of the icon (if not provided by the style object).
*/
2022-07-20 08:47:01 +00:00
color?: string,
/**
2022-07-20 08:47:01 +00:00
* Id of the icon container.
*/
2022-07-20 08:47:01 +00:00
containerId?: string,
/**
2022-07-20 08:47:01 +00:00
* Id prop (mainly for autotests).
*/
2022-07-20 08:47:01 +00:00
id?: string,
/**
2022-07-20 08:47:01 +00:00
* Function to invoke on click.
*/
2022-07-20 08:47:01 +00:00
onClick?: Function,
/**
2022-07-20 08:47:01 +00:00
* Keydown handler.
*/
2022-07-20 08:47:01 +00:00
onKeyDown?: Function,
/**
2022-07-20 08:47:01 +00:00
* Keypress handler.
*/
2022-07-20 08:47:01 +00:00
onKeyPress?: Function,
/**
2022-07-20 08:47:01 +00:00
* Role for the Icon.
*/
2022-07-20 08:47:01 +00:00
role?: string,
/**
2022-07-20 08:47:01 +00:00
* The size of the icon (if not provided by the style object).
*/
2022-07-20 08:47:01 +00:00
size?: number | string,
/**
2022-07-20 08:47:01 +00:00
* The preloaded icon component to render.
*/
2022-07-20 08:47:01 +00:00
src: Function,
/**
2022-07-20 08:47:01 +00:00
* Style object to be applied.
*/
2022-07-20 08:47:01 +00:00
style?: Object,
/**
2022-07-20 08:47:01 +00:00
* TabIndex for the Icon.
*/
2022-07-20 08:47:01 +00:00
tabIndex?: number
}
2019-08-30 16:39:06 +00:00
export const DEFAULT_COLOR = navigator.product === 'ReactNative' ? 'white' : undefined;
2021-02-23 11:09:22 +00:00
export const DEFAULT_SIZE = navigator.product === 'ReactNative' ? 36 : 22;
2019-08-30 16:39:06 +00:00
/**
* Implements an Icon component that takes a loaded SVG file as prop and renders it as an icon.
*
* @param {Props} props - The props of the component.
* @returns {ReactElement}
2019-08-30 16:39:06 +00:00
*/
export default function Icon(props: Props) {
const {
className,
color,
id,
containerId,
onClick,
2019-08-30 16:39:06 +00:00
size,
src: IconComponent,
style,
ariaHasPopup,
ariaLabel,
ariaDisabled,
ariaExpanded,
ariaControls,
tabIndex,
ariaPressed,
ariaDescribedBy,
role,
onKeyPress,
onKeyDown,
...rest
}: Props = props;
2019-08-30 16:39:06 +00:00
const {
color: styleColor,
fontSize: styleSize,
...restStyle
} = styleTypeToObject(style ?? {});
const calculatedColor = color ?? styleColor ?? DEFAULT_COLOR;
const calculatedSize = size ?? styleSize ?? DEFAULT_SIZE;
const onKeyPressHandler = useCallback(e => {
if ((e.key === 'Enter' || e.key === ' ') && onClick) {
e.preventDefault();
onClick(e);
} else if (onKeyPress) {
onKeyPress(e);
}
}, [ onClick, onKeyPress ]);
const jitsiIconClassName = calculatedColor ? 'jitsi-icon' : 'jitsi-icon jitsi-icon-default';
2019-08-30 16:39:06 +00:00
return (
<Container
{ ...rest }
aria-controls = { ariaControls }
aria-describedby = { ariaDescribedBy }
aria-disabled = { ariaDisabled }
aria-expanded = { ariaExpanded }
aria-haspopup = { ariaHasPopup }
aria-label = { ariaLabel }
aria-pressed = { ariaPressed }
className = { `${jitsiIconClassName} ${className || ''}` }
id = { containerId }
onClick = { onClick }
onKeyDown = { onKeyDown }
onKeyPress = { onKeyPressHandler }
role = { role }
style = { restStyle }
tabIndex = { tabIndex }>
2019-08-30 16:39:06 +00:00
<IconComponent
fill = { calculatedColor }
height = { calculatedSize }
id = { id }
width = { calculatedSize } />
</Container>
);
}
Icon.defaultProps = {
className: ''
};