@graphcommerce/magento-category 8.1.0-canary.8 → 9.0.0-canary.54
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/CHANGELOG.md +105 -0
- package/components/CategoryBreadcrumb/CategoryBreadcrumb.tsx +3 -0
- package/components/CategoryBreadcrumb/CategoryBreadcrumbs.tsx +40 -0
- package/components/CategoryBreadcrumb/categoryToBreadcrumbs.ts +30 -0
- package/components/CategoryBreadcrumb/index.ts +3 -1
- package/components/CategoryChildren/CategoryChildren.graphql +1 -5
- package/components/CategoryChildren/CategoryChildren.tsx +57 -59
- package/components/CategoryChildren/CategorySiblings.graphql +7 -0
- package/components/CategoryDescription/CategoryDescription.graphql +1 -1
- package/components/CategoryDescription/CategoryDescription.tsx +35 -11
- package/components/CategoryHeroNav/CategoryHeroNav.graphql +1 -0
- package/components/CategoryHeroNav/CategoryHeroNav.tsx +4 -4
- package/components/CategoryHeroNav/CategoryHeroNavTitle.tsx +5 -7
- package/index.ts +8 -0
- package/package.json +10 -10
- package/queries/CategoryPathFragment.graphql +1 -1
- package/queries/NavigationItem.graphql +2 -1
- package/queries/getCategoryStaticPaths.ts +2 -1
- package/utils/appendSiblingsAsChildren.ts +23 -0
- package/utils/findParentBreadcrumbItem.ts +12 -0
- package/utils/useCategoryTree.tsx +71 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,110 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 9.0.0-canary.54
|
|
4
|
+
|
|
5
|
+
## 8.1.0-canary.53
|
|
6
|
+
|
|
7
|
+
## 8.1.0-canary.52
|
|
8
|
+
|
|
9
|
+
## 8.1.0-canary.51
|
|
10
|
+
|
|
11
|
+
## 8.1.0-canary.50
|
|
12
|
+
|
|
13
|
+
## 8.1.0-canary.49
|
|
14
|
+
|
|
15
|
+
## 8.1.0-canary.48
|
|
16
|
+
|
|
17
|
+
## 8.1.0-canary.47
|
|
18
|
+
|
|
19
|
+
## 8.1.0-canary.46
|
|
20
|
+
|
|
21
|
+
## 8.1.0-canary.45
|
|
22
|
+
|
|
23
|
+
## 8.1.0-canary.44
|
|
24
|
+
|
|
25
|
+
## 8.1.0-canary.43
|
|
26
|
+
|
|
27
|
+
## 8.1.0-canary.42
|
|
28
|
+
|
|
29
|
+
## 8.1.0-canary.41
|
|
30
|
+
|
|
31
|
+
## 8.1.0-canary.40
|
|
32
|
+
|
|
33
|
+
## 8.1.0-canary.39
|
|
34
|
+
|
|
35
|
+
## 8.1.0-canary.38
|
|
36
|
+
|
|
37
|
+
## 8.1.0-canary.37
|
|
38
|
+
|
|
39
|
+
## 8.1.0-canary.36
|
|
40
|
+
|
|
41
|
+
## 8.1.0-canary.35
|
|
42
|
+
|
|
43
|
+
## 8.1.0-canary.34
|
|
44
|
+
|
|
45
|
+
## 8.1.0-canary.33
|
|
46
|
+
|
|
47
|
+
## 8.1.0-canary.32
|
|
48
|
+
|
|
49
|
+
## 8.1.0-canary.31
|
|
50
|
+
|
|
51
|
+
## 8.1.0-canary.30
|
|
52
|
+
|
|
53
|
+
## 8.1.0-canary.29
|
|
54
|
+
|
|
55
|
+
## 8.1.0-canary.28
|
|
56
|
+
|
|
57
|
+
## 8.1.0-canary.27
|
|
58
|
+
|
|
59
|
+
### Minor Changes
|
|
60
|
+
|
|
61
|
+
- [#2273](https://github.com/graphcommerce-org/graphcommerce/pull/2273) [`77955c5`](https://github.com/graphcommerce-org/graphcommerce/commit/77955c56ac8633ab1c5e0f3ddb25e3a87236e2bb) - Improve Breadcrumbs on Category and Product pages
|
|
62
|
+
([@Jessevdpoel](https://github.com/Jessevdpoel))
|
|
63
|
+
|
|
64
|
+
- [#2273](https://github.com/graphcommerce-org/graphcommerce/pull/2273) [`aa56540`](https://github.com/graphcommerce-org/graphcommerce/commit/aa56540af91638c09e4c7a0a1648aaa6c5fa0afb) - If a category has no children, the sibling links will be shown on the category page.
|
|
65
|
+
([@Jessevdpoel](https://github.com/Jessevdpoel))
|
|
66
|
+
|
|
67
|
+
## 8.1.0-canary.26
|
|
68
|
+
|
|
69
|
+
## 8.1.0-canary.25
|
|
70
|
+
|
|
71
|
+
## 8.1.0-canary.24
|
|
72
|
+
|
|
73
|
+
## 8.1.0-canary.23
|
|
74
|
+
|
|
75
|
+
## 8.1.0-canary.22
|
|
76
|
+
|
|
77
|
+
## 8.1.0-canary.21
|
|
78
|
+
|
|
79
|
+
## 8.1.0-canary.20
|
|
80
|
+
|
|
81
|
+
## 8.1.0-canary.19
|
|
82
|
+
|
|
83
|
+
## 8.1.0-canary.18
|
|
84
|
+
|
|
85
|
+
## 8.1.0-canary.17
|
|
86
|
+
|
|
87
|
+
## 8.1.0-canary.16
|
|
88
|
+
|
|
89
|
+
## 8.1.0-canary.15
|
|
90
|
+
|
|
91
|
+
### Patch Changes
|
|
92
|
+
|
|
93
|
+
- [#2267](https://github.com/graphcommerce-org/graphcommerce/pull/2267) [`9d5fd11`](https://github.com/graphcommerce-org/graphcommerce/commit/9d5fd11c7130612e80523608ab442976f3f5ddc5) - make the CategoryHeroNav fragment injectable and add image to the childeren
|
|
94
|
+
([@carlocarels90](https://github.com/carlocarels90))
|
|
95
|
+
|
|
96
|
+
## 8.1.0-canary.14
|
|
97
|
+
|
|
98
|
+
## 8.1.0-canary.13
|
|
99
|
+
|
|
100
|
+
## 8.1.0-canary.12
|
|
101
|
+
|
|
102
|
+
## 8.1.0-canary.11
|
|
103
|
+
|
|
104
|
+
## 8.1.0-canary.10
|
|
105
|
+
|
|
106
|
+
## 8.1.0-canary.9
|
|
107
|
+
|
|
3
108
|
## 8.1.0-canary.8
|
|
4
109
|
|
|
5
110
|
## 8.1.0-canary.7
|
|
@@ -5,6 +5,9 @@ import { CategoryBreadcrumbFragment } from './CategoryBreadcrumb.gql'
|
|
|
5
5
|
|
|
6
6
|
type CategoryPageBreadcrumbsProps = CategoryBreadcrumbFragment & Omit<BreadcrumbsProps, 'children'>
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Please use CategoryBreadcrumbs
|
|
10
|
+
*/
|
|
8
11
|
export function CategoryBreadcrumb(props: CategoryPageBreadcrumbsProps) {
|
|
9
12
|
const { breadcrumbs, name, ...breadcrumbsProps } = props
|
|
10
13
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Breadcrumbs,
|
|
3
|
+
BreadcrumbsJsonLd,
|
|
4
|
+
BreadcrumbsProps,
|
|
5
|
+
jsonLdBreadcrumb,
|
|
6
|
+
} from '@graphcommerce/next-ui'
|
|
7
|
+
import { useRouter } from 'next/router'
|
|
8
|
+
import type { BreadcrumbList } from 'schema-dts'
|
|
9
|
+
import { CategoryBreadcrumbFragment } from './CategoryBreadcrumb.gql'
|
|
10
|
+
import { categoryToBreadcrumbs } from './categoryToBreadcrumbs'
|
|
11
|
+
|
|
12
|
+
export type CategoryBreadcrumbsProps = Omit<BreadcrumbsProps, 'breadcrumbs'> & {
|
|
13
|
+
category?: CategoryBreadcrumbFragment
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function CategoryBreadcrumbs(props: CategoryBreadcrumbsProps) {
|
|
17
|
+
const { category, sx, ...breadcrumbsProps } = props
|
|
18
|
+
const router = useRouter()
|
|
19
|
+
|
|
20
|
+
if (!category) return null
|
|
21
|
+
|
|
22
|
+
const breadcrumbs = categoryToBreadcrumbs(category)
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<BreadcrumbsJsonLd<BreadcrumbList>
|
|
27
|
+
breadcrumbs={breadcrumbs}
|
|
28
|
+
render={(bc) => ({
|
|
29
|
+
'@context': 'https://schema.org',
|
|
30
|
+
...jsonLdBreadcrumb(bc, router),
|
|
31
|
+
})}
|
|
32
|
+
/>
|
|
33
|
+
<Breadcrumbs
|
|
34
|
+
breadcrumbs={breadcrumbs}
|
|
35
|
+
{...breadcrumbsProps}
|
|
36
|
+
sx={[...(Array.isArray(sx) ? sx : [sx])]}
|
|
37
|
+
/>
|
|
38
|
+
</>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { productListLink } from '@graphcommerce/magento-product'
|
|
2
|
+
import { BreadcrumbsType, filterNonNullableKeys } from '@graphcommerce/next-ui'
|
|
3
|
+
import { CategoryBreadcrumbFragment } from './CategoryBreadcrumb.gql'
|
|
4
|
+
|
|
5
|
+
export function categoryToBreadcrumbs(
|
|
6
|
+
category: CategoryBreadcrumbFragment,
|
|
7
|
+
): BreadcrumbsType['breadcrumbs'] {
|
|
8
|
+
if (!category.url_path || !category.name) return []
|
|
9
|
+
|
|
10
|
+
return [
|
|
11
|
+
...filterNonNullableKeys(category.breadcrumbs, [
|
|
12
|
+
'category_level',
|
|
13
|
+
'category_name',
|
|
14
|
+
'category_url_path',
|
|
15
|
+
])
|
|
16
|
+
.sort((a, b) => a.category_level - b.category_level)
|
|
17
|
+
.map(({ category_url_path, category_name }) => ({
|
|
18
|
+
href: productListLink({ url: category_url_path, filters: {}, sort: {} }),
|
|
19
|
+
name: category_name,
|
|
20
|
+
})),
|
|
21
|
+
{
|
|
22
|
+
href: productListLink({
|
|
23
|
+
url: category.url_path,
|
|
24
|
+
filters: {},
|
|
25
|
+
sort: {},
|
|
26
|
+
}),
|
|
27
|
+
name: category.name,
|
|
28
|
+
},
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Scroller, ScrollerProvider } from '@graphcommerce/framer-scroller'
|
|
2
|
-
import { ProductListParams } from '@graphcommerce/magento-product'
|
|
3
|
-
import {
|
|
4
|
-
import { extendableComponent } from '@graphcommerce/next-ui'
|
|
2
|
+
import { ProductListParams, productListLink } from '@graphcommerce/magento-product'
|
|
3
|
+
import { extendableComponent, filterNonNullableKeys } from '@graphcommerce/next-ui'
|
|
5
4
|
import { Box, Link, SxProps, Theme } from '@mui/material'
|
|
6
5
|
import { CategoryChildrenFragment } from './CategoryChildren.gql'
|
|
7
6
|
|
|
@@ -17,75 +16,74 @@ const { classes } = extendableComponent(name, parts)
|
|
|
17
16
|
export function CategoryChildren(props: CategoryChildrenProps) {
|
|
18
17
|
const { children, params, sx = [] } = props
|
|
19
18
|
|
|
20
|
-
const
|
|
19
|
+
const childItems = filterNonNullableKeys(children, ['url_path', 'name', 'include_in_menu']).map(
|
|
20
|
+
(category) => ({
|
|
21
|
+
name: category.name,
|
|
22
|
+
href: productListLink({
|
|
23
|
+
...params,
|
|
24
|
+
currentPage: 0,
|
|
25
|
+
url: category.url_path,
|
|
26
|
+
filters: { category_uid: { eq: category.uid } },
|
|
27
|
+
}),
|
|
28
|
+
active: params.url === category.url_path,
|
|
29
|
+
}),
|
|
30
|
+
)
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
const hasNavigatableChildren = childItems.some((cat) => !cat.active)
|
|
33
|
+
if (!hasNavigatableChildren) return null
|
|
23
34
|
|
|
24
35
|
return (
|
|
25
36
|
<ScrollerProvider scrollSnapAlign='none'>
|
|
26
37
|
<Box
|
|
27
38
|
className={classes.container}
|
|
28
|
-
sx={[
|
|
29
|
-
(theme) => ({
|
|
30
|
-
display: 'flex',
|
|
31
|
-
justifyContent: 'center',
|
|
32
|
-
marginBottom: theme.spacings.sm,
|
|
33
|
-
}),
|
|
34
|
-
...(Array.isArray(sx) ? sx : [sx]),
|
|
35
|
-
]}
|
|
39
|
+
sx={[{ display: 'flex' }, ...(Array.isArray(sx) ? sx : [sx])]}
|
|
36
40
|
>
|
|
37
41
|
<Scroller
|
|
38
42
|
className={classes.scroller}
|
|
39
43
|
hideScrollbar
|
|
40
|
-
sx={
|
|
44
|
+
sx={(theme) => ({
|
|
45
|
+
gridAutoColumns: `max-content`,
|
|
46
|
+
columnGap: theme.spacings.sm,
|
|
47
|
+
marginBottom: '-8px',
|
|
48
|
+
})}
|
|
41
49
|
>
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
50
|
+
{childItems.map((category) => (
|
|
51
|
+
<Link
|
|
52
|
+
key={category.href}
|
|
53
|
+
underline='none'
|
|
54
|
+
color='inherit'
|
|
55
|
+
href={category.href}
|
|
56
|
+
className={classes.link}
|
|
57
|
+
sx={(theme) => ({
|
|
58
|
+
whiteSpace: 'nowrap',
|
|
59
|
+
display: 'block',
|
|
60
|
+
typography: 'h6',
|
|
61
|
+
position: 'relative',
|
|
62
|
+
paddingBottom: '8px',
|
|
63
|
+
'&:before': {
|
|
64
|
+
content: '""',
|
|
65
|
+
width: 40,
|
|
66
|
+
height: 2,
|
|
67
|
+
background: theme.palette.primary.main,
|
|
68
|
+
position: 'absolute',
|
|
69
|
+
left: 0,
|
|
70
|
+
right: 0,
|
|
71
|
+
margin: '0 auto',
|
|
72
|
+
opacity: category.active ? 1 : 0,
|
|
73
|
+
transition: 'opacity .2s ease, bottom .2s ease',
|
|
74
|
+
bottom: category.active ? 5 : 0,
|
|
75
|
+
},
|
|
76
|
+
'&:hover': {
|
|
64
77
|
'&:before': {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
height: 2,
|
|
68
|
-
background: theme.palette.primary.main,
|
|
69
|
-
position: 'absolute',
|
|
70
|
-
left: 0,
|
|
71
|
-
right: 0,
|
|
72
|
-
margin: '0 auto',
|
|
73
|
-
opacity: 0,
|
|
74
|
-
transition: 'opacity .2s ease, bottom .2s ease',
|
|
75
|
-
bottom: 0,
|
|
78
|
+
opacity: 1,
|
|
79
|
+
bottom: 5,
|
|
76
80
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
})}
|
|
84
|
-
>
|
|
85
|
-
{cat.name}
|
|
86
|
-
</Link>
|
|
87
|
-
)
|
|
88
|
-
})}
|
|
81
|
+
},
|
|
82
|
+
})}
|
|
83
|
+
>
|
|
84
|
+
{category.name}
|
|
85
|
+
</Link>
|
|
86
|
+
))}
|
|
89
87
|
</Scroller>
|
|
90
88
|
</Box>
|
|
91
89
|
</ScrollerProvider>
|
|
@@ -2,16 +2,32 @@ import { extendableComponent } from '@graphcommerce/next-ui'
|
|
|
2
2
|
import { Box, SxProps, Theme } from '@mui/material'
|
|
3
3
|
import { CategoryDescriptionFragment } from './CategoryDescription.gql'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
type StateProps = {
|
|
6
|
+
textAlignSm?: 'start' | 'center'
|
|
7
|
+
textAlignMd?: 'start' | 'center'
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
-
const cmpName = 'CategoryDescription' as const
|
|
9
|
+
const componentName = 'CategoryDescription' as const
|
|
10
10
|
const parts = ['root'] as const
|
|
11
|
-
const {
|
|
11
|
+
const { withState } = extendableComponent<StateProps, typeof componentName, typeof parts>(
|
|
12
|
+
componentName,
|
|
13
|
+
parts,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
export type CategoryDescriptionProps = Omit<CategoryDescriptionFragment, 'uid'> &
|
|
17
|
+
StateProps & { sx?: SxProps<Theme> }
|
|
12
18
|
|
|
13
19
|
export function CategoryDescription(props: CategoryDescriptionProps) {
|
|
14
|
-
const {
|
|
20
|
+
const {
|
|
21
|
+
name,
|
|
22
|
+
description,
|
|
23
|
+
display_mode,
|
|
24
|
+
sx = [],
|
|
25
|
+
textAlignSm = 'center',
|
|
26
|
+
textAlignMd = 'center',
|
|
27
|
+
...divProps
|
|
28
|
+
} = props
|
|
29
|
+
|
|
30
|
+
const classes = withState({ textAlignSm, textAlignMd })
|
|
15
31
|
|
|
16
32
|
return description ? (
|
|
17
33
|
// eslint-disable-next-line react/no-danger
|
|
@@ -21,12 +37,20 @@ export function CategoryDescription(props: CategoryDescriptionProps) {
|
|
|
21
37
|
dangerouslySetInnerHTML={{ __html: description }}
|
|
22
38
|
sx={[
|
|
23
39
|
(theme) => ({
|
|
24
|
-
gridArea: 'description',
|
|
25
|
-
margin: `0 auto ${theme.spacings.sm}`,
|
|
26
|
-
padding: `0 ${theme.page.horizontal}`,
|
|
27
|
-
textAlign: 'center',
|
|
28
|
-
maxWidth: { md: '900px' },
|
|
29
40
|
typography: 'subtitle1',
|
|
41
|
+
[theme.breakpoints.down('sm')]: {
|
|
42
|
+
textAlign: textAlignSm,
|
|
43
|
+
'&.textAlignSmCenter': {
|
|
44
|
+
mx: 'auto',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
[theme.breakpoints.up('md')]: {
|
|
48
|
+
maxWidth: '900px',
|
|
49
|
+
textAlign: textAlignMd,
|
|
50
|
+
'&.textAlignMdCenter': {
|
|
51
|
+
mx: 'auto',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
30
54
|
}),
|
|
31
55
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
32
56
|
]}
|
|
@@ -14,8 +14,8 @@ const cmpName = 'CategoryHeroNav' as const
|
|
|
14
14
|
const parts = ['wrapper', 'categories', 'title', 'placeholder'] as const
|
|
15
15
|
const { classes } = extendableComponent(cmpName, parts)
|
|
16
16
|
|
|
17
|
-
export
|
|
18
|
-
|
|
17
|
+
export const CategoryHeroNav = React.memo<CategoryHeroNavProps>(
|
|
18
|
+
({ children, title, asset, sx = [] }) => (
|
|
19
19
|
<Row
|
|
20
20
|
className={classes.wrapper}
|
|
21
21
|
maxWidth={false}
|
|
@@ -133,5 +133,5 @@ export function CategoryHeroNav({ children, title, asset, sx = [] }: CategoryHer
|
|
|
133
133
|
<Box>{asset}</Box>
|
|
134
134
|
</Box>
|
|
135
135
|
</Row>
|
|
136
|
-
)
|
|
137
|
-
|
|
136
|
+
),
|
|
137
|
+
)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { LayoutTitle } from '@graphcommerce/next-ui'
|
|
2
2
|
import { SxProps, Theme } from '@mui/material'
|
|
3
|
-
import
|
|
3
|
+
import { memo } from 'react'
|
|
4
4
|
|
|
5
5
|
type CategoryHeroNavTitleProps = {
|
|
6
6
|
children: React.ReactNode
|
|
7
7
|
sx?: SxProps<Theme>
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export const CategoryHeroNavTitle = memo<CategoryHeroNavTitleProps>((props) => {
|
|
11
11
|
const { children, sx = [] } = props
|
|
12
12
|
|
|
13
13
|
return (
|
|
@@ -15,11 +15,9 @@ export function CategoryHeroNavTitle(props: CategoryHeroNavTitleProps) {
|
|
|
15
15
|
variant='h1'
|
|
16
16
|
sx={[
|
|
17
17
|
(theme) => ({
|
|
18
|
-
justifyContent: 'center',
|
|
19
18
|
[theme.breakpoints.up('md')]: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
justifyContent: 'end',
|
|
19
|
+
m: 0,
|
|
20
|
+
justifyContent: 'start',
|
|
23
21
|
},
|
|
24
22
|
}),
|
|
25
23
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
@@ -28,4 +26,4 @@ export function CategoryHeroNavTitle(props: CategoryHeroNavTitleProps) {
|
|
|
28
26
|
{children}
|
|
29
27
|
</LayoutTitle>
|
|
30
28
|
)
|
|
31
|
-
}
|
|
29
|
+
})
|
package/index.ts
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
export * from './components/CategoryChildren/CategoryChildren'
|
|
2
|
+
export * from './components/CategoryChildren/CategoryChildren.gql'
|
|
3
|
+
export * from './components/CategoryChildren/CategorySiblings.gql'
|
|
2
4
|
export * from './components/CategoryDescription/CategoryDescription'
|
|
3
5
|
export * from './components/CategoryHeroNav/CategoryHeroNav'
|
|
4
6
|
export * from './components/CategoryHeroNav/CategoryHeroNavTitle'
|
|
5
7
|
export * from './components/CategoryMeta/CategoryMeta'
|
|
8
|
+
export * from './utils/appendSiblingsAsChildren'
|
|
6
9
|
export * from './utils/magentoMenuToNavigation'
|
|
10
|
+
export * from './utils/findParentBreadcrumbItem'
|
|
7
11
|
export * from './queries/getCategoryStaticPaths'
|
|
8
12
|
export * from './components/CategoryBreadcrumb'
|
|
13
|
+
export * from './queries/CategoryQueryFragment.gql'
|
|
14
|
+
export * from './queries/MenuQueryFragment.gql'
|
|
15
|
+
export * from './queries/NavigationItem.gql'
|
|
16
|
+
export * from './utils/useCategoryTree'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/magento-category",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "9.0.0-canary.54",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@graphcommerce/eslint-config-pwa": "^
|
|
16
|
-
"@graphcommerce/framer-scroller": "^
|
|
17
|
-
"@graphcommerce/graphql": "^
|
|
18
|
-
"@graphcommerce/image": "^
|
|
19
|
-
"@graphcommerce/magento-product": "^
|
|
20
|
-
"@graphcommerce/magento-store": "^
|
|
21
|
-
"@graphcommerce/next-ui": "^
|
|
22
|
-
"@graphcommerce/prettier-config-pwa": "^
|
|
23
|
-
"@graphcommerce/typescript-config-pwa": "^
|
|
15
|
+
"@graphcommerce/eslint-config-pwa": "^9.0.0-canary.54",
|
|
16
|
+
"@graphcommerce/framer-scroller": "^9.0.0-canary.54",
|
|
17
|
+
"@graphcommerce/graphql": "^9.0.0-canary.54",
|
|
18
|
+
"@graphcommerce/image": "^9.0.0-canary.54",
|
|
19
|
+
"@graphcommerce/magento-product": "^9.0.0-canary.54",
|
|
20
|
+
"@graphcommerce/magento-store": "^9.0.0-canary.54",
|
|
21
|
+
"@graphcommerce/next-ui": "^9.0.0-canary.54",
|
|
22
|
+
"@graphcommerce/prettier-config-pwa": "^9.0.0-canary.54",
|
|
23
|
+
"@graphcommerce/typescript-config-pwa": "^9.0.0-canary.54",
|
|
24
24
|
"@lingui/core": "^4.2.1",
|
|
25
25
|
"@lingui/macro": "^4.2.1",
|
|
26
26
|
"@lingui/react": "^4.2.1",
|
|
@@ -10,6 +10,7 @@ type StaticPathsResult = GetStaticPathsResult<{ url: string[] }>
|
|
|
10
10
|
const getCategoryStaticPaths = async (
|
|
11
11
|
client: ApolloClient<NormalizedCacheObject>,
|
|
12
12
|
locale: string,
|
|
13
|
+
options: { limit?: boolean } = { limit: import.meta.graphCommerce.limitSsg || false },
|
|
13
14
|
) => {
|
|
14
15
|
const { data } = await client.query({
|
|
15
16
|
query: GetCategoryStaticPathsDocument,
|
|
@@ -24,7 +25,7 @@ const getCategoryStaticPaths = async (
|
|
|
24
25
|
}
|
|
25
26
|
data.categories?.items?.forEach(add)
|
|
26
27
|
|
|
27
|
-
return
|
|
28
|
+
return options.limit ? paths.slice(0, 1) : paths
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export { getCategoryStaticPaths }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ApolloClient } from '@graphcommerce/graphql'
|
|
2
|
+
import { CategoryBreadcrumbFragment } from '../components/CategoryBreadcrumb'
|
|
3
|
+
import { CategoryChildrenFragment } from '../components/CategoryChildren/CategoryChildren.gql'
|
|
4
|
+
import { CategorySiblingsDocument } from '../components/CategoryChildren/CategorySiblings.gql'
|
|
5
|
+
import { findParentBreadcrumbItem } from './findParentBreadcrumbItem'
|
|
6
|
+
|
|
7
|
+
export function appendSiblingsAsChildren(
|
|
8
|
+
categoryPromise: Promise<
|
|
9
|
+
(CategoryBreadcrumbFragment & CategoryChildrenFragment) | null | undefined
|
|
10
|
+
>,
|
|
11
|
+
client: ApolloClient<object>,
|
|
12
|
+
) {
|
|
13
|
+
return categoryPromise.then(async (cat) => {
|
|
14
|
+
const parentUid = findParentBreadcrumbItem(cat)?.category_uid
|
|
15
|
+
if (!cat || (cat?.children?.length ?? 0) > 0 || !parentUid) return
|
|
16
|
+
|
|
17
|
+
const res = await client.query({
|
|
18
|
+
query: CategorySiblingsDocument,
|
|
19
|
+
variables: { parentUid },
|
|
20
|
+
})
|
|
21
|
+
cat.children = res.data.categories?.items
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { filterNonNullableKeys } from '@graphcommerce/next-ui'
|
|
2
|
+
import { CategoryBreadcrumbFragment } from '../components/CategoryBreadcrumb'
|
|
3
|
+
|
|
4
|
+
export function findParentBreadcrumbItem(
|
|
5
|
+
category: CategoryBreadcrumbFragment | null | undefined,
|
|
6
|
+
): NonNullable<CategoryBreadcrumbFragment['breadcrumbs']>[number] | undefined {
|
|
7
|
+
const parentCategoryPath = category?.url_path?.split('/').slice(0, -1).join('/')
|
|
8
|
+
|
|
9
|
+
return filterNonNullableKeys(category?.breadcrumbs, ['category_url_path']).find(
|
|
10
|
+
(c) => parentCategoryPath === c.category_url_path,
|
|
11
|
+
)
|
|
12
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ProductListParams } from '@graphcommerce/magento-product'
|
|
2
|
+
import { filterNonNullableKeys } from '@graphcommerce/next-ui'
|
|
3
|
+
import { CategoryBreadcrumbFragment } from '../components/CategoryBreadcrumb'
|
|
4
|
+
import { CategoryChildrenFragment } from '../components/CategoryChildren/CategoryChildren.gql'
|
|
5
|
+
|
|
6
|
+
export type UseCategoryTreeProps = {
|
|
7
|
+
category?: CategoryChildrenFragment & CategoryBreadcrumbFragment
|
|
8
|
+
params?: ProductListParams
|
|
9
|
+
hideBreadcrumbs?: boolean | null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type CategoryTreeItem = {
|
|
13
|
+
title: React.ReactNode
|
|
14
|
+
value: string
|
|
15
|
+
selected: boolean
|
|
16
|
+
isBack?: boolean
|
|
17
|
+
indent: number
|
|
18
|
+
uid: string
|
|
19
|
+
count: null | number
|
|
20
|
+
visible?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useCategoryTree(props: UseCategoryTreeProps): CategoryTreeItem[] | null {
|
|
24
|
+
const { category, params, hideBreadcrumbs } = props
|
|
25
|
+
|
|
26
|
+
if (!params || !category || !category.url_path || !category.name) return null
|
|
27
|
+
|
|
28
|
+
const parents = filterNonNullableKeys(category?.breadcrumbs, [
|
|
29
|
+
'category_name',
|
|
30
|
+
'category_level',
|
|
31
|
+
'category_url_path',
|
|
32
|
+
]).map<CategoryTreeItem>((breadcrumb) => ({
|
|
33
|
+
title: breadcrumb.category_name,
|
|
34
|
+
value: breadcrumb.category_url_path,
|
|
35
|
+
indent: 0,
|
|
36
|
+
isBack: true,
|
|
37
|
+
selected: params?.url === breadcrumb.category_url_path,
|
|
38
|
+
uid: breadcrumb.category_uid,
|
|
39
|
+
count: null,
|
|
40
|
+
}))
|
|
41
|
+
|
|
42
|
+
let children = filterNonNullableKeys(category.children, [
|
|
43
|
+
'url_path',
|
|
44
|
+
'name',
|
|
45
|
+
'include_in_menu',
|
|
46
|
+
]).map<CategoryTreeItem>((categoryItem) => ({
|
|
47
|
+
title: <>{`${`${categoryItem.name}`}`}</>,
|
|
48
|
+
value: categoryItem.url_path,
|
|
49
|
+
indent: hideBreadcrumbs ? 0 : 2,
|
|
50
|
+
isBack: false,
|
|
51
|
+
selected: params.url === categoryItem.url_path,
|
|
52
|
+
uid: categoryItem.uid,
|
|
53
|
+
count: null,
|
|
54
|
+
}))
|
|
55
|
+
|
|
56
|
+
if (!children.find((item) => item.value === category.url_path) && !hideBreadcrumbs)
|
|
57
|
+
children.push({
|
|
58
|
+
title: <> {category.name}</>,
|
|
59
|
+
value: category.url_path,
|
|
60
|
+
indent: 1,
|
|
61
|
+
isBack: false,
|
|
62
|
+
selected: true,
|
|
63
|
+
uid: category.uid,
|
|
64
|
+
count: null,
|
|
65
|
+
})
|
|
66
|
+
else if (!hideBreadcrumbs) children = children.map((child) => ({ ...child, indent: 2 }))
|
|
67
|
+
|
|
68
|
+
if (hideBreadcrumbs) return children.sort((a, b) => a.indent - b.indent)
|
|
69
|
+
|
|
70
|
+
return [...parents, ...children].sort((a, b) => a.indent - b.indent)
|
|
71
|
+
}
|