react-view-router
Version:
react-view-router
361 lines (358 loc) • 14.7 kB
JavaScript
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
var _excluded = ["classNames", "children"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import "core-js/modules/es6.regexp.split.js";
import "core-js/modules/es6.symbol.js";
import "core-js/modules/es6.array.filter.js";
import "core-js/modules/es7.object.get-own-property-descriptors.js";
import React from 'react';
import PropTypes from 'prop-types';
import addOneClass from 'dom-helpers/addClass';
import removeOneClass from 'dom-helpers/removeClass';
import { classNamesShape } from 'react-transition-group/esm/utils/PropTypes';
import Transition from './Transition';
var addClass = (node, classes) => node && classes && classes.split(' ').forEach(c => addOneClass(node, c));
var removeClass = (node, classes) => node && classes && classes.split(' ').forEach(c => removeOneClass(node, c));
/**
* A transition component inspired by the excellent
* [ng-animate](https://docs.angularjs.org/api/ngAnimate) library, you should
* use it if you're using CSS transitions or animations. It's built upon the
* [`Transition`](https://reactcommunity.org/react-transition-group/transition)
* component, so it inherits all of its props.
*
* `CSSTransition` applies a pair of class names during the `appear`, `enter`,
* and `exit` states of the transition. The first class is applied and then a
* second `*-active` class in order to activate the CSS transition. After the
* transition, matching `*-done` class names are applied to persist the
* transition state.
*
* ```jsx
* function App() {
* const [inProp, setInProp] = useState(false);
* return (
* <div>
* <CSSTransition in={inProp} timeout={200} classNames="my-node">
* <div>
* {"I'll receive my-node-* classes"}
* </div>
* </CSSTransition>
* <button type="button" onClick={() => setInProp(true)}>
* Click to Enter
* </button>
* </div>
* );
* }
* ```
*
* When the `in` prop is set to `true`, the child component will first receive
* the class `example-enter`, then the `example-enter-active` will be added in
* the next tick. `CSSTransition` [forces a
* reflow](https://github.com/reactjs/react-transition-group/blob/5007303e729a74be66a21c3e2205e4916821524b/src/CSSTransition.js#L208-L215)
* between before adding the `example-enter-active`. This is an important trick
* because it allows us to transition between `example-enter` and
* `example-enter-active` even though they were added immediately one after
* another. Most notably, this is what makes it possible for us to animate
* _appearance_.
*
* ```css
* .my-node-enter {
* opacity: 0;
* }
* .my-node-enter-active {
* opacity: 1;
* transition: opacity 200ms;
* }
* .my-node-exit {
* opacity: 1;
* }
* .my-node-exit-active {
* opacity: 0;
* transition: opacity 200ms;
* }
* ```
*
* `*-active` classes represent which styles you want to animate **to**, so it's
* important to add `transition` declaration only to them, otherwise transitions
* might not behave as intended! This might not be obvious when the transitions
* are symmetrical, i.e. when `*-enter-active` is the same as `*-exit`, like in
* the example above (minus `transition`), but it becomes apparent in more
* complex transitions.
*
* **Note**: If you're using the
* [`appear`](http://reactcommunity.org/react-transition-group/transition#Transition-prop-appear)
* prop, make sure to define styles for `.appear-*` classes as well.
*/
class CSSTransition extends React.Component {
constructor(...args) {
super(...args);
_defineProperty(this, "appliedClasses", {
appear: {},
enter: {},
exit: {}
});
_defineProperty(this, "onEnter", (maybeNode, maybeAppearing) => {
var _this$resolveArgument = this.resolveArguments(maybeNode, maybeAppearing),
_this$resolveArgument2 = _slicedToArray(_this$resolveArgument, 2),
node = _this$resolveArgument2[0],
appearing = _this$resolveArgument2[1];
this.removeClasses(node, 'exit');
this.addClass(node, appearing ? 'appear' : 'enter', 'base');
if (this.props.onEnter) {
this.props.onEnter(maybeNode, maybeAppearing);
}
});
_defineProperty(this, "onEntering", (maybeNode, maybeAppearing) => {
var _this$resolveArgument3 = this.resolveArguments(maybeNode, maybeAppearing),
_this$resolveArgument4 = _slicedToArray(_this$resolveArgument3, 2),
node = _this$resolveArgument4[0],
appearing = _this$resolveArgument4[1];
var type = appearing ? 'appear' : 'enter';
this.addClass(node, type, 'active');
if (this.props.onEntering) {
this.props.onEntering(maybeNode, maybeAppearing);
}
});
_defineProperty(this, "onEntered", (maybeNode, maybeAppearing) => {
var _this$resolveArgument5 = this.resolveArguments(maybeNode, maybeAppearing),
_this$resolveArgument6 = _slicedToArray(_this$resolveArgument5, 2),
node = _this$resolveArgument6[0],
appearing = _this$resolveArgument6[1];
var type = appearing ? 'appear' : 'enter';
this.removeClasses(node, type);
this.addClass(node, type, 'done');
if (this.props.onEntered) {
this.props.onEntered(maybeNode, maybeAppearing);
}
});
_defineProperty(this, "onExit", maybeNode => {
var _this$resolveArgument7 = this.resolveArguments(maybeNode),
_this$resolveArgument8 = _slicedToArray(_this$resolveArgument7, 1),
node = _this$resolveArgument8[0];
this.removeClasses(node, 'appear');
this.removeClasses(node, 'enter');
this.addClass(node, 'exit', 'base');
if (this.props.onExit) {
this.props.onExit(maybeNode);
}
});
_defineProperty(this, "onExiting", maybeNode => {
var _this$resolveArgument9 = this.resolveArguments(maybeNode),
_this$resolveArgument0 = _slicedToArray(_this$resolveArgument9, 1),
node = _this$resolveArgument0[0];
this.addClass(node, 'exit', 'active');
if (this.props.onExiting) {
this.props.onExiting(maybeNode);
}
});
_defineProperty(this, "onExited", maybeNode => {
var _this$resolveArgument1 = this.resolveArguments(maybeNode),
_this$resolveArgument10 = _slicedToArray(_this$resolveArgument1, 1),
node = _this$resolveArgument10[0];
this.removeClasses(node, 'exit');
this.addClass(node, 'exit', 'done');
if (this.props.onExited) {
this.props.onExited(maybeNode);
}
});
// when prop `nodeRef` is provided `node` is excluded
_defineProperty(this, "resolveArguments", (maybeNode, maybeAppearing) => this.props.nodeRef ? [this.props.nodeRef.current, maybeNode] // here `maybeNode` is actually `appearing`
: [maybeNode, maybeAppearing]);
// `findDOMNode` was used
_defineProperty(this, "getClassNames", type => {
var classNames = this.props.classNames;
if (typeof classNames === 'function') classNames = classNames(this.props);
var isStringClassNames = typeof classNames === 'string';
var prefix = isStringClassNames && classNames ? `${classNames}-` : '';
var baseClassName = isStringClassNames ? `${prefix}${type}` : classNames[type];
var activeClassName = isStringClassNames ? `${baseClassName}-active` : classNames[`${type}Active`];
var doneClassName = isStringClassNames ? `${baseClassName}-done` : classNames[`${type}Done`];
return {
baseClassName,
activeClassName,
doneClassName
};
});
}
addClass(node, type, phase) {
var classNames = this.props.classNames;
var className = classNames && this.getClassNames(type)[`${phase}ClassName`] || '';
var _ref = classNames ? this.getClassNames('enter') : {},
doneClassName = _ref.doneClassName;
if (type === 'appear' && phase === 'done' && doneClassName) {
className += ` ${doneClassName}`;
}
// This is to force a repaint,
// which is necessary in order to transition styles when adding a class name.
if (phase === 'active') {
/* eslint-disable no-unused-expressions */
node && node.scrollTop;
}
if (className) {
this.appliedClasses[type][phase] = className;
addClass(node, className);
}
}
removeClasses(node, type) {
var _this$appliedClasses$ = this.appliedClasses[type],
baseClassName = _this$appliedClasses$.base,
activeClassName = _this$appliedClasses$.active,
doneClassName = _this$appliedClasses$.done;
this.appliedClasses[type] = {};
if (baseClassName) {
removeClass(node, baseClassName);
}
if (activeClassName) {
removeClass(node, activeClassName);
}
if (doneClassName) {
removeClass(node, doneClassName);
}
}
render() {
// eslint-disable-next-line no-unused-vars
var _this$props = this.props,
_ = _this$props.classNames,
children = _this$props.children,
props = _objectWithoutProperties(_this$props, _excluded);
return /*#__PURE__*/React.createElement(Transition, _objectSpread(_objectSpread({}, props), {}, {
onEnter: this.onEnter,
onEntered: this.onEntered,
onEntering: this.onEntering,
onExit: this.onExit,
onExiting: this.onExiting,
onExited: this.onExited
}), children);
}
}
// eslint-disable-next-line react/static-property-placement
_defineProperty(CSSTransition, "defaultProps", {
classNames: ''
});
CSSTransition.propTypes = _objectSpread(_objectSpread({}, Transition.propTypes), {}, {
/**
* The animation classNames applied to the component as it appears, enters,
* exits or has finished the transition. A single name can be provided, which
* will be suffixed for each stage, e.g. `classNames="fade"` applies:
*
* - `fade-appear`, `fade-appear-active`, `fade-appear-done`
* - `fade-enter`, `fade-enter-active`, `fade-enter-done`
* - `fade-exit`, `fade-exit-active`, `fade-exit-done`
*
* A few details to note about how these classes are applied:
*
* 1. They are _joined_ with the ones that are already defined on the child
* component, so if you want to add some base styles, you can use
* `className` without worrying that it will be overridden.
*
* 2. If the transition component mounts with `in={false}`, no classes are
* applied yet. You might be expecting `*-exit-done`, but if you think
* about it, a component cannot finish exiting if it hasn't entered yet.
*
* 2. `fade-appear-done` and `fade-enter-done` will _both_ be applied. This
* allows you to define different behavior for when appearing is done and
* when regular entering is done, using selectors like
* `.fade-enter-done:not(.fade-appear-done)`. For example, you could apply
* an epic entrance animation when element first appears in the DOM using
* [Animate.css](https://daneden.github.io/animate.css/). Otherwise you can
* simply use `fade-enter-done` for defining both cases.
*
* Each individual classNames can also be specified independently like:
*
* ```js
* classNames={{
* appear: 'my-appear',
* appearActive: 'my-active-appear',
* appearDone: 'my-done-appear',
* enter: 'my-enter',
* enterActive: 'my-active-enter',
* enterDone: 'my-done-enter',
* exit: 'my-exit',
* exitActive: 'my-active-exit',
* exitDone: 'my-done-exit',
* }}
* ```
*
* If you want to set these classes using CSS Modules:
*
* ```js
* import styles from './styles.css';
* ```
*
* you might want to use camelCase in your CSS file, that way could simply
* spread them instead of listing them one by one:
*
* ```js
* classNames={{ ...styles }}
* ```
*
* @type {string | {
* appear?: string,
* appearActive?: string,
* appearDone?: string,
* enter?: string,
* enterActive?: string,
* enterDone?: string,
* exit?: string,
* exitActive?: string,
* exitDone?: string,
* }}
*/
classNames: PropTypes.oneOfType([PropTypes.func, classNamesShape]),
/**
* A `<Transition>` callback fired immediately after the 'enter' or 'appear' class is
* applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEnter: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'enter-active' or
* 'appear-active' class is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEntering: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'enter' or
* 'appear' classes are **removed** and the `done` class is added to the DOM node.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed.
*
* @type Function(node: HtmlElement, isAppearing: bool)
*/
onEntered: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'exit' class is
* applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement)
*/
onExit: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'exit-active' is applied.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement)
*/
onExiting: PropTypes.func,
/**
* A `<Transition>` callback fired immediately after the 'exit' classes
* are **removed** and the `exit-done` class is added to the DOM node.
*
* **Note**: when `nodeRef` prop is passed, `node` is not passed
*
* @type Function(node: HtmlElement)
*/
onExited: PropTypes.func
});
export default CSSTransition;