UNPKG

27.1 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
6
7var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
8
9var _extends3 = require('babel-runtime/helpers/extends');
10
11var _extends4 = _interopRequireDefault(_extends3);
12
13var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
14
15var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
16
17var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
18
19var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
20
21var _inherits2 = require('babel-runtime/helpers/inherits');
22
23var _inherits3 = _interopRequireDefault(_inherits2);
24
25exports.default = ShellBase;
26
27var _react = require('react');
28
29var _react2 = _interopRequireDefault(_react);
30
31var _classnames12 = require('classnames');
32
33var _classnames13 = _interopRequireDefault(_classnames12);
34
35var _propTypes = require('prop-types');
36
37var _propTypes2 = _interopRequireDefault(_propTypes);
38
39var _reactLifecyclesCompat = require('react-lifecycles-compat');
40
41var _configProvider = require('../config-provider');
42
43var _configProvider2 = _interopRequireDefault(_configProvider);
44
45var _affix = require('../affix');
46
47var _affix2 = _interopRequireDefault(_affix);
48
49var _icon = require('../icon');
50
51var _icon2 = _interopRequireDefault(_icon);
52
53var _util = require('../util');
54
55var _util2 = require('./util');
56
57function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
58
59/**
60 * Shell
61 */
62function ShellBase(props) {
63 var _class, _temp, _initialiseProps;
64
65 var componentName = props.componentName;
66 var Shell = (_temp = _class = function (_Component) {
67 (0, _inherits3.default)(Shell, _Component);
68
69 function Shell(props) {
70 (0, _classCallCheck3.default)(this, Shell);
71
72 var _this = (0, _possibleConstructorReturn3.default)(this, _Component.call(this, props));
73
74 _initialiseProps.call(_this);
75
76 var deviceMap = (0, _util2.getCollapseMap)(props.device);
77 _this.layout = {};
78
79 _this.state = {
80 controll: false,
81 collapseMap: deviceMap,
82 device: props.device
83 };
84 return _this;
85 }
86
87 Shell.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
88 var device = prevState.device;
89
90
91 if (nextProps.device !== device) {
92 var deviceMap = (0, _util2.getCollapseMap)(nextProps.device);
93 return {
94 controll: false,
95 collapseMap: deviceMap,
96 device: nextProps.device
97 };
98 }
99
100 return {};
101 };
102
103 Shell.prototype.componentDidMount = function componentDidMount() {
104 this.checkAsideFixed();
105 };
106
107 Shell.prototype.componentDidUpdate = function componentDidUpdate(prevProps) {
108 var _this2 = this;
109
110 if (prevProps.device !== this.props.device) {
111 var deviceMapBefore = (0, _util2.getCollapseMap)(prevProps.device);
112 var deviceMapAfter = (0, _util2.getCollapseMap)(this.props.device);
113
114 Object.keys(deviceMapAfter).forEach(function (block) {
115 var _ref = _this2.layout[block] || {},
116 props = _ref.props;
117
118 if (deviceMapBefore[block] !== deviceMapAfter[block]) {
119 if (props && typeof props.onCollapseChange === 'function') {
120 props.onCollapseChange(deviceMapAfter[block]);
121 }
122 }
123 });
124 }
125
126 setTimeout(function () {
127 // 如果左侧边栏固定
128 _this2.checkAsideFixed();
129 }, 201);
130 };
131
132 Shell.prototype.render = function render() {
133 return this.renderShell(this.props);
134 };
135
136 return Shell;
137 }(_react.Component), _class.displayName = componentName, _class._typeMark = componentName, _class.propTypes = (0, _extends4.default)({}, _configProvider2.default.propTypes, {
138 prefix: _propTypes2.default.string,
139 /**
140 * 设备类型
141 * @enumdesc 手机, 平板, PC电脑
142 */
143 device: _propTypes2.default.oneOf(['phone', 'tablet', 'desktop']),
144 /**
145 * 设备类型
146 * @enumdesc 浅色, 深色, 主题色
147 */
148 type: _propTypes2.default.oneOf(['light', 'dark', 'brand']),
149 /**
150 * 是否固定 header, 用sticky实现,IE下降级为Affix
151 */
152 fixedHeader: _propTypes2.default.bool
153 }), _class.defaultProps = {
154 prefix: 'next-',
155 device: 'desktop',
156 type: 'light',
157 fixedHeader: false
158 }, _initialiseProps = function _initialiseProps() {
159 var _this3 = this;
160
161 this.checkAsideFixed = function () {
162 var fixedHeader = _this3.props.fixedHeader;
163
164
165 if (!fixedHeader) {
166 return;
167 }
168
169 var headerHeight = void 0;
170 if (_this3.headerRef && (_this3.navigationFixed || _this3.toolDockFixed)) {
171 headerHeight = _util.dom.getStyle(_this3.headerRef, 'height');
172 }
173
174 if (_this3.navigationFixed) {
175 var style = {};
176 style.marginLeft = _util.dom.getStyle(_this3.navRef, 'width');
177 _util.dom.addClass(_this3.navRef, 'fixed');
178 headerHeight && _util.dom.setStyle(_this3.navRef, { top: headerHeight });
179 _util.dom.setStyle(_this3.localNavRef || _this3.submainRef, style);
180 }
181
182 if (_this3.toolDockFixed) {
183 var _style = {};
184 _style.marginRight = _util.dom.getStyle(_this3.toolDockRef, 'width');
185 _util.dom.addClass(_this3.toolDockRef, 'fixed');
186 headerHeight && _util.dom.setStyle(_this3.toolDockRef, { top: headerHeight });
187 _util.dom.setStyle(_this3.localNavRef || _this3.submainRef, _style);
188 }
189 };
190
191 this.setChildCollapse = function (child, mark) {
192 var _state = _this3.state,
193 device = _state.device,
194 collapseMap = _state.collapseMap,
195 controll = _state.controll;
196 var collapse = child.props.collapse;
197
198 var deviceMap = (0, _util2.getCollapseMap)(device);
199 var props = {};
200
201 // 非受控模式
202 if ((0, _util2.isBoolean)(collapse) === false) {
203 props.collapse = controll ? collapseMap[mark] : deviceMap[mark];
204 // props.collapse = collapseMap[mark];
205 }
206
207 if (device !== 'phone' && mark === 'Navigation') {
208 props.miniable = true;
209 }
210
211 return _react2.default.cloneElement(child, props);
212 };
213
214 this.toggleAside = function (mark, props, e) {
215 var _extends2;
216
217 var _state2 = _this3.state,
218 device = _state2.device,
219 collapseMap = _state2.collapseMap;
220
221 var deviceMap = (0, _util2.getCollapseMap)(device);
222 var current = props.collapse;
223
224 var newCollapseMap = (0, _extends4.default)({}, deviceMap, collapseMap, (_extends2 = {}, _extends2[mark] = !current, _extends2));
225 _this3.setState({
226 controll: true,
227 collapseMap: newCollapseMap
228 });
229
230 if (props && typeof props.onCollapseChange === 'function') {
231 props.onCollapseChange(newCollapseMap[mark]);
232 }
233
234 var children = _this3.props.children;
235
236 var com = void 0;
237 if (mark === 'Navigation') {
238 com = children.filter(function (child) {
239 return child && child.type._typeMark.replace('Shell_', '') === mark && child.props.direction !== 'hoz';
240 }).pop();
241 } else {
242 com = children.filter(function (child) {
243 return child && child.type._typeMark.replace('Shell_', '') === mark;
244 }).pop();
245 }
246
247 var _com$props$triggerPro = com.props.triggerProps,
248 triggerProps = _com$props$triggerPro === undefined ? {} : _com$props$triggerPro;
249
250
251 if (typeof triggerProps.onClick === 'function') {
252 triggerProps.onClick(e, _this3.state.collapseMap[mark]);
253 }
254 };
255
256 this.toggleNavigation = function (e) {
257 var mark = 'Navigation';
258 var props = _this3.layout[mark].props;
259
260
261 if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) {
262 return;
263 }
264
265 _this3.toggleAside(mark, props, e);
266 };
267
268 this.toggleLocalNavigation = function (e) {
269 var mark = 'LocalNavigation';
270 var props = _this3.layout[mark].props;
271
272
273 if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) {
274 return;
275 }
276
277 _this3.toggleAside(mark, props, e);
278 };
279
280 this.toggleAncillary = function (e) {
281 var mark = 'Ancillary';
282 var props = _this3.layout[mark].props;
283
284
285 if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) {
286 return;
287 }
288
289 _this3.toggleAside(mark, props, e);
290 };
291
292 this.toggleToolDock = function (e) {
293 var mark = 'ToolDock';
294 var props = _this3.layout[mark].props;
295
296
297 if ('keyCode' in e && e.keyCode !== _util.KEYCODE.ENTER) {
298 return;
299 }
300
301 _this3.toggleAside(mark, props, e);
302 };
303
304 this.saveHeaderRef = function (ref) {
305 _this3.headerRef = ref;
306 };
307
308 this.saveLocalNavRef = function (ref) {
309 _this3.localNavRef = ref;
310 };
311
312 this.saveNavRef = function (ref) {
313 _this3.navRef = ref;
314 };
315
316 this.saveSubmainRef = function (ref) {
317 _this3.submainRef = ref;
318 };
319
320 this.saveToolDockRef = function (ref) {
321 _this3.toolDockRef = ref;
322 };
323
324 this.renderShell = function (props) {
325 var _classnames, _classnames2, _classnames3, _classnames4, _classnames5, _classnames6, _classnames7, _classnames11;
326
327 var prefix = props.prefix,
328 children = props.children,
329 className = props.className,
330 type = props.type,
331 fixedHeader = props.fixedHeader,
332 others = (0, _objectWithoutProperties3.default)(props, ['prefix', 'children', 'className', 'type', 'fixedHeader']);
333 var device = _this3.state.device;
334
335
336 var layout = {};
337 layout.header = {};
338 var hasToolDock = false,
339 needNavigationTrigger = false,
340 needDockTrigger = false;
341
342 _react2.default.Children.map(children, function (child) {
343 if (child && typeof child.type === 'function') {
344 var mark = child.type._typeMark.replace('Shell_', '');
345 switch (mark) {
346 case 'Branding':
347 case 'Action':
348 layout.header[mark] = child;
349 break;
350 case 'MultiTask':
351 layout.taskHeader = child;
352 break;
353 case 'LocalNavigation':
354 if (!layout[mark]) {
355 layout[mark] = [];
356 }
357 layout[mark] = _this3.setChildCollapse(child, mark);
358 break;
359 case 'Ancillary':
360 if (!layout[mark]) {
361 layout[mark] = [];
362 }
363
364 layout[mark] = _this3.setChildCollapse(child, mark);
365 break;
366 case 'ToolDock':
367 hasToolDock = true;
368
369 if (!layout[mark]) {
370 layout[mark] = [];
371 }
372
373 _this3.toolDockFixed = child.props.fixed;
374 var childT = _this3.setChildCollapse(child, mark);
375 layout[mark] = childT;
376
377 break;
378 case 'AppBar':
379 case 'Content':
380 case 'Footer':
381 layout.content || (layout.content = []);
382 layout.content.push(child);
383 break;
384 case 'Page':
385 layout.page || (layout.page = []);
386 layout.page = child;
387 break;
388 case 'Navigation':
389 if (child.props.direction === 'hoz') {
390 layout.header[mark] = child;
391 } else {
392 if (!layout[mark]) {
393 layout[mark] = [];
394 }
395
396 needNavigationTrigger = true;
397 _this3.navigationFixed = child.props.fixed;
398 var childN = _this3.setChildCollapse(child, mark);
399 layout[mark] = childN;
400 }
401 break;
402 default:
403 break;
404 }
405 }
406 });
407
408 var headerCls = (0, _classnames13.default)((_classnames = {}, _classnames[prefix + 'shell-header'] = true, _classnames[prefix + 'shell-fixed-header'] = fixedHeader, _classnames));
409
410 var mainCls = (0, _classnames13.default)((_classnames2 = {}, _classnames2[prefix + 'shell-main'] = true, _classnames2));
411
412 var pageCls = (0, _classnames13.default)((_classnames3 = {}, _classnames3[prefix + 'shell-page'] = true, _classnames3));
413
414 var submainCls = (0, _classnames13.default)((_classnames4 = {}, _classnames4[prefix + 'shell-sub-main'] = true, _classnames4));
415
416 var asideCls = (0, _classnames13.default)((_classnames5 = {}, _classnames5[prefix + 'shell-aside'] = true, _classnames5));
417
418 var toolDockCls = (0, _classnames13.default)((_classnames6 = {}, _classnames6[prefix + 'aside-tooldock'] = true, _classnames6));
419
420 var navigationCls = (0, _classnames13.default)((_classnames7 = {}, _classnames7[prefix + 'aside-navigation'] = true, _classnames7[prefix + 'shell-collapse'] = layout.Navigation && layout.Navigation.props.collapse, _classnames7));
421
422 if (hasToolDock) {
423 if (device === 'phone') {
424 needDockTrigger = true;
425 }
426 }
427
428 // 如果存在垂直模式的 Navigation, 则需要在 Branding 上出现 trigger
429 if (needNavigationTrigger) {
430 var branding = layout.header.Branding;
431 var _layout$Navigation$pr = layout.Navigation.props,
432 trigger = _layout$Navigation$pr.trigger,
433 collapse = _layout$Navigation$pr.collapse;
434
435
436 if ('trigger' in layout.Navigation.props) {
437 trigger = trigger && _react2.default.cloneElement(trigger, {
438 onClick: _this3.toggleNavigation,
439 'aria-expanded': !collapse
440 }) || trigger;
441 } else {
442 trigger = _react2.default.createElement(
443 'div',
444 {
445 key: 'nav-trigger',
446 role: 'button',
447 tabIndex: 0,
448 'aria-expanded': !collapse,
449 'aria-label': 'toggle',
450 className: 'nav-trigger',
451 onClick: _this3.toggleNavigation,
452 onKeyDown: _this3.toggleNavigation
453 },
454 collapse ? _react2.default.createElement(_icon2.default, { size: 'small', type: 'toggle-right' }) : _react2.default.createElement(_icon2.default, { size: 'small', type: 'toggle-left' })
455 );
456 }
457
458 if (!branding) {
459 trigger && (layout.header.Branding = trigger);
460 } else {
461 layout.header.Branding = _react2.default.cloneElement(branding, {}, [trigger, branding.props.children]);
462 }
463 }
464
465 // 如果存在 toolDock, 则需要在 Action 上出现 trigger
466 if (needDockTrigger) {
467 var action = layout.header.Action;
468 var _layout$ToolDock$prop = layout.ToolDock.props,
469 _trigger = _layout$ToolDock$prop.trigger,
470 _collapse = _layout$ToolDock$prop.collapse;
471
472
473 if ('trigger' in layout.ToolDock.props) {
474 _trigger = _trigger && _react2.default.cloneElement(_trigger, {
475 onClick: _this3.toggleToolDock,
476 'aria-expanded': !_collapse
477 }) || _trigger;
478 } else {
479 _trigger = _react2.default.createElement(
480 'div',
481 {
482 key: 'dock-trigger',
483 tabIndex: 0,
484 role: 'button',
485 'aria-expanded': !_collapse,
486 'aria-label': 'toggle',
487 className: 'dock-trigger',
488 onClick: _this3.toggleToolDock,
489 onKeyDown: _this3.toggleToolDock
490 },
491 _react2.default.createElement(_icon2.default, { size: 'small', type: 'add' })
492 );
493 }
494
495 if (!action) {
496 layout.header.Action = _trigger;
497 } else {
498 layout.header.Action = _react2.default.cloneElement(action, {}, [action.props.children, _trigger]);
499 }
500 }
501
502 var headerDom = [],
503 contentArr = [],
504 innerArr = [],
505 taskHeaderDom = null;
506
507 if (layout.taskHeader) {
508 var _classnames8;
509
510 var taskHeaderCls = (0, _classnames13.default)((_classnames8 = {}, _classnames8[prefix + 'shell-task-header'] = true, _classnames8));
511
512 taskHeaderDom = _react2.default.createElement(
513 'section',
514 { key: 'task-header', className: taskHeaderCls },
515 layout.taskHeader
516 );
517 }
518
519 // 按照dom结构,innerArr 包括 LocalNavigation content Ancillary
520 if (layout.LocalNavigation) {
521 var _classnames9;
522
523 var _layout$LocalNavigati = layout.LocalNavigation.props,
524 _trigger2 = _layout$LocalNavigati.trigger,
525 _collapse2 = _layout$LocalNavigati.collapse;
526
527
528 if ('trigger' in layout.LocalNavigation.props) {
529 _trigger2 = _trigger2 && _react2.default.cloneElement(_trigger2, {
530 onClick: _this3.toggleLocalNavigation,
531 'aria-expanded': !_collapse2
532 }) || _trigger2;
533 } else {
534 _trigger2 = _react2.default.createElement(
535 'div',
536 {
537 key: 'local-nav-trigger',
538 role: 'button',
539 tabIndex: 0,
540 'aria-expanded': !_collapse2,
541 'aria-label': 'toggle',
542 className: 'local-nav-trigger aside-trigger',
543 onClick: _this3.toggleLocalNavigation,
544 onKeyDown: _this3.toggleLocalNavigation
545 },
546 _collapse2 ? _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-right' }) : _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-left' })
547 );
548 }
549
550 var localNavCls = (0, _classnames13.default)(asideCls, (_classnames9 = {}, _classnames9[prefix + 'aside-localnavigation'] = true, _classnames9));
551
552 innerArr.push(_react2.default.createElement(
553 'aside',
554 { key: 'localnavigation', className: localNavCls, ref: _this3.saveLocalNavRef },
555 _react2.default.cloneElement(layout.LocalNavigation, {}, [_react2.default.createElement(
556 'div',
557 { key: 'wrapper', className: prefix + 'shell-content-wrapper' },
558 layout.LocalNavigation.props.children
559 ), _trigger2])
560 ));
561 }
562
563 if (layout.content) {
564 innerArr.push(_react2.default.createElement(
565 'section',
566 { key: 'submain', className: submainCls, ref: _this3.saveSubmainRef },
567 layout.content
568 ));
569 }
570
571 if (layout.Ancillary) {
572 var _classnames10;
573
574 var _layout$Ancillary$pro = layout.Ancillary.props,
575 _trigger3 = _layout$Ancillary$pro.trigger,
576 _collapse3 = _layout$Ancillary$pro.collapse;
577
578
579 if ('trigger' in layout.Ancillary.props) {
580 _trigger3 = _trigger3 && _react2.default.cloneElement(_trigger3, {
581 onClick: _this3.toggleAncillary,
582 'aria-expanded': !_collapse3
583 }) || _trigger3;
584 } else {
585 _trigger3 = _react2.default.createElement(
586 'div',
587 {
588 key: 'ancillary-trigger',
589 role: 'button',
590 tabIndex: 0,
591 'aria-expanded': !_collapse3,
592 'aria-label': 'toggle',
593 className: 'ancillary-trigger aside-trigger',
594 onClick: _this3.toggleAncillary,
595 onKeyDown: _this3.toggleAncillary
596 },
597 _collapse3 ? _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-left' }) : _react2.default.createElement(_icon2.default, { size: 'small', type: 'arrow-right' })
598 );
599 }
600
601 var ancillaryCls = (0, _classnames13.default)(asideCls, (_classnames10 = {}, _classnames10[prefix + 'aside-ancillary'] = true, _classnames10));
602
603 innerArr.push(_react2.default.createElement(
604 'aside',
605 { key: 'ancillary', className: ancillaryCls },
606 _react2.default.cloneElement(layout.Ancillary, {}, [_react2.default.createElement(
607 'div',
608 { key: 'wrapper', className: prefix + 'shell-content-wrapper' },
609 layout.Ancillary.props.children
610 ), _trigger3])
611 ));
612 }
613
614 // 按照dom结构, arr 包括 header Navigation ToolDock 和 innerArr
615 if (Object.keys(layout.header).length > 0) {
616 var _dom = _react2.default.createElement(
617 'header',
618 { key: 'header', className: headerCls, ref: _this3.saveHeaderRef },
619 layout.header.Branding,
620 layout.header.Navigation,
621 layout.header.Action
622 );
623 if (fixedHeader && _util.env.ieVersion) {
624 headerDom = _react2.default.createElement(
625 _affix2.default,
626 { style: { zIndex: 9 } },
627 _dom
628 );
629 } else {
630 headerDom = _dom;
631 }
632 }
633
634 layout.Navigation && contentArr.push(_react2.default.createElement(
635 'aside',
636 { key: 'navigation', className: navigationCls, ref: _this3.saveNavRef },
637 _react2.default.cloneElement(layout.Navigation, {
638 className: (0, _classnames13.default)(asideCls, layout.Navigation.props.className)
639 })
640 ));
641
642 // const contentArea = innerArr.length > 0
643 // ? <section key="main" className={mainCls}>{innerArr}</section>
644 // : layout.page;
645
646 // contentArr.push(contentArea);
647 contentArr = contentArr.concat(innerArr.length > 0 ? innerArr : [_react2.default.createElement(
648 'section',
649 { key: 'page', ref: _this3.saveSubmainRef, className: submainCls },
650 layout.page
651 )]);
652
653 layout.ToolDock && contentArr.push(_react2.default.createElement(
654 'aside',
655 { key: 'tooldock', className: toolDockCls, ref: _this3.saveToolDockRef },
656 _react2.default.cloneElement(layout.ToolDock, {
657 className: (0, _classnames13.default)(asideCls, layout.ToolDock.props.className),
658 key: 'tooldock'
659 })
660 ));
661
662 var cls = (0, _classnames13.default)((_classnames11 = {}, _classnames11[prefix + 'shell'] = true, _classnames11[prefix + 'shell-' + device] = true, _classnames11[prefix + 'shell-' + type] = true, _classnames11[className] = !!className, _classnames11));
663
664 if (componentName === 'Page') {
665 return _react2.default.createElement(
666 'section',
667 { className: pageCls },
668 children
669 );
670 }
671
672 _this3.layout = layout;
673
674 return _react2.default.createElement(
675 'section',
676 (0, _extends4.default)({ className: cls }, others),
677 headerDom,
678 taskHeaderDom,
679 _react2.default.createElement(
680 'section',
681 { className: mainCls },
682 contentArr
683 )
684 );
685 };
686 }, _temp);
687 Shell.displayName = 'Shell';
688
689
690 return (0, _reactLifecyclesCompat.polyfill)(Shell);
691}
692module.exports = exports['default'];
\No newline at end of file