@graphcommerce/next-ui 5.2.0-canary.0 → 5.2.0-canary.10

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 (45) hide show
  1. package/ActionCard/ActionCard.tsx +2 -2
  2. package/ActionCard/ActionCardList.tsx +10 -13
  3. package/ActionCard/ActionCardListForm.tsx +31 -13
  4. package/Blog/BlogListItem/BlogListItem.tsx +34 -39
  5. package/Blog/BlogTags/BlogTag.tsx +7 -13
  6. package/Button/LinkOrButton.tsx +2 -2
  7. package/CHANGELOG.md +46 -0
  8. package/Layout/components/LayoutHeader.tsx +16 -1
  9. package/Layout/components/LayoutHeaderBack.tsx +12 -14
  10. package/Layout/components/LayoutHeaderContent.tsx +30 -13
  11. package/Layout/components/LayoutProvider.tsx +3 -4
  12. package/Layout/context/layoutContext.tsx +1 -1
  13. package/Layout/hooks/useScrollY.tsx +6 -1
  14. package/LayoutDefault/components/LayoutDefault.tsx +4 -3
  15. package/LayoutOverlay/components/LayoutOverlay.tsx +3 -11
  16. package/LayoutParts/DesktopNavBarItem.tsx +28 -30
  17. package/LayoutParts/Logo.tsx +6 -8
  18. package/LayoutParts/MenuFabItem.tsx +11 -12
  19. package/LayoutParts/MenuFabSecondaryItem.tsx +13 -15
  20. package/Navigation/components/NavigationItem.tsx +30 -27
  21. package/Navigation/components/NavigationOverlay.tsx +3 -3
  22. package/Overlay/components/Overlay.tsx +29 -50
  23. package/Overlay/components/OverlayBase.tsx +23 -18
  24. package/Overlay/components/OverlayContainer.tsx +32 -0
  25. package/Overlay/components/OverlaySsr.tsx +43 -0
  26. package/Overlay/components/OverlayStickyBottom.tsx +23 -0
  27. package/Overlay/utils/variantsToScrollSnapType.ts +16 -0
  28. package/OverlayOrPopperChip/OverlayOrPopperChip.tsx +115 -0
  29. package/OverlayOrPopperChip/OverlayOrPopperPanel.tsx +21 -0
  30. package/OverlayOrPopperChip/OverlayPanel.tsx +32 -0
  31. package/OverlayOrPopperChip/OverlayPanelActions.tsx +76 -0
  32. package/OverlayOrPopperChip/PopperPanel.tsx +52 -0
  33. package/OverlayOrPopperChip/PopperPanelActions.tsx +67 -0
  34. package/OverlayOrPopperChip/index.ts +3 -0
  35. package/OverlayOrPopperChip/types.ts +22 -0
  36. package/OverlayOrPopperChip/useHandleClickNotDrag.ts +36 -0
  37. package/PageMeta/PageMeta.tsx +5 -5
  38. package/Row/ButtonLinkList/ButtonLinkListItem.tsx +17 -18
  39. package/Theme/MuiSlider.ts +12 -0
  40. package/Theme/NextLink.tsx +41 -0
  41. package/Theme/index.ts +1 -0
  42. package/hooks/useUrlQuery.ts +2 -2
  43. package/icons/index.ts +6 -4
  44. package/index.ts +1 -0
  45. package/package.json +9 -9
