UNPKG

backpack-ui

Version:

Lonely Planet's Components

406 lines (333 loc) 12.2 kB
"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);