wix-style-react
Version:
wix-style-react
370 lines (317 loc) • 12.5 kB
JavaScript
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;