@graphcommerce/next-ui 4.13.0 → 4.15.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.
- package/ActionCard/ActionCard.tsx +2 -2
- package/ActionCard/ActionCardList.tsx +107 -76
- package/ActionCard/ActionCardListForm.tsx +2 -1
- package/Blog/BlogListItem/BlogListItem.tsx +1 -1
- package/CHANGELOG.md +49 -0
- package/FramerScroller/SidebarGallery.tsx +12 -1
- package/Layout/components/LayoutHeaderContent.tsx +6 -4
- package/LayoutDefault/components/LayoutDefault.tsx +4 -2
- package/LayoutOverlay/components/LayoutOverlay.tsx +2 -1
- package/LayoutOverlay/test/LayoutOverlayDemo.tsx +1 -1
- package/Navigation/components/NavigationItem.tsx +51 -12
- package/Navigation/components/NavigationList.tsx +4 -3
- package/Navigation/components/NavigationOverlay.tsx +72 -16
- package/Navigation/components/NavigationProvider.tsx +7 -2
- package/Navigation/hooks/useNavigation.ts +2 -1
- package/Overlay/components/OverlayBase.tsx +4 -1
- package/PageMeta/PageMeta.tsx +4 -6
- package/index.ts +2 -0
- package/package.json +12 -10
- package/utils/cookie.ts +33 -0
|
@@ -11,7 +11,7 @@ export type ActionCardProps = {
|
|
|
11
11
|
price?: React.ReactNode
|
|
12
12
|
after?: React.ReactNode
|
|
13
13
|
secondaryAction?: React.ReactNode
|
|
14
|
-
onClick?: (
|
|
14
|
+
onClick?: (event: React.MouseEvent<HTMLElement>, value: string | number) => void
|
|
15
15
|
selected?: boolean
|
|
16
16
|
hidden?: boolean
|
|
17
17
|
value: string | number
|
|
@@ -66,7 +66,7 @@ export function ActionCard(props: ActionCardProps) {
|
|
|
66
66
|
|
|
67
67
|
const classes = withState({ hidden, disabled, selected, image: Boolean(image) })
|
|
68
68
|
|
|
69
|
-
const handleClick = (event:
|
|
69
|
+
const handleClick = (event: React.MouseEvent<HTMLElement>) => onClick?.(event, value)
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
72
|
<ButtonBase
|
|
@@ -3,19 +3,20 @@ import { AnimatePresence } from 'framer-motion'
|
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { isFragment } from 'react-is'
|
|
5
5
|
import { AnimatedRow } from '../AnimatedRow/AnimatedRow'
|
|
6
|
+
import { ActionCardProps } from './ActionCard'
|
|
6
7
|
|
|
7
8
|
type MultiSelect = {
|
|
8
9
|
multiple: true
|
|
9
|
-
value: string[]
|
|
10
|
+
value: (string | number)[]
|
|
10
11
|
|
|
11
|
-
onChange?: (event: React.MouseEvent<HTMLElement>, value:
|
|
12
|
+
onChange?: (event: React.MouseEvent<HTMLElement>, value: MultiSelect['value']) => void
|
|
12
13
|
}
|
|
13
14
|
type Select = {
|
|
14
15
|
multiple?: false
|
|
15
|
-
value: string
|
|
16
|
+
value: string | number
|
|
16
17
|
|
|
17
18
|
/** Value is null when deselected when not required */
|
|
18
|
-
onChange?: (event: React.MouseEvent<HTMLElement>, value:
|
|
19
|
+
onChange?: (event: React.MouseEvent<HTMLElement>, value: Select['value'] | null) => void
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export type ActionCardListProps<SelectOrMulti = MultiSelect | Select> = {
|
|
@@ -29,94 +30,124 @@ function isMulti(props: ActionCardListProps): props is ActionCardListProps<Multi
|
|
|
29
30
|
return props.multiple === true
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
function isValueSelected(
|
|
33
|
-
|
|
33
|
+
function isValueSelected(
|
|
34
|
+
value: ActionCardProps['value'],
|
|
35
|
+
candidate?: Select['value'] | MultiSelect['value'],
|
|
36
|
+
) {
|
|
37
|
+
if (candidate === undefined) return false
|
|
34
38
|
if (Array.isArray(candidate)) return candidate.indexOf(value) >= 0
|
|
35
39
|
return value === candidate
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
export
|
|
39
|
-
|
|
42
|
+
export const ActionCardList = React.forwardRef<HTMLDivElement, ActionCardListProps>(
|
|
43
|
+
(props, ref) => {
|
|
44
|
+
const { children, required, error = false, errorMessage } = props
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
const handleChange: ActionCardProps['onClick'] = isMulti(props)
|
|
47
|
+
? (event, v) => {
|
|
48
|
+
const { onChange, value } = props
|
|
49
|
+
const index = Boolean(value) && value?.indexOf(v)
|
|
50
|
+
let newValue: typeof value
|
|
46
51
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
if (value.length && index && index >= 0) {
|
|
53
|
+
newValue = value.slice()
|
|
54
|
+
newValue.splice(index, 1)
|
|
55
|
+
} else {
|
|
56
|
+
newValue = value ? [...value, v] : [v]
|
|
57
|
+
}
|
|
58
|
+
onChange?.(event, newValue)
|
|
52
59
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
: (event: React.MouseEvent<HTMLElement, MouseEvent>, buttonValue: string) => {
|
|
56
|
-
const { onChange } = props
|
|
60
|
+
: (event, v) => {
|
|
61
|
+
const { onChange, value } = props
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
if (value !== v) {
|
|
64
|
+
if (required) onChange?.(event, v)
|
|
65
|
+
else onChange?.(event, value === v ? null : v)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
62
68
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
sx={[
|
|
66
|
-
error &&
|
|
67
|
-
((theme) => ({
|
|
68
|
-
'& .ActionCard-root': {
|
|
69
|
-
borderLeft: 2,
|
|
70
|
-
borderRight: 2,
|
|
71
|
-
borderLeftColor: 'error.main',
|
|
72
|
-
borderRightColor: 'error.main',
|
|
73
|
-
paddingLeft: theme.spacings.xs,
|
|
74
|
-
paddingRight: theme.spacings.xs,
|
|
75
|
-
},
|
|
76
|
-
'& > div:first-of-type.ActionCard-root': {
|
|
77
|
-
borderTop: 2,
|
|
78
|
-
borderTopColor: 'error.main',
|
|
79
|
-
paddingTop: theme.spacings.xxs,
|
|
80
|
-
},
|
|
81
|
-
'& > div:last-of-type.ActionCard-root': {
|
|
82
|
-
borderBottom: 2,
|
|
83
|
-
borderBottomColor: 'error.main',
|
|
84
|
-
paddingBottom: theme.spacings.xxs,
|
|
85
|
-
},
|
|
86
|
-
})),
|
|
87
|
-
]}
|
|
69
|
+
type ActionCardLike = React.ReactElement<
|
|
70
|
+
Pick<ActionCardProps, 'value' | 'selected' | 'disabled' | 'onClick'>
|
|
88
71
|
>
|
|
89
|
-
|
|
90
|
-
|
|
72
|
+
function isActionCardLike(el: React.ReactElement): el is ActionCardLike {
|
|
73
|
+
const hasValue = (el as ActionCardLike).props.value
|
|
91
74
|
|
|
75
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
76
|
+
if (!hasValue) console.error(el, `must be an instance of ActionCard`)
|
|
77
|
+
}
|
|
78
|
+
return (el as ActionCardLike).props.value !== undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Make sure the children are cardlike
|
|
82
|
+
const childReactNodes = React.Children.toArray(children)
|
|
83
|
+
.filter(React.isValidElement)
|
|
84
|
+
.filter(isActionCardLike)
|
|
85
|
+
.filter((child) => {
|
|
92
86
|
if (process.env.NODE_ENV !== 'production') {
|
|
93
|
-
if (isFragment(child))
|
|
87
|
+
if (isFragment(child))
|
|
94
88
|
console.error(
|
|
95
89
|
[
|
|
96
90
|
"@graphcommerce/next-ui: The ActionCardList component doesn't accept a Fragment as a child.",
|
|
97
|
-
'Consider providing an array instead
|
|
91
|
+
'Consider providing an array instead',
|
|
98
92
|
].join('\n'),
|
|
99
93
|
)
|
|
100
|
-
}
|
|
101
94
|
}
|
|
102
95
|
|
|
103
|
-
return
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
96
|
+
return !isFragment(child)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// Make sure the selected values is in the list of all possible values
|
|
100
|
+
const value = childReactNodes.find(
|
|
101
|
+
// eslint-disable-next-line react/destructuring-assignment
|
|
102
|
+
(child) => child.props.value === props.value && child.props.disabled !== true,
|
|
103
|
+
)?.props.value
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<Box
|
|
107
|
+
ref={ref}
|
|
108
|
+
sx={[
|
|
109
|
+
error &&
|
|
110
|
+
((theme) => ({
|
|
111
|
+
'& .ActionCard-root': {
|
|
112
|
+
borderLeft: 2,
|
|
113
|
+
borderRight: 2,
|
|
114
|
+
borderLeftColor: 'error.main',
|
|
115
|
+
borderRightColor: 'error.main',
|
|
116
|
+
paddingLeft: theme.spacings.xs,
|
|
117
|
+
paddingRight: theme.spacings.xs,
|
|
118
|
+
},
|
|
119
|
+
'& > div:first-of-type.ActionCard-root': {
|
|
120
|
+
borderTop: 2,
|
|
121
|
+
borderTopColor: 'error.main',
|
|
122
|
+
paddingTop: theme.spacings.xxs,
|
|
123
|
+
},
|
|
124
|
+
'& > div:last-of-type.ActionCard-root': {
|
|
125
|
+
borderBottom: 2,
|
|
126
|
+
borderBottomColor: 'error.main',
|
|
127
|
+
paddingBottom: theme.spacings.xxs,
|
|
128
|
+
},
|
|
129
|
+
})),
|
|
130
|
+
]}
|
|
131
|
+
>
|
|
132
|
+
{childReactNodes.map((child) =>
|
|
133
|
+
React.cloneElement(child, {
|
|
134
|
+
onClick: handleChange,
|
|
135
|
+
selected:
|
|
136
|
+
child.props.selected === undefined
|
|
137
|
+
? isValueSelected(child.props.value, value)
|
|
138
|
+
: child.props.selected,
|
|
139
|
+
}),
|
|
140
|
+
)}
|
|
141
|
+
{error && (
|
|
142
|
+
<Alert
|
|
143
|
+
severity='error'
|
|
144
|
+
variant='filled'
|
|
145
|
+
sx={{ borderStartStartRadius: 0, borderStartEndRadius: 0 }}
|
|
146
|
+
>
|
|
147
|
+
{errorMessage}
|
|
148
|
+
</Alert>
|
|
149
|
+
)}
|
|
150
|
+
</Box>
|
|
151
|
+
)
|
|
152
|
+
},
|
|
153
|
+
)
|
|
@@ -34,10 +34,11 @@ export function ActionCardListForm<T extends ActionCardItemBase>(
|
|
|
34
34
|
control={control}
|
|
35
35
|
name={name}
|
|
36
36
|
rules={{ required, ...rules, validate: (v) => (v ? true : errorMessage) }}
|
|
37
|
-
render={({ field: { onChange, value }, fieldState, formState }) => (
|
|
37
|
+
render={({ field: { onChange, value, onBlur, ref }, fieldState, formState }) => (
|
|
38
38
|
<ActionCardList
|
|
39
39
|
required
|
|
40
40
|
value={value}
|
|
41
|
+
ref={ref}
|
|
41
42
|
onChange={(_, incomming) => onChange(incomming)}
|
|
42
43
|
error={formState.isSubmitted && !!fieldState.error}
|
|
43
44
|
errorMessage={fieldState.error?.message}
|
|
@@ -20,7 +20,7 @@ const { classes } = extendableComponent(name, parts)
|
|
|
20
20
|
export function BlogListItem(props: BlogListItemProps) {
|
|
21
21
|
const { asset, url, date, title, sx = [] } = props
|
|
22
22
|
|
|
23
|
-
const formatter = useDateTimeFormat({
|
|
23
|
+
const formatter = useDateTimeFormat({ dateStyle: 'long' })
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
26
|
<Box
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 4.15.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1566](https://github.com/graphcommerce-org/graphcommerce/pull/1566) [`e167992df`](https://github.com/graphcommerce-org/graphcommerce/commit/e167992dfdc6964a392af719667f8a188626ab1b) Thanks [@ErwinOtten](https://github.com/ErwinOtten)! - Introduced `@graphcommerce/next-ui/navigation` component.
|
|
8
|
+
|
|
9
|
+
- Navigation is always present in the DOM
|
|
10
|
+
- Configurable in LayoutNavigation.tsx
|
|
11
|
+
- Show categories directly, or nest them in a 'products' button
|
|
12
|
+
- Choose prefered mouseEvent: click or hover
|
|
13
|
+
|
|
14
|
+
* [#1566](https://github.com/graphcommerce-org/graphcommerce/pull/1566) [`9c2504b4e`](https://github.com/graphcommerce-org/graphcommerce/commit/9c2504b4ed75f41d3003c4d3339814010e85e37e) Thanks [@ErwinOtten](https://github.com/ErwinOtten)! - publish navigation
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies []:
|
|
19
|
+
- @graphcommerce/framer-scroller@2.1.25
|
|
20
|
+
|
|
21
|
+
## 4.14.0
|
|
22
|
+
|
|
23
|
+
### Minor Changes
|
|
24
|
+
|
|
25
|
+
- [#1553](https://github.com/graphcommerce-org/graphcommerce/pull/1553) [`323fdee4b`](https://github.com/graphcommerce-org/graphcommerce/commit/323fdee4b15ae23e0e84dd0588cb2c6446dcfd50) Thanks [@NickdeK](https://github.com/NickdeK)! - Added a new cookies utility to load cookies on the frontend
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- [#1553](https://github.com/graphcommerce-org/graphcommerce/pull/1553) [`afcd8e4bf`](https://github.com/graphcommerce-org/graphcommerce/commit/afcd8e4bfb7010da4d5faeed85b61991ed7975f4) Thanks [@NickdeK](https://github.com/NickdeK)! - ActionCardList will now show all options when the selected value isn't in any of the options
|
|
30
|
+
|
|
31
|
+
* [#1553](https://github.com/graphcommerce-org/graphcommerce/pull/1553) [`02e1988e5`](https://github.com/graphcommerce-org/graphcommerce/commit/02e1988e5f361c6f66ae30d3bbee38ef2ac062df) Thanks [@NickdeK](https://github.com/NickdeK)! - Make sure the useDateTimeFormat isn't giving hydration warnings
|
|
32
|
+
|
|
33
|
+
* Updated dependencies []:
|
|
34
|
+
- @graphcommerce/framer-scroller@2.1.24
|
|
35
|
+
|
|
36
|
+
## 4.13.1
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- [#1552](https://github.com/graphcommerce-org/graphcommerce/pull/1552) [`18054c441`](https://github.com/graphcommerce-org/graphcommerce/commit/18054c441962ba750bed3acc39ab46c8d3a341ce) Thanks [@paales](https://github.com/paales)! - Updated to Next.js v12.2.2 and other packages and made compatible
|
|
41
|
+
|
|
42
|
+
* [#1552](https://github.com/graphcommerce-org/graphcommerce/pull/1552) [`c5c539c44`](https://github.com/graphcommerce-org/graphcommerce/commit/c5c539c44eeac524cd62ce649e132d2e00333794) Thanks [@paales](https://github.com/paales)! - Make sure the gallery doesn't scroll when overlays are opened
|
|
43
|
+
|
|
44
|
+
- [#1552](https://github.com/graphcommerce-org/graphcommerce/pull/1552) [`6f69bc54c`](https://github.com/graphcommerce-org/graphcommerce/commit/6f69bc54c6e0224452817c532ae58d9c332b61ea) Thanks [@paales](https://github.com/paales)! - Prevent back button scrolling when navigating between overlays
|
|
45
|
+
|
|
46
|
+
* [#1552](https://github.com/graphcommerce-org/graphcommerce/pull/1552) [`21886d6fa`](https://github.com/graphcommerce-org/graphcommerce/commit/21886d6fa64a48d9e932bfaf8d138c9b13c36e43) Thanks [@paales](https://github.com/paales)! - Fix page stacking and scroll restoration when navigating
|
|
47
|
+
|
|
48
|
+
* Updated dependencies [[`18054c441`](https://github.com/graphcommerce-org/graphcommerce/commit/18054c441962ba750bed3acc39ab46c8d3a341ce), [`21886d6fa`](https://github.com/graphcommerce-org/graphcommerce/commit/21886d6fa64a48d9e932bfaf8d138c9b13c36e43), [`b4936e961`](https://github.com/graphcommerce-org/graphcommerce/commit/b4936e96175fe80717895822e245274db05638bd)]:
|
|
49
|
+
- @graphcommerce/framer-next-pages@3.2.4
|
|
50
|
+
- @graphcommerce/framer-scroller@2.1.23
|
|
51
|
+
|
|
3
52
|
## 4.13.0
|
|
4
53
|
|
|
5
54
|
### Minor Changes
|
|
@@ -119,6 +119,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
119
119
|
<Row maxWidth={false} disableGutters className={classes.row} sx={sx}>
|
|
120
120
|
<MotionBox
|
|
121
121
|
layout
|
|
122
|
+
layoutDependency={zoomed}
|
|
122
123
|
className={classes.root}
|
|
123
124
|
sx={[
|
|
124
125
|
{
|
|
@@ -146,6 +147,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
146
147
|
>
|
|
147
148
|
<MotionBox
|
|
148
149
|
layout
|
|
150
|
+
layoutDependency={zoomed}
|
|
149
151
|
className={classes.scrollerContainer}
|
|
150
152
|
sx={[
|
|
151
153
|
{
|
|
@@ -193,6 +195,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
193
195
|
<MotionImageAspect
|
|
194
196
|
key={typeof image.src === 'string' ? image.src : idx}
|
|
195
197
|
layout
|
|
198
|
+
layoutDependency={zoomed}
|
|
196
199
|
src={image.src}
|
|
197
200
|
width={image.width}
|
|
198
201
|
height={image.height}
|
|
@@ -209,6 +212,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
209
212
|
</Scroller>
|
|
210
213
|
<MotionBox
|
|
211
214
|
layout
|
|
215
|
+
layoutDependency={zoomed}
|
|
212
216
|
className={classes.topRight}
|
|
213
217
|
sx={{
|
|
214
218
|
display: 'grid',
|
|
@@ -243,6 +247,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
243
247
|
>
|
|
244
248
|
<ScrollerButton
|
|
245
249
|
layout
|
|
250
|
+
layoutDependency={zoomed}
|
|
246
251
|
direction='left'
|
|
247
252
|
size='small'
|
|
248
253
|
className={classes.sliderButtons}
|
|
@@ -262,6 +267,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
262
267
|
>
|
|
263
268
|
<ScrollerButton
|
|
264
269
|
layout
|
|
270
|
+
layoutDependency={zoomed}
|
|
265
271
|
direction='right'
|
|
266
272
|
size='small'
|
|
267
273
|
className={classes.sliderButtons}
|
|
@@ -286,7 +292,11 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
286
292
|
},
|
|
287
293
|
}}
|
|
288
294
|
>
|
|
289
|
-
<ScrollerDots
|
|
295
|
+
<ScrollerDots
|
|
296
|
+
layout
|
|
297
|
+
layoutDependency={zoomed}
|
|
298
|
+
sx={{ backgroundColor: 'background.paper', boxShadow: 6 }}
|
|
299
|
+
/>
|
|
290
300
|
</Box>
|
|
291
301
|
</MotionBox>
|
|
292
302
|
|
|
@@ -319,6 +329,7 @@ export function SidebarGallery(props: SidebarGalleryProps) {
|
|
|
319
329
|
>
|
|
320
330
|
<MotionBox
|
|
321
331
|
layout
|
|
332
|
+
layoutDependency={zoomed}
|
|
322
333
|
className={classes.sidebar}
|
|
323
334
|
sx={{
|
|
324
335
|
boxSizing: 'border-box',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
2
2
|
import { Box, styled, SxProps, Theme } from '@mui/material'
|
|
3
|
-
import { m } from 'framer-motion'
|
|
3
|
+
import { LayoutProps, m } from 'framer-motion'
|
|
4
4
|
import React, { useRef } from 'react'
|
|
5
5
|
import { extendableComponent } from '../../Styles'
|
|
6
6
|
import { useScrollY } from '../hooks/useScrollY'
|
|
@@ -16,6 +16,7 @@ export type LayoutHeaderContentProps = FloatingProps & {
|
|
|
16
16
|
switchPoint?: number
|
|
17
17
|
sx?: SxProps<Theme>
|
|
18
18
|
sxBg?: SxProps<Theme>
|
|
19
|
+
layout?: LayoutProps['layout']
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
type OwnerState = { floatingSm: boolean; floatingMd: boolean; scrolled: boolean; divider: boolean }
|
|
@@ -36,6 +37,7 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
|
|
|
36
37
|
switchPoint = 50,
|
|
37
38
|
sx = [],
|
|
38
39
|
sxBg = [],
|
|
40
|
+
layout,
|
|
39
41
|
} = props
|
|
40
42
|
|
|
41
43
|
const scroll = useScrollY()
|
|
@@ -142,7 +144,7 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
|
|
|
142
144
|
justifyContent: 'start',
|
|
143
145
|
})}
|
|
144
146
|
>
|
|
145
|
-
<MotionDiv layout=
|
|
147
|
+
<MotionDiv layout={layout}>{left}</MotionDiv>
|
|
146
148
|
</Box>
|
|
147
149
|
)}
|
|
148
150
|
<Box
|
|
@@ -175,7 +177,7 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
|
|
|
175
177
|
},
|
|
176
178
|
})}
|
|
177
179
|
>
|
|
178
|
-
<MotionDiv layout=
|
|
180
|
+
<MotionDiv layout={layout}>{children}</MotionDiv>
|
|
179
181
|
</Box>
|
|
180
182
|
<Box
|
|
181
183
|
className={classes.right}
|
|
@@ -191,7 +193,7 @@ export function LayoutHeaderContent(props: LayoutHeaderContentProps) {
|
|
|
191
193
|
justifyContent: 'end',
|
|
192
194
|
})}
|
|
193
195
|
>
|
|
194
|
-
<MotionDiv layout=
|
|
196
|
+
<MotionDiv layout={layout}>{right}</MotionDiv>
|
|
195
197
|
</Box>
|
|
196
198
|
{divider && (
|
|
197
199
|
<Box
|
|
@@ -39,8 +39,10 @@ export function LayoutDefault(props: LayoutDefaultProps) {
|
|
|
39
39
|
sx = [],
|
|
40
40
|
} = props
|
|
41
41
|
|
|
42
|
-
const
|
|
43
|
-
|
|
42
|
+
const scrollWithOffset = useTransform(
|
|
43
|
+
[useViewportScroll().scrollY, useScrollOffset()],
|
|
44
|
+
([y, offset]: number[]) => y + offset,
|
|
45
|
+
)
|
|
44
46
|
|
|
45
47
|
const classes = withState({ noSticky })
|
|
46
48
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { usePageContext, useGo, useScrollOffset } from '@graphcommerce/framer-next-pages'
|
|
2
2
|
import { ScrollerProvider, ScrollSnapType } from '@graphcommerce/framer-scroller'
|
|
3
|
+
import { useMotionValueValue } from '@graphcommerce/framer-utils'
|
|
3
4
|
import { usePresence } from 'framer-motion'
|
|
4
5
|
import type { SetOptional } from 'type-fest'
|
|
5
6
|
import { OverlayBase, LayoutOverlayBaseProps } from '../../Overlay/components/OverlayBase'
|
|
@@ -19,7 +20,7 @@ export function LayoutOverlay(props: LayoutOverlayProps) {
|
|
|
19
20
|
|
|
20
21
|
const { closeSteps, active, direction } = usePageContext()
|
|
21
22
|
const onCloseHandler = useGo(closeSteps * -1)
|
|
22
|
-
const offsetPageY = useScrollOffset()
|
|
23
|
+
const offsetPageY = useMotionValueValue(useScrollOffset(), (v) => v)
|
|
23
24
|
const [isPresent, safeToRemove] = usePresence()
|
|
24
25
|
|
|
25
26
|
return (
|
|
@@ -3,7 +3,7 @@ import { LayoutOverlay, LayoutOverlayProps } from '../components/LayoutOverlay'
|
|
|
3
3
|
|
|
4
4
|
export type LayoutOverlayState = Omit<
|
|
5
5
|
LayoutOverlayProps,
|
|
6
|
-
'children' | 'sx' | 'sxBackdrop' | 'mdSpacingTop' | 'smSpacingTop'
|
|
6
|
+
'children' | 'sx' | 'sxBackdrop' | 'mdSpacingTop' | 'smSpacingTop' | 'overlayPaneProps'
|
|
7
7
|
>
|
|
8
8
|
|
|
9
9
|
export function useLayoutState() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
|
-
import { Box, ListItemButton, styled, useEventCallback } from '@mui/material'
|
|
2
|
+
import { Box, ListItemButton, styled, Theme, useEventCallback, useMediaQuery } from '@mui/material'
|
|
3
3
|
import PageLink from 'next/link'
|
|
4
|
+
import { useEffect } from 'react'
|
|
4
5
|
import { IconSvg } from '../../IconSvg'
|
|
5
6
|
import { extendableComponent } from '../../Styles/extendableComponent'
|
|
6
7
|
import { iconChevronRight } from '../../icons'
|
|
@@ -26,7 +27,12 @@ type NavigationItemProps = NavigationNode & {
|
|
|
26
27
|
parentPath: NavigationPath
|
|
27
28
|
idx: number
|
|
28
29
|
NavigationList: typeof NavigationList
|
|
29
|
-
} & OwnerState
|
|
30
|
+
} & OwnerState &
|
|
31
|
+
mouseEventPref
|
|
32
|
+
|
|
33
|
+
export type mouseEventPref = {
|
|
34
|
+
mouseEvent: 'click' | 'hover'
|
|
35
|
+
}
|
|
30
36
|
|
|
31
37
|
const componentName = 'NavigationItem'
|
|
32
38
|
const parts = ['li', 'ul', 'item'] as const
|
|
@@ -39,10 +45,10 @@ const { withState } = extendableComponent<OwnerState, typeof componentName, type
|
|
|
39
45
|
const NavigationLI = styled('li')({ display: 'contents' })
|
|
40
46
|
|
|
41
47
|
export function NavigationItem(props: NavigationItemProps) {
|
|
42
|
-
const { id, parentPath, idx, first, last, NavigationList } = props
|
|
48
|
+
const { id, parentPath, idx, first, last, NavigationList, mouseEvent } = props
|
|
43
49
|
|
|
44
50
|
const row = idx + 1
|
|
45
|
-
const { selected, select, hideRootOnNavigate, onClose } = useNavigation()
|
|
51
|
+
const { selected, select, hideRootOnNavigate, onClose, animating } = useNavigation()
|
|
46
52
|
|
|
47
53
|
const itemPath = [...parentPath, id]
|
|
48
54
|
const isSelected = selected.slice(0, itemPath.length).join('/') === itemPath.join('/')
|
|
@@ -59,6 +65,8 @@ export function NavigationItem(props: NavigationItemProps) {
|
|
|
59
65
|
onClose?.(e, href)
|
|
60
66
|
})
|
|
61
67
|
|
|
68
|
+
const isDesktop = useMediaQuery<Theme>((theme) => theme.breakpoints.up('md'))
|
|
69
|
+
|
|
62
70
|
if (isNavigationButton(props)) {
|
|
63
71
|
const { childItems, name } = props
|
|
64
72
|
return (
|
|
@@ -66,18 +74,44 @@ export function NavigationItem(props: NavigationItemProps) {
|
|
|
66
74
|
<ListItemButton
|
|
67
75
|
className={classes.item}
|
|
68
76
|
role='button'
|
|
69
|
-
sx={
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
sx={[
|
|
78
|
+
(theme) => ({
|
|
79
|
+
gridRowStart: row,
|
|
80
|
+
gridColumnStart: column,
|
|
81
|
+
gap: theme.spacings.xxs,
|
|
82
|
+
display: hideItem ? 'none' : 'flex',
|
|
83
|
+
'&.Mui-disabled': {
|
|
84
|
+
opacity: 1,
|
|
85
|
+
background: theme.palette.action.hover,
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
mouseEvent === 'hover'
|
|
89
|
+
? {
|
|
90
|
+
'&.Mui-disabled': {
|
|
91
|
+
cursor: 'pointer',
|
|
92
|
+
pointerEvents: 'auto',
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
: {},
|
|
96
|
+
]}
|
|
75
97
|
disabled={isSelected}
|
|
76
98
|
tabIndex={selected.join(',').includes(parentPath.join(',')) ? undefined : -1}
|
|
77
99
|
onClick={(e) => {
|
|
78
100
|
e.preventDefault()
|
|
79
|
-
if (!isSelected)
|
|
101
|
+
if (!isSelected && animating.current === false) {
|
|
102
|
+
select(itemPath)
|
|
103
|
+
}
|
|
80
104
|
}}
|
|
105
|
+
onMouseEnter={
|
|
106
|
+
itemPath.length > 1 && mouseEvent === 'hover'
|
|
107
|
+
? (e) => {
|
|
108
|
+
if (isDesktop && animating.current === false && !isSelected) {
|
|
109
|
+
e.preventDefault()
|
|
110
|
+
setTimeout(() => select(itemPath), 0)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
: undefined
|
|
114
|
+
}
|
|
81
115
|
>
|
|
82
116
|
<Box
|
|
83
117
|
component='span'
|
|
@@ -93,7 +127,12 @@ export function NavigationItem(props: NavigationItemProps) {
|
|
|
93
127
|
<IconSvg src={iconChevronRight} sx={{ flexShrink: 0 }} />
|
|
94
128
|
</ListItemButton>
|
|
95
129
|
|
|
96
|
-
<NavigationList
|
|
130
|
+
<NavigationList
|
|
131
|
+
items={childItems}
|
|
132
|
+
selected={isSelected}
|
|
133
|
+
parentPath={itemPath}
|
|
134
|
+
mouseEvent={mouseEvent}
|
|
135
|
+
/>
|
|
97
136
|
</NavigationLI>
|
|
98
137
|
)
|
|
99
138
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { styled } from '@mui/material'
|
|
2
2
|
import { extendableComponent } from '../../Styles/extendableComponent'
|
|
3
3
|
import { NavigationNode, NavigationPath } from '../hooks/useNavigation'
|
|
4
|
-
import { NavigationItem } from './NavigationItem'
|
|
4
|
+
import { NavigationItem, mouseEventPref } from './NavigationItem'
|
|
5
5
|
|
|
6
6
|
const NavigationUList = styled('ul')({})
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ type NavigationItemsProps = {
|
|
|
9
9
|
parentPath?: NavigationPath
|
|
10
10
|
items: NavigationNode[]
|
|
11
11
|
selected?: boolean
|
|
12
|
-
}
|
|
12
|
+
} & mouseEventPref
|
|
13
13
|
|
|
14
14
|
type OwnerState = {
|
|
15
15
|
column: number
|
|
@@ -23,7 +23,7 @@ const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>
|
|
|
23
23
|
// const parts = ['li', 'ul', 'item'] as const
|
|
24
24
|
|
|
25
25
|
export function NavigationList(props: NavigationItemsProps) {
|
|
26
|
-
const { items, parentPath = [], selected = false } = props
|
|
26
|
+
const { items, parentPath = [], selected = false, mouseEvent } = props
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
29
|
<NavigationUList
|
|
@@ -43,6 +43,7 @@ export function NavigationList(props: NavigationItemsProps) {
|
|
|
43
43
|
first={idx === 0}
|
|
44
44
|
last={idx === items.length - 1}
|
|
45
45
|
column={0}
|
|
46
|
+
mouseEvent={mouseEvent}
|
|
46
47
|
/>
|
|
47
48
|
))}
|
|
48
49
|
</NavigationUList>
|
|
@@ -3,6 +3,7 @@ import { i18n } from '@lingui/core'
|
|
|
3
3
|
import { Trans } from '@lingui/react'
|
|
4
4
|
import { Box, Fab, SxProps, Theme, useEventCallback, useMediaQuery } from '@mui/material'
|
|
5
5
|
import { m } from 'framer-motion'
|
|
6
|
+
import { useState } from 'react'
|
|
6
7
|
import { IconSvg, useIconSvgSize } from '../../IconSvg'
|
|
7
8
|
import { LayoutHeaderContent } from '../../Layout/components/LayoutHeaderContent'
|
|
8
9
|
import { LayoutTitle } from '../../Layout/components/LayoutTitle'
|
|
@@ -18,14 +19,26 @@ import {
|
|
|
18
19
|
NavigationNodeHref,
|
|
19
20
|
useNavigation,
|
|
20
21
|
} from '../hooks/useNavigation'
|
|
22
|
+
import { mouseEventPref } from './NavigationItem'
|
|
21
23
|
import { NavigationList } from './NavigationList'
|
|
22
24
|
|
|
25
|
+
type LayoutOverlayVariant = 'left' | 'bottom' | 'right'
|
|
26
|
+
type LayoutOverlaySize = 'floating' | 'minimal' | 'full'
|
|
27
|
+
type LayoutOverlayAlign = 'start' | 'end' | 'center' | 'stretch'
|
|
28
|
+
|
|
23
29
|
type NavigationOverlayProps = {
|
|
24
30
|
active: boolean
|
|
25
31
|
sx?: SxProps<Theme>
|
|
26
32
|
stretchColumns?: boolean
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
variantSm: LayoutOverlayVariant
|
|
34
|
+
variantMd: LayoutOverlayVariant
|
|
35
|
+
sizeSm?: LayoutOverlaySize
|
|
36
|
+
sizeMd?: LayoutOverlaySize
|
|
37
|
+
justifySm?: LayoutOverlayAlign
|
|
38
|
+
justifyMd?: LayoutOverlayAlign
|
|
39
|
+
itemWidthSm?: string
|
|
40
|
+
itemWidthMd?: string
|
|
41
|
+
} & mouseEventPref
|
|
29
42
|
|
|
30
43
|
function findCurrent(
|
|
31
44
|
items: NavigationContextType['items'],
|
|
@@ -55,8 +68,21 @@ const parts = ['root', 'navigation', 'header', 'column'] as const
|
|
|
55
68
|
const { classes } = extendableComponent(componentName, parts)
|
|
56
69
|
|
|
57
70
|
export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
58
|
-
const {
|
|
59
|
-
|
|
71
|
+
const {
|
|
72
|
+
active,
|
|
73
|
+
sx,
|
|
74
|
+
stretchColumns,
|
|
75
|
+
variantMd,
|
|
76
|
+
variantSm,
|
|
77
|
+
justifyMd,
|
|
78
|
+
justifySm,
|
|
79
|
+
sizeMd,
|
|
80
|
+
sizeSm,
|
|
81
|
+
itemWidthSm,
|
|
82
|
+
itemWidthMd,
|
|
83
|
+
mouseEvent,
|
|
84
|
+
} = props
|
|
85
|
+
const { selected, select, items, onClose, animating } = useNavigation()
|
|
60
86
|
|
|
61
87
|
const fabSize = useFabSize('responsive')
|
|
62
88
|
const svgSize = useIconSvgSize('large')
|
|
@@ -74,12 +100,20 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
74
100
|
className={classes.root}
|
|
75
101
|
active={active}
|
|
76
102
|
onClosed={onClose}
|
|
77
|
-
variantSm=
|
|
78
|
-
sizeSm=
|
|
79
|
-
justifySm=
|
|
80
|
-
variantMd=
|
|
81
|
-
sizeMd=
|
|
82
|
-
justifyMd=
|
|
103
|
+
variantSm={variantSm}
|
|
104
|
+
sizeSm={sizeSm}
|
|
105
|
+
justifySm={justifySm}
|
|
106
|
+
variantMd={variantMd}
|
|
107
|
+
sizeMd={sizeMd}
|
|
108
|
+
justifyMd={justifyMd}
|
|
109
|
+
overlayPaneProps={{
|
|
110
|
+
onLayoutAnimationStart: () => {
|
|
111
|
+
animating.current = true
|
|
112
|
+
},
|
|
113
|
+
onLayoutAnimationComplete: () => {
|
|
114
|
+
animating.current = false
|
|
115
|
+
},
|
|
116
|
+
}}
|
|
83
117
|
sx={{
|
|
84
118
|
zIndex: 'drawer',
|
|
85
119
|
'& .LayoutOverlayBase-overlayPane': {
|
|
@@ -105,6 +139,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
105
139
|
floatingMd={false}
|
|
106
140
|
floatingSm={false}
|
|
107
141
|
switchPoint={0}
|
|
142
|
+
layout='position'
|
|
108
143
|
left={
|
|
109
144
|
showBack && (
|
|
110
145
|
<Fab
|
|
@@ -150,14 +185,35 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
150
185
|
sx={(theme) => ({
|
|
151
186
|
display: 'grid',
|
|
152
187
|
alignItems: !stretchColumns ? 'start' : undefined,
|
|
153
|
-
|
|
188
|
+
'& .NavigationItem-item': {
|
|
189
|
+
// eslint-disable-next-line no-nested-ternary
|
|
190
|
+
width: itemWidthMd
|
|
191
|
+
? selected.length >= 1
|
|
192
|
+
? `calc(${itemWidthMd} + 1px)`
|
|
193
|
+
: itemWidthMd
|
|
194
|
+
: 'auto',
|
|
195
|
+
},
|
|
154
196
|
[theme.breakpoints.down('md')]: {
|
|
197
|
+
width:
|
|
198
|
+
sizeSm !== 'floating'
|
|
199
|
+
? `calc(${itemWidthSm || '100vw'} + ${selected.length}px)`
|
|
200
|
+
: `calc(${itemWidthSm || '100vw'} - ${theme.page.horizontal} - ${
|
|
201
|
+
theme.page.horizontal
|
|
202
|
+
})`,
|
|
203
|
+
minWidth: 200,
|
|
155
204
|
overflow: 'hidden',
|
|
156
205
|
scrollSnapType: 'x mandatory',
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
206
|
+
'& .NavigationItem-item': {
|
|
207
|
+
width:
|
|
208
|
+
sizeSm !== 'floating'
|
|
209
|
+
? `calc(${itemWidthSm || '100vw'} - ${theme.spacings.md} - ${
|
|
210
|
+
theme.spacings.md
|
|
211
|
+
} + ${selected.length}px)`
|
|
212
|
+
: `calc(${itemWidthSm || '100vw'} - ${theme.spacings.md} - ${
|
|
213
|
+
theme.spacings.md
|
|
214
|
+
} - ${theme.page.horizontal} - ${theme.page.horizontal})`,
|
|
215
|
+
minWidth: `calc(${200}px - ${theme.spacings.md} - ${theme.spacings.md})`,
|
|
216
|
+
},
|
|
161
217
|
},
|
|
162
218
|
})}
|
|
163
219
|
>
|
|
@@ -227,7 +283,7 @@ export function NavigationOverlay(props: NavigationOverlayProps) {
|
|
|
227
283
|
/>
|
|
228
284
|
)}
|
|
229
285
|
|
|
230
|
-
<NavigationList items={items} selected />
|
|
286
|
+
<NavigationList items={items} selected mouseEvent={mouseEvent} />
|
|
231
287
|
</Box>
|
|
232
288
|
</Box>
|
|
233
289
|
</MotionDiv>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEventCallback } from '@mui/material'
|
|
2
2
|
import { MotionConfig } from 'framer-motion'
|
|
3
|
-
import { useState, useMemo } from 'react'
|
|
3
|
+
import { useState, useMemo, SetStateAction, useRef } from 'react'
|
|
4
4
|
import { isElement } from 'react-is'
|
|
5
5
|
import {
|
|
6
6
|
NavigationNode,
|
|
@@ -16,6 +16,8 @@ export type NavigationProviderProps = {
|
|
|
16
16
|
closeAfterNavigate?: boolean
|
|
17
17
|
children?: React.ReactNode
|
|
18
18
|
animationDuration?: number
|
|
19
|
+
selected: NavigationPath
|
|
20
|
+
setSelected: (value: SetStateAction<NavigationPath>) => void
|
|
19
21
|
onChange?: NavigationSelect
|
|
20
22
|
onClose?: NavigationContextType['onClose']
|
|
21
23
|
}
|
|
@@ -31,9 +33,11 @@ export function NavigationProvider(props: NavigationProviderProps) {
|
|
|
31
33
|
animationDuration = 0.275,
|
|
32
34
|
children,
|
|
33
35
|
onClose: onCloseUnstable,
|
|
36
|
+
selected,
|
|
37
|
+
setSelected,
|
|
34
38
|
} = props
|
|
35
39
|
|
|
36
|
-
const
|
|
40
|
+
const animating = useRef(false)
|
|
37
41
|
|
|
38
42
|
const select = useEventCallback((incomming: NavigationPath) => {
|
|
39
43
|
setSelected(incomming)
|
|
@@ -50,6 +54,7 @@ export function NavigationProvider(props: NavigationProviderProps) {
|
|
|
50
54
|
hideRootOnNavigate,
|
|
51
55
|
selected,
|
|
52
56
|
select,
|
|
57
|
+
animating,
|
|
53
58
|
items: items
|
|
54
59
|
.map((item, index) => (isElement(item) ? { id: item.key ?? index, component: item } : item))
|
|
55
60
|
.filter(nonNullable),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react'
|
|
1
|
+
import { createContext, MutableRefObject, SetStateAction, useContext } from 'react'
|
|
2
2
|
|
|
3
3
|
export type NavigationId = string | number
|
|
4
4
|
export type NavigationPath = NavigationId[]
|
|
@@ -17,6 +17,7 @@ export type NavigationContextType = {
|
|
|
17
17
|
items: NavigationNode[]
|
|
18
18
|
hideRootOnNavigate: boolean
|
|
19
19
|
onClose: NavigationOnClose
|
|
20
|
+
animating: MutableRefObject<boolean>
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
type NavigationNodeBase = {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useIsomorphicLayoutEffect,
|
|
6
6
|
} from '@graphcommerce/framer-utils'
|
|
7
7
|
import { Box, styled, SxProps, Theme, useTheme, useThemeProps } from '@mui/material'
|
|
8
|
-
import { m, useDomEvent, useMotionValue, useTransform } from 'framer-motion'
|
|
8
|
+
import { m, MotionProps, useDomEvent, useMotionValue, useTransform } from 'framer-motion'
|
|
9
9
|
import React, { useCallback, useEffect, useRef } from 'react'
|
|
10
10
|
import { LayoutProvider } from '../../Layout/components/LayoutProvider'
|
|
11
11
|
import { ExtendableComponent, extendableComponent } from '../../Styles'
|
|
@@ -40,6 +40,7 @@ export type LayoutOverlayBaseProps = {
|
|
|
40
40
|
offsetPageY: number
|
|
41
41
|
isPresent: boolean
|
|
42
42
|
safeToRemove: (() => void) | null | undefined
|
|
43
|
+
overlayPaneProps?: MotionProps
|
|
43
44
|
} & StyleProps &
|
|
44
45
|
OverridableProps
|
|
45
46
|
|
|
@@ -86,6 +87,7 @@ export function OverlayBase(incommingProps: LayoutOverlayBaseProps) {
|
|
|
86
87
|
offsetPageY,
|
|
87
88
|
isPresent,
|
|
88
89
|
safeToRemove,
|
|
90
|
+
overlayPaneProps,
|
|
89
91
|
} = props
|
|
90
92
|
|
|
91
93
|
const th = useTheme()
|
|
@@ -367,6 +369,7 @@ export function OverlayBase(incommingProps: LayoutOverlayBaseProps) {
|
|
|
367
369
|
})}
|
|
368
370
|
>
|
|
369
371
|
<MotionDiv
|
|
372
|
+
{...overlayPaneProps}
|
|
370
373
|
layout
|
|
371
374
|
className={classes.overlayPane}
|
|
372
375
|
sx={(theme) => ({
|
package/PageMeta/PageMeta.tsx
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { usePageContext } from '@graphcommerce/framer-next-pages'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
getDomainLocale,
|
|
7
|
-
} from 'next/dist/shared/lib/router/router'
|
|
2
|
+
import { addBasePath } from 'next/dist/client/add-base-path'
|
|
3
|
+
import { addLocale } from 'next/dist/client/add-locale'
|
|
4
|
+
import { getDomainLocale } from 'next/dist/client/get-domain-locale'
|
|
5
|
+
import { resolveHref } from 'next/dist/shared/lib/router/router'
|
|
8
6
|
import Head from 'next/head'
|
|
9
7
|
import { useRouter } from 'next/router'
|
|
10
8
|
|
package/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './ActionCard/ActionCard'
|
|
2
2
|
export * from './ActionCard/ActionCardList'
|
|
3
|
+
export * from './ActionCard/ActionCardListForm'
|
|
3
4
|
export * from './AnimatedRow/AnimatedRow'
|
|
4
5
|
export * from './Blog/BlogAuthor/BlogAuthor'
|
|
5
6
|
export * from './Blog/BlogContent/BlogContent'
|
|
@@ -55,3 +56,4 @@ export * from './ToggleButton/ToggleButton'
|
|
|
55
56
|
export * from './ToggleButtonGroup/ToggleButtonGroup'
|
|
56
57
|
export * from './UspList/UspList'
|
|
57
58
|
export * from './UspList/UspListItem'
|
|
59
|
+
export * from './utils/cookie'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/next-ui",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.15.0",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"sideEffects": false,
|
|
@@ -15,15 +15,16 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@emotion/babel-preset-css-prop": "^11.2.0",
|
|
18
|
-
"@emotion/cache": "^11.
|
|
19
|
-
"@emotion/react": "^11.9.
|
|
18
|
+
"@emotion/cache": "^11.9.3",
|
|
19
|
+
"@emotion/react": "^11.9.3",
|
|
20
20
|
"@emotion/server": "^11.4.0",
|
|
21
|
-
"@emotion/styled": "^11.
|
|
22
|
-
"@graphcommerce/framer-next-pages": "3.2.
|
|
23
|
-
"@graphcommerce/framer-scroller": "2.1.
|
|
21
|
+
"@emotion/styled": "^11.9.3",
|
|
22
|
+
"@graphcommerce/framer-next-pages": "3.2.4",
|
|
23
|
+
"@graphcommerce/framer-scroller": "2.1.25",
|
|
24
24
|
"@graphcommerce/framer-utils": "3.1.4",
|
|
25
25
|
"@graphcommerce/image": "3.1.7",
|
|
26
|
-
"
|
|
26
|
+
"cookie": "^0.5.0",
|
|
27
|
+
"react-is": "^18.2.0",
|
|
27
28
|
"react-schemaorg": "^2.0.0",
|
|
28
29
|
"schema-dts": "^1.1.0"
|
|
29
30
|
},
|
|
@@ -38,12 +39,13 @@
|
|
|
38
39
|
"react-dom": "^18.0.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"@graphcommerce/eslint-config-pwa": "^4.1.
|
|
42
|
+
"@graphcommerce/eslint-config-pwa": "^4.1.9",
|
|
42
43
|
"@graphcommerce/prettier-config-pwa": "^4.0.6",
|
|
43
|
-
"@graphcommerce/typescript-config-pwa": "^4.0.
|
|
44
|
+
"@graphcommerce/typescript-config-pwa": "^4.0.4",
|
|
44
45
|
"@playwright/test": "^1.21.1",
|
|
46
|
+
"@types/cookie": "^0.5.1",
|
|
45
47
|
"@types/react-is": "^17.0.3",
|
|
46
48
|
"type-fest": "^2.12.2",
|
|
47
|
-
"typescript": "4.7.
|
|
49
|
+
"typescript": "4.7.4"
|
|
48
50
|
}
|
|
49
51
|
}
|
package/utils/cookie.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { serialize, parse, CookieSerializeOptions } from 'cookie'
|
|
2
|
+
|
|
3
|
+
/** Read a cookie */
|
|
4
|
+
export function cookie(name: string): string | undefined
|
|
5
|
+
/** Set a cookie */
|
|
6
|
+
export function cookie(name: string, value: string, options?: CookieSerializeOptions): void
|
|
7
|
+
/** Delete a cookie */
|
|
8
|
+
export function cookie(name: string, value: null): void
|
|
9
|
+
/** Function to handle the three different cases */
|
|
10
|
+
export function cookie(name: string, value?: string | null, options?: CookieSerializeOptions) {
|
|
11
|
+
if (typeof window === 'undefined') {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Read a cookie
|
|
16
|
+
if (typeof value === 'undefined') return parse(document.cookie)[name]
|
|
17
|
+
|
|
18
|
+
// Set a cookie
|
|
19
|
+
if (typeof value === 'string') {
|
|
20
|
+
const serialized = serialize(name, value, { path: '/', maxAge: 31536000, ...options })
|
|
21
|
+
document.cookie = serialized
|
|
22
|
+
return undefined
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Delete a cookie
|
|
26
|
+
if (value === null) {
|
|
27
|
+
const serialized = serialize(name, '', { path: '/', maxAge: 0 })
|
|
28
|
+
document.cookie = serialized
|
|
29
|
+
return undefined
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return undefined
|
|
33
|
+
}
|