UNPKG

@nahanil/react-show

Version:
582 lines (488 loc) 19 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.Animate = exports.easings = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _raf = require('raf'); var _raf2 = _interopRequireDefault(_raf); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* eslint-disable no-restricted-syntax, react/forbid-prop-types */ var easings = exports.easings = { // Cubic easeInCubic: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)', easeOutCubic: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)', easeInOutCubic: 'cubic-bezier(0.645, 0.045, 0.355, 1.000)', // Circ easeInCirc: 'cubic-bezier(0.600, 0.040, 0.980, 0.335)', easeOutCirc: 'cubic-bezier(0.075, 0.820, 0.165, 1.000)', easeInOutCirc: 'cubic-bezier(0.785, 0.135, 0.150, 0.860)', // Expo easeInExpo: 'cubic-bezier(0.950, 0.050, 0.795, 0.035)', easeOutExpo: 'cubic-bezier(0.190, 1.000, 0.220, 1.000)', easeInOutExpo: 'cubic-bezier(1.000, 0.000, 0.000, 1.000)', // Quad easeInQuad: 'cubic-bezier(0.550, 0.085, 0.680, 0.530)', easeOutQuad: 'cubic-bezier(0.250, 0.460, 0.450, 0.940)', easeInOutQuad: 'cubic-bezier(0.455, 0.030, 0.515, 0.955)', // Quart easeInQuart: 'cubic-bezier(0.895, 0.030, 0.685, 0.220)', easeOutQuart: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)', easeInOutQuart: 'cubic-bezier(0.770, 0.000, 0.175, 1.000)', // Quint easeInQuint: 'cubic-bezier(0.755, 0.050, 0.855, 0.060)', easeOutQuint: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)', easeInOutQuint: 'cubic-bezier(0.860, 0.000, 0.070, 1.000)', // Sine easeInSine: 'cubic-bezier(0.470, 0.000, 0.745, 0.715)', easeOutSine: 'cubic-bezier(0.390, 0.575, 0.565, 1.000)', easeInOutSine: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)', // Back easeInBack: 'cubic-bezier(0.600, -0.280, 0.735, 0.045)', easeOutBack: 'cubic-bezier(0.175, 0.885, 0.320, 1.275)', easeInOutBack: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)' }; var Animate = exports.Animate = function (_React$Component) { _inherits(Animate, _React$Component); function Animate(props) { _classCallCheck(this, Animate); var _this = _possibleConstructorReturn(this, (Animate.__proto__ || Object.getPrototypeOf(Animate)).call(this, props)); _initialiseProps.call(_this); var _this$props = _this.props, show = _this$props.show, preMount = _this$props.preMount, transitionOnMount = _this$props.transitionOnMount, start = _this$props.start, enter = _this$props.enter; _this.stage = false; _this.stageStyles = {}; _this.transitioning = false; _this.state = { mountContent: preMount || show, currentStyle: transitionOnMount ? start : enter, styleOverrides: {} }; return _this; } _createClass(Animate, [{ key: 'componentDidMount', value: function componentDidMount() { var _props = this.props, transitionOnMount = _props.transitionOnMount, show = _props.show, enter = _props.enter; if (transitionOnMount && show) { this.transition('enter', enter); } } }, { key: 'componentDidUpdate', value: function componentDidUpdate(oldProps) { var _props2 = this.props, show = _props2.show, enter = _props2.enter, leave = _props2.leave, start = _props2.start, stage = this.stage; if (show) { // Entering if (!oldProps.show) { if (stage === 'leave') { return this.transition('clean'); } if (enter) { return this.transition('enter', enter); } return this.transition('clean'); } // Did Enter if (stage === 'didEnter') { return this.transition('clean'); } } else if (oldProps.show) { // Leaving return this.transition('leave', leave || start); } } }, { key: 'render', value: function render() { var _this2 = this; var _props3 = this.props, Comp = _props3.component, children = _props3.children, originalShow = _props3.show, easing = _props3.easing, duration = _props3.duration, transitionProperty = _props3.transitionProperty, stayMounted = _props3.stayMounted, transitionOnMount = _props3.transitionOnMount, show = _props3.show, style = _props3.style, leave = _props3.leave, enter = _props3.enter, innerRef = _props3.innerRef, onFinish = _props3.onFinish, onMount = _props3.onMount, onWillUnmount = _props3.onWillUnmount, preMount = _props3.preMount, rest = _objectWithoutProperties(_props3, ['component', 'children', 'show', 'easing', 'duration', 'transitionProperty', 'stayMounted', 'transitionOnMount', 'show', 'style', 'leave', 'enter', 'innerRef', 'onFinish', 'onMount', 'onWillUnmount', 'preMount']); var _state = this.state, mountContent = _state.mountContent, currentStyle = _state.currentStyle, styleOverrides = _state.styleOverrides; return mountContent ? _react2.default.createElement( Comp, _extends({ ref: function ref(el) { _this2.handleRef(el); if (innerRef) { innerRef(el); } }, onTransitionEnd: this.transitionEnd, style: this.makeStyles(currentStyle, styleOverrides) }, rest), _react2.default.createElement( MountNotifier, { onMount: onMount, onWillUnmount: onWillUnmount }, children ) ) : null; } }]); return Animate; }(_react2.default.Component); Animate.easings = easings; Animate.propTypes = { component: _propTypes2.default.string, show: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.number]), easing: _propTypes2.default.string, duration: _propTypes2.default.number, preMount: _propTypes2.default.bool, transitionProperty: _propTypes2.default.string, stayMounted: _propTypes2.default.bool, style: _propTypes2.default.object, start: _propTypes2.default.object, enter: _propTypes2.default.object, leave: _propTypes2.default.object, onFinish: _propTypes2.default.func, onMount: _propTypes2.default.func, onWillUnmount: _propTypes2.default.func, transitionOnMount: _propTypes2.default.bool, children: _propTypes2.default.node.isRequired }; Animate.defaultProps = { component: 'div', show: true, easing: 'easeOutQuad', duration: 300, transitionProperty: 'all', preMount: false, stayMounted: true, transitionOnMount: false, style: undefined, start: undefined, enter: undefined, leave: undefined, onFinish: function onFinish() {}, onMount: function onMount() {}, onWillUnmount: function onWillUnmount() {} }; var _initialiseProps = function _initialiseProps() { var _this4 = this; this.ensureMounted = function () { return new Promise(function (resolve) { var check = function check() { if (_this4.el) { return resolve(); } (0, _raf2.default)(function () { _this4.setState({ mountContent: true }, check); }); }; check(); }); }; this.setCurrentStyle = function (style) { return _this4.setState({ currentStyle: style }); }; this.overrideStyle = function (style) { return new Promise(function (resolve) { var check = function check() { _this4.setState({ styleOverrides: style }, function () { (0, _raf2.default)(function () { if (Object.keys(style).some(function (key) { return !_this4.el || _this4.el.style[key] !== style[key]; })) { return check(); } resolve(); }); }); }; check(); }); }; this.transition = function (stage) { var styles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var show = _this4.props.show; _this4.stage = stage; _this4.stageStyles = styles; _this4.transitioning = true; var wasAutoWidth = void 0; var wasAutoHeight = void 0; var isAutoWidth = void 0; var isAutoHeight = void 0; var isAutoChanged = void 0; return Promise.resolve().then(function () { if (show) { return _this4.ensureMounted(); } }).then(function () { var _state2 = _this4.state, currentStyle = _state2.currentStyle, styleOverrides = _state2.styleOverrides; var previousStyle = _this4.makeStyles(currentStyle, styleOverrides); var nextStyle = _this4.makeStyles(styles); wasAutoWidth = _this4.isProp(previousStyle, 'width', 'auto') || _this4.isProp(previousStyle, 'width', undefined); wasAutoHeight = _this4.isProp(previousStyle, 'height', 'auto') || _this4.isProp(previousStyle, 'height', undefined); isAutoWidth = _this4.isProp(nextStyle, 'width', 'auto') || _this4.isProp(nextStyle, 'width', undefined); isAutoHeight = _this4.isProp(nextStyle, 'height', 'auto') || _this4.isProp(nextStyle, 'height', undefined); var isAutoWidthChanged = wasAutoWidth !== isAutoWidth; var isAutoHeightChanged = wasAutoHeight !== isAutoHeight; isAutoChanged = isAutoWidthChanged || isAutoHeightChanged; if (isAutoChanged) { // First we have to make sure we are measuring an // inline-block element that is overflow hidden, otherwise measurements // can get very inaccurate return _this4.overrideStyle({ display: 'block', overflow: 'hidden' }).then(function () { // Then we measure var measurements = _this4.measure(); // Make sure overflow is hidden while we animate return _this4.overrideStyle(_extends({}, isAutoWidthChanged ? { width: measurements.width + 'px' } : {}, isAutoHeightChanged ? { height: measurements.height + 'px' } : {})); }); } }).then(function () { (0, _raf2.default)(function () { _this4.setState(function (_ref2) { var styleOverrides = _ref2.styleOverrides; styleOverrides = isAutoChanged ? _extends({}, styleOverrides, wasAutoWidth ? { width: styles.width } : {}, wasAutoHeight ? { height: styles.height } : {}) : styleOverrides; return { mountContent: true, currentStyle: styles, styleOverrides: styleOverrides }; }, function () { // If no styles were applied, then we need to manually complete the transition // TODO: this might also need to be done if the transitionProperty doesn't // match any of the styles provided. // if (!styles) { // this.completeTransition(); // } }); }); }); }; this.transitionEnd = function (e) { if (e) { e.persist(); // Only handle transitionEnd for this element if (e.target !== _this4.el) { return; } } // We have to debounce the action of stopping // the "transition" state, since onTransitionEnd // will fire more than once if there are multiple // properties that were transitioned. if (_this4.transitionRAF) { _raf2.default.cancel(_this4.transitionRAF); } _this4.transitionRAF = (0, _raf2.default)(_this4.completeTransition); }; this.completeTransition = function () { var _props4 = _this4.props, stayMounted = _props4.stayMounted, onFinish = _props4.onFinish; var shouldHide = _this4.stage === 'leave'; _this4.transitioning = false; if (_this4.stage === 'enter') { _this4.stage = 'didEnter'; } else if (_this4.stage === 'mount') { _this4.stage = 'mounted'; } else { _this4.stage = false; } _this4.setState({ mountContent: !(shouldHide && !stayMounted), styleOverrides: {} // This is to make sure the auto/hidden overrides are gone }, onFinish); }; this.handleRef = function (el) { _this4.el = el; }; this.isProp = function (style, prop, value) { return style[prop] === value; }; this.measure = function () { if (!_this4.el) { return {}; } return { width: _this4.el.scrollWidth, height: _this4.el.scrollHeight }; }; this.makeStyles = function () { var currentStyle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var overrides = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var _props5 = _this4.props, style = _props5.style, transitionProperty = _props5.transitionProperty, duration = _props5.duration, easing = _props5.easing; var resolvedEasing = easings[easing] || easing || 'ease-out'; return _extends({ transitionProperty: transitionProperty, transitionDuration: duration + 'ms', transitionTimingFunction: '' + resolvedEasing }, style, currentStyle, overrides); }; }; var MountNotifier = function (_React$Component2) { _inherits(MountNotifier, _React$Component2); function MountNotifier() { var _ref; var _temp, _this3, _ret; _classCallCheck(this, MountNotifier); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this3 = _possibleConstructorReturn(this, (_ref = MountNotifier.__proto__ || Object.getPrototypeOf(MountNotifier)).call.apply(_ref, [this].concat(args))), _this3), _this3.componentDidMount = function () { _this3.props.onMount(); }, _this3.componentWillUnmount = function () { _this3.props.onWillUnmount(); }, _temp), _possibleConstructorReturn(_this3, _ret); } _createClass(MountNotifier, [{ key: 'render', value: function render() { return this.props.children; } }]); return MountNotifier; }(_react2.default.Component); // I'll let someone smarter than me figure out how to do this ;) // export class AnimateGroup extends React.Component { // constructor (props) { // super(props) // const { data } = props // this.nodes = this.makeNodes(data) // } // componentDidUpdate () { // const { data } = this.props // const newNodes = this.makeNodes(data) // let needsUpdate // if (newNodes.some(node => !this.nodes.find(d => d.key === node.key))) { // needsUpdate = 'diff' // } // if (needsUpdate) { // console.log(needsUpdate, newNodes, this.nodes) // this.nodes = this.updateNodes(newNodes) // this.forceUpdate() // } // } // makeNodes = data => { // const { getKey } = this.props // return data.map(datum => ({ // key: getKey(datum), // data: datum, // show: true, // })) // } // updateNodes = next => { // const nodes = [] // this.nodes.forEach(node => { // if (next.find(d => d.key === node.key)) { // return // } // exiting.push({ // ...node, // show: false, // }) // }) // return [...next, ...exiting] // } // removeNode = node => { // this.nodes = this.nodes.filter(d => d.key !== node.key) // this.forceUpdate() // } // render () { // const { // data, // getKey, // children, // render, // start, // enter, // update, // leave, // duration, // easing, // ...rest // } = this.props // return ( // <React.Fragment> // {this.nodes.map((node, i) => ( // <Animate // key={node.key} // show={node.show} // start={typeof start === 'function' ? start(node.data, node.key, i) : start} // enter={typeof enter === 'function' ? enter(node.data, node.key, i) : enter} // update={typeof update === 'function' ? update(node.data, node.key, i) : update} // leave={typeof leave === 'function' ? leave(node.data, node.key, i) : leave} // onFinish={() => { // if (!node.show) { // this.removeNode(node) // } // }} // {...rest} // > // {(render || children)(node.data)} // </Animate> // ))} // </React.Fragment> // ) // } // } // function mergeNodes (left, right) { // let nodes = [] // let lastRightIndex = 0 // left.forEach(l => { // const index = right.findIndex(r => r.key === l.key) // if (index === -1) { // return nodes.push(l) // } // nodes = [...nodes, ...right.slice(lastRightIndex, index)] // lastRightIndex = index // }) // return nodes // }