@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
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import MenuIcon from '@material-ui/icons/Menu';
|
|
5
|
+
import Button from '@material-ui/core/IconButton';
|
|
6
|
+
import useTheme from '@material-ui/core/styles/useTheme';
|
|
7
|
+
import useMediaQuery from '@material-ui/core/useMediaQuery';
|
|
8
|
+
import Drawer from '@material-ui/core/Drawer';
|
|
9
|
+
import Header from './header';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ResponsiveHeader
|
|
13
|
+
* - 窄屏下显示 burge menu
|
|
14
|
+
* - 窄屏下将 children 区域显示到 menu 中
|
|
15
|
+
*
|
|
16
|
+
* 注意: 暂时不要通过 display: none 隐藏 logo, https://blog.patw.me/archives/1820/inline-svg-same-id-and-display-none-issue/
|
|
17
|
+
*/
|
|
18
|
+
function ResponsiveHeader({ menu, prepend, children, ...rest }) {
|
|
19
|
+
const theme = useTheme();
|
|
20
|
+
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
|
|
21
|
+
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
22
|
+
const _children =
|
|
23
|
+
typeof children === 'function'
|
|
24
|
+
? children({ isMobile, closeMenu: () => setDrawerOpen(false) })
|
|
25
|
+
: children;
|
|
26
|
+
const { logo, brand, brandAddon, description } = rest;
|
|
27
|
+
// 如果 children 没有值, 则使用普通的 Header 组件渲染 (此时并没有什么内容需要在 menu 中显示)
|
|
28
|
+
if (!children) {
|
|
29
|
+
return <Header prepend={prepend} {...rest} />;
|
|
30
|
+
}
|
|
31
|
+
return (
|
|
32
|
+
<Root
|
|
33
|
+
prepend={
|
|
34
|
+
prepend || (
|
|
35
|
+
<Button
|
|
36
|
+
color="inherit"
|
|
37
|
+
edge="start"
|
|
38
|
+
className="header-menu"
|
|
39
|
+
onClick={() => setDrawerOpen(true)}>
|
|
40
|
+
<MenuIcon />
|
|
41
|
+
</Button>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
{...rest}
|
|
45
|
+
logo={isMobile ? null : logo}
|
|
46
|
+
$theme={theme}>
|
|
47
|
+
{!isMobile && _children}
|
|
48
|
+
{isMobile && (
|
|
49
|
+
<Drawer
|
|
50
|
+
open={drawerOpen}
|
|
51
|
+
onClose={() => setDrawerOpen(false)}
|
|
52
|
+
ModalProps={{ disablePortal: true, keepMounted: true }}>
|
|
53
|
+
<Sidebar>
|
|
54
|
+
<div className="header-sidebar-head">
|
|
55
|
+
<div className="header-sidebar-logo">{logo}</div>
|
|
56
|
+
{brand && <h2>{brand}</h2>}
|
|
57
|
+
{description && <p className="header-sidebar-description">{description}</p>}
|
|
58
|
+
{brandAddon && <div className="header-sidebar-brandaddon">{brandAddon}</div>}
|
|
59
|
+
</div>
|
|
60
|
+
<div className="header-sidebar-content">{_children}</div>
|
|
61
|
+
</Sidebar>
|
|
62
|
+
</Drawer>
|
|
63
|
+
)}
|
|
64
|
+
</Root>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
ResponsiveHeader.propTypes = {
|
|
69
|
+
...Header.PropTypes,
|
|
70
|
+
// 如果是 function, 则
|
|
71
|
+
// - 会传入一个 isMobile 参数, isMobile 为 true 时, 表示 children 会显示在 menu 中, 可以根据 isMobile 参数调整要渲染的内容, 比如如果 isMobile 为 true 则使用 inline 模式的 NavMenu (适用于移动端)
|
|
72
|
+
// - 会传入一个 closeMenu 参数, 可以关闭 menu
|
|
73
|
+
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
ResponsiveHeader.defaultProps = {
|
|
77
|
+
...Header.defaultProps,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const Root = styled(Header)`
|
|
81
|
+
.header-menu {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
${props => props.$theme.breakpoints.down('sm')} {
|
|
85
|
+
.header-menu {
|
|
86
|
+
display: block;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Sidebar
|
|
93
|
+
*/
|
|
94
|
+
const Sidebar = styled.div`
|
|
95
|
+
min-width: 280px;
|
|
96
|
+
font-size: 14px;
|
|
97
|
+
.header-sidebar-head {
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
align-items: center;
|
|
101
|
+
padding: 24px 0;
|
|
102
|
+
border-bottom: 1px solid #eee;
|
|
103
|
+
font-size: 12px;
|
|
104
|
+
.header-sidebar-logo {
|
|
105
|
+
min-width: 44px;
|
|
106
|
+
height: 44px;
|
|
107
|
+
font-size: 44px;
|
|
108
|
+
> * {
|
|
109
|
+
width: auto;
|
|
110
|
+
height: 100%;
|
|
111
|
+
}
|
|
112
|
+
> a {
|
|
113
|
+
display: block;
|
|
114
|
+
}
|
|
115
|
+
img {
|
|
116
|
+
max-width: 100%;
|
|
117
|
+
max-height: 100%;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
h2 {
|
|
121
|
+
margin-top: 12px;
|
|
122
|
+
font-size: 14px;
|
|
123
|
+
}
|
|
124
|
+
.header-sidebar-description {
|
|
125
|
+
margin: 2px 0 0 0;
|
|
126
|
+
}
|
|
127
|
+
.header-sidebar-brandaddon {
|
|
128
|
+
margin-top: 8px;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
.header-sidebar-content {
|
|
132
|
+
padding: 16px 0;
|
|
133
|
+
}
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
export default ResponsiveHeader;
|
package/src/NavMenu/nav-menu.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { createContext, useContext, useMemo, useState, useRef } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import styled from 'styled-components';
|
|
4
3
|
import clsx from 'clsx';
|
|
5
|
-
import '
|
|
4
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
5
|
+
import { HorizontalStyle, InlineStyle } from './style';
|
|
6
6
|
|
|
7
7
|
const NavMenuContext = createContext();
|
|
8
8
|
|
|
@@ -26,12 +26,13 @@ function useUniqueId(id) {
|
|
|
26
26
|
*/
|
|
27
27
|
function NavMenu({
|
|
28
28
|
items,
|
|
29
|
-
|
|
29
|
+
mode,
|
|
30
30
|
children,
|
|
31
31
|
defaultActiveId,
|
|
32
32
|
textColor,
|
|
33
33
|
activeTextColor,
|
|
34
34
|
bgColor,
|
|
35
|
+
onSelected,
|
|
35
36
|
...rest
|
|
36
37
|
}) {
|
|
37
38
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -43,8 +44,10 @@ function NavMenu({
|
|
|
43
44
|
const contextValue = useMemo(() => {
|
|
44
45
|
return {
|
|
45
46
|
...state,
|
|
47
|
+
mode,
|
|
46
48
|
activate: id => {
|
|
47
49
|
setState(prev => ({ ...prev, activeId: id }));
|
|
50
|
+
onSelected?.(id);
|
|
48
51
|
},
|
|
49
52
|
open: id => {
|
|
50
53
|
setState(prev => ({ ...prev, openedIds: [...prev.openedIds, id] }));
|
|
@@ -54,7 +57,7 @@ function NavMenu({
|
|
|
54
57
|
},
|
|
55
58
|
};
|
|
56
59
|
}, [state]);
|
|
57
|
-
const classes = clsx('navmenu', `navmenu--${
|
|
60
|
+
const classes = clsx('navmenu', `navmenu--${mode}`, rest.className);
|
|
58
61
|
const renderItem = (item, index) => {
|
|
59
62
|
if (item.children) {
|
|
60
63
|
return (
|
|
@@ -68,67 +71,44 @@ function NavMenu({
|
|
|
68
71
|
<Item key={index} id={item.id} icon={item.icon} label={item.label} active={item.active} />
|
|
69
72
|
);
|
|
70
73
|
};
|
|
74
|
+
const StyledRoot = mode === 'inline' ? InlineStyle : HorizontalStyle;
|
|
71
75
|
return (
|
|
72
76
|
<NavMenuContext.Provider value={contextValue}>
|
|
73
|
-
<
|
|
77
|
+
<StyledRoot
|
|
74
78
|
{...rest}
|
|
75
79
|
className={classes}
|
|
76
80
|
$textColor={textColor}
|
|
77
81
|
$activeTextColor={activeTextColor}
|
|
78
82
|
$bgColor={bgColor}>
|
|
79
83
|
<ul className="navmenu-root">{items ? items.map(renderItem) : children}</ul>
|
|
80
|
-
</
|
|
84
|
+
</StyledRoot>
|
|
81
85
|
</NavMenuContext.Provider>
|
|
82
86
|
);
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
NavMenu.propTypes = {
|
|
86
90
|
items: PropTypes.array,
|
|
87
|
-
//
|
|
88
|
-
|
|
91
|
+
// 默认水平方向布局,
|
|
92
|
+
// inline 模式: 垂直布局, 且通过 click 事件来收缩/伸展子菜单, 适用于移动端
|
|
93
|
+
mode: PropTypes.oneOf(['horizontal', 'vertical', 'inline']),
|
|
89
94
|
children: PropTypes.array,
|
|
90
95
|
defaultActiveId: PropTypes.string,
|
|
91
96
|
textColor: PropTypes.string,
|
|
92
97
|
activeTextColor: PropTypes.string,
|
|
93
98
|
bgColor: PropTypes.string,
|
|
99
|
+
onSelected: PropTypes.func,
|
|
94
100
|
};
|
|
95
101
|
NavMenu.defaultProps = {
|
|
96
102
|
items: null,
|
|
97
|
-
|
|
103
|
+
mode: 'horizontal',
|
|
98
104
|
children: null,
|
|
99
105
|
defaultActiveId: null,
|
|
100
106
|
textColor: '#9397a1',
|
|
101
107
|
activeTextColor: '#25292f',
|
|
102
108
|
bgColor: '#fff',
|
|
109
|
+
onSelected: null,
|
|
103
110
|
};
|
|
104
111
|
|
|
105
|
-
const Root = styled.nav`
|
|
106
|
-
--text-color: ${props => props.$textColor};
|
|
107
|
-
--active-text-color: ${props => props.$activeTextColor};
|
|
108
|
-
--bg-color: ${props => props.$bgColor};
|
|
109
|
-
|
|
110
|
-
padding: 8px 16px;
|
|
111
|
-
background-color: var(--bg-color);
|
|
112
|
-
font-size: 14px;
|
|
113
|
-
ul {
|
|
114
|
-
list-style: none;
|
|
115
|
-
margin: 0;
|
|
116
|
-
padding: 0;
|
|
117
|
-
}
|
|
118
|
-
.navmenu-item,
|
|
119
|
-
.navmenu-item a,
|
|
120
|
-
.navmenu-sub {
|
|
121
|
-
color: var(--text-color);
|
|
122
|
-
}
|
|
123
|
-
.navmenu-item--active,
|
|
124
|
-
.navmenu-item:hover,
|
|
125
|
-
.navmenu-item:hover a,
|
|
126
|
-
.navmenu-item--active a,
|
|
127
|
-
.navmenu-sub--opened {
|
|
128
|
-
color: var(--active-text-color);
|
|
129
|
-
}
|
|
130
|
-
`;
|
|
131
|
-
|
|
132
112
|
/**
|
|
133
113
|
* Item
|
|
134
114
|
*/
|
|
@@ -146,10 +126,11 @@ function Item({ id: _id, icon, label, active, onClick, ...rest }) {
|
|
|
146
126
|
activate(id);
|
|
147
127
|
};
|
|
148
128
|
return (
|
|
149
|
-
|
|
129
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
130
|
+
<li {...rest} className={classes} onClick={handleClick}>
|
|
150
131
|
{icon && <span className="navmenu-item-icon">{icon}</span>}
|
|
151
|
-
<span className="navmenu-item-
|
|
152
|
-
</
|
|
132
|
+
<span className="navmenu-item-label">{label}</span>
|
|
133
|
+
</li>
|
|
153
134
|
);
|
|
154
135
|
}
|
|
155
136
|
|
|
@@ -171,47 +152,39 @@ Item.defaultProps = {
|
|
|
171
152
|
onClick: null,
|
|
172
153
|
};
|
|
173
154
|
|
|
174
|
-
const ItemRoot = styled.li`
|
|
175
|
-
position: relative;
|
|
176
|
-
cursor: pointer;
|
|
177
|
-
a {
|
|
178
|
-
text-decoration: none;
|
|
179
|
-
white-space: nowrap;
|
|
180
|
-
}
|
|
181
|
-
a::before {
|
|
182
|
-
position: absolute;
|
|
183
|
-
top: 0;
|
|
184
|
-
right: 0;
|
|
185
|
-
bottom: 0;
|
|
186
|
-
left: 0;
|
|
187
|
-
background-color: transparent;
|
|
188
|
-
content: '';
|
|
189
|
-
}
|
|
190
|
-
`;
|
|
191
|
-
|
|
192
155
|
/**
|
|
193
156
|
* Sub
|
|
194
157
|
*/
|
|
195
|
-
function Sub({ id: _id, icon, label, children, ...rest }) {
|
|
158
|
+
function Sub({ id: _id, icon, label, children, expandIcon, ...rest }) {
|
|
196
159
|
const id = useUniqueId(_id);
|
|
197
|
-
const { openedIds, open, close } = useContext(NavMenuContext);
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
160
|
+
const { openedIds, open, close, mode } = useContext(NavMenuContext);
|
|
161
|
+
const isOpen = openedIds.includes(id);
|
|
162
|
+
const classes = clsx('navmenu-sub', { 'navmenu-sub--opened': isOpen }, rest.className);
|
|
163
|
+
const isInlineMode = mode === 'inline';
|
|
164
|
+
// inline mode 时使用 click 事件控制收缩/伸展子菜单
|
|
165
|
+
const props = isInlineMode
|
|
166
|
+
? { onClick: () => (openedIds.includes(id) ? close(id) : open(id)) }
|
|
167
|
+
: {
|
|
168
|
+
onMouseEnter: () => open(id),
|
|
169
|
+
onMouseLeave: () => close(id),
|
|
170
|
+
};
|
|
171
|
+
// inline mode, 避免点击子菜单项时触发父菜单的 open/close
|
|
172
|
+
const containerProps = isInlineMode
|
|
173
|
+
? {
|
|
174
|
+
onClick: e => e.stopPropagation(),
|
|
175
|
+
}
|
|
176
|
+
: {};
|
|
203
177
|
return (
|
|
204
|
-
<
|
|
205
|
-
{...rest}
|
|
206
|
-
className={classes}
|
|
207
|
-
onMouseEnter={() => open(id)}
|
|
208
|
-
onMouseLeave={() => close(id)}>
|
|
178
|
+
<li {...rest} className={classes} {...props}>
|
|
209
179
|
{icon && <span className="navmenu-sub-icon">{icon}</span>}
|
|
210
|
-
<span className="navmenu-sub-
|
|
211
|
-
|
|
180
|
+
<span className="navmenu-sub-label">{label}</span>
|
|
181
|
+
{expandIcon && (
|
|
182
|
+
<span className="navmenu-sub-expand-icon">{expandIcon?.({ isOpen }) || expandIcon}</span>
|
|
183
|
+
)}
|
|
184
|
+
<div className="navmenu-sub-container" {...containerProps}>
|
|
212
185
|
<ul className="navmenu-sub-list">{filterItems(children)}</ul>
|
|
213
186
|
</div>
|
|
214
|
-
</
|
|
187
|
+
</li>
|
|
215
188
|
);
|
|
216
189
|
}
|
|
217
190
|
|
|
@@ -220,26 +193,24 @@ Sub.propTypes = {
|
|
|
220
193
|
icon: PropTypes.element,
|
|
221
194
|
label: PropTypes.node.isRequired,
|
|
222
195
|
children: PropTypes.array.isRequired,
|
|
196
|
+
expandIcon: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
223
197
|
};
|
|
224
198
|
|
|
225
199
|
Sub.defaultProps = {
|
|
226
200
|
id: null,
|
|
227
201
|
icon: null,
|
|
202
|
+
// eslint-disable-next-line react/prop-types
|
|
203
|
+
expandIcon: ({ isOpen }) => {
|
|
204
|
+
return (
|
|
205
|
+
<ExpandMoreIcon
|
|
206
|
+
style={{
|
|
207
|
+
transform: `rotate(${isOpen ? 180 : 0}deg)`,
|
|
208
|
+
}}
|
|
209
|
+
/>
|
|
210
|
+
);
|
|
211
|
+
},
|
|
228
212
|
};
|
|
229
213
|
|
|
230
|
-
const SubRoot = styled.li`
|
|
231
|
-
position: relative;
|
|
232
|
-
cursor: pointer;
|
|
233
|
-
.navmenu-sub-container {
|
|
234
|
-
display: none;
|
|
235
|
-
position: absolute;
|
|
236
|
-
}
|
|
237
|
-
&.navmenu-sub--opened > .navmenu-sub-container {
|
|
238
|
-
display: block;
|
|
239
|
-
top: 100%;
|
|
240
|
-
}
|
|
241
|
-
`;
|
|
242
|
-
|
|
243
214
|
NavMenu.Item = Item;
|
|
244
215
|
NavMenu.Sub = Sub;
|
|
245
216
|
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
const NavMenuBase = styled.nav`
|
|
4
|
+
--text-color: ${props => props.$textColor};
|
|
5
|
+
--active-text-color: ${props => props.$activeTextColor};
|
|
6
|
+
--bg-color: ${props => props.$bgColor};
|
|
7
|
+
|
|
8
|
+
background-color: var(--bg-color);
|
|
9
|
+
font-size: 14px;
|
|
10
|
+
ul {
|
|
11
|
+
list-style: none;
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
}
|
|
15
|
+
.navmenu-item,
|
|
16
|
+
.navmenu-sub {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
}
|
|
20
|
+
// active/hover
|
|
21
|
+
.navmenu-item,
|
|
22
|
+
.navmenu-item a,
|
|
23
|
+
.navmenu-sub {
|
|
24
|
+
color: var(--text-color);
|
|
25
|
+
}
|
|
26
|
+
.navmenu-item--active,
|
|
27
|
+
.navmenu-item:hover,
|
|
28
|
+
.navmenu-item:hover a,
|
|
29
|
+
.navmenu-item--active a,
|
|
30
|
+
.navmenu-sub--opened {
|
|
31
|
+
color: var(--active-text-color);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.navmenu-item {
|
|
35
|
+
position: relative;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
a {
|
|
38
|
+
text-decoration: none;
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
}
|
|
41
|
+
a::before {
|
|
42
|
+
position: absolute;
|
|
43
|
+
top: 0;
|
|
44
|
+
right: 0;
|
|
45
|
+
bottom: 0;
|
|
46
|
+
left: 0;
|
|
47
|
+
background-color: transparent;
|
|
48
|
+
content: '';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.navmenu-sub {
|
|
53
|
+
position: relative;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
// icon & expand icon
|
|
57
|
+
.navmenu-item-icon,
|
|
58
|
+
.navmenu-sub-icon,
|
|
59
|
+
.navmenu-sub-expand-icon {
|
|
60
|
+
display: flex;
|
|
61
|
+
line-height: 1;
|
|
62
|
+
}
|
|
63
|
+
.navmenu-item-icon,
|
|
64
|
+
.navmenu-sub-icon {
|
|
65
|
+
margin-right: 4px;
|
|
66
|
+
}
|
|
67
|
+
.navmenu-item-icon > *,
|
|
68
|
+
.navmenu-sub-icon > * {
|
|
69
|
+
font-size: 1.5em;
|
|
70
|
+
}
|
|
71
|
+
.navmenu-sub-expand-icon {
|
|
72
|
+
margin-left: 8px;
|
|
73
|
+
> * {
|
|
74
|
+
width: 0.8em;
|
|
75
|
+
height: 0.8em;
|
|
76
|
+
transition: transform 0.2s ease-in-out;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
export const HorizontalStyle = styled(NavMenuBase)`
|
|
82
|
+
padding: 8px 16px;
|
|
83
|
+
.navmenu-root {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
}
|
|
87
|
+
// 顶级菜单间隔
|
|
88
|
+
.navmenu-root > .navmenu-item,
|
|
89
|
+
.navmenu-root > .navmenu-sub {
|
|
90
|
+
margin-left: 24px;
|
|
91
|
+
}
|
|
92
|
+
.navmenu-root > .navmenu-item:first-child,
|
|
93
|
+
.navmenu-root > .navmenu-sub:first-child {
|
|
94
|
+
margin-left: 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* 子级列表 */
|
|
98
|
+
.navmenu-sub-container {
|
|
99
|
+
display: none;
|
|
100
|
+
position: absolute;
|
|
101
|
+
top: 100%;
|
|
102
|
+
}
|
|
103
|
+
.navmenu-sub-list {
|
|
104
|
+
padding: 16px;
|
|
105
|
+
border-radius: 4px;
|
|
106
|
+
background: #fff;
|
|
107
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
108
|
+
.navmenu-item + .navmenu-item {
|
|
109
|
+
margin-top: 8px;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// 二级 sub menu
|
|
113
|
+
.navmenu-root > .navmenu-sub {
|
|
114
|
+
> .navmenu-sub-container {
|
|
115
|
+
left: 50%;
|
|
116
|
+
transform: translateX(-50%);
|
|
117
|
+
padding-top: 16px;
|
|
118
|
+
}
|
|
119
|
+
&.navmenu-sub--opened > .navmenu-sub-container {
|
|
120
|
+
display: block;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
`;
|
|
124
|
+
|
|
125
|
+
/* inline mode */
|
|
126
|
+
export const InlineStyle = styled(NavMenuBase)`
|
|
127
|
+
.navmenu-root {
|
|
128
|
+
display: flex;
|
|
129
|
+
flex-direction: column;
|
|
130
|
+
align-items: stretch;
|
|
131
|
+
}
|
|
132
|
+
.navmenu-item,
|
|
133
|
+
.navmenu-sub {
|
|
134
|
+
padding: 0 16px;
|
|
135
|
+
}
|
|
136
|
+
// 顶级
|
|
137
|
+
.navmenu-root > .navmenu-item,
|
|
138
|
+
.navmenu-root > .navmenu-sub {
|
|
139
|
+
height: 48px;
|
|
140
|
+
line-height: 48px;
|
|
141
|
+
border-bottom: 1px solid #eee;
|
|
142
|
+
}
|
|
143
|
+
// icon
|
|
144
|
+
.navmenu-item-icon,
|
|
145
|
+
.navmenu-sub-icon {
|
|
146
|
+
width: 32px;
|
|
147
|
+
margin: 0;
|
|
148
|
+
}
|
|
149
|
+
.navmenu-sub-expand-icon {
|
|
150
|
+
margin-left: auto;
|
|
151
|
+
}
|
|
152
|
+
/* 子级列表 */
|
|
153
|
+
.navmenu-sub-container {
|
|
154
|
+
display: none;
|
|
155
|
+
position: absolute;
|
|
156
|
+
top: 100%;
|
|
157
|
+
left: 0;
|
|
158
|
+
right: 0;
|
|
159
|
+
.navmenu-item,
|
|
160
|
+
.navmenu-sub {
|
|
161
|
+
line-height: 24px;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
.navmenu-sub-list {
|
|
165
|
+
padding-left: 16px;
|
|
166
|
+
.navmenu-item,
|
|
167
|
+
.navmenu-sub {
|
|
168
|
+
padding-left: 32px;
|
|
169
|
+
margin-top: 8px;
|
|
170
|
+
font-size: 13px;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// 二级 menu
|
|
174
|
+
.navmenu-root > .navmenu-sub {
|
|
175
|
+
&.navmenu-sub--opened {
|
|
176
|
+
background: #eee;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
.navmenu-sub--opened > .navmenu-sub-container {
|
|
180
|
+
display: block;
|
|
181
|
+
}
|
|
182
|
+
`;
|
package/lib/NavMenu/style.css
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
.navmenu .navmenu-root {
|
|
2
|
-
display: flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
}
|
|
5
|
-
.navmenu-item,
|
|
6
|
-
.navmenu-sub {
|
|
7
|
-
display: flex;
|
|
8
|
-
align-items: center;
|
|
9
|
-
}
|
|
10
|
-
.navmenu-root > .navmenu-item,
|
|
11
|
-
.navmenu-root > .navmenu-sub {
|
|
12
|
-
margin-left: 24px;
|
|
13
|
-
}
|
|
14
|
-
.navmenu-root > .navmenu-item:first-child,
|
|
15
|
-
.navmenu-root > .navmenu-sub:first-child {
|
|
16
|
-
margin-left: 0;
|
|
17
|
-
}
|
|
18
|
-
.navmenu-item-icon,
|
|
19
|
-
.navmenu-sub-icon {
|
|
20
|
-
display: flex;
|
|
21
|
-
justify-content: center;
|
|
22
|
-
align-items: center;
|
|
23
|
-
height: 20px;
|
|
24
|
-
line-height: 1;
|
|
25
|
-
}
|
|
26
|
-
.navmenu-item-icon > *,
|
|
27
|
-
.navmenu-sub-icon > * {
|
|
28
|
-
width: auto !important;
|
|
29
|
-
height: 100% !important;
|
|
30
|
-
}
|
|
31
|
-
.navmenu-item-icon {
|
|
32
|
-
margin-right: 4px;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* 二级列表 */
|
|
36
|
-
.navmenu-root > .navmenu-sub > .navmenu-sub-container {
|
|
37
|
-
left: 50%;
|
|
38
|
-
transform: translateX(-50%);
|
|
39
|
-
padding-top: 16px;
|
|
40
|
-
}
|
|
41
|
-
.navmenu-root .navmenu-sub-list {
|
|
42
|
-
padding: 16px;
|
|
43
|
-
border-radius: 4px;
|
|
44
|
-
background: #fff;
|
|
45
|
-
}
|
|
46
|
-
.navmenu-sub-list > .navmenu-item + .navmenu-item {
|
|
47
|
-
margin-top: 8px;
|
|
48
|
-
}
|
package/src/NavMenu/style.css
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
.navmenu .navmenu-root {
|
|
2
|
-
display: flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
}
|
|
5
|
-
.navmenu-item,
|
|
6
|
-
.navmenu-sub {
|
|
7
|
-
display: flex;
|
|
8
|
-
align-items: center;
|
|
9
|
-
}
|
|
10
|
-
.navmenu-root > .navmenu-item,
|
|
11
|
-
.navmenu-root > .navmenu-sub {
|
|
12
|
-
margin-left: 24px;
|
|
13
|
-
}
|
|
14
|
-
.navmenu-root > .navmenu-item:first-child,
|
|
15
|
-
.navmenu-root > .navmenu-sub:first-child {
|
|
16
|
-
margin-left: 0;
|
|
17
|
-
}
|
|
18
|
-
.navmenu-item-icon,
|
|
19
|
-
.navmenu-sub-icon {
|
|
20
|
-
display: flex;
|
|
21
|
-
justify-content: center;
|
|
22
|
-
align-items: center;
|
|
23
|
-
height: 20px;
|
|
24
|
-
line-height: 1;
|
|
25
|
-
}
|
|
26
|
-
.navmenu-item-icon > *,
|
|
27
|
-
.navmenu-sub-icon > * {
|
|
28
|
-
width: auto !important;
|
|
29
|
-
height: 100% !important;
|
|
30
|
-
}
|
|
31
|
-
.navmenu-item-icon {
|
|
32
|
-
margin-right: 4px;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* 二级列表 */
|
|
36
|
-
.navmenu-root > .navmenu-sub > .navmenu-sub-container {
|
|
37
|
-
left: 50%;
|
|
38
|
-
transform: translateX(-50%);
|
|
39
|
-
padding-top: 16px;
|
|
40
|
-
}
|
|
41
|
-
.navmenu-root .navmenu-sub-list {
|
|
42
|
-
padding: 16px;
|
|
43
|
-
border-radius: 4px;
|
|
44
|
-
background: #fff;
|
|
45
|
-
}
|
|
46
|
-
.navmenu-sub-list > .navmenu-item + .navmenu-item {
|
|
47
|
-
margin-top: 8px;
|
|
48
|
-
}
|