@graphcommerce/next-ui 3.18.1 → 3.20.0

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 (97) hide show
  1. package/AppShell/AppShellSticky/index.tsx +3 -19
  2. package/AppShell/DesktopNavActions.tsx +3 -4
  3. package/AppShell/DesktopNavBar.tsx +4 -4
  4. package/AppShell/FixedFab.tsx +1 -6
  5. package/AppShell/GlobalHead.tsx +36 -0
  6. package/AppShell/Logo.tsx +11 -20
  7. package/AppShell/MenuFab.tsx +19 -8
  8. package/AppShell/MenuFabSecondaryItem.tsx +3 -3
  9. package/AppShell/PlaceholderFab/index.tsx +8 -27
  10. package/AppShell/index.tsx +19 -0
  11. package/AppShell/useFabAnimation.tsx +3 -2
  12. package/AppShell/useFixedFabAnimation.tsx +5 -5
  13. package/Blog/BlogAuthor/index.tsx +10 -6
  14. package/Blog/BlogHeader/index.tsx +7 -3
  15. package/Blog/BlogList/index.tsx +1 -1
  16. package/Blog/BlogListItem/index.tsx +2 -1
  17. package/Blog/BlogTitle/index.tsx +5 -5
  18. package/Button/index.tsx +27 -22
  19. package/ButtonLink/index.tsx +1 -1
  20. package/CHANGELOG.md +73 -0
  21. package/ChipMenu/index.tsx +2 -2
  22. package/FlagAvatar/index.tsx +3 -3
  23. package/{AppShell/Footer/index.tsx → Footer/Footer.tsx} +4 -4
  24. package/{AppShell/Footer → Footer}/SocialIcon.tsx +3 -3
  25. package/Footer/index.ts +2 -0
  26. package/Form/InputCheckmark.tsx +3 -3
  27. package/Form/index.tsx +8 -3
  28. package/FramerScroller/components/SidebarGallery.tsx +25 -21
  29. package/FramerScroller/components/SidebarSlider.tsx +2 -6
  30. package/FullPageMessage/index.tsx +1 -1
  31. package/IconHeader/index.tsx +2 -15
  32. package/Layout/components/LayoutHeader.tsx +151 -0
  33. package/Layout/components/LayoutHeaderBack.tsx +50 -0
  34. package/Layout/components/LayoutHeaderClose.tsx +27 -0
  35. package/Layout/components/LayoutHeaderContent.tsx +173 -0
  36. package/Layout/components/LayoutHeadertypes.ts +10 -0
  37. package/Layout/components/LayoutProvider.tsx +17 -0
  38. package/{Title/index.tsx → Layout/components/LayoutTitle.tsx} +24 -15
  39. package/Layout/context/layoutContext.tsx +7 -0
  40. package/Layout/hooks/useScrollY.tsx +6 -0
  41. package/Layout/index.ts +5 -0
  42. package/Layout/types.ts +5 -0
  43. package/LayoutDefault/components/LayoutDefault.tsx +90 -0
  44. package/LayoutDefault/index.ts +1 -0
  45. package/LayoutOverlay/components/LayoutOverlay.tsx +25 -0
  46. package/LayoutOverlay/components/LayoutOverlayBase.tsx +354 -0
  47. package/LayoutOverlay/components/LayoutOverlayHeader.tsx +5 -0
  48. package/LayoutOverlay/hooks/useOverlayPosition.ts +70 -0
  49. package/LayoutOverlay/index.ts +2 -0
  50. package/Page/App.tsx +2 -0
  51. package/PageMeta/index.tsx +3 -0
  52. package/Pagination/index.tsx +0 -1
  53. package/Row/ButtonLinkList/index.tsx +1 -1
  54. package/Row/ColumnOneBoxed/index.tsx +1 -1
  55. package/Row/ColumnTwoWithTop/index.tsx +3 -3
  56. package/Row/ContentLinks/index.tsx +3 -3
  57. package/Row/HeroBanner/index.tsx +28 -21
  58. package/Row/IconBlocks/index.tsx +1 -1
  59. package/Row/ImageText/index.tsx +12 -5
  60. package/Row/ImageTextBoxed/index.tsx +3 -1
  61. package/Row/ParagraphWithSidebarSlide/index.tsx +2 -0
  62. package/Row/SpecialBanner/index.tsx +11 -7
  63. package/Row/index.tsx +1 -1
  64. package/Snackbar/MessageSnackbarImpl.tsx +2 -1
  65. package/StarRatingField/index.tsx +3 -4
  66. package/Stepper/Stepper.tsx +1 -1
  67. package/Styles/breakpointVal.tsx +22 -0
  68. package/Styles/classesPicker.ts +41 -0
  69. package/Styles/responsiveVal.tsx +1 -1
  70. package/SvgImage/SvgImageSimple.tsx +14 -11
  71. package/SvgImage/index.tsx +9 -11
  72. package/TextInputNumber/index.tsx +3 -4
  73. package/Theme/types.ts +14 -12
  74. package/ToggleButton/index.tsx +6 -13
  75. package/UspList/UspListItem.tsx +4 -2
  76. package/icons/index.tsx +2 -0
  77. package/index.ts +9 -42
  78. package/package.json +8 -9
  79. package/AppShell/AppShellHeader/appShellHeaderContext.tsx +0 -11
  80. package/AppShell/AppShellHeader/index.tsx +0 -438
  81. package/AppShell/AppShellHeader/useAppShellHeaderContext.tsx +0 -6
  82. package/AppShell/AppShellProvider/index.tsx +0 -18
  83. package/AppShell/AppShellTitle/index.tsx +0 -45
  84. package/AppShell/ForwardButton.tsx +0 -53
  85. package/AppShell/FullPageShellBase.tsx +0 -82
  86. package/AppShell/MinimalPageShellBase.tsx +0 -22
  87. package/AppShell/PageShellHeader/index.tsx +0 -14
  88. package/AppShell/SheetShellBase/index.tsx +0 -114
  89. package/AppShell/SheetShellBase/useSheetStyles.ts +0 -18
  90. package/AppShell/SheetShellDragIndicator/index.tsx +0 -55
  91. package/AppShell/SheetShellHeader/index.tsx +0 -28
  92. package/AppShell/ShellBase.tsx +0 -45
  93. package/Debug/DebugSpacer.tsx +0 -51
  94. package/FramerNextPagesSlider/Slide.tsx +0 -71
  95. package/FramerNextPagesSlider/Slider.tsx +0 -39
  96. package/FramerNextPagesSlider/index.ts +0 -1
  97. package/FramerNextPagesSlider/types.ts +0 -3
