UNPKG

d2-ui

Version:
141 lines (115 loc) 3.37 kB
import React from 'react'; import ReactDOM from 'react-dom'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import StylePropable from '../mixins/style-propable'; import autoPrefix from '../styles/auto-prefix'; import Colors from '../styles/colors'; import Transitions from '../styles/transitions'; import ScaleInTransitionGroup from '../transition-groups/scale-in'; const pulsateDuration = 750; const FocusRipple = React.createClass({ propTypes: { color: React.PropTypes.string, innerStyle: React.PropTypes.object, /** * The material-ui theme applied to this component. */ muiTheme: React.PropTypes.object.isRequired, opacity: React.PropTypes.number, show: React.PropTypes.bool, /** * Override the inline-styles of the root element. */ style: React.PropTypes.object, }, mixins: [ PureRenderMixin, StylePropable, ], getDefaultProps() { return { color: Colors.darkBlack, }; }, componentDidMount() { if (this.props.show) { this._setRippleSize(); this._pulsate(); } }, componentDidUpdate() { if (this.props.show) { this._setRippleSize(); this._pulsate(); } else { if (this._timeout) clearTimeout(this._timeout); } }, _getRippleElement(props) { const { color, innerStyle, opacity, } = props; const innerStyles = this.mergeStyles({ position: 'absolute', height: '100%', width: '100%', borderRadius: '50%', opacity: opacity ? opacity : 0.16, backgroundColor: color, transition: Transitions.easeOut(pulsateDuration + 'ms', 'transform', null, Transitions.easeInOutFunction), }, innerStyle); return <div ref="innerCircle" style={this.prepareStyles(innerStyles)} />; }, _pulsate() { if (!this.isMounted()) return; let innerCircle = ReactDOM.findDOMNode(this.refs.innerCircle); if (!innerCircle) return; const startScale = 'scale(1)'; const endScale = 'scale(0.85)'; let currentScale = innerCircle.style.transform; let nextScale; currentScale = currentScale || startScale; nextScale = currentScale === startScale ? endScale : startScale; autoPrefix.set(innerCircle.style, 'transform', nextScale, this.props.muiTheme); this._timeout = setTimeout(this._pulsate, pulsateDuration); }, _setRippleSize() { let el = ReactDOM.findDOMNode(this.refs.innerCircle); const height = el.offsetHeight; const width = el.offsetWidth; const size = Math.max(height, width); let oldTop = 0; // For browsers that don't support endsWith() if (el.style.top.indexOf('px', el.style.top.length - 2) !== -1) { oldTop = parseInt(el.style.top); } el.style.height = size + 'px'; el.style.top = (height / 2) - (size / 2 ) + oldTop + 'px'; }, render() { const { show, style, } = this.props; const mergedRootStyles = this.mergeStyles({ height: '100%', width: '100%', position: 'absolute', top: 0, left: 0, }, style); const ripple = show ? this._getRippleElement(this.props) : null; return ( <ScaleInTransitionGroup maxScale={0.85} style={mergedRootStyles} > {ripple} </ScaleInTransitionGroup> ); }, }); export default FocusRipple;