@smartbooks-ai/layout 0.0.6 → 0.0.8
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/dist/components/PageWithMenuLayout/AppSelect/index.d.ts +0 -1
- package/dist/components/PageWithMenuLayout/AppSelect/index.d.ts.map +1 -1
- package/dist/components/PageWithMenuLayout/AppSelect/index.js +2 -2
- package/dist/components/PageWithMenuLayout/PageWithMenuLayout.d.ts +0 -1
- package/dist/components/PageWithMenuLayout/PageWithMenuLayout.d.ts.map +1 -1
- package/dist/components/PageWithMenuLayout/PageWithMenuLayout.js +2 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/theme/colorPrimitives.d.ts +1 -1
- package/dist/theme/colorPrimitives.d.ts.map +1 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/typography.d.ts.map +1 -1
- package/package.json +35 -32
- package/src/components/PageHeader/PageHeader.tsx +0 -15
- package/src/components/PageHeader/index.ts +0 -1
- package/src/components/PageHeader/styles.ts +0 -34
- package/src/components/PageWithMenuLayout/AppSelect/index.tsx +0 -66
- package/src/components/PageWithMenuLayout/AppSelect/styles.ts +0 -33
- package/src/components/PageWithMenuLayout/LogoHeaderImage.tsx +0 -44
- package/src/components/PageWithMenuLayout/LogoHeaderText.tsx +0 -48
- package/src/components/PageWithMenuLayout/MenuItemWithChildren/MenuItemWithChildren.tsx +0 -149
- package/src/components/PageWithMenuLayout/MenuItemWithChildren/styles.ts +0 -179
- package/src/components/PageWithMenuLayout/MenuSelect/index.tsx +0 -78
- package/src/components/PageWithMenuLayout/MenuSelect/styles.ts +0 -97
- package/src/components/PageWithMenuLayout/MultiSubscriptionsMenuItems/ConsolidationIcon.tsx +0 -6
- package/src/components/PageWithMenuLayout/MultiSubscriptionsMenuItems/MultiSubscriptionsMenuItems.tsx +0 -120
- package/src/components/PageWithMenuLayout/MultiSubscriptionsMenuItems/consolidation.svg +0 -8
- package/src/components/PageWithMenuLayout/MultiSubscriptionsMenuItems/index.ts +0 -1
- package/src/components/PageWithMenuLayout/MultiSubscriptionsMenuItems/styles.ts +0 -10
- package/src/components/PageWithMenuLayout/PageWithMenuLayout.tsx +0 -103
- package/src/components/PageWithMenuLayout/UserProfileSelect/index.tsx +0 -64
- package/src/components/PageWithMenuLayout/UserProfileSelect/styles.ts +0 -8
- package/src/components/PageWithMenuLayout/index.ts +0 -8
- package/src/components/PageWithMenuLayout/styles.ts +0 -110
- package/src/components/PageWithMenuLayout/types.ts +0 -7
- package/src/components/PageWithMenuLayout/useMenuToggle.ts +0 -19
- package/src/components/index.ts +0 -3
- package/src/emotion.d.ts +0 -76
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useIsAuthorized.ts +0 -35
- package/src/hooks/useToggle.ts +0 -27
- package/src/index.ts +0 -7
- package/src/package-isolation.test.ts +0 -60
- package/src/security/AuthorizedContent/index.tsx +0 -77
- package/src/security/AuthorizedContent/state.ts +0 -8
- package/src/security/AuthorizedContent/useAuthorizationState.ts +0 -42
- package/src/security/ProfileContext/ProfileContext.tsx +0 -37
- package/src/security/ProfileContext/index.ts +0 -4
- package/src/security/ProfileContext/types.ts +0 -7
- package/src/security/ProfileContext/useProfile.tsx +0 -7
- package/src/security/UserProfile.ts +0 -48
- package/src/security/index.ts +0 -2
- package/src/theme/colorPrimitives.ts +0 -107
- package/src/theme/colors.ts +0 -78
- package/src/theme/font.ts +0 -27
- package/src/theme/globalStyles.tsx +0 -55
- package/src/theme/index.tsx +0 -228
- package/src/theme/radius.ts +0 -12
- package/src/theme/spacing.ts +0 -12
- package/src/theme/typography.ts +0 -40
- package/src/utils/assertNever.ts +0 -14
- package/src/utils/index.ts +0 -2
- package/src/utils/shouldNotForwardPropsWithKeys.ts +0 -7
- package/tsconfig.json +0 -34
- package/tsconfig.layout.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -10
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/react';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDownRounded';
|
|
4
|
-
import MuiListItemIcon from '@mui/material/ListItemIcon';
|
|
5
|
-
import MuiListItemText, { listItemTextClasses } from '@mui/material/ListItemText';
|
|
6
|
-
import MuiMenuItem, { menuItemClasses } from '@mui/material/MenuItem';
|
|
7
|
-
import MuiMenuList from '@mui/material/MenuList';
|
|
8
|
-
import { rem } from 'polished';
|
|
9
|
-
|
|
10
|
-
import { shouldNotForwardPropsWithKeys } from '../../../utils/shouldNotForwardPropsWithKeys';
|
|
11
|
-
|
|
12
|
-
const iconMargin = rem(-2);
|
|
13
|
-
|
|
14
|
-
type MenuItemProps = {
|
|
15
|
-
isHighlighted: boolean;
|
|
16
|
-
elevation?: number;
|
|
17
|
-
isMenuOpen: boolean;
|
|
18
|
-
isTitle: boolean;
|
|
19
|
-
};
|
|
20
|
-
export const MenuItem = styled(
|
|
21
|
-
MuiMenuItem,
|
|
22
|
-
shouldNotForwardPropsWithKeys<MenuItemProps>(['isHighlighted', 'elevation', 'isMenuOpen', 'isTitle']),
|
|
23
|
-
)<MenuItemProps>(
|
|
24
|
-
({ theme, elevation = 0, isHighlighted, isMenuOpen, isTitle, disabled }) => css`
|
|
25
|
-
display: flex;
|
|
26
|
-
|
|
27
|
-
align-items: center;
|
|
28
|
-
|
|
29
|
-
padding: ${theme.my.spacing.xxs};
|
|
30
|
-
padding-left: 0;
|
|
31
|
-
margin-top: ${elevation === 0 && isMenuOpen && isTitle && theme.my.spacing.sm};
|
|
32
|
-
margin-left: ${!isMenuOpen ? `calc(${theme.my.spacing.xxs} - ${iconMargin})` : 0};
|
|
33
|
-
|
|
34
|
-
font: ${isHighlighted ? theme.my.font.nav2 : theme.my.font.nav1};
|
|
35
|
-
|
|
36
|
-
color: ${theme.my.colors.text.white};
|
|
37
|
-
|
|
38
|
-
transition:
|
|
39
|
-
font-weight 0.3s,
|
|
40
|
-
margin 0.3s;
|
|
41
|
-
|
|
42
|
-
&:hover {
|
|
43
|
-
background-color: ${theme.my.colors.background.hover};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
${disabled &&
|
|
47
|
-
css`
|
|
48
|
-
&.${menuItemClasses.disabled} {
|
|
49
|
-
text-transform: uppercase;
|
|
50
|
-
|
|
51
|
-
pointer-events: initial;
|
|
52
|
-
|
|
53
|
-
background-color: initial;
|
|
54
|
-
|
|
55
|
-
opacity: 1;
|
|
56
|
-
}
|
|
57
|
-
`};
|
|
58
|
-
`,
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
export const ListItemIcon = styled(MuiListItemIcon)`
|
|
62
|
-
/* Icons from MUI have small paddings, so we need to artificially move them 2px ⬅︎ */
|
|
63
|
-
margin-left: ${iconMargin};
|
|
64
|
-
|
|
65
|
-
/* Increasing specificity */
|
|
66
|
-
&&& {
|
|
67
|
-
min-width: 1.75rem;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
color: ${({ theme }) => theme.my.colors.text.white};
|
|
71
|
-
`;
|
|
72
|
-
|
|
73
|
-
type ListItemTextProps = {
|
|
74
|
-
isHighlighted: boolean;
|
|
75
|
-
isTitle: boolean;
|
|
76
|
-
elevation: number;
|
|
77
|
-
};
|
|
78
|
-
export const ListItemText = styled(
|
|
79
|
-
MuiListItemText,
|
|
80
|
-
shouldNotForwardPropsWithKeys<ListItemTextProps>(['isHighlighted', 'elevation', 'isTitle']),
|
|
81
|
-
)<ListItemTextProps>(
|
|
82
|
-
({ theme, isHighlighted, elevation, isTitle }) => css`
|
|
83
|
-
margin-top: 0;
|
|
84
|
-
margin-bottom: 0;
|
|
85
|
-
|
|
86
|
-
white-space: nowrap;
|
|
87
|
-
|
|
88
|
-
.${listItemTextClasses.primary} {
|
|
89
|
-
padding-left: calc(${Math.max(elevation - 1, 0)} * ${theme.my.spacing.xxs});
|
|
90
|
-
|
|
91
|
-
overflow: hidden;
|
|
92
|
-
text-overflow: ellipsis;
|
|
93
|
-
|
|
94
|
-
font: ${isHighlighted ? theme.my.font.nav2 : theme.my.font.nav1};
|
|
95
|
-
|
|
96
|
-
transition: font 0.3s;
|
|
97
|
-
|
|
98
|
-
${isTitle &&
|
|
99
|
-
css`
|
|
100
|
-
font-weight: 800;
|
|
101
|
-
`};
|
|
102
|
-
}
|
|
103
|
-
`,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
export const ListItem = styled.section`
|
|
107
|
-
display: flex;
|
|
108
|
-
|
|
109
|
-
width: 100%;
|
|
110
|
-
|
|
111
|
-
overflow: hidden;
|
|
112
|
-
`;
|
|
113
|
-
|
|
114
|
-
type ArrowDownIconProps = {
|
|
115
|
-
isExpanded: boolean;
|
|
116
|
-
isVisible: boolean;
|
|
117
|
-
};
|
|
118
|
-
export const ArrowDownIcon = styled(
|
|
119
|
-
ArrowDropDownIcon,
|
|
120
|
-
shouldNotForwardPropsWithKeys<ArrowDownIconProps>(['isExpanded', 'isVisible']),
|
|
121
|
-
)<ArrowDownIconProps>(
|
|
122
|
-
({ isExpanded, isVisible, theme }) => css`
|
|
123
|
-
color: ${isExpanded ? theme.my.colors.primitives.common.white : theme.my.colors.primitives.darkNavy[300]};
|
|
124
|
-
|
|
125
|
-
opacity: ${isVisible ? 1 : 0};
|
|
126
|
-
|
|
127
|
-
transform: rotate(${isExpanded ? 180 : 0}deg);
|
|
128
|
-
|
|
129
|
-
transition:
|
|
130
|
-
transform 0.3s,
|
|
131
|
-
color 0.3s,
|
|
132
|
-
opacity 0.3s;
|
|
133
|
-
`,
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
type MenuListProps = {
|
|
137
|
-
elevation: number;
|
|
138
|
-
};
|
|
139
|
-
export const MenuList = styled(MuiMenuList, shouldNotForwardPropsWithKeys<MenuListProps>(['elevation']))<MenuListProps>`
|
|
140
|
-
padding-top: 0;
|
|
141
|
-
padding-bottom: 0;
|
|
142
|
-
|
|
143
|
-
overflow: auto;
|
|
144
|
-
|
|
145
|
-
background-color: ${({ elevation, theme }) =>
|
|
146
|
-
[
|
|
147
|
-
theme.my.colors.primitives.darkNavy[900],
|
|
148
|
-
theme.my.colors.primitives.darkNavy[800],
|
|
149
|
-
theme.my.colors.primitives.darkNavy[700],
|
|
150
|
-
][elevation]};
|
|
151
|
-
border-radius: ${({ elevation, theme }) => elevation === 1 && theme.my.radius.md};
|
|
152
|
-
`;
|
|
153
|
-
|
|
154
|
-
type ActiveMenuItemIndicatorProps = {
|
|
155
|
-
visible: boolean;
|
|
156
|
-
isMenuOpen: boolean;
|
|
157
|
-
};
|
|
158
|
-
export const ActiveMenuItemIndicator = styled(
|
|
159
|
-
'div',
|
|
160
|
-
shouldNotForwardPropsWithKeys<ActiveMenuItemIndicatorProps>(['visible', 'isMenuOpen']),
|
|
161
|
-
)<ActiveMenuItemIndicatorProps>(
|
|
162
|
-
({ theme, visible, isMenuOpen }) => css`
|
|
163
|
-
display: inline-block;
|
|
164
|
-
|
|
165
|
-
width: ${isMenuOpen ? theme.my.spacing.xxxs : 0};
|
|
166
|
-
height: 1rem;
|
|
167
|
-
|
|
168
|
-
margin-right: ${theme.my.spacing.xxs};
|
|
169
|
-
|
|
170
|
-
background-color: transparent;
|
|
171
|
-
border-radius: ${theme.my.radius.sm};
|
|
172
|
-
|
|
173
|
-
transition: 0.3s;
|
|
174
|
-
${visible &&
|
|
175
|
-
css`
|
|
176
|
-
background-color: ${theme.my.colors.secondary.main};
|
|
177
|
-
`};
|
|
178
|
-
`,
|
|
179
|
-
);
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Fade } from '@mui/material';
|
|
4
|
-
import useResizeObserver from 'use-resize-observer';
|
|
5
|
-
|
|
6
|
-
import * as Styled from './styles';
|
|
7
|
-
|
|
8
|
-
type Props = {
|
|
9
|
-
isExpanded: boolean;
|
|
10
|
-
renderMenuItems: (params: { closeMenu: () => void }) => React.ReactElement[];
|
|
11
|
-
startIcon?: React.ReactNode;
|
|
12
|
-
selectedOptionText?: string;
|
|
13
|
-
menuPosition?: 'top' | 'bottom';
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const MenuSelect: React.FC<Props> = ({
|
|
17
|
-
isExpanded,
|
|
18
|
-
renderMenuItems,
|
|
19
|
-
startIcon,
|
|
20
|
-
selectedOptionText,
|
|
21
|
-
menuPosition = 'bottom',
|
|
22
|
-
}) => {
|
|
23
|
-
const openMenu: React.MouseEventHandler<HTMLElement> = (event) => {
|
|
24
|
-
setAnchorEl(event.currentTarget);
|
|
25
|
-
};
|
|
26
|
-
const closeMenu = () => {
|
|
27
|
-
setAnchorEl(undefined);
|
|
28
|
-
};
|
|
29
|
-
const [anchorEl, setAnchorEl] = useState<HTMLElement>();
|
|
30
|
-
const isMenuOpen = Boolean(anchorEl);
|
|
31
|
-
|
|
32
|
-
const menuItems = renderMenuItems({ closeMenu });
|
|
33
|
-
|
|
34
|
-
const { height: bodyHeight } = useResizeObserver({ ref: document.body });
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<>
|
|
38
|
-
<Styled.SelectorButton
|
|
39
|
-
isMenuExpanded={isExpanded}
|
|
40
|
-
variant="outlined"
|
|
41
|
-
aria-haspopup="true"
|
|
42
|
-
disableElevation={true}
|
|
43
|
-
onClick={openMenu}
|
|
44
|
-
endIcon={<Styled.UnfoldMoreIcon />}
|
|
45
|
-
fullWidth={true}
|
|
46
|
-
startIcon={startIcon}
|
|
47
|
-
disabled={!menuItems.length}
|
|
48
|
-
>
|
|
49
|
-
<Fade in={isExpanded}>
|
|
50
|
-
<Styled.SelectedOptionText>{selectedOptionText}</Styled.SelectedOptionText>
|
|
51
|
-
</Fade>
|
|
52
|
-
</Styled.SelectorButton>
|
|
53
|
-
|
|
54
|
-
<Styled.Menu
|
|
55
|
-
anchorEl={anchorEl}
|
|
56
|
-
open={isMenuOpen}
|
|
57
|
-
onClose={closeMenu}
|
|
58
|
-
sx={{ top: menuPosition === 'top' ? -4 : 4 }}
|
|
59
|
-
slotProps={{
|
|
60
|
-
paper: {
|
|
61
|
-
style: {
|
|
62
|
-
maxHeight:
|
|
63
|
-
anchorEl && bodyHeight ? bodyHeight - anchorEl?.getBoundingClientRect().bottom - 16 : undefined,
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
}}
|
|
67
|
-
anchorOrigin={
|
|
68
|
-
menuPosition === 'top' ? { horizontal: 'left', vertical: 'top' } : { horizontal: 'left', vertical: 'bottom' }
|
|
69
|
-
}
|
|
70
|
-
transformOrigin={
|
|
71
|
-
menuPosition === 'top' ? { horizontal: 'left', vertical: 'bottom' } : { horizontal: 'left', vertical: 'top' }
|
|
72
|
-
}
|
|
73
|
-
>
|
|
74
|
-
{menuItems}
|
|
75
|
-
</Styled.Menu>
|
|
76
|
-
</>
|
|
77
|
-
);
|
|
78
|
-
};
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/react';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import MuiUnfoldMoreIcon from '@mui/icons-material/UnfoldMoreRounded';
|
|
4
|
-
import Button, { buttonClasses } from '@mui/material/Button';
|
|
5
|
-
import MuiMenu, { menuClasses } from '@mui/material/Menu';
|
|
6
|
-
|
|
7
|
-
import { shouldNotForwardPropsWithKeys } from '../../../utils/shouldNotForwardPropsWithKeys';
|
|
8
|
-
|
|
9
|
-
type SelectorButtonProps = {
|
|
10
|
-
isMenuExpanded: boolean;
|
|
11
|
-
};
|
|
12
|
-
export const SelectorButton = styled(
|
|
13
|
-
Button,
|
|
14
|
-
shouldNotForwardPropsWithKeys<SelectorButtonProps>(['isMenuExpanded']),
|
|
15
|
-
)<SelectorButtonProps>(
|
|
16
|
-
({ theme, isMenuExpanded, disabled }) => css`
|
|
17
|
-
display: ${disabled && 'none'};
|
|
18
|
-
|
|
19
|
-
justify-content: flex-start;
|
|
20
|
-
|
|
21
|
-
min-width: 0;
|
|
22
|
-
height: 2.375rem;
|
|
23
|
-
|
|
24
|
-
padding-right: calc(${theme.my.spacing.xxxs} - 0.0625rem);
|
|
25
|
-
padding-left: calc(${theme.my.spacing.xxxs} - 0.0625rem);
|
|
26
|
-
|
|
27
|
-
text-overflow: ellipsis;
|
|
28
|
-
|
|
29
|
-
color: ${theme.my.colors.primitives.common.white};
|
|
30
|
-
|
|
31
|
-
white-space: nowrap;
|
|
32
|
-
|
|
33
|
-
border-radius: ${theme.my.radius.md};
|
|
34
|
-
|
|
35
|
-
transition:
|
|
36
|
-
height 0.3s,
|
|
37
|
-
padding 0.3s;
|
|
38
|
-
|
|
39
|
-
:hover {
|
|
40
|
-
&.${buttonClasses.outlined} {
|
|
41
|
-
border-color: ${theme.my.colors.primitives.common.white};
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
${isMenuExpanded &&
|
|
46
|
-
css`
|
|
47
|
-
height: 3rem;
|
|
48
|
-
|
|
49
|
-
padding-right: ${theme.my.spacing.xxs};
|
|
50
|
-
padding-left: ${theme.my.spacing.xxs};
|
|
51
|
-
`}
|
|
52
|
-
|
|
53
|
-
.${buttonClasses.startIcon} {
|
|
54
|
-
width: 1.75rem;
|
|
55
|
-
height: 1.75rem;
|
|
56
|
-
|
|
57
|
-
margin-right: 0;
|
|
58
|
-
margin-left: 0;
|
|
59
|
-
|
|
60
|
-
transition: 0.3s;
|
|
61
|
-
|
|
62
|
-
${isMenuExpanded &&
|
|
63
|
-
css`
|
|
64
|
-
width: 2rem;
|
|
65
|
-
height: 2rem;
|
|
66
|
-
`}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.${buttonClasses.endIcon} {
|
|
70
|
-
margin-right: ${theme.my.spacing.xxxs};
|
|
71
|
-
}
|
|
72
|
-
`,
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
export const SelectedOptionText = styled.span`
|
|
76
|
-
flex: 1;
|
|
77
|
-
|
|
78
|
-
padding-left: ${({ theme }) => theme.my.spacing.xxs};
|
|
79
|
-
|
|
80
|
-
overflow: hidden;
|
|
81
|
-
text-overflow: ellipsis;
|
|
82
|
-
|
|
83
|
-
font: ${({ theme }) => theme.my.font.highlight3};
|
|
84
|
-
|
|
85
|
-
text-align: left;
|
|
86
|
-
`;
|
|
87
|
-
|
|
88
|
-
export const Menu = styled(MuiMenu)`
|
|
89
|
-
.${menuClasses.root} {
|
|
90
|
-
padding: 0;
|
|
91
|
-
}
|
|
92
|
-
`;
|
|
93
|
-
|
|
94
|
-
export const UnfoldMoreIcon = styled(MuiUnfoldMoreIcon)`
|
|
95
|
-
width: 1rem;
|
|
96
|
-
height: 1rem;
|
|
97
|
-
`;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
const ConsolidationIcon = (props: React.SVGProps<SVGSVGElement>) => (
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 36 36" {...props}>
|
|
3
|
-
<path d="M9.8 18.8h16.4v3.08h1.6V17.2h-9V14h-1.6v3.2h-9v4.68h1.6zM14 23H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2M4 31v-6h10v6ZM32 23H22a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2m-10 8v-6h10v6ZM13 13h10a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H13a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2m0-8h10v6H13Z" />
|
|
4
|
-
</svg>
|
|
5
|
-
);
|
|
6
|
-
export default ConsolidationIcon;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { Fragment, useEffect, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Business as BusinessIcon,
|
|
5
|
-
ExpandLess as ExpandLessIcon,
|
|
6
|
-
ExpandMore as ExpandMoreIcon,
|
|
7
|
-
} from '@mui/icons-material';
|
|
8
|
-
import { Collapse, Divider, List, ListItemIcon, MenuItem, Tooltip } from '@mui/material';
|
|
9
|
-
import { AvailableCompany, AvailableTenant } from '@smartbooks-ai/api-client';
|
|
10
|
-
|
|
11
|
-
import ConsolidationIcon from './ConsolidationIcon';
|
|
12
|
-
import * as Styled from './styles';
|
|
13
|
-
|
|
14
|
-
import { assertNever } from '../../../utils/assertNever';
|
|
15
|
-
|
|
16
|
-
type Props = {
|
|
17
|
-
selectedTenant?: AvailableTenant;
|
|
18
|
-
tenants: AvailableTenant[];
|
|
19
|
-
onCompanySelected: (company: AvailableCompany) => void;
|
|
20
|
-
selectedCompanyCode: string | undefined;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const MultiSubscriptionsMenuItems: React.FC<Props> = ({
|
|
24
|
-
selectedTenant,
|
|
25
|
-
tenants,
|
|
26
|
-
onCompanySelected,
|
|
27
|
-
selectedCompanyCode,
|
|
28
|
-
}) => {
|
|
29
|
-
const [openTenants, setOpenTenants] = useState<string[]>([]);
|
|
30
|
-
|
|
31
|
-
const toggleTenant = (tenantCode: string) => {
|
|
32
|
-
if (openTenants.includes(tenantCode)) {
|
|
33
|
-
setOpenTenants(openTenants.filter((a) => a !== tenantCode));
|
|
34
|
-
} else {
|
|
35
|
-
setOpenTenants([...openTenants, tenantCode]);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (selectedTenant) {
|
|
41
|
-
setOpenTenants([selectedTenant.code]);
|
|
42
|
-
}
|
|
43
|
-
}, [selectedTenant]);
|
|
44
|
-
|
|
45
|
-
const sortedTenants = tenants.toSorted((a, b) => (a.description || '').localeCompare(b.description || ''));
|
|
46
|
-
|
|
47
|
-
const [highlightedCompanyMenuItem, setHighlightedCompanyMenuItem] = useState<HTMLElement | null>(null);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<>
|
|
51
|
-
{sortedTenants.map((tenant) => {
|
|
52
|
-
const sortedCompanies = tenant.companies.toSorted((a, b) =>
|
|
53
|
-
a.companyType === 'consolidation' && b.companyType !== 'consolidation'
|
|
54
|
-
? -1
|
|
55
|
-
: a.companyType !== 'consolidation' && b.companyType === 'consolidation'
|
|
56
|
-
? 1
|
|
57
|
-
: (a.description || '').localeCompare(b.description || ''),
|
|
58
|
-
);
|
|
59
|
-
const isOpen = tenants.length === 1 || openTenants.includes(tenant.code);
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<Fragment key={tenant.code}>
|
|
63
|
-
{tenants.length > 1 && (
|
|
64
|
-
<MenuItem onClick={() => toggleTenant(tenant.code)}>
|
|
65
|
-
{tenant.description}
|
|
66
|
-
|
|
67
|
-
<ListItemIcon sx={{ marginLeft: '1em' }}>
|
|
68
|
-
{isOpen ? <ExpandLessIcon fontSize="small" /> : <ExpandMoreIcon fontSize="small" />}
|
|
69
|
-
</ListItemIcon>
|
|
70
|
-
</MenuItem>
|
|
71
|
-
)}
|
|
72
|
-
<Collapse
|
|
73
|
-
in={isOpen}
|
|
74
|
-
timeout="auto"
|
|
75
|
-
unmountOnExit={true}
|
|
76
|
-
onEntered={() => {
|
|
77
|
-
if (tenant.code === selectedTenant?.code)
|
|
78
|
-
highlightedCompanyMenuItem?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
79
|
-
}}
|
|
80
|
-
>
|
|
81
|
-
<List component="div" disablePadding={true}>
|
|
82
|
-
<Divider />
|
|
83
|
-
|
|
84
|
-
{sortedCompanies.map((company) => (
|
|
85
|
-
<MenuItem
|
|
86
|
-
key={company.code}
|
|
87
|
-
onClick={() => onCompanySelected(company)}
|
|
88
|
-
selected={company.code === selectedCompanyCode}
|
|
89
|
-
autoFocus={company.code === selectedCompanyCode}
|
|
90
|
-
ref={(el) => {
|
|
91
|
-
if (company.code === selectedCompanyCode) setHighlightedCompanyMenuItem(el);
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
<ListItemIcon>
|
|
95
|
-
{company.companyType === 'consolidation' ? (
|
|
96
|
-
<Tooltip title="Consolidation" disableInteractive={true}>
|
|
97
|
-
<Styled.IconContainer>
|
|
98
|
-
<ConsolidationIcon fontSize="inherit" />
|
|
99
|
-
</Styled.IconContainer>
|
|
100
|
-
</Tooltip>
|
|
101
|
-
) : company.companyType === 'regular' ? (
|
|
102
|
-
<Styled.IconContainer>
|
|
103
|
-
<BusinessIcon fontSize="inherit" />
|
|
104
|
-
</Styled.IconContainer>
|
|
105
|
-
) : (
|
|
106
|
-
assertNever(company.companyType)
|
|
107
|
-
)}
|
|
108
|
-
</ListItemIcon>
|
|
109
|
-
|
|
110
|
-
{company.description}
|
|
111
|
-
</MenuItem>
|
|
112
|
-
))}
|
|
113
|
-
</List>
|
|
114
|
-
</Collapse>
|
|
115
|
-
</Fragment>
|
|
116
|
-
);
|
|
117
|
-
})}
|
|
118
|
-
</>
|
|
119
|
-
);
|
|
120
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<svg fill="currentColor" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<polygon
|
|
3
|
-
points="9.8 18.8 26.2 18.8 26.2 21.88 27.8 21.88 27.8 17.2 18.8 17.2 18.8 14 17.2 14 17.2 17.2 8.2 17.2 8.2 21.88 9.8 21.88 9.8 18.8">
|
|
4
|
-
</polygon>
|
|
5
|
-
<path d="M14,23H4a2,2,0,0,0-2,2v6a2,2,0,0,0,2,2H14a2,2,0,0,0,2-2V25A2,2,0,0,0,14,23ZM4,31V25H14v6Z"></path>
|
|
6
|
-
<path d="M32,23H22a2,2,0,0,0-2,2v6a2,2,0,0,0,2,2H32a2,2,0,0,0,2-2V25A2,2,0,0,0,32,23ZM22,31V25H32v6Z"></path>
|
|
7
|
-
<path d="M13,13H23a2,2,0,0,0,2-2V5a2,2,0,0,0-2-2H13a2,2,0,0,0-2,2v6A2,2,0,0,0,13,13Zm0-8H23v6H13Z"></path>
|
|
8
|
-
</svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { MultiSubscriptionsMenuItems } from './MultiSubscriptionsMenuItems';
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft';
|
|
2
|
-
import Fade from '@mui/material/Fade';
|
|
3
|
-
import MenuList from '@mui/material/MenuList';
|
|
4
|
-
import { AvailableCompany } from '@smartbooks-ai/api-client';
|
|
5
|
-
import { createPortal } from 'react-dom';
|
|
6
|
-
import { NavLink, Outlet } from 'react-router';
|
|
7
|
-
|
|
8
|
-
import LogoHeaderImage from './LogoHeaderImage';
|
|
9
|
-
import LogoHeaderText from './LogoHeaderText';
|
|
10
|
-
import { AppSelect, MenuItemWithChildren, UserProfileSelect } from './index';
|
|
11
|
-
import * as Styled from './styles';
|
|
12
|
-
import { MenuStructure } from './types';
|
|
13
|
-
import { useMenuToggle } from './useMenuToggle';
|
|
14
|
-
|
|
15
|
-
import { UserProfile } from '../../security/UserProfile';
|
|
16
|
-
|
|
17
|
-
export type PageWithMenuLayoutProps = {
|
|
18
|
-
resolvedCompanyCode?: string;
|
|
19
|
-
topMenu?: MenuStructure;
|
|
20
|
-
bottomMenu: MenuStructure;
|
|
21
|
-
profile: UserProfile | null;
|
|
22
|
-
tenantCode?: string;
|
|
23
|
-
switchToCompany: (company: AvailableCompany) => Promise<void>;
|
|
24
|
-
logout: () => void;
|
|
25
|
-
additionalOutletContent?: React.ReactNode;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const PageWithMenuLayout: React.FC<PageWithMenuLayoutProps> = ({
|
|
29
|
-
resolvedCompanyCode,
|
|
30
|
-
topMenu,
|
|
31
|
-
bottomMenu,
|
|
32
|
-
profile,
|
|
33
|
-
tenantCode,
|
|
34
|
-
switchToCompany,
|
|
35
|
-
logout,
|
|
36
|
-
additionalOutletContent,
|
|
37
|
-
}) => {
|
|
38
|
-
const { isExpanded, openMenu, toggleIsExpanded } = useMenuToggle();
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<>
|
|
42
|
-
<Styled.LockMenuButton onClick={toggleIsExpanded} isExpanded={isExpanded}>
|
|
43
|
-
<KeyboardArrowLeftIcon fontSize="inherit" />
|
|
44
|
-
</Styled.LockMenuButton>
|
|
45
|
-
|
|
46
|
-
{createPortal(
|
|
47
|
-
<Styled.Drawer open={isExpanded} variant="permanent">
|
|
48
|
-
<Styled.Header>
|
|
49
|
-
<Styled.LogoContainer>
|
|
50
|
-
<NavLink to="/">
|
|
51
|
-
<LogoHeaderImage height={24} />
|
|
52
|
-
</NavLink>
|
|
53
|
-
</Styled.LogoContainer>
|
|
54
|
-
|
|
55
|
-
<Fade in={isExpanded}>
|
|
56
|
-
<NavLink to="/">
|
|
57
|
-
<LogoHeaderText height={12} />
|
|
58
|
-
</NavLink>
|
|
59
|
-
</Fade>
|
|
60
|
-
</Styled.Header>
|
|
61
|
-
<AppSelect
|
|
62
|
-
tenantCode={tenantCode}
|
|
63
|
-
companyCode={resolvedCompanyCode}
|
|
64
|
-
isExpanded={isExpanded}
|
|
65
|
-
profile={profile}
|
|
66
|
-
onCompanyClicked={switchToCompany}
|
|
67
|
-
/>
|
|
68
|
-
|
|
69
|
-
<Styled.TopMenuList>
|
|
70
|
-
{topMenu?.map((firstLevelItem) => (
|
|
71
|
-
<MenuItemWithChildren
|
|
72
|
-
key={firstLevelItem.title}
|
|
73
|
-
menuItem={firstLevelItem}
|
|
74
|
-
isMenuOpen={isExpanded}
|
|
75
|
-
openMenu={openMenu}
|
|
76
|
-
/>
|
|
77
|
-
))}
|
|
78
|
-
</Styled.TopMenuList>
|
|
79
|
-
|
|
80
|
-
<MenuList disablePadding={true}>
|
|
81
|
-
{bottomMenu?.map((firstLevelItem) => (
|
|
82
|
-
<MenuItemWithChildren
|
|
83
|
-
key={firstLevelItem.title}
|
|
84
|
-
menuItem={firstLevelItem}
|
|
85
|
-
isMenuOpen={isExpanded}
|
|
86
|
-
openMenu={openMenu}
|
|
87
|
-
/>
|
|
88
|
-
))}
|
|
89
|
-
</MenuList>
|
|
90
|
-
|
|
91
|
-
<UserProfileSelect isTextVisible={isExpanded} profile={profile} logout={logout} />
|
|
92
|
-
</Styled.Drawer>,
|
|
93
|
-
document.body,
|
|
94
|
-
)}
|
|
95
|
-
|
|
96
|
-
<Styled.Main isLocked={isExpanded}>
|
|
97
|
-
<Outlet />
|
|
98
|
-
|
|
99
|
-
{additionalOutletContent}
|
|
100
|
-
</Styled.Main>
|
|
101
|
-
</>
|
|
102
|
-
);
|
|
103
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import AccountCircleRoundedIcon from '@mui/icons-material/AccountCircleRounded';
|
|
4
|
-
import { Fade } from '@mui/material';
|
|
5
|
-
import MenuItem from '@mui/material/MenuItem';
|
|
6
|
-
import { GlobalRole } from '@smartbooks-ai/api-client';
|
|
7
|
-
|
|
8
|
-
import * as Styled from './styles';
|
|
9
|
-
|
|
10
|
-
import { useIsAuthorized } from '../../../hooks/useIsAuthorized';
|
|
11
|
-
import { useToggle } from '../../../hooks/useToggle';
|
|
12
|
-
import { UserProfile } from '../../../security/ProfileContext';
|
|
13
|
-
import * as MenuItemWithChildrenStyled from '../MenuItemWithChildren/styles';
|
|
14
|
-
|
|
15
|
-
type Props = {
|
|
16
|
-
isTextVisible: boolean;
|
|
17
|
-
profile: UserProfile | null;
|
|
18
|
-
logout: () => void;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const UserProfileSelect: React.FC<Props> = ({ isTextVisible, profile, logout }) => {
|
|
22
|
-
const { value: isMenuOpen, switchOn: openMenu, switchOff: closeMenu } = useToggle();
|
|
23
|
-
const getIsAuthorized = useIsAuthorized();
|
|
24
|
-
|
|
25
|
-
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<>
|
|
29
|
-
<MenuItemWithChildrenStyled.MenuItem
|
|
30
|
-
isTitle={false}
|
|
31
|
-
isMenuOpen={isTextVisible}
|
|
32
|
-
ref={setAnchorEl}
|
|
33
|
-
isHighlighted={false}
|
|
34
|
-
onClick={openMenu}
|
|
35
|
-
>
|
|
36
|
-
<MenuItemWithChildrenStyled.ListItemIcon>
|
|
37
|
-
<AccountCircleRoundedIcon fontSize="small" />
|
|
38
|
-
</MenuItemWithChildrenStyled.ListItemIcon>
|
|
39
|
-
|
|
40
|
-
<Fade in={isTextVisible}>
|
|
41
|
-
<MenuItemWithChildrenStyled.ListItemText elevation={0} isHighlighted={false} isTitle={false}>
|
|
42
|
-
{profile?.displayName ?? 'My account'}
|
|
43
|
-
</MenuItemWithChildrenStyled.ListItemText>
|
|
44
|
-
</Fade>
|
|
45
|
-
|
|
46
|
-
<MenuItemWithChildrenStyled.ArrowDownIcon isExpanded={isMenuOpen} isVisible={isTextVisible} />
|
|
47
|
-
</MenuItemWithChildrenStyled.MenuItem>
|
|
48
|
-
|
|
49
|
-
<Styled.Menu
|
|
50
|
-
anchorOrigin={{ horizontal: 'left', vertical: 'top' }}
|
|
51
|
-
transformOrigin={{ horizontal: 'left', vertical: 'bottom' }}
|
|
52
|
-
anchorEl={anchorEl}
|
|
53
|
-
open={isMenuOpen}
|
|
54
|
-
onClose={closeMenu}
|
|
55
|
-
>
|
|
56
|
-
<MenuItem disabled={true}>{profile?.email}</MenuItem>
|
|
57
|
-
{getIsAuthorized({ globalRole: GlobalRole.GlobalAdmin }) && (
|
|
58
|
-
<MenuItem onClick={() => window.open('/ac/ga', '_blank')}>System admin</MenuItem>
|
|
59
|
-
)}
|
|
60
|
-
<MenuItem onClick={logout}>Logout</MenuItem>
|
|
61
|
-
</Styled.Menu>
|
|
62
|
-
</>
|
|
63
|
-
);
|
|
64
|
-
};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export { AppSelect } from './AppSelect';
|
|
2
|
-
export { MenuSelect } from './MenuSelect';
|
|
3
|
-
export { MultiSubscriptionsMenuItems } from './MultiSubscriptionsMenuItems';
|
|
4
|
-
export { MenuItemWithChildren } from './MenuItemWithChildren/MenuItemWithChildren';
|
|
5
|
-
export { UserProfileSelect } from './UserProfileSelect';
|
|
6
|
-
export { PageWithMenuLayout } from './PageWithMenuLayout';
|
|
7
|
-
export { default as LogoHeaderImage } from './LogoHeaderImage';
|
|
8
|
-
export { default as LogoHeaderText } from './LogoHeaderText';
|