@graphcommerce/next-ui 3.25.2 → 4.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 (138) hide show
  1. package/AnimatedRow/index.tsx +6 -3
  2. package/ApolloError/ApolloErrorAlert.tsx +20 -21
  3. package/ApolloError/ApolloErrorFullPage.tsx +3 -4
  4. package/ApolloError/ApolloErrorSnackbar.tsx +3 -3
  5. package/Blog/BlogAuthor/index.tsx +42 -48
  6. package/Blog/BlogContent/index.tsx +6 -23
  7. package/Blog/BlogHeader/index.tsx +26 -23
  8. package/Blog/BlogList/index.tsx +7 -25
  9. package/Blog/BlogListItem/index.tsx +63 -52
  10. package/Blog/BlogTags/BlogTag.tsx +27 -0
  11. package/Blog/BlogTags/index.tsx +7 -32
  12. package/Blog/BlogTitle/index.tsx +7 -21
  13. package/Button/Button.tsx +5 -0
  14. package/Button/LinkOrButton.tsx +80 -0
  15. package/Button/index.tsx +2 -177
  16. package/CHANGELOG.md +507 -642
  17. package/ChipMenu/index.tsx +71 -77
  18. package/ContainerWithHeader/index.tsx +33 -30
  19. package/FlagAvatar/index.tsx +2 -12
  20. package/Footer/Footer.tsx +105 -88
  21. package/Footer/index.ts +0 -1
  22. package/Form/Form.tsx +35 -0
  23. package/Form/FormActions.tsx +9 -14
  24. package/Form/FormDivider.tsx +8 -13
  25. package/Form/FormHeader.tsx +5 -26
  26. package/Form/FormRow.tsx +8 -13
  27. package/Form/InputCheckmark.tsx +9 -22
  28. package/FramerScroller/SidebarGallery.tsx +340 -0
  29. package/FramerScroller/SidebarSlider.tsx +107 -0
  30. package/FramerScroller/index.ts +2 -0
  31. package/FullPageMessage/index.tsx +52 -48
  32. package/Highlight/index.tsx +1 -1
  33. package/IconHeader/index.tsx +63 -58
  34. package/JsonLd/index.tsx +3 -2
  35. package/Layout/components/LayoutHeader.tsx +75 -82
  36. package/Layout/components/LayoutHeaderBack.tsx +21 -12
  37. package/Layout/components/LayoutHeaderClose.tsx +9 -22
  38. package/Layout/components/LayoutHeaderContent.tsx +190 -154
  39. package/Layout/components/LayoutHeadertypes.ts +1 -1
  40. package/Layout/components/LayoutTitle.tsx +60 -55
  41. package/LayoutDefault/components/LayoutDefault.tsx +96 -85
  42. package/LayoutOverlay/components/LayoutOverlay.tsx +2 -8
  43. package/LayoutOverlay/components/LayoutOverlayBase.tsx +233 -239
  44. package/LayoutOverlay/test/LayoutOverlayDemo.tsx +1 -1
  45. package/LayoutParts/DesktopHeaderBadge.tsx +28 -0
  46. package/LayoutParts/DesktopNavActions.tsx +15 -0
  47. package/LayoutParts/DesktopNavBar.tsx +113 -0
  48. package/LayoutParts/DesktopNavBarItem.tsx +44 -0
  49. package/{AppShell → LayoutParts}/GlobalHead.tsx +1 -2
  50. package/LayoutParts/Logo.tsx +77 -0
  51. package/LayoutParts/MenuFab.tsx +131 -0
  52. package/LayoutParts/MenuFabItem.tsx +25 -0
  53. package/LayoutParts/MenuFabSecondaryItem.tsx +37 -0
  54. package/{AppShell/PlaceholderFab/index.tsx → LayoutParts/PlaceholderFab.tsx} +1 -1
  55. package/LayoutParts/StickyBelowHeader.tsx +25 -0
  56. package/LayoutParts/index.ts +12 -0
  57. package/{AppShell → LayoutParts}/useFabAnimation.ts +0 -0
  58. package/Page/CssAndFramerMotionProvider.tsx +21 -0
  59. package/Page/index.ts +2 -0
  60. package/Page/types.ts +2 -8
  61. package/PageLoadIndicator/index.tsx +25 -30
  62. package/PageMeta/index.tsx +1 -1
  63. package/Pagination/index.tsx +37 -54
  64. package/RenderType/index.tsx +1 -1
  65. package/Row/ButtonLinkList/ButtonLinkList.tsx +35 -37
  66. package/Row/ButtonLinkList/ButtonLinkListItem.tsx +16 -33
  67. package/Row/ColumnOne/index.tsx +5 -10
  68. package/Row/ColumnOneBoxed/index.tsx +18 -19
  69. package/Row/ColumnOneCentered/index.tsx +3 -4
  70. package/Row/ColumnThree/index.tsx +62 -57
  71. package/Row/ColumnTwo/index.tsx +37 -35
  72. package/Row/ColumnTwoSpread/index.tsx +28 -37
  73. package/Row/ColumnTwoWithTop/index.tsx +37 -43
  74. package/Row/ContentLinks/index.tsx +24 -25
  75. package/Row/HeroBanner/index.tsx +98 -82
  76. package/Row/IconBlocks/IconBlock/index.tsx +45 -37
  77. package/Row/IconBlocks/index.tsx +29 -44
  78. package/Row/ImageText/index.tsx +71 -67
  79. package/Row/ImageTextBoxed/index.tsx +66 -65
  80. package/Row/ParagraphWithSidebarSlide/index.tsx +80 -76
  81. package/Row/Quote/index.tsx +3 -3
  82. package/Row/SpecialBanner/index.tsx +97 -97
  83. package/Row/index.tsx +4 -9
  84. package/SectionContainer/index.tsx +32 -31
  85. package/SectionHeader/index.tsx +41 -43
  86. package/Separator/index.tsx +19 -18
  87. package/Snackbar/MessageSnackbar.tsx +1 -2
  88. package/Snackbar/MessageSnackbarImpl.tsx +68 -115
  89. package/StarRatingField/index.tsx +24 -25
  90. package/Stepper/Stepper.tsx +34 -32
  91. package/Styles/EmotionProvider.tsx +14 -0
  92. package/Styles/breakpointVal.tsx +16 -10
  93. package/Styles/extendableComponent.ts +70 -0
  94. package/Styles/index.tsx +9 -2
  95. package/Styles/withEmotionCache.tsx +36 -0
  96. package/Styles/withTheme.tsx +15 -24
  97. package/SvgIcon/SvgIcon.tsx +60 -0
  98. package/TextInputNumber/index.tsx +49 -50
  99. package/Theme/MuiButton.ts +128 -0
  100. package/Theme/MuiSlider.ts +28 -0
  101. package/Theme/MuiSnackbar.ts +31 -0
  102. package/Theme/{types.ts → createTheme.ts} +8 -2
  103. package/Theme/index.ts +4 -0
  104. package/Theme/themeDefaults.ts +51 -0
  105. package/TimeAgo/index.tsx +1 -1
  106. package/ToggleButton/index.tsx +43 -49
  107. package/ToggleButtonGroup/index.tsx +39 -39
  108. package/UspList/UspListItem.tsx +56 -46
  109. package/UspList/index.tsx +29 -26
  110. package/docs/building-components.mdx +3 -0
  111. package/docs/components/ComponentBasic.tsx +26 -0
  112. package/docs/components/ComponentChild.tsx +48 -0
  113. package/docs/components/ComponentChildVariant.tsx +54 -0
  114. package/docs/components/ComponentChildVariantExtendable.tsx +62 -0
  115. package/docs/components/ComponentStylable.tsx +32 -0
  116. package/docs/pages/building-components.tsx +62 -0
  117. package/index.ts +27 -81
  118. package/package.json +27 -27
  119. package/types.d.ts +1 -1
  120. package/AppShell/AppShellSticky/index.tsx +0 -38
  121. package/AppShell/DesktopNavActions.tsx +0 -32
  122. package/AppShell/DesktopNavBar.tsx +0 -158
  123. package/AppShell/Logo.tsx +0 -46
  124. package/AppShell/Menu.tsx +0 -7
  125. package/AppShell/MenuFab.tsx +0 -162
  126. package/AppShell/MenuFabSecondaryItem.tsx +0 -32
  127. package/AppShell/index.ts +0 -15
  128. package/AspectRatioContainer/index.tsx +0 -27
  129. package/Footer/SocialIcon.tsx +0 -23
  130. package/Form/index.tsx +0 -67
  131. package/FramerScroller/components/SidebarGallery.tsx +0 -317
  132. package/FramerScroller/components/SidebarSlider.tsx +0 -97
  133. package/Page/App.tsx +0 -17
  134. package/Page/Document.tsx +0 -24
  135. package/StyledBadge/index.tsx +0 -20
  136. package/Styles/classesPicker.ts +0 -41
  137. package/SvgImage/SvgImageSimple.tsx +0 -100
  138. package/SvgImage/index.tsx +0 -74
