You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ToolbarButtonWithDialog.web.js 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import InlineDialog from '@atlaskit/inline-dialog';
  2. import PropTypes from 'prop-types';
  3. import React, { Component } from 'react';
  4. import { connect } from 'react-redux';
  5. import ToolbarButton from './ToolbarButton';
  6. /**
  7. * Maps AtlasKit {@code Tooltip} positions to equivalent {@code InlineDialog}
  8. * positions. The {@code InlineDialog} will appear from the the same side of
  9. * the button as the tooltip.
  10. *
  11. */
  12. const TOOLTIP_TO_DIALOG_POSITION = {
  13. bottom: 'bottom center',
  14. left: 'left middle',
  15. right: 'right middle',
  16. top: 'top center'
  17. };
  18. /**
  19. * React {@code Component} for displaying a button which will open an inline
  20. * dialog.
  21. *
  22. * @extends Component
  23. */
  24. class ToolbarButtonWithDialog extends Component {
  25. /**
  26. * {@code ToolbarButtonWithDialog}'s property types.
  27. *
  28. * @static
  29. */
  30. static propTypes = {
  31. /**
  32. * Whether or not the button is visible, based on the visibility of the
  33. * toolbar. Used to automatically hide {@code InlineDialog} if not
  34. * visible.
  35. */
  36. _visible: PropTypes.bool,
  37. /**
  38. * A configuration object to describe how {@code ToolbarButton} should
  39. * render.
  40. *
  41. */
  42. button: PropTypes.object,
  43. /**
  44. * The React Component to show within {@code InlineDialog}.
  45. */
  46. content: PropTypes.object,
  47. /**
  48. * From which side tooltips should display. Will be re-used for
  49. * displaying the inline dialog for video quality adjustment.
  50. */
  51. tooltipPosition: PropTypes.string
  52. };
  53. /**
  54. * Initializes new {@code ToolbarButtonWithDialog} instance.
  55. *
  56. * @param {Object} props - The read-only properties with which the new
  57. * instance is to be initialized.
  58. */
  59. constructor(props) {
  60. super(props);
  61. this.state = {
  62. /**
  63. * Whether or not the inline dialog should be displayed.
  64. */
  65. showDialog: false
  66. };
  67. // Bind event handlers so they are only bound once for every instance.
  68. this._onDialogClose = this._onDialogClose.bind(this);
  69. this._onDialogToggle = this._onDialogToggle.bind(this);
  70. }
  71. /**
  72. * Automatically close the inline dialog if the button will not be visible.
  73. *
  74. * @inheritdoc
  75. * @returns {void}
  76. */
  77. componentWillReceiveProps(nextProps) {
  78. if (!nextProps._visible) {
  79. this._onDialogClose();
  80. }
  81. }
  82. /**
  83. * Implements React's {@link Component#render()}.
  84. *
  85. * @inheritdoc
  86. * @returns {ReactElement}
  87. */
  88. render() {
  89. const { _visible, content, tooltipPosition } = this.props;
  90. const buttonConfiguration = {
  91. ...this.props.button,
  92. classNames: [
  93. ...this.props.button.classNames,
  94. this.state.showDialog ? 'toggled button-active' : ''
  95. ]
  96. };
  97. const Content = content;
  98. return (
  99. <InlineDialog
  100. content = { <Content onClose = { this._onDialogClose } /> }
  101. isOpen = { _visible && this.state.showDialog }
  102. onClose = { this._onDialogClose }
  103. position = { TOOLTIP_TO_DIALOG_POSITION[tooltipPosition] }>
  104. <ToolbarButton
  105. button = { buttonConfiguration }
  106. onClick = { this._onDialogToggle }
  107. tooltipPosition = { tooltipPosition } />
  108. </InlineDialog>
  109. );
  110. }
  111. /**
  112. * Hides the attached inline dialog.
  113. *
  114. * @private
  115. * @returns {void}
  116. */
  117. _onDialogClose() {
  118. this.setState({ showDialog: false });
  119. }
  120. /**
  121. * Toggles the display of the dialog.
  122. *
  123. * @private
  124. * @returns {void}
  125. */
  126. _onDialogToggle() {
  127. this.setState({
  128. showDialog: !this.state.showDialog
  129. });
  130. }
  131. }
  132. /**
  133. * Maps (parts of) the Redux state to the associated
  134. * {@code ToolbarButtonWithDialog} component's props.
  135. *
  136. * @param {Object} state - The Redux state.
  137. * @private
  138. * @returns {{
  139. * _visible: boolean
  140. * }}
  141. */
  142. function _mapStateToProps(state) {
  143. return {
  144. _visible: state['features/toolbox'].visible
  145. };
  146. }
  147. export default connect(_mapStateToProps)(ToolbarButtonWithDialog);