@graphcommerce/magento-cart-items 8.1.0-canary.8 → 9.0.0-canary.100

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.100
4
+
5
+ ## 9.0.0-canary.99
6
+
7
+ ## 9.0.0-canary.98
8
+
9
+ ## 9.0.0-canary.97
10
+
11
+ ## 9.0.0-canary.96
12
+
13
+ ## 9.0.0-canary.95
14
+
15
+ ## 9.0.0-canary.94
16
+
17
+ ## 9.0.0-canary.93
18
+
19
+ ## 9.0.0-canary.92
20
+
21
+ ## 9.0.0-canary.91
22
+
23
+ ## 9.0.0-canary.90
24
+
25
+ ## 9.0.0-canary.89
26
+
27
+ ## 9.0.0-canary.88
28
+
29
+ ## 9.0.0-canary.87
30
+
31
+ ## 9.0.0-canary.86
32
+
33
+ ## 9.0.0-canary.85
34
+
35
+ ## 9.0.0-canary.84
36
+
37
+ ## 9.0.0-canary.83
38
+
39
+ ## 9.0.0-canary.82
40
+
41
+ ## 9.0.0-canary.81
42
+
43
+ ## 9.0.0-canary.80
44
+
45
+ ### Minor Changes
46
+
47
+ - [#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))
48
+
49
+ ### Patch Changes
50
+
51
+ - [#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))
52
+
53
+ ## 9.0.0-canary.79
54
+
55
+ ## 9.0.0-canary.78
56
+
57
+ ## 9.0.0-canary.77
58
+
59
+ ## 9.0.0-canary.76
60
+
61
+ ## 9.0.0-canary.75
62
+
63
+ ## 9.0.0-canary.74
64
+
65
+ ## 9.0.0-canary.73
66
+
67
+ ## 9.0.0-canary.72
68
+
69
+ ## 9.0.0-canary.71
70
+
71
+ ## 9.0.0-canary.70
72
+
73
+ ## 9.0.0-canary.69
74
+
75
+ ## 9.0.0-canary.68
76
+
77
+ ## 9.0.0-canary.67
78
+
79
+ ## 9.0.0-canary.66
80
+
81
+ ## 9.0.0-canary.65
82
+
83
+ ## 9.0.0-canary.64
84
+
85
+ ## 9.0.0-canary.63
86
+
87
+ ## 9.0.0-canary.62
88
+
89
+ ## 9.0.0-canary.61
90
+
91
+ ## 9.0.0-canary.60
92
+
93
+ ## 9.0.0-canary.59
94
+
95
+ ## 9.0.0-canary.58
96
+
97
+ ## 9.0.0-canary.57
98
+
99
+ ## 9.0.0-canary.56
100
+
101
+ ## 9.0.0-canary.55
102
+
103
+ ## 9.0.0-canary.54
104
+
105
+ ## 8.1.0-canary.53
106
+
107
+ ## 8.1.0-canary.52
108
+
109
+ ## 8.1.0-canary.51
110
+
111
+ ### Minor Changes
112
+
113
+ - [#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))
114
+
115
+ ## 8.1.0-canary.50
116
+
117
+ ## 8.1.0-canary.49
118
+
119
+ ## 8.1.0-canary.48
120
+
121
+ ## 8.1.0-canary.47
122
+
123
+ ## 8.1.0-canary.46
124
+
125
+ ## 8.1.0-canary.45
126
+
127
+ ### Patch Changes
128
+
129
+ - [#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))
130
+
131
+ ## 8.1.0-canary.44
132
+
133
+ ## 8.1.0-canary.43
134
+
135
+ ## 8.1.0-canary.42
136
+
137
+ ## 8.1.0-canary.41
138
+
139
+ ## 8.1.0-canary.40
140
+
141
+ ## 8.1.0-canary.39
142
+
143
+ ## 8.1.0-canary.38
144
+
145
+ ## 8.1.0-canary.37
146
+
147
+ ## 8.1.0-canary.36
148
+
149
+ ## 8.1.0-canary.35
150
+
151
+ ## 8.1.0-canary.34
152
+
153
+ ## 8.1.0-canary.33
154
+
155
+ ## 8.1.0-canary.32
156
+
157
+ ## 8.1.0-canary.31
158
+
159
+ ## 8.1.0-canary.30
160
+
161
+ ## 8.1.0-canary.29
162
+
163
+ ## 8.1.0-canary.28
164
+
165
+ ## 8.1.0-canary.27
166
+
167
+ ## 8.1.0-canary.26
168
+
169
+ ## 8.1.0-canary.25
170
+
171
+ ## 8.1.0-canary.24
172
+
173
+ ## 8.1.0-canary.23
174
+
175
+ ## 8.1.0-canary.22
176
+
177
+ ## 8.1.0-canary.21
178
+
179
+ ## 8.1.0-canary.20
180
+
181
+ ### Minor Changes
182
+
183
+ - [#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))
184
+
185
+ ### Patch Changes
186
+
187
+ - [#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))
188
+
189
+ ## 8.1.0-canary.19
190
+
191
+ ## 8.1.0-canary.18
192
+
193
+ ## 8.1.0-canary.17
194
+
195
+ ### Minor Changes
196
+
197
+ - [#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))
198
+
199
+ ## 8.1.0-canary.16
200
+
201
+ ## 8.1.0-canary.15
202
+
203
+ ## 8.1.0-canary.14
204
+
205
+ ## 8.1.0-canary.13
206
+
207
+ ## 8.1.0-canary.12
208
+
209
+ ## 8.1.0-canary.11
210
+
211
+ ## 8.1.0-canary.10
212
+
213
+ ## 8.1.0-canary.9
214
+
3
215
  ## 8.1.0-canary.8
4
216
 
5
217
  ## 8.1.0-canary.7
@@ -78,8 +290,7 @@
78
290
 
79
291
  ### Patch Changes
80
292
 
81
- - [#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.
82
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
293
+ - [#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))
83
294
 
84
295
  ## 8.0.1-canary.4
85
296
 
@@ -87,8 +298,7 @@
87
298
 
88
299
  ### Patch Changes
89
300
 
90
- - [#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.
91
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
301
+ - [#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))
92
302
 
93
303
  ## 8.0.1-canary.2
94
304
 
@@ -100,25 +310,19 @@
100
310
 
101
311
  ### Minor Changes
102
312
 
103
- - [#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.
104
- ([@StefanAngenent](https://github.com/StefanAngenent))
313
+ - [#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))
105
314
 
106
- - [#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.
107
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
315
+ - [#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))
108
316
 
109
- - [#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.
110
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
317
+ - [#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))
111
318
 
112
319
  ### Patch Changes
113
320
 
114
- - [#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/>`.
115
- ([@paales](https://github.com/paales))
321
+ - [#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))
116
322
 
117
- - [#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.
118
- ([@paales](https://github.com/paales))
323
+ - [#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))
119
324
 
120
- - [#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
121
- ([@mikekeehnen](https://github.com/mikekeehnen))
325
+ - [#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))
122
326
 
123
327
  ## 8.0.0-canary.100
124
328
 
@@ -126,8 +330,7 @@
126
330
 
127
331
  ### Patch Changes
128
332
 
129
- - [#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.
130
- ([@paales](https://github.com/paales))
333
+ - [#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))
131
334
 
132
335
  ## 8.0.0-canary.98
133
336
 
@@ -137,8 +340,7 @@
137
340
 
138
341
  ### Patch Changes
139
342
 
140
- - [#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/>`.
141
- ([@paales](https://github.com/paales))
343
+ - [#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))
142
344
 
143
345
  ## 8.0.0-canary.95
144
346
 
@@ -192,8 +394,7 @@
192
394
 
193
395
  ### Minor Changes
194
396
 
195
- - [#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
196
- ([@Jessevdpoel](https://github.com/Jessevdpoel))
397
+ - [#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))
197
398
 
198
399
  ## 8.0.0-canary.70
199
400
 
@@ -205,8 +406,7 @@
205
406
 
206
407
  ### Minor Changes
207
408
 
208
- - [#2108](https://github.com/graphcommerce-org/graphcommerce/pull/2108) [`b9ab035`](https://github.com/graphcommerce-org/graphcommerce/commit/b9ab035893fd0fbbe747333973d0bb1948e5d846) - Add crosssells to cart
209
- ([@StefanAngenent](https://github.com/StefanAngenent))
409
+ - [#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))
210
410
 
211
411
  ## 7.1.0-canary.66
212
412
 
@@ -1485,31 +1685,31 @@
1485
1685
  All occurences of `<Trans>` and `t` need to be replaced:
1486
1686
 
1487
1687
  ```tsx
1488
- import { Trans, t } from "@lingui/macro";
1688
+ import { Trans, t } from '@lingui/macro'
1489
1689
 
1490
1690
  function MyComponent() {
1491
- const foo = "bar";
1691
+ const foo = 'bar'
1492
1692
  return (
1493
1693
  <div aria-label={t`Account ${foo}`}>
1494
1694
  <Trans>My Translation {foo}</Trans>
1495
1695
  </div>
1496
- );
1696
+ )
1497
1697
  }
1498
1698
  ```
1499
1699
 
1500
1700
  Needs to be replaced with:
1501
1701
 
1502
1702
  ```tsx
1503
- import { Trans } from "@lingui/react";
1504
- import { i18n } from "@lingui/core";
1703
+ import { Trans } from '@lingui/react'
1704
+ import { i18n } from '@lingui/core'
1505
1705
 
1506
1706
  function MyComponent() {
1507
- const foo = "bar";
1707
+ const foo = 'bar'
1508
1708
  return (
1509
1709
  <div aria-label={i18n._(/* i18n */ `Account {foo}`, { foo })}>
1510
- <Trans key="My Translation {foo}" values={{ foo }}></Trans>
1710
+ <Trans key='My Translation {foo}' values={{ foo }}></Trans>
1511
1711
  </div>
1512
- );
1712
+ )
1513
1713
  }
1514
1714
  ```
1515
1715
 
@@ -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.8",
5
+ "version": "9.0.0-canary.100",
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.8",
16
- "@graphcommerce/graphql": "^8.1.0-canary.8",
17
- "@graphcommerce/image": "^8.1.0-canary.8",
18
- "@graphcommerce/magento-cart": "^8.1.0-canary.8",
19
- "@graphcommerce/magento-customer": "^8.1.0-canary.8",
20
- "@graphcommerce/magento-product": "^8.1.0-canary.8",
21
- "@graphcommerce/magento-store": "^8.1.0-canary.8",
22
- "@graphcommerce/next-ui": "^8.1.0-canary.8",
23
- "@graphcommerce/prettier-config-pwa": "^8.1.0-canary.8",
24
- "@graphcommerce/react-hook-form": "^8.1.0-canary.8",
25
- "@graphcommerce/typescript-config-pwa": "^8.1.0-canary.8",
15
+ "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.100",
16
+ "@graphcommerce/framer-next-pages": "^9.0.0-canary.100",
17
+ "@graphcommerce/graphql": "^9.0.0-canary.100",
18
+ "@graphcommerce/image": "^9.0.0-canary.100",
19
+ "@graphcommerce/magento-cart": "^9.0.0-canary.100",
20
+ "@graphcommerce/magento-customer": "^9.0.0-canary.100",
21
+ "@graphcommerce/magento-product": "^9.0.0-canary.100",
22
+ "@graphcommerce/magento-store": "^9.0.0-canary.100",
23
+ "@graphcommerce/next-ui": "^9.0.0-canary.100",
24
+ "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.100",
25
+ "@graphcommerce/react-hook-form": "^9.0.0-canary.100",
26
+ "@graphcommerce/typescript-config-pwa": "^9.0.0-canary.100",
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.22.0"
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
+ }