@@ -1,21 +1,8 @@
1
- import { makeStyles } from '@material-ui/core'
2
- import clsx from 'clsx'
3
- import React, { PropsWithChildren } from 'react'
4
- import SvgImageSimple from '../SvgImage/SvgImageSimple'
1
+ import { SvgIconProps } from '@mui/material'
2
+ import { SvgIcon } from '../SvgIcon/SvgIcon'
5
3
  import { iconCheckmark } from '../icons'
6
4
 
7
- export type InputCheckmarkProps = PropsWithChildren<{ show?: boolean; select?: boolean }>
8
- const useStyles = makeStyles(
9
- {
10
- iconCheckmark: {
11
- stroke: '#01D26A',
12
- },
13
- select: {
14
- marginRight: 15,
15
- },
16
- },
17
- { name: 'InputCheckmark' },
18
- )
5
+ export type InputCheckmarkProps = { show?: boolean; select?: boolean } & Omit<SvgIconProps, 'src'>
19
6
 
20
7
  /**
21
8
  * When the `valid` prop is passed it will render a CheckIcon, else it will render children.
@@ -24,15 +11,15 @@ const useStyles = makeStyles(
24
11
  * ;<InputCheckmark valid>Fallback things</InputCheckmark>
25
12
  * ```
26
13
  */
