@smartbooks-ai/layout 0.0.6 → 0.0.7
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/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,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';
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { css } from '@emotion/react';
|
|
2
|
-
import styled from '@emotion/styled';
|
|
3
|
-
import MuiDrawer, { drawerClasses } from '@mui/material/Drawer';
|
|
4
|
-
import MuiIconButton from '@mui/material/IconButton';
|
|
5
|
-
import MenuList from '@mui/material/MenuList';
|
|
6
|
-
|
|
7
|
-
import { shouldNotForwardPropsWithKeys } from '../../utils/shouldNotForwardPropsWithKeys';
|
|
8
|
-
|
|
9
|
-
const drawerOpenWidthRem = 15.625;
|
|
10
|
-
const drawerClosedWidthRem = 3.75;
|
|
11
|
-
|
|
12
|
-
export const Drawer = styled(MuiDrawer)`
|
|
13
|
-
flex-shrink: 0;
|
|
14
|
-
|
|
15
|
-
overflow-x: hidden;
|
|
16
|
-
.${drawerClasses.paper} {
|
|
17
|
-
width: ${({ open }) => (open ? drawerOpenWidthRem : drawerClosedWidthRem)}rem;
|
|
18
|
-
|
|
19
|
-
padding: ${({ theme }) => theme.my.spacing.xs};
|
|
20
|
-
|
|
21
|
-
overflow: hidden;
|
|
22
|
-
|
|
23
|
-
background-color: ${({ theme }) => theme.my.colors.primary.main};
|
|
24
|
-
border: unset;
|
|
25
|
-
|
|
26
|
-
transition: width 0.3s;
|
|
27
|
-
}
|
|
28
|
-
`;
|
|
29
|
-
|
|
30
|
-
export const Header = styled.div`
|
|
31
|
-
display: flex;
|
|
32
|
-
|
|
33
|
-
column-gap: ${({ theme }) => theme.my.spacing.xxs};
|
|
34
|
-
align-items: center;
|
|
35
|
-
|
|
36
|
-
width: max-content;
|
|
37
|
-
min-width: 100%;
|
|
38
|
-
|
|
39
|
-
padding-bottom: ${({ theme }) => theme.my.spacing.xs};
|
|
40
|
-
|
|
41
|
-
overflow: hidden;
|
|
42
|
-
`;
|
|
43
|
-
|
|
44
|
-
export const LogoContainer = styled.div`
|
|
45
|
-
display: flex;
|
|
46
|
-
|
|
47
|
-
align-items: center;
|
|
48
|
-
justify-content: center;
|
|
49
|
-
|
|
50
|
-
width: 2.25rem;
|
|
51
|
-
height: 2.25rem;
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
type LockMenuButtonProps = {
|
|
55
|
-
isExpanded: boolean;
|
|
56
|
-
};
|
|
57
|
-
export const LockMenuButton = styled(
|
|
58
|
-
MuiIconButton,
|
|
59
|
-
shouldNotForwardPropsWithKeys<LockMenuButtonProps>(['isExpanded']),
|
|
60
|
-
)<LockMenuButtonProps>(
|
|
61
|
-
({ theme, isExpanded }) => css`
|
|
62
|
-
position: absolute;
|
|
63
|
-
top: ${theme.my.spacing.sm};
|
|
64
|
-
left: ${isExpanded ? drawerOpenWidthRem : drawerClosedWidthRem}rem;
|
|
65
|
-
z-index: ${(theme.zIndex?.drawer ?? 0) + 1};
|
|
66
|
-
|
|
67
|
-
padding: ${theme.my.spacing.xxxs};
|
|
68
|
-
|
|
69
|
-
font-size: 1rem;
|
|
70
|
-
|
|
71
|
-
color: ${theme.my.colors.text.white};
|
|
72
|
-
|
|
73
|
-
background-color: ${theme.my.colors.primitives.darkNavy[700]};
|
|
74
|
-
border-radius: ${theme.my.radius.xxl};
|
|
75
|
-
|
|
76
|
-
transform: translateX(-50%) rotate(${isExpanded ? 0 : 180}deg);
|
|
77
|
-
|
|
78
|
-
transition: 0.3s;
|
|
79
|
-
|
|
80
|
-
&:hover {
|
|
81
|
-
background-color: ${theme.my.colors.primitives.darkNavy[600]};
|
|
82
|
-
}
|
|
83
|
-
`,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
export const TopMenuList = styled(MenuList)`
|
|
87
|
-
display: flex;
|
|
88
|
-
|
|
89
|
-
flex: 1;
|
|
90
|
-
flex-direction: column;
|
|
91
|
-
|
|
92
|
-
gap: ${({ theme }) => theme.my.spacing.xxxs};
|
|
93
|
-
|
|
94
|
-
overflow: hidden auto;
|
|
95
|
-
`;
|
|
96
|
-
|
|
97
|
-
type MainProps = {
|
|
98
|
-
isLocked: boolean;
|
|
99
|
-
};
|
|
100
|
-
export const Main = styled('div', shouldNotForwardPropsWithKeys<MainProps>(['isLocked']))<MainProps>`
|
|
101
|
-
position: relative;
|
|
102
|
-
|
|
103
|
-
flex-grow: 1;
|
|
104
|
-
|
|
105
|
-
margin-left: ${({ isLocked }) => (isLocked ? drawerOpenWidthRem : drawerClosedWidthRem)}rem;
|
|
106
|
-
|
|
107
|
-
overflow: auto;
|
|
108
|
-
|
|
109
|
-
transition: margin 0.3s;
|
|
110
|
-
`;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
import { useProfile, useToggle } from '@smartbooks-ai/layout';
|
|
4
|
-
|
|
5
|
-
export const useMenuToggle = () => {
|
|
6
|
-
const { value: isExpanded, toggle: toggleIsExpanded, switchOn: openMenu, switchOff: closeMenu } = useToggle(true);
|
|
7
|
-
|
|
8
|
-
const { profile } = useProfile();
|
|
9
|
-
|
|
10
|
-
const tenants = profile?.allowedTenants;
|
|
11
|
-
|
|
12
|
-
const tenantsWithCompanies = useMemo(() => tenants?.filter(({ companies }) => companies.length > 0) ?? [], [tenants]);
|
|
13
|
-
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
if (tenants && !tenantsWithCompanies.length) closeMenu();
|
|
16
|
-
}, [closeMenu, tenants, tenantsWithCompanies.length]);
|
|
17
|
-
|
|
18
|
-
return { isExpanded, toggleIsExpanded, openMenu };
|
|
19
|
-
};
|
package/src/components/index.ts
DELETED