jiti-meet/react/features/toolbox/components/ToolbarButton.web.js

265 lines
6.3 KiB
JavaScript
Raw Normal View History

2017-02-16 23:02:40 +00:00
/* @flow */
import AKInlineDialog from '@atlaskit/inline-dialog';
2017-08-15 22:39:42 +00:00
import { Tooltip } from '@atlaskit/tooltip';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
2017-02-16 23:02:40 +00:00
import { translate } from '../../base/i18n';
2017-08-15 22:39:42 +00:00
import { isButtonEnabled } from '../functions';
import StatelessToolbarButton from './StatelessToolbarButton';
2017-02-16 23:02:40 +00:00
declare var APP: Object;
/**
* Mapping of tooltip positions to equivalent {@code AKInlineDialog} positions.
*
* @private
*/
const TOOLTIP_TO_POPUP_POSITION = {
bottom: 'bottom center',
left: 'left middle',
top: 'top center',
right: 'right middle'
};
2017-02-16 23:02:40 +00:00
/**
* Represents a button in Toolbar on React.
*
* @class ToolbarButton
* @extends AbstractToolbarButton
*/
class ToolbarButton extends Component {
button: Object;
2017-02-16 23:02:40 +00:00
2017-08-15 22:39:42 +00:00
_onClick: Function;
_onMouseOut: Function;
_onMouseOver: Function;
state: {
/**
* Whether or not the tooltip for the button should be displayed.
*
* @type {boolean}
*/
showTooltip: boolean
}
2017-02-16 23:02:40 +00:00
/**
* Toolbar button component's property types.
*
* @static
*/
static propTypes = {
...StatelessToolbarButton.propTypes,
2017-02-16 23:02:40 +00:00
/**
* Object describing button.
*/
button: PropTypes.object.isRequired,
2017-02-16 23:02:40 +00:00
/**
* Handler for component mount.
*/
onMount: PropTypes.func,
2017-02-16 23:02:40 +00:00
/**
* Handler for component unmount.
*/
onUnmount: PropTypes.func,
2017-02-16 23:02:40 +00:00
/**
* Translation helper function.
*/
t: PropTypes.func,
2017-04-06 22:40:10 +00:00
/**
* Indicates the position of the tooltip.
*/
tooltipPosition: PropTypes.oneOf([ 'bottom', 'left', 'right', 'top' ])
2017-02-16 23:02:40 +00:00
};
/**
* Initializes new ToolbarButton instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props: Object) {
super(props);
2017-08-15 22:39:42 +00:00
this.state = {
showTooltip: false
};
2017-02-16 23:02:40 +00:00
// Bind methods to save the context
2017-08-15 22:39:42 +00:00
this._onClick = this._onClick.bind(this);
this._onMouseOut = this._onMouseOut.bind(this);
this._onMouseOver = this._onMouseOver.bind(this);
2017-02-16 23:02:40 +00:00
}
/**
* Sets shortcut/tooltip
* after mounting of the component.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount(): void {
2017-08-15 22:39:42 +00:00
this._setShortcut();
2017-02-16 23:02:40 +00:00
if (this.props.onMount) {
this.props.onMount();
}
}
/**
* Invokes on unmount handler if it was passed to the props.
*
* @inheritdoc
* @returns {void}
*/
componentWillUnmount(): void {
if (this.props.onUnmount) {
this.props.onUnmount();
}
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render(): ReactElement<*> {
2017-08-15 22:39:42 +00:00
const { button, t, tooltipPosition } = this.props;
const props = {
...this.props,
2017-09-22 22:02:34 +00:00
onClick: this._onClick
};
const buttonComponent = ( // eslint-disable-line no-extra-parens
2017-08-15 22:39:42 +00:00
<Tooltip
description = { button.tooltipText || t(button.tooltipKey) }
onMouseOut = { this._onMouseOut }
onMouseOver = { this._onMouseOver }
position = { tooltipPosition }
visible = { this.state.showTooltip }>
2017-09-22 22:02:34 +00:00
<StatelessToolbarButton { ...props }>
{ this.props.children }
</StatelessToolbarButton>
2017-08-15 22:39:42 +00:00
</Tooltip>
2017-02-16 23:02:40 +00:00
);
let children = buttonComponent;
const popupConfig = this._getPopupDisplayConfiguration();
if (popupConfig) {
const { dataAttr, dataInterpolate, position } = popupConfig;
children = ( // eslint-disable-line no-extra-parens
<AKInlineDialog
content = { t(dataAttr, dataInterpolate) }
isOpen = { Boolean(popupConfig) }
position = { position }>
{ buttonComponent }
</AKInlineDialog>
);
}
return (
<div className = { `toolbar-button-wrapper ${button.id}-wrapper` }>
{ children }
</div>
);
2017-02-16 23:02:40 +00:00
}
2017-08-15 22:39:42 +00:00
/**
* Wrapper on on click handler props for current button.
*
* @param {Event} event - Click event object.
* @returns {void}
* @private
*/
_onClick(event) {
this.props.onClick(event);
this.setState({ showTooltip: false });
}
2017-02-16 23:02:40 +00:00
/**
* Parses the props and state to find any popup that should be displayed
* and returns an object describing how the popup should display.
2017-02-16 23:02:40 +00:00
*
* @private
* @returns {Object|null}
2017-02-16 23:02:40 +00:00
*/
_getPopupDisplayConfiguration() {
const { button, tooltipPosition } = this.props;
const { popups, popupDisplay } = button;
if (!popups || !popupDisplay) {
return null;
2017-02-16 23:02:40 +00:00
}
const { popupID } = popupDisplay;
const currentPopup = popups.find(popup => popup.id === popupID);
return Object.assign(
{},
currentPopup || {},
{
position: TOOLTIP_TO_POPUP_POSITION[tooltipPosition]
});
2017-02-16 23:02:40 +00:00
}
2017-08-15 22:39:42 +00:00
/**
* Hides any displayed tooltip.
*
* @private
* @returns {void}
*/
_onMouseOut(): void {
this.setState({ showTooltip: false });
}
/**
* Hides any displayed tooltip.
*
* @private
* @returns {void}
*/
_onMouseOver(): void {
const { button } = this.props;
this.setState({
showTooltip: isButtonEnabled(button.buttonName)
&& !button.unclickable
});
}
2017-02-16 23:02:40 +00:00
/**
* Sets shortcut and tooltip for current toolbar button.
*
* @private
* @returns {void}
*/
2017-08-15 22:39:42 +00:00
_setShortcut(): void {
const { button } = this.props;
if (button.shortcut && APP && APP.keyboardshortcut) {
APP.keyboardshortcut.registerShortcut(
button.shortcut,
button.shortcutAttr,
button.shortcutFunc,
button.shortcutDescription
);
}
2017-02-16 23:02:40 +00:00
}
}
2017-07-26 20:47:53 +00:00
export default translate(ToolbarButton);