refactor: monorepo setup with lerna (#243)

This commit is contained in:
Daniel Lautzenheiser
2022-12-15 13:44:49 -05:00
committed by GitHub
parent dac29fbf3c
commit 504d95c34f
706 changed files with 16571 additions and 142 deletions

View File

@ -0,0 +1,127 @@
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
import Collapse from '@mui/material/Collapse';
import List from '@mui/material/List';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import { useTheme } from '@mui/material/styles';
import Link from 'next/link';
import { useCallback, useMemo, useState } from 'react';
import ListSubheader from '@mui/material/ListSubheader';
import { useRouter } from 'next/router';
import MobileNavLink from './MobileNavLink';
import type { MouseEvent } from 'react';
import type { MenuItem, MenuLink, MenuLinkGroup } from '../../../interface';
interface MobileNavItemProps {
item: MenuItem;
}
function isMenuLinkGroup(link: MenuItem): link is MenuLinkGroup {
return 'groups' in link;
}
const MobileNavItem = ({ item }: MobileNavItemProps) => {
const theme = useTheme();
const { asPath } = useRouter();
const selected = useMemo(() => {
if ('url' in item) {
return asPath === item.url;
}
return asPath.startsWith(item.path);
}, [asPath, item]);
const [open, setOpen] = useState(selected);
const handleOnClick = useCallback(
(link: MenuItem | MenuLink) => (event: MouseEvent) => {
if (isMenuLinkGroup(link)) {
event.stopPropagation();
setOpen(!open);
return;
}
},
[open],
);
const url = useMemo(() => {
if (isMenuLinkGroup(item)) {
return undefined;
}
return item.url;
}, [item]);
const wrappedLink = useMemo(
() => (
<ListItemButton
component={url ? Link : 'button'}
href={url}
target={url?.startsWith('http') ? '_blank' : undefined}
key={`drawer-nav-item-${item.title}`}
onClick={handleOnClick(item)}
selected={selected}
>
<ListItemText primary={item.title} />
{isMenuLinkGroup(item) ? (
<ExpandLessIcon
sx={{
transform: `rotateZ(${open ? 0 : 90}deg)`,
transition: theme.transitions.create(['transform']),
}}
/>
) : null}
</ListItemButton>
),
[handleOnClick, item, open, selected, theme.transitions, url],
);
return (
<>
{wrappedLink}
{isMenuLinkGroup(item) ? (
<Collapse in={open} timeout="auto" unmountOnExit>
{item.groups.map(group => (
<List
key={group.title}
component="div"
subheader={
<ListSubheader
component="div"
id="nested-list-subheader"
sx={{
lineHeight: '32px',
textTransform: 'uppercase',
top: '-1px',
}}
>
{group.title}
</ListSubheader>
}
disablePadding
sx={{
marginTop: '8px',
'&:not(:first-of-type)': {
marginTop: '20px',
},
}}
>
{group.links.map(link => (
<MobileNavLink
key={`drawer-nav-item-${item.title}-sub-item-${link.title}`}
link={link}
onClick={handleOnClick(link)}
/>
))}
</List>
))}
</Collapse>
) : null}
</>
);
};
export default MobileNavItem;

View File

@ -0,0 +1,37 @@
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useMemo } from 'react';
import type { MouseEvent } from 'react';
import type { MenuLink } from '../../../interface';
interface MobileNavLinkProps {
link: MenuLink;
onClick: (event: MouseEvent) => void;
}
const MobileNavLink = ({ link, onClick }: MobileNavLinkProps) => {
const { title, url } = link;
const { asPath } = useRouter();
const selected = useMemo(() => {
return asPath === url;
}, [asPath, url]);
return (
<ListItemButton
component={Link}
href={url}
target={url.startsWith('http') ? '_blank' : undefined}
sx={{ paddingLeft: '24px', paddingTop: '4px', paddingBottom: '4px' }}
onClick={onClick}
selected={selected}
>
<ListItemText primary={title} />
</ListItemButton>
);
};
export default MobileNavLink;

View File

@ -0,0 +1,104 @@
import Divider from '@mui/material/Divider';
import List from '@mui/material/List';
import { styled, useTheme } from '@mui/material/styles';
import SwipeableDrawer from '@mui/material/SwipeableDrawer';
import { useMemo } from 'react';
import MobileNavItem from './MobileNavItem';
import Logo from '../Logo';
import type { MenuItem } from '../../../interface';
const DRAWER_WIDTH = 300;
const StyledDrawerContents = styled('div')`
text-align: center;
`;
const StyledLogoWrapper = styled('div')(
({ theme }) => `
display: flex;
justify-content: center;
padding: 16px 0;
background: ${
theme.palette.mode === 'light' ? theme.palette.primary.main : theme.palette.background.paper
};
`,
);
interface NavigationDrawerProps {
items: MenuItem[];
mobileOpen: boolean;
onMobileOpenToggle: () => void;
}
const NavigationDrawer = ({ items, mobileOpen, onMobileOpenToggle }: NavigationDrawerProps) => {
const theme = useTheme();
const iOS = useMemo(
() => typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent),
[],
);
const drawer = useMemo(
() => (
<StyledDrawerContents key="drawer-nav-contents" onClick={onMobileOpenToggle}>
<StyledLogoWrapper key="drawer-nav-logo-wrapper">
<Logo key="drawer-nav-logo" />
</StyledLogoWrapper>
<Divider key="drawer-nav-divider" sx={{ borderColor: 'rgba(255, 255, 255, 0.8)' }} />
<List key="drawer-nav-list">
{items.map(item => (
<MobileNavItem key={`drawer-nav-item-${item.title}`} item={item} />
))}
</List>
</StyledDrawerContents>
),
[items, onMobileOpenToggle],
);
const container = useMemo(
() => (typeof window !== 'undefined' ? window.document.body : undefined),
[],
);
return (
<SwipeableDrawer
key="swipable-drawer"
disableBackdropTransition={!iOS}
disableDiscovery={iOS}
container={container}
variant="temporary"
open={mobileOpen}
onOpen={onMobileOpenToggle}
onClose={onMobileOpenToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
sx={{
display: 'none',
[theme.breakpoints.down('lg')]: {
display: 'block',
},
width: '80%',
maxWidth: DRAWER_WIDTH,
'& .MuiBackdrop-root': {
width: '100%',
},
'& .MuiDrawer-paper': {
boxSizing: 'border-box',
width: '80%',
maxWidth: DRAWER_WIDTH,
background: theme.palette.background.paper,
},
'& .MuiListSubheader-root': {
textAlign: 'left',
},
}}
>
{drawer}
</SwipeableDrawer>
);
};
export default NavigationDrawer;