@arcblock/ux 1.17.13 → 1.17.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,15 +9,15 @@ var _react = _interopRequireWildcard(require("react"));
9
9
 
10
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
12
- var _styledComponents = _interopRequireDefault(require("styled-components"));
13
-
14
12
  var _clsx = _interopRequireDefault(require("clsx"));
15
13
 
16
- require("./style.css");
14
+ var _ExpandMore = _interopRequireDefault(require("@material-ui/icons/ExpandMore"));
15
+
16
+ var _style = require("./style");
17
17
 
18
- const _excluded = ["items", "orientation", "children", "defaultActiveId", "textColor", "activeTextColor", "bgColor"],
18
+ const _excluded = ["items", "mode", "children", "defaultActiveId", "textColor", "activeTextColor", "bgColor", "onSelected"],
19
19
  _excluded2 = ["id", "icon", "label", "active", "onClick"],
20
- _excluded3 = ["id", "icon", "label", "children"];
20
+ _excluded3 = ["id", "icon", "label", "children", "expandIcon"];
21
21
 
22
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
23
 
@@ -60,12 +60,13 @@ function NavMenu(_ref) {
60
60
 
61
61
  let {
62
62
  items,
63
- orientation,
63
+ mode,
64
64
  children,
65
65
  defaultActiveId,
66
66
  textColor,
67
67
  activeTextColor,
68
- bgColor
68
+ bgColor,
69
+ onSelected
69
70
  } = _ref,
70
71
  rest = _objectWithoutProperties(_ref, _excluded);
71
72
 
@@ -82,10 +83,12 @@ function NavMenu(_ref) {
82
83
  });
