@graphcommerce/magento-product 8.1.0-canary.5 → 8.1.0-canary.52

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.
Files changed (80) hide show
  1. package/Api/ProductListItem.graphql +1 -2
  2. package/Api/ProductPageItem.graphql +1 -1
  3. package/CHANGELOG.md +115 -0
  4. package/Config.graphqls +13 -0
  5. package/components/AddProductsToCart/AddProductsToCartButton.tsx +3 -2
  6. package/components/AddProductsToCart/AddProductsToCartFab.tsx +2 -2
  7. package/components/AddProductsToCart/AddProductsToCartForm.tsx +31 -28
  8. package/components/AddProductsToCart/AddProductsToCartSnackbar.tsx +25 -16
  9. package/components/AddProductsToCart/UseAddProductsToCartAction.graphql +1 -1
  10. package/components/AddProductsToCart/findAddedItems.ts +1 -4
  11. package/components/AddProductsToCart/useAddProductsToCartAction.ts +2 -1
  12. package/components/AddProductsToCart/useFormAddProductsToCart.ts +1 -2
  13. package/components/JsonLdProduct/JsonLdProduct.graphql +1 -1
  14. package/components/JsonLdProduct/ProductPageJsonLd.tsx +1 -1
  15. package/components/ProductAddToCart/ProductAddToCart.tsx +6 -8
  16. package/components/ProductCustomizable/ProductCustomizable.graphql +1 -1
  17. package/components/ProductCustomizable/index.ts +1 -0
  18. package/components/ProductCustomizable/productCustomizableSelectors.ts +59 -0
  19. package/components/ProductFiltersPro/PriceSlider.tsx +1 -2
  20. package/components/ProductFiltersPro/ProductFilterEqualChip.tsx +1 -1
  21. package/components/ProductFiltersPro/ProductFilterEqualSection.tsx +2 -2
  22. package/components/ProductFiltersPro/ProductFilterRangeChip.tsx +1 -1
  23. package/components/ProductFiltersPro/ProductFilterRangeSection.tsx +1 -1
  24. package/components/ProductFiltersPro/ProductFiltersPro.tsx +103 -19
  25. package/components/ProductFiltersPro/ProductFiltersProAggregations.tsx +31 -18
  26. package/components/ProductFiltersPro/ProductFiltersProAllFiltersChip.tsx +6 -10
  27. package/components/ProductFiltersPro/ProductFiltersProAllFiltersSidebar.tsx +18 -8
  28. package/components/ProductFiltersPro/ProductFiltersProCategorySection.tsx +130 -0
  29. package/components/ProductFiltersPro/ProductFiltersProChips.tsx +10 -8
  30. package/components/ProductFiltersPro/ProductFiltersProClearAll.tsx +4 -16
  31. package/components/ProductFiltersPro/ProductFiltersProLayoutSidebar.tsx +15 -7
  32. package/components/ProductFiltersPro/ProductFiltersProLimitSection.tsx +5 -2
  33. package/components/ProductFiltersPro/ProductFiltersProNoResults.tsx +79 -0
  34. package/components/ProductFiltersPro/ProductFiltersProSortChip.tsx +1 -1
  35. package/components/ProductFiltersPro/ProductFiltersProSortDirectionArrow.tsx +2 -4
  36. package/components/ProductFiltersPro/ProductFiltersProSortSection.tsx +7 -2
  37. package/components/ProductFiltersPro/activeAggregations.ts +5 -9
  38. package/components/ProductFiltersPro/applyAggregationCount.ts +14 -8
  39. package/components/ProductFiltersPro/index.ts +9 -0
  40. package/components/ProductFiltersPro/{useClearAllFiltersHandler.ts → useProductFiltersProClearAllAction.ts} +1 -1
  41. package/components/ProductFiltersPro/useProductFiltersProHasFiltersApplied.ts +21 -0
  42. package/components/ProductFiltersPro/useProductFiltersProSort.tsx +4 -2
  43. package/components/ProductList/ProductList.graphql +8 -5
  44. package/components/ProductListCount/ProductListCount.tsx +3 -1
  45. package/components/ProductListFilters/ProductFilters.graphql +7 -2
  46. package/components/ProductListFilters/ProductListFilters.graphql +1 -1
  47. package/components/ProductListFiltersContainer/ProductListFiltersContainer.tsx +2 -4
  48. package/components/ProductListItem/ProductDiscountLabel.tsx +2 -3
  49. package/components/ProductListItem/ProductListItem.tsx +3 -3
  50. package/components/ProductListItem/ProductListItemTitleAndPrice.tsx +18 -15
  51. package/components/ProductListItems/ProductListItemsBase.tsx +65 -23
  52. package/components/ProductListItems/filterTypes.tsx +14 -5
  53. package/components/ProductListItems/filteredProductList.tsx +23 -0
  54. package/components/ProductListItems/productListApplyCategoryDefaults.ts +44 -4
  55. package/components/ProductListItems/renderer.tsx +8 -2
  56. package/components/ProductListPagination/ProductListPagination.tsx +39 -20
  57. package/components/ProductListPrice/ProductListPrice.tsx +9 -4
  58. package/components/ProductListSuggestions/ProductListSuggestions.graphql +5 -0
  59. package/components/ProductListSuggestions/ProductListSuggestions.tsx +42 -0
  60. package/components/ProductPageBreadcrumb/ProductPageBreadcrumb.graphql +3 -0
  61. package/components/ProductPageBreadcrumb/ProductPageBreadcrumb.tsx +3 -0
  62. package/components/ProductPageBreadcrumb/ProductPageBreadcrumbs.tsx +40 -0
  63. package/components/ProductPageBreadcrumb/index.ts +1 -0
  64. package/components/ProductPageDescription/ComplexTextValue.graphql +1 -1
  65. package/components/ProductPageDescription/ProductPageDescription.tsx +1 -1
  66. package/components/ProductPageGallery/ProductImage.graphql +1 -0
  67. package/components/ProductPageGallery/ProductPageGallery.tsx +14 -8
  68. package/components/ProductPagePrice/ProductPagePrice.graphql +0 -6
  69. package/components/ProductPagePrice/ProductPagePrice.tsx +19 -12
  70. package/components/ProductPagePrice/ProductPagePriceTiers.tsx +4 -3
  71. package/components/ProductPagePrice/useCustomizableOptionPrice.ts +11 -53
  72. package/components/ProductShortDescription/ProductShortDescription.tsx +2 -0
  73. package/components/ProductStaticPaths/getProductStaticPaths.ts +2 -3
  74. package/components/ProductStaticPaths/getSitemapPaths.ts +3 -0
  75. package/components/ProductWeight/ProductWeight.tsx +12 -9
  76. package/components/index.ts +2 -0
  77. package/hooks/useProductList.ts +123 -0
  78. package/hooks/useProductListLink.ts +6 -3
  79. package/index.ts +1 -0
  80. package/package.json +14 -13
