@graphcommerce/next-ui 3.0.1
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/.babelrc +3 -0
- package/AnimatedRow/index.tsx +20 -0
- package/ApolloError/ApolloErrorAlert.tsx +59 -0
- package/ApolloError/ApolloErrorFullPage.tsx +25 -0
- package/AppShell/AppShellHeader/appShellHeaderContext.tsx +11 -0
- package/AppShell/AppShellHeader/index.tsx +433 -0
- package/AppShell/AppShellHeader/useAppShellHeaderContext.tsx +6 -0
- package/AppShell/AppShellProvider/index.tsx +18 -0
- package/AppShell/AppShellSticky/index.tsx +66 -0
- package/AppShell/AppShellTitle/index.tsx +45 -0
- package/AppShell/DesktopNavActions.tsx +28 -0
- package/AppShell/DesktopNavBar.tsx +110 -0
- package/AppShell/FixedFab.tsx +41 -0
- package/AppShell/ForwardButton.tsx +53 -0
- package/AppShell/FullPageShellBase.tsx +59 -0
- package/AppShell/Menu.tsx +7 -0
- package/AppShell/MenuFab.tsx +132 -0
- package/AppShell/MenuFabSecondaryItem.tsx +32 -0
- package/AppShell/MinimalPageShellBase.tsx +22 -0
- package/AppShell/PageShellHeader/index.tsx +14 -0
- package/AppShell/SheetShellBase/index.tsx +107 -0
- package/AppShell/SheetShellBase/useSheetStyles.ts +11 -0
- package/AppShell/SheetShellDragIndicator/index.tsx +48 -0
- package/AppShell/SheetShellHeader/index.tsx +28 -0
- package/AppShell/ShellBase.tsx +45 -0
- package/AppShell/useFabAnimation.tsx +19 -0
- package/AppShell/useFixedFabAnimation.tsx +18 -0
- package/AspectRatioContainer/index.tsx +27 -0
- package/Blog/BlogAuthor/index.tsx +60 -0
- package/Blog/BlogContent/index.tsx +24 -0
- package/Blog/BlogHeader/index.tsx +64 -0
- package/Blog/BlogList/index.tsx +27 -0
- package/Blog/BlogListItem/index.tsx +83 -0
- package/Blog/BlogTags/index.tsx +34 -0
- package/Blog/BlogTitle/index.tsx +29 -0
- package/Button/index.tsx +164 -0
- package/ButtonLink/index.tsx +45 -0
- package/CHANGELOG.md +1095 -0
- package/ChipMenu/index.tsx +130 -0
- package/ContainerWithHeader/index.tsx +49 -0
- package/Debug/DebugSpacer.tsx +51 -0
- package/FlagAvatar/index.tsx +28 -0
- package/Form/FormActions.tsx +15 -0
- package/Form/FormDivider.tsx +14 -0
- package/Form/FormHeader.tsx +27 -0
- package/Form/FormRow.tsx +14 -0
- package/Form/InputCheckmark.tsx +19 -0
- package/Form/index.tsx +62 -0
- package/FramerNextPagesSlider/Slide.tsx +71 -0
- package/FramerNextPagesSlider/Slider.tsx +39 -0
- package/FramerNextPagesSlider/index.ts +1 -0
- package/FramerNextPagesSlider/types.ts +3 -0
- package/FramerScroller/components/SidebarGallery.tsx +246 -0
- package/FramerScroller/components/SidebarSlider.tsx +103 -0
- package/FullPageMessage/index.tsx +68 -0
- package/Highlight/index.tsx +14 -0
- package/IconHeader/index.tsx +109 -0
- package/JsonLd/index.tsx +18 -0
- package/Page/App.tsx +15 -0
- package/Page/Document.tsx +23 -0
- package/Page/framerFeatures.ts +4 -0
- package/Page/types.ts +19 -0
- package/PageLoadIndicator/index.tsx +46 -0
- package/PageMeta/index.tsx +40 -0
- package/Pagination/index.tsx +123 -0
- package/RenderType/index.tsx +40 -0
- package/Row/ButtonLinkList/index.tsx +53 -0
- package/Row/ColumnOne/index.tsx +11 -0
- package/Row/ColumnOneBoxed/index.tsx +27 -0
- package/Row/ColumnOneCentered/index.tsx +22 -0
- package/Row/ColumnThree/index.tsx +66 -0
- package/Row/ColumnTwo/index.tsx +44 -0
- package/Row/ColumnTwoSpread/index.tsx +41 -0
- package/Row/ColumnTwoWithTop/index.tsx +53 -0
- package/Row/ContentLinks/index.tsx +48 -0
- package/Row/HeroBanner/index.tsx +102 -0
- package/Row/IconBlocks/IconBlock/index.tsx +56 -0
- package/Row/IconBlocks/index.tsx +57 -0
- package/Row/ParagraphWithSidebarSlide/index.tsx +114 -0
- package/Row/Quote/index.tsx +13 -0
- package/Row/RowImageText/index.tsx +67 -0
- package/Row/RowImageTextBoxed/index.tsx +75 -0
- package/Row/SpecialBanner/index.tsx +107 -0
- package/Row/index.tsx +13 -0
- package/SectionContainer/index.tsx +39 -0
- package/SectionHeader/index.tsx +69 -0
- package/Separator/index.tsx +33 -0
- package/Snackbar/ErrorSnackbar.tsx +9 -0
- package/Snackbar/MessageSnackbar.tsx +5 -0
- package/Snackbar/MessageSnackbarImpl.tsx +202 -0
- package/StarRatingField/index.tsx +58 -0
- package/Stepper/Stepper.tsx +45 -0
- package/StyledBadge/index.tsx +21 -0
- package/Styles/index.tsx +3 -0
- package/Styles/responsiveVal.tsx +20 -0
- package/SvgImage/SvgImageSimple.tsx +66 -0
- package/SvgImage/index.tsx +76 -0
- package/TextInputNumber/index.tsx +169 -0
- package/Theme/types.ts +63 -0
- package/TimeAgo/index.tsx +29 -0
- package/Title/index.tsx +71 -0
- package/ToggleButton/index.tsx +100 -0
- package/ToggleButtonGroup/index.tsx +112 -0
- package/UspList/UspListItem.tsx +46 -0
- package/UspList/index.tsx +32 -0
- package/icons/icon_addresses.svg +17 -0
- package/icons/icon_arrow_back.svg +1 -0
- package/icons/icon_arrow_forward.svg +1 -0
- package/icons/icon_box.svg +6 -0
- package/icons/icon_chat.svg +1 -0
- package/icons/icon_checkmark.svg +1 -0
- package/icons/icon_checkmark_green.svg +1 -0
- package/icons/icon_chevron_back.svg +8 -0
- package/icons/icon_chevron_down.svg +8 -0
- package/icons/icon_chevron_left.svg +8 -0
- package/icons/icon_chevron_right.svg +8 -0
- package/icons/icon_chevron_up.svg +8 -0
- package/icons/icon_close.svg +6 -0
- package/icons/icon_close_circle.svg +1 -0
- package/icons/icon_collapse_vertical.svg +11 -0
- package/icons/icon_customer_service.svg +6 -0
- package/icons/icon_email.svg +1 -0
- package/icons/icon_email_outline.svg +6 -0
- package/icons/icon_expand_vertical.svg +11 -0
- package/icons/icon_heart.svg +15 -0
- package/icons/icon_home.svg +6 -0
- package/icons/icon_id.svg +6 -0
- package/icons/icon_invoice_red.svg +7 -0
- package/icons/icon_location_red.svg +7 -0
- package/icons/icon_lock.svg +6 -0
- package/icons/icon_menu.svg +1 -0
- package/icons/icon_min.svg +1 -0
- package/icons/icon_newspaper.svg +6 -0
- package/icons/icon_party.svg +7 -0
- package/icons/icon_person.svg +6 -0
- package/icons/icon_person_alt.svg +6 -0
- package/icons/icon_person_alt_big.svg +15 -0
- package/icons/icon_phone.svg +1 -0
- package/icons/icon_plus.svg +1 -0
- package/icons/icon_sad_face.svg +11 -0
- package/icons/icon_sad_shoppingbag.svg +16 -0
- package/icons/icon_search.svg +1 -0
- package/icons/icon_shopping_bag.svg +7 -0
- package/icons/icon_shutdown.svg +6 -0
- package/icons/icon_star.svg +6 -0
- package/icons/icon_star_filled_muted.svg +6 -0
- package/icons/icon_star_yellow.svg +6 -0
- package/icons/index.tsx +42 -0
- package/index.ts +163 -0
- package/package.json +61 -0
- package/tsconfig.json +5 -0
- package/types.d.ts +13 -0
- package/useIntersectionObserver/index.tsx +31 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import { m } from 'framer-motion'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
|
|
5
|
+
const useStyles = makeStyles(
|
|
6
|
+
(theme: Theme) => ({
|
|
7
|
+
actions: {
|
|
8
|
+
display: 'none',
|
|
9
|
+
[theme.breakpoints.up('md')]: {
|
|
10
|
+
'& > *': {
|
|
11
|
+
pointerEvents: 'all',
|
|
12
|
+
},
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
display: 'grid',
|
|
15
|
+
gridAutoFlow: 'column',
|
|
16
|
+
columnGap: 6,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
{ name: 'DesktopNavActions' },
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
export default function DesktopNavActions(props: { children?: React.ReactNode }) {
|
|
24
|
+
const { children } = props
|
|
25
|
+
const classes = useStyles()
|
|
26
|
+
|
|
27
|
+
return <m.div className={classes.actions}>{children}</m.div>
|
|
28
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Link, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import { Scroller, ScrollerButton, ScrollerProvider } from '@graphcommerce/framer-scroller'
|
|
3
|
+
import clsx from 'clsx'
|
|
4
|
+
import PageLink from 'next/link'
|
|
5
|
+
import { useRouter } from 'next/router'
|
|
6
|
+
import React from 'react'
|
|
7
|
+
import SvgImageSimple from '../SvgImage/SvgImageSimple'
|
|
8
|
+
import { iconChevronLeft, iconChevronRight } from '../icons'
|
|
9
|
+
import { MenuProps } from './Menu'
|
|
10
|
+
|
|
11
|
+
const useStyles = makeStyles(
|
|
12
|
+
(theme: Theme) => ({
|
|
13
|
+
container: {
|
|
14
|
+
minWidth: 200,
|
|
15
|
+
flex: 1,
|
|
16
|
+
position: 'relative',
|
|
17
|
+
pointerEvents: 'all',
|
|
18
|
+
[theme.breakpoints.down('sm')]: {
|
|
19
|
+
display: 'none',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
scroller: {
|
|
23
|
+
display: 'flex',
|
|
24
|
+
columnGap: 40,
|
|
25
|
+
padding: '0 40px',
|
|
26
|
+
minHeight: 40,
|
|
27
|
+
},
|
|
28
|
+
prevNext: {
|
|
29
|
+
pointerEvents: 'all',
|
|
30
|
+
position: 'absolute',
|
|
31
|
+
background: theme.palette.background.default,
|
|
32
|
+
top: 5,
|
|
33
|
+
[theme.breakpoints.down('sm')]: { display: 'none' },
|
|
34
|
+
boxShadow: 'none',
|
|
35
|
+
},
|
|
36
|
+
prev: {
|
|
37
|
+
left: 0,
|
|
38
|
+
},
|
|
39
|
+
next: {
|
|
40
|
+
right: 0,
|
|
41
|
+
},
|
|
42
|
+
link: {
|
|
43
|
+
whiteSpace: 'nowrap',
|
|
44
|
+
color: 'black',
|
|
45
|
+
'&:hover': {
|
|
46
|
+
textDecoration: 'none',
|
|
47
|
+
},
|
|
48
|
+
paddingTop: 6,
|
|
49
|
+
},
|
|
50
|
+
line: {
|
|
51
|
+
maxWidth: 40,
|
|
52
|
+
width: '100%',
|
|
53
|
+
display: 'flex',
|
|
54
|
+
justifyContent: 'center',
|
|
55
|
+
height: 2,
|
|
56
|
+
background: theme.palette.primary.main,
|
|
57
|
+
margin: '0 auto',
|
|
58
|
+
marginTop: 6,
|
|
59
|
+
opacity: 0,
|
|
60
|
+
},
|
|
61
|
+
lineShow: {
|
|
62
|
+
opacity: 1,
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
{ name: 'DesktopNavBar' },
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
export type MenuTabsProps = MenuProps
|
|
69
|
+
|
|
70
|
+
export default function DesktopNavBar(props: MenuTabsProps) {
|
|
71
|
+
const { menu } = props
|
|
72
|
+
const classes = useStyles()
|
|
73
|
+
const router = useRouter()
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<ScrollerProvider scrollSnapAlign='none'>
|
|
77
|
+
<div className={classes.container}>
|
|
78
|
+
<Scroller className={classes.scroller} hideScrollbar>
|
|
79
|
+
{menu.map(({ href, children, ...linkProps }) => (
|
|
80
|
+
<PageLink key={href.toString()} href={href} {...linkProps} passHref>
|
|
81
|
+
<Link className={classes.link} variant='h6'>
|
|
82
|
+
{children}
|
|
83
|
+
<div
|
|
84
|
+
className={clsx(
|
|
85
|
+
classes.line,
|
|
86
|
+
router.asPath.startsWith(href.toString()) && classes.lineShow,
|
|
87
|
+
)}
|
|
88
|
+
/>
|
|
89
|
+
</Link>
|
|
90
|
+
</PageLink>
|
|
91
|
+
))}
|
|
92
|
+
<ScrollerButton
|
|
93
|
+
direction='left'
|
|
94
|
+
size='small'
|
|
95
|
+
className={clsx(classes.prevNext, classes.prev)}
|
|
96
|
+
>
|
|
97
|
+
<SvgImageSimple src={iconChevronLeft} />
|
|
98
|
+
</ScrollerButton>
|
|
99
|
+
<ScrollerButton
|
|
100
|
+
direction='right'
|
|
101
|
+
size='small'
|
|
102
|
+
className={clsx(classes.prevNext, classes.next)}
|
|
103
|
+
>
|
|
104
|
+
<SvgImageSimple src={iconChevronRight} />
|
|
105
|
+
</ScrollerButton>
|
|
106
|
+
</Scroller>
|
|
107
|
+
</div>
|
|
108
|
+
</ScrollerProvider>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import { m } from 'framer-motion'
|
|
3
|
+
import { UseStyles } from '../Styles'
|
|
4
|
+
|
|
5
|
+
const useStyles = makeStyles(
|
|
6
|
+
(theme: Theme) => ({
|
|
7
|
+
root: {
|
|
8
|
+
position: 'fixed',
|
|
9
|
+
top: 'unset',
|
|
10
|
+
bottom: 20,
|
|
11
|
+
right: 20,
|
|
12
|
+
zIndex: 100,
|
|
13
|
+
boxShadow: theme.shadows[4],
|
|
14
|
+
borderRadius: 99,
|
|
15
|
+
[theme.breakpoints.down('sm')]: {
|
|
16
|
+
top: 'unset !important',
|
|
17
|
+
},
|
|
18
|
+
[theme.breakpoints.up('md')]: {
|
|
19
|
+
pointerEvents: 'all',
|
|
20
|
+
top: `calc(${theme.spacings.xxs} - 2px)`,
|
|
21
|
+
left: `calc(100vw - ${theme.page.horizontal} - 70px)`,
|
|
22
|
+
bottom: 'unset',
|
|
23
|
+
boxShadow: 'unset',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
{
|
|
28
|
+
name: 'FixedFab',
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
type FixedFabProps = {
|
|
33
|
+
children: React.ReactNode
|
|
34
|
+
} & UseStyles<typeof useStyles>
|
|
35
|
+
|
|
36
|
+
export default function FixedFab(props: FixedFabProps) {
|
|
37
|
+
const { children } = props
|
|
38
|
+
const classes = useStyles(props)
|
|
39
|
+
|
|
40
|
+
return <m.div className={classes.root}>{children}</m.div>
|
|
41
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ButtonProps, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import Button from '../Button'
|
|
4
|
+
import { UseStyles } from '../Styles'
|
|
5
|
+
import SvgImage from '../SvgImage'
|
|
6
|
+
import { iconChevronRight } from '../icons'
|
|
7
|
+
|
|
8
|
+
const useStyles = makeStyles(
|
|
9
|
+
(theme: Theme) => ({
|
|
10
|
+
root: {
|
|
11
|
+
width: 'min-content',
|
|
12
|
+
pointerEvents: 'all',
|
|
13
|
+
[theme.breakpoints.down('sm')]: {
|
|
14
|
+
height: 40,
|
|
15
|
+
minWidth: 40,
|
|
16
|
+
borderRadius: 20,
|
|
17
|
+
},
|
|
18
|
+
[theme.breakpoints.down('xs')]: {
|
|
19
|
+
boxShadow: 'unset',
|
|
20
|
+
paddingLeft: `12px`,
|
|
21
|
+
paddingRight: `10px`,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
label: {
|
|
25
|
+
whiteSpace: 'nowrap',
|
|
26
|
+
},
|
|
27
|
+
icon: {
|
|
28
|
+
display: 'none',
|
|
29
|
+
[theme.breakpoints.up('sm')]: {
|
|
30
|
+
display: 'unset',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
text: {
|
|
34
|
+
pointerEvents: 'none',
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
{ name: 'ForwardButton' },
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
export type ForwardButtonProps = UseStyles<typeof useStyles> & ButtonProps & { down?: boolean }
|
|
41
|
+
|
|
42
|
+
const ForwardButton = React.forwardRef((props: ForwardButtonProps, ref) => {
|
|
43
|
+
const { text, icon, ...classes } = useStyles(props)
|
|
44
|
+
const { children, down, ...fabProps } = props
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Button variant='pill' classes={classes} {...fabProps}>
|
|
48
|
+
<span className={text}>{children}</span>
|
|
49
|
+
<SvgImage src={iconChevronRight} alt='chevron right' size='small' classes={{ root: icon }} />
|
|
50
|
+
</Button>
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
export default ForwardButton
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import { m } from 'framer-motion'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { UseStyles } from '../Styles'
|
|
5
|
+
import AppShellProvider from './AppShellProvider'
|
|
6
|
+
import ShellBase, { PageLayoutBaseProps } from './ShellBase'
|
|
7
|
+
|
|
8
|
+
const useStyles = makeStyles(
|
|
9
|
+
(theme: Theme) => ({
|
|
10
|
+
root: {
|
|
11
|
+
background: '#fff',
|
|
12
|
+
minHeight: '100vh',
|
|
13
|
+
display: 'grid',
|
|
14
|
+
gridTemplateRows: `auto 1fr auto`,
|
|
15
|
+
gridTemplateColumns: '100%',
|
|
16
|
+
},
|
|
17
|
+
header: {
|
|
18
|
+
display: 'flex',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
justifyContent: 'center',
|
|
21
|
+
[theme.breakpoints.up('md')]: {
|
|
22
|
+
padding: `${theme.spacings.xxs} ${theme.page.horizontal} 0`,
|
|
23
|
+
top: 0,
|
|
24
|
+
display: 'flex',
|
|
25
|
+
pointerEvents: 'none',
|
|
26
|
+
justifyContent: 'left',
|
|
27
|
+
width: '100%',
|
|
28
|
+
height: theme.page.headerInnerHeight.md,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
}),
|
|
32
|
+
{ name: 'FullPageShellBase' },
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
export type FullPageShellBaseProps = {
|
|
36
|
+
header: React.ReactNode
|
|
37
|
+
footer: React.ReactNode
|
|
38
|
+
children?: React.ReactNode
|
|
39
|
+
backFallbackHref?: string | null
|
|
40
|
+
backFallbackTitle?: string | null
|
|
41
|
+
} & UseStyles<typeof useStyles> &
|
|
42
|
+
PageLayoutBaseProps
|
|
43
|
+
|
|
44
|
+
export default function FullPageShellBase(props: FullPageShellBaseProps) {
|
|
45
|
+
const { children, header, footer, name } = props
|
|
46
|
+
const classes = useStyles(props)
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div className={classes.root}>
|
|
50
|
+
<AppShellProvider>
|
|
51
|
+
<ShellBase name={name}>
|
|
52
|
+
<header className={classes.header}>{header}</header>
|
|
53
|
+
<div>{children}</div>
|
|
54
|
+
<div>{footer}</div>
|
|
55
|
+
</ShellBase>
|
|
56
|
+
</AppShellProvider>
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Divider,
|
|
3
|
+
Fab,
|
|
4
|
+
List,
|
|
5
|
+
ListItem,
|
|
6
|
+
ListItemText,
|
|
7
|
+
makeStyles,
|
|
8
|
+
Menu,
|
|
9
|
+
Theme,
|
|
10
|
+
} from '@material-ui/core'
|
|
11
|
+
import { m } from 'framer-motion'
|
|
12
|
+
import PageLink from 'next/link'
|
|
13
|
+
import { Router, useRouter } from 'next/router'
|
|
14
|
+
import React from 'react'
|
|
15
|
+
import { UseStyles } from '../Styles'
|
|
16
|
+
import responsiveVal from '../Styles/responsiveVal'
|
|
17
|
+
import SvgImageSimple from '../SvgImage/SvgImageSimple'
|
|
18
|
+
import { iconMenu } from '../icons'
|
|
19
|
+
import { MenuProps } from './Menu'
|
|
20
|
+
import useFabAnimation from './useFabAnimation'
|
|
21
|
+
|
|
22
|
+
const useStyles = makeStyles(
|
|
23
|
+
(theme: Theme) => ({
|
|
24
|
+
menuWrapper: {
|
|
25
|
+
position: 'fixed',
|
|
26
|
+
zIndex: 99,
|
|
27
|
+
left: theme.page.horizontal,
|
|
28
|
+
top: `calc(${theme.spacings.xxs} - 5px)`,
|
|
29
|
+
[theme.breakpoints.down('sm')]: {
|
|
30
|
+
top: 'unset',
|
|
31
|
+
left: 20,
|
|
32
|
+
bottom: 20,
|
|
33
|
+
transform: 'none !important',
|
|
34
|
+
opacity: '1 !important',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
menuFab: {
|
|
38
|
+
background: theme.palette.text.primary,
|
|
39
|
+
boxShadow: theme.shadows[2],
|
|
40
|
+
width: responsiveVal(42, 56),
|
|
41
|
+
height: responsiveVal(42, 56),
|
|
42
|
+
pointerEvents: 'all',
|
|
43
|
+
'&:hover, &:focus': {
|
|
44
|
+
background: theme.palette.text.primary,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
menu: {
|
|
48
|
+
backgroundColor: theme.palette.background.paper,
|
|
49
|
+
color: theme.palette.text.primary,
|
|
50
|
+
minWidth: responsiveVal(200, 280),
|
|
51
|
+
},
|
|
52
|
+
menuItemText: {
|
|
53
|
+
fontSize: '1.5em',
|
|
54
|
+
fontWeight: 500,
|
|
55
|
+
letterSpacing: '-0.0375em',
|
|
56
|
+
lineHeight: 1,
|
|
57
|
+
},
|
|
58
|
+
menuItem: {},
|
|
59
|
+
}),
|
|
60
|
+
{ name: 'Menu' },
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
export type MenuFabProps = MenuProps &
|
|
64
|
+
UseStyles<typeof useStyles> & { children?: React.ReactNode; search?: React.ReactNode }
|
|
65
|
+
|
|
66
|
+
export default function MenuFab(props: MenuFabProps) {
|
|
67
|
+
const { menu, children, search } = props
|
|
68
|
+
const classes = useStyles(props)
|
|
69
|
+
const router = useRouter()
|
|
70
|
+
const [openEl, setOpenEl] = React.useState<null | HTMLElement>(null)
|
|
71
|
+
|
|
72
|
+
const { filter, opacity, scale } = useFabAnimation()
|
|
73
|
+
|
|
74
|
+
Router.events.on('routeChangeStart', () => setOpenEl(null))
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<m.div className={classes.menuWrapper} style={{ opacity, scale, filter }}>
|
|
78
|
+
<Fab
|
|
79
|
+
color='primary'
|
|
80
|
+
aria-label='Open Menu'
|
|
81
|
+
size='medium'
|
|
82
|
+
onClick={(event) => setOpenEl(event.currentTarget)}
|
|
83
|
+
className={classes.menuFab}
|
|
84
|
+
>
|
|
85
|
+
<SvgImageSimple src={iconMenu} inverted alt='menu' loading='eager' />
|
|
86
|
+
</Fab>
|
|
87
|
+
|
|
88
|
+
<Menu
|
|
89
|
+
anchorEl={openEl}
|
|
90
|
+
open={!!openEl}
|
|
91
|
+
onClose={() => setOpenEl(null)}
|
|
92
|
+
classes={{ paper: classes.menu }}
|
|
93
|
+
disableScrollLock
|
|
94
|
+
>
|
|
95
|
+
{search && (
|
|
96
|
+
<List>
|
|
97
|
+
<ListItem dense>{search}</ListItem>
|
|
98
|
+
</List>
|
|
99
|
+
)}
|
|
100
|
+
<List>
|
|
101
|
+
<PageLink href='/' passHref>
|
|
102
|
+
<ListItem
|
|
103
|
+
button
|
|
104
|
+
dense
|
|
105
|
+
selected={router.asPath === '/'}
|
|
106
|
+
classes={{ root: classes.menuItem }}
|
|
107
|
+
>
|
|
108
|
+
<ListItemText classes={{ primary: classes.menuItemText }}>Home</ListItemText>
|
|
109
|
+
</ListItem>
|
|
110
|
+
</PageLink>
|
|
111
|
+
|
|
112
|
+
{menu.map(({ href, children: itemChildren, ...linkProps }) => (
|
|
113
|
+
<PageLink key={href.toString()} href={href} {...linkProps} passHref>
|
|
114
|
+
<ListItem
|
|
115
|
+
button
|
|
116
|
+
dense
|
|
117
|
+
selected={router.asPath.startsWith(href.toString())}
|
|
118
|
+
classes={{ root: classes.menuItem }}
|
|
119
|
+
>
|
|
120
|
+
<ListItemText classes={{ primary: classes.menuItemText }}>
|
|
121
|
+
{itemChildren}
|
|
122
|
+
</ListItemText>
|
|
123
|
+
</ListItem>
|
|
124
|
+
</PageLink>
|
|
125
|
+
))}
|
|
126
|
+
</List>
|
|
127
|
+
<Divider variant='middle' />
|
|
128
|
+
<List component='div'>{children}</List>
|
|
129
|
+
</Menu>
|
|
130
|
+
</m.div>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ListItem, ListItemIcon, ListItemText, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import PageLink from 'next/link'
|
|
3
|
+
import router from 'next/router'
|
|
4
|
+
import React from 'react'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme: Theme) => ({
|
|
8
|
+
listItemText: {},
|
|
9
|
+
icon: { minWidth: 30 },
|
|
10
|
+
}),
|
|
11
|
+
{ name: 'FabMenuSecondaryItem' },
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
export type FabMenuSecondaryItemProps = {
|
|
15
|
+
href: string
|
|
16
|
+
children: React.ReactNode
|
|
17
|
+
icon: React.ReactNode
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function MenuFabSecondaryItem(props: FabMenuSecondaryItemProps) {
|
|
21
|
+
const { href, children, icon } = props
|
|
22
|
+
const classes = useStyles()
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<PageLink href={href} passHref>
|
|
26
|
+
<ListItem component='a' dense button selected={router.asPath.startsWith(href)}>
|
|
27
|
+
<ListItemIcon classes={{ root: classes.icon }}>{icon}</ListItemIcon>
|
|
28
|
+
<ListItemText primary={children} classes={{ primary: classes.listItemText }} />
|
|
29
|
+
</ListItem>
|
|
30
|
+
</PageLink>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import FullPageShellBase, { FullPageShellBaseProps } from './FullPageShellBase'
|
|
4
|
+
|
|
5
|
+
const useStyles = makeStyles(
|
|
6
|
+
(theme: Theme) => ({
|
|
7
|
+
header: {
|
|
8
|
+
[theme.breakpoints.up('md')]: {
|
|
9
|
+
minHeight: 60,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
}),
|
|
13
|
+
{ name: 'MinimalPageShellBase' },
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
export type MinimalPageShellBaseProps = FullPageShellBaseProps
|
|
17
|
+
|
|
18
|
+
export default function MinimalPageShellBase(props: MinimalPageShellBaseProps) {
|
|
19
|
+
const classes = useStyles(props)
|
|
20
|
+
|
|
21
|
+
return <FullPageShellBase {...props} classes={classes} />
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useViewportScroll } from 'framer-motion'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import AppShellHeader, { AppShellHeaderProps } from '../AppShellHeader'
|
|
4
|
+
|
|
5
|
+
export type PageShellHeaderProps = Omit<
|
|
6
|
+
AppShellHeaderProps,
|
|
7
|
+
'scrollY' | 'hideClose' | 'dragIndicator'
|
|
8
|
+
>
|
|
9
|
+
|
|
10
|
+
export default function PageShellHeader(props: PageShellHeaderProps) {
|
|
11
|
+
const { scrollY } = useViewportScroll()
|
|
12
|
+
|
|
13
|
+
return <AppShellHeader {...props} scrollY={scrollY} hideClose />
|
|
14
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import { usePageContext, usePageRouter } from '@graphcommerce/framer-next-pages'
|
|
3
|
+
import {
|
|
4
|
+
Sheet,
|
|
5
|
+
SheetBackdrop,
|
|
6
|
+
SheetContainer,
|
|
7
|
+
SheetPanel,
|
|
8
|
+
SheetProps,
|
|
9
|
+
SnapPoint,
|
|
10
|
+
styles,
|
|
11
|
+
} from '@graphcommerce/framer-sheet'
|
|
12
|
+
import { useDomEvent } from 'framer-motion'
|
|
13
|
+
import { useRouter } from 'next/router'
|
|
14
|
+
import React, { useRef } from 'react'
|
|
15
|
+
import responsiveVal from '../../Styles/responsiveVal'
|
|
16
|
+
import AppShellProvider from '../AppShellProvider'
|
|
17
|
+
import ShellBase, { PageLayoutBaseProps } from '../ShellBase'
|
|
18
|
+
import useSheetStyles from './useSheetStyles'
|
|
19
|
+
|
|
20
|
+
export type SheetShellBaseProps = {
|
|
21
|
+
header?: React.ReactNode
|
|
22
|
+
children?: React.ReactNode
|
|
23
|
+
} & Pick<SheetProps, 'size' | 'variant'> &
|
|
24
|
+
PageLayoutBaseProps
|
|
25
|
+
|
|
26
|
+
const useStyles = makeStyles(
|
|
27
|
+
(theme: Theme) => ({
|
|
28
|
+
container: {
|
|
29
|
+
...styles.container,
|
|
30
|
+
},
|
|
31
|
+
containertop: {
|
|
32
|
+
...styles.containertop,
|
|
33
|
+
},
|
|
34
|
+
containerbottom: {
|
|
35
|
+
...styles.containerbottom,
|
|
36
|
+
paddingTop: `calc(${theme.page.headerInnerHeight.md} * 0.55)`,
|
|
37
|
+
[theme.breakpoints.up('md')]: {
|
|
38
|
+
// offset top is x% of the header height, so it slightly overlaps the logo
|
|
39
|
+
paddingTop: `calc(${theme.page.headerInnerHeight.md} * 0.85)`,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
containerleft: {
|
|
43
|
+
...styles.containerleft,
|
|
44
|
+
paddingRight: responsiveVal(26, 48),
|
|
45
|
+
},
|
|
46
|
+
containerright: {
|
|
47
|
+
...styles.containerright,
|
|
48
|
+
paddingLeft: responsiveVal(26, 48),
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
{ name: 'SheetShellBase' },
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
function SheetShellBase(props: SheetShellBaseProps) {
|
|
55
|
+
const { children, variant, size, name } = props
|
|
56
|
+
const sheetContainerClasses = useStyles()
|
|
57
|
+
const sheetClasses = useSheetStyles(props)
|
|
58
|
+
const router = useRouter()
|
|
59
|
+
const pageRouter = usePageRouter()
|
|
60
|
+
const { depth, closeSteps, active } = usePageContext()
|
|
61
|
+
const open = depth < 0 || router.asPath === pageRouter.asPath
|
|
62
|
+
const initialLocale = useRef(router.locale)
|
|
63
|
+
|
|
64
|
+
function handleClose() {
|
|
65
|
+
return initialLocale.current !== router.locale
|
|
66
|
+
? pageRouter.push('/')
|
|
67
|
+
: pageRouter.go(closeSteps * -1)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function handleSnap(snapPoint: SnapPoint) {
|
|
71
|
+
if (snapPoint !== 'closed') return
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
73
|
+
handleClose()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const windowRef = useRef(typeof window !== 'undefined' ? window : null)
|
|
77
|
+
|
|
78
|
+
function handleEscapeKey(e: KeyboardEvent | Event) {
|
|
79
|
+
if (active) {
|
|
80
|
+
if ((e as KeyboardEvent)?.key === 'Escape') {
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
82
|
+
handleClose()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
useDomEvent(windowRef, 'keyup', handleEscapeKey, { passive: true })
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<AppShellProvider>
|
|
91
|
+
<ShellBase name={name}>
|
|
92
|
+
<Sheet open={open} onSnap={handleSnap} variant={variant} size={size}>
|
|
93
|
+
<SheetBackdrop onTap={handleClose} classes={sheetClasses} />
|
|
94
|
+
<SheetContainer classes={sheetContainerClasses}>
|
|
95
|
+
<SheetPanel classes={sheetClasses}>
|
|
96
|
+
{/* <FocusLock returnFocus={{ preventScroll: true }} disabled={!isActive}> */}
|
|
97
|
+
{children}
|
|
98
|
+
{/* </FocusLock> */}
|
|
99
|
+
</SheetPanel>
|
|
100
|
+
</SheetContainer>
|
|
101
|
+
</Sheet>
|
|
102
|
+
</ShellBase>
|
|
103
|
+
</AppShellProvider>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default SheetShellBase
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { makeStyles, StyleRules, Theme } from '@material-ui/core'
|
|
2
|
+
import { ClassNameMap } from '@material-ui/styles'
|
|
3
|
+
import styles, { ClassKeys } from '@graphcommerce/framer-sheet/styles'
|
|
4
|
+
|
|
5
|
+
type UseSheetStylesReturn = (props?: Record<string, unknown>) => ClassNameMap<ClassKeys>
|
|
6
|
+
|
|
7
|
+
const useSheetStyles = makeStyles<Theme, never, ClassKeys>(styles as StyleRules<ClassKeys>, {
|
|
8
|
+
name: 'Sheet',
|
|
9
|
+
}) as UseSheetStylesReturn
|
|
10
|
+
|
|
11
|
+
export default useSheetStyles
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { makeStyles } from '@material-ui/core'
|
|
2
|
+
import { SheetDragIndicator, SheetDragIndicatorProps, styles } from '@graphcommerce/framer-sheet'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import responsiveVal from '../../Styles/responsiveVal'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
() => ({
|
|
8
|
+
indicatorRoot: {
|
|
9
|
+
...styles.indicatorRoot,
|
|
10
|
+
position: 'absolute',
|
|
11
|
+
left: 0,
|
|
12
|
+
right: 0,
|
|
13
|
+
top: 0,
|
|
14
|
+
},
|
|
15
|
+
indicatorRoottop: {
|
|
16
|
+
...styles.indicatorRoottop,
|
|
17
|
+
padding: `${responsiveVal(4, 8)} 4px 4px 4px`,
|
|
18
|
+
},
|
|
19
|
+
indicatorRootbottom: {
|
|
20
|
+
...styles.indicatorRootbottom,
|
|
21
|
+
padding: `${responsiveVal(4, 8)} 4px 4px 4px`,
|
|
22
|
+
},
|
|
23
|
+
indicatorRootleft: {
|
|
24
|
+
...styles.indicatorRootleft,
|
|
25
|
+
},
|
|
26
|
+
indicatorRootright: {
|
|
27
|
+
...styles.indicatorRootright,
|
|
28
|
+
},
|
|
29
|
+
indicator: {
|
|
30
|
+
...styles.indicator,
|
|
31
|
+
borderRadius: 99,
|
|
32
|
+
backgroundColor: '#ddd',
|
|
33
|
+
},
|
|
34
|
+
indicatortop: { ...styles.indicatortop, width: responsiveVal(12, 40), height: 4 },
|
|
35
|
+
indicatorbottom: { ...styles.indicatorbottom, width: responsiveVal(12, 40), height: 4 },
|
|
36
|
+
indicatorleft: { ...styles.indicatorleft, width: 4, height: responsiveVal(12, 40) },
|
|
37
|
+
indicatorright: { ...styles.indicatorright, width: 4, height: responsiveVal(12, 40) },
|
|
38
|
+
}),
|
|
39
|
+
{ name: 'SheetShellDragIndicator' },
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
type SheetShellDragIndicatorProps = SheetDragIndicatorProps
|
|
43
|
+
|
|
44
|
+
export default function SheetShellDragIndicator(props: SheetShellDragIndicatorProps) {
|
|
45
|
+
const classes = useStyles()
|
|
46
|
+
|
|
47
|
+
return <SheetDragIndicator {...props} classes={classes} />
|
|
48
|
+
}
|