83
84
  const contextValue = (0, _react.useMemo)(() => {
84
85
  return _objectSpread(_objectSpread({}, state), {}, {
86
+ mode,
85
87
  activate: id => {
86
88
  setState(prev => _objectSpread(_objectSpread({}, prev), {}, {
87
89
  activeId: id
88
90
  }));
91
+ onSelected === null || onSelected === void 0 ? void 0 : onSelected(id);
89
92
  },
90
93
  open: id => {
91
94
  setState(prev => _objectSpread(_objectSpread({}, prev), {}, {
@@ -99,7 +102,7 @@ function NavMenu(_ref) {
99
102
  }
100
103
  });
101
104
  }, [state]);
102
- const classes = (0, _clsx.default)('navmenu', "navmenu--".concat(orientation), rest.className);
105
+ const classes = (0, _clsx.default)('navmenu', "navmenu--".concat(mode), rest.className);
103
106
 
104
107
  const renderItem = (item, index) => {
105
108
  if (item.children) {
@@ -124,9 +127,10 @@ function NavMenu(_ref) {
124
127
  );
125
128
  };
126
129
 
130
+ const StyledRoot = mode === 'inline' ? _style.InlineStyle : _style.HorizontalStyle;
127
131
  return /*#__PURE__*/_react.default.createElement(NavMenuContext.Provider, {
128
132
  value: contextValue
129
- }, /*#__PURE__*/_react.default.createElement(Root, Object.assign({}, rest, {
133
+ }, /*#__PURE__*/_react.default.createElement(StyledRoot, Object.assign({}, rest, {
130
134
  className: classes,
131
135
  $textColor: textColor,
132
136
  $activeTextColor: activeTextColor,
@@ -138,33 +142,30 @@ function NavMenu(_ref) {
138
142
 
139
143
  NavMenu.propTypes = {
140
144
  items: _propTypes.default.array,
141
- // 默认水平方向布局
142
- orientation: _propTypes.default.oneOf(['horizontal', 'vertical']),
145
+ // 默认水平方向布局,
146
+ // inline 模式: 垂直布局, 且通过 click 事件来收缩/伸展子菜单, 适用于移动端
147
+ mode: _propTypes.default.oneOf(['horizontal', 'vertical', 'inline']),
143
148
  children: _propTypes.default.array,
144
149
  defaultActiveId: _propTypes.default.string,
145
150
  textColor: _propTypes.default.string,
146
151
  activeTextColor: _propTypes.default.string,
147
- bgColor: _propTypes.default.string
152
+ bgColor: _propTypes.default.string,
153
+ onSelected: _propTypes.default.func
148
154
  };
149
155
  NavMenu.defaultProps = {
150
156
  items: null,
151
- orientation: 'horizontal',
157
+ mode: 'horizontal',
152
158
  children: null,
153
159
  defaultActiveId: null,
154
160
  textColor: '#9397a1',
155
161
  activeTextColor: '#25292f',
156
- bgColor: '#fff'
162
+ bgColor: '#fff',
163
+ onSelected: null
157
164
  };
158
-
159
- const Root = _styledComponents.default.nav.withConfig({
160
- displayName: "nav-menu__Root",
161
- componentId: "sc-1atwjw0-0"
162
- })(["--text-color:", ";--active-text-color:", ";--bg-color:", ";padding:8px 16px;background-color:var(--bg-color);font-size:14px;ul{list-style:none;margin:0;padding:0;}.navmenu-item,.navmenu-item a,.navmenu-sub{color:var(--text-color);}.navmenu-item--active,.navmenu-item:hover,.navmenu-item:hover a,.navmenu-item--active a,.navmenu-sub--opened{color:var(--active-text-color);}"], props => props.$textColor, props => props.$activeTextColor, props => props.$bgColor);
163
165
  /**
164
166
  * Item
165
167
  */
166
168
 
167
-
168
169
  function Item(_ref2) {
169
170
  let {
170
171
  id: _id,
@@ -195,14 +196,18 @@ function Item(_ref2) {
195
196
  activate(id);
196
197
  };
197
198
 
198
- return /*#__PURE__*/_react.default.createElement(ItemRoot, Object.assign({}, rest, {
199
- className: classes,
200
- onClick: handleClick
201
- }), icon && /*#__PURE__*/_react.default.createElement("span", {
202
- className: "navmenu-item-icon"
203
- }, icon), /*#__PURE__*/_react.default.createElement("span", {
204
- className: "navmenu-item-content"
205
- }, label));
199
+ return (
200
+ /*#__PURE__*/
201
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
202
+ _react.default.createElement("li", Object.assign({}, rest, {
203
+ className: classes,
204
+ onClick: handleClick
205
+ }), icon && /*#__PURE__*/_react.default.createElement("span", {
206
+ className: "navmenu-item-icon"
207
+ }, icon), /*#__PURE__*/_react.default.createElement("span", {
208
+ className: "navmenu-item-label"
209
+ }, label))
210
+ );
206
211
  }
207
212
 
208
213
  Item.propTypes = {
@@ -221,22 +226,17 @@ Item.defaultProps = {
221
226
  active: false,
222
227
  onClick: null
223
228
  };
224
-
225
- const ItemRoot = _styledComponents.default.li.withConfig({
226
- displayName: "nav-menu__ItemRoot",
227
- componentId: "sc-1atwjw0-1"
228
- })(["position:relative;cursor:pointer;a{text-decoration:none;white-space:nowrap;}a::before{position:absolute;top:0;right:0;bottom:0;left:0;background-color:transparent;content:'';}"]);
229
229
  /**
230
230
  * Sub
231
231
  */
232
232
 
233
-
234
233
  function Sub(_ref3) {
235
234
  let {
236
235
  id: _id,
237
236
  icon,
238
237
  label,
239
- children
238
+ children,
239
+ expandIcon
240
240
  } = _ref3,
241
241
  rest = _objectWithoutProperties(_ref3, _excluded3);
242
242
 
@@ -244,22 +244,38 @@ function Sub(_ref3) {
244
244
  const {
245
245
  openedIds,
246
246
  open,
247
- close
247
+ close,
248
+ mode
248
249
  } = (0, _react.useContext)(NavMenuContext);
250
+ const isOpen = openedIds.includes(id);
249
251
  const classes = (0, _clsx.default)('navmenu-sub', {
250
- 'navmenu-sub--opened': openedIds.includes(id)
252
+ 'navmenu-sub--opened': isOpen
251
253
  }, rest.className);
252
- return /*#__PURE__*/_react.default.createElement(SubRoot, Object.assign({}, rest, {
253
- className: classes,
254
+ const isInlineMode = mode === 'inline'; // inline mode 时使用 click 事件控制收缩/伸展子菜单
255
+
256
+ const props = isInlineMode ? {
257
+ onClick: () => openedIds.includes(id) ? close(id) : open(id)
258
+ } : {
254
259
  onMouseEnter: () => open(id),
255
260
  onMouseLeave: () => close(id)
256
- }), icon && /*#__PURE__*/_react.default.createElement("span", {
261
+ }; // inline mode, 避免点击子菜单项时触发父菜单的 open/close
262
+
263
+ const containerProps = isInlineMode ? {
264
+ onClick: e => e.stopPropagation()
265
+ } : {};
266
+ return /*#__PURE__*/_react.default.createElement("li", Object.assign({}, rest, {
267
+ className: classes
268
+ }, props), icon && /*#__PURE__*/_react.default.createElement("span", {
257
269
  className: "navmenu-sub-icon"
258
270
  }, icon), /*#__PURE__*/_react.default.createElement("span", {
259
- className: "navmenu-sub-content"
260
- }, label), /*#__PURE__*/_react.default.createElement("div", {
271
+ className: "navmenu-sub-label"
272
+ }, label), expandIcon && /*#__PURE__*/_react.default.createElement("span", {
273
+ className: "navmenu-sub-expand-icon"
274
+ }, (expandIcon === null || expandIcon === void 0 ? void 0 : expandIcon({
275
+ isOpen
276
+ })) || expandIcon), /*#__PURE__*/_react.default.createElement("div", Object.assign({
261
277
  className: "navmenu-sub-container"
262
- }, /*#__PURE__*/_react.default.createElement("ul", {
278
+ }, containerProps), /*#__PURE__*/_react.default.createElement("ul", {
263
279
  className: "navmenu-sub-list"
264
280
  }, filterItems(children))));
265
281
  }
@@ -268,18 +284,24 @@ Sub.propTypes = {
268
284
  id: _propTypes.default.string,
269
285
  icon: _propTypes.default.element,
270
286
  label: _propTypes.default.node.isRequired,
271
- children: _propTypes.default.array.isRequired
287
+ children: _propTypes.default.array.isRequired,
288
+ expandIcon: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func])
272
289
  };
273
290
  Sub.defaultProps = {
274
291
  id: null,
275
- icon: null
292
+ icon: null,
293
+ // eslint-disable-next-line react/prop-types
294
+ expandIcon: _ref4 => {
295
+ let {
296
+ isOpen
297
+ } = _ref4;
298
+ return /*#__PURE__*/_react.default.createElement(_ExpandMore.default, {
299
+ style: {
300
+ transform: "rotate(".concat(isOpen ? 180 : 0, "deg)")
301
+ }
302
+ });
303
+ }
276
304
  };
277
-
278
- const SubRoot = _styledComponents.default.li.withConfig({
279
- displayName: "nav-menu__SubRoot",
280
- componentId: "sc-1atwjw0-2"
281
- })(["position:relative;cursor:pointer;.navmenu-sub-container{display:none;position:absolute;}&.navmenu-sub--opened > .navmenu-sub-container{display:block;top:100%;}"]);
282
-
283
305
  NavMenu.Item = Item;
284
306
  NavMenu.Sub = Sub;
285
307
  var _default = NavMenu;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.InlineStyle = exports.HorizontalStyle = void 0;
7
+
8
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ const NavMenuBase = _styledComponents.default.nav.withConfig({
13
+ displayName: "style__NavMenuBase",
14
+ componentId: "sc-2g7isz-0"
15
+ })(["--text-color:", ";--active-text-color:", ";--bg-color:", ";background-color:var(--bg-color);font-size:14px;ul{list-style:none;margin:0;padding:0;}.navmenu-item,.navmenu-sub{display:flex;align-items:center;}.navmenu-item,.navmenu-item a,.navmenu-sub{color:var(--text-color);}.navmenu-item--active,.navmenu-item:hover,.navmenu-item:hover a,.navmenu-item--active a,.navmenu-sub--opened{color:var(--active-text-color);}.navmenu-item{position:relative;cursor:pointer;a{text-decoration:none;white-space:nowrap;}a::before{position:absolute;top:0;right:0;bottom:0;left:0;background-color:transparent;content:'';}}.navmenu-sub{position:relative;cursor:pointer;}.navmenu-item-icon,.navmenu-sub-icon,.navmenu-sub-expand-icon{display:flex;line-height:1;}.navmenu-item-icon,.navmenu-sub-icon{margin-right:4px;}.navmenu-item-icon > *,.navmenu-sub-icon > *{font-size:1.5em;}.navmenu-sub-expand-icon{margin-left:8px;> *{width:0.8em;height:0.8em;transition:transform 0.2s ease-in-out;}}"], props => props.$textColor, props => props.$activeTextColor, props => props.$bgColor);
16
+
17
+ const HorizontalStyle = (0, _styledComponents.default)(NavMenuBase).withConfig({
18
+ displayName: "style__HorizontalStyle",
19
+ componentId: "sc-2g7isz-1"
20
+ })(["padding:8px 16px;.navmenu-root{display:flex;align-items:center;}.navmenu-root > .navmenu-item,.navmenu-root > .navmenu-sub{margin-left:24px;}.navmenu-root > .navmenu-item:first-child,.navmenu-root > .navmenu-sub:first-child{margin-left:0;}.navmenu-sub-container{display:none;position:absolute;top:100%;}.navmenu-sub-list{padding:16px;border-radius:4px;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,0.15);.navmenu-item + .navmenu-item{margin-top:8px;}}.navmenu-root > .navmenu-sub{> .navmenu-sub-container{left:50%;transform:translateX(-50%);padding-top:16px;}&.navmenu-sub--opened > .navmenu-sub-container{display:block;}}"]);
21
+ /* inline mode */
22
+
23
+ exports.HorizontalStyle = HorizontalStyle;
24
+ const InlineStyle = (0, _styledComponents.default)(NavMenuBase).withConfig({
25
+ displayName: "style__InlineStyle",
26
+ componentId: "sc-2g7isz-2"
27
+ })([".navmenu-root{display:flex;flex-direction:column;align-items:stretch;}.navmenu-item,.navmenu-sub{padding:0 16px;}.navmenu-root > .navmenu-item,.navmenu-root > .navmenu-sub{height:48px;line-height:48px;border-bottom:1px solid #eee;}.navmenu-item-icon,.navmenu-sub-icon{width:32px;margin:0;}.navmenu-sub-expand-icon{margin-left:auto;}.navmenu-sub-container{display:none;position:absolute;top:100%;left:0;right:0;.navmenu-item,.navmenu-sub{line-height:24px;}}.navmenu-sub-list{padding-left:16px;.navmenu-item,.navmenu-sub{padding-left:32px;margin-top:8px;font-size:13px;}}.navmenu-root > .navmenu-sub{&.navmenu-sub--opened{background:#eee;}}.navmenu-sub--opened > .navmenu-sub-container{display:block;}"]);
28
+ exports.InlineStyle = InlineStyle;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ux",
3
- "version": "1.17.13",
3
+ "version": "1.17.16",
4
4
  "description": "Common used react components for arcblock products",
5
5
  "keywords": [
6
6
  "react",
@@ -53,10 +53,10 @@
53
53
  "react": ">=16.12.0",
54
54
  "react-ga": "^2.7.0"
55
55
  },
56
- "gitHead": "da903274c188ed5dbb9e318b1495af6faa5ce668",
56
+ "gitHead": "acab741ed856df9b4def509821a1ab6217350625",
57
57
  "dependencies": {
58
- "@arcblock/icons": "^1.17.13",
59
- "@arcblock/react-hooks": "^1.17.13",
58
+ "@arcblock/icons": "^1.17.16",
59
+ "@arcblock/react-hooks": "^1.17.16",
60
60
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
61
61
  "@fontsource/lato": "^4.5.3",
62
62
  "@material-ui/core": "^4.12.3",
@@ -11,6 +11,7 @@ import lottieJson from './default-animation.json';
11
11
  * @param {Number} size 动画的尺寸,单位px
12
12
  * @param {String|Array} message 动画下方的文字;数组情况下会在一定时间切换文案
13
13
  * @param {Number} messageDuration 动画下方的文字为数组时,每个文案的持续时间;默认5000ms
14
+ * @param {Number} messageLoop 动画下方的文字为数组时,文案是否循环播放
14
15
  * @param {Array} tips 底部的提示元素
15
16
  * @param {Number} tipsDuration 底部提示的切换时间,单位毫秒,默认3000ms
16
17
  * @param {Number} speed 动画默认的播放速度
@@ -23,6 +24,7 @@ export default function AnimationWaiter({
23
24
  size,
24
25
  message,
25
26
  messageDuration,
27
+ messageLoop,
26
28
  tips,
27
29
  tipsDuration,
28
30
  maybeDuration,
@@ -36,7 +38,6 @@ export default function AnimationWaiter({
36
38
  // 动画的开始时间
37
39
  const startTime = useRef(new Date().getTime());
38
40
 
39
- // 省略号
40
41
  useEffect(() => {
41
42
  if (!message) {
42
43
  return;
@@ -50,7 +51,11 @@ export default function AnimationWaiter({
50
51
  timer1 = setInterval(() => {
51
52
  msgId++;
52
53
  if (msgId >= message.length) {
53
- msgId = 0;
54
+ if (messageLoop) {
55
+ msgId = 0;
56
+ } else {
57
+ msgId = message.length - 1;
58
+ }
54
59
  }
55
60
  setDesc(message[msgId]);
56
61
  }, messageDuration);
@@ -145,6 +150,7 @@ AnimationWaiter.propTypes = {
145
150
  size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
146
151
  message: PropTypes.any,
147
152
  messageDuration: PropTypes.number,
153
+ messageLoop: PropTypes.bool,
148
154
  tips: PropTypes.array,
149
155
  tipsDuration: PropTypes.number,
150
156
  speed: PropTypes.number,
@@ -157,6 +163,7 @@ AnimationWaiter.defaultProps = {
157
163
  size: '',
158
164
  message: '',
159
165
  messageDuration: 5000,
166
+ messageLoop: true,
160
167
  tips: [],
161
168
  tipsDuration: 5000,
162
169
  speed: 1,
@@ -95,24 +95,24 @@ const Div = styled.div`
95
95
  font-size: 16px;
96
96
  font-weight: 500;
97
97
  line-height: 19px;
98
+ max-height: 19px;
98
99
  overflow: hidden;
99
100
  text-overflow: ellipsis;
100
- display: -webkit-box;
101
- -webkit-line-clamp: 2;
102
- -webkit-box-orient: vertical;
103
- max-height: 38px;
104
- word-break: break-all;
101
+ white-space: nowrap;
105
102
  }
106
103
  .arcblock-blocklet__describe {
107
- margin-top: 2px;
104
+ margin-top: 4px;
108
105
  color: ${props => props.theme.palette.grey[600]};
109
106
  font-size: 14px;
110
107
  font-weight: 500;
111
108
  line-height: 17px;
112
- max-height: 17px;
109
+ max-height: 34px;
113
110
  overflow: hidden;
114
111
  text-overflow: ellipsis;
115
- white-space: nowrap;
112
+ display: -webkit-box;
113
+ -webkit-line-clamp: 2;
114
+ -webkit-box-orient: vertical;
115
+ word-break: break-all;
116
116
  }
117
117
  .arcblock-blocklet__version {
118
118
  color: ${props => props.theme.palette.grey[600]};
@@ -0,0 +1,157 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import Box from '@material-ui/core/Box';
5
+ import Container from '@material-ui/core/Container';
6
+ import useTheme from '@material-ui/core/styles/useTheme';
7
+
8
+ /**
9
+ * Header 组件
10
+ * TODO: Layout/dashboard 可以复用此处的 header
11
+ */
12
+ function Header({
13
+ logo,
14
+ brand,
15
+ brandAddon,
16
+ description,
17
+ children,
18
+ addons,
19
+ prepend,
20
+ containerComponent: ContainerComponent,
21
+ ...rest
22
+ }) {
23
+ const theme = useTheme();
24
+ return (
25
+ <Root {...rest} $theme={theme}>
26
+ <ContainerComponent className="header-container">
27
+ {prepend}
28
+ {logo && <div className="header-logo">{logo}</div>}
29
+ <div className="header-brand">
30
+ <div className="header-brand-title">
31
+ <h2>{brand}</h2>
32
+ <div className="header-brand-addon">{brandAddon}</div>
33
+ </div>
34
+ <div className="header-brand-desc">{description}</div>
35
+ </div>
36
+ {children}
37
+ <Box flexGrow={1} />
38
+ <div className="header-addons">{addons}</div>
39
+ </ContainerComponent>
40
+ </Root>
41
+ );
42
+ }
43
+
44
+ Header.propTypes = {
45
+ logo: PropTypes.node,
46
+ // 相当于 Title
47
+ brand: PropTypes.string,
48
+ // brand 右侧的内容区域, 可显示一个 badge 或 tag
49
+ brandAddon: PropTypes.node,
50
+ // brand 下方的描述
51
+ description: PropTypes.string,
52
+ children: PropTypes.node,
53
+ // 右侧区域, 可以放置 icons/actions/login 等
54
+ addons: PropTypes.node,
55
+ // logo 左侧内容
56
+ prepend: PropTypes.node,
57
+ // 默认使用 mui 的 Container, 如果不想限制 header 内容区域的宽度, 可以设置为 div
58
+ containerComponent: PropTypes.elementType,
59
+ };
60
+
61
+ Header.defaultProps = {
62
+ logo: null,
63
+ brand: null,
64
+ brandAddon: null,
65
+ description: null,
66
+ children: null,
67
+ addons: null,
68
+ prepend: null,
69
+ containerComponent: Container,
70
+ };
71
+
72
+ const Root = styled.div`
73
+ position: relative;
74
+ z-index: ${props => props.$theme.zIndex.drawer + 1};
75
+ font-size: 14px;
76
+ background: ${props => props.$theme.palette.common.white};
77
+ .header-container {
78
+ display: flex;
79
+ align-items: center;
80
+ height: 64px;
81
+ padding: 8px 16px;
82
+ }
83
+ .header-logo {
84
+ display: inline-flex;
85
+ justify-content: center;
86
+ position: relative;
87
+ height: 40px;
88
+ margin-right: 16px;
89
+ img,
90
+ svg {
91
+ width: auto;
92
+ height: 100%;
93
+ }
94
+ > a {
95
+ height: 100%;
96
+ line-height: 1;
97
+ }
98
+ > a::before {
99
+ position: absolute;
100
+ top: 0;
101
+ right: 0;
102
+ bottom: 0;
103
+ left: 0;
104
+ background-color: transparent;
105
+ content: '';
106
+ }
107
+ }
108
+ .header-brand {
109
+ display: flex;
110
+ flex-direction: column;
111
+ flex-shrink: 0;
112
+ margin-right: 16px;
113
+ .header-brand-title {
114
+ display: flex;
115
+ align-items: center;
116
+ h2 {
117
+ font-size: 16px;
118
+ }
119
+ .header-brand-addon {
120
+ margin-left: 8px;
121
+ }
122
+ }
123
+ .header-brand-desc {
124
+ color: #9397a1;
125
+ }
126
+ }
127
+ .header-addons {
128
+ display: flex;
129
+ align-items: center;
130
+ }
131
+ ${props => props.$theme.breakpoints.down('md')} {
132
+ .header-brand {
133
+ margin-right: 12px;
134
+ .header-brand-title {
135
+ h2 {
136
+ font-size: 14px;
137
+ }
138
+ }
139
+ }
140
+ }
141
+ ${props => props.$theme.breakpoints.down('sm')} {
142
+ .header-container {
143
+ height: 56px;
144
+ }
145
+ .header-menu {
146
+ display: inline-block;
147
+ }
148
+ .header-logo {
149
+ height: 32px;
150
+ }
151
+ .header-brand {
152
+ display: none;
153
+ }
154
+ }
155
+ `;
156
+
157
+ export default Header;
@@ -1,156 +1,2 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import styled from 'styled-components';
4
- import Box from '@material-ui/core/Box';
5
- import useTheme from '@material-ui/core/styles/useTheme';
6
- import useMediaQuery from '@material-ui/core/useMediaQuery';
7
- import MenuIcon from '@material-ui/icons/Menu';
8
- import Button from '@material-ui/core/IconButton';
9
-
10
- /**
11
- * Header 组件
12
- * TODO: Layout/dashboard 可以复用此处的 header
13
- */
14
- function Header({
15
- logo,
16
- brand,
17
- brandAddon,
18
- description,
19
- children,
20
- addons,
21
- mobile,
22
- onToggleMenu,
23
- ...rest
24
- }) {
25
- const theme = useTheme();
26
- const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
27
- const _mobile = { ...Header.defaultProps.mobile, ...mobile };
28
- // 暂时不要通过 display: none 隐藏 logo, https://blog.patw.me/archives/1820/inline-svg-same-id-and-display-none-issue/
29
- const hideLogo = isMobile && _mobile.hideLogo;
30
- return (
31
- <Root {...rest} $theme={theme}>
32
- {_mobile.enableMenu && (
33
- <Button color="inherit" edge="start" className="header-menu" onClick={onToggleMenu}>
34
- <MenuIcon />
35
- </Button>
36
- )}
37
- {!hideLogo && <div className="header-logo">{logo}</div>}
38
- <div className="header-brand">
39
- <div className="header-brand-title">
40
- <h2>{brand}</h2>
41
- <div className="header-brand-addon">{brandAddon}</div>
42
- </div>
43
- <div className="header-brand-desc">{description}</div>
44
- </div>
45
- {children}
46
- <Box flexGrow={1} />
47
- <div className="header-addons">{addons}</div>
48
- </Root>
49
- );
50
- }
51
-
52
- Header.propTypes = {
53
- logo: PropTypes.any,
54
- // 相当于 Title
55
- brand: PropTypes.string,
56
- // brand 右侧的内容区域, 可显示一个 badge 或 tag
57
- brandAddon: PropTypes.any,
58
- // brand 下方的描述
59
- description: PropTypes.string,
60
- children: PropTypes.any,
61
- // 右侧区域, 可以放置 icons/actions/login 等
62
- addons: PropTypes.any,
63
- // 窄屏下配置
64
- mobile: PropTypes.shape({
65
- enableMenu: PropTypes.bool,
66
- hideLogo: PropTypes.bool,
67
- }),
68
- onToggleMenu: PropTypes.func,
69
- };
70
-
71
- Header.defaultProps = {
72
- logo: null,
73
- brand: null,
74
- brandAddon: null,
75
- description: null,
76
- children: null,
77
- addons: null,
78
- mobile: { enableMenu: true, hideLogo: true },
79
- onToggleMenu: () => {},
80
- };
81
-
82
- const Root = styled.div`
83
- display: flex;
84
- align-items: center;
85
- position: relative;
86
- z-index: ${props => props.$theme.zIndex.drawer + 1};
87
- height: 64px;
88
- padding: 12px 24px;
89
- font-size: 14px;
90
- background: #fff;
91
- .header-menu {
92
- display: none;
93
- }
94
- .header-logo {
95
- display: inline-flex;
96
- justify-content: center;
97
- position: relative;
98
- height: 40px;
99
- margin-right: 16px;
100
- img,
101
- svg {
102
- width: auto;
103
- height: 100%;
104
- }
105
- > a {
106
- height: 100%;
107
- line-height: 1;
108
- }
109
- > a::before {
110
- position: absolute;
111
- top: 0;
112
- right: 0;
113
- bottom: 0;
114
- left: 0;
115
- background-color: transparent;
116
- content: '';
117
- }
118
- }
119
- .header-brand {
120
- display: flex;
121
- flex-direction: column;
122
- margin-right: 16px;
123
- .header-brand-title {
124
- display: flex;
125
- align-items: center;
126
- h2 {
127
- font-size: 16px;
128
- }
129
- .header-brand-addon {
130
- margin-left: 8px;
131
- }
132
- }
133
- .header-brand-desc {
134
- color: #9397a1;
135
- }
136
- }
137
- .header-addons {
138
- display: flex;
139
- align-items: center;
140
- }
141
- ${props => props.$theme.breakpoints.down('sm')} {
142
- height: 56px;
143
- padding: 8px 16px;
144
- .header-menu {
145
- display: inline-block;
146
- }
147
- .header-logo {
148
- height: 32px;
149
- }
150
- .header-brand {
151
- display: none;
152
- }
153
- }
154
- `;
155
-
156
- export default Header;
1
+ export { default as Header } from './header';
2
+ export { default as ResponsiveHeader } from './responsive-header';