@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,40 @@
|
|
|
1
|
+
import Head from 'next/head'
|
|
2
|
+
|
|
3
|
+
// https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#directives
|
|
4
|
+
export type MetaRobots =
|
|
5
|
+
| 'noindex'
|
|
6
|
+
| 'nofollow'
|
|
7
|
+
| 'noarchive'
|
|
8
|
+
| 'nosnippet'
|
|
9
|
+
| 'notranslate'
|
|
10
|
+
| 'noimageindex'
|
|
11
|
+
| `unavailable_after:${string}`
|
|
12
|
+
| `max-snippet:${number}`
|
|
13
|
+
| `max-image-preview:${'none' | 'standard' | 'large'}`
|
|
14
|
+
| `max-video-preview:${number}`
|
|
15
|
+
type MetaRobotsAll = ['all' | 'none']
|
|
16
|
+
|
|
17
|
+
export type PageMetaProps = {
|
|
18
|
+
title: string
|
|
19
|
+
canonical?: `http://${string}` | `https://${string}` | string
|
|
20
|
+
metaDescription?: string
|
|
21
|
+
metaRobots?: MetaRobotsAll | MetaRobots[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function PageMeta(props: PageMetaProps) {
|
|
25
|
+
const { title, canonical, metaDescription, metaRobots = ['all'] } = props
|
|
26
|
+
|
|
27
|
+
if (!(canonical ?? 'http').startsWith('http'))
|
|
28
|
+
throw new Error(`canonical must start with http:// or https://, '${canonical}' given`)
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Head>
|
|
32
|
+
<title>{title.trim()}</title>
|
|
33
|
+
{metaDescription && (
|
|
34
|
+
<meta name='description' content={metaDescription.trim()} key='meta-description' />
|
|
35
|
+
)}
|
|
36
|
+
<meta name='robots' content={metaRobots.join(',')} key='meta-robots' />
|
|
37
|
+
{canonical && <link rel='canonical' href={canonical} key='canonical' />}
|
|
38
|
+
</Head>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import { PaginationProps, usePagination } from '@material-ui/lab'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { UseStyles } from '../Styles'
|
|
5
|
+
import SvgImage from '../SvgImage'
|
|
6
|
+
import { iconChevronLeft, iconChevronRight } from '../icons'
|
|
7
|
+
|
|
8
|
+
const useStyles = makeStyles((theme: Theme) => ({
|
|
9
|
+
pagination: {
|
|
10
|
+
gridArea: 'pagination',
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
display: 'grid',
|
|
13
|
+
gap: 8,
|
|
14
|
+
gridAutoFlow: 'column',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
marginBottom: theme.spacings.xxl,
|
|
17
|
+
[theme.breakpoints.up('md')]: {
|
|
18
|
+
marginBottom: theme.spacings.lg,
|
|
19
|
+
},
|
|
20
|
+
...theme.typography.body1,
|
|
21
|
+
'& > *': {
|
|
22
|
+
whiteSpace: 'nowrap',
|
|
23
|
+
boxShadow: 'none',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
disabled: {
|
|
27
|
+
background: 'none !important',
|
|
28
|
+
},
|
|
29
|
+
root: {
|
|
30
|
+
margin: '32px auto 0 auto',
|
|
31
|
+
marginTop: theme.spacings.lg,
|
|
32
|
+
marginBottom: theme.spacings.lg,
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
// fontSize: 18,
|
|
37
|
+
'& span': {
|
|
38
|
+
padding: '0 8px 0 0',
|
|
39
|
+
},
|
|
40
|
+
'& a': {
|
|
41
|
+
transition: 'background .25s ease',
|
|
42
|
+
borderRadius: '100%',
|
|
43
|
+
height: 40,
|
|
44
|
+
width: 40,
|
|
45
|
+
'&:hover': {
|
|
46
|
+
background: 'rgba(0, 0, 0, 0.04)',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
[theme.breakpoints.down('xs')]: {
|
|
50
|
+
alignItems: 'center',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
icon: {
|
|
54
|
+
borderRadius: '100%',
|
|
55
|
+
padding: 6,
|
|
56
|
+
height: 40,
|
|
57
|
+
width: 40,
|
|
58
|
+
},
|
|
59
|
+
label: {
|
|
60
|
+
textAlign: 'center',
|
|
61
|
+
},
|
|
62
|
+
labelTitle: {
|
|
63
|
+
display: 'inline',
|
|
64
|
+
[theme.breakpoints.down('xs')]: {
|
|
65
|
+
display: 'block',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}))
|
|
69
|
+
|
|
70
|
+
export type PagePaginationProps = {
|
|
71
|
+
count: number
|
|
72
|
+
page: number
|
|
73
|
+
renderLink: (page: number, icon: React.ReactNode, btnProps: any) => React.ReactNode
|
|
74
|
+
} & Omit<PaginationProps, 'count' | 'defaultPage' | 'page' | 'renderItem'> &
|
|
75
|
+
UseStyles<typeof useStyles>
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Rel="prev" and rel="next" are deprecated by Google.
|
|
79
|
+
*
|
|
80
|
+
* Read more: https://ahrefs.com/blog/rel-prev-next-pagination/
|
|
81
|
+
*/
|
|
82
|
+
export default function Pagination(props: PagePaginationProps) {
|
|
83
|
+
const { count, page, renderLink, classes: styles, ...paginationProps } = props
|
|
84
|
+
const classes = useStyles(props)
|
|
85
|
+
const { items } = usePagination({
|
|
86
|
+
count,
|
|
87
|
+
defaultPage: 1,
|
|
88
|
+
page,
|
|
89
|
+
...paginationProps,
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
const prevBtnProps = items[0]
|
|
93
|
+
const nextBtnProps = items[items.length - 1]
|
|
94
|
+
|
|
95
|
+
const chevronLeft = (
|
|
96
|
+
<SvgImage
|
|
97
|
+
src={iconChevronLeft}
|
|
98
|
+
alt='chevron left'
|
|
99
|
+
shade={page === 1 ? 'muted' : undefined}
|
|
100
|
+
classes={{ root: classes.icon }}
|
|
101
|
+
/>
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const chevronRight = (
|
|
105
|
+
<SvgImage
|
|
106
|
+
src={iconChevronRight}
|
|
107
|
+
alt='chevron right'
|
|
108
|
+
shade={page === count ? 'muted' : undefined}
|
|
109
|
+
classes={{ root: classes.icon }}
|
|
110
|
+
/>
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div className={classes.root}>
|
|
115
|
+
{page === 1 ? chevronLeft : renderLink(page - 1, chevronLeft, prevBtnProps)}
|
|
116
|
+
|
|
117
|
+
<span className={classes.labelTitle}>Page</span>
|
|
118
|
+
<span className={classes.label}>{`${page} of ${Math.max(1, count)}`}</span>
|
|
119
|
+
|
|
120
|
+
{page === count ? chevronRight : renderLink(page + 1, chevronRight, nextBtnProps)}
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
/** To make renderers customizable we need to be able to provide renders for all types */
|
|
3
|
+
type TypeObject = { __typename: string; [index: string]: unknown }
|
|
4
|
+
|
|
5
|
+
type FilterTypeByTypename<A extends TypeObject, Typename extends string> = A extends unknown
|
|
6
|
+
? A['__typename'] extends Typename
|
|
7
|
+
? A
|
|
8
|
+
: never
|
|
9
|
+
: never
|
|
10
|
+
|
|
11
|
+
type TypeRenderMethod<P> = (props: P) => React.ReactElement | null
|
|
12
|
+
|
|
13
|
+
type TypeRenderMap<
|
|
14
|
+
T extends TypeObject,
|
|
15
|
+
TypeNames extends string,
|
|
16
|
+
TAdd extends Record<string, unknown>
|
|
17
|
+
> = {
|
|
18
|
+
[K in TypeNames]: TypeRenderMethod<FilterTypeByTypename<T, K> & TAdd>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type TypeRenderer<
|
|
22
|
+
T extends TypeObject,
|
|
23
|
+
TAdd extends Record<string, unknown> = Record<string, unknown>
|
|
24
|
+
> = TypeRenderMap<T, T['__typename'], TAdd>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A simple array with renderers but with strict typing that validates of the provided Renderer is
|
|
28
|
+
* actually able to render the Type
|
|
29
|
+
*/
|
|
30
|
+
export default function RenderType<
|
|
31
|
+
T extends TypeObject,
|
|
32
|
+
A extends Record<string, unknown> = Record<string, unknown>
|
|
33
|
+
>(props: { renderer: TypeRenderer<T, A> } & FilterTypeByTypename<T, T['__typename']> & A) {
|
|
34
|
+
const { renderer, __typename, ...typeItemProps } = props
|
|
35
|
+
const TypeItem: TypeRenderMethod<typeof typeItemProps> = renderer[__typename]
|
|
36
|
+
? renderer[__typename]
|
|
37
|
+
: () => <>{__typename}</>
|
|
38
|
+
|
|
39
|
+
return <TypeItem {...typeItemProps} __typename={__typename} />
|
|
40
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Theme } from '@material-ui/core'
|
|
2
|
+
import { makeStyles } from '@material-ui/styles'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import Row from '..'
|
|
5
|
+
import SectionContainer from '../../SectionContainer'
|
|
6
|
+
import { UseStyles } from '../../Styles'
|
|
7
|
+
import responsiveVal from '../../Styles/responsiveVal'
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles(
|
|
10
|
+
(theme: Theme) => ({
|
|
11
|
+
container: {
|
|
12
|
+
maxWidth: 820,
|
|
13
|
+
},
|
|
14
|
+
h1: {
|
|
15
|
+
textAlign: 'center',
|
|
16
|
+
...theme.typography.h2,
|
|
17
|
+
},
|
|
18
|
+
overline: {
|
|
19
|
+
display: 'block',
|
|
20
|
+
padding: `${theme.spacings.xs} 0`,
|
|
21
|
+
borderBottom: `1px solid ${theme.palette.grey[300]}`,
|
|
22
|
+
},
|
|
23
|
+
links: ({ containsBigLinks }: ButtonLinkListPropsBase) => ({
|
|
24
|
+
display: 'grid',
|
|
25
|
+
gridTemplateColumns: containsBigLinks
|
|
26
|
+
? undefined
|
|
27
|
+
: `repeat(auto-fill, minmax(${responsiveVal(210, 350)}, 1fr))`,
|
|
28
|
+
columnGap: theme.spacings.sm,
|
|
29
|
+
}),
|
|
30
|
+
}),
|
|
31
|
+
{ name: 'ButtonLinkList' },
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
type ButtonLinkListPropsBase = {
|
|
35
|
+
title: string
|
|
36
|
+
links: React.ReactNode
|
|
37
|
+
containsBigLinks: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type ButtonLinkListProps = UseStyles<typeof useStyles> & ButtonLinkListPropsBase
|
|
41
|
+
|
|
42
|
+
export default function ButtonLinkList(props: ButtonLinkListProps) {
|
|
43
|
+
const { title, links } = props
|
|
44
|
+
const classes = useStyles(props)
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Row maxWidth='md' className={classes.container}>
|
|
48
|
+
<SectionContainer labelLeft={title}>
|
|
49
|
+
<div className={classes.links}>{links}</div>
|
|
50
|
+
</SectionContainer>
|
|
51
|
+
</Row>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Container, ContainerProps, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import Row from '..'
|
|
4
|
+
|
|
5
|
+
const useStyles = makeStyles(
|
|
6
|
+
(theme: Theme) => ({
|
|
7
|
+
boxed: {
|
|
8
|
+
padding: theme.spacings.lg,
|
|
9
|
+
boxShadow: theme.shadows[24],
|
|
10
|
+
'& h1, & h2, & h3': {
|
|
11
|
+
marginTop: 0,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
}),
|
|
15
|
+
{ name: 'ColumnOneBoxed' },
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
export default function ColumnOneBoxed(props: ContainerProps) {
|
|
19
|
+
const { children } = props
|
|
20
|
+
const classes = useStyles(props)
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Row {...props}>
|
|
24
|
+
<div className={classes.boxed}>{children}</div>
|
|
25
|
+
</Row>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ContainerProps, styled } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import ColumnOne from '../ColumnOne'
|
|
4
|
+
|
|
5
|
+
const Wrapper = styled('div')(({ theme }) => ({
|
|
6
|
+
marginBottom: theme.spacings.lg,
|
|
7
|
+
marginTop: theme.spacings.lg,
|
|
8
|
+
textAlign: 'center',
|
|
9
|
+
maxWidth: `calc(1050px + calc(${theme.spacings.md} * 2))`,
|
|
10
|
+
margin: `0 auto`,
|
|
11
|
+
position: 'relative',
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
export default function ColumnOneCentered(props: ContainerProps) {
|
|
15
|
+
const { children } = props
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<ColumnOne>
|
|
19
|
+
<Wrapper>{children}</Wrapper>
|
|
20
|
+
</ColumnOne>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ContainerProps, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import Row from '..'
|
|
4
|
+
import { UseStyles } from '../../Styles'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme: Theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
display: 'grid',
|
|
10
|
+
gridColumnGap: theme.spacings.md,
|
|
11
|
+
gridRowGap: theme.spacings.lg,
|
|
12
|
+
gridTemplateColumns: `1fr`,
|
|
13
|
+
gridTemplateAreas: `
|
|
14
|
+
"one"
|
|
15
|
+
"two"
|
|
16
|
+
"three"
|
|
17
|
+
`,
|
|
18
|
+
'& h2, & h3': {
|
|
19
|
+
...theme.typography.h4,
|
|
20
|
+
[theme.breakpoints.up('md')]: {
|
|
21
|
+
marginBottom: '-25px',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
'& p': {
|
|
25
|
+
[theme.breakpoints.up('md')]: {
|
|
26
|
+
marginTop: '65px',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
[theme.breakpoints.up('sm')]: {
|
|
30
|
+
gridTemplateColumns: `1fr 1fr`,
|
|
31
|
+
gridTemplateAreas: `
|
|
32
|
+
"one two"
|
|
33
|
+
"three three"
|
|
34
|
+
`,
|
|
35
|
+
},
|
|
36
|
+
[theme.breakpoints.up('md')]: {
|
|
37
|
+
gridTemplateColumns: `1fr 1fr 1fr`,
|
|
38
|
+
gridTemplateAreas: '"one two three"',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
colOne: { gridArea: 'one', zIndex: 2 },
|
|
42
|
+
colTwo: { gridArea: 'two', zIndex: 2 },
|
|
43
|
+
colThree: { gridArea: 'three', zIndex: 2 },
|
|
44
|
+
}),
|
|
45
|
+
{ name: 'ColumnThree' },
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
export type ColumnThreeProps = UseStyles<typeof useStyles> &
|
|
49
|
+
Omit<ContainerProps, 'children'> & {
|
|
50
|
+
colOneContent: React.ReactNode
|
|
51
|
+
colTwoContent: React.ReactNode
|
|
52
|
+
colThreeContent: React.ReactNode
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default function ColumnThree(props: ColumnThreeProps) {
|
|
56
|
+
const { colOneContent, colTwoContent, colThreeContent, ...containerProps } = props
|
|
57
|
+
const classes = useStyles(props)
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<Row className={classes.root} {...containerProps}>
|
|
61
|
+
<div className={classes.colOne}>{colOneContent}</div>
|
|
62
|
+
<div className={classes.colTwo}>{colTwoContent}</div>
|
|
63
|
+
<div className={classes.colThree}>{colThreeContent}</div>
|
|
64
|
+
</Row>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ContainerProps, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import Row from '..'
|
|
4
|
+
import { UseStyles } from '../../Styles'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme: Theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
gridColumnGap: theme.spacings.md,
|
|
10
|
+
gridRowGap: theme.spacings.lg,
|
|
11
|
+
display: `grid`,
|
|
12
|
+
gridTemplateColumns: `1fr`,
|
|
13
|
+
gridTemplateAreas: `"one" "two"`,
|
|
14
|
+
'& h2, & h3': {
|
|
15
|
+
...theme.typography.h4,
|
|
16
|
+
},
|
|
17
|
+
[theme.breakpoints.up('sm')]: {
|
|
18
|
+
gridTemplateColumns: `1fr 1fr`,
|
|
19
|
+
gridTemplateAreas: `"one two"`,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
colOne: { gridArea: 'one' },
|
|
23
|
+
colTwo: { gridArea: 'two' },
|
|
24
|
+
}),
|
|
25
|
+
{ name: 'ColumnTwo' },
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
export type ColumnTwoProps = UseStyles<typeof useStyles> &
|
|
29
|
+
Omit<ContainerProps, 'children'> & {
|
|
30
|
+
colOneContent: React.ReactNode
|
|
31
|
+
colTwoContent: React.ReactNode
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default function ColumnTwo(props: ColumnTwoProps) {
|
|
35
|
+
const { colOneContent, colTwoContent, ...containerProps } = props
|
|
36
|
+
const classes = useStyles(props)
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Row maxWidth='lg' {...containerProps} className={classes.root}>
|
|
40
|
+
<div className={classes.colOne}>{colOneContent}</div>
|
|
41
|
+
<div className={classes.colTwo}>{colTwoContent}</div>
|
|
42
|
+
</Row>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ContainerProps, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { UseStyles } from '../../Styles'
|
|
4
|
+
import ColumnTwo from '../ColumnTwo'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
({ breakpoints }: Theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
[breakpoints.up('md')]: {
|
|
10
|
+
gridTemplateColumns: `1fr 1fr 1fr`,
|
|
11
|
+
gridTemplateAreas: ({ somethingWithNodeLength }: any) =>
|
|
12
|
+
somethingWithNodeLength ? `"one one two"` : `"one two two"`,
|
|
13
|
+
'& h2, & h3': {
|
|
14
|
+
'&:empty': {
|
|
15
|
+
display: 'block',
|
|
16
|
+
minHeight: 30,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
gridTemplateColumns: `1fr`,
|
|
21
|
+
gridTemplateAreas: `
|
|
22
|
+
"one"
|
|
23
|
+
"two"
|
|
24
|
+
`,
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
{ name: 'ColumnTwoSpread' },
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
export type ColumnTwoSpreadProps = Omit<ContainerProps, 'children'> &
|
|
31
|
+
UseStyles<typeof useStyles> & {
|
|
32
|
+
nodeLength: boolean
|
|
33
|
+
colOneContent: React.ReactNode
|
|
34
|
+
colTwoContent: React.ReactNode
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default function ColumnTwoSpread(props: ColumnTwoSpreadProps) {
|
|
38
|
+
const classes = useStyles(props)
|
|
39
|
+
|
|
40
|
+
return <ColumnTwo {...props} classes={classes} />
|
|
41
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Container, makeStyles, Theme } from '@material-ui/core'
|
|
2
|
+
import React, { PropsWithChildren } from 'react'
|
|
3
|
+
import Row from '..'
|
|
4
|
+
import { UseStyles } from '../../Styles'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme: Theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
display: 'grid',
|
|
10
|
+
gap: `${theme.spacings.lg} 0`,
|
|
11
|
+
gridTemplateAreas: `"top"
|
|
12
|
+
"left"
|
|
13
|
+
"right"`,
|
|
14
|
+
[theme.breakpoints.up('md')]: {
|
|
15
|
+
gridTemplateAreas: `"top ."
|
|
16
|
+
"left right"`,
|
|
17
|
+
gridTemplateColumns: '1fr auto',
|
|
18
|
+
gap: `${theme.spacings.sm} ${theme.spacings.xl}`,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
top: {
|
|
22
|
+
gridArea: 'top',
|
|
23
|
+
},
|
|
24
|
+
left: {
|
|
25
|
+
gridArea: 'left',
|
|
26
|
+
},
|
|
27
|
+
right: {
|
|
28
|
+
gridArea: 'right',
|
|
29
|
+
},
|
|
30
|
+
}),
|
|
31
|
+
{ name: 'ColumnTwoWithTop' },
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
export type ProductDescriptionProps = PropsWithChildren<
|
|
35
|
+
UseStyles<typeof useStyles> & {
|
|
36
|
+
top: React.ReactNode
|
|
37
|
+
left: React.ReactNode
|
|
38
|
+
right: React.ReactNode
|
|
39
|
+
}
|
|
40
|
+
>
|
|
41
|
+
|
|
42
|
+
export default function ColumnTwoWithTop(props: ProductDescriptionProps) {
|
|
43
|
+
const { top, left, right } = props
|
|
44
|
+
const classes = useStyles(props)
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Row className={classes.root}>
|
|
48
|
+
<div className={classes.top}>{top}</div>
|
|
49
|
+
<div className={classes.left}>{left}</div>
|
|
50
|
+
<div className={classes.right}>{right}</div>
|
|
51
|
+
</Row>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Container, makeStyles, Theme, Typography } from '@material-ui/core'
|
|
2
|
+
import { Scroller, ScrollerProvider } from '@graphcommerce/framer-scroller'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { UseStyles } from '../../Styles'
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles(
|
|
7
|
+
(theme: Theme) => ({
|
|
8
|
+
root: {},
|
|
9
|
+
scroller: {
|
|
10
|
+
marginBottom: `${theme.spacings.lg}`,
|
|
11
|
+
display: 'grid',
|
|
12
|
+
gridAutoFlow: 'column',
|
|
13
|
+
justifyContent: 'start',
|
|
14
|
+
gap: `${theme.spacings.md}`,
|
|
15
|
+
alignContent: 'center',
|
|
16
|
+
'& > *': {
|
|
17
|
+
minWidth: 'max-content',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
title: {
|
|
21
|
+
fontWeight: 600,
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
{ name: 'ContentLinks' },
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
export type ContentLinksProps = UseStyles<typeof useStyles> & {
|
|
28
|
+
title: string
|
|
29
|
+
children: React.ReactNode
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default function ContentLinks(props: ContentLinksProps) {
|
|
33
|
+
const { title, children } = props
|
|
34
|
+
const classes = useStyles(props)
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Container className={classes.root} maxWidth={false}>
|
|
38
|
+
<ScrollerProvider scrollSnapAlign='none'>
|
|
39
|
+
<Scroller className={classes.scroller} hideScrollbar>
|
|
40
|
+
<Typography variant='body1' component='h4' className={classes.title}>
|
|
41
|
+
{title}
|
|
42
|
+
</Typography>
|
|
43
|
+
{children}
|
|
44
|
+
</Scroller>
|
|
45
|
+
</ScrollerProvider>
|
|
46
|
+
</Container>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ContainerProps, Theme } from '@material-ui/core'
|
|
2
|
+
import { makeStyles } from '@material-ui/styles'
|
|
3
|
+
import { m, useTransform, useViewportScroll } from 'framer-motion'
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import Row from '..'
|
|
6
|
+
import { UseStyles } from '../../Styles'
|
|
7
|
+
import responsiveVal from '../../Styles/responsiveVal'
|
|
8
|
+
|
|
9
|
+
const useStyles = makeStyles(
|
|
10
|
+
(theme: Theme) => ({
|
|
11
|
+
container: {
|
|
12
|
+
[theme.breakpoints.up('md')]: {
|
|
13
|
+
paddingTop: theme.spacings.xxs,
|
|
14
|
+
},
|
|
15
|
+
paddingLeft: 0,
|
|
16
|
+
paddingRight: 0,
|
|
17
|
+
},
|
|
18
|
+
wrapper: {
|
|
19
|
+
position: 'relative',
|
|
20
|
+
},
|
|
21
|
+
copy: {
|
|
22
|
+
zIndex: 1,
|
|
23
|
+
color: theme.palette.secondary.contrastText,
|
|
24
|
+
position: 'relative',
|
|
25
|
+
display: 'grid',
|
|
26
|
+
justifyItems: 'center',
|
|
27
|
+
alignContent: 'center',
|
|
28
|
+
padding: `${theme.spacings.lg} ${theme.spacings.md}`,
|
|
29
|
+
minHeight: '90vh',
|
|
30
|
+
'& > *': {
|
|
31
|
+
zIndex: 1,
|
|
32
|
+
maxWidth: 'max-content',
|
|
33
|
+
},
|
|
34
|
+
[theme.breakpoints.up('md')]: {
|
|
35
|
+
width: '70%',
|
|
36
|
+
},
|
|
37
|
+
[theme.breakpoints.up('lg')]: {
|
|
38
|
+
padding: `${theme.spacings.lg} ${theme.spacings.lg}`,
|
|
39
|
+
width: '50%',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
asset: {
|
|
43
|
+
position: 'absolute',
|
|
44
|
+
top: '0',
|
|
45
|
+
zIndex: 0,
|
|
46
|
+
width: '100%',
|
|
47
|
+
height: '100%',
|
|
48
|
+
display: 'grid',
|
|
49
|
+
justifyItems: 'center',
|
|
50
|
+
overflow: 'hidden',
|
|
51
|
+
'& video': {
|
|
52
|
+
objectFit: 'cover',
|
|
53
|
+
width: '100%',
|
|
54
|
+
height: '100%',
|
|
55
|
+
},
|
|
56
|
+
[theme.breakpoints.up('md')]: {
|
|
57
|
+
height: '100%',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
{ name: 'HeroBanner' },
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
export type HeroBannerProps = UseStyles<typeof useStyles> &
|
|
65
|
+
ContainerProps & {
|
|
66
|
+
pageLinks: React.ReactNode
|
|
67
|
+
videoSrc: string
|
|
68
|
+
children: React.ReactNode
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default function HeroBanner(props: HeroBannerProps) {
|
|
72
|
+
const { pageLinks, videoSrc, children, ...containerProps } = props
|
|
73
|
+
const classes = useStyles(props)
|
|
74
|
+
|
|
75
|
+
const { scrollY } = useViewportScroll()
|
|
76
|
+
const actionsAnimWidth = useTransform(
|
|
77
|
+
scrollY,
|
|
78
|
+
[10, 150],
|
|
79
|
+
[`calc(100% - ${responsiveVal(30, 60)})`, `calc(100% - ${responsiveVal(0, 0)})`],
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Row maxWidth={false} {...containerProps} className={classes.container}>
|
|
84
|
+
<div className={classes.wrapper}>
|
|
85
|
+
<div className={classes.copy}>
|
|
86
|
+
{children}
|
|
87
|
+
{pageLinks}
|
|
88
|
+
</div>
|
|
89
|
+
<div className={classes.asset}>
|
|
90
|
+
<m.video
|
|
91
|
+
src={videoSrc}
|
|
92
|
+
autoPlay
|
|
93
|
+
muted
|
|
94
|
+
loop
|
|
95
|
+
playsInline
|
|
96
|
+
style={{ width: actionsAnimWidth }}
|
|
97
|
+
/>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</Row>
|
|
101
|
+
)
|
|
102
|
+
}
|