react-native-web-headroom
Version:
React Native Web Headroom
252 lines (202 loc) • 9.56 kB
JavaScript
;
exports.__esModule = true;
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 _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _ChildMapping = require('./utils/ChildMapping');
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; }
var values = Object.values || function (obj) {
return Object.keys(obj).map(function (k) {
return obj[k];
});
};
var propTypes = {
/**
* `<TransitionGroup>` renders a `<div>` by default. You can change this
* behavior by providing a `component` prop.
* If you use React v16+ and would like to avoid a wrapping `<div>` element
* you can pass in `component={null}`. This is useful if the wrapping div
* borks your css styles.
*/
component: _propTypes2.default.any,
/**
* A set of `<Transition>` components, that are toggled `in` and out as they
* leave. the `<TransitionGroup>` will inject specific transition props, so
* remember to spread them through if you are wrapping the `<Transition>` as
* with our `<Fade>` example.
*/
children: _propTypes2.default.node,
/**
* A convenience prop that enables or disables appear animations
* for all children. Note that specifying this will override any defaults set
* on individual children Transitions.
*/
appear: _propTypes2.default.bool,
/**
* A convenience prop that enables or disables enter animations
* for all children. Note that specifying this will override any defaults set
* on individual children Transitions.
*/
enter: _propTypes2.default.bool,
/**
* A convenience prop that enables or disables exit animations
* for all children. Note that specifying this will override any defaults set
* on individual children Transitions.
*/
exit: _propTypes2.default.bool,
/**
* You may need to apply reactive updates to a child as it is exiting.
* This is generally done by using `cloneElement` however in the case of an exiting
* child the element has already been removed and not accessible to the consumer.
*
* If you do need to update a child as it leaves you can provide a `childFactory`
* to wrap every child, even the ones that are leaving.
*
* @type Function(child: ReactElement) -> ReactElement
*/
childFactory: _propTypes2.default.func
};
var defaultProps = {
component: 'div',
childFactory: function childFactory(child) {
return child;
}
};
/**
* The `<TransitionGroup>` component manages a set of `<Transition>` components
* in a list. Like with the `<Transition>` component, `<TransitionGroup>`, is a
* state machine for managing the mounting and unmounting of components over
* time.
*
* Consider the example below using the `Fade` CSS transition from before.
* As items are removed or added to the TodoList the `in` prop is toggled
* automatically by the `<TransitionGroup>`. You can use _any_ `<Transition>`
* component in a `<TransitionGroup>`, not just css.
*
* ## Example
*
* <iframe src="https://codesandbox.io/embed/00rqyo26kn?fontsize=14" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
*
* Note that `<TransitionGroup>` does not define any animation behavior!
* Exactly _how_ a list item animates is up to the individual `<Transition>`
* components. This means you can mix and match animations across different
* list items.
*/
var TransitionGroup = function (_React$Component) {
_inherits(TransitionGroup, _React$Component);
function TransitionGroup(props, context) {
_classCallCheck(this, TransitionGroup);
// Initial children should all be entering, dependent on appear
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context));
_this.state = {
children: (0, _ChildMapping.getChildMapping)(props.children, function (child) {
return (0, _react.cloneElement)(child, {
onExited: _this.handleExited.bind(_this, child),
in: true,
appear: _this.getProp(child, 'appear'),
enter: _this.getProp(child, 'enter'),
exit: _this.getProp(child, 'exit')
});
})
};
return _this;
}
TransitionGroup.prototype.getChildContext = function getChildContext() {
return {
transitionGroup: { isMounting: !this.appeared }
};
};
// use child config unless explictly set by the Group
TransitionGroup.prototype.getProp = function getProp(child, prop) {
var props = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.props;
return props[prop] != null ? props[prop] : child.props[prop];
};
TransitionGroup.prototype.componentDidMount = function componentDidMount() {
this.appeared = true;
};
TransitionGroup.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
var _this2 = this;
var prevChildMapping = this.state.children;
var nextChildMapping = (0, _ChildMapping.getChildMapping)(nextProps.children);
var children = (0, _ChildMapping.mergeChildMappings)(prevChildMapping, nextChildMapping);
Object.keys(children).forEach(function (key) {
var child = children[key];
if (!(0, _react.isValidElement)(child)) return;
var hasPrev = key in prevChildMapping;
var hasNext = key in nextChildMapping;
var prevChild = prevChildMapping[key];
var isLeaving = (0, _react.isValidElement)(prevChild) && !prevChild.props.in;
// item is new (entering)
if (hasNext && (!hasPrev || isLeaving)) {
// console.log('entering', key)
children[key] = (0, _react.cloneElement)(child, {
onExited: _this2.handleExited.bind(_this2, child),
in: true,
exit: _this2.getProp(child, 'exit', nextProps),
enter: _this2.getProp(child, 'enter', nextProps)
});
}
// item is old (exiting)
else if (!hasNext && hasPrev && !isLeaving) {
// console.log('leaving', key)
children[key] = (0, _react.cloneElement)(child, { in: false });
}
// item hasn't changed transition states
// copy over the last transition props;
else if (hasNext && hasPrev && (0, _react.isValidElement)(prevChild)) {
// console.log('unchanged', key)
children[key] = (0, _react.cloneElement)(child, {
onExited: _this2.handleExited.bind(_this2, child),
in: prevChild.props.in,
exit: _this2.getProp(child, 'exit', nextProps),
enter: _this2.getProp(child, 'enter', nextProps)
});
}
});
this.setState({ children: children });
};
TransitionGroup.prototype.handleExited = function handleExited(child, node) {
var currentChildMapping = (0, _ChildMapping.getChildMapping)(this.props.children);
if (child.key in currentChildMapping) return;
if (child.props.onExited) {
child.props.onExited(node);
}
this.setState(function (state) {
var children = _extends({}, state.children);
delete children[child.key];
return { children: children };
});
};
TransitionGroup.prototype.render = function render() {
var _props = this.props,
Component = _props.component,
childFactory = _props.childFactory,
props = _objectWithoutProperties(_props, ['component', 'childFactory']);
var children = values(this.state.children).map(childFactory);
delete props.appear;
delete props.enter;
delete props.exit;
if (Component === null) {
return children;
}
return _react2.default.createElement(
Component,
props,
children
);
};
return TransitionGroup;
}(_react2.default.Component);
TransitionGroup.childContextTypes = {
transitionGroup: _propTypes2.default.object.isRequired
};
TransitionGroup.propTypes = process.env.NODE_ENV !== "production" ? propTypes : {};
TransitionGroup.defaultProps = defaultProps;
exports.default = TransitionGroup;
module.exports = exports['default'];