@graphcommerce/magento-cart-items 8.1.0-canary.9 → 9.0.0-canary.101

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.
@@ -1,4 +1,4 @@
1
- fragment CartItem on CartItemInterface @injectable {
1
+ fragment CartItem on CartItemInterface {
2
2
  uid
3
3
  quantity
4
4
  __typename
@@ -1,4 +1,4 @@
1
- fragment CartItems on Cart @injectable {
1
+ fragment CartItems on Cart {
2
2
  id
3
3
  items {
4
4
  uid
package/CHANGELOG.md CHANGED
@@ -1,5 +1,217 @@
1
1
  # Change Log
2
2
 
3
+ ## 9.0.0-canary.101
4
+
5
+ ## 9.0.0-canary.100
6
+
7
+ ## 9.0.0-canary.99
8
+
9
+ ## 9.0.0-canary.98
10
+
11
+ ## 9.0.0-canary.97
12
+
13
+ ## 9.0.0-canary.96
14
+
15
+ ## 9.0.0-canary.95
16
+
17
+ ## 9.0.0-canary.94
18
+
19
+ ## 9.0.0-canary.93
20
+
21
+ ## 9.0.0-canary.92
22
+
23
+ ## 9.0.0-canary.91
24
+
25
+ ## 9.0.0-canary.90
26
+
27
+ ## 9.0.0-canary.89
28
+
29
+ ## 9.0.0-canary.88
30
+
31
+ ## 9.0.0-canary.87
32
+
33
+ ## 9.0.0-canary.86
34
+
35
+ ## 9.0.0-canary.85
36
+
37
+ ## 9.0.0-canary.84
38
+
39
+ ## 9.0.0-canary.83
40
+
41
+ ## 9.0.0-canary.82
42
+
43
+ ## 9.0.0-canary.81
44
+
45
+ ## 9.0.0-canary.80
46
+
47
+ ### Minor Changes
48
+
49
+ - [#2341](https://github.com/graphcommerce-org/graphcommerce/pull/2341) [`1d6512d`](https://github.com/graphcommerce-org/graphcommerce/commit/1d6512d4118cfb46602aa1f2432c3566fdb3261d) - Rename experimental_useV2 prop to deprecated_useV1 in useFromGql and enable it by default ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
50
+
51
+ ### Patch Changes
52
+
53
+ - [#2341](https://github.com/graphcommerce-org/graphcommerce/pull/2341) [`97522bd`](https://github.com/graphcommerce-org/graphcommerce/commit/97522bdb2505e6b57de98ea02ca252341ac69443) - Solve issue where the CartEditForm would temporarily show an empty cart after saving. ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
54
+
55
+ ## 9.0.0-canary.79
56
+
57
+ ## 9.0.0-canary.78
58
+
59
+ ## 9.0.0-canary.77
60
+
61
+ ## 9.0.0-canary.76
62
+
63
+ ## 9.0.0-canary.75
64
+
65
+ ## 9.0.0-canary.74
66
+
67
+ ## 9.0.0-canary.73
68
+
69
+ ## 9.0.0-canary.72
70
+
71
+ ## 9.0.0-canary.71
72
+
73
+ ## 9.0.0-canary.70
74
+
75
+ ## 9.0.0-canary.69
76
+
77
+ ## 9.0.0-canary.68
78
+
79
+ ## 9.0.0-canary.67
80
+
81
+ ## 9.0.0-canary.66
82
+
83
+ ## 9.0.0-canary.65
84
+
85
+ ## 9.0.0-canary.64
86
+
87
+ ## 9.0.0-canary.63
88
+
89
+ ## 9.0.0-canary.62
90
+
91
+ ## 9.0.0-canary.61
92
+
93
+ ## 9.0.0-canary.60
94
+
95
+ ## 9.0.0-canary.59
96
+
97
+ ## 9.0.0-canary.58
98
+
99
+ ## 9.0.0-canary.57
100
+
101
+ ## 9.0.0-canary.56
102
+
103
+ ## 9.0.0-canary.55
104
+
105
+ ## 9.0.0-canary.54
106
+
107
+ ## 8.1.0-canary.53
108
+
109
+ ## 8.1.0-canary.52
110
+
111
+ ## 8.1.0-canary.51
112
+
113
+ ### Minor Changes
114
+
115
+ - [#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 ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
116
+
117
+ ## 8.1.0-canary.50
118
+
119
+ ## 8.1.0-canary.49
120
+
121
+ ## 8.1.0-canary.48
122
+
123
+ ## 8.1.0-canary.47
124
+
125
+ ## 8.1.0-canary.46
126
+
127
+ ## 8.1.0-canary.45
128
+
129
+ ### Patch Changes
130
+
131
+ - [#2216](https://github.com/graphcommerce-org/graphcommerce/pull/2216) [`c30ac07`](https://github.com/graphcommerce-org/graphcommerce/commit/c30ac07d1e9aee5fb3df483404d8a8ca853c93ce) - Make sure the edit cart item isn't shown for an order ([@paales](https://github.com/paales))
132
+
133
+ ## 8.1.0-canary.44
134
+
135
+ ## 8.1.0-canary.43
136
+
137
+ ## 8.1.0-canary.42
138
+
139
+ ## 8.1.0-canary.41
140
+
141
+ ## 8.1.0-canary.40
142
+
143
+ ## 8.1.0-canary.39
144
+
145
+ ## 8.1.0-canary.38
146
+
147
+ ## 8.1.0-canary.37
148
+
149
+ ## 8.1.0-canary.36
150
+
151
+ ## 8.1.0-canary.35
152
+
153
+ ## 8.1.0-canary.34
154
+
155
+ ## 8.1.0-canary.33
156
+
157
+ ## 8.1.0-canary.32
158
+
159
+ ## 8.1.0-canary.31
160
+
161
+ ## 8.1.0-canary.30
162
+
163
+ ## 8.1.0-canary.29
164
+
165
+ ## 8.1.0-canary.28
166
+
167
+ ## 8.1.0-canary.27
168
+
169
+ ## 8.1.0-canary.26
170
+
171
+ ## 8.1.0-canary.25
172
+
173
+ ## 8.1.0-canary.24
174
+
175
+ ## 8.1.0-canary.23
176
+
177
+ ## 8.1.0-canary.22
178
+
179
+ ## 8.1.0-canary.21
180
+
181
+ ## 8.1.0-canary.20
182
+
183
+ ### Minor Changes
184
+
185
+ - [#2246](https://github.com/graphcommerce-org/graphcommerce/pull/2246) [`13524f9`](https://github.com/graphcommerce-org/graphcommerce/commit/13524f991a810c1679db49b3b8b4f04f90d0d6c1) - Added the ability to edit cart items with full support for all product types and custom options ([@Jessevdpoel](https://github.com/Jessevdpoel))
186
+
187
+ ### Patch Changes
188
+
189
+ - [#2246](https://github.com/graphcommerce-org/graphcommerce/pull/2246) [`fc5c04d`](https://github.com/graphcommerce-org/graphcommerce/commit/fc5c04d4a2c0301be7d3cc983d9b31f6fcaf6fe6) - Create useRemoveItemFromCart hook to allow for reuse while keeping compatibility with plugins. ([@Jessevdpoel](https://github.com/Jessevdpoel))
190
+
191
+ ## 8.1.0-canary.19
192
+
193
+ ## 8.1.0-canary.18
194
+
195
+ ## 8.1.0-canary.17
196
+
197
+ ### Minor Changes
198
+
199
+ - [#2209](https://github.com/graphcommerce-org/graphcommerce/pull/2209) [`2872cab`](https://github.com/graphcommerce-org/graphcommerce/commit/2872cabdca9ee4f0378fd411c6a633f71bb92f1f) - Removed useMediaQuery from the wishlist and cart ItemActionCard and replaced it with a new responsive size prop. ([@Jessevdpoel](https://github.com/Jessevdpoel))
200
+
201
+ ## 8.1.0-canary.16
202
+
203
+ ## 8.1.0-canary.15
204
+
205
+ ## 8.1.0-canary.14
206
+
207
+ ## 8.1.0-canary.13
208
+
209
+ ## 8.1.0-canary.12
210
+
211
+ ## 8.1.0-canary.11
212
+
213
+ ## 8.1.0-canary.10
214
+
3
215
  ## 8.1.0-canary.9
4
216
 
5
217
  ## 8.1.0-canary.8
@@ -80,8 +292,7 @@
80
292
 
81
293
  ### Patch Changes
82
294
 
83
- - [#2190](https://github.com/graphcommerce-org/graphcommerce/pull/2190) [`770a309`](https://github.com/graphcommerce-org/graphcommerce/commit/770a309cdf0586aaaed5defd345e451dee8d89c8) - Fixed a bug concerning customizable options. Customizable options of configurable products are shown again in the cart.
84
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
295
+ - [#2190](https://github.com/graphcommerce-org/graphcommerce/pull/2190) [`770a309`](https://github.com/graphcommerce-org/graphcommerce/commit/770a309cdf0586aaaed5defd345e451dee8d89c8) - Fixed a bug concerning customizable options. Customizable options of configurable products are shown again in the cart. ([@Jessevdpoel](https://github.com/Jessevdpoel))
85
296
 
86
297
  ## 8.0.1-canary.4
87
298
 
@@ -89,8 +300,7 @@
89
300
 
90
301
  ### Patch Changes
91
302
 
92
- - [#2190](https://github.com/graphcommerce-org/graphcommerce/pull/2190) [`770a309`](https://github.com/graphcommerce-org/graphcommerce/commit/770a309cdf0586aaaed5defd345e451dee8d89c8) - Fixed a bug concerning customizable options. Customizable options of configurable products are shown again in the cart.
93
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
303
+ - [#2190](https://github.com/graphcommerce-org/graphcommerce/pull/2190) [`770a309`](https://github.com/graphcommerce-org/graphcommerce/commit/770a309cdf0586aaaed5defd345e451dee8d89c8) - Fixed a bug concerning customizable options. Customizable options of configurable products are shown again in the cart. ([@Jessevdpoel](https://github.com/Jessevdpoel))
94
304
 
95
305
  ## 8.0.1-canary.2
96
306
 
@@ -102,25 +312,19 @@
102
312
 
103
313
  ### Minor Changes
104
314
 
105
- - [#2108](https://github.com/graphcommerce-org/graphcommerce/pull/2108) [`b9ab035`](https://github.com/graphcommerce-org/graphcommerce/commit/b9ab035893fd0fbbe747333973d0bb1948e5d846) - Added a new `<CartCrosssellsScroller />` component to render crosssells in a horizontal scroller in the cart.
106
- ([@StefanAngenent](https://github.com/StefanAngenent))
315
+ - [#2108](https://github.com/graphcommerce-org/graphcommerce/pull/2108) [`b9ab035`](https://github.com/graphcommerce-org/graphcommerce/commit/b9ab035893fd0fbbe747333973d0bb1948e5d846) - Added a new `<CartCrosssellsScroller />` component to render crosssells in a horizontal scroller in the cart. ([@StefanAngenent](https://github.com/StefanAngenent))
107
316
 
108
- - [#2099](https://github.com/graphcommerce-org/graphcommerce/pull/2099) [`ff796b8`](https://github.com/graphcommerce-org/graphcommerce/commit/ff796b838fae6cb5e35b101500133b0235a8677d) - Support for all customizable product options (except file upload) on the product pages and in the cart.
109
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
317
+ - [#2099](https://github.com/graphcommerce-org/graphcommerce/pull/2099) [`ff796b8`](https://github.com/graphcommerce-org/graphcommerce/commit/ff796b838fae6cb5e35b101500133b0235a8677d) - Support for all customizable product options (except file upload) on the product pages and in the cart. ([@Jessevdpoel](https://github.com/Jessevdpoel))
110
318
 
111
- - [#2018](https://github.com/graphcommerce-org/graphcommerce/pull/2018) [`750aa6a`](https://github.com/graphcommerce-org/graphcommerce/commit/750aa6a72710869d54244467253212e551d335e0) - Changed the layout of the succes page. We are using ActionCards right now to match the design of the cart.
112
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
319
+ - [#2018](https://github.com/graphcommerce-org/graphcommerce/pull/2018) [`750aa6a`](https://github.com/graphcommerce-org/graphcommerce/commit/750aa6a72710869d54244467253212e551d335e0) - Changed the layout of the succes page. We are using ActionCards right now to match the design of the cart. ([@Jessevdpoel](https://github.com/Jessevdpoel))
113
320
 
114
321
  ### Patch Changes
115
322
 
116
- - [#2179](https://github.com/graphcommerce-org/graphcommerce/pull/2179) [`2e6afd9`](https://github.com/graphcommerce-org/graphcommerce/commit/2e6afd945a41f94facfc0379ca6416de8552341f) - The `<UpdateItemQuantity />` component now accepts `textInputProps` to be passed to the `<TextInputNumber/>`.
117
- ([@paales](https://github.com/paales))
323
+ - [#2179](https://github.com/graphcommerce-org/graphcommerce/pull/2179) [`2e6afd9`](https://github.com/graphcommerce-org/graphcommerce/commit/2e6afd945a41f94facfc0379ca6416de8552341f) - The `<UpdateItemQuantity />` component now accepts `textInputProps` to be passed to the `<TextInputNumber/>`. ([@paales](https://github.com/paales))
118
324
 
119
- - [#2183](https://github.com/graphcommerce-org/graphcommerce/pull/2183) [`afc8810`](https://github.com/graphcommerce-org/graphcommerce/commit/afc8810d89f409f1ea2f6e82a01b3120ded208f9) - When updating the quantity of the product in the cart it could happen that the form would become out of sync with the actual data.
120
- ([@paales](https://github.com/paales))
325
+ - [#2183](https://github.com/graphcommerce-org/graphcommerce/pull/2183) [`afc8810`](https://github.com/graphcommerce-org/graphcommerce/commit/afc8810d89f409f1ea2f6e82a01b3120ded208f9) - When updating the quantity of the product in the cart it could happen that the form would become out of sync with the actual data. ([@paales](https://github.com/paales))
121
326
 
122
- - [#2079](https://github.com/graphcommerce-org/graphcommerce/pull/2079) [`98799e0`](https://github.com/graphcommerce-org/graphcommerce/commit/98799e0892d430f32b7599a351cf49a37cfc072c) - Updated styling `<SelectedCustomizableOptions />`, so items get more spacing and elements accessable via sx prop
123
- ([@mikekeehnen](https://github.com/mikekeehnen))
327
+ - [#2079](https://github.com/graphcommerce-org/graphcommerce/pull/2079) [`98799e0`](https://github.com/graphcommerce-org/graphcommerce/commit/98799e0892d430f32b7599a351cf49a37cfc072c) - Updated styling `<SelectedCustomizableOptions />`, so items get more spacing and elements accessable via sx prop ([@mikekeehnen](https://github.com/mikekeehnen))
124
328
 
125
329
  ## 8.0.0-canary.100
126
330
 
@@ -128,8 +332,7 @@
128
332
 
129
333
  ### Patch Changes
130
334
 
131
- - [#2183](https://github.com/graphcommerce-org/graphcommerce/pull/2183) [`afc8810`](https://github.com/graphcommerce-org/graphcommerce/commit/afc8810d89f409f1ea2f6e82a01b3120ded208f9) - When updating the quantity of the product in the cart it could happen that the form would become out of sync with the actual data.
132
- ([@paales](https://github.com/paales))
335
+ - [#2183](https://github.com/graphcommerce-org/graphcommerce/pull/2183) [`afc8810`](https://github.com/graphcommerce-org/graphcommerce/commit/afc8810d89f409f1ea2f6e82a01b3120ded208f9) - When updating the quantity of the product in the cart it could happen that the form would become out of sync with the actual data. ([@paales](https://github.com/paales))
133
336
 
134
337
  ## 8.0.0-canary.98
135
338
 
@@ -139,8 +342,7 @@
139
342
 
140
343
  ### Patch Changes
141
344
 
142
- - [#2179](https://github.com/graphcommerce-org/graphcommerce/pull/2179) [`2e6afd9`](https://github.com/graphcommerce-org/graphcommerce/commit/2e6afd945a41f94facfc0379ca6416de8552341f) - The `<UpdateItemQuantity />` component now accepts `textInputProps` to be passed to the `<TextInputNumber/>`.
143
- ([@paales](https://github.com/paales))
345
+ - [#2179](https://github.com/graphcommerce-org/graphcommerce/pull/2179) [`2e6afd9`](https://github.com/graphcommerce-org/graphcommerce/commit/2e6afd945a41f94facfc0379ca6416de8552341f) - The `<UpdateItemQuantity />` component now accepts `textInputProps` to be passed to the `<TextInputNumber/>`. ([@paales](https://github.com/paales))
144
346
 
145
347
  ## 8.0.0-canary.95
146
348
 
@@ -194,8 +396,7 @@
194
396
 
195
397
  ### Minor Changes
196
398
 
197
- - [#2099](https://github.com/graphcommerce-org/graphcommerce/pull/2099) [`ff796b8`](https://github.com/graphcommerce-org/graphcommerce/commit/ff796b838fae6cb5e35b101500133b0235a8677d) - Created UI for all customizable options except for the file upload customizable option
198
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
399
+ - [#2099](https://github.com/graphcommerce-org/graphcommerce/pull/2099) [`ff796b8`](https://github.com/graphcommerce-org/graphcommerce/commit/ff796b838fae6cb5e35b101500133b0235a8677d) - Created UI for all customizable options except for the file upload customizable option ([@Jessevdpoel](https://github.com/Jessevdpoel))
199
400
 
200
401
  ## 8.0.0-canary.70
201
402
 
@@ -207,8 +408,7 @@
207
408
 
208
409
  ### Minor Changes
209
410
 
210
- - [#2108](https://github.com/graphcommerce-org/graphcommerce/pull/2108) [`b9ab035`](https://github.com/graphcommerce-org/graphcommerce/commit/b9ab035893fd0fbbe747333973d0bb1948e5d846) - Add crosssells to cart
211
- ([@StefanAngenent](https://github.com/StefanAngenent))
411
+ - [#2108](https://github.com/graphcommerce-org/graphcommerce/pull/2108) [`b9ab035`](https://github.com/graphcommerce-org/graphcommerce/commit/b9ab035893fd0fbbe747333973d0bb1948e5d846) - Add crosssells to cart ([@StefanAngenent](https://github.com/StefanAngenent))
212
412
 
213
413
  ## 7.1.0-canary.66
214
414
 
@@ -1487,31 +1687,31 @@
1487
1687
  All occurences of `<Trans>` and `t` need to be replaced:
1488
1688
 
1489
1689
  ```tsx
1490
- import { Trans, t } from "@lingui/macro";
1690
+ import { Trans, t } from '@lingui/macro'
1491
1691
 
1492
1692
  function MyComponent() {
1493
- const foo = "bar";
1693
+ const foo = 'bar'
1494
1694
  return (
1495
1695
  <div aria-label={t`Account ${foo}`}>
1496
1696
  <Trans>My Translation {foo}</Trans>
1497
1697
  </div>
1498
- );
1698
+ )
1499
1699
  }
1500
1700
  ```
1501
1701
 
1502
1702
  Needs to be replaced with:
1503
1703
 
1504
1704
  ```tsx
1505
- import { Trans } from "@lingui/react";
1506
- import { i18n } from "@lingui/core";
1705
+ import { Trans } from '@lingui/react'
1706
+ import { i18n } from '@lingui/core'
1507
1707
 
1508
1708
  function MyComponent() {
1509
- const foo = "bar";
1709
+ const foo = 'bar'
1510
1710
  return (
1511
1711
  <div aria-label={i18n._(/* i18n */ `Account {foo}`, { foo })}>
1512
- <Trans key="My Translation {foo}" values={{ foo }}></Trans>
1712
+ <Trans key='My Translation {foo}' values={{ foo }}></Trans>
1513
1713
  </div>
1514
- );
1714
+ )
1515
1715
  }
1516
1716
  ```
1517
1717
 
@@ -5,7 +5,7 @@ import {
5
5
  ProductScroller,
6
6
  ProductScrollerProps,
7
7
  } from '@graphcommerce/magento-product'
8
- import { Trans } from '@lingui/react'
8
+ import { Trans } from '@lingui/macro'
9
9
 
10
10
  export type CartItemCrosssellsProps = {
11
11
  renderer: ProductListItemRenderer
@@ -24,7 +24,7 @@ export function CartCrosssellsScroller(props: CartItemCrosssellsProps) {
24
24
  productListRenderer={renderer}
25
25
  items={crossSellItems}
26
26
  sx={sx}
27
- title={title ?? <Trans id='Complete your purchase' />}
27
+ title={title ?? <Trans>Complete your purchase</Trans>}
28
28
  titleProps={{ variant: 'h6', ...titleProps }}
29
29
  />
30
30
  </AddProductsToCartForm>
@@ -93,10 +93,7 @@ export function CartItem(props: CartItemProps) {
93
93
  color='default'
94
94
  badgeContent={
95
95
  <RemoveItemFromCartFab
96
- uid={uid}
97
- quantity={quantity}
98
- prices={prices}
99
- product={product}
96
+ {...props}
100
97
  fabProps={{ className: classes.badge }}
101
98
  sx={(theme) => ({
102
99
  '& > button': {
@@ -1,13 +1,15 @@
1
1
  import { Image } from '@graphcommerce/image'
2
2
  import { useDisplayInclTax } from '@graphcommerce/magento-cart/hooks'
3
+ import { ProductLinkProps } from '@graphcommerce/magento-product'
3
4
  import { Money } from '@graphcommerce/magento-store'
4
5
  import {
5
6
  ActionCard,
6
7
  ActionCardProps,
7
- responsiveVal,
8
8
  filterNonNullableKeys,
9
+ actionCardImageSizes,
9
10
  } from '@graphcommerce/next-ui'
10
- import { Box, Link } from '@mui/material'
11
+ import { Trans } from '@lingui/react'
12
+ import { Box, Button, Link } from '@mui/material'
11
13
  import { CartItemFragment } from '../../Api/CartItem.gql'
12
14
  import { RemoveItemFromCart } from '../RemoveItemFromCart/RemoveItemFromCart'
13
15
  import { UpdateItemQuantity } from '../UpdateItemQuantity/UpdateItemQuantity'
@@ -17,20 +19,12 @@ export type CartItemActionCardProps = { cartItem: CartItemFragment; readOnly?: b
17
19
  'value' | 'image' | 'price' | 'title' | 'action'
18
20
  >
19
21
 
20
- export const productImageSizes = {
21
- small: responsiveVal(60, 80),
22
- medium: responsiveVal(60, 80),
23
- large: responsiveVal(100, 120),
24
- }
25
-
26
- const typographySizes = {
27
- small: 'body2',
28
- medium: 'body1',
29
- large: 'subtitle1',
22
+ export function productEditLink(link: ProductLinkProps) {
23
+ return `/checkout/item/${link.url_key}`
30
24
  }
31
25
 
32
26
  export function CartItemActionCard(props: CartItemActionCardProps) {
33
- const { cartItem, sx = [], size = 'large', readOnly = false, ...rest } = props
27
+ const { cartItem, sx = [], size = 'responsive', readOnly = false, ...rest } = props
34
28
  const { uid, quantity, prices, errors, product } = cartItem
35
29
  const { name, thumbnail, url_key } = product
36
30
 
@@ -49,6 +43,11 @@ export function CartItemActionCard(props: CartItemActionCardProps) {
49
43
  price = prices?.price.value
50
44
  }
51
45
 
46
+ const hasOptions = !(
47
+ (cartItem.__typename === 'SimpleCartItem' || cartItem.__typename === 'VirtualCartItem') &&
48
+ cartItem.customizable_options.length === 0
49
+ )
50
+
52
51
  return (
53
52
  <ActionCard
54
53
  value={uid}
@@ -58,13 +57,16 @@ export function CartItemActionCard(props: CartItemActionCardProps) {
58
57
  px: 0,
59
58
  py: theme.spacings.xs,
60
59
  },
61
- '& .MuiBox-root': {
60
+ '& .ActionCard-rootInner': {
62
61
  justifyContent: 'space-between',
63
62
  alignItems: 'stretch',
64
63
  },
65
64
  '&.sizeSmall': {
66
65
  px: 0,
67
66
  },
67
+ '&.sizeResponsive': {
68
+ [theme.breakpoints.down('md')]: { px: 0 },
69
+ },
68
70
  '& .ActionCard-end': {
69
71
  justifyContent: readOnly ? 'center' : 'space-between',
70
72
  },
@@ -75,16 +77,11 @@ export function CartItemActionCard(props: CartItemActionCardProps) {
75
77
  alignSelf: 'flex-start',
76
78
  },
77
79
  '& .ActionCard-secondaryAction': {
78
- typography: typographySizes[size],
79
- display: 'flex',
80
- alignItems: 'center',
81
- color: 'text.secondary',
82
- mt: 1,
83
- gap: '10px',
84
- justifyContent: 'start',
80
+ display: 'grid',
81
+ rowGap: theme.spacings.xs,
82
+ justifyItems: 'start',
85
83
  },
86
84
  '& .ActionCard-price': {
87
- typography: typographySizes[size],
88
85
  pr: readOnly ? 0 : theme.spacings.xs,
89
86
  mb: { xs: 0.5, sm: 0 },
90
87
  },
@@ -97,13 +94,13 @@ export function CartItemActionCard(props: CartItemActionCardProps) {
97
94
  layout='fill'
98
95
  src={thumbnail?.url}
99
96
  sx={{
100
- width: productImageSizes[size],
101
- height: productImageSizes[size],
97
+ width: actionCardImageSizes[size],
98
+ height: actionCardImageSizes[size],
102
99
  display: 'block',
103
100
  borderRadius: 1,
104
101
  objectFit: 'contain',
105
102
  }}
106
- sizes={productImageSizes[size]}
103
+ sizes={actionCardImageSizes[size]}
107
104
  />
108
105
  )
109
106
  }
@@ -126,14 +123,41 @@ export function CartItemActionCard(props: CartItemActionCardProps) {
126
123
  }
127
124
  secondaryAction={
128
125
  <>
129
- {readOnly ? quantity : <UpdateItemQuantity uid={uid} quantity={quantity} />}
130
- {' ⨉ '}
126
+ <Box
127
+ sx={{
128
+ display: 'flex',
129
+ alignItems: 'center',
130
+ color: 'text.secondary',
131
+ mt: 1,
132
+ gap: '10px',
133
+ justifyContent: 'start',
134
+ }}
135
+ >
136
+ {readOnly ? quantity : <UpdateItemQuantity uid={uid} quantity={quantity} />}
137
+ {' ⨉ '}
131
138
 
132
- <Money value={price} currency={prices?.price.currency} />
139
+ <Money value={price} currency={prices?.price.currency} />
140
+ </Box>
141
+ {hasOptions && !readOnly && (
142
+ <Button
143
+ variant='inline'
144
+ color='secondary'
145
+ href={`${productEditLink(product)}?cartItemId=${uid}`}
146
+ >
147
+ <Trans id='Edit options' />
148
+ </Button>
149
+ )}
133
150
  </>
134
151
  }
135
152
  price={<Money {...(inclTaxes ? prices?.row_total_including_tax : prices?.row_total)} />}
136
- action={!readOnly && <RemoveItemFromCart {...cartItem} buttonProps={{ size }} />}
153
+ action={
154
+ !readOnly && (
155
+ <RemoveItemFromCart
156
+ {...cartItem}
157
+ buttonProps={{ size: size === 'responsive' ? 'large' : size }}
158
+ />
159
+ )
160
+ }
137
161
  size={size}
138
162
  after={filterNonNullableKeys(errors).map((error) => (
139
163
  <Box sx={{ color: 'error.main', typography: 'caption' }} key={error.message}>
@@ -141,6 +165,7 @@ export function CartItemActionCard(props: CartItemActionCardProps) {
141
165
  </Box>
142
166
  ))}
143
167
  {...rest}
168
+ details={<>{rest.details}</>}
144
169
  />
145
170
  )
146
171
  }
@@ -1,5 +1,4 @@
1
1
  import { ActionCardLayout, ActionCardLayoutProps, nonNullable } from '@graphcommerce/next-ui'
2
- import { Theme, useMediaQuery } from '@mui/material'
3
2
  import { CartItemsFragment } from '../../Api/CartItems.gql'
4
3
  import {
5
4
  CartItemActionCard,
@@ -8,7 +7,13 @@ import {
8
7
 
9
8
  export type CartProps = Omit<ActionCardLayoutProps, 'className'> & {
10
9
  cart?: CartItemsFragment | null
10
+ /**
11
+ * @deprecated Not used anymore, please use the size prop
12
+ */
11
13
  sizeSm?: CartItemActionCardProps['size']
14
+ /**
15
+ * @deprecated Not used anymore, please use the size prop
16
+ */
12
17
  sizeMd?: CartItemActionCardProps['size']
13
18
  variant?: CartItemActionCardProps['variant']
14
19
  itemProps?: Omit<
@@ -31,32 +36,25 @@ export function CartItemsActionCards(props: CartProps) {
31
36
  children,
32
37
  layout = 'list',
33
38
  itemProps = {},
34
- sizeSm = 'medium',
35
- sizeMd = 'large',
36
39
  variant = 'default',
37
40
  ...remainingProps
38
41
  } = props
39
42
 
40
- const isMobile = useMediaQuery<Theme>((theme) => theme.breakpoints.down('md'), {
41
- defaultMatches: false,
42
- })
43
-
44
- const size = isMobile ? sizeSm : sizeMd
45
-
46
43
  if (!cart?.items?.length) return null
47
44
 
48
45
  return (
49
46
  <ActionCardLayout layout={layout} {...remainingProps}>
50
- {cart.items?.filter(nonNullable).map((item) => (
51
- <CartItemActionCard
52
- key={item.uid}
53
- cartItem={item}
54
- layout={layout}
55
- size={size}
56
- variant={variant}
57
- {...itemProps}
58
- />
59
- ))}
47
+ {cart.items
48
+ ?.filter(nonNullable)
49
+ .map((item) => (
50
+ <CartItemActionCard
51
+ key={item.uid}
52
+ cartItem={item}
53
+ layout={layout}
54
+ variant={variant}
55
+ {...itemProps}
56
+ />
57
+ ))}
60
58
  {children}
61
59
  </ActionCardLayout>
62
60
  )
@@ -0,0 +1,15 @@
1
+ import {
2
+ AddProductsToCartButton,
3
+ AddProductsToCartButtonProps,
4
+ } from '@graphcommerce/magento-product'
5
+ import { Trans } from '@lingui/react'
6
+
7
+ export function EditCartItemButton(props: AddProductsToCartButtonProps) {
8
+ const { children, ...rest } = props
9
+
10
+ return (
11
+ <AddProductsToCartButton color='secondary' {...rest}>
12
+ <Trans id='Save changes' />
13
+ </AddProductsToCartButton>
14
+ )
15
+ }
@@ -0,0 +1,8 @@
1
+ fragment EditCartItemForm on ProductInterface {
2
+ ...ProductCustomizable
3
+ ...ProductWeight
4
+ ...ProductPageItem
5
+ ...ConfigurableOptions
6
+ ...DownloadableProductOptions
7
+ ...BundleProductOptions
8
+ }
@@ -0,0 +1,70 @@
1
+ import { UseHistoryLink, useHistoryGo } from '@graphcommerce/framer-next-pages'
2
+ import {
3
+ useFormAddProductsToCart,
4
+ AddProductsToCartFormProps,
5
+ AddToCartItemSelector,
6
+ AddProductsToCartForm,
7
+ } from '@graphcommerce/magento-product'
8
+ import { useRouter } from 'next/router'
9
+ import { useEffect, useRef } from 'react'
10
+ import { CartItemsFragment } from '../../../Api/CartItems.gql'
11
+ import {
12
+ UseRemoveItemFromCartProps,
13
+ useRemoveItemFromCart,
14
+ } from '../../../hooks/useRemoveItemFromCart'
15
+ import {
16
+ CartItemToCartItemInputProps,
17
+ cartItemToCartItemInput,
18
+ } from '../../../utils/cartItemToCartItemInput'
19
+
20
+ type EditInitProps = CartItemToCartItemInputProps & AddToCartItemSelector
21
+
22
+ function EditInit(props: EditInitProps) {
23
+ const { product, selectors, cartItem, index = 0 } = props
24
+ const { setValue } = useFormAddProductsToCart()
25
+
26
+ useEffect(() => {
27
+ const cartItemInput = cartItemToCartItemInput({ product, cartItem, selectors })
28
+ if (cartItemInput) setValue(`cartItems.${index}`, cartItemInput)
29
+ }, [cartItem, index, product, selectors, setValue])
30
+
31
+ return null
32
+ }
33
+
34
+ export type EditCartItemFormProps = CartItemToCartItemInputProps &
35
+ AddToCartItemSelector &
36
+ UseHistoryLink &
37
+ AddProductsToCartFormProps
38
+
39
+ export function EditCartItemForm(props: EditCartItemFormProps) {
40
+ const { product, cartItem, onBeforeSubmit, onComplete, index = 0, children, href } = props
41
+
42
+ const remove = useRemoveItemFromCart(cartItem as UseRemoveItemFromCartProps)
43
+ const goToCart = useHistoryGo({ href })
44
+
45
+ return (
46
+ <AddProductsToCartForm
47
+ {...props}
48
+ onBeforeSubmit={async (variables) => {
49
+ await remove.submit()
50
+ return onBeforeSubmit?.(variables) ?? variables
51
+ }}
52
+ onComplete={async (result, variables) => {
53
+ await goToCart()
54
+ return onComplete?.(result, variables)
55
+ }}
56
+ >
57
+ {children}
58
+ <EditInit product={product} cartItem={cartItem} index={index} />
59
+ </AddProductsToCartForm>
60
+ )
61
+ }
62
+
63
+ export function useEditItem(cart: CartItemsFragment | null | undefined) {
64
+ const cartItemId = useRouter().query.cartItemId as string
65
+ const cartItem = cart?.items?.find((item) => item?.uid === cartItemId)
66
+ const cartItemRef = useRef(cartItem)
67
+ if (cartItem) cartItemRef.current = cartItem
68
+
69
+ return cartItemRef.current
70
+ }
@@ -0,0 +1,3 @@
1
+ export * from './EditCartItemButton/EditCartItemButton'
2
+ export * from './EditCartItemForm/EditCartItemForm'
3
+ export * from './EditCartItemForm/EditCartItemForm.gql'
@@ -1,12 +1,13 @@
1
- import { ApolloCartErrorSnackbar, useFormGqlMutationCart } from '@graphcommerce/magento-cart'
1
+ import { ApolloCartErrorSnackbar } from '@graphcommerce/magento-cart'
2
2
  import { Button, ButtonProps } from '@graphcommerce/next-ui'
3
3
  import { Trans } from '@lingui/react'
4
4
  import { SxProps, Theme, styled } from '@mui/material'
5
- import type { DistributedOmit } from 'type-fest'
6
- import { CartItemFragment } from '../../Api/CartItem.gql'
7
- import { RemoveItemFromCartDocument } from './RemoveItemFromCart.gql'
5
+ import {
6
+ UseRemoveItemFromCartProps,
7
+ useRemoveItemFromCart,
8
+ } from '../../hooks/useRemoveItemFromCart'
8
9
 
9
- export type RemoveItemFromCartProps = DistributedOmit<CartItemFragment, '__typename'> & {
10
+ export type RemoveItemFromCartProps = UseRemoveItemFromCartProps & {
10
11
  sx?: SxProps<Theme>
11
12
  buttonProps?: Omit<ButtonProps, 'type' | 'loading'>
12
13
  }
@@ -15,12 +16,10 @@ const Form = styled('form')({})
15
16
 
16
17
  export function RemoveItemFromCart(props: RemoveItemFromCartProps) {
17
18
  const { uid, quantity, prices, buttonProps, ...formProps } = props
18
- const form = useFormGqlMutationCart(RemoveItemFromCartDocument, { defaultValues: { uid } })
19
- const { handleSubmit, formState, error } = form
20
- const submitHandler = handleSubmit(() => {})
21
19
 
20
+ const { submit, formState, error } = useRemoveItemFromCart(props)
22
21
  return (
23
- <Form noValidate onSubmit={submitHandler} {...formProps}>
22
+ <Form noValidate onSubmit={submit} {...formProps}>
24
23
  <Button
25
24
  variant='inline'
26
25
  color='secondary'
@@ -1,11 +1,13 @@
1
- import { ApolloCartErrorSnackbar, useFormGqlMutationCart } from '@graphcommerce/magento-cart'
1
+ import { ApolloCartErrorSnackbar } from '@graphcommerce/magento-cart'
2
2
  import { Fab, FabProps, iconClose } from '@graphcommerce/next-ui'
3
3
  import { i18n } from '@lingui/core'
4
4
  import { SxProps, Theme, styled } from '@mui/material'
5
- import { CartItemFragment } from '../../Api/CartItem.gql'
6
- import { RemoveItemFromCartDocument } from './RemoveItemFromCart.gql'
5
+ import {
6
+ UseRemoveItemFromCartProps,
7
+ useRemoveItemFromCart,
8
+ } from '../../hooks/useRemoveItemFromCart'
7
9
 
8
- export type RemoveItemFromCartFabProps = Omit<CartItemFragment, '__typename'> & {
10
+ export type RemoveItemFromCartFabProps = UseRemoveItemFromCartProps & {
9
11
  sx?: SxProps<Theme>
10
12
  fabProps?: Omit<FabProps, 'type' | 'icon' | 'loading'>
11
13
  }
@@ -14,12 +16,11 @@ const Form = styled('form')({})
14
16
 
15
17
  export function RemoveItemFromCartFab(props: RemoveItemFromCartFabProps) {
16
18
  const { uid, quantity, prices, product, ...formProps } = props
17
- const form = useFormGqlMutationCart(RemoveItemFromCartDocument, { defaultValues: { uid } })
18
- const { handleSubmit, formState, error } = form
19
- const submitHandler = handleSubmit(() => {})
19
+
20
+ const { submit, formState, error } = useRemoveItemFromCart(props)
20
21
 
21
22
  return (
22
- <Form noValidate onSubmit={submitHandler} {...formProps}>
23
+ <Form noValidate onSubmit={submit} {...formProps}>
23
24
  <Fab
24
25
  aria-label={i18n._(/* i18n */ 'Remove Product')}
25
26
  size='small'
@@ -6,14 +6,11 @@ import { SelectedCustomizableOptionFragment } from './SelectedCustomizableOption
6
6
 
7
7
  type SelectedCustomizableOptionProps = CartItemFragment & {
8
8
  customizable_options?: (SelectedCustomizableOptionFragment | null | undefined)[] | null
9
- configurable_customizable?: (SelectedCustomizableOptionFragment | null | undefined)[] | null
10
9
  }
11
10
 
12
11
  export function SelectedCustomizableOptions(props: SelectedCustomizableOptionProps) {
13
- const { customizable_options, product, configurable_customizable } = props
14
- const options = customizable_options
15
- ? filterNonNullableKeys(customizable_options, [])
16
- : filterNonNullableKeys(configurable_customizable, [])
12
+ const { customizable_options, product } = props
13
+ const options = filterNonNullableKeys(customizable_options, [])
17
14
 
18
15
  if (!options.length) return null
19
16
 
@@ -22,29 +19,20 @@ export function SelectedCustomizableOptions(props: SelectedCustomizableOptionPro
22
19
  return (
23
20
  <>
24
21
  {options.map((option) => (
25
- <Box>
26
- <Box key={option.customizable_option_uid} sx={{ color: 'text.primary' }}>
27
- {option.label}
28
- </Box>
22
+ <Box key={option.customizable_option_uid}>
23
+ <Box sx={{ color: 'text.primary' }}>{option.label}</Box>
29
24
  {option.values.filter(nonNullable).map((value) => (
30
25
  <Box
31
- key={option.customizable_option_uid}
26
+ key={value.customizable_option_value_uid}
32
27
  sx={(theme) => ({
33
28
  display: 'flex',
34
29
  gap: theme.spacings.xxs,
35
30
  flexDirection: 'row',
36
31
  })}
37
32
  >
38
- {value.label && (
39
- <span key={`${value.customizable_option_value_uid}_${value.label}`}>
40
- {value.label}
41
- </span>
42
- )}
33
+ {value.label && <span>{value.label}</span>}
43
34
  {value.price.value > 0 && productPrice && (
44
- <Box
45
- sx={(theme) => ({ position: 'absolute', right: theme.spacings.xs })}
46
- key={`${value.customizable_option_value_uid}_${value.price.value}`}
47
- >
35
+ <Box sx={(theme) => ({ position: 'absolute', right: theme.spacings.xs })}>
48
36
  <Money
49
37
  value={
50
38
  value.price.type === 'PERCENT'
@@ -1,6 +1,5 @@
1
1
  import { NumberFieldElement, NumberFieldElementProps } from '@graphcommerce/ecommerce-ui'
2
2
  import { ApolloCartErrorSnackbar, useFormGqlMutationCart } from '@graphcommerce/magento-cart'
3
- import { TextInputNumberProps } from '@graphcommerce/next-ui'
4
3
  import { FormAutoSubmit, UseFormGraphQlOptions } from '@graphcommerce/react-hook-form'
5
4
  import { SxProps, Theme } from '@mui/material'
6
5
  import React from 'react'
@@ -27,7 +26,6 @@ export type UpdateItemQuantityProps = Omit<UpdateItemQuantityMutationVariables,
27
26
  export function UpdateItemQuantity(props: UpdateItemQuantityProps) {
28
27
  const { uid, quantity, sx, textInputProps, formOptions } = props
29
28
  const form = useFormGqlMutationCart(UpdateItemQuantityDocument, {
30
- experimental_useV2: true,
31
29
  defaultValues: { uid, quantity },
32
30
  mode: 'onChange',
33
31
  ...formOptions,
@@ -38,7 +36,7 @@ export function UpdateItemQuantity(props: UpdateItemQuantityProps) {
38
36
 
39
37
  return (
40
38
  <form noValidate onSubmit={submit}>
41
- <FormAutoSubmit control={control} submit={submit} initialWait={0} />
39
+ <FormAutoSubmit control={control} submit={submit} leading />
42
40
  <NumberFieldElement
43
41
  control={control}
44
42
  name='quantity'
@@ -0,0 +1,28 @@
1
+ import { useFormGqlMutationCart } from '@graphcommerce/magento-cart/hooks'
2
+ import { UseFormGraphQlOptions } from '@graphcommerce/react-hook-form'
3
+ import type { DistributedOmit } from 'type-fest'
4
+ import { CartItemFragment } from '../Api/CartItem.gql'
5
+ import {
6
+ RemoveItemFromCartMutation,
7
+ RemoveItemFromCartMutationVariables,
8
+ RemoveItemFromCartDocument,
9
+ } from '../components/RemoveItemFromCart/RemoveItemFromCart.gql'
10
+
11
+ export type UseRemoveItemFromCartProps = DistributedOmit<CartItemFragment, '__typename'> &
12
+ Omit<
13
+ UseFormGraphQlOptions<RemoveItemFromCartMutation, RemoveItemFromCartMutationVariables>,
14
+ 'errors'
15
+ >
16
+
17
+ export function useRemoveItemFromCart(props: UseRemoveItemFromCartProps) {
18
+ const { uid, errors, ...options } = props
19
+
20
+ const form = useFormGqlMutationCart(RemoveItemFromCartDocument, {
21
+ defaultValues: { uid },
22
+ ...options,
23
+ })
24
+
25
+ const { handleSubmit } = form
26
+ const submit = handleSubmit(() => {})
27
+ return { ...form, submit }
28
+ }
package/index.ts CHANGED
@@ -9,3 +9,5 @@ export * from './components/RemoveItemFromCart/RemoveItemFromCart.gql'
9
9
  export * from './components/RemoveItemFromCart/RemoveItemFromCartFab'
10
10
  export * from './components/SelectedCustomizableOptions/SelectedCustomizableOptions'
11
11
  export * from './components/UpdateItemQuantity/UpdateItemQuantity'
12
+ export * from './components/EditCartItem'
13
+ export * from './hooks/useRemoveItemFromCart'
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-cart-items",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "8.1.0-canary.9",
5
+ "version": "9.0.0-canary.101",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -12,17 +12,18 @@
12
12
  }
13
13
  },
14
14
  "peerDependencies": {
15
- "@graphcommerce/eslint-config-pwa": "^8.1.0-canary.9",
16
- "@graphcommerce/graphql": "^8.1.0-canary.9",
17
- "@graphcommerce/image": "^8.1.0-canary.9",
18
- "@graphcommerce/magento-cart": "^8.1.0-canary.9",
19
- "@graphcommerce/magento-customer": "^8.1.0-canary.9",
20
- "@graphcommerce/magento-product": "^8.1.0-canary.9",
21
- "@graphcommerce/magento-store": "^8.1.0-canary.9",
22
- "@graphcommerce/next-ui": "^8.1.0-canary.9",
23
- "@graphcommerce/prettier-config-pwa": "^8.1.0-canary.9",
24
- "@graphcommerce/react-hook-form": "^8.1.0-canary.9",
25
- "@graphcommerce/typescript-config-pwa": "^8.1.0-canary.9",
15
+ "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.101",
16
+ "@graphcommerce/framer-next-pages": "^9.0.0-canary.101",
17
+ "@graphcommerce/graphql": "^9.0.0-canary.101",
18
+ "@graphcommerce/image": "^9.0.0-canary.101",
19
+ "@graphcommerce/magento-cart": "^9.0.0-canary.101",
20
+ "@graphcommerce/magento-customer": "^9.0.0-canary.101",
21
+ "@graphcommerce/magento-product": "^9.0.0-canary.101",
22
+ "@graphcommerce/magento-store": "^9.0.0-canary.101",
23
+ "@graphcommerce/next-ui": "^9.0.0-canary.101",
24
+ "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.101",
25
+ "@graphcommerce/react-hook-form": "^9.0.0-canary.101",
26
+ "@graphcommerce/typescript-config-pwa": "^9.0.0-canary.101",
26
27
  "@lingui/core": "^4.2.1",
27
28
  "@lingui/macro": "^4.2.1",
28
29
  "@lingui/react": "^4.2.1",
@@ -33,6 +34,6 @@
33
34
  "react-dom": "^18.2.0"
34
35
  },
35
36
  "devDependencies": {
36
- "type-fest": "^4.15.0"
37
+ "type-fest": "^4.26.1"
37
38
  }
38
39
  }
@@ -0,0 +1,113 @@
1
+ import {
2
+ AddProductsToCartFields,
3
+ AnyOption,
4
+ CustomizableProductOptionBase,
5
+ OptionValueSelector,
6
+ SelectorsProp,
7
+ productCustomizableSelectors,
8
+ } from '@graphcommerce/magento-product'
9
+ import { isTypename, filterNonNullableKeys, nonNullable } from '@graphcommerce/next-ui'
10
+ import { CartItemFragment } from '../Api/CartItem.gql'
11
+ import { EditCartItemFormFragment } from '../components/EditCartItem/EditCartItemForm/EditCartItemForm.gql'
12
+
13
+ type CartItemInput = AddProductsToCartFields['cartItems'][number]
14
+
15
+ export type CartItemToCartItemInputProps = {
16
+ product: EditCartItemFormFragment
17
+ cartItem: CartItemFragment
18
+ } & SelectorsProp
19
+
20
+ export function cartItemToCartItemInput(
21
+ props: CartItemToCartItemInputProps,
22
+ ): CartItemInput | undefined {
23
+ const { product, cartItem, selectors } = props
24
+
25
+ if (isTypename(product, ['GroupedProduct']) || !product.sku || !cartItem) return undefined
26
+
27
+ const allSelectors: OptionValueSelector = { ...productCustomizableSelectors, ...selectors }
28
+
29
+ const cartItemInput: CartItemInput = {
30
+ sku: product.sku,
31
+ quantity: cartItem.quantity,
32
+ customizable_options: {},
33
+ selected_options: [],
34
+ entered_options: [],
35
+ }
36
+
37
+ const cartItemCustomizableOptions = filterNonNullableKeys(cartItem.customizable_options ?? {})
38
+
39
+ if (cartItemCustomizableOptions.length > 0) {
40
+ product.options?.filter(nonNullable).forEach((productOption) => {
41
+ // @todo Date option: Magento's backend does not provide an ISO date string that can be used, only localized strings are available which can not be parsed.
42
+ // @todo File option: We do not support file options yet.
43
+ if (isTypename(productOption, ['CustomizableDateOption', 'CustomizableFileOption'])) return
44
+
45
+ const selector = allSelectors[productOption.__typename] as
46
+ | undefined
47
+ | ((option: AnyOption) => CustomizableProductOptionBase | CustomizableProductOptionBase[])
48
+ const possibleProductValues = selector ? selector(productOption) : null
49
+
50
+ const cartItemCustomizableOption = cartItemCustomizableOptions.find(
51
+ (option) => option?.customizable_option_uid === productOption.uid,
52
+ )
53
+
54
+ const cartItemCustomizableOptionValue = filterNonNullableKeys(
55
+ cartItemCustomizableOption?.values,
56
+ )
57
+ if (cartItemCustomizableOptionValue.length === 0) return
58
+
59
+ if (Array.isArray(possibleProductValues)) {
60
+ const value = cartItemCustomizableOptionValue.map((v) => v.customizable_option_value_uid)
61
+ if (!cartItemInput.customizable_options) cartItemInput.customizable_options = {}
62
+ cartItemInput.customizable_options[productOption.uid] = isTypename(productOption, [
63
+ 'CustomizableRadioOption',
64
+ 'CustomizableDropDownOption',
65
+ ])
66
+ ? value[0]
67
+ : value
68
+ } else {
69
+ const idx = (productOption.sort_order ?? 0) + 100
70
+
71
+ if (!cartItemInput.entered_options) cartItemInput.entered_options = []
72
+ cartItemInput.entered_options[idx] = {
73
+ uid: productOption.uid,
74
+ value: cartItemCustomizableOptionValue[0].value,
75
+ }
76
+ }
77
+ })
78
+ }
79
+
80
+ if (isTypename(cartItem, ['ConfigurableCartItem']) && cartItem.configurable_options) {
81
+ cartItemInput.selected_options = filterNonNullableKeys(cartItem.configurable_options).map(
82
+ (option) => option.configurable_product_option_value_uid,
83
+ )
84
+ }
85
+
86
+ if (isTypename(cartItem, ['BundleCartItem']) && isTypename(product, ['BundleProduct'])) {
87
+ filterNonNullableKeys(product.items).forEach((productBundleItem) => {
88
+ const cartItemBundleOption = cartItem.bundle_options.find(
89
+ (option) => option?.uid === productBundleItem?.uid,
90
+ )
91
+
92
+ if (!cartItemBundleOption) return
93
+
94
+ // todo multi select..
95
+ const idx = productBundleItem.position ?? 0 + 1000
96
+ const value = cartItemBundleOption.values[0]
97
+
98
+ if (!value) return
99
+ if (productBundleItem.options?.some((o) => o?.can_change_quantity)) {
100
+ if (!cartItemInput.entered_options) cartItemInput.entered_options = []
101
+ cartItemInput.entered_options[idx] = {
102
+ uid: value.uid,
103
+ value: `${value.quantity}`,
104
+ }
105
+ } else {
106
+ if (!cartItemInput.selected_options) cartItemInput.selected_options = []
107
+ cartItemInput.selected_options[idx] = value.uid
108
+ }
109
+ })
110
+ }
111
+
112
+ return cartItemInput
113
+ }