@@ -29,9 +29,9 @@ export type ActionCardProps = {
29
29
  price?: React.ReactNode
30
30
  after?: React.ReactNode
31
31
  secondaryAction?: React.ReactNode
32
- onClick?: (event: React.MouseEvent<HTMLElement>, value: string | number) => void
32
+ onClick?: (event: React.MouseEvent<HTMLElement>, value: string | number | null) => void
33
33
  selected?: boolean
34
- value: string | number
34
+ value: string | number | null
35
35
  reset?: React.ReactNode
36
36
  disabled?: boolean
37
37
  error?: boolean
@@ -8,13 +8,13 @@ import { ActionCardLayout } from './ActionCardLayout'
8
8
  type MultiSelect = {
9
9
  multiple: true
10
10
  collapse?: false
11
- value: (string | number)[]
11
+ value: (string | number | null)[]
12
12
 
13
13
  onChange?: (event: React.MouseEvent<HTMLElement>, value: MultiSelect['value']) => void
14
14
  }
15
15
  type Select = {
16
- multiple?: false
17
- value: string | number
16
+ multiple?: boolean
17
+ value: string | number | null
18
18
  collapse?: boolean
19
19
 
20
20
  /** Value is null when deselected when not required */
@@ -47,11 +47,10 @@ type HoistedActionCardProps = Pick<ActionCardProps, 'color' | 'variant' | 'size'
47
47
 
48
48
  const parts = ['root'] as const
49
49
  const name = 'ActionCardList'
50
- const { withState, selectors } = extendableComponent<
51
- HoistedActionCardProps,
52
- typeof name,
53
- typeof parts
54
- >(name, parts)
50
+ const { withState } = extendableComponent<HoistedActionCardProps, typeof name, typeof parts>(
51
+ name,
52
+ parts,
53
+ )
55
54
 
56
55
  export const ActionCardList = React.forwardRef<HTMLDivElement, ActionCardListProps>(
57
56
  (props, ref) => {
@@ -73,8 +72,7 @@ export const ActionCardList = React.forwardRef<HTMLDivElement, ActionCardListPro
73
72
  const { onChange, value } = props
74
73
  const index = Boolean(value) && value?.indexOf(v)
75
74
  let newValue: typeof value
76
-
77
- if (value.length && index && index >= 0) {
75
+ if (value?.length && index !== false && index >= 0) {
78
76
  newValue = value.slice()
79
77
  newValue.splice(index, 1)
80
78
  } else {
@@ -84,7 +82,6 @@ export const ActionCardList = React.forwardRef<HTMLDivElement, ActionCardListPro
84
82
  }
85
83
  : (event, v) => {
86
84
  const { onChange, value } = props
87
-
88
85
  if (value !== v) {
89
86
  if (required) onChange?.(event, v)
90
87
  else onChange?.(event, value === v ? null : v)
@@ -100,7 +97,7 @@ export const ActionCardList = React.forwardRef<HTMLDivElement, ActionCardListPro
100
97
  const hasValue = (el as ActionCardLike).props.value
101
98
 
102
99
  if (process.env.NODE_ENV !== 'production') {
103
- if (!hasValue) console.error(el, `must be an instance of ActionCard`)
100
+ if (hasValue === undefined) console.error(el, `must be an instance of ActionCard`)
104
101
  }
105
102
  return (el as ActionCardLike).props.value !== undefined
106
103
  }
@@ -132,7 +129,7 @@ export const ActionCardList = React.forwardRef<HTMLDivElement, ActionCardListPro
132
129
  const classes = withState({ size, color, variant, layout })
133
130
 
134
131
  return (
135
- <div>
132
+ <div ref={ref}>
136
133
  <ActionCardLayout sx={sx} className={classes.root} layout={layout}>
137
134
  {childReactNodes.map((child) => {
138
135
  if (collapse && Boolean(value) && !isValueSelected(child.props.value, value))
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable import/no-extraneous-dependencies */
2
- import { Controller, ControllerProps } from '@graphcommerce/react-hook-form'
2
+ import { Controller, ControllerProps, FieldValues } from '@graphcommerce/react-hook-form'
3
3
  import React, { MouseEventHandler } from 'react'
4
4
  import { ActionCardProps } from './ActionCard'
5
5
  import { ActionCardList, ActionCardListProps } from './ActionCardList'
@@ -10,22 +10,39 @@ export type ActionCardItemRenderProps<T> = ActionCardProps & {
10
10
  onReset: MouseEventHandler<HTMLAnchorElement> & MouseEventHandler<HTMLSpanElement>
11
11
  } & T
12
12
 
13
- export type ActionCardListFormProps<T extends ActionCardItemBase> = Omit<
13
+ export type ActionCardListFormProps<A, F extends FieldValues = FieldValues> = Omit<
14
14
  ActionCardListProps,
15
- 'value' | 'error' | 'onChange' | 'children' | 'multiple'
15
+ 'value' | 'error' | 'onChange' | 'children'
16
16
  > &
17
- Omit<ControllerProps<any>, 'render' | 'shouldUnregister'> & {
18
- items: T[]
19
- render: React.FC<ActionCardItemRenderProps<T>>
17
+ Omit<ControllerProps<F>, 'render'> & {
18
+ items: A[]
19
+ render: React.FC<ActionCardItemRenderProps<A>>
20
20
  }
21
21
 
22
- export function ActionCardListForm<T extends ActionCardItemBase>(
23
- props: ActionCardListFormProps<T>,
24
- ) {
25
- const { required, rules, items, render, control, name, errorMessage, defaultValue, ...other } =
26
- props
22
+ export function ActionCardListForm<
23
+ T extends ActionCardItemBase,
24
+ F extends FieldValues = FieldValues,
25
+ >(props: ActionCardListFormProps<T, F>) {
26
+ const {
27
+ required,
28
+ rules,
29
+ items,
30
+ render,
31
+ control,
32
+ name,
33
+ errorMessage,
34
+ defaultValue,
35
+ multiple,
36
+ ...other
37
+ } = props
27
38
  const RenderItem = render as React.FC<ActionCardItemRenderProps<ActionCardItemBase>>
28
39
 
40
+ function onSelect(itemValue: unknown, selectValues: unknown) {
41
+ return multiple
42
+ ? Array.isArray(selectValues) && selectValues.some((selectValue) => selectValue === itemValue)
43
+ : selectValues === itemValue
44
+ }
45
+
29
46
  return (
30
47
  <Controller
31
48
  {...props}
@@ -36,6 +53,7 @@ export function ActionCardListForm<T extends ActionCardItemBase>(
36
53
  render={({ field: { onChange, value, ref }, fieldState, formState }) => (
37
54
  <ActionCardList
38
55
  {...other}
56
+ multiple={multiple}
39
57
  required={required}
40
58
  value={value}
41
59
  ref={ref}
@@ -46,9 +64,9 @@ export function ActionCardListForm<T extends ActionCardItemBase>(
46
64
  {items.map((item) => (
47
65
  <RenderItem
48
66
  {...item}
49
- key={item.value}
67
+ key={item.value ?? 'tralala'}
50
68
  value={item.value}
51
- selected={value === item.value}
69
+ selected={onSelect(item.value, value)}
52
70
  onReset={(e) => {
53
71
  e.preventDefault()
54
72
  onChange(null)
@@ -1,5 +1,4 @@
1
1
  import { Box, Link, SxProps, Theme, Typography } from '@mui/material'
2
- import PageLink from 'next/link'
3
2
  import React from 'react'
4
3
  import { extendableComponent } from '../../Styles'
5
4
  import { breakpointVal } from '../../Styles/breakpointVal'
@@ -38,37 +37,35 @@ export function BlogListItem(props: BlogListItemProps) {
38
37
  ...(Array.isArray(sx) ? sx : [sx]),
39
38
  ]}
40
39
  >
41
- <PageLink href={`/${url}`} passHref>
42
- <Link color='inherit' underline='hover'>
43
- <Box
44
- className={classes.asset}
45
- sx={(theme) => ({
46
- display: 'grid',
47
- alignContent: 'center',
48
- overflow: 'hidden',
49
- height: '100%',
50
- width: '100%',
51
- ...breakpointVal(
52
- 'borderRadius',
53
- theme.shape.borderRadius * 2,
54
- theme.shape.borderRadius * 3,
55
- theme.breakpoints.values,
56
- ),
57
- '& img': {
58
- height: '100% !important',
59
- objectFit: 'cover',
60
- },
61
- '& p': {
62
- alignSelf: 'center',
63
- justifySelf: 'center',
64
- },
65
- background: theme.palette.background.paper,
66
- })}
67
- >
68
- {asset}
69
- </Box>
70
- </Link>
71
- </PageLink>
40
+ <Link href={`/${url}`} color='inherit' underline='hover'>
41
+ <Box
42
+ className={classes.asset}
43
+ sx={(theme) => ({
44
+ display: 'grid',
45
+ alignContent: 'center',
46
+ overflow: 'hidden',
47
+ height: '100%',
48
+ width: '100%',
49
+ ...breakpointVal(
50
+ 'borderRadius',
51
+ theme.shape.borderRadius * 2,
52
+ theme.shape.borderRadius * 3,
53
+ theme.breakpoints.values,
54
+ ),
55
+ '& img': {
56
+ height: '100% !important',
57
+ objectFit: 'cover',
58
+ },
59
+ '& p': {
60
+ alignSelf: 'center',
61
+ justifySelf: 'center',
62
+ },
63
+ background: theme.palette.background.paper,
64
+ })}
65
+ >
66
+ {asset}
67
+ </Box>
68
+ </Link>
72
69
 
73
70
  <Box
74
71
  component='time'
@@ -83,13 +80,11 @@ export function BlogListItem(props: BlogListItemProps) {
83
80
  {formatter.format(new Date(date))}
84
81
  </Box>
85
82
 
86
- <PageLink href={`/${url}`} passHref>
87
- <Link href={`/${url}`} className={classes.title} color='inherit' underline='hover'>
88
- <Typography component='h2' variant='h4'>
89
- {title}
90
- </Typography>
91
- </Link>
92
- </PageLink>
83
+ <Link href={`/${url}`} className={classes.title} color='inherit' underline='hover'>
84
+ <Typography component='h2' variant='h4'>
85
+ {title}
86
+ </Typography>
87
+ </Link>
93
88
  </Box>
94
89
  )
95
90
  }
@@ -1,5 +1,5 @@
1
1
  import { Chip, SxProps, Theme } from '@mui/material'
2
- import PageLink from 'next/link'
2
+ import { NextLink } from '../../Theme'
3
3
 
4
4
  type BlogTagsProps = {
5
5
  url: string
@@ -10,17 +10,11 @@ type BlogTagsProps = {
10
10
  export function BlogTag(props: BlogTagsProps) {
11
11
  const { url, title, sx = [] } = props
12
12
  return (
13
- <PageLink href={`/${url}`} passHref>
14
- <Chip
15
- label={title}
16
- sx={[
17
- {
18
- marginRight: 3,
19
- borderRadius: 2,
20
- },
21
- ...(Array.isArray(sx) ? sx : [sx]),
22
- ]}
23
- />
24
- </PageLink>
13
+ <Chip
14
+ href={`/${url}`}
15
+ component={NextLink}
16
+ label={title}
17
+ sx={[{ marginRight: 3, borderRadius: 2 }, ...(Array.isArray(sx) ? sx : [sx])]}
18
+ />
25
19
  )
26
20
  }
@@ -1,4 +1,4 @@
1
- import { Link, LinkProps, useForkRef } from '@mui/material'
1
+ import { Breakpoint, Link, LinkProps, useForkRef } from '@mui/material'
2
2
  import React, { useRef } from 'react'
3
3
  import type { ConditionalExcept } from 'type-fest'
4
4
  import { Button, ButtonProps } from './Button'
@@ -13,7 +13,7 @@ type SharedProperties<A, B> = OmitNever<
13
13
  export type LinkOrButtonProps = {
14
14
  button?: ButtonProps
15
15
  link?: LinkProps
16
- breakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
16
+ breakpoint?: Breakpoint
17
17
  disabled?: boolean
18
18
  } & SharedProperties<
19
19
  Omit<ButtonProps, 'sx'>,
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # Change Log
2
2
 
3
+ ## 5.2.0-canary.10
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1793](https://github.com/graphcommerce-org/graphcommerce/pull/1793) [`5562fa69b`](https://github.com/graphcommerce-org/graphcommerce/commit/5562fa69b1bc260f68555dcfaf30153eda489bed) - Add newsletter subscribe form ([@ErwinOtten](https://github.com/ErwinOtten))
8
+
9
+ ## 5.2.0-canary.9
10
+
11
+ ### Patch Changes
12
+
13
+ - [`b0b8348b0`](https://github.com/graphcommerce-org/graphcommerce/commit/b0b8348b0d294f98140c2605691d47011add5b01) - Fix ellipsis for long titles on mobile ([@bramvanderholst](https://github.com/bramvanderholst))
14
+
15
+ ## 5.2.0-canary.8
16
+
17
+ ## 5.2.0-canary.7
18
+
19
+ ### Minor Changes
20
+
21
+ - [#1749](https://github.com/graphcommerce-org/graphcommerce/pull/1749) [`0cc472915`](https://github.com/graphcommerce-org/graphcommerce/commit/0cc4729154d316227a41712b5f0adf514768e91f) - Added new filter UI and behaviour. Filters will appear as a popper on the md and up breakpoints and as an overlay on sm and below breakpoints. Filters now have an Apply button instead of applying directly. ([@paales](https://github.com/paales))
22
+
23
+ ### Patch Changes
24
+
25
+ - [#1749](https://github.com/graphcommerce-org/graphcommerce/pull/1749) [`16e91da42`](https://github.com/graphcommerce-org/graphcommerce/commit/16e91da42dcb454ea4761d1780b9338c88ef1463) - Fix spelling error incomming to incoming ([@paales](https://github.com/paales))
26
+
27
+ ## 5.2.0-canary.6
28
+
29
+ ## 5.2.0-canary.5
30
+
31
+ ### Patch Changes
32
+
33
+ - [#1776](https://github.com/graphcommerce-org/graphcommerce/pull/1776) [`09f7312ae`](https://github.com/graphcommerce-org/graphcommerce/commit/09f7312ae44fae531947f9ce64711b7ac5983fc1) - add media query guard to category menu behaviour. ([@FrankHarland](https://github.com/FrankHarland))
34
+
35
+ ## 5.2.0-canary.4
36
+
37
+ ## 5.2.0-canary.3
38
+
39
+ ## 5.2.0-canary.2
40
+
41
+ ### Patch Changes
42
+
43
+ - [#1771](https://github.com/graphcommerce-org/graphcommerce/pull/1771) [`aec07f567`](https://github.com/graphcommerce-org/graphcommerce/commit/aec07f5679472281b8eb71cf6967a1ff775d2a7f) - Navigation shouldn't become visible when resizing the viewport ([@paales](https://github.com/paales))
44
+
45
+ - [#1771](https://github.com/graphcommerce-org/graphcommerce/pull/1771) [`55d267ba0`](https://github.com/graphcommerce-org/graphcommerce/commit/55d267ba039f64af2b0248c68a1e1478970c9b31) - Solve issue where overlays would close durting opening when they got rerendered. ([@paales](https://github.com/paales))
46
+
47
+ ## 5.2.0-canary.1
48
+
3
49
  ## 5.2.0-canary.0
4
50
 
5
51
  ## 5.1.1
@@ -34,6 +34,7 @@ type ComponentStyleProps = {
34
34
  children: boolean
35
35
  floatingSm: boolean
36
36
  floatingMd: boolean
37
+ size: 'small' | 'responsive'
37
38
  }
38
39
 
39
40
  const { selectors, withState } = extendableComponent<ComponentStyleProps, 'LayoutHeader'>(
@@ -42,7 +43,16 @@ const { selectors, withState } = extendableComponent<ComponentStyleProps, 'Layou
42
43
  )
43
44
 
44
45
  export function LayoutHeader(props: LayoutHeaderProps) {
45
- const { children, divider, primary, secondary, noAlign = false, switchPoint, sx = [] } = props
46
+ const {
47
+ children,
48
+ divider,
49
+ primary,
50
+ secondary,
51
+ noAlign = false,
52
+ switchPoint,
53
+ size = 'responsive',
54
+ sx = [],
55
+ } = props
46
56
  const showBack = useShowBack()
47
57
  const showClose = useShowClose()
48
58
 
@@ -73,6 +83,7 @@ export function LayoutHeader(props: LayoutHeaderProps) {
73
83
  noAlign,
74
84
  children: !!children,
75
85
  divider: !!divider,
86
+ size,
76
87
  })
77
88
 
78
89
  return (
@@ -118,6 +129,9 @@ export function LayoutHeader(props: LayoutHeaderProps) {
118
129
  marginTop: 0,
119
130
  height: theme.appShell.appBarHeightMd,
120
131
  marginBottom: `calc(${theme.appShell.appBarHeightMd} * -1)`,
132
+ '&.sizeSmall': {
133
+ height: theme.appShell.headerHeightSm,
134
+ },
121
135
  },
122
136
  '&.divider': {
123
137
  marginBottom: 0,
@@ -128,6 +142,7 @@ export function LayoutHeader(props: LayoutHeaderProps) {
128
142
  ]}
129
143
  >
130
144
  <LayoutHeaderContent
145
+ size={size}
131
146
  left={left}
132
147
  right={right}
133
148
  divider={divider}
@@ -1,7 +1,6 @@
1
1
  import { useUp, usePrevUp, usePageContext } from '@graphcommerce/framer-next-pages'
2
2
  import { i18n } from '@lingui/core'
3
3
  import { Box, SxProps, Theme } from '@mui/material'
4
- import PageLink from 'next/link'
5
4
  import { useRouter } from 'next/router'
6
5
  import { LinkOrButton, LinkOrButtonProps } from '../../Button/LinkOrButton'
7
6
  import { IconSvg } from '../../IconSvg'
@@ -69,19 +68,18 @@ export function LayoutHeaderBack(props: BackProps) {
69
68
 
70
69
  if (up?.href && up.href !== path)
71
70
  return (
72
- <PageLink href={up.href} passHref>
73
- <LinkOrButton
74
- button={{ variant: 'pill', sx: buttonSx }}
75
- startIcon={backIcon}
76
- aria-label={up.title}
77
- color='inherit'
78
- {...props}
79
- >
80
- <Box component='span' sx={{ display: { xs: 'none', md: 'inline' } }}>
81
- {up.title}
82
- </Box>
83
- </LinkOrButton>
84
- </PageLink>
71
+ <LinkOrButton
72
+ href={up.href}
73
+ button={{ variant: 'pill', sx: buttonSx }}
74
+ startIcon={backIcon}
75
+ aria-label={up.title}
76
+ color='inherit'
77
+ {...props}
78
+ >
79
+ <Box component='span' sx={{ display: { xs: 'none', md: 'inline' } }}>
80
+ {up.title}
81
+ </Box>
82
+ </LinkOrButton>
85
83
  )
86
84
 
87
85
  return null
@@ -17,9 +17,16 @@ export type LayoutHeaderContentProps = FloatingProps & {
17
17
  sx?: SxProps<Theme>
18
18
  sxBg?: SxProps<Theme>
19
19
  layout?: LayoutProps['layout']
20
+ size?: 'small' | 'responsive'
20
21
  }
21
22
 
22
- type OwnerState = { floatingSm: boolean; floatingMd: boolean; scrolled: boolean; divider: boolean }
23
+ type OwnerState = {
24
+ floatingSm: boolean
25
+ floatingMd: boolean
26
+ scrolled: boolean
27
+ divider: boolean
28
+ size: 'small' | 'responsive'
29
+ }
23
30
  const name = 'LayoutHeaderContent' as const
24
31
  const parts = ['bg', 'content', 'left', 'center', 'right', 'divider'] as const
25
32
  const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
@@ -38,17 +45,13 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
38
45
  sx = [],
39
46
  sxBg = [],
40
47
  layout,
48
+ size = 'responsive',
41
49
  } = props
42
50
 
43
51
  const scroll = useScrollY()
44
52
  const scrolled = useMotionValueValue(scroll, (y) => y >= switchPoint)
45
53
 
46
- const classes = withState({
47
- floatingSm,
48
- floatingMd,
49
- scrolled,
50
- divider: !!divider,
51
- })
54
+ const classes = withState({ floatingSm, floatingMd, scrolled, divider: !!divider, size })
52
55
 
53
56
  return (
54
57
  <>
@@ -66,6 +69,9 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
66
69
  [theme.breakpoints.up('md')]: {
67
70
  height: theme.appShell.appBarHeightMd,
68
71
  },
72
+ '&.sizeSmall': {
73
+ height: theme.appShell.headerHeightSm,
74
+ },
69
75
  borderTopLeftRadius: theme.shape.borderRadius * 3,
70
76
  borderTopRightRadius: theme.shape.borderRadius * 3,
71
77
 
@@ -105,25 +111,31 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
105
111
  gridTemplateAreas: `"left center right"`,
106
112
  gridTemplateColumns: '1fr auto 1fr',
107
113
  alignItems: 'center',
108
- // columnGap: theme.spacings.xs,
114
+ gap: theme.page.horizontal,
109
115
 
110
116
  height: theme.appShell.headerHeightSm,
111
- padding: `0 ${theme.page.horizontal}`,
112
-
117
+ px: theme.page.horizontal,
113
118
  [theme.breakpoints.up('md')]: {
114
119
  height: theme.appShell.appBarHeightMd,
115
120
  },
121
+ '&.sizeSmall': {
122
+ height: theme.appShell.headerHeightSm,
123
+ px: 2,
124
+ [theme.breakpoints.up('md')]: {
125
+ px: 2,
126
+ },
127
+ },
116
128
 
117
129
  '&.floatingSm': {
118
130
  [theme.breakpoints.down('md')]: {
119
- padding: `0 ${theme.page.horizontal}`,
131
+ px: theme.page.horizontal,
120
132
  background: 'none',
121
133
  pointerEvents: 'none',
122
134
  },
123
135
  },
124
136
  '&.floatingMd': {
125
137
  [theme.breakpoints.up('md')]: {
126
- padding: `0 ${theme.page.horizontal}`,
138
+ px: theme.page.horizontal,
127
139
  background: 'none',
128
140
  pointerEvents: 'none',
129
141
  },
@@ -180,7 +192,12 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
180
192
  },
181
193
  })}
182
194
  >
183
- <MotionDiv layout={layout}>{children}</MotionDiv>
195
+ <MotionDiv
196
+ sx={{ minWidth: 0 }}
197
+ layout={layout}
198
+ >
199
+ {children}
200
+ </MotionDiv>
184
201
  </Box>
185
202
  <Box
186
203
  className={classes.right}
@@ -1,14 +1,13 @@
1
- import { MotionValue } from 'framer-motion'
2
1
  import { useMemo } from 'react'
3
2
  import { layoutContext } from '../context/layoutContext'
3
+ import { LayoutContext } from '../types'
4
4
 
5
5
  export type LayoutProviderProps = {
6
6
  children: React.ReactNode
7
- scroll: MotionValue<number>
8
- }
7
+ } & LayoutContext
9
8
 
10
9
  export function LayoutProvider(props: LayoutProviderProps) {
11
- const { children, scroll } = props
10
+ const { children, scroll: scroll } = props
12
11
 
13
12
  return (
14
13
  <layoutContext.Provider value={useMemo(() => ({ scroll }), [scroll])}>
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
2
  import { LayoutContext } from '../types'
3
3
 
4
- export const layoutContext = React.createContext(undefined as unknown as LayoutContext)
4
+ export const layoutContext = React.createContext<null | LayoutContext>(null)
5
5
  layoutContext.displayName = 'layoutContext'
@@ -2,5 +2,10 @@ import { useContext } from 'react'
2
2
  import { layoutContext } from '../context/layoutContext'
3
3
 
4
4
  export function useScrollY() {
5
- return useContext(layoutContext).scroll
5
+ const context = useContext(layoutContext)
6
+
7
+ if (!context) {
8
+ throw new Error('useScrollY must be used within a LayoutProvider')
9
+ }
10
+ return context.scroll
6
11
  }
@@ -40,8 +40,9 @@ export function LayoutDefault(props: LayoutDefaultProps) {
40
40
  sx = [],
41
41
  } = props
42
42
 
43
- const scrollWithOffset = useTransform(
44
- [useScroll().scrollY, useScrollOffset()],
43
+ const { scrollY } = useScroll()
44
+ const scrollYOffset = useTransform(
45
+ [scrollY, useScrollOffset()],
45
46
  ([y, offset]: number[]) => y + offset,
46
47
  )
47
48
 
@@ -66,7 +67,7 @@ export function LayoutDefault(props: LayoutDefaultProps) {
66
67
  ...(Array.isArray(sx) ? sx : [sx]),
67
68
  ]}
68
69
  >
69
- <LayoutProvider scroll={scrollWithOffset}>
70
+ <LayoutProvider scroll={scrollYOffset}>
70
71
  {beforeHeader}
71
72
  <Box
72
73
  component='header'
@@ -1,10 +1,11 @@
1
1
  import { usePageContext, useGo, useScrollOffset } from '@graphcommerce/framer-next-pages'
2
- import { ScrollerProvider, ScrollSnapType } from '@graphcommerce/framer-scroller'
2
+ import { ScrollerProvider } from '@graphcommerce/framer-scroller'
3
3
  import { useMotionValueValue } from '@graphcommerce/framer-utils'
4
4
  import { useEventCallback } from '@mui/material'
5
5
  import { usePresence } from 'framer-motion'
6
6
  import type { SetOptional } from 'type-fest'
7
7
  import { OverlayBase, LayoutOverlayBaseProps } from '../../Overlay/components/OverlayBase'
8
+ import { variantsToScrollSnapType } from '../../Overlay/utils/variantsToScrollSnapType'
8
9
 
9
10
  export type LayoutOverlayProps = Omit<
10
11
  SetOptional<LayoutOverlayBaseProps, 'variantSm' | 'variantMd'>,
@@ -14,22 +15,13 @@ export type LayoutOverlayProps = Omit<
14
15
  export function LayoutOverlay(props: LayoutOverlayProps) {
15
16
  const { children, variantSm = 'bottom', variantMd = 'right', ...otherProps } = props
16
17
 
17
- const scrollSnapTypeSm: ScrollSnapType =
18
- variantSm === 'left' || variantSm === 'right' ? 'inline mandatory' : 'block proximity'
19
- const scrollSnapTypeMd: ScrollSnapType =
20
- variantMd === 'left' || variantMd === 'right' ? 'inline mandatory' : 'block proximity'
21
-
22
18
  const { closeSteps, active, direction } = usePageContext()
23
19
  const onCloseHandler = useGo(closeSteps * -1)
24
20
  const offsetPageY = useMotionValueValue(useScrollOffset(), (v) => v)
25
21
  const [isPresent, safeToRemove] = usePresence()
26
22
 
27
23
  return (
28
- <ScrollerProvider
29
- scrollSnapTypeSm={scrollSnapTypeSm}
30
- scrollSnapTypeMd={scrollSnapTypeMd}
31
- _inititalSnap={false}
32
- >
24
+ <ScrollerProvider {...variantsToScrollSnapType(props)} _inititalSnap={false}>
33
25
  <OverlayBase
34
26
  active={active}
35
27
  direction={direction}