UNPKG

backpack-ui

Version:
428 lines (350 loc) 12.1 kB
"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);