@cashub/ui 0.29.1 → 0.29.3
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/layout/AsideHeader.jsx +27 -27
- package/layout/Container.js +4 -3
- package/layout/Header.jsx +55 -55
- package/layout/Layout.jsx +84 -82
- package/layout/Logo.jsx +17 -17
- package/layout/MenuIcon.jsx +27 -27
- package/layout/Sidebar.jsx +241 -241
- package/package.json +1 -1
package/layout/AsideHeader.jsx
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import styled from 'styled-components';
|
|
2
|
-
import headerStyle from '
|
|
3
|
-
import media from '
|
|
4
|
-
import Logo from './Logo';
|
|
5
|
-
import MenuIcon from './MenuIcon';
|
|
6
|
-
|
|
7
|
-
const AsideHeader = ({ theme, logo, hasSidebar, toggleSidebar }) => {
|
|
8
|
-
return (
|
|
9
|
-
<Brand>
|
|
10
|
-
{hasSidebar && <MenuIcon theme={theme} toggleSidebar={toggleSidebar} />}
|
|
11
|
-
{logo && <Logo src={logo} />}
|
|
12
|
-
</Brand>
|
|
13
|
-
);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const Brand = styled.div`
|
|
17
|
-
display: none;
|
|
18
|
-
height: ${headerStyle.height};
|
|
19
|
-
|
|
20
|
-
${media.tablet`
|
|
21
|
-
padding: 0 var(--spacing-xs);
|
|
22
|
-
align-items: center;
|
|
23
|
-
display: flex
|
|
24
|
-
`};
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
export default AsideHeader;
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import headerStyle from '../styles/config/header.style';
|
|
3
|
+
import media from '../styles/mixin/media';
|
|
4
|
+
import Logo from './Logo';
|
|
5
|
+
import MenuIcon from './MenuIcon';
|
|
6
|
+
|
|
7
|
+
const AsideHeader = ({ theme, logo, hasSidebar, toggleSidebar }) => {
|
|
8
|
+
return (
|
|
9
|
+
<Brand>
|
|
10
|
+
{hasSidebar && <MenuIcon theme={theme} toggleSidebar={toggleSidebar} />}
|
|
11
|
+
{logo && <Logo src={logo} />}
|
|
12
|
+
</Brand>
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const Brand = styled.div`
|
|
17
|
+
display: none;
|
|
18
|
+
height: ${headerStyle.height};
|
|
19
|
+
|
|
20
|
+
${media.tablet`
|
|
21
|
+
padding: 0 var(--spacing-xs);
|
|
22
|
+
align-items: center;
|
|
23
|
+
display: flex
|
|
24
|
+
`};
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
export default AsideHeader;
|
package/layout/Container.js
CHANGED
|
@@ -13,10 +13,11 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
13
13
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
14
14
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
15
15
|
function _taggedTemplateLiteral(e, t) { return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } })); }
|
|
16
|
-
const Container = _styledComponents.default.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n transition: 0.3s;\n width:
|
|
16
|
+
const Container = _styledComponents.default.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n transition: 0.3s;\n width: 100%;\n padding: calc(", " + var(--spacing)) var(--spacing)\n var(--spacing);\n\n ", "\n"])), _header.default.height, _ref => {
|
|
17
17
|
let {
|
|
18
|
+
hasSidebar,
|
|
18
19
|
$display
|
|
19
20
|
} = _ref;
|
|
20
|
-
return
|
|
21
|
-
}
|
|
21
|
+
return hasSidebar === true && (0, _styledComponents.css)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n width: calc(\n 100% -\n ", "\n );\n margin-left: ", ";\n\n ", "\n "])), $display === true ? _sidebar.default.open.width : _sidebar.default.close.width, $display === true ? _sidebar.default.open.width : _sidebar.default.close.width, _media.default.tablet(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n width: 100%;\n margin-left: 0;\n "]))));
|
|
22
|
+
});
|
|
22
23
|
var _default = exports.default = Container;
|
package/layout/Header.jsx
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import styled from 'styled-components';
|
|
2
|
-
import headerStyle from '../styles/config/header.style';
|
|
3
|
-
import media from '../styles/mixin/media';
|
|
4
|
-
import MenuIcon from './MenuIcon';
|
|
5
|
-
import Logo from './Logo';
|
|
6
|
-
|
|
7
|
-
const Header = ({ theme, logo, hasSidebar, toggleSidebar, children }) => {
|
|
8
|
-
return (
|
|
9
|
-
<>
|
|
10
|
-
<Wrapper>
|
|
11
|
-
<Brand>
|
|
12
|
-
{hasSidebar && (
|
|
13
|
-
<MenuIcon theme={theme} toggleSidebar={toggleSidebar} />
|
|
14
|
-
)}
|
|
15
|
-
{logo && <Logo src={logo} />}
|
|
16
|
-
</Brand>
|
|
17
|
-
<Topbar>{children}</Topbar>
|
|
18
|
-
</Wrapper>
|
|
19
|
-
</>
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const Wrapper = styled.header`
|
|
24
|
-
background: var(--color-background2);
|
|
25
|
-
display: flex;
|
|
26
|
-
justify-content: space-between;
|
|
27
|
-
align-items: center;
|
|
28
|
-
position: fixed;
|
|
29
|
-
z-index: 40;
|
|
30
|
-
width: 100%;
|
|
31
|
-
height: ${headerStyle.height};
|
|
32
|
-
padding: 0 calc(var(--spacing-s) + 0.25rem) 0 var(--spacing-s);
|
|
33
|
-
|
|
34
|
-
${media.tablet`
|
|
35
|
-
padding: 0 var(--spacing-s) 0 calc(var(--spacing-s) - 0.25rem);
|
|
36
|
-
`}
|
|
37
|
-
`;
|
|
38
|
-
|
|
39
|
-
const Brand = styled.div`
|
|
40
|
-
display: flex;
|
|
41
|
-
|
|
42
|
-
> * {
|
|
43
|
-
flex: none;
|
|
44
|
-
}
|
|
45
|
-
`;
|
|
46
|
-
|
|
47
|
-
const Topbar = styled.div`
|
|
48
|
-
display: flex;
|
|
49
|
-
|
|
50
|
-
> *:not(:last-child) {
|
|
51
|
-
margin-right: calc(var(--spacing) - 0.5rem);
|
|
52
|
-
}
|
|
53
|
-
`;
|
|
54
|
-
|
|
55
|
-
export default Header;
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import headerStyle from '../styles/config/header.style';
|
|
3
|
+
import media from '../styles/mixin/media';
|
|
4
|
+
import MenuIcon from './MenuIcon';
|
|
5
|
+
import Logo from './Logo';
|
|
6
|
+
|
|
7
|
+
const Header = ({ theme, logo, hasSidebar, toggleSidebar, children }) => {
|
|
8
|
+
return (
|
|
9
|
+
<>
|
|
10
|
+
<Wrapper>
|
|
11
|
+
<Brand>
|
|
12
|
+
{hasSidebar && (
|
|
13
|
+
<MenuIcon theme={theme} toggleSidebar={toggleSidebar} />
|
|
14
|
+
)}
|
|
15
|
+
{logo && <Logo src={logo} />}
|
|
16
|
+
</Brand>
|
|
17
|
+
<Topbar>{children}</Topbar>
|
|
18
|
+
</Wrapper>
|
|
19
|
+
</>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const Wrapper = styled.header`
|
|
24
|
+
background: var(--color-background2);
|
|
25
|
+
display: flex;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
align-items: center;
|
|
28
|
+
position: fixed;
|
|
29
|
+
z-index: 40;
|
|
30
|
+
width: 100%;
|
|
31
|
+
height: ${headerStyle.height};
|
|
32
|
+
padding: 0 calc(var(--spacing-s) + 0.25rem) 0 var(--spacing-s);
|
|
33
|
+
|
|
34
|
+
${media.tablet`
|
|
35
|
+
padding: 0 var(--spacing-s) 0 calc(var(--spacing-s) - 0.25rem);
|
|
36
|
+
`}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const Brand = styled.div`
|
|
40
|
+
display: flex;
|
|
41
|
+
|
|
42
|
+
> * {
|
|
43
|
+
flex: none;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
const Topbar = styled.div`
|
|
48
|
+
display: flex;
|
|
49
|
+
|
|
50
|
+
> *:not(:last-child) {
|
|
51
|
+
margin-right: calc(var(--spacing) - 0.5rem);
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
export default Header;
|
package/layout/Layout.jsx
CHANGED
|
@@ -1,82 +1,84 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import styled from 'styled-components';
|
|
3
|
-
import { ScrollToTopButton } from '
|
|
4
|
-
import Header from './Header';
|
|
5
|
-
import Container from './Container';
|
|
6
|
-
import Footer from './Footer';
|
|
7
|
-
import Sidebar from './Sidebar';
|
|
8
|
-
import Backdrop from './Backdrop';
|
|
9
|
-
|
|
10
|
-
const Layout = ({
|
|
11
|
-
mode,
|
|
12
|
-
theme,
|
|
13
|
-
logo,
|
|
14
|
-
headerContent,
|
|
15
|
-
navContent,
|
|
16
|
-
footerContent,
|
|
17
|
-
children,
|
|
18
|
-
}) => {
|
|
19
|
-
const [display, setDisplay] = useState(!!navContent);
|
|
20
|
-
|
|
21
|
-
const toggleSidebar = () => {
|
|
22
|
-
setDisplay(!display);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// hide sidebar
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
if (mode === 'tablet') {
|
|
28
|
-
setDisplay(false);
|
|
29
|
-
}
|
|
30
|
-
}, [mode, setDisplay]);
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<Wrapper>
|
|
34
|
-
<Header
|
|
35
|
-
theme={theme}
|
|
36
|
-
logo={logo}
|
|
37
|
-
hasSidebar={!!navContent}
|
|
38
|
-
toggleSidebar={toggleSidebar}
|
|
39
|
-
>
|
|
40
|
-
{headerContent}
|
|
41
|
-
</Header>
|
|
42
|
-
|
|
43
|
-
<Main>
|
|
44
|
-
<Backdrop $display={display} onClick={toggleSidebar} />
|
|
45
|
-
|
|
46
|
-
{navContent && (
|
|
47
|
-
<Sidebar
|
|
48
|
-
theme={theme}
|
|
49
|
-
logo={logo}
|
|
50
|
-
hasSidebar={!!navContent}
|
|
51
|
-
$display={display}
|
|
52
|
-
toggleSidebar={toggleSidebar}
|
|
53
|
-
>
|
|
54
|
-
{navContent}
|
|
55
|
-
</Sidebar>
|
|
56
|
-
)}
|
|
57
|
-
|
|
58
|
-
<Container $display={display}>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { ScrollToTopButton } from '../button';
|
|
4
|
+
import Header from './Header';
|
|
5
|
+
import Container from './Container';
|
|
6
|
+
import Footer from './Footer';
|
|
7
|
+
import Sidebar from './Sidebar';
|
|
8
|
+
import Backdrop from './Backdrop';
|
|
9
|
+
|
|
10
|
+
const Layout = ({
|
|
11
|
+
mode,
|
|
12
|
+
theme,
|
|
13
|
+
logo,
|
|
14
|
+
headerContent,
|
|
15
|
+
navContent,
|
|
16
|
+
footerContent,
|
|
17
|
+
children,
|
|
18
|
+
}) => {
|
|
19
|
+
const [display, setDisplay] = useState(!!navContent);
|
|
20
|
+
|
|
21
|
+
const toggleSidebar = () => {
|
|
22
|
+
setDisplay(!display);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// hide sidebar
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (mode === 'tablet') {
|
|
28
|
+
setDisplay(false);
|
|
29
|
+
}
|
|
30
|
+
}, [mode, setDisplay]);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Wrapper>
|
|
34
|
+
<Header
|
|
35
|
+
theme={theme}
|
|
36
|
+
logo={logo}
|
|
37
|
+
hasSidebar={!!navContent}
|
|
38
|
+
toggleSidebar={toggleSidebar}
|
|
39
|
+
>
|
|
40
|
+
{headerContent}
|
|
41
|
+
</Header>
|
|
42
|
+
|
|
43
|
+
<Main>
|
|
44
|
+
<Backdrop $display={display} onClick={toggleSidebar} />
|
|
45
|
+
|
|
46
|
+
{navContent && (
|
|
47
|
+
<Sidebar
|
|
48
|
+
theme={theme}
|
|
49
|
+
logo={logo}
|
|
50
|
+
hasSidebar={!!navContent}
|
|
51
|
+
$display={display}
|
|
52
|
+
toggleSidebar={toggleSidebar}
|
|
53
|
+
>
|
|
54
|
+
{navContent}
|
|
55
|
+
</Sidebar>
|
|
56
|
+
)}
|
|
57
|
+
|
|
58
|
+
<Container hasSidebar={!!navContent} $display={display}>
|
|
59
|
+
{children}
|
|
60
|
+
</Container>
|
|
61
|
+
|
|
62
|
+
<ScrollToTopButton />
|
|
63
|
+
</Main>
|
|
64
|
+
|
|
65
|
+
<Footer hasSidebar={!!navContent} $display={display}>
|
|
66
|
+
{footerContent}
|
|
67
|
+
</Footer>
|
|
68
|
+
</Wrapper>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const Wrapper = styled.div`
|
|
73
|
+
display: flex;
|
|
74
|
+
flex-direction: column;
|
|
75
|
+
min-height: 100vh;
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
const Main = styled.div`
|
|
79
|
+
display: flex;
|
|
80
|
+
flex: 1;
|
|
81
|
+
position: relative;
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
export default Layout;
|
package/layout/Logo.jsx
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import styled from 'styled-components';
|
|
2
|
-
import { ImageFluid } from '../image';
|
|
3
|
-
|
|
4
|
-
const Logo = ({ src }) => {
|
|
5
|
-
return (
|
|
6
|
-
<Figure>
|
|
7
|
-
<ImageFluid src={src} alt='CasHUB logo' />
|
|
8
|
-
</Figure>
|
|
9
|
-
);
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const Figure = styled.figure`
|
|
13
|
-
max-width: 220px;
|
|
14
|
-
height: 40px;
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
|
-
export default Logo;
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { ImageFluid } from '../image';
|
|
3
|
+
|
|
4
|
+
const Logo = ({ src }) => {
|
|
5
|
+
return (
|
|
6
|
+
<Figure>
|
|
7
|
+
<ImageFluid src={src} alt='CasHUB logo' />
|
|
8
|
+
</Figure>
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const Figure = styled.figure`
|
|
13
|
+
max-width: 220px;
|
|
14
|
+
height: 40px;
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
export default Logo;
|
package/layout/MenuIcon.jsx
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import styled from 'styled-components';
|
|
2
|
-
import { ImageFluid } from '../image';
|
|
3
|
-
import { IconFigure } from '../figure';
|
|
4
|
-
import { IconButton } from '../button';
|
|
5
|
-
import burgerWhite from '../assets/icons/burger-white.png';
|
|
6
|
-
import burgerBlack from '../assets/icons/burger-black.png';
|
|
7
|
-
|
|
8
|
-
const MenuIcon = ({ theme, toggleSidebar }) => {
|
|
9
|
-
return (
|
|
10
|
-
<Wrapper onClick={toggleSidebar}>
|
|
11
|
-
<IconFigure>
|
|
12
|
-
<ImageFluid
|
|
13
|
-
crossOrigin='anonymous'
|
|
14
|
-
src={theme === 'Dark' ? burgerWhite : burgerBlack}
|
|
15
|
-
alt='Sidebar toggler'
|
|
16
|
-
/>
|
|
17
|
-
</IconFigure>
|
|
18
|
-
</Wrapper>
|
|
19
|
-
);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const Wrapper = styled(IconButton)`
|
|
23
|
-
margin: 0;
|
|
24
|
-
margin-right: calc(var(--spacing) - 0.5rem);
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
export default MenuIcon;
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
import { ImageFluid } from '../image';
|
|
3
|
+
import { IconFigure } from '../figure';
|
|
4
|
+
import { IconButton } from '../button';
|
|
5
|
+
import burgerWhite from '../assets/icons/burger-white.png';
|
|
6
|
+
import burgerBlack from '../assets/icons/burger-black.png';
|
|
7
|
+
|
|
8
|
+
const MenuIcon = ({ theme, toggleSidebar }) => {
|
|
9
|
+
return (
|
|
10
|
+
<Wrapper onClick={toggleSidebar}>
|
|
11
|
+
<IconFigure>
|
|
12
|
+
<ImageFluid
|
|
13
|
+
crossOrigin='anonymous'
|
|
14
|
+
src={theme === 'Dark' ? burgerWhite : burgerBlack}
|
|
15
|
+
alt='Sidebar toggler'
|
|
16
|
+
/>
|
|
17
|
+
</IconFigure>
|
|
18
|
+
</Wrapper>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const Wrapper = styled(IconButton)`
|
|
23
|
+
margin: 0;
|
|
24
|
+
margin-right: calc(var(--spacing) - 0.5rem);
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
export default MenuIcon;
|
package/layout/Sidebar.jsx
CHANGED
|
@@ -1,241 +1,241 @@
|
|
|
1
|
-
import { useEffect, useState, useRef } from 'react';
|
|
2
|
-
import { FaCaretRight } from 'react-icons/fa';
|
|
3
|
-
import { Link, useLocation } from 'react-router-dom';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import styled, { css } from 'styled-components';
|
|
6
|
-
import headerStyle from '
|
|
7
|
-
import media from '
|
|
8
|
-
import scrollbar from '
|
|
9
|
-
import Aside from './Aside';
|
|
10
|
-
import AsideHeader from './AsideHeader';
|
|
11
|
-
|
|
12
|
-
const Sidebar = ({
|
|
13
|
-
theme,
|
|
14
|
-
logo,
|
|
15
|
-
hasSidebar,
|
|
16
|
-
$display,
|
|
17
|
-
toggleSidebar,
|
|
18
|
-
children,
|
|
19
|
-
}) => {
|
|
20
|
-
const location = useLocation();
|
|
21
|
-
const sidebarRef = useRef(null);
|
|
22
|
-
const [hoverDisplay, setHoverDisplay] = useState(false);
|
|
23
|
-
|
|
24
|
-
const nowPath = (path) => {
|
|
25
|
-
return location.pathname.includes(path);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const handleMouseOver = () => {
|
|
29
|
-
if ($display === true) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
setHoverDisplay(true);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const handleMouseOut = (event) => {
|
|
37
|
-
if ($display === true) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (sidebarRef.current.contains(event.relatedTarget)) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
setHoverDisplay(false);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<>
|
|
50
|
-
<Aside
|
|
51
|
-
ref={sidebarRef}
|
|
52
|
-
$display={$display || hoverDisplay}
|
|
53
|
-
onMouseOver={handleMouseOver}
|
|
54
|
-
onMouseOut={handleMouseOut}
|
|
55
|
-
>
|
|
56
|
-
<AsideHeader
|
|
57
|
-
theme={theme}
|
|
58
|
-
logo={logo}
|
|
59
|
-
hasSidebar={hasSidebar}
|
|
60
|
-
toggleSidebar={toggleSidebar}
|
|
61
|
-
/>
|
|
62
|
-
<Menu>
|
|
63
|
-
{children.map((prop, key) => {
|
|
64
|
-
if (prop.parent === true) {
|
|
65
|
-
return (
|
|
66
|
-
<MenuListWithSubMenu
|
|
67
|
-
{...prop}
|
|
68
|
-
active={nowPath(prop.path)}
|
|
69
|
-
currentPath={location.pathname}
|
|
70
|
-
key={key}
|
|
71
|
-
$display={$display}
|
|
72
|
-
hoverDisplay={hoverDisplay}
|
|
73
|
-
/>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return <MenuList {...prop} active={nowPath(prop.path)} key={key} />;
|
|
78
|
-
})}
|
|
79
|
-
</Menu>
|
|
80
|
-
</Aside>
|
|
81
|
-
</>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const MenuList = ({ path, name, icon, active }) => {
|
|
86
|
-
const { t: trans } = useTranslation();
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<MenuItem active={active}>
|
|
90
|
-
<MenuItemLink to={path}>
|
|
91
|
-
<img
|
|
92
|
-
crossOrigin='anonymous'
|
|
93
|
-
src={icon}
|
|
94
|
-
alt={`${name} icon`}
|
|
95
|
-
width='24px'
|
|
96
|
-
/>
|
|
97
|
-
<span>{trans(name)}</span>
|
|
98
|
-
</MenuItemLink>
|
|
99
|
-
</MenuItem>
|
|
100
|
-
);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const MenuListWithSubMenu = ({
|
|
104
|
-
path,
|
|
105
|
-
name,
|
|
106
|
-
icon,
|
|
107
|
-
child,
|
|
108
|
-
active,
|
|
109
|
-
currentPath,
|
|
110
|
-
$display,
|
|
111
|
-
hoverDisplay,
|
|
112
|
-
}) => {
|
|
113
|
-
const { t: trans } = useTranslation();
|
|
114
|
-
const [open, setOpen] = useState(active);
|
|
115
|
-
|
|
116
|
-
const toggleOpen = () => {
|
|
117
|
-
setOpen(!open);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
$display === false && hoverDisplay === false && setOpen(false);
|
|
122
|
-
}, [$display, hoverDisplay]);
|
|
123
|
-
|
|
124
|
-
return (
|
|
125
|
-
<>
|
|
126
|
-
<MenuItem onClick={toggleOpen}>
|
|
127
|
-
<MenuItemButton as='button' open={open}>
|
|
128
|
-
<img crossOrigin='anonymous' src={icon} alt={`${name} icon`} />
|
|
129
|
-
<span>{trans(name)}</span>
|
|
130
|
-
<span className='arrow' role='presentation' aria-hidden='true'>
|
|
131
|
-
<FaCaretRight />
|
|
132
|
-
</span>
|
|
133
|
-
</MenuItemButton>
|
|
134
|
-
</MenuItem>
|
|
135
|
-
<SubMenu open={open}>
|
|
136
|
-
{child
|
|
137
|
-
.filter((prop) => prop.name)
|
|
138
|
-
.map((prop, key) => {
|
|
139
|
-
const href = `${path}${prop.path}`;
|
|
140
|
-
const active = currentPath.includes(prop.path);
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<SubMenuItem key={key} active={active}>
|
|
144
|
-
<Link to={href}>
|
|
145
|
-
<span>{trans(prop.name)}</span>
|
|
146
|
-
</Link>
|
|
147
|
-
</SubMenuItem>
|
|
148
|
-
);
|
|
149
|
-
})}
|
|
150
|
-
</SubMenu>
|
|
151
|
-
</>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const Menu = styled.ul`
|
|
156
|
-
overflow-y: auto;
|
|
157
|
-
overflow-x: hidden;
|
|
158
|
-
height: 100%;
|
|
159
|
-
|
|
160
|
-
span {
|
|
161
|
-
color: var(--font-on-background);
|
|
162
|
-
font-size: var(--font-body1);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
li {
|
|
166
|
-
transition: 0.3s;
|
|
167
|
-
|
|
168
|
-
&:hover {
|
|
169
|
-
background: var(--color-hover);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
${scrollbar}
|
|
174
|
-
|
|
175
|
-
${media.tablet`
|
|
176
|
-
height: calc(100% - ${headerStyle.height});
|
|
177
|
-
`};
|
|
178
|
-
`;
|
|
179
|
-
|
|
180
|
-
const MenuItem = styled.li`
|
|
181
|
-
${(props) =>
|
|
182
|
-
props.active === true &&
|
|
183
|
-
css`
|
|
184
|
-
background: var(--color-active);
|
|
185
|
-
`};
|
|
186
|
-
`;
|
|
187
|
-
|
|
188
|
-
const MenuItemLink = styled(Link)`
|
|
189
|
-
display: flex;
|
|
190
|
-
align-items: center;
|
|
191
|
-
padding: 0 var(--spacing);
|
|
192
|
-
height: 48px;
|
|
193
|
-
|
|
194
|
-
img {
|
|
195
|
-
width: 24px;
|
|
196
|
-
height: 24px;
|
|
197
|
-
margin-right: var(--spacing);
|
|
198
|
-
flex: 0 0 24px;
|
|
199
|
-
}
|
|
200
|
-
`;
|
|
201
|
-
|
|
202
|
-
const MenuItemButton = styled(MenuItemLink)`
|
|
203
|
-
background-color: transparent;
|
|
204
|
-
border: none;
|
|
205
|
-
cursor: pointer;
|
|
206
|
-
width: 100%;
|
|
207
|
-
|
|
208
|
-
.arrow {
|
|
209
|
-
margin-left: auto;
|
|
210
|
-
color: var(--color-primary);
|
|
211
|
-
|
|
212
|
-
${({ open }) =>
|
|
213
|
-
open === true &&
|
|
214
|
-
css`
|
|
215
|
-
transform: rotate(90deg);
|
|
216
|
-
transition: all 0.4s;
|
|
217
|
-
`};
|
|
218
|
-
}
|
|
219
|
-
`;
|
|
220
|
-
|
|
221
|
-
const SubMenu = styled.ul`
|
|
222
|
-
overflow: hidden;
|
|
223
|
-
height: ${(props) => (props.open === true ? 'auto' : '0px')};
|
|
224
|
-
`;
|
|
225
|
-
|
|
226
|
-
const SubMenuItem = styled.li`
|
|
227
|
-
a {
|
|
228
|
-
display: flex;
|
|
229
|
-
align-items: center;
|
|
230
|
-
padding: 0 calc(var(--spacing) * 2 + 1.5rem);
|
|
231
|
-
height: 48px;
|
|
232
|
-
|
|
233
|
-
${({ active }) =>
|
|
234
|
-
active === true &&
|
|
235
|
-
css`
|
|
236
|
-
background: var(--color-active);
|
|
237
|
-
`};
|
|
238
|
-
}
|
|
239
|
-
`;
|
|
240
|
-
|
|
241
|
-
export default Sidebar;
|
|
1
|
+
import { useEffect, useState, useRef } from 'react';
|
|
2
|
+
import { FaCaretRight } from 'react-icons/fa';
|
|
3
|
+
import { Link, useLocation } from 'react-router-dom';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import styled, { css } from 'styled-components';
|
|
6
|
+
import headerStyle from '../styles/config/header.style';
|
|
7
|
+
import media from '../styles/mixin/media';
|
|
8
|
+
import scrollbar from '../styles/mixin/scrollbar';
|
|
9
|
+
import Aside from './Aside';
|
|
10
|
+
import AsideHeader from './AsideHeader';
|
|
11
|
+
|
|
12
|
+
const Sidebar = ({
|
|
13
|
+
theme,
|
|
14
|
+
logo,
|
|
15
|
+
hasSidebar,
|
|
16
|
+
$display,
|
|
17
|
+
toggleSidebar,
|
|
18
|
+
children,
|
|
19
|
+
}) => {
|
|
20
|
+
const location = useLocation();
|
|
21
|
+
const sidebarRef = useRef(null);
|
|
22
|
+
const [hoverDisplay, setHoverDisplay] = useState(false);
|
|
23
|
+
|
|
24
|
+
const nowPath = (path) => {
|
|
25
|
+
return location.pathname.includes(path);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const handleMouseOver = () => {
|
|
29
|
+
if ($display === true) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setHoverDisplay(true);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleMouseOut = (event) => {
|
|
37
|
+
if ($display === true) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (sidebarRef.current.contains(event.relatedTarget)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setHoverDisplay(false);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<Aside
|
|
51
|
+
ref={sidebarRef}
|
|
52
|
+
$display={$display || hoverDisplay}
|
|
53
|
+
onMouseOver={handleMouseOver}
|
|
54
|
+
onMouseOut={handleMouseOut}
|
|
55
|
+
>
|
|
56
|
+
<AsideHeader
|
|
57
|
+
theme={theme}
|
|
58
|
+
logo={logo}
|
|
59
|
+
hasSidebar={hasSidebar}
|
|
60
|
+
toggleSidebar={toggleSidebar}
|
|
61
|
+
/>
|
|
62
|
+
<Menu>
|
|
63
|
+
{children.map((prop, key) => {
|
|
64
|
+
if (prop.parent === true) {
|
|
65
|
+
return (
|
|
66
|
+
<MenuListWithSubMenu
|
|
67
|
+
{...prop}
|
|
68
|
+
active={nowPath(prop.path)}
|
|
69
|
+
currentPath={location.pathname}
|
|
70
|
+
key={key}
|
|
71
|
+
$display={$display}
|
|
72
|
+
hoverDisplay={hoverDisplay}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return <MenuList {...prop} active={nowPath(prop.path)} key={key} />;
|
|
78
|
+
})}
|
|
79
|
+
</Menu>
|
|
80
|
+
</Aside>
|
|
81
|
+
</>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const MenuList = ({ path, name, icon, active }) => {
|
|
86
|
+
const { t: trans } = useTranslation();
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<MenuItem active={active}>
|
|
90
|
+
<MenuItemLink to={path}>
|
|
91
|
+
<img
|
|
92
|
+
crossOrigin='anonymous'
|
|
93
|
+
src={icon}
|
|
94
|
+
alt={`${name} icon`}
|
|
95
|
+
width='24px'
|
|
96
|
+
/>
|
|
97
|
+
<span>{trans(name)}</span>
|
|
98
|
+
</MenuItemLink>
|
|
99
|
+
</MenuItem>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const MenuListWithSubMenu = ({
|
|
104
|
+
path,
|
|
105
|
+
name,
|
|
106
|
+
icon,
|
|
107
|
+
child,
|
|
108
|
+
active,
|
|
109
|
+
currentPath,
|
|
110
|
+
$display,
|
|
111
|
+
hoverDisplay,
|
|
112
|
+
}) => {
|
|
113
|
+
const { t: trans } = useTranslation();
|
|
114
|
+
const [open, setOpen] = useState(active);
|
|
115
|
+
|
|
116
|
+
const toggleOpen = () => {
|
|
117
|
+
setOpen(!open);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
$display === false && hoverDisplay === false && setOpen(false);
|
|
122
|
+
}, [$display, hoverDisplay]);
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<>
|
|
126
|
+
<MenuItem onClick={toggleOpen}>
|
|
127
|
+
<MenuItemButton as='button' open={open}>
|
|
128
|
+
<img crossOrigin='anonymous' src={icon} alt={`${name} icon`} />
|
|
129
|
+
<span>{trans(name)}</span>
|
|
130
|
+
<span className='arrow' role='presentation' aria-hidden='true'>
|
|
131
|
+
<FaCaretRight />
|
|
132
|
+
</span>
|
|
133
|
+
</MenuItemButton>
|
|
134
|
+
</MenuItem>
|
|
135
|
+
<SubMenu open={open}>
|
|
136
|
+
{child
|
|
137
|
+
.filter((prop) => prop.name)
|
|
138
|
+
.map((prop, key) => {
|
|
139
|
+
const href = `${path}${prop.path}`;
|
|
140
|
+
const active = currentPath.includes(prop.path);
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<SubMenuItem key={key} active={active}>
|
|
144
|
+
<Link to={href}>
|
|
145
|
+
<span>{trans(prop.name)}</span>
|
|
146
|
+
</Link>
|
|
147
|
+
</SubMenuItem>
|
|
148
|
+
);
|
|
149
|
+
})}
|
|
150
|
+
</SubMenu>
|
|
151
|
+
</>
|
|
152
|
+
);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const Menu = styled.ul`
|
|
156
|
+
overflow-y: auto;
|
|
157
|
+
overflow-x: hidden;
|
|
158
|
+
height: 100%;
|
|
159
|
+
|
|
160
|
+
span {
|
|
161
|
+
color: var(--font-on-background);
|
|
162
|
+
font-size: var(--font-body1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
li {
|
|
166
|
+
transition: 0.3s;
|
|
167
|
+
|
|
168
|
+
&:hover {
|
|
169
|
+
background: var(--color-hover);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
${scrollbar}
|
|
174
|
+
|
|
175
|
+
${media.tablet`
|
|
176
|
+
height: calc(100% - ${headerStyle.height});
|
|
177
|
+
`};
|
|
178
|
+
`;
|
|
179
|
+
|
|
180
|
+
const MenuItem = styled.li`
|
|
181
|
+
${(props) =>
|
|
182
|
+
props.active === true &&
|
|
183
|
+
css`
|
|
184
|
+
background: var(--color-active);
|
|
185
|
+
`};
|
|
186
|
+
`;
|
|
187
|
+
|
|
188
|
+
const MenuItemLink = styled(Link)`
|
|
189
|
+
display: flex;
|
|
190
|
+
align-items: center;
|
|
191
|
+
padding: 0 var(--spacing);
|
|
192
|
+
height: 48px;
|
|
193
|
+
|
|
194
|
+
img {
|
|
195
|
+
width: 24px;
|
|
196
|
+
height: 24px;
|
|
197
|
+
margin-right: var(--spacing);
|
|
198
|
+
flex: 0 0 24px;
|
|
199
|
+
}
|
|
200
|
+
`;
|
|
201
|
+
|
|
202
|
+
const MenuItemButton = styled(MenuItemLink)`
|
|
203
|
+
background-color: transparent;
|
|
204
|
+
border: none;
|
|
205
|
+
cursor: pointer;
|
|
206
|
+
width: 100%;
|
|
207
|
+
|
|
208
|
+
.arrow {
|
|
209
|
+
margin-left: auto;
|
|
210
|
+
color: var(--color-primary);
|
|
211
|
+
|
|
212
|
+
${({ open }) =>
|
|
213
|
+
open === true &&
|
|
214
|
+
css`
|
|
215
|
+
transform: rotate(90deg);
|
|
216
|
+
transition: all 0.4s;
|
|
217
|
+
`};
|
|
218
|
+
}
|
|
219
|
+
`;
|
|
220
|
+
|
|
221
|
+
const SubMenu = styled.ul`
|
|
222
|
+
overflow: hidden;
|
|
223
|
+
height: ${(props) => (props.open === true ? 'auto' : '0px')};
|
|
224
|
+
`;
|
|
225
|
+
|
|
226
|
+
const SubMenuItem = styled.li`
|
|
227
|
+
a {
|
|
228
|
+
display: flex;
|
|
229
|
+
align-items: center;
|
|
230
|
+
padding: 0 calc(var(--spacing) * 2 + 1.5rem);
|
|
231
|
+
height: 48px;
|
|
232
|
+
|
|
233
|
+
${({ active }) =>
|
|
234
|
+
active === true &&
|
|
235
|
+
css`
|
|
236
|
+
background: var(--color-active);
|
|
237
|
+
`};
|
|
238
|
+
}
|
|
239
|
+
`;
|
|
240
|
+
|
|
241
|
+
export default Sidebar;
|