bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/common/button/component.jsx

271 lines
5.8 KiB
React
Raw Normal View History

import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import TooltipContainer from '/imports/ui/components/common/tooltip/container';
2021-11-10 19:37:08 +08:00
import Styled from './styles';
import BaseButton from './base/component';
import ButtonEmoji from './button-emoji/ButtonEmoji';
const SIZES = [
2016-10-12 03:04:50 +08:00
'jumbo', 'lg', 'md', 'sm',
];
const COLORS = [
2022-08-29 20:39:20 +08:00
'default', 'primary', 'danger', 'warning', 'success', 'dark', 'light', 'offline', 'muted', 'secondary',
];
const propTypes = {
...BaseButton.propTypes,
/**
* Defines the button size style
* @type {("lg"|"md"|"sm")}
* @defaultValue 'md'
*/
size: PropTypes.oneOf(SIZES),
/**
* Defines the button color style
* @type {("default"|"primary"|"danger"|"success")}
* @defaultValue 'md'
*/
color: PropTypes.oneOf(COLORS),
/**
* Defines if the button should be styled as a ghost (outline)
* @defaultValue false
*/
ghost: PropTypes.bool,
/**
* Defines if the button should be styled as circle
* @defaultValue false
*/
circle: PropTypes.bool,
/**
* Defines if the button should have `display: block`
* @defaultValue false
*/
block: PropTypes.bool,
/**
* Defines the button icon
* @defaultValue undefined
*/
icon: PropTypes.string,
/**
* Defines the button icon is on the right side
* @defaultValue false
*/
iconRight: PropTypes.bool,
/**
* Defines the button label should be visible
* @defaultValue false
*/
hideLabel: PropTypes.bool,
/**
2017-06-03 07:41:28 +08:00
* Optional SVG / html object can be passed to the button as an icon
* Has to be styled before being sent to the Button
* (e.g width, height, position and percentage-based object's coordinates)
* @defaultvalue undefined
*/
2017-06-03 07:41:28 +08:00
customIcon: PropTypes.node,
2024-08-06 01:05:04 +08:00
/**
* Defines the buttom loading state
* @defaultValue false
*/
loading: PropTypes.bool,
};
const defaultProps = {
...BaseButton.defaultProps,
size: 'md',
color: 'default',
ghost: false,
circle: false,
block: false,
iconRight: false,
hideLabel: false,
tooltipLabel: '',
2024-08-06 01:05:04 +08:00
loading: false,
};
export default class Button extends BaseButton {
_cleanProps(otherProps) {
const remainingProps = Object.assign({}, otherProps);
delete remainingProps.icon;
delete remainingProps.customIcon;
delete remainingProps.size;
delete remainingProps.color;
delete remainingProps.ghost;
delete remainingProps.circle;
delete remainingProps.block;
delete remainingProps.hideLabel;
delete remainingProps.tooltipLabel;
return remainingProps;
}
hasButtonEmojiComponent() {
const { children } = this.props;
if (!children) return false;
const buttonEmoji = React.Children.only(children);
return (buttonEmoji && buttonEmoji.type && buttonEmoji.type.name)
? (buttonEmoji.type.name === ButtonEmoji.name)
: false;
}
render() {
const {
circle,
hideLabel,
label,
'aria-label': ariaLabel,
2018-12-12 22:01:33 +08:00
'aria-expanded': ariaExpanded,
tooltipLabel,
2023-04-04 11:09:45 +08:00
tooltipdelay,
tooltipplacement,
} = this.props;
const renderFuncName = circle ? 'renderCircle' : 'renderDefault';
if ((hideLabel && !ariaExpanded) || tooltipLabel) {
const buttonLabel = label || ariaLabel;
return (
<TooltipContainer
title={tooltipLabel || buttonLabel}
2023-04-04 11:09:45 +08:00
delay={tooltipdelay}
placement={tooltipplacement}
>
{this[renderFuncName]()}
</TooltipContainer>
);
}
return this[renderFuncName]();
}
renderDefault() {
const {
className,
iconRight,
2021-11-10 22:41:55 +08:00
size,
color,
ghost,
circle,
block,
2024-08-06 01:05:04 +08:00
loading,
...otherProps
} = this.props;
const remainingProps = this._cleanProps(otherProps);
2016-07-12 04:10:55 +08:00
return (
2021-11-10 22:41:55 +08:00
<Styled.Button
size={size}
color={color}
ghost={ghost}
circle={circle}
block={block}
className={className}
iconRight={iconRight}
2024-08-06 01:05:04 +08:00
loading={loading}
2016-07-12 04:10:55 +08:00
{...remainingProps}
>
{this.renderIcon()}
{this.renderLabel()}
2021-11-10 22:41:55 +08:00
</Styled.Button>
);
}
renderCircle() {
const {
className,
size,
2016-05-27 08:13:53 +08:00
iconRight,
children,
2021-11-10 22:41:55 +08:00
color,
ghost,
circle,
block,
2024-08-06 01:05:04 +08:00
loading,
...otherProps
} = this.props;
const remainingProps = this._cleanProps(otherProps);
2016-07-12 04:10:55 +08:00
return (
2021-11-10 22:41:55 +08:00
<Styled.ButtonWrapper
size={size}
className={cx(size, 'buttonWrapper', className)}
color={color}
ghost={ghost}
circle={circle}
block={block}
2024-08-06 01:05:04 +08:00
loading={loading}
2016-07-12 04:10:55 +08:00
{...remainingProps}
>
{this.renderButtonEmojiSibling()}
{!iconRight ? null : this.renderLabel()}
2021-11-10 22:41:55 +08:00
<Styled.ButtonSpan
size={size}
color={color}
ghost={ghost}
circle={circle}
block={block}
>
{this.renderIcon()}
2021-11-10 22:41:55 +08:00
</Styled.ButtonSpan>
{iconRight ? null : this.renderLabel()}
{this.hasButtonEmojiComponent() ? children : null}
2021-11-10 22:41:55 +08:00
</Styled.ButtonWrapper>
);
}
renderButtonEmojiSibling() {
if (!this.hasButtonEmojiComponent()) {
return null;
}
2021-11-10 22:41:55 +08:00
return (<Styled.EmojiButtonSibling />);
}
renderIcon() {
2019-03-09 08:33:04 +08:00
const {
icon: iconName,
customIcon,
} = this.props;
if (iconName) {
2021-11-10 19:37:08 +08:00
return (<Styled.ButtonIcon iconName={iconName} />);
2018-12-06 01:42:31 +08:00
} if (customIcon) {
2017-06-03 07:41:28 +08:00
return customIcon;
}
return null;
}
renderLabel() {
const { label, hideLabel } = this.props;
if (!label) return null;
return (
2021-11-10 22:41:55 +08:00
<Styled.ButtonLabel hideLabel={hideLabel}>
{label}
{!this.hasButtonEmojiComponent() ? this.props.children : null}
2021-11-10 22:41:55 +08:00
</Styled.ButtonLabel>
);
}
}
Button.propTypes = propTypes;
Button.defaultProps = defaultProps;