您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ToolbarButton.web.js 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /* @flow */
  2. import { Tooltip } from '@atlaskit/tooltip';
  3. import React, { Component } from 'react';
  4. import { translate } from '../../base/i18n';
  5. import { isButtonEnabled } from '../functions';
  6. import StatelessToolbarButton from './StatelessToolbarButton';
  7. declare var APP: Object;
  8. /**
  9. * Represents a button in Toolbar on React.
  10. *
  11. * @class ToolbarButton
  12. * @extends AbstractToolbarButton
  13. */
  14. class ToolbarButton extends Component {
  15. button: Object;
  16. _createRefToButton: Function;
  17. _onClick: Function;
  18. _onMouseOut: Function;
  19. _onMouseOver: Function;
  20. state: {
  21. /**
  22. * Whether or not the tooltip for the button should be displayed.
  23. *
  24. * @type {boolean}
  25. */
  26. showTooltip: boolean
  27. }
  28. /**
  29. * Toolbar button component's property types.
  30. *
  31. * @static
  32. */
  33. static propTypes = {
  34. ...StatelessToolbarButton.propTypes,
  35. /**
  36. * Object describing button.
  37. */
  38. button: React.PropTypes.object.isRequired,
  39. /**
  40. * Handler for component mount.
  41. */
  42. onMount: React.PropTypes.func,
  43. /**
  44. * Handler for component unmount.
  45. */
  46. onUnmount: React.PropTypes.func,
  47. /**
  48. * Translation helper function.
  49. */
  50. t: React.PropTypes.func,
  51. /**
  52. * Indicates the position of the tooltip.
  53. */
  54. tooltipPosition:
  55. React.PropTypes.oneOf([ 'bottom', 'left', 'right', 'top' ])
  56. };
  57. /**
  58. * Initializes new ToolbarButton instance.
  59. *
  60. * @param {Object} props - The read-only properties with which the new
  61. * instance is to be initialized.
  62. */
  63. constructor(props: Object) {
  64. super(props);
  65. this.state = {
  66. showTooltip: false
  67. };
  68. // Bind methods to save the context
  69. this._createRefToButton = this._createRefToButton.bind(this);
  70. this._onClick = this._onClick.bind(this);
  71. this._onMouseOut = this._onMouseOut.bind(this);
  72. this._onMouseOver = this._onMouseOver.bind(this);
  73. }
  74. /**
  75. * Sets shortcut/tooltip
  76. * after mounting of the component.
  77. *
  78. * @inheritdoc
  79. * @returns {void}
  80. */
  81. componentDidMount(): void {
  82. this._setShortcut();
  83. if (this.props.onMount) {
  84. this.props.onMount();
  85. }
  86. }
  87. /**
  88. * Invokes on unmount handler if it was passed to the props.
  89. *
  90. * @inheritdoc
  91. * @returns {void}
  92. */
  93. componentWillUnmount(): void {
  94. if (this.props.onUnmount) {
  95. this.props.onUnmount();
  96. }
  97. }
  98. /**
  99. * Implements React's {@link Component#render()}.
  100. *
  101. * @inheritdoc
  102. * @returns {ReactElement}
  103. */
  104. render(): ReactElement<*> {
  105. const { button, t, tooltipPosition } = this.props;
  106. const popups = button.popups || [];
  107. const props = {
  108. ...this.props,
  109. onClick: this._onClick,
  110. createRefToButton: this._createRefToButton
  111. };
  112. return (
  113. <Tooltip
  114. description = { button.tooltipText || t(button.tooltipKey) }
  115. onMouseOut = { this._onMouseOut }
  116. onMouseOver = { this._onMouseOver }
  117. position = { tooltipPosition }
  118. visible = { this.state.showTooltip }>
  119. <StatelessToolbarButton { ...props }>
  120. { this._renderPopups(popups) }
  121. </StatelessToolbarButton>
  122. </Tooltip>
  123. );
  124. }
  125. /**
  126. * Wrapper on on click handler props for current button.
  127. *
  128. * @param {Event} event - Click event object.
  129. * @returns {void}
  130. * @private
  131. */
  132. _onClick(event) {
  133. this.props.onClick(event);
  134. this.setState({ showTooltip: false });
  135. }
  136. /**
  137. * Creates reference to current toolbar button.
  138. *
  139. * @param {HTMLElement} element - HTMLElement representing the toolbar
  140. * button.
  141. * @returns {void}
  142. * @private
  143. */
  144. _createRefToButton(element: HTMLElement): void {
  145. this.button = element;
  146. }
  147. /**
  148. * If toolbar button should contain children elements
  149. * renders them.
  150. *
  151. * @returns {ReactElement|null}
  152. * @private
  153. */
  154. _renderInnerElementsIfRequired(): ReactElement<*> | null {
  155. if (this.props.button.html) {
  156. return this.props.button.html;
  157. }
  158. return null;
  159. }
  160. /**
  161. * Renders popup element for toolbar button.
  162. *
  163. * @param {Array} popups - Array of popup objects.
  164. * @returns {Array}
  165. * @private
  166. */
  167. _renderPopups(popups: Array<*> = []): Array<*> {
  168. return popups.map(popup => {
  169. let gravity = 'n';
  170. if (popup.dataAttrPosition) {
  171. gravity = popup.dataAttrPosition;
  172. }
  173. const title = this.props.t(popup.dataAttr, popup.dataInterpolate);
  174. return (
  175. <div
  176. className = { popup.className }
  177. data-popup = { gravity }
  178. id = { popup.id }
  179. key = { popup.id }
  180. title = { title } />
  181. );
  182. });
  183. }
  184. /**
  185. * Hides any displayed tooltip.
  186. *
  187. * @private
  188. * @returns {void}
  189. */
  190. _onMouseOut(): void {
  191. this.setState({ showTooltip: false });
  192. }
  193. /**
  194. * Hides any displayed tooltip.
  195. *
  196. * @private
  197. * @returns {void}
  198. */
  199. _onMouseOver(): void {
  200. const { button } = this.props;
  201. this.setState({
  202. showTooltip: isButtonEnabled(button.buttonName)
  203. && !button.unclickable
  204. });
  205. }
  206. /**
  207. * Sets shortcut and tooltip for current toolbar button.
  208. *
  209. * @private
  210. * @returns {void}
  211. */
  212. _setShortcut(): void {
  213. const { button } = this.props;
  214. if (button.shortcut && APP && APP.keyboardshortcut) {
  215. APP.keyboardshortcut.registerShortcut(
  216. button.shortcut,
  217. button.shortcutAttr,
  218. button.shortcutFunc,
  219. button.shortcutDescription
  220. );
  221. }
  222. }
  223. }
  224. export default translate(ToolbarButton);