UNPKG

react-bootstrap

Version:

Bootstrap 3 components build with React

293 lines (233 loc) 8.16 kB
/*eslint-disable react/prop-types */ 'use strict'; var _extends = require('babel-runtime/helpers/extends')['default']; var _Object$keys = require('babel-runtime/core-js/object/keys')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; exports.__esModule = true; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _utilsCreateChainedFunction = require('./utils/createChainedFunction'); var _utilsCreateChainedFunction2 = _interopRequireDefault(_utilsCreateChainedFunction); var _utilsCreateContextWrapper = require('./utils/createContextWrapper'); var _utilsCreateContextWrapper2 = _interopRequireDefault(_utilsCreateContextWrapper); var _Overlay = require('./Overlay'); var _Overlay2 = _interopRequireDefault(_Overlay); var _reactLibWarning = require('react/lib/warning'); var _reactLibWarning2 = _interopRequireDefault(_reactLibWarning); var _lodashObjectPick = require('lodash/object/pick'); /** * Check if value one is inside or equal to the of value * * @param {string} one * @param {string|array} of * @returns {boolean} */ var _lodashObjectPick2 = _interopRequireDefault(_lodashObjectPick); function isOneOf(one, of) { if (Array.isArray(of)) { return of.indexOf(one) >= 0; } return one === of; } var OverlayTrigger = _react2['default'].createClass({ displayName: 'OverlayTrigger', propTypes: _extends({}, _Overlay2['default'].propTypes, { /** * Specify which action or actions trigger Overlay visibility */ trigger: _react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.oneOf(['click', 'hover', 'focus']), _react2['default'].PropTypes.arrayOf(_react2['default'].PropTypes.oneOf(['click', 'hover', 'focus']))]), /** * A millisecond delay amount to show and hide the Overlay once triggered */ delay: _react2['default'].PropTypes.number, /** * A millisecond delay amount before showing the Overlay once triggered. */ delayShow: _react2['default'].PropTypes.number, /** * A millisecond delay amount before hiding the Overlay once triggered. */ delayHide: _react2['default'].PropTypes.number, /** * The initial visibility state of the Overlay, for more nuanced visibility controll consider * using the Overlay component directly. */ defaultOverlayShown: _react2['default'].PropTypes.bool, /** * An element or text to overlay next to the target. */ overlay: _react2['default'].PropTypes.node.isRequired, /** * @private */ onBlur: _react2['default'].PropTypes.func, /** * @private */ onClick: _react2['default'].PropTypes.func, /** * @private */ onFocus: _react2['default'].PropTypes.func, /** * @private */ onMouseEnter: _react2['default'].PropTypes.func, /** * @private */ onMouseLeave: _react2['default'].PropTypes.func, //override specific overlay props /** * @private */ target: function target() {}, /** * @private */ onHide: function onHide() {}, /** * @private */ show: function show() {} }), getDefaultProps: function getDefaultProps() { return { trigger: ['hover', 'focus'] }; }, getInitialState: function getInitialState() { return { isOverlayShown: this.props.defaultOverlayShown == null ? false : this.props.defaultOverlayShown }; }, show: function show() { this.setState({ isOverlayShown: true }); }, hide: function hide() { this.setState({ isOverlayShown: false }); }, toggle: function toggle() { if (this.state.isOverlayShown) { this.hide(); } else { this.show(); } }, componentDidMount: function componentDidMount() { this._mountNode = document.createElement('div'); _react2['default'].render(this._overlay, this._mountNode); }, componentWillUnmount: function componentWillUnmount() { _react2['default'].unmountComponentAtNode(this._mountNode); this._mountNode = null; clearTimeout(this._hoverDelay); }, componentDidUpdate: function componentDidUpdate() { if (this._mountNode) { _react2['default'].render(this._overlay, this._mountNode); } }, getOverlayTarget: function getOverlayTarget() { return _react2['default'].findDOMNode(this); }, getOverlay: function getOverlay() { var overlayProps = _extends({}, _lodashObjectPick2['default'](this.props, _Object$keys(_Overlay2['default'].propTypes)), { show: this.state.isOverlayShown, onHide: this.hide, target: this.getOverlayTarget, onExit: this.props.onExit, onExiting: this.props.onExiting, onExited: this.props.onExited, onEnter: this.props.onEnter, onEntering: this.props.onEntering, onEntered: this.props.onEntered }); var overlay = _react.cloneElement(this.props.overlay, { placement: overlayProps.placement, container: overlayProps.container }); return _react2['default'].createElement( _Overlay2['default'], overlayProps, overlay ); }, render: function render() { var trigger = _react2['default'].Children.only(this.props.children); var props = { 'aria-describedby': this.props.overlay.props.id }; // create in render otherwise owner is lost... this._overlay = this.getOverlay(); props.onClick = _utilsCreateChainedFunction2['default'](trigger.props.onClick, this.props.onClick); if (isOneOf('click', this.props.trigger)) { props.onClick = _utilsCreateChainedFunction2['default'](this.toggle, props.onClick); } if (isOneOf('hover', this.props.trigger)) { _reactLibWarning2['default'](!(this.props.trigger === 'hover'), '[react-bootstrap] Specifying only the `"hover"` trigger limits the visibilty of the overlay to just mouse users. ' + 'Consider also including the `"focus"` trigger so that touch and keyboard only users can see the overlay as well.'); props.onMouseOver = _utilsCreateChainedFunction2['default'](this.handleDelayedShow, this.props.onMouseOver); props.onMouseOut = _utilsCreateChainedFunction2['default'](this.handleDelayedHide, this.props.onMouseOut); } if (isOneOf('focus', this.props.trigger)) { props.onFocus = _utilsCreateChainedFunction2['default'](this.handleDelayedShow, this.props.onFocus); props.onBlur = _utilsCreateChainedFunction2['default'](this.handleDelayedHide, this.props.onBlur); } return _react.cloneElement(trigger, props); }, handleDelayedShow: function handleDelayedShow() { var _this = this; if (this._hoverDelay != null) { clearTimeout(this._hoverDelay); this._hoverDelay = null; return; } var delay = this.props.delayShow != null ? this.props.delayShow : this.props.delay; if (!delay) { this.show(); return; } this._hoverDelay = setTimeout(function () { _this._hoverDelay = null; _this.show(); }, delay); }, handleDelayedHide: function handleDelayedHide() { var _this2 = this; if (this._hoverDelay != null) { clearTimeout(this._hoverDelay); this._hoverDelay = null; return; } var delay = this.props.delayHide != null ? this.props.delayHide : this.props.delay; if (!delay) { this.hide(); return; } this._hoverDelay = setTimeout(function () { _this2._hoverDelay = null; _this2.hide(); }, delay); } }); /** * Creates a new OverlayTrigger class that forwards the relevant context * * This static method should only be called at the module level, instead of in * e.g. a render() method, because it's expensive to create new classes. * * For example, you would want to have: * * > export default OverlayTrigger.withContext({ * > myContextKey: React.PropTypes.object * > }); * * and import this when needed. */ OverlayTrigger.withContext = _utilsCreateContextWrapper2['default'](OverlayTrigger, 'overlay'); exports['default'] = OverlayTrigger; module.exports = exports['default'];