@graphcommerce/magento-product 9.1.0-canary.34 → 9.1.0-canary.36
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 +12 -0
- package/components/ProductListItems/filteredProductList.tsx +6 -1
- package/components/ProductListPrice/ProductListPrice.tsx +50 -10
- package/components/ProductPagePrice/ProductPagePrice.tsx +40 -8
- package/components/ProductPagePrice/ProductPagePriceTiers.tsx +4 -2
- package/hooks/useProductListLink.ts +1 -1
- package/package.json +13 -13
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 9.1.0-canary.36
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- [`c8aa135`](https://github.com/graphcommerce-org/graphcommerce/commit/c8aa13561f2a25b658466c0f3cddaa1bd338c443) - Add support for price prefix and suffix to be able to customize rendering ([@paales](https://github.com/paales))
|
8
|
+
|
9
|
+
## 9.1.0-canary.35
|
10
|
+
|
11
|
+
### Patch Changes
|
12
|
+
|
13
|
+
- [`4b02607`](https://github.com/graphcommerce-org/graphcommerce/commit/4b02607b26dd45e33bba3fb73d36052757dc2dec) - Solve issue where seaches containing a `/` would not consider everything after the `/` as part of the search. ([@paales](https://github.com/paales))
|
14
|
+
|
3
15
|
## 9.1.0-canary.34
|
4
16
|
|
5
17
|
## 9.1.0-canary.33
|
@@ -15,7 +15,12 @@ export function parseParams(
|
|
15
15
|
filterTypes: FilterTypes,
|
16
16
|
search: string | null = null,
|
17
17
|
): ProductListParams | undefined {
|
18
|
-
const productListParams: ProductListParams = {
|
18
|
+
const productListParams: ProductListParams = {
|
19
|
+
url,
|
20
|
+
filters: {},
|
21
|
+
sort: {},
|
22
|
+
search: search ? decodeURIComponent(search) : null,
|
23
|
+
}
|
19
24
|
|
20
25
|
const typeMap = filterTypes
|
21
26
|
|
@@ -1,47 +1,87 @@
|
|
1
1
|
import { PrivateQueryMask } from '@graphcommerce/graphql'
|
2
2
|
import { Money } from '@graphcommerce/magento-store'
|
3
|
-
import { extendableComponent } from '@graphcommerce/next-ui'
|
4
|
-
import type
|
5
|
-
import { Typography } from '@mui/material'
|
3
|
+
import { extendableComponent, sxx } from '@graphcommerce/next-ui'
|
4
|
+
import { Box, type TypographyProps } from '@mui/material'
|
6
5
|
import type { ProductListPriceFragment } from './ProductListPrice.gql'
|
7
6
|
|
8
7
|
export const productListPrice = extendableComponent('ProductListPrice', [
|
8
|
+
'prefix',
|
9
9
|
'root',
|
10
10
|
'finalPrice',
|
11
11
|
'discountPrice',
|
12
|
+
'suffix',
|
12
13
|
] as const)
|
13
14
|
|
14
15
|
const { classes, selectors } = productListPrice
|
15
16
|
|
16
|
-
export type ProductListPriceProps = ProductListPriceFragment &
|
17
|
+
export type ProductListPriceProps = ProductListPriceFragment &
|
18
|
+
Pick<TypographyProps, 'sx'> & {
|
19
|
+
prefix?: React.ReactNode
|
20
|
+
suffix?: React.ReactNode
|
21
|
+
}
|
17
22
|
|
18
23
|
export function ProductListPrice(props: ProductListPriceProps) {
|
19
|
-
const { regular_price, final_price, sx } = props
|
24
|
+
const { regular_price, final_price, sx, prefix, suffix } = props
|
20
25
|
|
21
26
|
return (
|
22
|
-
<
|
27
|
+
<Box
|
28
|
+
className={classes.root}
|
29
|
+
sx={sxx({ typography: 'body1', display: 'inline-flex', columnGap: '0.3em' }, sx)}
|
30
|
+
>
|
31
|
+
{prefix && (
|
32
|
+
<PrivateQueryMask
|
33
|
+
component='span'
|
34
|
+
skeleton={{
|
35
|
+
variant: 'text',
|
36
|
+
sx: { width: '3.5em', transform: 'none' },
|
37
|
+
}}
|
38
|
+
className={classes.prefix}
|
39
|
+
>
|
40
|
+
{prefix}
|
41
|
+
</PrivateQueryMask>
|
42
|
+
)}
|
43
|
+
|
23
44
|
{regular_price.value !== final_price.value && (
|
24
45
|
<PrivateQueryMask
|
25
46
|
component='span'
|
26
47
|
sx={{
|
27
48
|
textDecoration: 'line-through',
|
28
49
|
color: 'text.disabled',
|
29
|
-
marginRight: '8px',
|
30
50
|
}}
|
31
|
-
skeleton={{
|
51
|
+
skeleton={{
|
52
|
+
variant: 'text',
|
53
|
+
sx: { width: '3.5em', transform: 'none' },
|
54
|
+
}}
|
32
55
|
className={classes.discountPrice}
|
33
56
|
>
|
34
57
|
<Money {...regular_price} />
|
35
58
|
</PrivateQueryMask>
|
36
59
|
)}
|
60
|
+
|
37
61
|
<PrivateQueryMask
|
38
62
|
className={classes.finalPrice}
|
39
63
|
component='span'
|
40
|
-
skeleton={{
|
64
|
+
skeleton={{
|
65
|
+
variant: 'text',
|
66
|
+
sx: { width: '3.5em', transform: 'none' },
|
67
|
+
}}
|
41
68
|
>
|
42
69
|
<Money {...final_price} />
|
43
70
|
</PrivateQueryMask>
|
44
|
-
|
71
|
+
|
72
|
+
{suffix && (
|
73
|
+
<PrivateQueryMask
|
74
|
+
component='span'
|
75
|
+
skeleton={{
|
76
|
+
variant: 'text',
|
77
|
+
sx: { width: '3.5em', transform: 'none' },
|
78
|
+
}}
|
79
|
+
className={classes.suffix}
|
80
|
+
>
|
81
|
+
{suffix}
|
82
|
+
</PrivateQueryMask>
|
83
|
+
)}
|
84
|
+
</Box>
|
45
85
|
)
|
46
86
|
}
|
47
87
|
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import { useWatch } from '@graphcommerce/ecommerce-ui'
|
2
2
|
import { PrivateQueryMask } from '@graphcommerce/graphql'
|
3
3
|
import { Money } from '@graphcommerce/magento-store'
|
4
|
-
import { extendableComponent } from '@graphcommerce/next-ui'
|
4
|
+
import { extendableComponent, sxx } from '@graphcommerce/next-ui'
|
5
|
+
import { Box, type SxProps, type Theme } from '@mui/material'
|
5
6
|
import type { AddToCartItemSelector } from '../AddProductsToCart'
|
6
7
|
import { useFormAddProductsToCart } from '../AddProductsToCart'
|
7
8
|
import { getProductTierPrice } from './getProductTierPrice'
|
@@ -9,16 +10,23 @@ import type { ProductPagePriceFragment } from './ProductPagePrice.gql'
|
|
9
10
|
import type { UseCustomizableOptionPriceProps } from './useCustomizableOptionPrice'
|
10
11
|
import { useCustomizableOptionPrice } from './useCustomizableOptionPrice'
|
11
12
|
|
12
|
-
export type ProductPagePriceProps = {
|
13
|
+
export type ProductPagePriceProps = {
|
14
|
+
product: ProductPagePriceFragment
|
15
|
+
prefix?: React.ReactNode
|
16
|
+
suffix?: React.ReactNode
|
17
|
+
sx?: SxProps<Theme>
|
18
|
+
} & AddToCartItemSelector &
|
13
19
|
UseCustomizableOptionPriceProps
|
14
20
|
|
15
21
|
const { classes } = extendableComponent('ProductPagePrice', [
|
16
22
|
'finalPrice',
|
17
23
|
'discountPrice',
|
24
|
+
'prefix',
|
25
|
+
'suffix',
|
18
26
|
] as const)
|
19
27
|
|
20
28
|
export function ProductPagePrice(props: ProductPagePriceProps) {
|
21
|
-
const { product, index = 0 } = props
|
29
|
+
const { product, index = 0, prefix, suffix, sx } = props
|
22
30
|
|
23
31
|
const { control } = useFormAddProductsToCart()
|
24
32
|
const quantity = useWatch({ control, name: `cartItems.${index}.quantity` })
|
@@ -29,24 +37,48 @@ export function ProductPagePrice(props: ProductPagePriceProps) {
|
|
29
37
|
const regularPrice = product.price_range.minimum_price.regular_price
|
30
38
|
|
31
39
|
return (
|
32
|
-
|
40
|
+
<Box component='span' sx={sxx({ display: 'inline-flex', columnGap: '0.3em' }, sx)}>
|
41
|
+
{prefix && (
|
42
|
+
<PrivateQueryMask
|
43
|
+
component='span'
|
44
|
+
className={classes.prefix}
|
45
|
+
skeleton={{
|
46
|
+
variant: 'text',
|
47
|
+
sx: { width: '3.5em', transform: 'none' },
|
48
|
+
}}
|
49
|
+
>
|
50
|
+
{prefix}
|
51
|
+
</PrivateQueryMask>
|
52
|
+
)}
|
33
53
|
{regularPrice.value !== price.value && (
|
34
54
|
<PrivateQueryMask
|
35
55
|
component='span'
|
36
56
|
className={classes.discountPrice}
|
37
|
-
skeleton={{ variant: 'text', sx: { width: '
|
38
|
-
sx={[{ textDecoration: 'line-through', color: 'text.disabled'
|
57
|
+
skeleton={{ variant: 'text', sx: { width: '3.5em', transform: 'none' } }}
|
58
|
+
sx={[{ textDecoration: 'line-through', color: 'text.disabled' }]}
|
39
59
|
>
|
40
60
|
<Money {...regularPrice} />
|
41
61
|
</PrivateQueryMask>
|
42
62
|
)}
|
43
63
|
<PrivateQueryMask
|
44
64
|
component='span'
|
45
|
-
skeleton={{ variant: 'text', sx: { width: '
|
65
|
+
skeleton={{ variant: 'text', sx: { width: '3.5em', transform: 'none' } }}
|
46
66
|
className={classes.finalPrice}
|
47
67
|
>
|
48
68
|
<Money {...price} value={priceValue} />
|
49
69
|
</PrivateQueryMask>
|
50
|
-
|
70
|
+
{suffix && (
|
71
|
+
<PrivateQueryMask
|
72
|
+
component='span'
|
73
|
+
className={classes.suffix}
|
74
|
+
skeleton={{
|
75
|
+
variant: 'text',
|
76
|
+
sx: { width: '3.5em', transform: 'none' },
|
77
|
+
}}
|
78
|
+
>
|
79
|
+
{suffix}
|
80
|
+
</PrivateQueryMask>
|
81
|
+
)}
|
82
|
+
</Box>
|
51
83
|
)
|
52
84
|
}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { PrivateQueryMask } from '@graphcommerce/graphql'
|
2
|
-
import { Money } from '@graphcommerce/magento-store'
|
3
2
|
import { filterNonNullableKeys } from '@graphcommerce/next-ui'
|
4
3
|
import { Trans } from '@lingui/react'
|
5
4
|
import type { SxProps, Theme } from '@mui/material'
|
5
|
+
import { ProductListPrice } from '../ProductListPrice/ProductListPrice'
|
6
6
|
import type { ProductPagePriceFragment } from './ProductPagePrice.gql'
|
7
7
|
|
8
8
|
export type ProductPagePriceTiersProps = {
|
@@ -27,7 +27,9 @@ export function ProductPagePriceTiers(props: ProductPagePriceTiersProps) {
|
|
27
27
|
<div key={quantity}>
|
28
28
|
<Trans
|
29
29
|
id='Buy {quantity} for <0/> and save {percent}%'
|
30
|
-
components={{
|
30
|
+
components={{
|
31
|
+
0: <ProductListPrice final_price={final_price} regular_price={final_price} />,
|
32
|
+
}}
|
31
33
|
values={{ quantity, percent: discount.percent_off }}
|
32
34
|
/>
|
33
35
|
</div>
|
@@ -16,7 +16,7 @@ export function productListLinkFromFilter(props: ProductFilterParams): string {
|
|
16
16
|
const uid = incoming?.category_uid?.eq || incoming?.category_uid?.in?.[0]
|
17
17
|
|
18
18
|
let urlBase = url
|
19
|
-
if (isSearch) urlBase = search ? `search/${search}` : 'search'
|
19
|
+
if (isSearch) urlBase = search ? `search/${encodeURIComponent(search)}` : 'search'
|
20
20
|
|
21
21
|
// base url path generation
|
22
22
|
let paginateSort = ''
|
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "@graphcommerce/magento-product",
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
5
|
-
"version": "9.1.0-canary.
|
5
|
+
"version": "9.1.0-canary.36",
|
6
6
|
"sideEffects": false,
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
8
8
|
"eslintConfig": {
|
@@ -18,18 +18,18 @@
|
|
18
18
|
"typescript": "5.7.2"
|
19
19
|
},
|
20
20
|
"peerDependencies": {
|
21
|
-
"@graphcommerce/ecommerce-ui": "^9.1.0-canary.
|
22
|
-
"@graphcommerce/eslint-config-pwa": "^9.1.0-canary.
|
23
|
-
"@graphcommerce/framer-next-pages": "^9.1.0-canary.
|
24
|
-
"@graphcommerce/framer-scroller": "^9.1.0-canary.
|
25
|
-
"@graphcommerce/graphql": "^9.1.0-canary.
|
26
|
-
"@graphcommerce/graphql-mesh": "^9.1.0-canary.
|
27
|
-
"@graphcommerce/image": "^9.1.0-canary.
|
28
|
-
"@graphcommerce/magento-cart": "^9.1.0-canary.
|
29
|
-
"@graphcommerce/magento-store": "^9.1.0-canary.
|
30
|
-
"@graphcommerce/next-ui": "^9.1.0-canary.
|
31
|
-
"@graphcommerce/prettier-config-pwa": "^9.1.0-canary.
|
32
|
-
"@graphcommerce/typescript-config-pwa": "^9.1.0-canary.
|
21
|
+
"@graphcommerce/ecommerce-ui": "^9.1.0-canary.36",
|
22
|
+
"@graphcommerce/eslint-config-pwa": "^9.1.0-canary.36",
|
23
|
+
"@graphcommerce/framer-next-pages": "^9.1.0-canary.36",
|
24
|
+
"@graphcommerce/framer-scroller": "^9.1.0-canary.36",
|
25
|
+
"@graphcommerce/graphql": "^9.1.0-canary.36",
|
26
|
+
"@graphcommerce/graphql-mesh": "^9.1.0-canary.36",
|
27
|
+
"@graphcommerce/image": "^9.1.0-canary.36",
|
28
|
+
"@graphcommerce/magento-cart": "^9.1.0-canary.36",
|
29
|
+
"@graphcommerce/magento-store": "^9.1.0-canary.36",
|
30
|
+
"@graphcommerce/next-ui": "^9.1.0-canary.36",
|
31
|
+
"@graphcommerce/prettier-config-pwa": "^9.1.0-canary.36",
|
32
|
+
"@graphcommerce/typescript-config-pwa": "^9.1.0-canary.36",
|
33
33
|
"@lingui/core": "^4.2.1",
|
34
34
|
"@lingui/macro": "^4.2.1",
|
35
35
|
"@lingui/react": "^4.2.1",
|