@graphcommerce/magento-product 3.8.13 → 4.0.2
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 +422 -315
- package/components/ProductAddToCart/ProductAddToCart.tsx +32 -30
- package/components/ProductListCount/ProductListCount.tsx +46 -0
- package/components/ProductListFilters/FilterCheckboxType.tsx +6 -13
- package/components/ProductListFilters/FilterEqualType.tsx +107 -102
- package/components/ProductListFilters/FilterRangeType.tsx +32 -40
- package/components/ProductListFilters/ProductListFilters.graphql +2 -0
- package/components/ProductListFilters/{index.tsx → ProductListFilters.tsx} +0 -1
- package/components/ProductListFiltersContainer/index.tsx +104 -91
- package/components/ProductListItem/index.tsx +186 -146
- package/components/ProductListItems/ProductListItemsBase.tsx +22 -32
- package/components/ProductListItems/getFilterTypes.ts +1 -1
- package/components/ProductListLink/ProductListLink.tsx +2 -2
- package/components/ProductListPagination/index.tsx +2 -2
- package/components/ProductListPrice/index.tsx +21 -21
- package/components/ProductListSort/index.tsx +15 -13
- package/components/ProductPageDescription/index.tsx +38 -37
- package/components/ProductShortDescription/index.tsx +7 -17
- package/components/ProductSidebarDelivery/index.tsx +48 -44
- package/components/ProductSpecs/index.tsx +32 -41
- package/components/ProductStaticPaths/getProductStaticPaths.ts +1 -1
- package/components/ProductWeight/index.tsx +1 -1
- package/components/index.ts +16 -26
- package/package.json +22 -26
- package/components/ProductListCount/index.tsx +0 -55
|
@@ -3,33 +3,24 @@ import { ApolloCartErrorAlert, useFormGqlMutationCart } from '@graphcommerce/mag
|
|
|
3
3
|
import { Money, MoneyProps } from '@graphcommerce/magento-store'
|
|
4
4
|
import {
|
|
5
5
|
Button,
|
|
6
|
-
ButtonProps,
|
|
7
6
|
MessageSnackbar,
|
|
8
7
|
TextInputNumber,
|
|
9
8
|
iconChevronRight,
|
|
10
|
-
|
|
9
|
+
SvgIcon,
|
|
10
|
+
extendableComponent,
|
|
11
11
|
} from '@graphcommerce/next-ui'
|
|
12
|
-
import {
|
|
12
|
+
import { Trans } from '@lingui/macro'
|
|
13
|
+
import { Divider, Typography, ButtonProps, Box } from '@mui/material'
|
|
13
14
|
import PageLink from 'next/link'
|
|
14
15
|
import React from 'react'
|
|
15
16
|
import { ProductAddToCartDocument, ProductAddToCartMutationVariables } from './ProductAddToCart.gql'
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
price: {
|
|
24
|
-
fontWeight: theme.typography.fontWeightBold,
|
|
25
|
-
margin: `${theme.spacings.sm} 0`,
|
|
26
|
-
},
|
|
27
|
-
divider: {
|
|
28
|
-
margin: `${theme.spacings.xs} 0`,
|
|
29
|
-
},
|
|
30
|
-
}),
|
|
31
|
-
{ name: 'AddToCart' },
|
|
32
|
-
)
|
|
18
|
+
const { classes, selectors } = extendableComponent('ProductAddToCart', [
|
|
19
|
+
'root',
|
|
20
|
+
'button',
|
|
21
|
+
'price',
|
|
22
|
+
'divider',
|
|
23
|
+
] as const)
|
|
33
24
|
|
|
34
25
|
export type AddToCartProps = React.ComponentProps<typeof ProductAddToCart>
|
|
35
26
|
|
|
@@ -41,7 +32,7 @@ export default function ProductAddToCart(
|
|
|
41
32
|
children?: React.ReactNode
|
|
42
33
|
} & Omit<ButtonProps, 'type' | 'name'>,
|
|
43
34
|
) {
|
|
44
|
-
const { name, children, variables, price, ...buttonProps } = props
|
|
35
|
+
const { name, children, variables, price, sx, ...buttonProps } = props
|
|
45
36
|
|
|
46
37
|
const form = useFormGqlMutationCart(ProductAddToCartDocument, {
|
|
47
38
|
defaultValues: { ...variables },
|
|
@@ -49,13 +40,19 @@ export default function ProductAddToCart(
|
|
|
49
40
|
|
|
50
41
|
const { handleSubmit, formState, error, muiRegister, required } = form
|
|
51
42
|
const submitHandler = handleSubmit(() => {})
|
|
52
|
-
const classes = useStyles()
|
|
53
43
|
|
|
54
44
|
return (
|
|
55
|
-
<form onSubmit={submitHandler} noValidate>
|
|
56
|
-
<Divider className={classes.divider} />
|
|
45
|
+
<Box component='form' onSubmit={submitHandler} noValidate className={classes.root} sx={sx}>
|
|
46
|
+
<Divider className={classes.divider} sx={(theme) => ({ margin: `${theme.spacings.xs} 0` })} />
|
|
57
47
|
|
|
58
|
-
<Typography
|
|
48
|
+
<Typography
|
|
49
|
+
variant='h4'
|
|
50
|
+
className={classes.price}
|
|
51
|
+
sx={(theme) => ({
|
|
52
|
+
fontWeight: theme.typography.fontWeightBold,
|
|
53
|
+
margin: `${theme.spacings.sm} 0`,
|
|
54
|
+
})}
|
|
55
|
+
>
|
|
59
56
|
<Money {...price} />
|
|
60
57
|
</Typography>
|
|
61
58
|
|
|
@@ -72,11 +69,15 @@ export default function ProductAddToCart(
|
|
|
72
69
|
{children}
|
|
73
70
|
<Button
|
|
74
71
|
type='submit'
|
|
75
|
-
|
|
72
|
+
className={classes.button}
|
|
76
73
|
loading={formState.isSubmitting}
|
|
77
74
|
color='primary'
|
|
78
75
|
variant='pill'
|
|
79
76
|
size='large'
|
|
77
|
+
sx={(theme) => ({
|
|
78
|
+
marginTop: theme.spacings.sm,
|
|
79
|
+
width: '100%',
|
|
80
|
+
})}
|
|
80
81
|
{...buttonProps}
|
|
81
82
|
>
|
|
82
83
|
Add to Cart
|
|
@@ -93,17 +94,18 @@ export default function ProductAddToCart(
|
|
|
93
94
|
size='medium'
|
|
94
95
|
variant='pill'
|
|
95
96
|
color='secondary'
|
|
96
|
-
endIcon={<
|
|
97
|
+
endIcon={<SvgIcon src={iconChevronRight} />}
|
|
97
98
|
>
|
|
98
99
|
View shopping cart
|
|
99
100
|
</Button>
|
|
100
101
|
</PageLink>
|
|
101
102
|
}
|
|
102
103
|
>
|
|
103
|
-
|
|
104
|
-
<strong>{name}</strong
|
|
105
|
-
|
|
104
|
+
<Trans>
|
|
105
|
+
<strong>{name}</strong> has been added to your shopping cart!
|
|
106
|
+
</Trans>
|
|
106
107
|
</MessageSnackbar>
|
|
107
|
-
</
|
|
108
|
+
</Box>
|
|
108
109
|
)
|
|
109
110
|
}
|
|
111
|
+
ProductAddToCart.selectors = selectors
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { responsiveVal, extendableComponent } from '@graphcommerce/next-ui'
|
|
2
|
+
import { Trans } from '@lingui/macro'
|
|
3
|
+
import { Box, Divider, SxProps, Theme, Typography } from '@mui/material'
|
|
4
|
+
import { ProductListCountFragment } from './ProductListCount.gql'
|
|
5
|
+
|
|
6
|
+
const { classes, selectors } = extendableComponent('ProductListCount', [
|
|
7
|
+
'root',
|
|
8
|
+
'line',
|
|
9
|
+
'count',
|
|
10
|
+
] as const)
|
|
11
|
+
|
|
12
|
+
export type ProductCountProps = ProductListCountFragment & { sx?: SxProps<Theme> }
|
|
13
|
+
|
|
14
|
+
export function ProductListCount(props: ProductCountProps) {
|
|
15
|
+
const { total_count, sx = [] } = props
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Box
|
|
19
|
+
sx={[
|
|
20
|
+
(theme) => ({
|
|
21
|
+
display: 'grid',
|
|
22
|
+
gridAutoFlow: 'column',
|
|
23
|
+
gridTemplateColumns: '1fr max-content 1fr',
|
|
24
|
+
columnGap: theme.spacings.xs,
|
|
25
|
+
maxWidth: '100%',
|
|
26
|
+
width: responsiveVal(280, 650),
|
|
27
|
+
margin: '0 auto',
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
marginTop: theme.spacings.md,
|
|
30
|
+
marginBottom: theme.spacings.md,
|
|
31
|
+
}),
|
|
32
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
33
|
+
]}
|
|
34
|
+
className={classes.root}
|
|
35
|
+
>
|
|
36
|
+
<Divider component='div' className={classes.line} />
|
|
37
|
+
<Typography variant='body2' color='text.disabled' className={classes.count}>
|
|
38
|
+
{total_count === 0 && <Trans>no products</Trans>}
|
|
39
|
+
{total_count === 1 && <Trans>one product</Trans>}
|
|
40
|
+
{(total_count ?? 0) > 1 && <Trans>{total_count} products</Trans>}
|
|
41
|
+
</Typography>
|
|
42
|
+
<Divider component='div' className={classes.line} />
|
|
43
|
+
</Box>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
ProductListCount.selectors = selectors
|
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
import { cloneDeep } from '@
|
|
2
|
-
import {
|
|
3
|
-
import { Chip, ChipProps } from '@material
|
|
4
|
-
import clsx from 'clsx'
|
|
5
|
-
import React from 'react'
|
|
1
|
+
import { cloneDeep } from '@graphcommerce/graphql'
|
|
2
|
+
import { iconCancelAlt, SvgIcon } from '@graphcommerce/next-ui'
|
|
3
|
+
import { Chip, ChipProps, SxProps, Theme } from '@mui/material'
|
|
6
4
|
import { useProductListLinkReplace } from '../../hooks/useProductListLinkReplace'
|
|
7
5
|
import { useProductListParamsContext } from '../../hooks/useProductListParamsContext'
|
|
8
6
|
import ProductListLink from '../ProductListLink/ProductListLink'
|
|
9
7
|
import { FilterIn } from './FilterEqualType'
|
|
10
8
|
import { ProductListFiltersFragment } from './ProductListFilters.gql'
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
> &
|
|
15
|
-
Omit<ChipProps, 'selected'>
|
|
10
|
+
type Filter = NonNullable<NonNullable<ProductListFiltersFragment['aggregations']>[number]>
|
|
11
|
+
export type FilterCheckboxTypeProps = Filter & Omit<ChipProps, 'selected'> & { sx?: SxProps<Theme> }
|
|
16
12
|
|
|
17
13
|
export default function FilterCheckboxType(props: FilterCheckboxTypeProps) {
|
|
18
14
|
const { attribute_code, count, label, options, ...chipProps } = props
|
|
19
15
|
const { params } = useProductListParamsContext()
|
|
20
|
-
const classes = useChipMenuStyles(props)
|
|
21
16
|
const currentFilter = params.filters[attribute_code]
|
|
22
17
|
const replaceRoute = useProductListLinkReplace({ scroll: false })
|
|
23
18
|
|
|
@@ -37,7 +32,6 @@ export default function FilterCheckboxType(props: FilterCheckboxTypeProps) {
|
|
|
37
32
|
link={{ scroll: false, replace: true }}
|
|
38
33
|
>
|
|
39
34
|
<Chip
|
|
40
|
-
variant='outlined'
|
|
41
35
|
color={isActive ? undefined : 'default'}
|
|
42
36
|
onDelete={
|
|
43
37
|
isActive
|
|
@@ -51,11 +45,10 @@ export default function FilterCheckboxType(props: FilterCheckboxTypeProps) {
|
|
|
51
45
|
}
|
|
52
46
|
: undefined
|
|
53
47
|
}
|
|
54
|
-
deleteIcon={isActive ? <
|
|
48
|
+
deleteIcon={isActive ? <SvgIcon src={iconCancelAlt} size='small' /> : undefined}
|
|
55
49
|
label={label}
|
|
56
50
|
clickable
|
|
57
51
|
{...chipProps}
|
|
58
|
-
className={clsx(classes.chip, isActive && classes.chipSelected, chipProps.className)}
|
|
59
52
|
/>
|
|
60
53
|
</ProductListLink>
|
|
61
54
|
)
|
|
@@ -1,103 +1,52 @@
|
|
|
1
|
-
import { cloneDeep } from '@
|
|
2
|
-
import {
|
|
3
|
-
import { ChipMenu, ChipMenuProps, responsiveVal } from '@graphcommerce/next-ui'
|
|
1
|
+
import { cloneDeep, FilterEqualTypeInput } from '@graphcommerce/graphql'
|
|
2
|
+
import { ChipMenu, ChipMenuProps, responsiveVal, extendableComponent } from '@graphcommerce/next-ui'
|
|
4
3
|
import {
|
|
4
|
+
Box,
|
|
5
5
|
Checkbox,
|
|
6
6
|
ListItem,
|
|
7
7
|
ListItemSecondaryAction,
|
|
8
8
|
ListItemText,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from '@material-ui/core'
|
|
12
|
-
import clsx from 'clsx'
|
|
13
|
-
import React from 'react'
|
|
9
|
+
listItemTextClasses,
|
|
10
|
+
} from '@mui/material'
|
|
14
11
|
import { SetRequired } from 'type-fest'
|
|
15
12
|
import { useProductListLinkReplace } from '../../hooks/useProductListLinkReplace'
|
|
16
13
|
import { useProductListParamsContext } from '../../hooks/useProductListParamsContext'
|
|
17
14
|
import ProductListLink from '../ProductListLink/ProductListLink'
|
|
18
15
|
import { ProductListFiltersFragment } from './ProductListFilters.gql'
|
|
19
16
|
|
|
17
|
+
type OwnerState = {
|
|
18
|
+
isColor: boolean
|
|
19
|
+
isActive: boolean
|
|
20
|
+
}
|
|
21
|
+
const componentName = 'FilterEqual' as const
|
|
22
|
+
const parts = [
|
|
23
|
+
'listItem',
|
|
24
|
+
'listItemInnerContainer',
|
|
25
|
+
'checkbox',
|
|
26
|
+
'linkContainer',
|
|
27
|
+
'button',
|
|
28
|
+
'resetButton',
|
|
29
|
+
'filterAmount',
|
|
30
|
+
'filterLabel',
|
|
31
|
+
'isColor',
|
|
32
|
+
'isActive',
|
|
33
|
+
] as const
|
|
34
|
+
|
|
35
|
+
const { classes, selectors, withState } = extendableComponent<
|
|
36
|
+
OwnerState,
|
|
37
|
+
typeof componentName,
|
|
38
|
+
typeof parts
|
|
39
|
+
>(componentName, parts)
|
|
40
|
+
|
|
20
41
|
export type FilterIn = SetRequired<Omit<FilterEqualTypeInput, 'eq'>, 'in'>
|
|
21
42
|
|
|
22
|
-
type
|
|
23
|
-
NonNullable<ProductListFiltersFragment['aggregations']>[0]
|
|
24
|
-
> &
|
|
25
|
-
Omit<ChipMenuProps, 'selected'>
|
|
43
|
+
type Filter = NonNullable<NonNullable<ProductListFiltersFragment['aggregations']>[number]>
|
|
26
44
|
|
|
27
|
-
|
|
28
|
-
(theme: Theme) => ({
|
|
29
|
-
root: {},
|
|
30
|
-
listItem: {
|
|
31
|
-
padding: `0 ${theme.spacings.xxs} 0`,
|
|
32
|
-
display: 'block',
|
|
33
|
-
'&:not(:nth-last-of-type(-n+2)) > div': {
|
|
34
|
-
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
listItemInnerContainer: {
|
|
38
|
-
width: '100%',
|
|
39
|
-
paddingTop: responsiveVal(0, 3),
|
|
40
|
-
paddingBottom: theme.spacings.xxs,
|
|
41
|
-
'& > div': {
|
|
42
|
-
display: 'inline-block',
|
|
43
|
-
[theme.breakpoints.down('sm')]: {
|
|
44
|
-
maxWidth: '72%',
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
checkbox: {
|
|
49
|
-
padding: 0,
|
|
50
|
-
margin: '-10px 0 0 0',
|
|
51
|
-
float: 'right',
|
|
52
|
-
},
|
|
53
|
-
linkContainer: {
|
|
54
|
-
display: 'grid',
|
|
55
|
-
gridTemplateColumns: 'repeat(2, 1fr)',
|
|
56
|
-
columnGap: responsiveVal(2, 16),
|
|
57
|
-
minWidth: 0,
|
|
58
|
-
[theme.breakpoints.down('sm')]: {
|
|
59
|
-
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
button: {
|
|
63
|
-
float: 'right',
|
|
64
|
-
marginTop: theme.spacings.xxs,
|
|
65
|
-
marginRight: theme.spacings.xxs,
|
|
66
|
-
textDecoration: 'none',
|
|
67
|
-
},
|
|
68
|
-
resetButton: {
|
|
69
|
-
// background: theme.palette.grey['100'],
|
|
70
|
-
marginRight: theme.spacings.xxs,
|
|
71
|
-
},
|
|
72
|
-
filterAmount: {
|
|
73
|
-
color: theme.palette.grey[500],
|
|
74
|
-
marginLeft: 4,
|
|
75
|
-
fontSize: theme.typography.pxToRem(11),
|
|
76
|
-
display: 'inline',
|
|
77
|
-
},
|
|
78
|
-
filterLabel: {
|
|
79
|
-
display: 'inline',
|
|
80
|
-
overflow: 'hidden',
|
|
81
|
-
whiteSpace: 'break-spaces',
|
|
82
|
-
},
|
|
83
|
-
isColor: {
|
|
84
|
-
border: `1px solid ${theme.palette.divider}`,
|
|
85
|
-
'& > *': {
|
|
86
|
-
opacity: 0,
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
isActive: {
|
|
90
|
-
border: `1px solid ${theme.palette.primary.main}`,
|
|
91
|
-
boxShadow: `inset 0 0 0 4px ${theme.palette.background.paper}`,
|
|
92
|
-
},
|
|
93
|
-
}),
|
|
94
|
-
{ name: 'FilterEqual' },
|
|
95
|
-
)
|
|
45
|
+
type FilterEqualTypeProps = Filter & Omit<ChipMenuProps, 'selected'>
|
|
96
46
|
|
|
97
47
|
export default function FilterEqualType(props: FilterEqualTypeProps) {
|
|
98
|
-
const { attribute_code, count, label, options, ...chipProps } = props
|
|
48
|
+
const { attribute_code, count, label, options, __typename, ...chipProps } = props
|
|
99
49
|
const { params } = useProductListParamsContext()
|
|
100
|
-
const classes = useFilterEqualStyles()
|
|
101
50
|
const replaceRoute = useProductListLinkReplace({ scroll: false })
|
|
102
51
|
|
|
103
52
|
const currentFilter: FilterEqualTypeInput = cloneDeep(params.filters[attribute_code]) ?? {
|
|
@@ -127,19 +76,25 @@ export default function FilterEqualType(props: FilterEqualTypeProps) {
|
|
|
127
76
|
selected={currentLabels.length > 0}
|
|
128
77
|
selectedLabel={currentLabels.length > 0 ? currentLabels.join(', ') : undefined}
|
|
129
78
|
onDelete={currentLabels.length > 0 ? removeFilter : undefined}
|
|
130
|
-
className={
|
|
79
|
+
className={componentName}
|
|
131
80
|
>
|
|
132
|
-
<
|
|
81
|
+
<Box
|
|
82
|
+
className={classes.linkContainer}
|
|
83
|
+
sx={{
|
|
84
|
+
display: 'grid',
|
|
85
|
+
gridTemplateColumns: { xs: 'repeat(2, minmax(0, 1fr))', md: 'repeat(2, 1fr)' },
|
|
86
|
+
columnGap: responsiveVal(2, 16),
|
|
87
|
+
minWidth: 0,
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
133
90
|
{options?.map((option) => {
|
|
134
91
|
if (!option?.value) return null
|
|
135
92
|
const labelId = `filter-equal-${attribute_code}-${option?.value}`
|
|
136
93
|
const filters = cloneDeep(params.filters)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (label?.toLowerCase().includes('color')) {
|
|
140
|
-
isColor = true
|
|
141
|
-
}
|
|
94
|
+
const isColor = !!attribute_code?.toLowerCase().includes('color')
|
|
95
|
+
const isActive = Boolean(isColor && currentFilter.in?.includes(option?.value) && isColor)
|
|
142
96
|
|
|
97
|
+
const cls = withState({ isColor, isActive })
|
|
143
98
|
if (currentFilter.in?.includes(option.value)) {
|
|
144
99
|
filters[attribute_code] = {
|
|
145
100
|
...currentFilter,
|
|
@@ -161,12 +116,47 @@ export default function FilterEqualType(props: FilterEqualTypeProps) {
|
|
|
161
116
|
color='inherit'
|
|
162
117
|
link={{ replace: anyFilterActive }}
|
|
163
118
|
>
|
|
164
|
-
<ListItem
|
|
165
|
-
|
|
119
|
+
<ListItem
|
|
120
|
+
dense
|
|
121
|
+
className={cls.listItem}
|
|
122
|
+
sx={(theme) => ({
|
|
123
|
+
padding: `0 ${theme.spacings.xxs} 0`,
|
|
124
|
+
display: 'block',
|
|
125
|
+
'&:not(:nth-last-of-type(-n+2)) > div': {
|
|
126
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
127
|
+
},
|
|
128
|
+
})}
|
|
129
|
+
>
|
|
130
|
+
<Box
|
|
131
|
+
className={cls.listItemInnerContainer}
|
|
132
|
+
sx={(theme) => ({
|
|
133
|
+
width: '100%',
|
|
134
|
+
paddingTop: responsiveVal(0, 3),
|
|
135
|
+
paddingBottom: theme.spacings.xxs,
|
|
136
|
+
'& > div': {
|
|
137
|
+
display: 'inline-block',
|
|
138
|
+
[theme.breakpoints.down('md')]: {
|
|
139
|
+
maxWidth: '72%',
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
})}
|
|
143
|
+
>
|
|
166
144
|
<ListItemText
|
|
167
145
|
primary={option?.label}
|
|
168
|
-
classes={{ primary: classes.filterLabel, secondary: classes.filterAmount }}
|
|
169
146
|
secondary={`(${option?.count})`}
|
|
147
|
+
sx={(theme) => ({
|
|
148
|
+
[`& .${listItemTextClasses.primary}`]: {
|
|
149
|
+
display: 'inline',
|
|
150
|
+
overflow: 'hidden',
|
|
151
|
+
whiteSpace: 'break-spaces',
|
|
152
|
+
},
|
|
153
|
+
[`& .${listItemTextClasses.secondary}`]: {
|
|
154
|
+
color: theme.palette.grey[500],
|
|
155
|
+
marginLeft: `4px`,
|
|
156
|
+
fontSize: theme.typography.pxToRem(11),
|
|
157
|
+
display: 'inline',
|
|
158
|
+
},
|
|
159
|
+
})}
|
|
170
160
|
/>
|
|
171
161
|
<ListItemSecondaryAction>
|
|
172
162
|
<Checkbox
|
|
@@ -177,13 +167,26 @@ export default function FilterEqualType(props: FilterEqualTypeProps) {
|
|
|
177
167
|
color='primary'
|
|
178
168
|
disableRipple
|
|
179
169
|
inputProps={{ 'aria-labelledby': labelId }}
|
|
180
|
-
className={
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
:
|
|
186
|
-
|
|
170
|
+
className={cls.checkbox}
|
|
171
|
+
sx={[
|
|
172
|
+
{
|
|
173
|
+
padding: 0,
|
|
174
|
+
margin: '-10px 0 0 0',
|
|
175
|
+
float: 'right',
|
|
176
|
+
},
|
|
177
|
+
isColor && {
|
|
178
|
+
border: 1,
|
|
179
|
+
borderColor: 'divider',
|
|
180
|
+
'& > *': {
|
|
181
|
+
opacity: 0,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
isActive &&
|
|
185
|
+
((theme) => ({
|
|
186
|
+
border: `1px solid ${theme.palette.primary.main}`,
|
|
187
|
+
boxShadow: `inset 0 0 0 4px ${theme.palette.background.paper}`,
|
|
188
|
+
})),
|
|
189
|
+
]}
|
|
187
190
|
style={
|
|
188
191
|
isColor
|
|
189
192
|
? { background: `${option?.label}`, color: `${option?.label}` }
|
|
@@ -191,12 +194,14 @@ export default function FilterEqualType(props: FilterEqualTypeProps) {
|
|
|
191
194
|
}
|
|
192
195
|
/>
|
|
193
196
|
</ListItemSecondaryAction>
|
|
194
|
-
</
|
|
197
|
+
</Box>
|
|
195
198
|
</ListItem>
|
|
196
199
|
</ProductListLink>
|
|
197
200
|
)
|
|
198
201
|
})}
|
|
199
|
-
</
|
|
202
|
+
</Box>
|
|
200
203
|
</ChipMenu>
|
|
201
204
|
)
|
|
202
205
|
}
|
|
206
|
+
|
|
207
|
+
FilterEqualType.selectors = selectors
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { cloneDeep } from '@
|
|
2
|
-
import { FilterRangeTypeInput } from '@graphcommerce/graphql'
|
|
1
|
+
import { cloneDeep, FilterRangeTypeInput } from '@graphcommerce/graphql'
|
|
3
2
|
import { Money } from '@graphcommerce/magento-store'
|
|
4
|
-
import { ChipMenu, ChipMenuProps } from '@graphcommerce/next-ui'
|
|
5
|
-
import {
|
|
3
|
+
import { ChipMenu, ChipMenuProps, extendableComponent } from '@graphcommerce/next-ui'
|
|
4
|
+
import { Box, Slider } from '@mui/material'
|
|
6
5
|
import React, { useEffect } from 'react'
|
|
7
6
|
import { useProductListLinkReplace } from '../../hooks/useProductListLinkReplace'
|
|
8
7
|
import { useProductListParamsContext } from '../../hooks/useProductListParamsContext'
|
|
@@ -14,47 +13,16 @@ type FilterRangeTypeProps = NonNullable<
|
|
|
14
13
|
Omit<ChipMenuProps, 'selected'>
|
|
15
14
|
|
|
16
15
|
const sliderThumbWidth = 28
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
container: {
|
|
20
|
-
padding: `${theme.spacings.xxs} ${theme.spacings.xxs} !important`,
|
|
21
|
-
width: '100%',
|
|
22
|
-
},
|
|
23
|
-
slider: {
|
|
24
|
-
maxWidth: `calc(100% - ${sliderThumbWidth}px)`,
|
|
25
|
-
margin: `${theme.spacings.xxs} auto`,
|
|
26
|
-
display: 'block',
|
|
27
|
-
paddingBottom: 32,
|
|
28
|
-
'& .MuiSlider-rail': {
|
|
29
|
-
color: theme.palette.text.disabled,
|
|
30
|
-
height: 4,
|
|
31
|
-
borderRadius: 10,
|
|
32
|
-
},
|
|
33
|
-
'& .MuiSlider-track': {
|
|
34
|
-
color: theme.palette.primary.main,
|
|
35
|
-
height: 4,
|
|
36
|
-
},
|
|
37
|
-
'& .MuiSlider-thumb': {
|
|
38
|
-
width: sliderThumbWidth,
|
|
39
|
-
height: sliderThumbWidth,
|
|
40
|
-
marginLeft: `-${sliderThumbWidth * 0.5}px`,
|
|
41
|
-
marginTop: `-${sliderThumbWidth * 0.5}px`,
|
|
42
|
-
background: theme.palette.background.default,
|
|
43
|
-
boxShadow: theme.shadows[6],
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
}),
|
|
47
|
-
{ name: 'FilterRangeType' },
|
|
48
|
-
)
|
|
16
|
+
|
|
17
|
+
const { classes } = extendableComponent('FilterRangeType', ['root', 'container', 'slider'] as const)
|
|
49
18
|
|
|
50
19
|
export default function FilterRangeType(props: FilterRangeTypeProps) {
|
|
51
20
|
const { attribute_code, label, options, ...chipProps } = props
|
|
52
|
-
const classes = useFilterRangeType(props)
|
|
53
21
|
const { params } = useProductListParamsContext()
|
|
54
22
|
const replaceRoute = useProductListLinkReplace({ scroll: false })
|
|
55
23
|
|
|
56
24
|
// eslint-disable-next-line no-case-declarations
|
|
57
|
-
const marks: { [index: number]:
|
|
25
|
+
const marks: { [index: number]: { value: number; label?: React.ReactNode } } = {}
|
|
58
26
|
const paramValues = params.filters[attribute_code]
|
|
59
27
|
|
|
60
28
|
const [min, maxish] = options
|
|
@@ -141,6 +109,7 @@ export default function FilterRangeType(props: FilterRangeTypeProps) {
|
|
|
141
109
|
selected={!!currentLabel}
|
|
142
110
|
{...chipProps}
|
|
143
111
|
onDelete={currentLabel ? resetFilter : undefined}
|
|
112
|
+
className={classes.root}
|
|
144
113
|
labelRight={
|
|
145
114
|
<>
|
|
146
115
|
<Money round value={value[0]} />
|
|
@@ -149,7 +118,13 @@ export default function FilterRangeType(props: FilterRangeTypeProps) {
|
|
|
149
118
|
</>
|
|
150
119
|
}
|
|
151
120
|
>
|
|
152
|
-
<
|
|
121
|
+
<Box
|
|
122
|
+
sx={(theme) => ({
|
|
123
|
+
padding: `${theme.spacings.xxs} ${theme.spacings.xxs} !important`,
|
|
124
|
+
width: '100%',
|
|
125
|
+
})}
|
|
126
|
+
className={classes.container}
|
|
127
|
+
>
|
|
153
128
|
<Slider
|
|
154
129
|
min={min}
|
|
155
130
|
max={max}
|
|
@@ -167,8 +142,25 @@ export default function FilterRangeType(props: FilterRangeTypeProps) {
|
|
|
167
142
|
}}
|
|
168
143
|
valueLabelDisplay='off'
|
|
169
144
|
className={classes.slider}
|
|
145
|
+
sx={(theme) => ({
|
|
146
|
+
maxWidth: `calc(100% - ${sliderThumbWidth}px)`,
|
|
147
|
+
margin: `${theme.spacings.xxs} auto`,
|
|
148
|
+
display: 'block',
|
|
149
|
+
paddingBottom: '32px',
|
|
150
|
+
'& .MuiSlider-rail': {
|
|
151
|
+
height: 4,
|
|
152
|
+
borderRadius: '10px',
|
|
153
|
+
},
|
|
154
|
+
'& .MuiSlider-track': {
|
|
155
|
+
height: 4,
|
|
156
|
+
},
|
|
157
|
+
'& .MuiSlider-thumb': {
|
|
158
|
+
width: sliderThumbWidth,
|
|
159
|
+
height: sliderThumbWidth,
|
|
160
|
+
},
|
|
161
|
+
})}
|
|
170
162
|
/>
|
|
171
|
-
</
|
|
163
|
+
</Box>
|
|
172
164
|
</ChipMenu>
|
|
173
165
|
)
|
|
174
166
|
}
|