UNPKG

@alifd/next

Version:

A configurable component library for web built on React.

692 lines (549 loc) 27.1 kB
'use strict'; exports.__esModule = true; var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties'); var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2); var _extends3 = require('babel-runtime/helpers/extends'); var _extends4 = _interopRequireDefault(_extends3); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); exports.default = ShellBase; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _classnames12 = require('classnames'); var _classnames13 = _interopRequireDefault(_classnames12); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _reactLifecyclesCompat = require('react-lifecycles-compat'); var _configProvider = require('../config-provider'); var _configProvider2 = _interopRequireDefault(_configProvider); var _affix = require('../affix'); var _affix2 = _interopRequireDefault(_affix); var _icon = require('../icon'); var _icon2 = _interopRequireDefault(_icon); var _util = require('../util'); var _util2 = require('./util'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Shell */ function ShellBase(props) { var _class, _temp, _initialiseProps; var componentName = props.componentName; var Shell = (_temp = _class = function (_Component) { (0, _inherits3.default)(Shell, _Component); function Shell(props) { (0, _classCallCheck3.default)(this, Shell); var _this = (0, _possibleConstructorReturn3.default)(this, _Component.call(this, props)); _initialiseProps.call(_this); var deviceMap = (0, _util2.getCollapseMap)(props.device); _this.layout = {}; _this.state = { controll: false, collapseMap: deviceMap, device: props.device }; return _this; } Shell.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) { var device = prevState.device; if (nextProps.device !== device) { var deviceMap = (0, _util2.getCollapseMap)(nextProps.device); return { controll: false, collapseMap: deviceMap, device: nextProps.device }; } return {}; }; Shell.prototype.componentDidMount = function componentDidMount() { this.checkAsideFixed(); }; Shell.prototype.componentDidUpdate = function componentDidUpdate(prevProps) { var _this2 = this; if (prevProps.device !== this.props.device) { var deviceMapBefore = (0, _util2.getCollapseMap)(prevProps.device); var deviceMapAfter = (0, _util2.getCollapseMap)(this.props.device); Object.keys(deviceMapAfter).forEach(function (block) { var _ref = _this2.layout[block] || {}, props = _ref.props; if (deviceMapBefore[block] !== deviceMapAfter[block]) { if (props && typeof props.onCollapseChange === 'function') { props.onCollapseChange(deviceMapAfter[block]); } } }); } setTimeout(function () { // 如果左侧边栏固定 _this2.checkAsideFixed(); }, 201); }; Shell.prototype.render = function render() { return this.renderShell(this.props); }; return Shell; }(_react.Component), _class.displayName = componentName, _class._typeMark = componentName, _class.propTypes = (0, _extends4.default)({}, _configProvider2.default.propTypes, { prefix: _propTypes2.default.string, /** * 设备类型 * @enumdesc 手机, 平板, PC电脑 */ device: _propTypes2.default.oneOf(['phone', 'tablet', 'desktop']), /** * 设备类型 * @enumdesc 浅色, 深色, 主题色 */ type: _propTypes2.default.oneOf(['light', 'dark', 'brand']), /** * 是否固定 header, 用sticky实现,IE下降级为Affix */ fixedHeader: _propTypes2.default.bool }), _class.defaultProps = { prefix: 'next-', device: 'desktop', type: 'light', fixedHeader: false }, _initialiseProps = function _initialiseProps() { var _this3 = this; this.checkAsideFixed = function () { var fixedHeader = _this3.props.fixedHeader; if (!fixedHeader) { return; } var headerHeight = void 0; if (_this3.headerRef && (_this3.navigationFixed || _this3.toolDockFixed)) { headerHeight = _util.dom.getStyle(_this3.headerRef, 'height'); } if (_this3.navigationFixed) { var style = {}; style.marginLeft = _util.dom.getStyle(_this3.navRef, 'width'); _util.dom.addClass(_this3.navRef, 'fixed'); headerHeight && _util.dom.setStyle(_this3.navRef, { top: headerHeight }); _util.dom.setStyle(_this3.localNavRef || _this3.submainRef, style); } if (_this3.toolDockFixed) { var _style = {}; _style.marginRight = _util.dom.getStyle(_this3.toolDockRef, 'width'); _util.dom.addClass(_this3.toolDockRef, 'fixed'); headerHeight && _util.dom.setStyle(_this3.toolDockRef, { top: headerHeight }); _util.dom.setStyle(_this3.localNavRef || _this3.submainRef, _style); } }; this.setChildCollapse = function (child, mark) { var _state = _this3.state, device = _state.device, collapseMap = _state.collapseMap, controll = _state.controll; var collapse = child.props.collapse; var deviceMap = (0, _util2.getCollapseMap)(device); var props = {}; // 非受控模式 if ((0, _util2.isBoolean)(collapse) === false) { props.collapse = controll ? collapseMap[mark] : deviceMap[mark]; // props.collapse = collapseMap[mark]; } if (device !== 'phone' && mark === 'Navigation') { props.miniable = true; } return _react2.default.cloneElement(child, props); }; this.toggleAside = function (mark, props, e) { var _extends2; var _state2 = _this3.state, device = _state2.device, collapseMap = _state2.collapseMap; var deviceMap = (0, _util2.getCollapseMap)(device); var current = props.collapse; var newCollapseMap = (0, _extends4.default)({}, deviceMap, collapseMap, (_extends2 = {}, _extends2[mark] = !current, _extends2)); _this3.setState({ controll: true, collapseMap: newCollapseMap }); if (props && typeof props.onCollapseChange === 'function') { props.onCollapseChange(newCollapseMap[mark]); } var children = _this3.props.children; var com = void 0; if (mark === 'Navigation') { com = children.filter(function (child) { return child && child.type._typeMark.replace('Shell_', '') === mark && child.props.direction !== 'hoz'; }).pop(); } else { com = children.filter(function (child) { return child && child.type._typeMark.replace('Shell_', '') === mark; }).pop(); } var _com$props$triggerPro = com.props.triggerProps, triggerProps = _com$props$triggerPro === undefined ? {} : _com$props$triggerPro; if (typeof triggerProps.onClick === 'function') { triggerProps.onClick(e, _this3.state.collapseMap[mark]); } }; this.toggleNavigation = function (e) { var mark = 'Navigation'; var props = _this3.layout[mark].props; if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) { return; } _this3.toggleAside(mark, props, e); }; this.toggleLocalNavigation = function (e) { var mark = 'LocalNavigation'; var props = _this3.layout[mark].props; if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) { return; } _this3.toggleAside(mark, props, e); }; this.toggleAncillary = function (e) { var mark = 'Ancillary'; var props = _this3.layout[mark].props; if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) { return; } _this3.toggleAside(mark, props, e); }; this.toggleToolDock = function (e) { var mark = 'ToolDock'; var props = _this3.layout[mark].props; if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) { return; } _this3.toggleAside(mark, props, e); }; this.saveHeaderRef = function (ref) { _this3.headerRef = ref; }; this.saveLocalNavRef = function (ref) { _this3.localNavRef = ref; }; this.saveNavRef = function (ref) { _this3.navRef = ref; }; this.saveSubmainRef = function (ref) { _this3.submainRef = ref; }; this.saveToolDockRef = function (ref) { _this3.toolDockRef = ref; }; this.renderShell = function (props) { var _classnames, _classnames2, _classnames3, _classnames4, _classnames5, _classnames6, _classnames7, _classnames11; var prefix = props.prefix, children = props.children, className = props.className, type = props.type, fixedHeader = props.fixedHeader, others = (0, _objectWithoutProperties3.default)(props, ['prefix', 'children', 'className', 'type', 'fixedHeader']); var device = _this3.state.device; var layout = {}; layout.header = {}; var hasToolDock = false, needNavigationTrigger = false, needDockTrigger = false; _react2.default.Children.map(children, function (child) { if (child && typeof child.type === 'function') { var mark = child.type._typeMark.replace('Shell_', ''); switch (mark) { case 'Branding': case 'Action': layout.header[mark] = child; break; case 'MultiTask': layout.taskHeader = child; break; case 'LocalNavigation': if (!layout[mark]) { layout[mark] = []; } layout[mark] = _this3.setChildCollapse(child, mark); break; case 'Ancillary': if (!layout[mark]) { layout[mark] = []; } layout[mark] = _this3.setChildCollapse(child, mark); break; case 'ToolDock': hasToolDock = true; if (!layout[mark]) { layout[mark] = []; } _this3.toolDockFixed = child.props.fixed; var childT = _this3.setChildCollapse(child, mark); layout[mark] = childT; break; case 'AppBar': case 'Content': case 'Footer': layout.content || (layout.content = []); layout.content.push(child); break; case 'Page': layout.page || (layout.page = []); layout.page = child; break; case 'Navigation': if (child.props.direction === 'hoz') { layout.header[mark] = child; } else { if (!layout[mark]) { layout[mark] = []; } needNavigationTrigger = true; _this3.navigationFixed = child.props.fixed; var childN = _this3.setChildCollapse(child, mark); layout[mark] = childN; } break; default: break; } } }); var headerCls = (0, _classnames13.default)((_classnames = {}, _classnames[prefix + 'shell-header'] = true, _classnames[prefix + 'shell-fixed-header'] = fixedHeader, _classnames)); var mainCls = (0, _classnames13.default)((_classnames2 = {}, _classnames2[prefix + 'shell-main'] = true, _classnames2)); var pageCls = (0, _classnames13.default)((_classnames3 = {}, _classnames3[prefix + 'shell-page'] = true, _classnames3)); var submainCls = (0, _classnames13.default)((_classnames4 = {}, _classnames4[prefix + 'shell-sub-main'] = true, _classnames4)); var asideCls = (0, _classnames13.default)((_classnames5 = {}, _classnames5[prefix + 'shell-aside'] = true, _classnames5)); var toolDockCls = (0, _classnames13.default)((_classnames6 = {}, _classnames6[prefix + 'aside-tooldock'] = true, _classnames6)); var navigationCls = (0, _classnames13.default)((_classnames7 = {}, _classnames7[prefix + 'aside-navigation'] = true, _classnames7[prefix + 'shell-collapse'] = layout.Navigation && layout.Navigation.props.collapse, _classnames7)); if (hasToolDock) { if (device === 'phone') { needDockTrigger = true; } } // 如果存在垂直模式的 Navigation, 则需要在 Branding 上出现 trigger if (needNavigationTrigger) { var branding = layout.header.Branding; var _layout$Navigation$pr = layout.Navigation.props, trigger = _layout$Navigation$pr.trigger, collapse = _layout$Navigation$pr.collapse; if ('trigger' in layout.Navigation.props) { trigger = trigger && _react2.default.cloneElement(trigger, { onClick: _this3.toggleNavigation, 'aria-expanded': !collapse }) || trigger; } else { trigger = _react2.default.createElement( 'div', { key: 'nav-trigger', role: 'button', tabIndex: 0, 'aria-expanded': !collapse, 'aria-label': 'toggle', className: 'nav-trigger', onClick: _this3.toggleNavigation, onKeyDown: _this3.toggleNavigation }, collapse ? _react2.default.createElement(_icon2.default, { size: 'small', type: 'toggle-right' }) : _react2.default.createElement(_icon2.default, { size: 'small', type: 'toggle-left' }) ); } if (!branding) { trigger && (layout.header.Branding = trigger); } else { layout.header.Branding = _react2.default.cloneElement(branding, {}, [trigger, branding.props.children]); } } // 如果存在 toolDock, 则需要在 Action 上出现 trigger if (needDockTrigger) { var action = layout.header.Action; var _layout$ToolDock$prop = layout.ToolDock.props, _trigger = _layout$ToolDock$prop.trigger, _collapse = _layout$ToolDock$prop.collapse; if ('trigger' in layout.ToolDock.props) { _trigger = _trigger && _react2.default.cloneElement(_trigger, { onClick: _this3.toggleToolDock, 'aria-expanded': !_collapse }) || _trigger; } else { _trigger = _react2.default.createElement( 'div', { key: 'dock-trigger', tabIndex: 0, role: 'button', 'aria-expanded': !_collapse, 'aria-label': 'toggle', className: 'dock-trigger', onClick: _this3.toggleToolDock, onKeyDown: _this3.toggleToolDock }, _react2.default.createElement(_icon2.default, { size: 'small', type: 'add' }) ); } if (!action) { layout.header.Action = _trigger; } else { layout.header.Action = _react2.default.cloneElement(action, {}, [action.props.children, _trigger]); } } var headerDom = [], contentArr = [], innerArr = [], taskHeaderDom = null; if (layout.taskHeader) { var _classnames8; var taskHeaderCls = (0, _classnames13.default)((_classnames8 = {}, _classnames8[prefix + 'shell-task-header'] = true, _classnames8)); taskHeaderDom = _react2.default.createElement( 'section', { key: 'task-header', className: taskHeaderCls }, layout.taskHeader ); } // 按照dom结构,innerArr 包括 LocalNavigation content Ancillary if (layout.LocalNavigation) { var _classnames9; var _layout$LocalNavigati = layout.LocalNavigation.props, _trigger2 = _layout$LocalNavigati.trigger, _collapse2 = _layout$LocalNavigati.collapse; if ('trigger' in layout.LocalNavigation.props) { _trigger2 = _trigger2 && _react2.default.cloneElement(_trigger2, { onClick: _this3.toggleLocalNavigation, 'aria-expanded': !_collapse2 }) || _trigger2; } else { _trigger2 = _react2.default.createElement( 'div', { key: 'local-nav-trigger', role: 'button', tabIndex: 0, 'aria-expanded': !_collapse2, 'aria-label': 'toggle', className: 'local-nav-trigger aside-trigger', onClick: _this3.toggleLocalNavigation, onKeyDown: _this3.toggleLocalNavigation }, _collapse2 ? _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-right' }) : _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-left' }) ); } var localNavCls = (0, _classnames13.default)(asideCls, (_classnames9 = {}, _classnames9[prefix + 'aside-localnavigation'] = true, _classnames9)); innerArr.push(_react2.default.createElement( 'aside', { key: 'localnavigation', className: localNavCls, ref: _this3.saveLocalNavRef }, _react2.default.cloneElement(layout.LocalNavigation, {}, [_react2.default.createElement( 'div', { key: 'wrapper', className: prefix + 'shell-content-wrapper' }, layout.LocalNavigation.props.children ), _trigger2]) )); } if (layout.content) { innerArr.push(_react2.default.createElement( 'section', { key: 'submain', className: submainCls, ref: _this3.saveSubmainRef }, layout.content )); } if (layout.Ancillary) { var _classnames10; var _layout$Ancillary$pro = layout.Ancillary.props, _trigger3 = _layout$Ancillary$pro.trigger, _collapse3 = _layout$Ancillary$pro.collapse; if ('trigger' in layout.Ancillary.props) { _trigger3 = _trigger3 && _react2.default.cloneElement(_trigger3, { onClick: _this3.toggleAncillary, 'aria-expanded': !_collapse3 }) || _trigger3; } else { _trigger3 = _react2.default.createElement( 'div', { key: 'ancillary-trigger', role: 'button', tabIndex: 0, 'aria-expanded': !_collapse3, 'aria-label': 'toggle', className: 'ancillary-trigger aside-trigger', onClick: _this3.toggleAncillary, onKeyDown: _this3.toggleAncillary }, _collapse3 ? _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-left' }) : _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-right' }) ); } var ancillaryCls = (0, _classnames13.default)(asideCls, (_classnames10 = {}, _classnames10[prefix + 'aside-ancillary'] = true, _classnames10)); innerArr.push(_react2.default.createElement( 'aside', { key: 'ancillary', className: ancillaryCls }, _react2.default.cloneElement(layout.Ancillary, {}, [_react2.default.createElement( 'div', { key: 'wrapper', className: prefix + 'shell-content-wrapper' }, layout.Ancillary.props.children ), _trigger3]) )); } // 按照dom结构, arr 包括 header Navigation ToolDock 和 innerArr if (Object.keys(layout.header).length > 0) { var _dom = _react2.default.createElement( 'header', { key: 'header', className: headerCls, ref: _this3.saveHeaderRef }, layout.header.Branding, layout.header.Navigation, layout.header.Action ); if (fixedHeader && _util.env.ieVersion) { headerDom = _react2.default.createElement( _affix2.default, { style: { zIndex: 9 } }, _dom ); } else { headerDom = _dom; } } layout.Navigation && contentArr.push(_react2.default.createElement( 'aside', { key: 'navigation', className: navigationCls, ref: _this3.saveNavRef }, _react2.default.cloneElement(layout.Navigation, { className: (0, _classnames13.default)(asideCls, layout.Navigation.props.className) }) )); // const contentArea = innerArr.length > 0 // ? <section key="main" className={mainCls}>{innerArr}</section> // : layout.page; // contentArr.push(contentArea); contentArr = contentArr.concat(innerArr.length > 0 ? innerArr : [_react2.default.createElement( 'section', { key: 'page', ref: _this3.saveSubmainRef, className: submainCls }, layout.page )]); layout.ToolDock && contentArr.push(_react2.default.createElement( 'aside', { key: 'tooldock', className: toolDockCls, ref: _this3.saveToolDockRef }, _react2.default.cloneElement(layout.ToolDock, { className: (0, _classnames13.default)(asideCls, layout.ToolDock.props.className), key: 'tooldock' }) )); var cls = (0, _classnames13.default)((_classnames11 = {}, _classnames11[prefix + 'shell'] = true, _classnames11[prefix + 'shell-' + device] = true, _classnames11[prefix + 'shell-' + type] = true, _classnames11[className] = !!className, _classnames11)); if (componentName === 'Page') { return _react2.default.createElement( 'section', { className: pageCls }, children ); } _this3.layout = layout; return _react2.default.createElement( 'section', (0, _extends4.default)({ className: cls }, others), headerDom, taskHeaderDom, _react2.default.createElement( 'section', { className: mainCls }, contentArr ) ); }; }, _temp); Shell.displayName = 'Shell'; return (0, _reactLifecyclesCompat.polyfill)(Shell); } module.exports = exports['default'];