@nahanil/react-show
Version:
react-show React component
582 lines (488 loc) • 19 kB
JavaScript
;
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
// }