@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.
Files changed (153) hide show
  1. package/.babelrc +3 -0
  2. package/AnimatedRow/index.tsx +20 -0
  3. package/ApolloError/ApolloErrorAlert.tsx +59 -0
  4. package/ApolloError/ApolloErrorFullPage.tsx +25 -0
  5. package/AppShell/AppShellHeader/appShellHeaderContext.tsx +11 -0
  6. package/AppShell/AppShellHeader/index.tsx +433 -0
  7. package/AppShell/AppShellHeader/useAppShellHeaderContext.tsx +6 -0
  8. package/AppShell/AppShellProvider/index.tsx +18 -0
  9. package/AppShell/AppShellSticky/index.tsx +66 -0
  10. package/AppShell/AppShellTitle/index.tsx +45 -0
  11. package/AppShell/DesktopNavActions.tsx +28 -0
  12. package/AppShell/DesktopNavBar.tsx +110 -0
  13. package/AppShell/FixedFab.tsx +41 -0
  14. package/AppShell/ForwardButton.tsx +53 -0
  15. package/AppShell/FullPageShellBase.tsx +59 -0
  16. package/AppShell/Menu.tsx +7 -0
  17. package/AppShell/MenuFab.tsx +132 -0
  18. package/AppShell/MenuFabSecondaryItem.tsx +32 -0
  19. package/AppShell/MinimalPageShellBase.tsx +22 -0
  20. package/AppShell/PageShellHeader/index.tsx +14 -0
  21. package/AppShell/SheetShellBase/index.tsx +107 -0
  22. package/AppShell/SheetShellBase/useSheetStyles.ts +11 -0
  23. package/AppShell/SheetShellDragIndicator/index.tsx +48 -0
  24. package/AppShell/SheetShellHeader/index.tsx +28 -0
  25. package/AppShell/ShellBase.tsx +45 -0
  26. package/AppShell/useFabAnimation.tsx +19 -0
  27. package/AppShell/useFixedFabAnimation.tsx +18 -0
  28. package/AspectRatioContainer/index.tsx +27 -0
  29. package/Blog/BlogAuthor/index.tsx +60 -0
  30. package/Blog/BlogContent/index.tsx +24 -0
  31. package/Blog/BlogHeader/index.tsx +64 -0
  32. package/Blog/BlogList/index.tsx +27 -0
  33. package/Blog/BlogListItem/index.tsx +83 -0
  34. package/Blog/BlogTags/index.tsx +34 -0
  35. package/Blog/BlogTitle/index.tsx +29 -0
  36. package/Button/index.tsx +164 -0
  37. package/ButtonLink/index.tsx +45 -0
  38. package/CHANGELOG.md +1095 -0
  39. package/ChipMenu/index.tsx +130 -0
  40. package/ContainerWithHeader/index.tsx +49 -0
  41. package/Debug/DebugSpacer.tsx +51 -0
  42. package/FlagAvatar/index.tsx +28 -0
  43. package/Form/FormActions.tsx +15 -0
  44. package/Form/FormDivider.tsx +14 -0
  45. package/Form/FormHeader.tsx +27 -0
  46. package/Form/FormRow.tsx +14 -0
  47. package/Form/InputCheckmark.tsx +19 -0
  48. package/Form/index.tsx +62 -0
  49. package/FramerNextPagesSlider/Slide.tsx +71 -0
  50. package/FramerNextPagesSlider/Slider.tsx +39 -0
  51. package/FramerNextPagesSlider/index.ts +1 -0
  52. package/FramerNextPagesSlider/types.ts +3 -0
  53. package/FramerScroller/components/SidebarGallery.tsx +246 -0
  54. package/FramerScroller/components/SidebarSlider.tsx +103 -0
  55. package/FullPageMessage/index.tsx +68 -0
  56. package/Highlight/index.tsx +14 -0
  57. package/IconHeader/index.tsx +109 -0
  58. package/JsonLd/index.tsx +18 -0
  59. package/Page/App.tsx +15 -0
  60. package/Page/Document.tsx +23 -0
  61. package/Page/framerFeatures.ts +4 -0
  62. package/Page/types.ts +19 -0
  63. package/PageLoadIndicator/index.tsx +46 -0
  64. package/PageMeta/index.tsx +40 -0
  65. package/Pagination/index.tsx +123 -0
  66. package/RenderType/index.tsx +40 -0
  67. package/Row/ButtonLinkList/index.tsx +53 -0
  68. package/Row/ColumnOne/index.tsx +11 -0
  69. package/Row/ColumnOneBoxed/index.tsx +27 -0
  70. package/Row/ColumnOneCentered/index.tsx +22 -0
  71. package/Row/ColumnThree/index.tsx +66 -0
  72. package/Row/ColumnTwo/index.tsx +44 -0
  73. package/Row/ColumnTwoSpread/index.tsx +41 -0
  74. package/Row/ColumnTwoWithTop/index.tsx +53 -0
  75. package/Row/ContentLinks/index.tsx +48 -0
  76. package/Row/HeroBanner/index.tsx +102 -0
  77. package/Row/IconBlocks/IconBlock/index.tsx +56 -0
  78. package/Row/IconBlocks/index.tsx +57 -0
  79. package/Row/ParagraphWithSidebarSlide/index.tsx +114 -0
  80. package/Row/Quote/index.tsx +13 -0
  81. package/Row/RowImageText/index.tsx +67 -0
  82. package/Row/RowImageTextBoxed/index.tsx +75 -0
  83. package/Row/SpecialBanner/index.tsx +107 -0
  84. package/Row/index.tsx +13 -0
  85. package/SectionContainer/index.tsx +39 -0
  86. package/SectionHeader/index.tsx +69 -0
  87. package/Separator/index.tsx +33 -0
  88. package/Snackbar/ErrorSnackbar.tsx +9 -0
  89. package/Snackbar/MessageSnackbar.tsx +5 -0
  90. package/Snackbar/MessageSnackbarImpl.tsx +202 -0
  91. package/StarRatingField/index.tsx +58 -0
  92. package/Stepper/Stepper.tsx +45 -0
  93. package/StyledBadge/index.tsx +21 -0
  94. package/Styles/index.tsx +3 -0
  95. package/Styles/responsiveVal.tsx +20 -0
  96. package/SvgImage/SvgImageSimple.tsx +66 -0
  97. package/SvgImage/index.tsx +76 -0
  98. package/TextInputNumber/index.tsx +169 -0
  99. package/Theme/types.ts +63 -0
  100. package/TimeAgo/index.tsx +29 -0
  101. package/Title/index.tsx +71 -0
  102. package/ToggleButton/index.tsx +100 -0
  103. package/ToggleButtonGroup/index.tsx +112 -0
  104. package/UspList/UspListItem.tsx +46 -0
  105. package/UspList/index.tsx +32 -0
  106. package/icons/icon_addresses.svg +17 -0
  107. package/icons/icon_arrow_back.svg +1 -0
  108. package/icons/icon_arrow_forward.svg +1 -0
  109. package/icons/icon_box.svg +6 -0
  110. package/icons/icon_chat.svg +1 -0
  111. package/icons/icon_checkmark.svg +1 -0
  112. package/icons/icon_checkmark_green.svg +1 -0
  113. package/icons/icon_chevron_back.svg +8 -0
  114. package/icons/icon_chevron_down.svg +8 -0
  115. package/icons/icon_chevron_left.svg +8 -0
  116. package/icons/icon_chevron_right.svg +8 -0
  117. package/icons/icon_chevron_up.svg +8 -0
  118. package/icons/icon_close.svg +6 -0
  119. package/icons/icon_close_circle.svg +1 -0
  120. package/icons/icon_collapse_vertical.svg +11 -0
  121. package/icons/icon_customer_service.svg +6 -0
  122. package/icons/icon_email.svg +1 -0
  123. package/icons/icon_email_outline.svg +6 -0
  124. package/icons/icon_expand_vertical.svg +11 -0
  125. package/icons/icon_heart.svg +15 -0
  126. package/icons/icon_home.svg +6 -0
  127. package/icons/icon_id.svg +6 -0
  128. package/icons/icon_invoice_red.svg +7 -0
  129. package/icons/icon_location_red.svg +7 -0
  130. package/icons/icon_lock.svg +6 -0
  131. package/icons/icon_menu.svg +1 -0
  132. package/icons/icon_min.svg +1 -0
  133. package/icons/icon_newspaper.svg +6 -0
  134. package/icons/icon_party.svg +7 -0
  135. package/icons/icon_person.svg +6 -0
  136. package/icons/icon_person_alt.svg +6 -0
  137. package/icons/icon_person_alt_big.svg +15 -0
  138. package/icons/icon_phone.svg +1 -0
  139. package/icons/icon_plus.svg +1 -0
  140. package/icons/icon_sad_face.svg +11 -0
  141. package/icons/icon_sad_shoppingbag.svg +16 -0
  142. package/icons/icon_search.svg +1 -0
  143. package/icons/icon_shopping_bag.svg +7 -0
  144. package/icons/icon_shutdown.svg +6 -0
  145. package/icons/icon_star.svg +6 -0
  146. package/icons/icon_star_filled_muted.svg +6 -0
  147. package/icons/icon_star_yellow.svg +6 -0
  148. package/icons/index.tsx +42 -0
  149. package/index.ts +163 -0
  150. package/package.json +61 -0
  151. package/tsconfig.json +5 -0
  152. package/types.d.ts +13 -0
  153. 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,7 @@
1
+ import { LinkProps } from 'next/link'
2
+
3
+ type MenuItemProps = LinkProps & { children: React.ReactNode }
4
+
5
+ export type MenuProps = {
6
+ menu: MenuItemProps[]
7
+ }
@@ -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
+ }