@@ -0,0 +1,173 @@
1
+ import { useMotionValueValue } from '@graphcommerce/framer-utils'
2
+ import { Divider, makeStyles, Theme } from '@material-ui/core'
3
+ import React, { useRef } from 'react'
4
+ import { UseStyles } from '../../Styles'
5
+ import { classesPicker } from '../../Styles/classesPicker'
6
+ import { useScrollY } from '../hooks/useScrollY'
7
+ import { FloatingProps } from './LayoutHeadertypes'
8
+
9
+ type Classes = 'bg' | 'content' | 'left' | 'center' | 'right' | 'divider'
10
+
11
+ const time = '150ms'
12
+
13
+ const useStyles = makeStyles(
14
+ (theme: Theme) => ({
15
+ bg: {
16
+ position: 'absolute',
17
+ left: 0,
18
+ width: '100%',
19
+ backgroundColor: theme.palette.background.default,
20
+ opacity: 0,
21
+ transition: `opacity ${time}`,
22
+
23
+ height: theme.appShell.headerHeightSm,
24
+ [theme.breakpoints.up('md')]: {
25
+ height: theme.appShell.appBarHeightMd,
26
+ },
27
+ },
28
+ bgFloatingSm: {
29
+ [theme.breakpoints.down('sm')]: {
30
+ display: 'none',
31
+ },
32
+ },
33
+ bgFloatingMd: {
34
+ [theme.breakpoints.up('md')]: {
35
+ display: 'none',
36
+ },
37
+ },
38
+ bgScrolled: {
39
+ opacity: 1,
40
+ },
41
+ content: {
42
+ position: 'absolute',
43
+ left: 0,
44
+ width: '100%',
45
+ display: 'grid',
46
+ gridTemplateAreas: `"left center right"`,
47
+ gridTemplateColumns: '1fr auto 1fr',
48
+ alignItems: 'center',
49
+
50
+ height: theme.appShell.headerHeightSm,
51
+ [theme.breakpoints.up('md')]: {
52
+ padding: `0 ${theme.page.horizontal}`,
53
+ height: theme.appShell.appBarHeightMd,
54
+ },
55
+ },
56
+ contentFloatingMd: {
57
+ [theme.breakpoints.up('md')]: {
58
+ padding: `0 ${theme.page.horizontal}`,
59
+ background: 'none',
60
+ pointerEvents: 'none',
61
+ },
62
+ },
63
+ contentFloatingSm: {
64
+ [theme.breakpoints.down('sm')]: {
65
+ padding: `0 ${theme.page.horizontal}`,
66
+ background: 'none',
67
+ pointerEvents: 'none',
68
+ },
69
+ },
70
+ left: {
71
+ '& > *': { pointerEvents: 'all' },
72
+ display: 'grid',
73
+ gridAutoFlow: 'column',
74
+ gap: theme.spacings.sm,
75
+ gridArea: 'left',
76
+ justifyContent: 'start',
77
+ },
78
+ center: {
79
+ display: 'grid',
80
+ gridAutoFlow: 'column',
81
+ gap: theme.spacings.sm,
82
+ gridArea: 'center',
83
+ justifyContent: 'start',
84
+ overflow: 'hidden',
85
+ transition: `opacity ${time}`,
86
+ opacity: 0,
87
+ },
88
+ centerScrolled: {
89
+ opacity: 1,
90
+ '& > *': { pointerEvents: 'all' },
91
+ },
92
+ centerFloatingSm: {
93
+ [theme.breakpoints.down('sm')]: {
94
+ display: 'none',
95
+ },
96
+ },
97
+ centerFloatingMd: {
98
+ [theme.breakpoints.up('md')]: {
99
+ display: 'none',
100
+ },
101
+ },
102
+ right: {
103
+ '& > *': { pointerEvents: 'all' },
104
+ display: 'grid',
105
+ gridAutoFlow: 'column',
106
+ gap: theme.spacings.sm,
107
+ gridArea: 'right',
108
+ justifyContent: 'end',
109
+ },
110
+ divider: {
111
+ position: 'absolute',
112
+ bottom: 0,
113
+ left: 0,
114
+ right: 0,
115
+ transition: `opacity ${time}`,
116
+ opacity: 0,
117
+ },
118
+ dividerCustomDivider: {
119
+ opacity: 1,
120
+ },
121
+ dividerScrolled: {
122
+ opacity: 1,
123
+ },
124
+ dividerFloatingSm: {
125
+ [theme.breakpoints.down('sm')]: {
126
+ display: 'none',
127
+ },
128
+ },
129
+ dividerFloatingMd: {
130
+ [theme.breakpoints.up('md')]: {
131
+ display: 'none',
132
+ },
133
+ },
134
+ }),
135
+ { name: 'LayoutHeaderContent' },
136
+ )
137
+
138
+ export type ContentProps = FloatingProps &
139
+ UseStyles<typeof useStyles> & {
140
+ children?: React.ReactNode
141
+ left?: React.ReactNode
142
+ right?: React.ReactNode
143
+ divider?: React.ReactNode
144
+ }
145
+
146
+ export default function LayoutHeaderContent(props: ContentProps) {
147
+ const ref = useRef<HTMLDivElement>(null)
148
+ const scroll = useScrollY()
149
+
150
+ const { left, children, right, divider, floatingMd = false, floatingSm = false } = props
151
+ const classes = useStyles(props)
152
+
153
+ const scrolled = useMotionValueValue(scroll, (y) => y > 50)
154
+
155
+ const className = classesPicker<Classes>(classes, {
156
+ floatingSm,
157
+ floatingMd,
158
+ scrolled,
159
+ customDivider: !!divider,
160
+ })
161
+
162
+ return (
163
+ <>
164
+ <div {...className('bg')} />
165
+ <div {...className('content')} ref={ref}>
166
+ <div {...className('left')}>{left}</div>
167
+ <div {...className('center')}>{children}</div>
168
+ <div {...className('right')}>{right}</div>
169
+ <div {...className('divider')}>{divider ?? <Divider />}</div>
170
+ </div>
171
+ </>
172
+ )
173
+ }
@@ -0,0 +1,10 @@
1
+ type Matrix<T extends string, M extends string> = `${T}${Capitalize<M>}`
2
+
3
+ // Possible configurations for the AppShellHeader
4
+ export type Variant = 'floating'
5
+ export type Size = 'sm' | 'md'
6
+
7
+ // Matrix
8
+ export type VariantSize = Matrix<Variant, Size>
9
+
10
+ export type FloatingProps = Partial<Record<Matrix<Variant, Size>, boolean>>
@@ -0,0 +1,17 @@
1
+ import { MotionValue } from 'framer-motion'
2
+ import { useMemo } from 'react'
3
+ import layoutContext from '../context/layoutContext'
4
+
5
+ export type LayoutProviderProps = {
6
+ children: React.ReactNode
7
+ scroll: MotionValue<number>
8
+ }
9
+
10
+ export default function LayoutProvider(props: LayoutProviderProps) {
11
+ const { children, scroll } = props
12
+ return (
13
+ <layoutContext.Provider value={useMemo(() => ({ scroll }), [scroll])}>
14
+ {children}
15
+ </layoutContext.Provider>
16
+ )
17
+ }
@@ -1,10 +1,10 @@
1
1
  import { makeStyles, Theme, Typography, TypographyProps } from '@material-ui/core'
