orcs-design-system 3.3.39 → 3.3.41
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/es/components/Divider/index.js +1 -1
- package/es/components/Icon/index.js +45 -27
- package/es/components/Popover/index.js +9 -1
- package/es/components/SideNavV2/NavItem.js +231 -0
- package/es/components/SideNavV2/SideNav.js +295 -0
- package/es/components/SideNavV2/SideNavV2.stories.js +382 -0
- package/es/components/SideNavV2/__tests__/resize.test.js +129 -0
- package/es/components/SideNavV2/__tests__/sections.test.js +333 -0
- package/es/components/SideNavV2/components/BaseSection.js +178 -0
- package/es/components/SideNavV2/components/CurrentViewSectionPortalTarget.js +35 -0
- package/es/components/SideNavV2/components/ExpandedPanel.js +161 -0
- package/es/components/SideNavV2/components/ItemSection.js +156 -0
- package/es/components/SideNavV2/components/PanelControl.js +128 -0
- package/es/components/SideNavV2/components/RenderCurrentViewSection.js +39 -0
- package/es/components/SideNavV2/components/index.js +4 -0
- package/es/components/SideNavV2/constants/sideNav.js +21 -0
- package/es/components/SideNavV2/context/SideNavStateProvider.js +57 -0
- package/es/components/SideNavV2/hooks/index.js +3 -0
- package/es/components/SideNavV2/hooks/useResize.js +70 -0
- package/es/components/SideNavV2/hooks/useResponsive.js +32 -0
- package/es/components/SideNavV2/hooks/useSideNavState.js +88 -0
- package/es/components/SideNavV2/index.js +3 -0
- package/es/components/SideNavV2/sections/SideNavCurrentViewSection.js +124 -0
- package/es/components/SideNavV2/sections/SideNavPinnedSection.js +125 -0
- package/es/components/SideNavV2/sections/SideNavTeamsSection.js +91 -0
- package/es/components/SideNavV2/styles/SideNavV2.styles.js +156 -0
- package/es/components/SideNavV2/types/sideNav.js +53 -0
- package/es/components/SideNavV2/utils/index.js +2 -0
- package/es/components/SideNavV2/utils/itemUtils.js +51 -0
- package/es/components/SideNavV2/utils/resizeUtils.js +57 -0
- package/es/components/StatusDot/StatusDot.stories.js +59 -72
- package/es/components/StatusDot/index.js +14 -5
- package/es/components.test.js +4 -0
- package/es/index.js +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { H5, H6 } from "../../Typography";
|
|
5
|
+
import Avatar from "../../Avatar";
|
|
6
|
+
import { NavLink } from "react-router-dom";
|
|
7
|
+
import themeGet from "@styled-system/theme-get";
|
|
8
|
+
import Flex from "../../Flex";
|
|
9
|
+
import Popover from "../../Popover";
|
|
10
|
+
import { CurrentViewSectionShape } from "../types/sideNav";
|
|
11
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
|
+
const SubNavList = styled.ul.withConfig({
|
|
13
|
+
displayName: "SideNavCurrentViewSection__SubNavList",
|
|
14
|
+
componentId: "sc-12clz4a-0"
|
|
15
|
+
})(["list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:", ";width:100%;"], props => themeGet("space.s")(props));
|
|
16
|
+
const StyledNavLink = styled(NavLink).withConfig({
|
|
17
|
+
displayName: "SideNavCurrentViewSection__StyledNavLink",
|
|
18
|
+
componentId: "sc-12clz4a-1"
|
|
19
|
+
})(["font-size:", ";border-left:2px solid transparent;padding-left:", ";transition:border-left 0.2s ease;color:", ";text-decoration:none;span{display:block;padding:2px 0;}&:hover,&:focus{outline:none;color:", ";}&.active{border-left:2px solid ", ";color:", ";}"], themeGet("fontSizes.1"), themeGet("space.s"), themeGet("colors.greyDarkest"), themeGet("colors.primary"), themeGet("colors.primary"), themeGet("colors.primary"));
|
|
20
|
+
const CurrentViewContent = _ref => {
|
|
21
|
+
let {
|
|
22
|
+
name,
|
|
23
|
+
badge,
|
|
24
|
+
subNav,
|
|
25
|
+
isExpanded
|
|
26
|
+
} = _ref;
|
|
27
|
+
return /*#__PURE__*/_jsxs(Flex, {
|
|
28
|
+
flexDirection: "column",
|
|
29
|
+
gap: "s",
|
|
30
|
+
p: isExpanded ? "0" : "s",
|
|
31
|
+
children: [/*#__PURE__*/_jsx(H6, {
|
|
32
|
+
sizing: "small",
|
|
33
|
+
color: "greyDark",
|
|
34
|
+
children: "Currently Viewing"
|
|
35
|
+
}), /*#__PURE__*/_jsxs(Flex, {
|
|
36
|
+
flexWrap: "wrap",
|
|
37
|
+
gap: "s",
|
|
38
|
+
mt: isExpanded ? "0" : "s",
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
children: [/*#__PURE__*/_jsx(H5, {
|
|
41
|
+
fontWeight: "bold",
|
|
42
|
+
children: name
|
|
43
|
+
}), badge]
|
|
44
|
+
}), /*#__PURE__*/_jsx(SubNavList, {
|
|
45
|
+
children: subNav?.map(_ref2 => {
|
|
46
|
+
let {
|
|
47
|
+
name,
|
|
48
|
+
link
|
|
49
|
+
} = _ref2;
|
|
50
|
+
return /*#__PURE__*/_jsx(StyledNavLink, {
|
|
51
|
+
to: link,
|
|
52
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
53
|
+
children: name
|
|
54
|
+
})
|
|
55
|
+
}, name);
|
|
56
|
+
})
|
|
57
|
+
})]
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
CurrentViewContent.propTypes = {
|
|
61
|
+
...CurrentViewSectionShape,
|
|
62
|
+
isExpanded: PropTypes.bool
|
|
63
|
+
};
|
|
64
|
+
const SideNavCurrentViewSection = _ref3 => {
|
|
65
|
+
let {
|
|
66
|
+
name,
|
|
67
|
+
badge,
|
|
68
|
+
subNav,
|
|
69
|
+
isExpanded,
|
|
70
|
+
avatar,
|
|
71
|
+
shape,
|
|
72
|
+
isSmallScreen
|
|
73
|
+
} = _ref3;
|
|
74
|
+
const currentViewMarkup = /*#__PURE__*/_jsx(CurrentViewContent, {
|
|
75
|
+
name: name,
|
|
76
|
+
badge: badge,
|
|
77
|
+
subNav: subNav,
|
|
78
|
+
isExpanded: isExpanded
|
|
79
|
+
});
|
|
80
|
+
return /*#__PURE__*/_jsxs(Flex, {
|
|
81
|
+
isExpanded: isExpanded,
|
|
82
|
+
flexDirection: "column",
|
|
83
|
+
gap: "s",
|
|
84
|
+
mt: isExpanded ? "s" : "0",
|
|
85
|
+
children: [(!isExpanded || isSmallScreen) && /*#__PURE__*/_jsx(Popover, {
|
|
86
|
+
direction: isSmallScreen ? "top" : "right",
|
|
87
|
+
width: "fit-content",
|
|
88
|
+
text: currentViewMarkup,
|
|
89
|
+
children: /*#__PURE__*/_jsx(Avatar, {
|
|
90
|
+
image: avatar,
|
|
91
|
+
customSize: "30px",
|
|
92
|
+
shape: shape
|
|
93
|
+
})
|
|
94
|
+
}), isExpanded && !isSmallScreen && currentViewMarkup]
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
SideNavCurrentViewSection.propTypes = {
|
|
98
|
+
...CurrentViewSectionShape,
|
|
99
|
+
isExpanded: PropTypes.bool,
|
|
100
|
+
isSmallScreen: PropTypes.bool
|
|
101
|
+
};
|
|
102
|
+
SideNavCurrentViewSection.__docgenInfo = {
|
|
103
|
+
"description": "",
|
|
104
|
+
"methods": [],
|
|
105
|
+
"displayName": "SideNavCurrentViewSection",
|
|
106
|
+
"props": {
|
|
107
|
+
"isExpanded": {
|
|
108
|
+
"description": "",
|
|
109
|
+
"type": {
|
|
110
|
+
"name": "bool"
|
|
111
|
+
},
|
|
112
|
+
"required": false
|
|
113
|
+
},
|
|
114
|
+
"isSmallScreen": {
|
|
115
|
+
"description": "",
|
|
116
|
+
"type": {
|
|
117
|
+
"name": "bool"
|
|
118
|
+
},
|
|
119
|
+
"required": false
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"composes": ["../types/sideNav"]
|
|
123
|
+
};
|
|
124
|
+
export default SideNavCurrentViewSection;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Popover from "../../Popover";
|
|
4
|
+
import Icon from "../../Icon";
|
|
5
|
+
import Button from "../../Button";
|
|
6
|
+
import BaseSection, { AvatarLink, Item } from "../components/BaseSection";
|
|
7
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
const SideNavPinnedSection = _ref => {
|
|
9
|
+
let {
|
|
10
|
+
items,
|
|
11
|
+
isExpanded
|
|
12
|
+
} = _ref;
|
|
13
|
+
const renderPinnedItem = (item, isExpanded) => {
|
|
14
|
+
const {
|
|
15
|
+
avatar,
|
|
16
|
+
name,
|
|
17
|
+
link,
|
|
18
|
+
shape,
|
|
19
|
+
onUnpin
|
|
20
|
+
} = item;
|
|
21
|
+
return /*#__PURE__*/_jsx(Item, {
|
|
22
|
+
children: isExpanded ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
23
|
+
children: [/*#__PURE__*/_jsx(AvatarLink, {
|
|
24
|
+
avatar: avatar,
|
|
25
|
+
name: name,
|
|
26
|
+
link: link,
|
|
27
|
+
shape: shape,
|
|
28
|
+
showName: true
|
|
29
|
+
}), /*#__PURE__*/_jsx(Popover, {
|
|
30
|
+
text: "Unpin item",
|
|
31
|
+
direction: "right",
|
|
32
|
+
width: "fit-content",
|
|
33
|
+
children: /*#__PURE__*/_jsx(Button, {
|
|
34
|
+
height: "20px",
|
|
35
|
+
width: "20px",
|
|
36
|
+
borderRadius: "20px",
|
|
37
|
+
variant: "borderGrey",
|
|
38
|
+
borderColor: "white",
|
|
39
|
+
onClick: () => onUnpin?.(item),
|
|
40
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
41
|
+
icon: ["fas", "thumbtack"],
|
|
42
|
+
secondaryIcon: ["fas", "slash"],
|
|
43
|
+
color: "greyDarkest",
|
|
44
|
+
size: "sm"
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
})]
|
|
48
|
+
}) : /*#__PURE__*/_jsx(Popover, {
|
|
49
|
+
text: name,
|
|
50
|
+
direction: "right",
|
|
51
|
+
width: "fit-content",
|
|
52
|
+
children: /*#__PURE__*/_jsx(AvatarLink, {
|
|
53
|
+
avatar: avatar,
|
|
54
|
+
name: name,
|
|
55
|
+
link: link,
|
|
56
|
+
shape: shape,
|
|
57
|
+
showName: false
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
}, name);
|
|
61
|
+
};
|
|
62
|
+
return /*#__PURE__*/_jsx(BaseSection, {
|
|
63
|
+
title: "Pinned",
|
|
64
|
+
items: items,
|
|
65
|
+
isExpanded: isExpanded,
|
|
66
|
+
renderItem: renderPinnedItem
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
SideNavPinnedSection.propTypes = {
|
|
70
|
+
items: PropTypes.arrayOf(PropTypes.shape({
|
|
71
|
+
avatar: PropTypes.string,
|
|
72
|
+
name: PropTypes.string.isRequired,
|
|
73
|
+
link: PropTypes.string.isRequired,
|
|
74
|
+
shape: PropTypes.string,
|
|
75
|
+
onUnpin: PropTypes.func
|
|
76
|
+
})),
|
|
77
|
+
isExpanded: PropTypes.bool
|
|
78
|
+
};
|
|
79
|
+
SideNavPinnedSection.__docgenInfo = {
|
|
80
|
+
"description": "",
|
|
81
|
+
"methods": [],
|
|
82
|
+
"displayName": "SideNavPinnedSection",
|
|
83
|
+
"props": {
|
|
84
|
+
"items": {
|
|
85
|
+
"description": "",
|
|
86
|
+
"type": {
|
|
87
|
+
"name": "arrayOf",
|
|
88
|
+
"value": {
|
|
89
|
+
"name": "shape",
|
|
90
|
+
"value": {
|
|
91
|
+
"avatar": {
|
|
92
|
+
"name": "string",
|
|
93
|
+
"required": false
|
|
94
|
+
},
|
|
95
|
+
"name": {
|
|
96
|
+
"name": "string",
|
|
97
|
+
"required": true
|
|
98
|
+
},
|
|
99
|
+
"link": {
|
|
100
|
+
"name": "string",
|
|
101
|
+
"required": true
|
|
102
|
+
},
|
|
103
|
+
"shape": {
|
|
104
|
+
"name": "string",
|
|
105
|
+
"required": false
|
|
106
|
+
},
|
|
107
|
+
"onUnpin": {
|
|
108
|
+
"name": "func",
|
|
109
|
+
"required": false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"required": false
|
|
115
|
+
},
|
|
116
|
+
"isExpanded": {
|
|
117
|
+
"description": "",
|
|
118
|
+
"type": {
|
|
119
|
+
"name": "bool"
|
|
120
|
+
},
|
|
121
|
+
"required": false
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
export default SideNavPinnedSection;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import Popover from "../../Popover";
|
|
4
|
+
import BaseSection, { AvatarLink, Item } from "../components/BaseSection";
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
const SideNavTeamsSection = _ref => {
|
|
7
|
+
let {
|
|
8
|
+
teams,
|
|
9
|
+
isExpanded
|
|
10
|
+
} = _ref;
|
|
11
|
+
const renderTeamItem = (team, isExpanded) => {
|
|
12
|
+
const {
|
|
13
|
+
avatar,
|
|
14
|
+
name,
|
|
15
|
+
link
|
|
16
|
+
} = team;
|
|
17
|
+
return /*#__PURE__*/_jsx(Item, {
|
|
18
|
+
children: isExpanded ? /*#__PURE__*/_jsx(AvatarLink, {
|
|
19
|
+
avatar: avatar,
|
|
20
|
+
name: name,
|
|
21
|
+
link: link,
|
|
22
|
+
shape: "square",
|
|
23
|
+
showName: true
|
|
24
|
+
}) : /*#__PURE__*/_jsx(Popover, {
|
|
25
|
+
text: name,
|
|
26
|
+
direction: "right",
|
|
27
|
+
width: "fit-content",
|
|
28
|
+
children: /*#__PURE__*/_jsx(AvatarLink, {
|
|
29
|
+
avatar: avatar,
|
|
30
|
+
name: name,
|
|
31
|
+
link: link,
|
|
32
|
+
shape: "square",
|
|
33
|
+
showName: false
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
}, name);
|
|
37
|
+
};
|
|
38
|
+
return /*#__PURE__*/_jsx(BaseSection, {
|
|
39
|
+
title: "Your Teams",
|
|
40
|
+
items: teams,
|
|
41
|
+
isExpanded: isExpanded,
|
|
42
|
+
renderItem: renderTeamItem
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
SideNavTeamsSection.propTypes = {
|
|
46
|
+
teams: PropTypes.arrayOf(PropTypes.shape({
|
|
47
|
+
avatar: PropTypes.string,
|
|
48
|
+
name: PropTypes.string.isRequired,
|
|
49
|
+
link: PropTypes.string.isRequired
|
|
50
|
+
})),
|
|
51
|
+
isExpanded: PropTypes.bool
|
|
52
|
+
};
|
|
53
|
+
SideNavTeamsSection.__docgenInfo = {
|
|
54
|
+
"description": "",
|
|
55
|
+
"methods": [],
|
|
56
|
+
"displayName": "SideNavTeamsSection",
|
|
57
|
+
"props": {
|
|
58
|
+
"teams": {
|
|
59
|
+
"description": "",
|
|
60
|
+
"type": {
|
|
61
|
+
"name": "arrayOf",
|
|
62
|
+
"value": {
|
|
63
|
+
"name": "shape",
|
|
64
|
+
"value": {
|
|
65
|
+
"avatar": {
|
|
66
|
+
"name": "string",
|
|
67
|
+
"required": false
|
|
68
|
+
},
|
|
69
|
+
"name": {
|
|
70
|
+
"name": "string",
|
|
71
|
+
"required": true
|
|
72
|
+
},
|
|
73
|
+
"link": {
|
|
74
|
+
"name": "string",
|
|
75
|
+
"required": true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"required": false
|
|
81
|
+
},
|
|
82
|
+
"isExpanded": {
|
|
83
|
+
"description": "",
|
|
84
|
+
"type": {
|
|
85
|
+
"name": "bool"
|
|
86
|
+
},
|
|
87
|
+
"required": false
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
export default SideNavTeamsSection;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { css } from "@styled-system/css";
|
|
3
|
+
import { themeGet } from "@styled-system/theme-get";
|
|
4
|
+
import Popover from "../../Popover";
|
|
5
|
+
import { BREAKPOINTS, DEFAULT_WIDTHS } from "../constants/sideNav";
|
|
6
|
+
export const SideNavWrapper = styled("div").withConfig({
|
|
7
|
+
displayName: "SideNavV2styles__SideNavWrapper",
|
|
8
|
+
componentId: "sc-y5tsj2-0"
|
|
9
|
+
})(props => css({
|
|
10
|
+
bg: themeGet("colors.white")(props),
|
|
11
|
+
color: themeGet("colors.greyDarkest")(props),
|
|
12
|
+
minHeight: props.sideNavHeight || "100%",
|
|
13
|
+
height: props.sideNavHeight || "100%",
|
|
14
|
+
maxWidth: "max-content",
|
|
15
|
+
fontFamily: themeGet("fonts.main")(props),
|
|
16
|
+
borderRight: `solid 1px ${themeGet("colors.greyLighter")(props)}`,
|
|
17
|
+
display: "flex",
|
|
18
|
+
alignItems: "stretch",
|
|
19
|
+
alignContent: "stretch",
|
|
20
|
+
[`@media screen and (max-width: ${BREAKPOINTS.SMALL_SCREEN}px)`]: {
|
|
21
|
+
borderRight: "none",
|
|
22
|
+
borderTop: `solid 1px ${themeGet("colors.greyLighter")(props)}`,
|
|
23
|
+
width: "100%",
|
|
24
|
+
height: "auto",
|
|
25
|
+
minWidth: "auto",
|
|
26
|
+
maxWidth: "initial",
|
|
27
|
+
minHeight: "initial",
|
|
28
|
+
maxHeight: themeGet("appScale.sidebarMobileHeight", "100vh")(props),
|
|
29
|
+
position: "fixed",
|
|
30
|
+
bottom: "0",
|
|
31
|
+
left: "0",
|
|
32
|
+
zIndex: "6",
|
|
33
|
+
flexDirection: "column-reverse"
|
|
34
|
+
}
|
|
35
|
+
}));
|
|
36
|
+
export const SideNavItems = styled("div").withConfig({
|
|
37
|
+
displayName: "SideNavV2styles__SideNavItems",
|
|
38
|
+
componentId: "sc-y5tsj2-1"
|
|
39
|
+
})(props => css({
|
|
40
|
+
width: props.isExpanded ? "200px" : themeGet("appScale.sideNavSize")(props),
|
|
41
|
+
minHeight: "inherit",
|
|
42
|
+
height: "100%",
|
|
43
|
+
overflowX: "hidden",
|
|
44
|
+
overflowY: "auto",
|
|
45
|
+
display: "flex",
|
|
46
|
+
flexDirection: "column",
|
|
47
|
+
flexShrink: "0",
|
|
48
|
+
padding: "10px",
|
|
49
|
+
gap: "s",
|
|
50
|
+
alignItems: props.isExpanded ? "stretch" : "center",
|
|
51
|
+
justifyContent: "flex-start",
|
|
52
|
+
textAlign: props.isExpanded ? "left" : "center",
|
|
53
|
+
position: "relative",
|
|
54
|
+
[`@media screen and (max-width: ${BREAKPOINTS.SMALL_SCREEN}px)`]: {
|
|
55
|
+
height: "auto",
|
|
56
|
+
flexDirection: "row",
|
|
57
|
+
justifyContent: "space-around",
|
|
58
|
+
alignItems: "center",
|
|
59
|
+
width: "auto"
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
export const PanelControlTooltip = styled(Popover).withConfig({
|
|
63
|
+
displayName: "SideNavV2styles__PanelControlTooltip",
|
|
64
|
+
componentId: "sc-y5tsj2-2"
|
|
65
|
+
})(["width:fit-content;margin:2px 0 4px 0;", ""], props => props.position === "absolute" && css({
|
|
66
|
+
position: "absolute",
|
|
67
|
+
right: themeGet("space.r")(props),
|
|
68
|
+
top: themeGet("space.r")(props)
|
|
69
|
+
}));
|
|
70
|
+
export const PanelControl = styled("button").withConfig({
|
|
71
|
+
displayName: "SideNavV2styles__PanelControl",
|
|
72
|
+
componentId: "sc-y5tsj2-3"
|
|
73
|
+
})(props => css({
|
|
74
|
+
borderRadius: "50%",
|
|
75
|
+
width: "20px",
|
|
76
|
+
height: "20px",
|
|
77
|
+
background: themeGet("colors.greyLighter")(props),
|
|
78
|
+
color: themeGet("colors.greyDarker")(props),
|
|
79
|
+
fontSize: "1.2rem",
|
|
80
|
+
display: "flex",
|
|
81
|
+
alignItems: "center",
|
|
82
|
+
justifyContent: "center",
|
|
83
|
+
cursor: "pointer",
|
|
84
|
+
border: "none"
|
|
85
|
+
}));
|
|
86
|
+
export const ResizeHandle = styled("div").withConfig({
|
|
87
|
+
displayName: "SideNavV2styles__ResizeHandle",
|
|
88
|
+
componentId: "sc-y5tsj2-4"
|
|
89
|
+
})(props => css({
|
|
90
|
+
position: "absolute",
|
|
91
|
+
right: "0",
|
|
92
|
+
top: "0",
|
|
93
|
+
bottom: "0",
|
|
94
|
+
width: "6px",
|
|
95
|
+
height: "100%",
|
|
96
|
+
cursor: "col-resize",
|
|
97
|
+
backgroundColor: "rgba(0, 0, 0, 0.05)",
|
|
98
|
+
zIndex: "1000",
|
|
99
|
+
"&:hover": {
|
|
100
|
+
backgroundColor: "rgba(0, 0, 0, 0.1)"
|
|
101
|
+
},
|
|
102
|
+
"&::before": {
|
|
103
|
+
content: '""',
|
|
104
|
+
position: "absolute",
|
|
105
|
+
right: "1px",
|
|
106
|
+
top: "50%",
|
|
107
|
+
transform: "translateY(-50%)",
|
|
108
|
+
width: "3px",
|
|
109
|
+
height: "40px",
|
|
110
|
+
backgroundColor: themeGet("colors.grey")(props),
|
|
111
|
+
borderRadius: "3px"
|
|
112
|
+
},
|
|
113
|
+
[`@media screen and (max-width: ${BREAKPOINTS.SMALL_SCREEN}px)`]: {
|
|
114
|
+
right: "auto",
|
|
115
|
+
top: "0",
|
|
116
|
+
left: "0",
|
|
117
|
+
bottom: "0",
|
|
118
|
+
width: "100%",
|
|
119
|
+
height: "6px",
|
|
120
|
+
cursor: "row-resize",
|
|
121
|
+
"&::before": {
|
|
122
|
+
right: "auto",
|
|
123
|
+
top: "50%",
|
|
124
|
+
left: "50%",
|
|
125
|
+
transform: "translate(-50%, -50%)",
|
|
126
|
+
width: "40px",
|
|
127
|
+
height: "3px"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}));
|
|
131
|
+
export const SideNavExpanded = styled("div").withConfig({
|
|
132
|
+
displayName: "SideNavV2styles__SideNavExpanded",
|
|
133
|
+
componentId: "sc-y5tsj2-5"
|
|
134
|
+
})(props => css({
|
|
135
|
+
position: "relative",
|
|
136
|
+
display: props.active ? "block" : "none",
|
|
137
|
+
width: props.width ? `${props.width}px` : "auto",
|
|
138
|
+
minWidth: `${DEFAULT_WIDTHS.min}px`,
|
|
139
|
+
maxWidth: `${DEFAULT_WIDTHS.max}px`,
|
|
140
|
+
height: "inherit",
|
|
141
|
+
overflowY: "auto",
|
|
142
|
+
overflowX: "hidden",
|
|
143
|
+
padding: "16px",
|
|
144
|
+
borderLeft: `solid 1px ${themeGet("colors.greyLighter")(props)}`,
|
|
145
|
+
"&:focus": {
|
|
146
|
+
outline: "0"
|
|
147
|
+
},
|
|
148
|
+
[`@media screen and (max-width: ${BREAKPOINTS.SMALL_SCREEN}px)`]: {
|
|
149
|
+
width: "100%",
|
|
150
|
+
minWidth: "initial",
|
|
151
|
+
maxWidth: "initial",
|
|
152
|
+
borderLeft: "none",
|
|
153
|
+
borderBottom: `solid 1px ${themeGet("colors.greyLighter")(props)}`,
|
|
154
|
+
height: "calc(" + themeGet("appScale.sidebarMobileHeight", "100vh")(props) + " - " + themeGet("appScale.newNavBarSize")(props) + ")"
|
|
155
|
+
}
|
|
156
|
+
}));
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import PropTypes from "prop-types";
|
|
2
|
+
import { BADGE_VARIANTS, ITEM_TYPES } from "../constants/sideNav";
|
|
3
|
+
export const NavigationItemShape = {
|
|
4
|
+
iconName: PropTypes.string.isRequired,
|
|
5
|
+
name: PropTypes.string.isRequired,
|
|
6
|
+
badgeNumber: PropTypes.string,
|
|
7
|
+
badgeDot: PropTypes.bool,
|
|
8
|
+
hide: PropTypes.bool,
|
|
9
|
+
large: PropTypes.bool,
|
|
10
|
+
bottomAligned: PropTypes.bool,
|
|
11
|
+
actionType: PropTypes.oneOf(Object.values(ITEM_TYPES)).isRequired,
|
|
12
|
+
component: PropTypes.elementType,
|
|
13
|
+
link: PropTypes.string,
|
|
14
|
+
onClick: PropTypes.func,
|
|
15
|
+
isActive: PropTypes.bool,
|
|
16
|
+
pageSpecific: PropTypes.bool,
|
|
17
|
+
isExpandedByDefault: PropTypes.bool
|
|
18
|
+
};
|
|
19
|
+
export const ViewingSectionShape = {
|
|
20
|
+
teamName: PropTypes.string.isRequired,
|
|
21
|
+
avatar: PropTypes.string,
|
|
22
|
+
shape: PropTypes.string,
|
|
23
|
+
teamLink: PropTypes.string.isRequired,
|
|
24
|
+
teamType: PropTypes.string,
|
|
25
|
+
badgeVariant: PropTypes.oneOf(BADGE_VARIANTS),
|
|
26
|
+
subNav: PropTypes.arrayOf(PropTypes.shape({
|
|
27
|
+
name: PropTypes.string.isRequired,
|
|
28
|
+
link: PropTypes.string.isRequired
|
|
29
|
+
}))
|
|
30
|
+
};
|
|
31
|
+
export const TeamShape = {
|
|
32
|
+
avatar: PropTypes.string,
|
|
33
|
+
name: PropTypes.string.isRequired,
|
|
34
|
+
link: PropTypes.string.isRequired
|
|
35
|
+
};
|
|
36
|
+
export const PinnedItemShape = {
|
|
37
|
+
avatar: PropTypes.string,
|
|
38
|
+
name: PropTypes.string.isRequired,
|
|
39
|
+
link: PropTypes.string.isRequired,
|
|
40
|
+
shape: PropTypes.string,
|
|
41
|
+
onUnpin: PropTypes.func
|
|
42
|
+
};
|
|
43
|
+
export const SubNavItemShape = {
|
|
44
|
+
name: PropTypes.string.isRequired,
|
|
45
|
+
link: PropTypes.string.isRequired
|
|
46
|
+
};
|
|
47
|
+
export const CurrentViewSectionShape = {
|
|
48
|
+
name: PropTypes.string.isRequired,
|
|
49
|
+
avatar: PropTypes.string,
|
|
50
|
+
shape: PropTypes.string,
|
|
51
|
+
badge: PropTypes.node,
|
|
52
|
+
subNav: PropTypes.arrayOf(SubNavItemShape)
|
|
53
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Categorizes navigation items into different sections based on their properties
|
|
3
|
+
* @param {Array} items - Array of navigation items
|
|
4
|
+
* @returns {Object} Object containing categorized items
|
|
5
|
+
*/
|
|
6
|
+
export const categorizeItems = items => {
|
|
7
|
+
const allItems = items.map((item, index) => ({
|
|
8
|
+
...item,
|
|
9
|
+
index
|
|
10
|
+
}));
|
|
11
|
+
const topAlignedItems = allItems.filter(item => !item.bottomAligned && !item.pageSpecific);
|
|
12
|
+
const pageSpecificItems = allItems.filter(item => !item.bottomAligned && item.pageSpecific);
|
|
13
|
+
const bottomAlignedItems = allItems.filter(item => item.bottomAligned);
|
|
14
|
+
return {
|
|
15
|
+
topAlignedItems,
|
|
16
|
+
pageSpecificItems,
|
|
17
|
+
bottomAlignedItems,
|
|
18
|
+
allItems
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Filters out hidden items from a list
|
|
24
|
+
* @param {Array} items - Array of navigation items
|
|
25
|
+
* @returns {Array} Filtered items without hidden ones
|
|
26
|
+
*/
|
|
27
|
+
export const filterVisibleItems = items => {
|
|
28
|
+
return items.filter(item => !item.hide);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Finds the first item that should be expanded by default
|
|
33
|
+
* @param {Array} items - Array of navigation items
|
|
34
|
+
* @returns {number} Index of the first item to expand by default, or -1 if none
|
|
35
|
+
*/
|
|
36
|
+
export const findFirstExpandedByDefault = items => {
|
|
37
|
+
return items.findIndex(item => item.isExpandedByDefault && !item.hide);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Determines if an item should be active based on its type and state
|
|
42
|
+
* @param {Object} item - Navigation item
|
|
43
|
+
* @param {number} expandedItem - Currently expanded item index
|
|
44
|
+
* @returns {boolean} Whether the item should be active
|
|
45
|
+
*/
|
|
46
|
+
export const isItemActive = (item, expandedItem) => {
|
|
47
|
+
if (item.actionType === "link") {
|
|
48
|
+
return item.isActive;
|
|
49
|
+
}
|
|
50
|
+
return expandedItem === item.index;
|
|
51
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { DEFAULT_WIDTHS, RESIZE_CONFIG } from "../constants/sideNav";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Calculates the clamped width for desktop resize
|
|
5
|
+
* @param {number} clientX - Mouse X position
|
|
6
|
+
* @param {Element} sideNavItems - SideNavItems element
|
|
7
|
+
* @returns {number} Clamped width value
|
|
8
|
+
*/
|
|
9
|
+
export const calculateDesktopWidth = (clientX, sideNavItems) => {
|
|
10
|
+
if (!sideNavItems) return DEFAULT_WIDTHS.normal;
|
|
11
|
+
const sideNavRect = sideNavItems.getBoundingClientRect();
|
|
12
|
+
const newWidth = clientX - sideNavRect.right;
|
|
13
|
+
return Math.max(DEFAULT_WIDTHS.min, Math.min(DEFAULT_WIDTHS.max, newWidth));
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Calculates the clamped height for mobile resize
|
|
18
|
+
* @param {number} clientY - Mouse Y position
|
|
19
|
+
* @param {number} resizeStartY - Starting Y position
|
|
20
|
+
* @param {number} resizeStartHeight - Starting height
|
|
21
|
+
* @returns {number} Clamped height value
|
|
22
|
+
*/
|
|
23
|
+
export const calculateMobileHeight = (clientY, resizeStartY, resizeStartHeight) => {
|
|
24
|
+
const deltaY = clientY - resizeStartY;
|
|
25
|
+
const newHeight = resizeStartHeight - deltaY; // Reversed direction
|
|
26
|
+
|
|
27
|
+
const minHeight = RESIZE_CONFIG.MOBILE_MIN_HEIGHT;
|
|
28
|
+
const maxHeight = window.innerHeight * RESIZE_CONFIG.MOBILE_MAX_HEIGHT_RATIO;
|
|
29
|
+
return Math.max(minHeight, Math.min(maxHeight, newHeight));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Gets the initial width for an expanded item
|
|
34
|
+
* @param {Object} item - Navigation item
|
|
35
|
+
* @returns {number} Initial width
|
|
36
|
+
*/
|
|
37
|
+
export const getInitialWidth = item => {
|
|
38
|
+
const isLarge = item?.large;
|
|
39
|
+
return isLarge ? DEFAULT_WIDTHS.large : DEFAULT_WIDTHS.normal;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Applies resize cursor styles to document body
|
|
44
|
+
* @param {boolean} isSmallScreen - Whether we're on a small screen
|
|
45
|
+
*/
|
|
46
|
+
export const applyResizeCursor = isSmallScreen => {
|
|
47
|
+
document.body.style.cursor = isSmallScreen ? "row-resize" : "col-resize";
|
|
48
|
+
document.body.style.userSelect = "none";
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Removes resize cursor styles from document body
|
|
53
|
+
*/
|
|
54
|
+
export const removeResizeCursor = () => {
|
|
55
|
+
document.body.style.cursor = "";
|
|
56
|
+
document.body.style.userSelect = "";
|
|
57
|
+
};
|