backpack-ui
Version:
Lonely Planet's Components
406 lines (333 loc) • 12.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
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 _reactPortal = require("react-portal");
var _reactPortal2 = _interopRequireDefault(_reactPortal);
var _radium = require("radium");
var _radium2 = _interopRequireDefault(_radium);
var _noScroll = require("no-scroll");
var _noScroll2 = _interopRequireDefault(_noScroll);
var _settings = require("../../../settings.json");
var _icon = require("../icon");
var _icon2 = _interopRequireDefault(_icon);
var _overlay = require("../overlay");
var _overlay2 = _interopRequireDefault(_overlay);
var _color = require("../../utils/color");
var _grid = require("../../utils/grid");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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 Takeover = function (_Component) {
_inherits(Takeover, _Component);
function Takeover(props) {
_classCallCheck(this, Takeover);
// setting the state here will open the takeover without the animation when
// `this.props.isOpened` is true
var _this = _possibleConstructorReturn(this, (Takeover.__proto__ || Object.getPrototypeOf(Takeover)).call(this, props));
_this.state = {
isOpen: props.isOpened,
hasAnimated: props.isOpened
};
_this.animatonSpeed = parseInt(_settings.timing.default.replace("ms", ""), 10);
_this.onOpen = _this.onOpen.bind(_this);
_this.onClose = _this.onClose.bind(_this);
_this.handleKeydown = _this.handleKeydown.bind(_this);
return _this;
}
_createClass(Takeover, [{
key: "componentDidMount",
value: function componentDidMount() {
document.addEventListener("keydown", this.handleKeydown);
if (this.props.isOpened) {
this.onOpen();
}
}
}, {
key: "componentWillReceiveProps",
value: function componentWillReceiveProps(nextProps) {
var shouldOpen = this.props.isOpened !== nextProps.isOpened && nextProps.isOpened;
if (shouldOpen) {
this.onOpen();
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
document.removeEventListener("keydown", this.handleKeydown);
this.document = null;
}
}, {
key: "onOpen",
value: function onOpen() {
var _this2 = this;
this.setState({
isOpen: true
});
// Wait for animation
setTimeout(function () {
_this2.setState({
hasAnimated: true
});
if (_this2.props.scroll) {
_noScroll2.default.on();
}
}, 10);
}
}, {
key: "onClose",
value: function onClose() {
var _this3 = this;
this.setState({
hasAnimated: false
});
// Wait for animation
setTimeout(function () {
_this3.setState({
isOpen: false
});
if (_this3.props.scroll) {
_noScroll2.default.off();
}
}, this.animatonSpeed);
}
}, {
key: "handleKeydown",
value: function handleKeydown(event) {
if (event.keyCode === 27 && this.state.isOpen) {
this.onClose();
}
}
}, {
key: "render",
value: function render() {
var _props = this.props;
var children = _props.children;
var closeOnHeaderClick = _props.closeOnHeaderClick;
var cover = _props.cover;
var hasOverlay = _props.hasOverlay;
var title = _props.title;
var mobile = _props.mobile;
var contentFill = _props.contentFill;
var scroll = _props.scroll;
var styles = {
portal: {
base: {
height: 0,
width: 0
}
},
takeover: {
container: {
base: {
backgroundColor: _settings.color.white,
boxShadow: "0 5px 50px rgba(" + (0, _color.rgb)(_settings.color.black) + ", 0.5)",
left: 0,
opacity: 0,
position: "fixed",
top: 0,
transform: "translateY(15%)",
transition: "opacity " + this.animatonSpeed + "ms,\n transform " + this.animatonSpeed + "ms",
width: "100%",
zIndex: _settings.zIndex.modal
},
cover: {
bottom: 0,
height: "100vh",
right: 0
},
hidden: {
opacity: 0,
transform: "translateY(15%)"
},
visible: {
opacity: 1,
transform: "translateY(0)"
}
},
header: {
base: {
backgroundColor: _settings.color.white,
height: _settings.components.header.heightMobile,
position: "relative",
textAlign: "center",
zIndex: _settings.zIndex.modal
},
shadow: {
boxShadow: "40px 2px 20px rgba(" + (0, _color.rgb)(_settings.color.black) + ", 0.05),\n -40px 2px 20px rgba(" + (0, _color.rgb)(_settings.color.black) + ", 0.05)"
},
border: {
borderBottom: "1px solid " + _settings.color.gray
},
mobile: {
paddingLeft: _settings.spacing.mobile,
paddingRight: _settings.spacing.mobile
}
},
heading: {
base: {
display: "inline-block",
fontSize: "20px",
fontWeight: 400,
lineHeight: 1,
maxWidth: 275 / 20 + "em",
overflow: "hidden",
paddingBottom: 13 / 20 + "em",
paddingTop: 17 / 20 + "em",
textOverflow: "ellipsis"
}
},
close: {
base: {
backgroundColor: "transparent",
color: _settings.color.darkGray,
fontSize: "16px",
height: _settings.components.header.heightMobile,
width: _settings.components.header.heightMobile,
position: "absolute",
right: 3 / 16 + "em",
top: 0
}
},
content: {
base: {},
cover: {
height: "calc(100vh - " + _settings.components.header.heightMobile + ")"
}
}
}
};
return _react2.default.createElement(
"span",
null,
_react2.default.createElement(
_reactPortal2.default,
{
className: "Takeover-portal",
key: "content",
isOpened: this.state.isOpen,
style: styles.portal.base
},
_react2.default.createElement(
"div",
{
className: "Takeover",
style: [styles.takeover.container.base, cover && styles.takeover.container.cover, !this.state.hasAnimated ? styles.takeover.container.hidden : styles.takeover.container.visible]
},
_react2.default.createElement(
"header",
{
className: "Takeover-header",
style: [styles.takeover.header.base, title && contentFill && styles.takeover.header.shadow, title && !contentFill && styles.takeover.header.border, mobile && styles.takeover.header.mobile],
onClick: closeOnHeaderClick && this.onClose
},
title && _react2.default.createElement(
"h4",
{ className: "Takeover-heading", style: styles.takeover.heading.base },
title
),
_react2.default.createElement(
"button",
{
className: "Takeover-close",
style: styles.takeover.close.base,
onClick: !closeOnHeaderClick && this.onClose
},
_react2.default.createElement(_icon2.default.Cross, { label: "Close" })
)
),
_react2.default.createElement(
"div",
{
className: "Takeover-content",
style: [cover && styles.takeover.content.cover, scroll && {
overflow: "auto",
WebkitOverflowScrolling: "touch"
}]
},
_react2.default.createElement(
"div",
{
style: [mobile && !contentFill && { padding: "40px " + _settings.spacing.mobile }, !mobile && !contentFill && { padding: (0, _grid.gutter)() }, cover && !scroll && { height: "100%" }]
},
children
)
)
)
),
hasOverlay && _react2.default.createElement(_overlay2.default, {
attached: this.state.isOpen,
onClick: this.onClose,
visible: this.state.hasAnimated
})
);
}
}]);
return Takeover;
}(_react.Component);
Takeover.propTypes = {
/**
* Content for the takeover
*/
children: _react.PropTypes.node.isRequired,
/**
* Should the takeover be opened on page load; probably only ever true if the
* takeover has its own URL, i.e., lonelyplanet.com/asia/map could load the
* takeover opened
*/
isOpened: _react.PropTypes.bool,
/**
* Should an overlay be displayed beneath the takeover to obscure the page
* content; generally, if `cover` is true, this can be false (but it doesn't
* have to be)
*/
hasOverlay: _react.PropTypes.bool,
/**
* Should the takeover close when the header is clicked; note that the close
* button in the header will *always* close the takeover and this prop allows
* for the any part of the header to be clicked to close the takeover
*/
closeOnHeaderClick: _react.PropTypes.bool,
/**
* Should the takeover cover the entire height of the viewport
*/
cover: _react.PropTypes.bool,
/**
* A title for the takeover's header
*/
title: _react.PropTypes.string,
/**
* Whether or not the layout is mobile
*/
mobile: _react.PropTypes.bool,
/**
* Should the content fill the entire width and height of the area provided,
* i.e., no padding
*/
contentFill: _react.PropTypes.bool,
/**
* Can the content scroll?
*/
scroll: _react.PropTypes.bool,
/**
* store dispatch function
*/
dispatch: _react.PropTypes.func
};
Takeover.defaultProps = {
children: null,
isOpened: false,
hasOverlay: false,
closeOnHeaderClick: false,
cover: false,
title: "",
mobile: false,
contentFill: false,
scroll: false,
dispatch: null
};
exports.default = (0, _radium2.default)(Takeover);