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

189 lines
4.1 KiB
TypeScript
Raw Normal View History

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';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
2020-05-20 10:57:03 +00:00
import { styleTypeToObject } from '../../styles';
2019-08-30 16:39:06 +00:00
interface IProps {
2019-08-30 16:39:06 +00:00
/**
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
*/
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
*/
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
*/
ariaDisabled?: boolean;
2019-08-30 16:39:06 +00:00
/**
2022-07-20 08:47:01 +00:00
* Whether the element popup is expanded.
*/
ariaExpanded?: boolean;
/**
2022-07-20 08:47:01 +00:00
* Whether the element has a popup.
*/
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
*/
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
*/
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
*/
className?: string;
/**
2022-07-20 08:47:01 +00:00
* Color of the icon (if not provided by the style object).
*/
color?: string;
/**
2022-07-20 08:47:01 +00:00
* Id of the icon container.
*/
containerId?: string;
/**
2022-07-20 08:47:01 +00:00
* Id prop (mainly for autotests).
*/
id?: string;
/**
2022-07-20 08:47:01 +00:00
* Function to invoke on click.
*/
onClick?: Function;
/**
2022-07-20 08:47:01 +00:00
* Keydown handler.
*/
onKeyDown?: Function;
/**
2022-07-20 08:47:01 +00:00
* Keypress handler.
*/
onKeyPress?: Function;
/**
2022-07-20 08:47:01 +00:00
* Role for the Icon.
*/
role?: string;
/**
2022-07-20 08:47:01 +00:00
* The size of the icon (if not provided by the style object).
*/
size?: number | string;
/**
2022-07-20 08:47:01 +00:00
* The preloaded icon component to render.
*/
src: Function;
/**
2022-07-20 08:47:01 +00:00
* Style object to be applied.
*/
style?: Object;
/**
2022-07-20 08:47:01 +00:00
* TabIndex for the Icon.
*/
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 {IProps} props - The props of the component.
* @returns {ReactElement}
2019-08-30 16:39:06 +00:00
*/
export default function Icon(props: IProps) {
2019-08-30 16:39:06 +00:00
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
}: IProps = 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: ''
};