27
- export default function InputCheckmark(props: InputCheckmarkProps) {
28
- const { show: valid, children, select = false } = props
29
- const classes = useStyles()
14
+ export function InputCheckmark(props: InputCheckmarkProps) {
15
+ const { show, children, select = false } = props
30
16
 
31
- if (!valid) return <>{children}</>
17
+ if (!show) return <>{children}</>
32
18
  return (
33
- <SvgImageSimple
19
+ <SvgIcon
34
20
  src={iconCheckmark}
35
- className={clsx(classes.iconCheckmark, select && classes.select)}
21
+ className='InputCheckmark'
22
+ sx={[{ stroke: '#01D26A' }, select && { marginRight: '15px' }]}
36
23
  />
37
24
  )
38
25
  }
@@ -0,0 +1,340 @@
1
+ import { usePrevPageRouter } from '@graphcommerce/framer-next-pages/hooks/usePrevPageRouter'
2
+ import {
3
+ MotionImageAspect,
4
+ MotionImageAspectProps,
5
+ Scroller,
6
+ ScrollerButton,
7
+ ScrollerDots,
8
+ ScrollerProvider,
9
+ } from '@graphcommerce/framer-scroller'
10
+ import { clientSize, useMotionValueValue } from '@graphcommerce/framer-utils'
11
+ import { Fab, useTheme, alpha, Box, styled } from '@mui/material'
12
+ import { m, useDomEvent, useMotionValue } from 'framer-motion'
13
+ import { useRouter } from 'next/router'
14
+ import React, { useEffect, useRef } from 'react'
15
+ import { Row } from '../Row'
16
+ import { extendableComponent } from '../Styles'
17
+ import { responsiveVal } from '../Styles/responsiveVal'
18
+ import { SvgIcon } from '../SvgIcon/SvgIcon'
19
+ import { iconChevronLeft, iconChevronRight, iconFullscreen, iconFullscreenExit } from '../icons'
20
+
21
+ const MotionBox = styled(m.div)({})
22
+
23
+ type OwnerState = { zoomed: boolean }
24
+ const name = 'SidebarGallery' as const
25
+ const parts = [
26
+ 'row',
27
+ 'root',
28
+ 'scrollerContainer',
29
+ 'scroller',
30
+ 'sidebarWrapper',
31
+ 'sidebar',
32
+ 'bottomCenter',
33
+ 'sliderButtons',
34
+ 'toggleIcon',
35
+ 'topRight',
36
+ 'centerLeft',
37
+ 'centerRight',
38
+ 'dots',
39
+ ] as const
40
+ const { withState, selectors } = extendableComponent<OwnerState, typeof name, typeof parts>(
41
+ name,
42
+ parts,
43
+ )
44
+
45
+ export type SidebarGalleryProps = {
46
+ sidebar: React.ReactNode
47
+ images: MotionImageAspectProps[]
48
+ aspectRatio?: [number, number]
49
+ routeHash?: string
50
+ }
51
+
52
+ export function SidebarGallery(props: SidebarGalleryProps) {
53
+ const { sidebar, images, aspectRatio: [width, height] = [1, 1], routeHash = 'gallery' } = props
54
+
55
+ const router = useRouter()
56
+ const prevRoute = usePrevPageRouter()
57
+ const clientHeight = useMotionValueValue(clientSize.y, (y) => y)
58
+ // const classes = useMergedClasses(useStyles({ clientHeight, aspectRatio }).classes, props.classes)
59
+
60
+ const route = `#${routeHash}`
61
+ // We're using the URL to manage the state of the gallery.
62
+ const zoomed = router.asPath.endsWith(route)
63
+
64
+ // cleanup if someone enters the page with #gallery
65
+ useEffect(() => {
66
+ if (!prevRoute?.pathname && zoomed) {
67
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
68
+ router.replace(router.asPath.replace(route, ''))
69
+ }
70
+ }, [prevRoute?.pathname, route, router, zoomed])
71
+
72
+ const toggle = () => {
73
+ if (!zoomed) {
74
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
75
+ router.push(route, undefined, { shallow: true })
76
+ document.body.style.overflow = 'hidden'
77
+ window.scrollTo({ top: 0, behavior: 'smooth' })
78
+ } else {
79
+ router.back()
80
+ }
81
+ }
82
+
83
+ const classes = withState({ zoomed })
84
+ const theme = useTheme()
85
+ const windowRef = useRef(typeof window !== 'undefined' ? window : null)
86
+
87
+ const handleEscapeKey = (e: KeyboardEvent | Event) => {
88
+ if (zoomed && (e as KeyboardEvent)?.key === 'Escape') toggle()
89
+ }
90
+
91
+ const dragStart = useMotionValue<number>(0)
92
+ const onMouseDownScroller: React.MouseEventHandler<HTMLDivElement> = (e) => {
93
+ if (dragStart.get() === e.clientX) return
94
+ dragStart.set(e.clientX)
95
+ }
96
+ const onMouseUpScroller: React.MouseEventHandler<HTMLDivElement> = (e) => {
97
+ const currentDragLoc = e.clientX
98
+ if (Math.abs(currentDragLoc - dragStart.get()) < 8) toggle()
99
+ }
100
+
101
+ useDomEvent(windowRef, 'keyup', handleEscapeKey, { passive: true })
102
+
103
+ const headerHeight = `${theme.appShell.headerHeightSm} - ${theme.spacings.sm} * 2`
104
+ const galleryMargin = theme.spacings.lg
105
+ const extraSpacing = theme.spacings.md
106
+
107
+ const maxHeight = `calc(100vh - ${headerHeight} - ${galleryMargin} - ${extraSpacing})`
108
+ const ratio = `calc(${height} / ${width} * 100%)`
109
+
110
+ return (
111
+ <ScrollerProvider scrollSnapAlign='center'>
112
+ <Row maxWidth={false} disableGutters className={classes.row}>
113
+ <MotionBox
114
+ layout
115
+ className={classes.root}
116
+ sx={[
117
+ {
118
+ willChange: 'transform',
119
+ display: 'grid',
120
+ [theme.breakpoints.up('md')]: {
121
+ gridTemplateColumns: '1fr auto',
122
+ },
123
+ background:
124
+ theme.palette.mode === 'light'
125
+ ? theme.palette.background.image
126
+ : theme.palette.background.paper,
127
+ paddingRight: `calc((100% - ${theme.breakpoints.values.lg}px) / 2)`,
128
+ },
129
+ zoomed && {
130
+ position: 'relative',
131
+ zIndex: theme.zIndex.modal,
132
+ marginTop: `calc(${theme.appShell.headerHeightSm} * -1)`,
133
+ [theme.breakpoints.up('md')]: {
134
+ marginTop: `calc(${theme.appShell.headerHeightMd} * -1 - ${theme.spacings.lg})`,
135
+ },
136
+ paddingRight: 0,
137
+ },
138
+ ]}
139
+ >
140
+ <MotionBox
141
+ layout
142
+ className={classes.scrollerContainer}
143
+ sx={[
144
+ {
145
+ willChange: 'transform',
146
+ height: 0, // https://stackoverflow.com/questions/44770074/css-grid-row-height-safari-bug
147
+ backgroundColor: theme.palette.background.image,
148
+ position: 'relative',
149
+ minHeight: '100%',
150
+ paddingTop: `min(${ratio}, ${maxHeight})`,
151
+ [theme.breakpoints.down('md')]: {
152
+ width: '100vw',
153
+ },
154
+ },
155
+ zoomed && {
156
+ paddingTop: `${clientHeight}px`,
157
+ },
158
+ ]}
159
+ onLayoutAnimationComplete={() => {
160
+ if (!zoomed) document.body.style.overflow = ''
161
+ }}
162
+ >
163
+ <Scroller
164
+ className={classes.scroller}
165
+ hideScrollbar
166
+ onMouseDown={onMouseDownScroller}
167
+ onMouseUp={onMouseUpScroller}
168
+ sx={[
169
+ {
170
+ willChange: 'transform',
171
+ position: 'absolute',
172
+ top: 0,
173
+ width: '100%',
174
+ height: '100%',
175
+ gridAutoColumns: `100%`,
176
+ gridTemplateRows: `100%`,
177
+ cursor: 'zoom-in',
178
+ },
179
+ zoomed && {
180
+ height: clientHeight,
181
+ cursor: 'inherit',
182
+ },
183
+ ]}
184
+ >
185
+ {images.map((image, idx) => (
186
+ <MotionImageAspect
187
+ key={typeof image.src === 'string' ? image.src : idx}
188
+ layout
189
+ src={image.src}
190
+ width={image.width}
191
+ height={image.height}
192
+ loading={idx === 0 ? 'eager' : 'lazy'}
193
+ sizes={{
194
+ 0: '100vw',
195
+ [theme.breakpoints.values.md]: zoomed ? '100vw' : '60vw',
196
+ }}
197
+ alt={image.alt || `Product Image ${idx}` || undefined}
198
+ dontReportWronglySizedImages
199
+ />
200
+ ))}
201
+ </Scroller>
202
+ <MotionBox
203
+ layout
204
+ className={classes.topRight}
205
+ sx={{
206
+ display: 'grid',
207
+ gridAutoFlow: 'column',
208
+ top: theme.spacings.sm,
209
+ gap: theme.spacings.xxs,
210
+ position: 'absolute',
211
+ right: theme.spacings.sm,
212
+ }}
213
+ >
214
+ <Fab
215
+ size='small'
216
+ className={classes.toggleIcon}
217
+ onMouseUp={toggle}
218
+ aria-label='Toggle Fullscreen'
219
+ sx={{
220
+ boxShadow: theme.shadows[6],
221
+ }}
222
+ >
223
+ {!zoomed ? <SvgIcon src={iconFullscreen} /> : <SvgIcon src={iconFullscreenExit} />}
224
+ </Fab>
225
+ </MotionBox>
226
+ <Box
227
+ className={classes.centerLeft}
228
+ sx={{
229
+ display: 'grid',
230
+ gridAutoFlow: 'row',
231
+ gap: theme.spacings.xxs,
232
+ position: 'absolute',
233
+ left: theme.spacings.sm,
234
+ top: `calc(50% - 28px)`,
235
+ }}
236
+ >
237
+ <ScrollerButton
238
+ layout
239
+ direction='left'
240
+ size='small'
241
+ className={classes.sliderButtons}
242
+ >
243
+ <SvgIcon src={iconChevronLeft} />
244
+ </ScrollerButton>
245
+ </Box>
246
+ <Box
247
+ className={classes.centerRight}
248
+ sx={{
249
+ display: 'grid',
250
+ gap: theme.spacings.xxs,
251
+ position: 'absolute',
252
+ right: theme.spacings.sm,
253
+ top: `calc(50% - 28px)`,
254
+ }}
255
+ >
256
+ <ScrollerButton
257
+ layout
258
+ direction='right'
259
+ size='small'
260
+ className={classes.sliderButtons}
261
+ >
262
+ <SvgIcon src={iconChevronRight} />
263
+ </ScrollerButton>
264
+ </Box>
265
+
266
+ <Box
267
+ className={classes.bottomCenter}
268
+ sx={{
269
+ display: 'grid',
270
+ gridAutoFlow: 'column',
271
+ gap: theme.spacings.xxs,
272
+ position: 'absolute',
273
+ bottom: theme.spacings.xxs,
274
+ justifyContent: 'center',
275
+ width: '100%',
276
+ pointerEvents: 'none',
277
+ '& > *': {
278
+ pointerEvents: 'all',
279
+ },
280
+ }}
281
+ >
282
+ <ScrollerDots
283
+ layout
284
+ sx={{
285
+ background: alpha(theme.palette.background.paper, 1),
286
+ boxShadow: theme.shadows[6],
287
+ }}
288
+ />
289
+ </Box>
290
+ </MotionBox>
291
+
292
+ <Box
293
+ className={classes.sidebarWrapper}
294
+ sx={[
295
+ {
296
+ boxSizing: 'content-box',
297
+ display: 'grid',
298
+ justifyItems: 'start',
299
+ alignContent: 'center',
300
+ position: 'relative',
301
+ [theme.breakpoints.up('md')]: {
302
+ width: `calc(${responsiveVal(300, 500, theme.breakpoints.values.lg)} + ${
303
+ theme.page.horizontal
304
+ } * 2)`,
305
+ },
306
+ },
307
+ zoomed && {
308
+ [theme.breakpoints.up('md')]: {
309
+ marginLeft: `calc((${responsiveVal(300, 500, theme.breakpoints.values.lg)} + ${
310
+ theme.page.horizontal
311
+ } * 2) * -1)`,
312
+ left: `calc(${responsiveVal(300, 500, theme.breakpoints.values.lg)} + ${
313
+ theme.page.horizontal
314
+ } * 2)`,
315
+ },
316
+ },
317
+ ]}
318
+ >
319
+ <MotionBox
320
+ layout
321
+ className={classes.sidebar}
322
+ sx={{
323
+ boxSizing: 'border-box',
324
+ width: '100%',
325
+ padding: `${theme.spacings.lg} ${theme.page.horizontal}`,
326
+ [theme.breakpoints.up('md')]: {
327
+ paddingLeft: theme.spacings.lg,
328
+ },
329
+ }}
330
+ >
331
+ {sidebar}
332
+ </MotionBox>
333
+ </Box>
334
+ </MotionBox>
335
+ </Row>
336
+ </ScrollerProvider>
337
+ )
338
+ }
339
+
340
+ SidebarGallery.selectors = selectors
@@ -0,0 +1,107 @@
1
+ import {
2
+ Scroller,
3
+ ScrollerButton,
4
+ ScrollerPageCounter,
5
+ ScrollerProvider,
6
+ } from '@graphcommerce/framer-scroller'
7
+ import { Box, SxProps, Theme } from '@mui/material'
8
+ import { ReactNode } from 'react'
9
+ import { Row } from '../Row'
10
+ import { extendableComponent } from '../Styles/extendableComponent'
11
+ import { responsiveVal } from '../Styles/responsiveVal'
12
+ import { SvgIcon } from '../SvgIcon/SvgIcon'
13
+ import { iconChevronLeft, iconChevronRight } from '../icons'
14
+
15
+ const { classes, selectors } = extendableComponent('SidebarSlider', [
16
+ 'root',
17
+ 'grid',
18
+ 'sidebar',
19
+ 'scrollerContainer',
20
+ 'scroller',
21
+ 'sliderButtons',
22
+ 'centerLeft',
23
+ 'centerRight',
24
+ ] as const)
25
+
26
+ export type SidebarSliderProps = { children: ReactNode; sidebar: ReactNode; sx?: SxProps<Theme> }
27
+
28
+ export function SidebarSlider(props: SidebarSliderProps) {
29
+ const { children, sidebar, sx } = props
30
+
31
+ return (
32
+ <Row maxWidth={false} disableGutters className={classes.root} sx={sx}>
33
+ <ScrollerProvider scrollSnapAlign='start'>
34
+ <Box
35
+ className={classes.grid}
36
+ sx={{
37
+ display: 'grid',
38
+ gridTemplateColumns: 'minmax(150px, 25%) 1fr',
39
+ maxWidth: '100%',
40
+ }}
41
+ >
42
+ <Box
43
+ className={classes.sidebar}
44
+ sx={(theme) => ({
45
+ display: 'grid',
46
+ alignContent: 'space-between',
47
+ padding: `0 ${theme.spacings.lg} 0 ${theme.page.horizontal}`,
48
+ })}
49
+ >
50
+ <Box>{sidebar}</Box>
51
+ <ScrollerPageCounter />
52
+ </Box>
53
+
54
+ <Box className={classes.scrollerContainer} sx={{ position: 'relative', minWidth: 1 }}>
55
+ <Scroller
56
+ className={classes.scroller}
57
+ hideScrollbar
58
+ sx={(theme) => ({
59
+ gridColumnGap: theme.spacings.md,
60
+ gridRowGap: theme.spacings.lg,
61
+ paddingRight: theme.page.horizontal,
62
+ gridAutoColumns: responsiveVal(200, 400),
63
+ })}
64
+ >
65
+ {children}
66
+ </Scroller>
67
+ <Box
68
+ className={classes.centerLeft}
69
+ sx={(theme) => ({
70
+ display: 'grid',
71
+ gridAutoFlow: 'row',
72
+ gap: theme.spacings.xxs,
73
+ position: 'absolute',
74
+ left: theme.spacings.sm,
75
+ top: `calc(50% - 28px)`,
76
+ })}
77
+ >
78
+ <ScrollerButton
79
+ direction='left'
80
+ className={classes.sliderButtons}
81
+ sx={{ display: { xs: 'none', md: 'flex' } }}
82
+ >
83
+ <SvgIcon src={iconChevronLeft} />
84
+ </ScrollerButton>
85
+ </Box>
86
+ <Box
87
+ className={classes.centerRight}
88
+ sx={(theme) => ({
89
+ display: 'grid',
90
+ gap: theme.spacings.xxs,
91
+ position: 'absolute',
92
+ right: theme.spacings.sm,
93
+ top: `calc(50% - 28px)`,
94
+ })}
95
+ >
96
+ <ScrollerButton direction='right' className={classes.sliderButtons}>
97
+ <SvgIcon src={iconChevronRight} />
98
+ </ScrollerButton>
99
+ </Box>
100
+ </Box>
101
+ </Box>
102
+ </ScrollerProvider>
103
+ </Row>
104
+ )
105
+ }
106
+
107
+ SidebarSlider.selectors = selectors
@@ -0,0 +1,2 @@
1
+ export * from './SidebarGallery'
2
+ export * from './SidebarSlider'
@@ -1,38 +1,8 @@
1
- import { Container, Theme, Typography } from '@material-ui/core'
2
- import { makeStyles } from '@material-ui/styles'
3
- import clsx from 'clsx'
1
+ import { Box, Container, SxProps, Theme, Typography } from '@mui/material'
4
2
  import React from 'react'
3
+ import { extendableComponent } from '../Styles'
5
4
  import { responsiveVal } from '../Styles/responsiveVal'
6
5
 
7
- const useStyles = makeStyles(
8
- (theme: Theme) => ({
9
- root: {
10
- alignItems: 'center',
11
- marginTop: theme.spacings.md,
12
- marginBottom: theme.spacings.md,
13
- },
14
- innerContainer: {
15
- display: 'grid',
16
- alignItems: 'center',
17
- justifyItems: 'center',
18
- },
19
- rootMargin: {
20
- marginTop: responsiveVal(50, 250),
21
- },
22
- subject: {
23
- textAlign: 'center',
24
- marginTop: theme.spacings.sm,
25
- },
26
- button: {
27
- marginTop: theme.spacings.sm,
28
- },
29
- altButton: {
30
- marginTop: 6,
31
- },
32
- }),
33
- { name: 'FullPageMessage' },
34
- )
35
-
36
6
  export type FullPageMessageProps = {
37
7
  icon: React.ReactNode
38
8
  title: React.ReactNode
@@ -40,31 +10,65 @@ export type FullPageMessageProps = {
40
10
  button?: React.ReactNode
41
11
  altButton?: React.ReactNode
42
12
  disableMargin?: boolean
13
+ sx?: SxProps<Theme>
43
14
  }
44
15
 
45
- export default function FullPageMessage(props: FullPageMessageProps) {
46
- const { icon, title, children, button, altButton, disableMargin = false } = props
47
- const classes = useStyles()
16
+ const { classes, selectors } = extendableComponent('FullPageMessage', [
17
+ 'root',
18
+ 'innerContainer',
19
+ 'subject',
20
+ 'button',
21
+ 'altButton',
22
+ 'iconWrapper',
23
+ ] as const)
24
+
25
+ export function FullPageMessage(props: FullPageMessageProps) {
26
+ const { icon, title, children, button, altButton, disableMargin = false, sx = [] } = props
48
27
 
49
28
  return (
50
- <div className={clsx(classes.root, disableMargin || classes.rootMargin)}>
51
- <Container maxWidth='md' className={classes.innerContainer}>
52
- <div>{icon}</div>
29
+ <Box
30
+ className={classes.root}
31
+ sx={[
32
+ (theme) => ({
33
+ alignItems: 'center',
34
+ marginTop: theme.spacings.md,
35
+ marginBottom: theme.spacings.md,
36
+ }),
37
+ !disableMargin && {
38
+ marginTop: responsiveVal(50, 250),
39
+ },
40
+ ...(Array.isArray(sx) ? sx : [sx]),
41
+ ]}
42
+ >
43
+ <Container
44
+ maxWidth='md'
45
+ className={classes.innerContainer}
46
+ sx={{
47
+ display: 'grid',
48
+ alignItems: 'center',
49
+ justifyItems: 'center',
50
+ }}
51
+ >
52
+ <Box className={classes.iconWrapper}>{icon}</Box>
53
53
 
54
- <div className={classes.subject}>
54
+ <Box
55
+ className={classes.subject}
56
+ sx={(theme) => ({ textAlign: 'center', marginTop: theme.spacings.sm })}
57
+ >
55
58
  <Typography variant='h3' gutterBottom>
56
59
  {title}
57
60
  </Typography>
58
- {children && (
59
- <Typography component='div' variant='body1'>
60
- {children}
61
- </Typography>
62
- )}
63
- </div>
61
+ {children && <Box typography='body1'>{children}</Box>}
62
+ </Box>
64
63
 
65
- <div className={classes.button}>{button}</div>
66
- <div className={classes.altButton}>{altButton}</div>
64
+ <Box className={classes.button} sx={(theme) => ({ marginTop: theme.spacings.sm })}>
65
+ {button}
66
+ </Box>
67
+ <Box className={classes.altButton} sx={{ marginTop: '6px' }}>
68
+ {altButton}
69
+ </Box>
67
70
  </Container>
68
- </div>
71
+ </Box>
69
72
  )
70
73
  }
74
+ FullPageMessage.selectors = selectors
@@ -1,4 +1,4 @@
1
- export default function Highlight(props: { text: string; highlight: string }) {
1
+ export function Highlight(props: { text: string; highlight: string }) {
2
2
  const { text, highlight } = props
3
3
  const start = text.toLocaleLowerCase().indexOf(highlight.toLocaleLowerCase())
4
4