@graphcommerce/magento-product 4.7.3 → 4.8.1

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 CHANGED
@@ -1,5 +1,39 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1684](https://github.com/graphcommerce-org/graphcommerce/pull/1684) [`aab6b4fa5`](https://github.com/graphcommerce-org/graphcommerce/commit/aab6b4fa5b4708003cfb5bf673a617dc5dbf3078) Thanks [@paales](https://github.com/paales)! - Make sure the images are sorted according to their position field
8
+
9
+ - Updated dependencies [[`ae28fb14c`](https://github.com/graphcommerce-org/graphcommerce/commit/ae28fb14cec298c52970260a4fc2c2551b5f175e), [`98d6a9cce`](https://github.com/graphcommerce-org/graphcommerce/commit/98d6a9cce1bb9514088be0af2736721b3edda467)]:
10
+ - @graphcommerce/magento-cart@4.9.2
11
+ - @graphcommerce/next-ui@4.29.1
12
+ - @graphcommerce/ecommerce-ui@1.5.6
13
+ - @graphcommerce/framer-scroller@2.1.43
14
+ - @graphcommerce/magento-store@4.3.4
15
+
16
+ ## 4.8.0
17
+
18
+ ### Minor Changes
19
+
20
+ - [#1679](https://github.com/graphcommerce-org/graphcommerce/pull/1679) [`2b5451395`](https://github.com/graphcommerce-org/graphcommerce/commit/2b5451395dc1173de55d18d08968866e561f90ab) Thanks [@paales](https://github.com/paales)! - Move AddProductsToCartSnackbar to inside AddProductsToCartForm and make AddProductsToCartForm configrable via theme.ts
21
+
22
+ - [#1679](https://github.com/graphcommerce-org/graphcommerce/pull/1679) [`e76df6dc3`](https://github.com/graphcommerce-org/graphcommerce/commit/e76df6dc37c11c793a5d008ba36932d17dc23855) Thanks [@paales](https://github.com/paales)! - Added AddProductsToCartFab for a smaller add to cart button
23
+
24
+ - [#1678](https://github.com/graphcommerce-org/graphcommerce/pull/1678) [`78d7d51cb`](https://github.com/graphcommerce-org/graphcommerce/commit/78d7d51cb1551601d3a4756cd1f2157a49ff93b9) Thanks [@Jessevdpoel](https://github.com/Jessevdpoel)! - Changed styling and forwarded breadcrumbprops
25
+
26
+ ### Patch Changes
27
+
28
+ - [#1679](https://github.com/graphcommerce-org/graphcommerce/pull/1679) [`c4ed376e2`](https://github.com/graphcommerce-org/graphcommerce/commit/c4ed376e2c72b16b34704d7d1ca69c074de172ba) Thanks [@paales](https://github.com/paales)! - Support passing children to AddProductsToCartButton instead of Add To Cart
29
+
30
+ - Updated dependencies [[`e76df6dc3`](https://github.com/graphcommerce-org/graphcommerce/commit/e76df6dc37c11c793a5d008ba36932d17dc23855), [`0bd9ea582`](https://github.com/graphcommerce-org/graphcommerce/commit/0bd9ea58230dde79c5fe2cdb07e9860151460270)]:
31
+ - @graphcommerce/next-ui@4.29.0
32
+ - @graphcommerce/ecommerce-ui@1.5.5
33
+ - @graphcommerce/framer-scroller@2.1.42
34
+ - @graphcommerce/magento-cart@4.9.1
35
+ - @graphcommerce/magento-store@4.3.3
36
+
3
37
  ## 4.7.3
4
38
 
5
39
  ### Patch Changes
@@ -1,48 +1,31 @@
1
1
  import { Button, ButtonProps } from '@graphcommerce/next-ui'
2
2
  import { Trans } from '@lingui/react'
3
- import { SxProps, Theme, useEventCallback } from '@mui/material'
4
- import { useFormAddProductsToCart } from './AddProductsToCartForm'
3
+ import {
4
+ useAddProductsToCartAction,
5
+ UseAddProductsToCartActionProps,
6
+ } from './useAddProductsToCartAction'
5
7
 
6
- export type AddProductsToCartButtonProps = {
7
- sx?: SxProps<Theme>
8
- sku: string
9
- index?: number
10
- } & Pick<
11
- ButtonProps<'button'>,
12
- | 'variant'
13
- | 'color'
14
- | 'size'
15
- | 'disabled'
16
- | 'fullWidth'
17
- | 'startIcon'
18
- | 'endIcon'
19
- | 'onClick'
20
- | 'loading'
21
- >
8
+ export type AddProductsToCartButtonProps = UseAddProductsToCartActionProps &
9
+ Pick<
10
+ ButtonProps<'button'>,
11
+ | 'variant'
12
+ | 'color'
13
+ | 'size'
14
+ | 'fullWidth'
15
+ | 'startIcon'
16
+ | 'endIcon'
17
+ | 'onClick'
18
+ | 'sx'
19
+ | 'children'
20
+ >
22
21
 
23
22
  export function AddProductsToCartButton(props: AddProductsToCartButtonProps) {
24
- const { formState, setValue } = useFormAddProductsToCart()
25
- const { loading, sku, index = 0, disabled, onClick } = props
26
-
27
- const clickHandler: NonNullable<AddProductsToCartButtonProps['onClick']> = useEventCallback(
28
- (e) => {
29
- setValue(`cartItems.${index}.sku`, sku)
30
- onClick?.(e)
31
- },
32
- )
23
+ const { children } = props
24
+ const action = useAddProductsToCartAction(props)
33
25
 
34
26
  return (
35
- <Button
36
- type='submit'
37
- color='primary'
38
- variant='pill'
39
- size='large'
40
- {...props}
41
- disabled={Boolean(formState.errors.cartItems?.[index].sku?.message) || disabled}
42
- loading={formState.isSubmitting || loading}
43
- onClick={clickHandler}
44
- >
45
- <Trans id='Add to Cart' />
27
+ <Button type='submit' color='primary' variant='pill' size='large' {...props} {...action}>
28
+ {children || <Trans id='Add to Cart' />}
46
29
  </Button>
47
30
  )
48
31
  }
@@ -1,5 +1,5 @@
1
1
  import { FormHelperText } from '@mui/material'
2
- import { useFormAddProductsToCart } from './AddProductsToCartForm'
2
+ import { useFormAddProductsToCart } from './useFormAddProductsToCart'
3
3
 
4
4
  type AddProductsToCartErrorProps = {
5
5
  children?: React.ReactNode
@@ -0,0 +1,18 @@
1
+ import { Fab, FabProps, iconShoppingBag } from '@graphcommerce/next-ui'
2
+ import { SxProps, Theme } from '@mui/material'
3
+ import {
4
+ useAddProductsToCartAction,
5
+ UseAddProductsToCartActionProps,
6
+ } from './useAddProductsToCartAction'
7
+
8
+ export type AddProductsToCartFabProps = {
9
+ sx?: SxProps<Theme>
10
+ icon?: FabProps['icon']
11
+ } & Pick<FabProps, 'color' | 'size'> &
12
+ UseAddProductsToCartActionProps
13
+
14
+ export function AddProductsToCartFab(props: AddProductsToCartFabProps) {
15
+ const { icon = iconShoppingBag } = props
16
+ const action = useAddProductsToCartAction(props)
17
+ return <Fab type='submit' {...props} {...action} icon={icon} />
18
+ }
@@ -1,104 +1,111 @@
1
- import { UseFormGqlMutationReturn, UseFormGraphQlOptions } from '@graphcommerce/ecommerce-ui'
1
+ import { UseFormGraphQlOptions } from '@graphcommerce/ecommerce-ui'
2
2
  import { useFormGqlMutationCart } from '@graphcommerce/magento-cart'
3
- import { Box, SxProps, Theme } from '@mui/material'
3
+ import { ExtendableComponent } from '@graphcommerce/next-ui'
4
+ import { Box, SxProps, Theme, useThemeProps } from '@mui/material'
4
5
  import { useRouter } from 'next/router'
5
- import { createContext, useContext, useEffect } from 'react'
6
+ import { useMemo } from 'react'
6
7
  import {
7
8
  AddProductsToCartDocument,
8
9
  AddProductsToCartMutation,
9
10
  AddProductsToCartMutationVariables,
10
11
  } from './AddProductsToCart.gql'
11
-
12
- type RedirectType = 'added' | 'cart' | 'checkout' | undefined
13
-
14
- type AddProductsToCartFormState = AddProductsToCartMutationVariables & {
15
- redirect?: RedirectType
16
- }
17
-
18
- type AddProductsToCartContextType = UseFormGqlMutationReturn<
19
- AddProductsToCartMutation,
20
- AddProductsToCartFormState
21
- >
22
-
23
- export const addProductsToCartContext = createContext(
24
- undefined as AddProductsToCartContextType | undefined,
25
- )
12
+ import {
13
+ AddProductsToCartSnackbar,
14
+ AddProductsToCartSnackbarProps,
15
+ } from './AddProductsToCartSnackbar'
16
+ import { AddProductsToCartContext, RedirectType } from './useFormAddProductsToCart'
26
17
 
27
18
  type AddProductsToCartFormProps = {
19
+ // The props are actually used, but are passed through useThemeProps and that breaks react/no-unused-prop-types
20
+ // eslint-disable-next-line react/no-unused-prop-types
28
21
  children: React.ReactNode
22
+ // eslint-disable-next-line react/no-unused-prop-types
29
23
  sx?: SxProps<Theme>
24
+ // eslint-disable-next-line react/no-unused-prop-types
30
25
  redirect?: RedirectType
31
- } & Omit<
32
- UseFormGraphQlOptions<AddProductsToCartMutation, AddProductsToCartFormState>,
33
- 'onBeforeSubmit'
34
- >
26
+ } & UseFormGraphQlOptions<AddProductsToCartMutation, AddProductsToCartMutationVariables> &
27
+ AddProductsToCartSnackbarProps
35
28
 
29
+ const name = 'AddProductsToCartForm'
30
+
31
+ /** Expose the component to be exendable in your theme.components */
32
+ declare module '@mui/material/styles/components' {
33
+ interface Components {
34
+ AddProductsToCartForm?: Pick<
35
+ ExtendableComponent<Omit<AddProductsToCartFormProps, 'children'>>,
36
+ 'defaultProps'
37
+ >
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Component that handles adding products to the cart. Used on the product page, but can be used for
43
+ * any product listing.
44
+ *
45
+ * Can be configured globally in your theme.ts;
46
+ *
47
+ * - Uses react-hook-form's useForm hook under the hood and exposes the form as a context which can be
48
+ * consumed with `useFormAddProductsToCart` hook.
49
+ * - Cleans up the submitted data.
50
+ * - Redirects the user to the cart/checkout/added page after successful submission.
51
+ */
36
52
  export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
37
- const { children, defaultValues, redirect, onComplete, sx, ...formProps } = props
53
+ const {
54
+ children,
55
+ redirect = 'cart',
56
+ onComplete,
57
+ sx,
58
+ errorSnackbar,
59
+ successSnackbar,
60
+ ...formProps
61
+ } = useThemeProps({ name, props })
38
62
  const router = useRouter()
39
63
 
40
- const form = useFormGqlMutationCart<AddProductsToCartMutation, AddProductsToCartFormState>(
41
- AddProductsToCartDocument,
42
- {
43
- defaultValues: {
44
- ...defaultValues,
45
- redirect,
46
- },
64
+ const form = useFormGqlMutationCart<
65
+ AddProductsToCartMutation,
66
+ AddProductsToCartMutationVariables
67
+ >(AddProductsToCartDocument, {
68
+ ...formProps,
69
+ // We're stripping out incomplete entered options.
70
+ onBeforeSubmit: async (variables) => {
71
+ const variables2 = (await formProps.onBeforeSubmit?.(variables)) ?? variables
72
+ if (variables2 === false) return false
47
73
 
48
- // We're stripping out incomplete entered options.
49
- onBeforeSubmit: ({ cartId, cartItems }) => ({
74
+ const { cartId, cartItems } = variables2
75
+ return {
50
76
  cartId,
51
77
  cartItems: cartItems
52
78
  .filter((cartItem) => cartItem.sku)
53
79
  .map((cartItem) => ({
54
80
  ...cartItem,
81
+ quantity: cartItem.quantity || 1,
55
82
  selected_options: cartItem.selected_options?.filter(Boolean),
56
83
  entered_options: cartItem.entered_options?.filter((option) => option?.value),
57
84
  })),
58
- }),
59
- onComplete: async (result, variables) => {
60
- await onComplete?.(result, variables)
85
+ }
86
+ },
87
+ onComplete: async (result, variables) => {
88
+ await onComplete?.(result, variables)
61
89
 
62
- if (
63
- result.data?.addProductsToCart?.user_errors?.length ||
64
- result.errors?.length ||
65
- !redirect
66
- )
67
- return
90
+ if (result.data?.addProductsToCart?.user_errors?.length || result.errors?.length || !redirect)
91
+ return
68
92
 
69
- if (redirect === 'checkout') await router.push('/checkout')
70
- if (redirect === 'added') await router.push({ pathname: '/checkout/added' })
71
- if (redirect === 'cart') await router.push({ pathname: '/cart' })
72
- },
73
- ...formProps,
93
+ if (redirect === 'checkout') await router.push('/checkout')
94
+ if (redirect === 'added') await router.push({ pathname: '/checkout/added' })
95
+ if (redirect === 'cart') await router.push({ pathname: '/cart' })
74
96
  },
75
- )
76
-
77
- // When the value changes, update the value in the form
78
- useEffect(() => {
79
- if (form.getValues('redirect') !== redirect) form.setValue('redirect', redirect)
80
- }, [form, redirect])
97
+ })
81
98
 
82
99
  const submit = form.handleSubmit(() => {})
83
100
 
84
101
  return (
85
- <addProductsToCartContext.Provider value={form}>
86
- <Box component='form' onSubmit={submit} noValidate sx={sx}>
102
+ <AddProductsToCartContext.Provider
103
+ value={useMemo(() => ({ ...form, redirect }), [form, redirect])}
104
+ >
105
+ <Box component='form' onSubmit={submit} noValidate sx={sx} className={name}>
87
106
  {children}
88
107
  </Box>
89
- </addProductsToCartContext.Provider>
108
+ <AddProductsToCartSnackbar errorSnackbar={errorSnackbar} successSnackbar={successSnackbar} />
109
+ </AddProductsToCartContext.Provider>
90
110
  )
91
111
  }
92
-
93
- export function useFormAddProductsToCart(optional: true): AddProductsToCartContextType | undefined
94
- export function useFormAddProductsToCart(optional?: false): AddProductsToCartContextType
95
- export function useFormAddProductsToCart(optional = false) {
96
- const context = useContext(addProductsToCartContext)
97
-
98
- if (!optional && typeof context === 'undefined') {
99
- throw Error(
100
- 'useFormAddProductsToCart must be used within a AddProductsToCartForm or provide the optional=true argument',
101
- )
102
- }
103
- return context
104
- }
@@ -1,5 +1,5 @@
1
1
  import { NumberFieldElement, NumberFieldElementProps } from '@graphcommerce/ecommerce-ui'
2
- import { useFormAddProductsToCart } from './AddProductsToCartForm'
2
+ import { useFormAddProductsToCart } from './useFormAddProductsToCart'
3
3
 
4
4
  type AddToCartQuantityProps = Omit<
5
5
  NumberFieldElementProps,
@@ -1,69 +1,84 @@
1
1
  import { ApolloCartErrorSnackbar } from '@graphcommerce/magento-cart'
2
2
  import {
3
3
  Button,
4
+ ErrorSnackbar,
5
+ ErrorSnackbarProps,
6
+ filterNonNullableKeys,
4
7
  iconChevronRight,
5
8
  IconSvg,
6
9
  MessageSnackbar,
7
- ErrorSnackbar,
10
+ MessageSnackbarProps,
8
11
  } from '@graphcommerce/next-ui'
9
12
  import { Trans } from '@lingui/react'
10
13
  import PageLink from 'next/link'
11
- import { useFormAddProductsToCart } from './AddProductsToCartForm'
14
+ import { useFormAddProductsToCart } from './useFormAddProductsToCart'
12
15
 
13
- type AddToCartMessageProps = { name?: string | null }
16
+ export type AddProductsToCartSnackbarProps = {
17
+ errorSnackbar?: Omit<ErrorSnackbarProps, 'open'>
18
+ successSnackbar?: Omit<MessageSnackbarProps, 'open' | 'action'>
19
+ }
14
20
 
15
- export function AddProductsToCartSnackbar(props: AddToCartMessageProps) {
16
- const { name } = props
17
- const { formState, error, data, getValues } = useFormAddProductsToCart()
21
+ export function AddProductsToCartSnackbar(props: AddProductsToCartSnackbarProps) {
22
+ const { errorSnackbar, successSnackbar } = props
23
+ const { formState, error, data, redirect } = useFormAddProductsToCart()
18
24
 
19
25
  const showSuccess =
20
26
  !formState.isSubmitting &&
21
27
  formState.isSubmitSuccessful &&
22
28
  !error?.message &&
23
29
  !data?.addProductsToCart?.user_errors?.length &&
24
- !getValues('redirect')
30
+ !redirect
25
31
 
32
+ const items = filterNonNullableKeys(data?.addProductsToCart?.cart.items)
33
+
34
+ const showErrorSnackbar = (data?.addProductsToCart?.user_errors?.length ?? 0) > 0
26
35
  return (
27
36
  <>
28
- <ApolloCartErrorSnackbar error={error} />
29
-
30
- <ErrorSnackbar
31
- variant='pill'
32
- severity='error'
33
- open={(data?.addProductsToCart?.user_errors?.length ?? 0) > 0}
34
- action={
35
- <Button size='medium' variant='pill' color='secondary'>
36
- <Trans id='Ok' />
37
- </Button>
38
- }
39
- >
40
- <>{data?.addProductsToCart?.user_errors?.map((e) => e?.message).join(', ')}</>
41
- </ErrorSnackbar>
37
+ {error && <ApolloCartErrorSnackbar error={error} />}
42
38
 
43
- <MessageSnackbar
44
- open={showSuccess}
45
- variant='pill'
46
- action={
47
- <PageLink href='/cart' passHref>
48
- <Button
49
- id='view-shopping-cart-button'
50
- size='medium'
51
- variant='pill'
52
- color='secondary'
53
- endIcon={<IconSvg src={iconChevronRight} />}
54
- sx={{ display: 'flex' }}
55
- >
56
- <Trans id='View shopping cart' />
39
+ {showErrorSnackbar && (
40
+ <ErrorSnackbar
41
+ variant='pill'
42
+ severity='error'
43
+ action={
44
+ <Button size='medium' variant='pill' color='secondary'>
45
+ <Trans id='Ok' />
57
46
  </Button>
58
- </PageLink>
59
- }
60
- >
61
- <Trans
62
- id='<0>{name}</0> has been added to your shopping cart!'
63
- components={{ 0: <strong /> }}
64
- values={{ name }}
65
- />
66
- </MessageSnackbar>
47
+ }
48
+ {...errorSnackbar}
49
+ open={showErrorSnackbar}
50
+ >
51
+ <>{data?.addProductsToCart?.user_errors?.map((e) => e?.message).join(', ')}</>
52
+ </ErrorSnackbar>
53
+ )}
54
+
55
+ {showSuccess && (
56
+ <MessageSnackbar
57
+ variant='pill'
58
+ {...successSnackbar}
59
+ open={showSuccess}
60
+ action={
61
+ <PageLink href='/cart' passHref>
62
+ <Button
63
+ id='view-shopping-cart-button'
64
+ size='medium'
65
+ variant='pill'
66
+ color='secondary'
67
+ endIcon={<IconSvg src={iconChevronRight} />}
68
+ sx={{ display: 'flex' }}
69
+ >
70
+ <Trans id='View shopping cart' />
71
+ </Button>
72
+ </PageLink>
73
+ }
74
+ >
75
+ <Trans
76
+ id='<0>{name}</0> has been added to your shopping cart!'
77
+ components={{ 0: <strong /> }}
78
+ values={{ name: items[items.length - 1]?.product.name }}
79
+ />
80
+ </MessageSnackbar>
81
+ )}
67
82
  </>
68
83
  )
69
84
  }
@@ -3,4 +3,5 @@ export * from './AddProductsToCartButton'
3
3
  export * from './AddProductsToCartError'
4
4
  export * from './AddProductsToCartForm'
5
5
  export * from './AddProductsToCartQuantity'
6
- export * from './AddProductsToCartSnackbar'
6
+ export * from './useFormAddProductsToCart'
7
+ export * from './AddProductsToCartFab'
@@ -0,0 +1,40 @@
1
+ import { useEventCallback } from '@mui/material'
2
+ import { useMemo } from 'react'
3
+ import { useFormAddProductsToCart } from './useFormAddProductsToCart'
4
+
5
+ export type UseAddProductsToCartActionProps = {
6
+ sku: string | null | undefined
7
+ index?: number
8
+ disabled?: boolean
9
+ loading?: boolean
10
+ onClick?: React.MouseEventHandler<HTMLButtonElement>
11
+ }
12
+
13
+ export type UseAddProductsToCartActionReturn = {
14
+ disabled: boolean
15
+ loading: boolean
16
+ onClick: React.MouseEventHandler<HTMLButtonElement>
17
+ onMouseDown: React.MouseEventHandler<HTMLButtonElement>
18
+ }
19
+
20
+ export function useAddProductsToCartAction(
21
+ props: UseAddProductsToCartActionProps,
22
+ ): UseAddProductsToCartActionReturn {
23
+ const { formState, setValue, getValues } = useFormAddProductsToCart()
24
+ const { sku, index = 0, onClick: onClickIncomming, disabled, loading } = props
25
+
26
+ return {
27
+ disabled: Boolean(formState.errors.cartItems?.[index].sku?.message || disabled),
28
+ loading: loading || (formState.isSubmitting && getValues(`cartItems.${index}.sku`) === sku),
29
+ onClick: useEventCallback((e) => {
30
+ e.stopPropagation()
31
+ if (formState.isSubmitting) return
32
+ if (process.env.NODE_ENV !== 'production') {
33
+ if (!sku) console.warn(`You must provide a 'sku' to useAddProductsToCartAction`)
34
+ }
35
+ setValue(`cartItems.${index}.sku`, sku ?? '')
36
+ onClickIncomming?.(e)
37
+ }),
38
+ onMouseDown: useEventCallback((e) => e.stopPropagation()),
39
+ }
40
+ }
@@ -0,0 +1,30 @@
1
+ import { UseFormGqlMutationReturn } from '@graphcommerce/ecommerce-ui'
2
+ import { createContext, useContext } from 'react'
3
+ import {
4
+ AddProductsToCartMutation,
5
+ AddProductsToCartMutationVariables,
6
+ } from './AddProductsToCart.gql'
7
+
8
+ export type RedirectType = 'added' | 'cart' | 'checkout' | undefined
9
+
10
+ export type AddProductsToCartContextType = { redirect: RedirectType } & UseFormGqlMutationReturn<
11
+ AddProductsToCartMutation,
12
+ AddProductsToCartMutationVariables
13
+ >
14
+
15
+ export const AddProductsToCartContext = createContext(
16
+ undefined as AddProductsToCartContextType | undefined,
17
+ )
18
+
19
+ export function useFormAddProductsToCart(optional: true): AddProductsToCartContextType | undefined
20
+ export function useFormAddProductsToCart(optional?: false): AddProductsToCartContextType
21
+ export function useFormAddProductsToCart(optional = false) {
22
+ const context = useContext(AddProductsToCartContext)
23
+
24
+ if (!optional && typeof context === 'undefined') {
25
+ throw Error(
26
+ 'useFormAddProductsToCart must be used within a AddProductsToCartForm or provide the optional=true argument',
27
+ )
28
+ }
29
+ return context
30
+ }
@@ -5,38 +5,36 @@ import PageLink from 'next/link'
5
5
  import { productPageCategory } from '../ProductPageCategory/productPageCategory'
6
6
  import { ProductPageBreadcrumbFragment } from './ProductPageBreadcrumb.gql'
7
7
 
8
- type ProductPageBreadcrumbsProps = ProductPageBreadcrumbFragment & BreadcrumbsProps
8
+ type ProductPageBreadcrumbsProps = ProductPageBreadcrumbFragment & Omit<BreadcrumbsProps, 'children'>
9
9
 
10
10
  export function ProductPageBreadcrumb(props: ProductPageBreadcrumbsProps) {
11
- const { categories, name } = props
11
+ const { categories, name, ...breadcrumbProps } = props
12
12
  const prev = usePrevPageRouter()
13
13
 
14
14
  const category =
15
15
  categories?.find((c) => `/${c?.url_path}` === prev?.asPath) ?? productPageCategory(props)
16
16
 
17
17
  return (
18
- <Container maxWidth={false}>
19
- <Breadcrumbs>
20
- <PageLink href='/' passHref>
21
- <Link underline='hover' color='inherit'>
22
- <Trans id='Home' />
23
- </Link>
24
- </PageLink>
25
- {category?.breadcrumbs?.map((mapped_category, i) => (
26
- <Link
27
- underline='hover'
28
- key={mapped_category?.category_uid}
29
- color='inherit'
30
- href={`/${mapped_category?.category_url_path}`}
31
- >
32
- {mapped_category?.category_name}
33
- </Link>
34
- ))}
35
- <Link underline='hover' color='inherit' href={`/${category?.url_path}`}>
36
- {category?.name}
18
+ <Breadcrumbs {...breadcrumbProps}>
19
+ <PageLink href='/' passHref>
20
+ <Link underline='hover' color='inherit'>
21
+ <Trans id='Home' />
37
22
  </Link>
38
- <Typography color='text.primary'>{name}</Typography>
39
- </Breadcrumbs>
40
- </Container>
23
+ </PageLink>
24
+ {category?.breadcrumbs?.map((mapped_category, i) => (
25
+ <Link
26
+ underline='hover'
27
+ key={mapped_category?.category_uid}
28
+ color='inherit'
29
+ href={`/${mapped_category?.category_url_path}`}
30
+ >
31
+ {mapped_category?.category_name}
32
+ </Link>
33
+ ))}
34
+ <Link underline='hover' color='inherit' href={`/${category?.url_path}`}>
35
+ {category?.name}
36
+ </Link>
37
+ <Typography color='text.primary'>{name}</Typography>
38
+ </Breadcrumbs>
41
39
  )
42
40
  }
@@ -1,4 +1,9 @@
1
- import { SidebarGallery, SidebarGalleryProps, TypeRenderer } from '@graphcommerce/next-ui'
1
+ import {
2
+ nonNullable,
3
+ SidebarGallery,
4
+ SidebarGalleryProps,
5
+ TypeRenderer,
6
+ } from '@graphcommerce/next-ui'
2
7
  import { PropsWithChildren } from 'react'
3
8
  import { ProductPageGalleryFragment } from './ProductPageGallery.gql'
4
9
 
@@ -23,14 +28,17 @@ export function ProductPageGallery(props: ProductPageGalleryProps) {
23
28
  sidebar={children}
24
29
  aspectRatio={[width, height]}
25
30
  images={
26
- media_gallery?.map((item) => {
27
- if (item?.__typename === 'ProductImage')
28
- return { src: item.url ?? '', alt: item.label || undefined, width, height }
29
- return {
30
- src: '',
31
- alt: `{${item?.__typename} not yet supported}`,
32
- }
33
- }) ?? []
31
+ media_gallery
32
+ ?.filter(nonNullable)
33
+ .sort((a, b) => (a.position ?? 0) - (b.position ?? 0))
34
+ .map((item) => {
35
+ if (item.__typename === 'ProductImage')
36
+ return { src: item.url ?? '', alt: item.label || undefined, width, height }
37
+ return {
38
+ src: '',
39
+ alt: `{${item.__typename} not yet supported}`,
40
+ }
41
+ }) ?? []
34
42
  }
35
43
  />
36
44
  )
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": "4.7.3",
5
+ "version": "4.8.1",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -19,15 +19,15 @@
19
19
  "type-fest": "^2.12.2"
20
20
  },
21
21
  "dependencies": {
22
- "@graphcommerce/ecommerce-ui": "1.5.4",
23
- "@graphcommerce/framer-scroller": "2.1.41",
22
+ "@graphcommerce/ecommerce-ui": "1.5.6",
23
+ "@graphcommerce/framer-scroller": "2.1.43",
24
24
  "@graphcommerce/framer-next-pages": "3.3.2",
25
25
  "@graphcommerce/graphql": "3.5.0",
26
26
  "@graphcommerce/graphql-mesh": "4.2.0",
27
27
  "@graphcommerce/image": "3.1.10",
28
- "@graphcommerce/magento-cart": "4.9.0",
29
- "@graphcommerce/magento-store": "4.3.2",
30
- "@graphcommerce/next-ui": "4.28.1",
28
+ "@graphcommerce/magento-cart": "4.9.2",
29
+ "@graphcommerce/magento-store": "4.3.4",
30
+ "@graphcommerce/next-ui": "4.29.1",
31
31
  "schema-dts": "^1.1.0"
32
32
  },
33
33
  "peerDependencies": {