UNPKG

wix-style-react

Version:
370 lines (317 loc) • 12.5 kB
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 _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; }; }(); 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; } import React, { Children } from 'react'; import PropTypes from 'prop-types'; import SideMenu from '../core/SideMenu'; import SlideAnimation, { SlideDirection } from '../../Animations/SlideAnimation'; import styles from './DrillView.scss'; var isAnchorTag = function isAnchorTag(item) { return item.type === 'a'; }; var SideMenuDrill = function (_React$Component) { _inherits(SideMenuDrill, _React$Component); function SideMenuDrill(props) { _classCallCheck(this, SideMenuDrill); var _this = _possibleConstructorReturn(this, (SideMenuDrill.__proto__ || Object.getPrototypeOf(SideMenuDrill)).call(this, props)); var state = { menus: {}, currentMenuId: _this.props.menuKey, previousMenuId: null, showMenuA: true, slideDirection: SlideDirection.in }; _this.processChildren({ props: _this.props }, state); _this.state = state; _this.isAnimating = false; return _this; } _createClass(SideMenuDrill, [{ key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var state = { menus: {} }; this.processChildren({ props: nextProps }, state); this.setState(state); } }, { key: 'setSelectedItemMenu', value: function setSelectedItemMenu(selectedItemMenuId, state) { // initial selected menu if (!this.state) { Object.assign(state, { currentMenuId: selectedItemMenuId, selectedItemMenuId: selectedItemMenuId }); return; } // returning to an already selected menu item (force nav) if (this.lastClickedMenuKey === selectedItemMenuId) { this.navigateToMenu(selectedItemMenuId, SlideDirection.in); this.lastClickedMenuKey = null; } if (this.state.selectedItemMenuId === selectedItemMenuId) { return; } this.setState({ selectedItemMenuId: selectedItemMenuId }); if (this.state.currentMenuId !== selectedItemMenuId) { this.navigateToMenu(selectedItemMenuId, this.getSlideDirectionTo(selectedItemMenuId)); } } }, { key: 'getSlideDirectionTo', value: function getSlideDirectionTo(selectedItemMenuId) { var _state = this.state, currentMenuId = _state.currentMenuId, menus = _state.menus; if (!menus[currentMenuId] || !menus[selectedItemMenuId]) { return SlideDirection.in; } return menus[currentMenuId].level < menus[selectedItemMenuId].level ? SlideDirection.in : SlideDirection.out; } }, { key: 'navigateToMenu', value: function navigateToMenu(nextMenuId, slideDirection) { var previousMenuId = this.state.currentMenuId; var showMenuA = !this.state.showMenuA; if (nextMenuId === previousMenuId) { return; } this.setState({ currentMenuId: nextMenuId, previousMenuId: previousMenuId, showMenuA: showMenuA, slideDirection: slideDirection }); } }, { key: 'clickFirstClickableChild', value: function clickFirstClickableChild(item, event) { var _this2 = this; var found = false; if (item.props.onClick && !item.props.disabled) { item.props.onClick(event); return true; } else if (isAnchorTag(item)) { return false; } Children.forEach(item.props.children, function (child) { if (!found && child.props) { found = _this2.clickFirstClickableChild(child, event); } }); return found; } }, { key: 'selectFirstLinkChild', value: function selectFirstLinkChild(menu, event) { var _this3 = this; var found = false; Children.forEach(menu.props.children, function (child) { if (!found && child.type === SideMenuDrill.Link) { _this3.clickFirstClickableChild(child, event); found = true; } if (!found && child.props && child.props.children) { _this3.selectFirstLinkChild(child, event); } }); } }, { key: 'alterMenu', value: function alterMenu(menu, childrenClone, parentMenuKey, isActive) { var _this4 = this; var defaultSubMenProps = { isOpen: false, onSelectHandler: function onSelectHandler(event) { _this4.lastClickedMenuKey = menu.props.menuKey; _this4.selectFirstLinkChild(menu, event); if (menu.props.onSelectHandler) { menu.props.onSelectHandler.apply(menu, [event]); } }, onBackHandler: function onBackHandler(event) { _this4.navigateToMenu(parentMenuKey, SlideDirection.out); if (menu.props.onBackHandler) { menu.props.onBackHandler.apply(menu, [event]); } }, isActive: isActive }; return React.cloneElement(menu, defaultSubMenProps, childrenClone); } }, { key: 'cloneSubMenu', value: function cloneSubMenu(menu, state, parentMenuKey, childrenClone) { var isMenuActive = state.menus[menu.props.menuKey].isActive; if (isMenuActive && state.menus[parentMenuKey]) { state.menus[parentMenuKey].isActive = true; } var menuClone = this.alterMenu(menu, childrenClone, parentMenuKey, isMenuActive); state.menus[menuClone.props.menuKey].component = menuClone; return menuClone; } }, { key: 'cloneChild', value: function cloneChild(menu, state, parentMenuKey, childrenClone) { if (menu.type === SideMenuDrill.Link && menu.props.isActive) { this.setSelectedItemMenu(parentMenuKey, state); state.menus[parentMenuKey].isActive = true; } if (menu.props.menuKey) { return this.cloneSubMenu(menu, state, parentMenuKey, childrenClone); } return React.cloneElement(menu, {}, childrenClone); } }, { key: 'processChildren', value: function processChildren(menu, state, parentMenuKey) { var _this5 = this; var level = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; var childrenClone = Children.map(menu.props.children, function (child) { if (child && child.props && child.props.children) { var menuKey = menu.props.menuKey || parentMenuKey; if (!state.menus[menuKey]) { state.menus[menuKey] = { isActive: false, component: null, level: level }; } return _this5.processChildren(child, state, menuKey, level + 1); } return child; }); return this.cloneChild(menu, state, parentMenuKey, childrenClone, level); } }, { key: 'renderNavigation', value: function renderNavigation(menu) { if (!menu) { return null; } if (menu.props.menuKey === this.props.menuKey) { // Render root items return menu.props.children; } // Render open SubMenu return React.cloneElement(menu, { isOpen: true }); } }, { key: 'renderMenu', value: function renderMenu(menu) { var navigationMenu = this.renderNavigation(menu); return navigationMenu && React.createElement( 'div', { 'data-hook': 'drill-view-panel', className: styles.drillViewPanel }, navigationMenu ); } }, { key: 'shouldComponentUpdate', value: function shouldComponentUpdate() { if (this.isAnimating) { this.queuedUpdate = true; } return !this.isAnimating; } }, { key: 'animationStart', value: function animationStart() { this.isAnimating = true; } }, { key: 'animationComplete', value: function animationComplete() { this.isAnimating = false; if (this.queuedUpdate) { this.queuedUpdate = false; this.forceUpdate(); } } }, { key: 'getAnimationHandlers', value: function getAnimationHandlers() { var _this6 = this; var enterHandlers = {}; var exitHandlers = {}; var enterPromise = new Promise(function (resolve) { return enterHandlers.onEnter = resolve; }); var enteredPromise = new Promise(function (resolve) { return enterHandlers.onEntered = resolve; }); var exitPromise = new Promise(function (resolve) { return exitHandlers.onExit = resolve; }); var exitedPromise = new Promise(function (resolve) { return exitHandlers.onExited = resolve; }); Promise.race([enterPromise, exitPromise]).then(function () { return _this6.animationStart(); }); Promise.all([enteredPromise, exitedPromise]).then(function () { return _this6.animationComplete(); }); return { enterHandlers: enterHandlers, exitHandlers: exitHandlers }; } }, { key: 'render', value: function render() { var _state2 = this.state, menus = _state2.menus, currentMenuId = _state2.currentMenuId, previousMenuId = _state2.previousMenuId, showMenuA = _state2.showMenuA, slideDirection = _state2.slideDirection; var menuAId = showMenuA ? currentMenuId : previousMenuId; var menuBId = showMenuA ? previousMenuId : currentMenuId; var menuA = menuAId && menus[menuAId].component; var menuB = menuBId && menus[menuBId].component; var _getAnimationHandlers = this.getAnimationHandlers(), enterHandlers = _getAnimationHandlers.enterHandlers, exitHandlers = _getAnimationHandlers.exitHandlers; var menuAHandlers = showMenuA ? enterHandlers : exitHandlers; var menuBHandlers = showMenuA ? exitHandlers : enterHandlers; return React.createElement( SideMenu, { dataHook: this.props.dataHook, inFlex: this.props.inFlex }, React.createElement( 'div', { className: styles.drillViewContainer }, React.createElement( SlideAnimation, _extends({ direction: slideDirection, animateAppear: false, isVisible: showMenuA }, menuAHandlers), this.renderMenu(menuA) ), React.createElement( SlideAnimation, _extends({ direction: slideDirection, animateAppear: false, isVisible: !showMenuA }, menuBHandlers), this.renderMenu(menuB) ) ), this.props.stickyFooter ); } }]); return SideMenuDrill; }(React.Component); SideMenuDrill.defaultProps = { inFlex: false, menuKey: 'root' }; SideMenuDrill.propTypes = { dataHook: PropTypes.string, inFlex: PropTypes.bool, menuKey: PropTypes.string, children: PropTypes.node, stickyFooter: PropTypes.node }; export default SideMenuDrill;