@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.
- package/ActionCard/ActionCard.tsx +2 -2
- package/ActionCard/ActionCardList.tsx +10 -13
- package/ActionCard/ActionCardListForm.tsx +31 -13
- package/Blog/BlogListItem/BlogListItem.tsx +34 -39
- package/Blog/BlogTags/BlogTag.tsx +7 -13
- package/Button/LinkOrButton.tsx +2 -2
- package/CHANGELOG.md +46 -0
- package/Layout/components/LayoutHeader.tsx +16 -1
- package/Layout/components/LayoutHeaderBack.tsx +12 -14
- package/Layout/components/LayoutHeaderContent.tsx +30 -13
- package/Layout/components/LayoutProvider.tsx +3 -4
- package/Layout/context/layoutContext.tsx +1 -1
- package/Layout/hooks/useScrollY.tsx +6 -1
- package/LayoutDefault/components/LayoutDefault.tsx +4 -3
- package/LayoutOverlay/components/LayoutOverlay.tsx +3 -11
- package/LayoutParts/DesktopNavBarItem.tsx +28 -30
- package/LayoutParts/Logo.tsx +6 -8
- package/LayoutParts/MenuFabItem.tsx +11 -12
- package/LayoutParts/MenuFabSecondaryItem.tsx +13 -15
- package/Navigation/components/NavigationItem.tsx +30 -27
- package/Navigation/components/NavigationOverlay.tsx +3 -3
- package/Overlay/components/Overlay.tsx +29 -50
- package/Overlay/components/OverlayBase.tsx +23 -18
- package/Overlay/components/OverlayContainer.tsx +32 -0
- package/Overlay/components/OverlaySsr.tsx +43 -0
- package/Overlay/components/OverlayStickyBottom.tsx +23 -0
- package/Overlay/utils/variantsToScrollSnapType.ts +16 -0
- package/OverlayOrPopperChip/OverlayOrPopperChip.tsx +115 -0
- package/OverlayOrPopperChip/OverlayOrPopperPanel.tsx +21 -0
- package/OverlayOrPopperChip/OverlayPanel.tsx +32 -0
- package/OverlayOrPopperChip/OverlayPanelActions.tsx +76 -0
- package/OverlayOrPopperChip/PopperPanel.tsx +52 -0
- package/OverlayOrPopperChip/PopperPanelActions.tsx +67 -0
- package/OverlayOrPopperChip/index.ts +3 -0
- package/OverlayOrPopperChip/types.ts +22 -0
- package/OverlayOrPopperChip/useHandleClickNotDrag.ts +36 -0
- package/PageMeta/PageMeta.tsx +5 -5
- package/Row/ButtonLinkList/ButtonLinkListItem.tsx +17 -18
- package/Theme/MuiSlider.ts +12 -0
- package/Theme/NextLink.tsx +41 -0
- package/Theme/index.ts +1 -0
- package/hooks/useUrlQuery.ts +2 -2
- package/icons/index.ts +6 -4
- package/index.ts +1 -0
- 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?:
|
|
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
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 (
|
|
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<
|
|
13
|
+
export type ActionCardListFormProps<A, F extends FieldValues = FieldValues> = Omit<
|
|
14
14
|
ActionCardListProps,
|
|
15
|
-
'value' | 'error' | 'onChange' | 'children'
|
|
15
|
+
'value' | 'error' | 'onChange' | 'children'
|
|
16
16
|
> &
|
|
17
|
-
Omit<ControllerProps<
|
|
18
|
-
items:
|
|
19
|
-
render: React.FC<ActionCardItemRenderProps<
|
|
17
|
+
Omit<ControllerProps<F>, 'render'> & {
|
|
18
|
+
items: A[]
|
|
19
|
+
render: React.FC<ActionCardItemRenderProps<A>>
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function ActionCardListForm<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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={
|
|
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
|
-
<
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
'
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
<
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
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
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
}
|
package/Button/LinkOrButton.tsx
CHANGED
|
@@ -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?:
|
|
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 {
|
|
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
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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 = {
|
|
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
|
-
|
|
114
|
+
gap: theme.page.horizontal,
|
|
109
115
|
|
|
110
116
|
height: theme.appShell.headerHeightSm,
|
|
111
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
44
|
-
|
|
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={
|
|
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
|
|
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}
|