2
- import clsx from 'clsx'
3
2
  import React from 'react'
4
- import { responsiveVal } from '..'
5
- import { UseStyles } from '../Styles'
6
- import SvgImage, { SvgImageProps } from '../SvgImage'
7
- import SvgImageSimple from '../SvgImage/SvgImageSimple'
3
+ import { UseStyles } from '../../Styles'
4
+ import { classesPicker } from '../../Styles/classesPicker'
5
+ import { responsiveVal } from '../../Styles/responsiveVal'
6
+ import { SvgImageProps } from '../../SvgImage'
7
+ import SvgImageSimple from '../../SvgImage/SvgImageSimple'
8
8
 
9
9
  const useStyles = makeStyles(
10
10
  (theme: Theme) => ({
@@ -18,8 +18,7 @@ const useStyles = makeStyles(
18
18
  flexFlow: 'column',
19
19
  },
20
20
  },
21
- typography: {},
22
- small: {
21
+ containerSizeSmall: {
23
22
  flexFlow: 'unset',
24
23
  '& svg': {
25
24
  width: responsiveVal(24, 28),
@@ -27,10 +26,15 @@ const useStyles = makeStyles(
27
26
  strokeWidth: 1.4,
28
27
  },
29
28
  },
29
+ containerGutterTop: {
30
+ marginTop: theme.spacings.xl,
31
+ },
32
+ containerGutterBottom: {
33
+ marginBottom: theme.spacings.lg,
34
+ },
35
+ typography: {},
30
36
  }),
31
- {
32
- name: 'Title',
33
- },
37
+ { name: 'Title' },
34
38
  )
35
39
 
36
40
  export type TitleProps = {
@@ -38,17 +42,24 @@ export type TitleProps = {
38
42
  icon?: SvgImageProps['src']
39
43
  size?: 'small' | 'medium'
40
44
  variant?: TypographyProps['variant']
45
+ gutterTop?: boolean
46
+ gutterBottom?: boolean
41
47
  component?: React.ElementType
42
48
  } & UseStyles<typeof useStyles>
43
49
 
44
- const Title = React.forwardRef<HTMLDivElement, TitleProps>((props, ref) => {
50
+ export const LayoutTitle = React.forwardRef<HTMLDivElement, TitleProps>((props, ref) => {
45
51
  const { children, icon, size = 'medium', component, variant } = props
46
52
  const classes = useStyles(props)
47
53
  const small = size === 'small'
48
54
 
55
+ const gutterTop = !!(props.gutterTop ?? size !== 'small')
56
+ const gutterBottom = !!(props.gutterBottom ?? size !== 'small')
57
+
58
+ const className = classesPicker(classes, { size, gutterBottom, gutterTop })
59
+
49
60
  return (
50
- <div className={clsx(classes.container, small && classes.small)}>
51
- {icon && <SvgImageSimple src={icon} size='xl' />}
61
+ <div {...className('container')}>
62
+ {icon && <SvgImageSimple src={icon} size={small ? 'large' : 'xl'} />}
52
63
  <Typography
53
64
  ref={ref}
54
65
  variant={variant || (small ? 'h6' : 'h3')}
@@ -60,5 +71,3 @@ const Title = React.forwardRef<HTMLDivElement, TitleProps>((props, ref) => {
60
71
  </div>
61
72
  )
62
73
  })
63
-
64
- export default Title
@@ -0,0 +1,7 @@
1
+ import React from 'react'
2
+ import { LayoutContext } from '../types'
3
+
4
+ const layoutContext = React.createContext(undefined as unknown as LayoutContext)
5
+ layoutContext.displayName = 'layoutContext'
6
+
7
+ export default layoutContext
@@ -0,0 +1,6 @@
1
+ import { useContext } from 'react'
2
+ import layoutContext from '../context/layoutContext'
3
+
4
+ export function useScrollY() {
5
+ return useContext(layoutContext).scroll
6
+ }
@@ -0,0 +1,5 @@
1
+ export * from './types'
2
+ export * from './components/LayoutHeader'
3
+ export * from './components/LayoutProvider'
4
+ export * from './components/LayoutTitle'
5
+ export * from './hooks/useScrollY'
@@ -0,0 +1,5 @@
1
+ import { MotionValue } from 'framer-motion'
2
+
3
+ export type LayoutContext = {
4
+ scroll: MotionValue<number>
5
+ }
@@ -0,0 +1,90 @@
1
+ import { usePageRouter, useScrollOffset } from '@graphcommerce/framer-next-pages'
2
+ import { makeStyles, Theme } from '@material-ui/core'
3
+ import clsx from 'clsx'
4
+ import { useTransform, useViewportScroll } from 'framer-motion'
5
+ import React from 'react'
6
+ import LayoutProvider from '../../Layout/components/LayoutProvider'
7
+ import { UseStyles } from '../../Styles'
8
+
9
+ const useStyles = makeStyles(
10
+ (theme: Theme) => ({
11
+ root: {
12
+ minHeight: '100vh',
13
+ '@supports (-webkit-touch-callout: none)': {
14
+ minHeight: '-webkit-fill-available',
15
+ },
16
+ display: 'grid',
17
+ gridTemplateRows: `auto 1fr auto`,
18
+ gridTemplateColumns: '100%',
19
+ background: theme.palette.background.default,
20
+ },
21
+ hideFabsOnVirtualKeyboardOpen: {
22
+ [theme.breakpoints.down('sm')]: {
23
+ '@media (max-height: 530px)': {
24
+ display: 'none',
25
+ },
26
+ },
27
+ },
28
+ header: {
29
+ zIndex: theme.zIndex.appBar - 1,
30
+ display: 'flex',
31
+ alignItems: 'center',
32
+ justifyContent: 'center',
33
+ height: theme.appShell.headerHeightSm,
34
+ pointerEvents: 'none',
35
+ '& > *': {
36
+ pointerEvents: 'all',
37
+ },
38
+ [theme.breakpoints.up('md')]: {
39
+ height: theme.appShell.headerHeightMd,
40
+ padding: `0 ${theme.page.horizontal} 0`,
41
+ top: 0,
42
+ display: 'flex',
43
+ justifyContent: 'left',
44
+ width: '100%',
45
+ },
46
+ },
47
+ headerSticky: {
48
+ [theme.breakpoints.down('sm')]: {
49
+ position: 'sticky',
50
+ top: 0,
51
+ },
52
+ },
53
+ }),
54
+ { name: 'LayoutDefault' },
55
+ )
56
+
57
+ export type LayoutDefaultProps = {
58
+ header: React.ReactNode
59
+ footer: React.ReactNode
60
+ menuFab?: React.ReactNode
61
+ cartFab?: React.ReactNode
62
+ children?: React.ReactNode
63
+ noSticky?: boolean
64
+ } & UseStyles<typeof useStyles>
65
+
66
+ export function LayoutDefault(props: LayoutDefaultProps) {
67
+ const { children, header, footer, menuFab, cartFab, noSticky } = props
68
+ const classes = useStyles(props)
69
+
70
+ const offset = useScrollOffset().y
71
+ const scrollWithOffset = useTransform(useViewportScroll().scrollY, (y) => y + offset)
72
+
73
+ return (
74
+ <div className={classes.root}>
75
+ <LayoutProvider scroll={scrollWithOffset}>
76
+ <header className={clsx(classes.header, !noSticky && classes.headerSticky)}>
77
+ {header}
78
+ </header>
79
+ <div>
80
+ <div className={classes.hideFabsOnVirtualKeyboardOpen}>
81
+ {menuFab}
82
+ {cartFab}
83
+ </div>
84
+ {children}
85
+ </div>
86
+ <div>{footer}</div>
87
+ </LayoutProvider>
88
+ </div>
89
+ )
90
+ }
@@ -0,0 +1 @@
1
+ export * from './components/LayoutDefault'
@@ -0,0 +1,25 @@
1
+ import { ScrollerProvider, ScrollSnapType } from '@graphcommerce/framer-scroller'
2
+ import React from 'react'
3
+ import { SetOptional } from 'type-fest'
4
+ import { LayoutOverlayBase, LayoutOverlayBaseProps } from './LayoutOverlayBase'
5
+
6
+ export type { LayoutOverlayVariant } from './LayoutOverlayBase'
7
+
8
+ export type LayoutOverlayProps = SetOptional<LayoutOverlayBaseProps, 'variantSm' | 'variantMd'>
9
+
10
+ export function LayoutOverlay(props: LayoutOverlayProps) {
11
+ const { children, variantSm = 'bottom', variantMd = 'right', classes } = props
12
+
13
+ const scrollSnapTypeSm: ScrollSnapType =
14
+ variantSm === 'left' || variantSm === 'right' ? 'both mandatory' : 'block proximity'
15
+ const scrollSnapTypeMd: ScrollSnapType =
16
+ variantMd === 'left' || variantMd === 'right' ? 'both mandatory' : 'block proximity'
17
+
18
+ return (
19
+ <ScrollerProvider scrollSnapTypeSm={scrollSnapTypeSm} scrollSnapTypeMd={scrollSnapTypeMd}>
20
+ <LayoutOverlayBase variantMd={variantMd} variantSm={variantSm} classes={classes}>
21
+ {children}
22
+ </LayoutOverlayBase>
23
+ </ScrollerProvider>
24
+ )
25
+ }