@@ -1,4 +1,4 @@
1
- fragment ProductListItem on ProductInterface @injectable {
1
+ fragment ProductListItem on ProductInterface {
2
2
  uid
3
3
  ...ProductLink
4
4
  sku
@@ -11,5 +11,4 @@ fragment ProductListItem on ProductInterface @injectable {
11
11
  ...ProductListPrice
12
12
  }
13
13
  }
14
- ...ConfigurableOptions
15
14
  }
@@ -1,4 +1,4 @@
1
- fragment ProductPageItem on ProductInterface @injectable {
1
+ fragment ProductPageItem on ProductInterface {
2
2
  __typename
3
3
  uid
4
4
  ...ProductListItem
package/CHANGELOG.md CHANGED
@@ -1,5 +1,120 @@
1
1
  # Change Log
2
2
 
3
+ ## 8.1.0-canary.52
4
+
5
+ ## 8.1.0-canary.51
6
+
7
+ ### Minor Changes
8
+
9
+ - [#2322](https://github.com/graphcommerce-org/graphcommerce/pull/2322) [`4d08a2b`](https://github.com/graphcommerce-org/graphcommerce/commit/4d08a2bd8c1919bd85b18e8e856775d18fb67e00) - Rename configurable_customizable back to customizable_options
10
+ ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
11
+
12
+ ## 8.1.0-canary.50
13
+
14
+ ## 8.1.0-canary.49
15
+
16
+ ## 8.1.0-canary.48
17
+
18
+ ## 8.1.0-canary.47
19
+
20
+ ## 8.1.0-canary.46
21
+
22
+ ## 8.1.0-canary.45
23
+
24
+ ## 8.1.0-canary.44
25
+
26
+ ## 8.1.0-canary.43
27
+
28
+ ## 8.1.0-canary.42
29
+
30
+ ## 8.1.0-canary.41
31
+
32
+ ### Patch Changes
33
+
34
+ - [#2242](https://github.com/graphcommerce-org/graphcommerce/pull/2242) [`a4cce76`](https://github.com/graphcommerce-org/graphcommerce/commit/a4cce76ca37af2bec604e953ada4bb11bd91f55d) - Add option to show an extended version of the pagination component. Configurable via the "productListPaginationVariant" key in your graphcommerce.config.js
35
+ COMPACT means: "< Page X of Y >"
36
+ EXTENDED means: "< 1 2 ... [5] ... 10 11 >" ([@FrankHarland](https://github.com/FrankHarland))
37
+
38
+ ## 8.1.0-canary.40
39
+
40
+ ## 8.1.0-canary.39
41
+
42
+ ## 8.1.0-canary.38
43
+
44
+ ## 8.1.0-canary.37
45
+
46
+ ## 8.1.0-canary.36
47
+
48
+ ## 8.1.0-canary.35
49
+
50
+ ## 8.1.0-canary.34
51
+
52
+ ## 8.1.0-canary.33
53
+
54
+ ## 8.1.0-canary.32
55
+
56
+ ## 8.1.0-canary.31
57
+
58
+ ## 8.1.0-canary.30
59
+
60
+ ## 8.1.0-canary.29
61
+
62
+ ## 8.1.0-canary.28
63
+
64
+ ## 8.1.0-canary.27
65
+
66
+ ### Minor Changes
67
+
68
+ - [#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
69
+ ([@Jessevdpoel](https://github.com/Jessevdpoel))
70
+
71
+ ## 8.1.0-canary.26
72
+
73
+ ## 8.1.0-canary.25
74
+
75
+ ## 8.1.0-canary.24
76
+
77
+ ## 8.1.0-canary.23
78
+
79
+ ## 8.1.0-canary.22
80
+
81
+ ## 8.1.0-canary.21
82
+
83
+ ## 8.1.0-canary.20
84
+
85
+ ## 8.1.0-canary.19
86
+
87
+ ## 8.1.0-canary.18
88
+
89
+ ## 8.1.0-canary.17
90
+
91
+ ## 8.1.0-canary.16
92
+
93
+ ## 8.1.0-canary.15
94
+
95
+ ## 8.1.0-canary.14
96
+
97
+ ## 8.1.0-canary.13
98
+
99
+ ## 8.1.0-canary.12
100
+
101
+ ## 8.1.0-canary.11
102
+
103
+ ### Patch Changes
104
+
105
+ - [#2255](https://github.com/graphcommerce-org/graphcommerce/pull/2255) [`679d07d`](https://github.com/graphcommerce-org/graphcommerce/commit/679d07dad5b5e2dab3c0f3d537716b6115af8ef7) - make the ProductPageMeta fragment injectable
106
+ ([@carlocarels90](https://github.com/carlocarels90))
107
+
108
+ ## 8.1.0-canary.10
109
+
110
+ ## 8.1.0-canary.9
111
+
112
+ ## 8.1.0-canary.8
113
+
114
+ ## 8.1.0-canary.7
115
+
116
+ ## 8.1.0-canary.6
117
+
3
118
  ## 8.1.0-canary.5
4
119
 
5
120
  ### Patch Changes
package/Config.graphqls CHANGED
@@ -3,6 +3,11 @@ enum ProductFiltersLayout {
3
3
  SIDEBAR
4
4
  }
5
5
 
6
+ enum PaginationVariant {
7
+ COMPACT
8
+ EXTENDED
9
+ }
10
+
6
11
  extend input GraphCommerceConfig {
7
12
  """
8
13
  Product filters with better UI for mobile and desktop.
@@ -37,4 +42,12 @@ extend input GraphCommerceConfig {
37
42
  Default: 'false'
38
43
  """
39
44
  crossSellsHideCartItems: Boolean = false
45
+
46
+ """
47
+ Pagination variant for the product listings.
48
+
49
+ COMPACT means: "< Page X of Y >"
50
+ EXTENDED means: "< 1 2 ... 4 [5] 6 ... 10 11 >"
51
+ """
52
+ productListPaginationVariant: PaginationVariant = COMPACT
40
53
  }
@@ -1,5 +1,5 @@
1
1
  import { Button, ButtonProps } from '@graphcommerce/next-ui'
2
- import { Trans } from '@lingui/react'
2
+ import { Trans } from '@lingui/macro'
3
3
  import {
4
4
  useAddProductsToCartAction,
5
5
  UseAddProductsToCartActionProps,
@@ -17,6 +17,7 @@ export type AddProductsToCartButtonProps = UseAddProductsToCartActionProps &
17
17
  | 'onClick'
18
18
  | 'sx'
19
19
  | 'children'
20
+ | 'type'
20
21
  >
21
22
 
22
23
  export function AddProductsToCartButton(props: AddProductsToCartButtonProps) {
@@ -25,7 +26,7 @@ export function AddProductsToCartButton(props: AddProductsToCartButtonProps) {
25
26
 
26
27
  return (
27
28
  <Button type='submit' color='primary' variant='pill' size='large' {...rest} {...action}>
28
- {children || <Trans id='Add to Cart' />}
29
+ {children || <Trans>Add to Cart</Trans>}
29
30
  </Button>
30
31
  )
31
32
  }
@@ -1,5 +1,5 @@
1
1
  import { Fab, FabProps, iconShoppingBag, iconCheckmark } from '@graphcommerce/next-ui'
2
- import { i18n } from '@lingui/core'
2
+ import { t } from '@lingui/macro'
3
3
  import { SxProps, Theme } from '@mui/material'
4
4
  import {
5
5
  useAddProductsToCartAction,
@@ -22,7 +22,7 @@ export function AddProductsToCartFab(props: AddProductsToCartFabProps) {
22
22
  {...rest}
23
23
  {...action}
24
24
  icon={showSuccess && !action.loading ? iconCheckmark : icon}
25
- aria-label={i18n._(/* i18n*/ `Add to Cart`)}
25
+ aria-label={t`Add to Cart`}
26
26
  />
27
27
  )
28
28
  }
@@ -5,8 +5,8 @@ import {
5
5
  CrosssellsDocument,
6
6
  CrosssellsQuery,
7
7
  } from '@graphcommerce/magento-cart'
8
- import { ExtendableComponent, nonNullable } from '@graphcommerce/next-ui'
9
- import { Box, SxProps, Theme, useThemeProps } from '@mui/material'
8
+ import { ErrorSnackbarProps, MessageSnackbarProps, nonNullable } from '@graphcommerce/next-ui'
9
+ import { Box, SxProps, Theme } from '@mui/material'
10
10
  import { useRouter } from 'next/router'
11
11
  import { useMemo, useRef } from 'react'
12
12
  import { AddProductsToCartDocument, AddProductsToCartMutation } from './AddProductsToCart.gql'
@@ -22,30 +22,27 @@ import {
22
22
  } from './useFormAddProductsToCart'
23
23
 
24
24
  export type AddProductsToCartFormProps = {
25
- // The props are actually used, but are passed through useThemeProps and that breaks react/no-unused-prop-types
26
- // eslint-disable-next-line react/no-unused-prop-types
27
25
  children: React.ReactNode
28
- // eslint-disable-next-line react/no-unused-prop-types
29
26
  sx?: SxProps<Theme>
30
- // eslint-disable-next-line react/no-unused-prop-types
31
27
  redirect?: RedirectType
32
-
28
+ snackbarProps?: AddProductsToCartSnackbarProps
29
+
30
+ /**
31
+ * @deprecated use snackbarProps.errorSnackbar instead
32
+ */
33
+ errorSnackbar?: Omit<ErrorSnackbarProps, 'open'>
34
+ /**
35
+ * @deprecated use snackbarProps.successSnackbar instead
36
+ */
37
+ successSnackbar?: Omit<MessageSnackbarProps, 'open' | 'action'>
38
+ /**
39
+ * @deprecated use snackbarProps.disableSuccessSnackbar instead
40
+ */
33
41
  disableSuccessSnackbar?: boolean
34
- } & UseFormGraphQlOptions<AddProductsToCartMutation, AddProductsToCartFields> &
35
- AddProductsToCartSnackbarProps
42
+ } & UseFormGraphQlOptions<AddProductsToCartMutation, AddProductsToCartFields>
36
43
 
37
44
  const name = 'AddProductsToCartForm'
38
45
 
39
- /** Expose the component to be exendable in your theme.components */
40
- declare module '@mui/material/styles/components' {
41
- interface Components {
42
- AddProductsToCartForm?: Pick<
43
- ExtendableComponent<Omit<AddProductsToCartFormProps, 'children'>>,
44
- 'defaultProps'
45
- >
46
- }
47
- }
48
-
49
46
  /**
50
47
  * Component that handles adding products to the cart. Used on the product page, but can be used for
51
48
  * any product listing.
@@ -66,8 +63,9 @@ export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
66
63
  disableSuccessSnackbar,
67
64
  errorSnackbar,
68
65
  successSnackbar,
66
+ snackbarProps,
69
67
  ...formProps
70
- } = useThemeProps({ name, props })
68
+ } = props
71
69
  const router = useRouter()
72
70
  const client = useApolloClient()
73
71
  const crosssellsQuery = useRef<Promise<ApolloQueryResult<CrosssellsQuery>>>()
@@ -90,7 +88,7 @@ export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
90
88
  const requestData = {
91
89
  cartId,
92
90
  cartItems: cartItems
93
- .filter((cartItem) => cartItem.sku)
91
+ .filter((cartItem) => cartItem.sku && cartItem.quantity !== 0)
94
92
  .map(({ customizable_options, ...cartItem }) => {
95
93
  const options = Object.values(customizable_options ?? {})
96
94
  .flat(1)
@@ -103,7 +101,12 @@ export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
103
101
  ...(cartItem.selected_options ?? []).filter(Boolean),
104
102
  ...options,
105
103
  ],
106
- entered_options: cartItem.entered_options?.filter((option) => option?.value),
104
+ entered_options: [
105
+ ...(cartItem.entered_options
106
+ ?.filter((option) => option?.value)
107
+ .filter(nonNullable)
108
+ .map((option) => ({ uid: option.uid, value: `${option?.value}` })) ?? []),
109
+ ],
107
110
  }
108
111
  }),
109
112
  }
@@ -155,12 +158,12 @@ export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
155
158
  <Box component='form' onSubmit={submit} noValidate sx={sx} className={name}>
156
159
  {children}
157
160
  </Box>
158
- {disableSuccessSnackbar ? null : (
159
- <AddProductsToCartSnackbar
160
- errorSnackbar={errorSnackbar}
161
- successSnackbar={successSnackbar}
162
- />
163
- )}
161
+ <AddProductsToCartSnackbar
162
+ errorSnackbar={errorSnackbar}
163
+ successSnackbar={successSnackbar}
164
+ disableSuccessSnackbar={disableSuccessSnackbar}
165
+ {...snackbarProps}
166
+ />
164
167
  </AddProductsToCartContext.Provider>
165
168
  )
166
169
  }
@@ -6,12 +6,13 @@ import {
6
6
  ErrorSnackbarProps,
7
7
  iconChevronRight,
8
8
  IconSvg,
9
+ ListFormat,
9
10
  MessageSnackbar,
10
11
  MessageSnackbarProps,
11
12
  nonNullable,
12
13
  useLocale,
13
14
  } from '@graphcommerce/next-ui'
14
- import { Trans } from '@lingui/react'
15
+ import { Plural, Trans } from '@lingui/macro'
15
16
  import { useMemo } from 'react'
16
17
  import { findAddedItems } from './findAddedItems'
17
18
  import { toUserErrors } from './toUserErrors'
@@ -20,18 +21,19 @@ import { useFormAddProductsToCart } from './useFormAddProductsToCart'
20
21
  export type AddProductsToCartSnackbarProps = {
21
22
  errorSnackbar?: Omit<ErrorSnackbarProps, 'open'>
22
23
  successSnackbar?: Omit<MessageSnackbarProps, 'open' | 'action'>
24
+ disableSuccessSnackbar?: boolean
23
25
  }
24
26
 
25
27
  export function AddProductsToCartSnackbar(props: AddProductsToCartSnackbarProps) {
26
- const { errorSnackbar, successSnackbar } = props
28
+ const { errorSnackbar, successSnackbar, disableSuccessSnackbar } = props
27
29
  const { error, data, redirect, control, submittedVariables } = useFormAddProductsToCart()
28
30
  const formState = useFormState({ control })
29
31
 
30
- const formatter = new Intl.ListFormat(useLocale(), { style: 'long', type: 'conjunction' })
31
-
32
+ const locale = useLocale()
32
33
  const userErrors = toUserErrors(data)
33
34
 
34
35
  const showSuccess =
36
+ !disableSuccessSnackbar &&
35
37
  !formState.isSubmitting &&
36
38
  formState.isSubmitSuccessful &&
37
39
  !error?.message &&
@@ -71,22 +73,29 @@ export function AddProductsToCartSnackbar(props: AddProductsToCartSnackbarProps)
71
73
  endIcon={<IconSvg src={iconChevronRight} />}
72
74
  sx={{ display: 'flex' }}
73
75
  >
74
- <Trans id='View shopping cart' />
76
+ <Trans>View shopping cart</Trans>
75
77
  </Button>
76
78
  }
77
79
  >
78
- <Trans
79
- id={
80
- addedItems.length === 1
81
- ? '<0>{name}</0> has been added to your shopping cart!'
82
- : '<0>{name}</0> have been added to your shopping cart!'
80
+ <Plural
81
+ value={addedItems.length}
82
+ one={
83
+ <Trans>
84
+ <ListFormat listStyle='long' type='conjunction'>
85
+ {addedItems.map((item) => item?.itemInCart?.product.name).filter(nonNullable)}
86
+ </ListFormat>{' '}
87
+ has been added to your shopping cart
88
+ </Trans>
89
+ }
90
+ two={
91
+ <Trans>
92
+ <ListFormat listStyle='long' type='conjunction'>
93
+ {addedItems.map((item) => item?.itemInCart?.product.name).filter(nonNullable)}
94
+ </ListFormat>{' '}
95
+ have been added to your shopping cart!
96
+ </Trans>
83
97
  }
84
- components={{ 0: <strong /> }}
85
- values={{
86
- name: formatter.format(
87
- addedItems.map((item) => item?.itemInCart?.product.name).filter(nonNullable),
88
- ),
89
- }}
98
+ other={<Trans># products have been added to your shopping cart!</Trans>}
90
99
  />
91
100
  </MessageSnackbar>
92
101
  )}
@@ -1,4 +1,4 @@
1
- fragment UseAddProductsToCartAction on ProductInterface @injectable {
1
+ fragment UseAddProductsToCartAction on ProductInterface {
2
2
  uid
3
3
  sku
4
4
  only_x_left_in_stock
@@ -47,10 +47,7 @@ export function findAddedItems(
47
47
  }
48
48
  }
49
49
 
50
- const customizable_options = isTypename(cartItem, ['ConfigurableCartItem'])
51
- ? cartItem.configurable_customizable
52
- : cartItem.customizable_options
53
-
50
+ const { customizable_options } = cartItem
54
51
  const matchEntered = filterNonNullableKeys(itemVariable.entered_options).every(
55
52
  (requestOption) =>
56
53
  customizable_options.find(
@@ -68,7 +68,8 @@ export function useAddProductsToCartAction(
68
68
  if (process.env.NODE_ENV !== 'production') {
69
69
  if (!sku) console.warn(`You must provide a 'sku' to useAddProductsToCartAction`)
70
70
  }
71
- setValue(`cartItems.${index}.sku`, sku ?? '')
71
+ // TODO should be removed, setting the form value on submission isn't a great idea.
72
+ if (!getValues(`cartItems.${index}.sku`)) setValue(`cartItems.${index}.sku`, sku ?? '')
72
73
  startTransition(() => {
73
74
  onClickIncoming?.(e)
74
75
  })
@@ -1,11 +1,10 @@
1
1
  import { UseFormGqlMutationReturn } from '@graphcommerce/ecommerce-ui'
2
2
  import { createContext, useContext } from 'react'
3
- import type { LiteralUnion } from 'type-fest'
3
+ import type { Simplify, LiteralUnion } from 'type-fest'
4
4
  import {
5
5
  AddProductsToCartMutation,
6
6
  AddProductsToCartMutationVariables,
7
7
  } from './AddProductsToCart.gql'
8
- import { Simplify } from 'type-fest'
9
8
 
10
9
  export type RedirectType = LiteralUnion<'added' | undefined | false, `/${string}`>
11
10
 
@@ -1,4 +1,4 @@
1
- fragment JsonLdProduct on ProductInterface @inject(into: ["ProductPageItem"]) @injectable {
1
+ fragment JsonLdProduct on ProductInterface @inject(into: ["ProductPageItem"]) {
2
2
  uid
3
3
  name
4
4
  sku
@@ -13,5 +13,5 @@ export function ProductPageJsonLd<T extends { '@type': string }, P extends JsonL
13
13
  props: ProductPageJsonLdProps<T, P>,
14
14
  ) {
15
15
  const { product, render } = props
16
- return <JsonLd<T> item={render(product)} />
16
+ return <JsonLd<T> item={render(product)} keyVal='product-jsonld' />
17
17
  }
@@ -9,7 +9,7 @@ import {
9
9
  IconSvg,
10
10
  extendableComponent,
11
11
  } from '@graphcommerce/next-ui'
12
- import { Trans } from '@lingui/react'
12
+ import { Trans } from '@lingui/macro'
13
13
  import { Divider, Typography, ButtonProps, Box, Alert } from '@mui/material'
14
14
  import React from 'react'
15
15
  import { ProductAddToCartDocument, ProductAddToCartMutationVariables } from './ProductAddToCart.gql'
@@ -93,7 +93,7 @@ export function ProductAddToCart(
93
93
  })}
94
94
  {...buttonProps}
95
95
  >
96
- <Trans id='Add to Cart' />
96
+ <Trans>Add to Cart</Trans>
97
97
  </Button>
98
98
  {additionalButtons}
99
99
  </Box>
@@ -125,15 +125,13 @@ export function ProductAddToCart(
125
125
  color='secondary'
126
126
  endIcon={<IconSvg src={iconChevronRight} />}
127
127
  >
128
- <Trans id='View shopping cart' />
128
+ <Trans>View shopping cart</Trans>
129
129
  </Button>
130
130
  }
131
131
  >
132
- <Trans
133
- id='<0>{name}</0> has been added to your shopping cart!'
134
- components={{ 0: <strong /> }}
135
- values={{ name }}
136
- />
132
+ <Trans>
133
+ <strong>{name}</strong> has been added to your shopping cart!
134
+ </Trans>
137
135
  </MessageSnackbar>
138
136
  </Box>
139
137
  )
@@ -1,4 +1,4 @@
1
- fragment ProductCustomizable on CustomizableProductInterface @injectable {
1
+ fragment ProductCustomizable on CustomizableProductInterface {
2
2
  options {
3
3
  uid
4
4
  __typename
@@ -1 +1,2 @@
1
1
  export * from './ProductCustomizable'
2
+ export * from './productCustomizableSelectors'
@@ -0,0 +1,59 @@
1
+ import type { PriceTypeEnum } from '@graphcommerce/graphql-mesh'
2
+ import type { Simplify } from 'type-fest'
3
+ import type { CustomizableAreaOptionFragment } from './CustomizableAreaOption.gql'
4
+ import type { CustomizableCheckboxOptionFragment } from './CustomizableCheckboxOption.gql'
5
+ import type { CustomizableDateOptionFragment } from './CustomizableDateOption.gql'
6
+ import type { CustomizableDropDownOptionFragment } from './CustomizableDropDownOption.gql'
7
+ import type { CustomizableFieldOptionFragment } from './CustomizableFieldOption.gql'
8
+ import type { CustomizableFileOptionFragment } from './CustomizableFileOption.gql'
9
+ import type { CustomizableMultipleOptionFragment } from './CustomizableMultipleOption.gql'
10
+ import type { CustomizableRadioOptionFragment } from './CustomizableRadioOption.gql'
11
+ import type { ProductCustomizable_SimpleProduct_Fragment } from './ProductCustomizable.gql'
12
+
13
+ export type CustomizableProductOptionBase =
14
+ | {
15
+ price?: number | null | undefined
16
+ price_type?: PriceTypeEnum | null | undefined
17
+ uid?: string | null | undefined
18
+ }
19
+ | undefined
20
+ | null
21
+
22
+ export type AnyOption = NonNullable<
23
+ NonNullable<ProductCustomizable_SimpleProduct_Fragment['options']>[number]
24
+ >
25
+
26
+ export type OptionValueSelector = {
27
+ [T in AnyOption as T['__typename']]: (
28
+ option: T,
29
+ ) => CustomizableProductOptionBase | CustomizableProductOptionBase[]
30
+ }
31
+
32
+ type MissingOptionValueSelectors = Omit<
33
+ OptionValueSelector,
34
+ keyof typeof productCustomizableSelectors
35
+ >
36
+ type DefinedOptionValueSelectors = Partial<
37
+ Pick<OptionValueSelector, keyof typeof productCustomizableSelectors>
38
+ >
39
+
40
+ type Selectors = Simplify<
41
+ keyof MissingOptionValueSelectors extends never
42
+ ? (MissingOptionValueSelectors & DefinedOptionValueSelectors) | undefined
43
+ : MissingOptionValueSelectors & DefinedOptionValueSelectors
44
+ >
45
+
46
+ export const productCustomizableSelectors = {
47
+ CustomizableAreaOption: (o: CustomizableAreaOptionFragment) => o.areaValue,
48
+ CustomizableCheckboxOption: (o: CustomizableCheckboxOptionFragment) => o.checkboxValue,
49
+ CustomizableFileOption: (o: CustomizableFileOptionFragment) => o.fileValue,
50
+ CustomizableDateOption: (o: CustomizableDateOptionFragment) => o.dateValue,
51
+ CustomizableDropDownOption: (o: CustomizableDropDownOptionFragment) => o.dropdownValue,
52
+ CustomizableFieldOption: (o: CustomizableFieldOptionFragment) => o.fieldValue,
53
+ CustomizableMultipleOption: (o: CustomizableMultipleOptionFragment) => o.multipleValue,
54
+ CustomizableRadioOption: (o: CustomizableRadioOptionFragment) => o.radioValue,
55
+ }
56
+
57
+ export type SelectorsProp = keyof MissingOptionValueSelectors extends never
58
+ ? { selectors?: Selectors }
59
+ : { selectors: Selectors }
@@ -1,10 +1,9 @@
1
1
  import { FilterRangeTypeInput } from '@graphcommerce/graphql-mesh'
2
2
  import { Money } from '@graphcommerce/magento-store'
3
3
  import { extendableComponent, filterNonNullableKeys } from '@graphcommerce/next-ui'
4
- // eslint-disable-next-line @typescript-eslint/no-restricted-imports
5
4
  import { Box, Slider, SxProps, Theme, useEventCallback } from '@mui/material'
6
5
  import { useCallback } from 'react'
7
- import { FilterProps } from './ProductFiltersProAggregations'
6
+ import type { FilterProps } from './ProductFiltersProAggregations'
8
7
 
9
8
  export type PriceSliderProps = {
10
9
  value: FilterRangeTypeInput | null | undefined
@@ -12,7 +12,7 @@ import { Box } from '@mui/material'
12
12
  import { useMemo } from 'react'
13
13
  import { isFilterTypeEqual } from '../ProductListItems/filterTypes'
14
14
  import { useProductFiltersPro } from './ProductFiltersPro'
15
- import { FilterProps } from './ProductFiltersProAggregations'
15
+ import type { FilterProps } from './ProductFiltersProAggregations'
16
16
 
17
17
  export function ProductFilterEqualChip(props: FilterProps) {
18
18
  const { aggregation } = props
@@ -14,7 +14,7 @@ import { Box } from '@mui/material'
14
14
  import { useMemo } from 'react'
15
15
  import { isFilterTypeEqual } from '../ProductListItems/filterTypes'
16
16
  import { useProductFiltersPro } from './ProductFiltersPro'
17
- import { FilterProps } from './ProductFiltersProAggregations'
17
+ import type { FilterProps } from './ProductFiltersProAggregations'
18
18
 
19
19
  export function ProductFilterEqualSection(props: FilterProps) {
20
20
  const { aggregation } = props
@@ -66,7 +66,7 @@ export function ProductFilterEqualSection(props: FilterProps) {
66
66
  multiple
67
67
  layout='list'
68
68
  variant='default'
69
- size='medium'
69
+ size='responsive'
70
70
  items={items}
71
71
  showMoreAfter={4}
72
72
  />
@@ -5,7 +5,7 @@ import { ChipOverlayOrPopper, extendableComponent } from '@graphcommerce/next-ui
5
5
  import { isFilterTypeRange } from '../ProductListItems/filterTypes'
6
6
  import { getMinMaxFromOptions, PriceSlider } from './PriceSlider'
7
7
  import { useProductFiltersPro } from './ProductFiltersPro'
8
- import { FilterProps } from './ProductFiltersProAggregations'
8
+ import type { FilterProps } from './ProductFiltersProAggregations'
9
9
 
10
10
  const { classes } = extendableComponent('FilterRangeType', ['root', 'container', 'slider'] as const)
11
11
 
@@ -5,7 +5,7 @@ import { Trans } from '@lingui/react'
5
5
  import { isFilterTypeRange } from '../ProductListItems/filterTypes'
6
6
  import { PriceSlider, getMinMaxFromOptions } from './PriceSlider'
7
7
  import { useProductFiltersPro } from './ProductFiltersPro'
8
- import { FilterProps } from './ProductFiltersProAggregations'
8
+ import type { FilterProps } from './ProductFiltersProAggregations'
9
9
 
10
10
  export function ProductFilterRangeSection(props: FilterProps) {
11
11
  const { aggregation } = props