@graphcommerce/magento-product-configurable 9.0.0-canary.99 → 9.0.1-canary.0
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 +88 -1053
- package/ConfigurableCartItem/ConfigurableCartItem.tsx +7 -2
- package/ConfigurableCartItem/OptionsList.tsx +5 -4
- package/SwatchList.tsx +3 -3
- package/Swatches/ColorSwatchData.tsx +7 -6
- package/Swatches/ImageSwatchData.tsx +8 -6
- package/Swatches/TextSwatchData.tsx +6 -5
- package/Swatches/types.ts +4 -4
- package/components/ConfigurableCartItemOptions/ConfigurableCartItemOptions.tsx +4 -3
- package/components/ConfigurableOptionValue/ConfigurableOptionValue.tsx +2 -2
- package/components/ConfigurableOptionValueColor/ConfigurableOptionValueColor.tsx +2 -2
- package/components/ConfigurableOptionValueImage/ConfigurableOptionValueImage.tsx +2 -2
- package/components/ConfigurableOptionValueText/ConfigurableOptionValueText.tsx +2 -2
- package/components/ConfigurableProductOptions/ConfigurableProductOption.tsx +16 -13
- package/components/ConfigurableProductOptions/ConfigurableProductOptions.tsx +11 -5
- package/components/ProductListItemConfigurable/ProductListItemConfigurable.tsx +3 -6
- package/hooks/useConfigurableOptionsSelection.ts +2 -1
- package/index.ts +0 -2
- package/package.json +19 -19
- package/plugins/ConfigurableProductPage/ConfigurableProductPageDescription.tsx +2 -2
- package/plugins/ConfigurableProductPage/ConfigurableProductPageGallery.tsx +1 -0
- package/plugins/ConfigurableProductPage/ConfigurableProductPageMeta.tsx +2 -5
- package/plugins/ConfigurableProductPage/ConfigurableProductPagePrice.tsx +1 -1
- package/test/addConfigurableProductToCart.ts +2 -1
- package/utils/defaultConfigurableOptionsSelection.ts +3 -3
- package/ConfigurableContext/ConfigurableContext.tsx +0 -165
- package/ConfigurableContext/cheapestVariant.ts +0 -14
- package/ConfigurableOptions/ConfigurableOptions.tsx +0 -143
- package/ConfigurableProductAddToCart/ConfigurableProductAddToCart.tsx +0 -185
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { CartItemProps } from '@graphcommerce/magento-cart-items'
|
|
2
|
+
import { CartItem } from '@graphcommerce/magento-cart-items'
|
|
3
|
+
import type { ConfigurableCartItemFragment } from './ConfigurableCartItem.gql'
|
|
3
4
|
import { OptionsList } from './OptionsList'
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @deprecated
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
5
10
|
export function ConfigurableCartItem(props: ConfigurableCartItemFragment & CartItemProps) {
|
|
6
11
|
const { configurable_options, configured_variant, product } = props
|
|
7
12
|
return (
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { extendableComponent } from '@graphcommerce/next-ui'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
3
|
+
import { Box } from '@mui/material'
|
|
4
|
+
import type { ConfigurableCartItemFragment } from './ConfigurableCartItem.gql'
|
|
4
5
|
|
|
5
|
-
type CartItemOptionsListProps = Partial<ConfigurableCartItemFragment> & {
|
|
6
|
+
export type CartItemOptionsListProps = Partial<ConfigurableCartItemFragment> & {
|
|
6
7
|
sx?: SxProps<Theme>
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
const name = 'ColorSwatchData'
|
|
10
|
+
const name = 'ColorSwatchData'
|
|
10
11
|
const parts = ['root', 'option'] as const
|
|
11
12
|
const { classes } = extendableComponent(name, parts)
|
|
12
13
|
|
package/SwatchList.tsx
CHANGED
|
@@ -4,10 +4,10 @@ import React from 'react'
|
|
|
4
4
|
import { ColorSwatchData } from './Swatches/ColorSwatchData'
|
|
5
5
|
import { ImageSwatchData } from './Swatches/ImageSwatchData'
|
|
6
6
|
import { TextSwatchData } from './Swatches/TextSwatchData'
|
|
7
|
-
import { SwatchSize, SwatchTypeRenderer } from './Swatches/types'
|
|
8
|
-
import { ProductListItemConfigurableFragment } from './components/ProductListItemConfigurable/ProductListItemConfigurable.gql'
|
|
7
|
+
import type { SwatchSize, SwatchTypeRenderer } from './Swatches/types'
|
|
8
|
+
import type { ProductListItemConfigurableFragment } from './components/ProductListItemConfigurable/ProductListItemConfigurable.gql'
|
|
9
9
|
|
|
10
|
-
type SwatchListProps = {
|
|
10
|
+
export type SwatchListProps = {
|
|
11
11
|
attributes?: string[]
|
|
12
12
|
configurable_options?: Maybe<ProductListItemConfigurableFragment['configurable_options']>
|
|
13
13
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { extendableComponent, responsiveVal } from '@graphcommerce/next-ui'
|
|
2
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
3
|
+
import { Box } from '@mui/material'
|
|
4
|
+
import type { ColorSwatchDataFragment } from './ColorSwatchData.gql'
|
|
5
|
+
import type { SwatchDataProps } from './types'
|
|
5
6
|
|
|
6
|
-
type ColorSwatchDataProps = ColorSwatchDataFragment &
|
|
7
|
+
export type ColorSwatchDataProps = ColorSwatchDataFragment &
|
|
7
8
|
SwatchDataProps & {
|
|
8
9
|
sx?: SxProps<Theme>
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
type OwnerState = Pick<SwatchDataProps, 'size'>
|
|
12
|
-
const name = 'ColorSwatchData'
|
|
13
|
+
const name = 'ColorSwatchData'
|
|
13
14
|
const parts = ['root', 'color', 'label'] as const
|
|
14
15
|
const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
|
|
15
16
|
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Image } from '@graphcommerce/image'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { extendableComponent, responsiveVal } from '@graphcommerce/next-ui'
|
|
3
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
4
|
+
import { Box } from '@mui/material'
|
|
5
|
+
import type { ImageSwatchDataFragment } from './ImageSwatchData.gql'
|
|
6
|
+
import type { SwatchDataProps } from './types'
|
|
6
7
|
|
|
7
|
-
type ImageSwatchDataProps = ImageSwatchDataFragment &
|
|
8
|
+
export type ImageSwatchDataProps = ImageSwatchDataFragment &
|
|
9
|
+
SwatchDataProps & { sx?: SxProps<Theme> }
|
|
8
10
|
|
|
9
11
|
type OwnerState = Pick<SwatchDataProps, 'size'>
|
|
10
|
-
const name = 'ColorSwatchData'
|
|
12
|
+
const name = 'ColorSwatchData'
|
|
11
13
|
const parts = ['root', 'image', 'label'] as const
|
|
12
14
|
const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
|
|
13
15
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Money } from '@graphcommerce/magento-store'
|
|
2
2
|
import { extendableComponent } from '@graphcommerce/next-ui'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
4
|
+
import { Box } from '@mui/material'
|
|
5
|
+
import type { TextSwatchDataFragment } from './TextSwatchData.gql'
|
|
6
|
+
import type { SwatchDataProps } from './types'
|
|
6
7
|
|
|
7
|
-
type TextSwatchDataProps = TextSwatchDataFragment & SwatchDataProps & { sx?: SxProps<Theme> }
|
|
8
|
+
export type TextSwatchDataProps = TextSwatchDataFragment & SwatchDataProps & { sx?: SxProps<Theme> }
|
|
8
9
|
|
|
9
10
|
type OwnerState = Pick<SwatchDataProps, 'size'>
|
|
10
|
-
const name = 'TextSwatchData'
|
|
11
|
+
const name = 'TextSwatchData'
|
|
11
12
|
const parts = ['root', 'value', 'price', 'label', 'storeLabel', 'content'] as const
|
|
12
13
|
const { withState } = extendableComponent<OwnerState, typeof name, typeof parts>(name, parts)
|
|
13
14
|
|
package/Swatches/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { MoneyProps } from '@graphcommerce/magento-store'
|
|
2
|
-
import { TypeRenderer } from '@graphcommerce/next-ui'
|
|
3
|
-
import { ProductListItemConfigurableFragment } from '../components/ProductListItemConfigurable/ProductListItemConfigurable.gql'
|
|
4
|
-
import { SwatchDataFragment } from './SwatchData.gql'
|
|
1
|
+
import type { MoneyProps } from '@graphcommerce/magento-store'
|
|
2
|
+
import type { TypeRenderer } from '@graphcommerce/next-ui'
|
|
3
|
+
import type { ProductListItemConfigurableFragment } from '../components/ProductListItemConfigurable/ProductListItemConfigurable.gql'
|
|
4
|
+
import type { SwatchDataFragment } from './SwatchData.gql'
|
|
5
5
|
|
|
6
6
|
type ConfigurableOption = NonNullable<
|
|
7
7
|
NonNullable<ProductListItemConfigurableFragment['configurable_options']>[0]
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { CartItemFragment
|
|
1
|
+
import type { CartItemFragment } from '@graphcommerce/magento-cart-items'
|
|
2
|
+
import { SelectedCustomizableOptions } from '@graphcommerce/magento-cart-items'
|
|
2
3
|
import { Box } from '@mui/material'
|
|
3
|
-
import { ConfigurableCartItemFragment } from '../../ConfigurableCartItem/ConfigurableCartItem.gql'
|
|
4
|
+
import type { ConfigurableCartItemFragment } from '../../ConfigurableCartItem/ConfigurableCartItem.gql'
|
|
4
5
|
|
|
5
|
-
type ConfigurableActionCartItemProps = ConfigurableCartItemFragment & CartItemFragment
|
|
6
|
+
export type ConfigurableActionCartItemProps = ConfigurableCartItemFragment & CartItemFragment
|
|
6
7
|
|
|
7
8
|
export function ConfigurableCartItemOptions(props: ConfigurableActionCartItemProps) {
|
|
8
9
|
const { configurable_options } = props
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
1
|
+
import type { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { RenderType } from '@graphcommerce/next-ui'
|
|
3
3
|
import { ConfigurableOptionValueColor } from '../ConfigurableOptionValueColor'
|
|
4
4
|
import { ConfigurableOptionValueImage } from '../ConfigurableOptionValueImage/ConfigurableOptionValueImage'
|
|
5
5
|
import { ConfigurableOptionValueText } from '../ConfigurableOptionValueText/ConfigurableOptionValueText'
|
|
6
|
-
import { ConfigurableOptionValueFragment } from './ConfigurableOptionValue.gql'
|
|
6
|
+
import type { ConfigurableOptionValueFragment } from './ConfigurableOptionValue.gql'
|
|
7
7
|
|
|
8
8
|
export type ConfigurabeOptionValueProps = ActionCardItemRenderProps<ConfigurableOptionValueFragment>
|
|
9
9
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
1
|
+
import type { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { ActionCard } from '@graphcommerce/next-ui'
|
|
3
3
|
import { Box } from '@mui/material'
|
|
4
4
|
import { swatchSizes } from '../ConfigurableOptionValueImage'
|
|
5
|
-
import { ConfigurableOptionValueColorFragment } from './ConfigurableOptionValueColor.gql'
|
|
5
|
+
import type { ConfigurableOptionValueColorFragment } from './ConfigurableOptionValueColor.gql'
|
|
6
6
|
|
|
7
7
|
export type ConfigurableOptionValueColorProps =
|
|
8
8
|
ActionCardItemRenderProps<ConfigurableOptionValueColorFragment>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
1
|
+
import type { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { Image } from '@graphcommerce/image'
|
|
3
3
|
import { ActionCard, responsiveVal } from '@graphcommerce/next-ui'
|
|
4
4
|
import { Trans } from '@lingui/react'
|
|
5
5
|
import { Button } from '@mui/material'
|
|
6
|
-
import { ConfigurableOptionValueImageFragment } from './ConfigurableOptionValueImage.gql'
|
|
6
|
+
import type { ConfigurableOptionValueImageFragment } from './ConfigurableOptionValueImage.gql'
|
|
7
7
|
|
|
8
8
|
export type ConfigurableOptionValueImageProps =
|
|
9
9
|
ActionCardItemRenderProps<ConfigurableOptionValueImageFragment>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
1
|
+
import type { ActionCardItemRenderProps } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { ActionCard } from '@graphcommerce/next-ui'
|
|
3
|
-
import { ConfigurableOptionValueTextFragment } from './ConfigurableOptionValueText.gql'
|
|
3
|
+
import type { ConfigurableOptionValueTextFragment } from './ConfigurableOptionValueText.gql'
|
|
4
4
|
|
|
5
5
|
export type ConfigurableOptionValueTextProps =
|
|
6
6
|
ActionCardItemRenderProps<ConfigurableOptionValueTextFragment>
|
|
@@ -1,36 +1,39 @@
|
|
|
1
|
-
import { ActionCardItemBase
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from '@graphcommerce/
|
|
6
|
-
import { filterNonNullableKeys, nonNullable, SectionHeader } from '@graphcommerce/next-ui'
|
|
1
|
+
import type { ActionCardItemBase } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { ActionCardListForm } from '@graphcommerce/ecommerce-ui'
|
|
3
|
+
import type { AddProductsToCartFields } from '@graphcommerce/magento-product/components'
|
|
4
|
+
import { useFormAddProductsToCart } from '@graphcommerce/magento-product/components'
|
|
5
|
+
import { SectionHeader, filterNonNullableKeys, nonNullable } from '@graphcommerce/next-ui'
|
|
7
6
|
import { useWatch } from '@graphcommerce/react-hook-form'
|
|
8
7
|
import { i18n } from '@lingui/core'
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
9
|
+
import { Box } from '@mui/material'
|
|
10
|
+
import type { ConfigurableOptionsFragment } from '../../graphql/ConfigurableOptions.gql'
|
|
11
|
+
import type { UseConfigurableOptionsSelection } from '../../hooks'
|
|
12
|
+
import { useConfigurableOptionsForSelection } from '../../hooks'
|
|
13
|
+
import type {
|
|
13
14
|
ConfigurableOptionValue,
|
|
14
15
|
ConfigurableOptionValueFragment,
|
|
15
16
|
} from '../ConfigurableOptionValue'
|
|
16
17
|
|
|
17
|
-
type
|
|
18
|
+
export type ConfigurableProductOptionProps = NonNullable<
|
|
18
19
|
NonNullable<ConfigurableOptionsFragment['configurable_options']>[number]
|
|
19
20
|
> & {
|
|
20
21
|
index: number
|
|
21
22
|
optionIndex: number
|
|
23
|
+
optionStartLabels?: Record<string, React.ReactNode>
|
|
22
24
|
optionEndLabels?: Record<string, React.ReactNode>
|
|
23
25
|
sx?: SxProps<Theme>
|
|
24
26
|
attribute_code: string
|
|
25
27
|
render: typeof ConfigurableOptionValue
|
|
26
28
|
} & UseConfigurableOptionsSelection
|
|
27
29
|
|
|
28
|
-
export function ConfigurableProductOption(props:
|
|
30
|
+
export function ConfigurableProductOption(props: ConfigurableProductOptionProps) {
|
|
29
31
|
const {
|
|
30
32
|
values,
|
|
31
33
|
label,
|
|
32
34
|
index,
|
|
33
35
|
optionIndex,
|
|
36
|
+
optionStartLabels,
|
|
34
37
|
optionEndLabels,
|
|
35
38
|
sx,
|
|
36
39
|
attribute_code,
|
|
@@ -70,7 +73,7 @@ export function ConfigurableProductOption(props: Props) {
|
|
|
70
73
|
return (
|
|
71
74
|
<Box key={fieldName} sx={[...(Array.isArray(sx) ? sx : [sx])]}>
|
|
72
75
|
<SectionHeader
|
|
73
|
-
labelLeft={label}
|
|
76
|
+
labelLeft={optionStartLabels?.[attribute_code ?? ''] ?? label}
|
|
74
77
|
labelRight={optionEndLabels?.[attribute_code ?? '']}
|
|
75
78
|
sx={{ mt: 0 }}
|
|
76
79
|
/>
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { ActionCardRequireOptionSelection } from '@graphcommerce/ecommerce-ui'
|
|
2
|
-
import { AddToCartItemSelector
|
|
3
|
-
import {
|
|
1
|
+
import type { ActionCardRequireOptionSelection } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import type { AddToCartItemSelector } from '@graphcommerce/magento-product'
|
|
3
|
+
import { useFormAddProductsToCart } from '@graphcommerce/magento-product'
|
|
4
|
+
import type { ActionCardListProps } from '@graphcommerce/next-ui'
|
|
5
|
+
import { filterNonNullableKeys, useLocale } from '@graphcommerce/next-ui'
|
|
4
6
|
import { i18n } from '@lingui/core'
|
|
5
|
-
import {
|
|
7
|
+
import type { SxProps, Theme } from '@mui/material'
|
|
8
|
+
import { Box } from '@mui/material'
|
|
6
9
|
import React, { useEffect, useMemo } from 'react'
|
|
7
|
-
import { ConfigurableOptionsFragment } from '../../graphql/ConfigurableOptions.gql'
|
|
10
|
+
import type { ConfigurableOptionsFragment } from '../../graphql/ConfigurableOptions.gql'
|
|
8
11
|
import { useConfigurableOptionsSelection } from '../../hooks'
|
|
9
12
|
import { ConfigurableOptionValue } from '../ConfigurableOptionValue/ConfigurableOptionValue'
|
|
10
13
|
import { ConfigurableProductOption } from './ConfigurableProductOption'
|
|
11
14
|
|
|
12
15
|
export type ConfigurableProductOptionsProps = AddToCartItemSelector & {
|
|
16
|
+
optionStartLabels?: Record<string, React.ReactNode>
|
|
13
17
|
optionEndLabels?: Record<string, React.ReactNode>
|
|
14
18
|
sx?: SxProps<Theme>
|
|
15
19
|
render?: typeof ConfigurableOptionValue
|
|
@@ -19,6 +23,7 @@ export type ConfigurableProductOptionsProps = AddToCartItemSelector & {
|
|
|
19
23
|
|
|
20
24
|
export function ConfigurableProductOptions(props: ConfigurableProductOptionsProps) {
|
|
21
25
|
const {
|
|
26
|
+
optionStartLabels,
|
|
22
27
|
optionEndLabels,
|
|
23
28
|
sx,
|
|
24
29
|
render = ConfigurableOptionValue,
|
|
@@ -65,6 +70,7 @@ export function ConfigurableProductOptions(props: ConfigurableProductOptionsProp
|
|
|
65
70
|
{...option}
|
|
66
71
|
key={option.uid}
|
|
67
72
|
render={render}
|
|
73
|
+
optionStartLabels={optionStartLabels}
|
|
68
74
|
optionEndLabels={optionEndLabels}
|
|
69
75
|
index={index}
|
|
70
76
|
optionIndex={optionIndex}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
OverlayAreaKeys,
|
|
4
|
-
ProductListItemProps,
|
|
5
|
-
} from '@graphcommerce/magento-product'
|
|
1
|
+
import type { OverlayAreaKeys, ProductListItemProps } from '@graphcommerce/magento-product'
|
|
2
|
+
import { ProductListItem } from '@graphcommerce/magento-product'
|
|
6
3
|
import { SwatchList } from '../../SwatchList'
|
|
7
|
-
import { ProductListItemConfigurableFragment } from './ProductListItemConfigurable.gql'
|
|
4
|
+
import type { ProductListItemConfigurableFragment } from './ProductListItemConfigurable.gql'
|
|
8
5
|
|
|
9
6
|
export type ProdustListItemConfigurableProps = ProductListItemConfigurableFragment &
|
|
10
7
|
ProductListItemProps & {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useQuery } from '@graphcommerce/graphql'
|
|
2
|
-
import { AddToCartItemSelector
|
|
2
|
+
import type { AddToCartItemSelector } from '@graphcommerce/magento-product'
|
|
3
|
+
import { useFormAddProductsToCart } from '@graphcommerce/magento-product'
|
|
3
4
|
import { findByTypename, nonNullable } from '@graphcommerce/next-ui'
|
|
4
5
|
import { useWatch } from '@graphcommerce/react-hook-form'
|
|
5
6
|
import { GetConfigurableOptionsSelectionDocument } from '../graphql/GetConfigurableOptionsSelection.gql'
|
package/index.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export * from './components'
|
|
2
2
|
export * from './ConfigurableCartItem/ConfigurableCartItem'
|
|
3
|
-
export * from './ConfigurableContext/ConfigurableContext'
|
|
4
|
-
export * from './ConfigurableProductAddToCart/ConfigurableProductAddToCart'
|
|
5
3
|
export * from './ConfigurableProductPage.gql'
|
|
6
4
|
export * from './graphql'
|
|
7
5
|
export * from './hooks'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/magento-product-configurable",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "9.0.
|
|
5
|
+
"version": "9.0.1-canary.0",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -12,28 +12,28 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"@graphcommerce/ecommerce-ui": "^9.0.
|
|
16
|
-
"@graphcommerce/eslint-config-pwa": "^9.0.
|
|
17
|
-
"@graphcommerce/graphql": "^9.0.
|
|
18
|
-
"@graphcommerce/graphql-mesh": "^9.0.
|
|
19
|
-
"@graphcommerce/image": "^9.0.
|
|
20
|
-
"@graphcommerce/lingui-next": "9.0.
|
|
21
|
-
"@graphcommerce/magento-cart": "^9.0.
|
|
22
|
-
"@graphcommerce/magento-cart-items": "^9.0.
|
|
23
|
-
"@graphcommerce/magento-category": "^9.0.
|
|
24
|
-
"@graphcommerce/magento-customer": "^9.0.
|
|
25
|
-
"@graphcommerce/magento-product": "^9.0.
|
|
26
|
-
"@graphcommerce/magento-product-simple": "^9.0.
|
|
27
|
-
"@graphcommerce/magento-store": "^9.0.
|
|
28
|
-
"@graphcommerce/next-ui": "^9.0.
|
|
29
|
-
"@graphcommerce/prettier-config-pwa": "^9.0.
|
|
30
|
-
"@graphcommerce/react-hook-form": "^9.0.
|
|
31
|
-
"@graphcommerce/typescript-config-pwa": "^9.0.
|
|
15
|
+
"@graphcommerce/ecommerce-ui": "^9.0.1-canary.0",
|
|
16
|
+
"@graphcommerce/eslint-config-pwa": "^9.0.1-canary.0",
|
|
17
|
+
"@graphcommerce/graphql": "^9.0.1-canary.0",
|
|
18
|
+
"@graphcommerce/graphql-mesh": "^9.0.1-canary.0",
|
|
19
|
+
"@graphcommerce/image": "^9.0.1-canary.0",
|
|
20
|
+
"@graphcommerce/lingui-next": "9.0.1-canary.0",
|
|
21
|
+
"@graphcommerce/magento-cart": "^9.0.1-canary.0",
|
|
22
|
+
"@graphcommerce/magento-cart-items": "^9.0.1-canary.0",
|
|
23
|
+
"@graphcommerce/magento-category": "^9.0.1-canary.0",
|
|
24
|
+
"@graphcommerce/magento-customer": "^9.0.1-canary.0",
|
|
25
|
+
"@graphcommerce/magento-product": "^9.0.1-canary.0",
|
|
26
|
+
"@graphcommerce/magento-product-simple": "^9.0.1-canary.0",
|
|
27
|
+
"@graphcommerce/magento-store": "^9.0.1-canary.0",
|
|
28
|
+
"@graphcommerce/next-ui": "^9.0.1-canary.0",
|
|
29
|
+
"@graphcommerce/prettier-config-pwa": "^9.0.1-canary.0",
|
|
30
|
+
"@graphcommerce/react-hook-form": "^9.0.1-canary.0",
|
|
31
|
+
"@graphcommerce/typescript-config-pwa": "^9.0.1-canary.0",
|
|
32
32
|
"@lingui/core": "^4.2.1",
|
|
33
33
|
"@lingui/macro": "^4.2.1",
|
|
34
34
|
"@lingui/react": "^4.2.1",
|
|
35
35
|
"@mui/material": "^5.10.16",
|
|
36
|
-
"framer-motion": "^
|
|
36
|
+
"framer-motion": "^11.0.0",
|
|
37
37
|
"next": "*",
|
|
38
38
|
"react": "^18.2.0",
|
|
39
39
|
"react-dom": "^18.2.0"
|
|
@@ -11,9 +11,9 @@ export const config: PluginConfig = {
|
|
|
11
11
|
ifConfig: 'configurableVariantValues.content',
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export
|
|
14
|
+
export function ProductPageDescription(
|
|
15
15
|
props: PluginProps<ProductPageDescriptionProps & AddToCartItemSelector>,
|
|
16
|
-
)
|
|
16
|
+
) {
|
|
17
17
|
const { Prev, product, index, ...rest } = props
|
|
18
18
|
const variant = useConfigurableSelectedVariant({ url_key: product.url_key, index })
|
|
19
19
|
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { mergeDeep } from '@graphcommerce/graphql'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
type AddToCartItemSelector,
|
|
5
|
-
ProductPageMetaProps,
|
|
6
|
-
} from '@graphcommerce/magento-product'
|
|
2
|
+
import type { ProductPageMetaProps } from '@graphcommerce/magento-product'
|
|
3
|
+
import { type AddToCartItemSelector, productLink } from '@graphcommerce/magento-product'
|
|
7
4
|
import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
|
|
8
5
|
import { useRouter } from 'next/router'
|
|
9
6
|
import { useEffect } from 'react'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddToCartItemSelector, ProductPagePriceProps } from '@graphcommerce/magento-product'
|
|
1
|
+
import type { AddToCartItemSelector, ProductPagePriceProps } from '@graphcommerce/magento-product'
|
|
2
2
|
import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
|
|
3
3
|
import { useConfigurableSelectedVariant } from '../../hooks'
|
|
4
4
|
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import { waitForGraphQlResponse } from '@graphcommerce/graphql/test/apolloClient.fixture'
|
|
3
3
|
import { CreateEmptyCartDocument } from '@graphcommerce/magento-cart/hooks/CreateEmptyCart.gql'
|
|
4
4
|
import { ProductAddToCartDocument } from '@graphcommerce/magento-product'
|
|
5
|
-
import { Page
|
|
5
|
+
import type { Page } from '@playwright/test'
|
|
6
|
+
import { expect } from '@playwright/test'
|
|
6
7
|
|
|
7
8
|
export async function addConfigurableProductToCart(page: Page, productUrl: string) {
|
|
8
9
|
await page.goto(productUrl)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ApolloClient } from '@graphcommerce/graphql'
|
|
2
|
-
import { AddProductsToCartFormProps } from '@graphcommerce/magento-product'
|
|
1
|
+
import type { ApolloClient } from '@graphcommerce/graphql'
|
|
2
|
+
import type { AddProductsToCartFormProps } from '@graphcommerce/magento-product'
|
|
3
3
|
import { filterNonNullableKeys, findByTypename, nonNullable } from '@graphcommerce/next-ui'
|
|
4
4
|
import { GetConfigurableOptionsSelectionDocument } from '../graphql'
|
|
5
|
-
import { DefaultConfigurableOptionsSelectionFragment } from './DefaultConfigurableOptionsSelection.gql'
|
|
5
|
+
import type { DefaultConfigurableOptionsSelectionFragment } from './DefaultConfigurableOptionsSelection.gql'
|
|
6
6
|
|
|
7
7
|
type BaseQuery =
|
|
8
8
|
| { products?: DefaultConfigurableOptionsSelectionFragment | null | undefined }
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useContext,
|
|
3
|
-
createContext,
|
|
4
|
-
Context,
|
|
5
|
-
useState,
|
|
6
|
-
Dispatch,
|
|
7
|
-
SetStateAction,
|
|
8
|
-
useMemo,
|
|
9
|
-
useCallback,
|
|
10
|
-
} from 'react'
|
|
11
|
-
import { ConfigurableProductFormFragment } from './ConfigurableProductForm.gql'
|
|
12
|
-
import cheapestVariant from './cheapestVariant'
|
|
13
|
-
|
|
14
|
-
type ConfigurableProductFormProps = ConfigurableProductFormFragment & {
|
|
15
|
-
sku: string
|
|
16
|
-
children?: React.ReactNode
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type Selected = { [attrCode: string]: number }
|
|
20
|
-
export type Variants = NonNullable<ConfigurableProductFormProps['variants']>
|
|
21
|
-
type GetVariants = (values?: Selected) => Variants
|
|
22
|
-
type GetUids = (values?: Selected) => string[]
|
|
23
|
-
|
|
24
|
-
type ConfigurableContext = {
|
|
25
|
-
selection: Selected
|
|
26
|
-
variants: Variants
|
|
27
|
-
cheapest: Variants[0]
|
|
28
|
-
select: Dispatch<SetStateAction<Selected>>
|
|
29
|
-
options: ConfigurableProductFormFragment['configurable_options']
|
|
30
|
-
getVariants: GetVariants
|
|
31
|
-
getUids: GetUids
|
|
32
|
-
}
|
|
33
|
-
const contexts: { [sku: string]: Context<ConfigurableContext> } = {}
|
|
34
|
-
|
|
35
|
-
function configurableContext(sku: string): Context<ConfigurableContext> {
|
|
36
|
-
if (contexts?.[sku]) return contexts[sku]
|
|
37
|
-
contexts[sku] = createContext<ConfigurableContext>({
|
|
38
|
-
selection: {},
|
|
39
|
-
variants: [],
|
|
40
|
-
cheapest: {},
|
|
41
|
-
select: () => {},
|
|
42
|
-
options: undefined,
|
|
43
|
-
getVariants: () => [],
|
|
44
|
-
getUids: () => [],
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
return contexts[sku]
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
type AttributeTree = {
|
|
51
|
-
code: string
|
|
52
|
-
values: AttributeValues
|
|
53
|
-
}
|
|
54
|
-
type AttributeValues = {
|
|
55
|
-
[index: string]: {
|
|
56
|
-
variants: NonNullable<ConfigurableProductFormProps['variants']>
|
|
57
|
-
attribute?: AttributeTree
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function generateAttrTree(
|
|
62
|
-
idx: number,
|
|
63
|
-
options: ConfigurableProductFormProps['configurable_options'],
|
|
64
|
-
variants: ConfigurableProductFormProps['variants'],
|
|
65
|
-
selected: Selected,
|
|
66
|
-
tree?: AttributeTree,
|
|
67
|
-
) {
|
|
68
|
-
const attribute = options?.[idx]
|
|
69
|
-
if (!attribute || !attribute.attribute_code) return tree
|
|
70
|
-
|
|
71
|
-
const attributeTree: AttributeTree = { code: attribute.attribute_code, values: {} }
|
|
72
|
-
|
|
73
|
-
attribute.values?.forEach((val) => {
|
|
74
|
-
if (!val?.uid) return
|
|
75
|
-
const newSelected = { ...selected, [attributeTree.code]: [val.uid] } as Selected
|
|
76
|
-
|
|
77
|
-
const filteredVariants = variants?.filter(
|
|
78
|
-
(variant) =>
|
|
79
|
-
!!variant?.attributes?.find(
|
|
80
|
-
(attr) => attr?.code === attribute.attribute_code && val.uid === attr?.uid,
|
|
81
|
-
),
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
attributeTree.values[val.uid] = {
|
|
85
|
-
variants: filteredVariants ?? [],
|
|
86
|
-
attribute: generateAttrTree(idx + 1, options, filteredVariants, newSelected),
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
return attributeTree
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function traverseAttrTree(selection: Selected, attrTree: AttributeTree | undefined): Variants {
|
|
94
|
-
if (!attrTree) return []
|
|
95
|
-
|
|
96
|
-
const id = selection?.[attrTree.code]
|
|
97
|
-
const attrVal = id ? attrTree.values[id] : undefined
|
|
98
|
-
|
|
99
|
-
// We have a request, but isn't found in the current tree node
|
|
100
|
-
if (id && !attrVal) return []
|
|
101
|
-
|
|
102
|
-
if (attrVal?.attribute) return traverseAttrTree(selection, attrVal.attribute)
|
|
103
|
-
if (attrVal?.variants) return attrVal.variants
|
|
104
|
-
|
|
105
|
-
const attrValues = Object.entries(attrTree.values)
|
|
106
|
-
const variantList: NonNullable<ConfigurableProductFormProps['variants']> = []
|
|
107
|
-
|
|
108
|
-
attrValues.forEach(([optionId, attrVal2]) => {
|
|
109
|
-
variantList.push(
|
|
110
|
-
...(attrVal2.attribute
|
|
111
|
-
? traverseAttrTree({ ...selection, [attrTree.code]: Number(optionId) }, attrVal2.attribute)
|
|
112
|
-
: attrVal2.variants),
|
|
113
|
-
)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
return variantList
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function ConfigurableContextProvider(props: ConfigurableProductFormProps) {
|
|
120
|
-
const { children, sku, configurable_options, variants: providedVariants } = props
|
|
121
|
-
const [selection, select] = useState<Selected>({})
|
|
122
|
-
|
|
123
|
-
if (!configurable_options || !providedVariants)
|
|
124
|
-
throw Error('please provide configurabl_options and variants')
|
|
125
|
-
|
|
126
|
-
const lookupTree = useMemo(
|
|
127
|
-
() => generateAttrTree(0, configurable_options, providedVariants, {}),
|
|
128
|
-
[configurable_options, providedVariants],
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
const getVariants: GetVariants = useCallback(
|
|
132
|
-
(options: Selected = {}) => traverseAttrTree(options, lookupTree),
|
|
133
|
-
[lookupTree],
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
const getUids: GetUids = useCallback(
|
|
137
|
-
(options: Selected = {}) =>
|
|
138
|
-
(getVariants(options as unknown as Selected) ?? [])
|
|
139
|
-
.map((variant) => (variant?.attributes?.map((attr) => attr?.uid) ?? []) as string[])
|
|
140
|
-
.flat(),
|
|
141
|
-
[getVariants],
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
const context = configurableContext(sku)
|
|
145
|
-
const variants = getVariants(selection)
|
|
146
|
-
|
|
147
|
-
const value = useMemo(
|
|
148
|
-
() => ({
|
|
149
|
-
selection,
|
|
150
|
-
variants,
|
|
151
|
-
cheapest: cheapestVariant(variants),
|
|
152
|
-
select,
|
|
153
|
-
getVariants,
|
|
154
|
-
getUids,
|
|
155
|
-
options: configurable_options,
|
|
156
|
-
}),
|
|
157
|
-
[configurable_options, getUids, getVariants, selection, variants],
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
return <context.Provider value={value}>{children}</context.Provider>
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
export function useConfigurableContext(sku: string): ConfigurableContext {
|
|
164
|
-
return useContext(configurableContext(sku))
|
|
165
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ConfigurableProductFormFragment } from './ConfigurableProductForm.gql'
|
|
2
|
-
|
|
3
|
-
type Variants = NonNullable<ConfigurableProductFormFragment['variants']>
|
|
4
|
-
|
|
5
|
-
export default function cheapestVariant(variants: Variants): Variants[0] {
|
|
6
|
-
if (!variants.length) return null
|
|
7
|
-
const cheapest = variants?.reduce((prev, curr) =>
|
|
8
|
-
(curr?.product?.price_range.minimum_price.final_price.value ?? 0) <
|
|
9
|
-
(prev?.product?.price_range.minimum_price.final_price.value ?? 0)
|
|
10
|
-
? curr
|
|
11
|
-
: prev,
|
|
12
|
-
)
|
|
13
|
-
return cheapest
|
|
14
|
-
}
|