@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.
- package/lib/AnimationWaiter/index.js +11 -4
- package/lib/Blocklet/blocklet.js +1 -1
- package/lib/Header/header.js +100 -0
- package/lib/Header/index.js +15 -116
- package/lib/Header/responsive-header.js +132 -0
- package/lib/NavMenu/nav-menu.js +73 -51
- package/lib/NavMenu/style.js +28 -0
- package/package.json +4 -4
- package/src/AnimationWaiter/index.js +9 -2
- package/src/Blocklet/blocklet.js +8 -8
- package/src/Header/header.js +157 -0
- package/src/Header/index.js +2 -156
- package/src/Header/responsive-header.js +136 -0
- package/src/NavMenu/nav-menu.js +56 -85
- package/src/NavMenu/style.js +182 -0
- package/lib/NavMenu/style.css +0 -48
- package/src/NavMenu/style.css +0 -48
package/lib/NavMenu/nav-menu.js
CHANGED
|
@@ -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("
|
|
14
|
+
var _ExpandMore = _interopRequireDefault(require("@material-ui/icons/ExpandMore"));
|
|
15
|
+
|
|
16
|
+
var _style = require("./style");
|
|
17
17
|
|
|
18
|
-
const _excluded = ["items", "
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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':
|
|
252
|
+
'navmenu-sub--opened': isOpen
|
|
251
253
|
}, rest.className);
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
}
|
|
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-
|
|
260
|
-
}, label), /*#__PURE__*/_react.default.createElement("
|
|
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.
|
|
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": "
|
|
56
|
+
"gitHead": "acab741ed856df9b4def509821a1ab6217350625",
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@arcblock/icons": "^1.17.
|
|
59
|
-
"@arcblock/react-hooks": "^1.17.
|
|
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
|
-
|
|
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,
|
package/src/Blocklet/blocklet.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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:
|
|
109
|
+
max-height: 34px;
|
|
113
110
|
overflow: hidden;
|
|
114
111
|
text-overflow: ellipsis;
|
|
115
|
-
|
|
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;
|
package/src/Header/index.js
CHANGED
|
@@ -1,156 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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';
|