backpack-ui
Version:
Lonely Planet's Components
428 lines (350 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn");
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require("babel-runtime/helpers/inherits");
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
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 _colors = require("../../styles/colors");
var _colors2 = _interopRequireDefault(_colors);
var _dimensions = require("../../styles/dimensions");
var _dimensions2 = _interopRequireDefault(_dimensions);
var _timing = require("../../styles/timing");
var _timing2 = _interopRequireDefault(_timing);
var _zIndex = require("../../styles/zIndex");
var _zIndex2 = _interopRequireDefault(_zIndex);
var _color = require("../../utils/color");
var _grid = require("../../utils/grid");
var _icon = require("../icon");
var _icon2 = _interopRequireDefault(_icon);
var _overlay = require("../overlay");
var _overlay2 = _interopRequireDefault(_overlay);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var Takeover = function (_Component) {
(0, _inherits3.default)(Takeover, _Component);
function Takeover(props) {
(0, _classCallCheck3.default)(this, Takeover);
// setting the state here will open the takeover without the animation when
// `this.props.isOpened` is true
var _this = (0, _possibleConstructorReturn3.default)(this, (Takeover.__proto__ || (0, _getPrototypeOf2.default)(Takeover)).call(this, props));
_this.state = {
isOpen: props.isOpened,
hasAnimated: props.isOpened
};
_this.animatonSpeed = parseInt(_timing2.default.default.replace("ms", ""), 10);
_this.onOpen = _this.onOpen.bind(_this);
_this.onClose = _this.onClose.bind(_this);
_this.handleKeydown = _this.handleKeydown.bind(_this);
return _this;
}
(0, _createClass3.default)(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,
children = _props.children,
closeOnHeaderClick = _props.closeOnHeaderClick,
cover = _props.cover,
hasOverlay = _props.hasOverlay,
title = _props.title,
mobile = _props.mobile,
contentFill = _props.contentFill,
scroll = _props.scroll,
qaHook = _props.qaHook;
var styles = {
portal: {
base: {
height: 0,
width: 0
}
},
takeover: {
container: {
base: {
backgroundColor: _colors2.default.bgPrimary,
boxShadow: "0 5px 50px rgba(" + (0, _color.rgb)(_colors2.default.shadowPrimary) + ", 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: _zIndex2.default.modal
},
cover: {
bottom: 0,
height: "100vh",
right: 0
},
hidden: {
opacity: 0,
transform: "translateY(15%)"
},
visible: {
opacity: 1,
transform: "translateY(0)"
}
},
header: {
base: {
backgroundColor: _colors2.default.bgPrimary,
height: _dimensions2.default.headerHeightMobile + "px",
position: "relative",
textAlign: "center",
zIndex: _zIndex2.default.modal
},
shadow: {
boxShadow: "40px 2px 20px rgba(" + (0, _color.rgb)(_colors2.default.shadowPrimary) + ", 0.05),\n -40px 2px 20px rgba(" + (0, _color.rgb)(_colors2.default.shadowPrimary) + ", 0.05)"
},
border: {
borderBottom: "1px solid " + _colors2.default.borderPrimary
},
mobile: {
paddingLeft: "16px",
paddingRight: "16px"
}
},
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: _colors2.default.textPrimary,
fontSize: "16px",
height: "50px",
width: "50px",
position: "absolute",
right: 3 / 16 + "em",
top: 0
}
},
content: {
base: {},
cover: {
height: "calc(100vh - " + _dimensions2.default.headerHeightMobile + "px)"
}
}
}
};
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",
{ // eslint-disable-line jsx-a11y/no-static-element-interactions
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,
"data-testid": qaHook ? "takeover-close-btn" : null
},
_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 16px" }, !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: _propTypes2.default.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: _propTypes2.default.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: _propTypes2.default.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: _propTypes2.default.bool,
/**
* Should the takeover cover the entire height of the viewport
*/
cover: _propTypes2.default.bool,
/**
* A title for the takeover's header
*/
title: _propTypes2.default.string,
/**
* Whether or not the layout is mobile
*/
mobile: _propTypes2.default.bool,
/**
* Should the content fill the entire width and height of the area provided,
* i.e., no padding
*/
contentFill: _propTypes2.default.bool,
/**
* Can the content scroll?
*/
scroll: _propTypes2.default.bool,
/**
* For automation purposes
*/
qaHook: _propTypes2.default.bool
};
Takeover.defaultProps = {
children: null,
isOpened: false,
hasOverlay: false,
closeOnHeaderClick: false,
cover: false,
title: "",
mobile: false,
contentFill: false,
scroll: false,
qaHook: false
};
exports.default = (0, _radium2.default)(Takeover);