@hanzo/commerce 7.3.1 → 7.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/components/Icons.tsx +34 -34
  2. package/components/add-to-cart-widget.tsx +183 -183
  3. package/components/buy/buy-card.tsx +259 -259
  4. package/components/buy/carousel-buy-card.tsx +242 -242
  5. package/components/buy/multi-family/all-variants-carousel.tsx +261 -261
  6. package/components/buy/multi-family/family-carousel/index.tsx +77 -77
  7. package/components/buy/multi-family/family-carousel/slide.tsx +83 -83
  8. package/components/buy/multi-family/family-carousel/state.ts +87 -87
  9. package/components/buy/multi-family/index.ts +2 -2
  10. package/components/buy/single-family-selector.tsx +90 -90
  11. package/components/buy/title-and-byline.tsx +25 -25
  12. package/components/cart/cart-panel/cart-line-item.tsx +76 -76
  13. package/components/cart/cart-panel/index.tsx +154 -154
  14. package/components/cart/cart-panel/promo-code.tsx +106 -106
  15. package/components/cart/cart-panel/total-area.tsx +60 -60
  16. package/components/checkout/payment-step-form/card-icon-row.tsx +26 -26
  17. package/components/checkout/payment-step-form/card-icons/amex.tsx +32 -32
  18. package/components/checkout/payment-step-form/card-icons/diners-club.tsx +13 -13
  19. package/components/checkout/payment-step-form/card-icons/discover.tsx +25 -25
  20. package/components/checkout/payment-step-form/card-icons/jcb.tsx +26 -26
  21. package/components/checkout/payment-step-form/card-icons/mastercard.tsx +27 -27
  22. package/components/checkout/payment-step-form/card-icons/visa.tsx +25 -25
  23. package/components/checkout/payment-step-form/cc-button.tsx +17 -17
  24. package/components/checkout/payment-step-form/contact-form.tsx +49 -49
  25. package/components/checkout/payment-step-form/crypto-icons/btc.tsx +11 -11
  26. package/components/checkout/payment-step-form/crypto-icons/eth.tsx +20 -20
  27. package/components/checkout/payment-step-form/crypto-icons/usdt.tsx +13 -13
  28. package/components/checkout/payment-step-form/index.tsx +122 -122
  29. package/components/checkout/payment-step-form/methods/bank-transfer.tsx +79 -79
  30. package/components/checkout/payment-step-form/methods/card.tsx +232 -232
  31. package/components/checkout/payment-step-form/methods/crypto.tsx +227 -227
  32. package/components/checkout/payment-step-form/methods/index.ts +22 -22
  33. package/components/checkout/shipping-step-form.tsx +172 -172
  34. package/components/index.ts +11 -11
  35. package/components/item/product-card.tsx +48 -48
  36. package/components/item-selector/button.tsx +188 -188
  37. package/components/item-selector/carousel/index.tsx +197 -197
  38. package/components/item-selector/carousel/slider.tsx +40 -40
  39. package/components/item-selector/index.ts +5 -5
  40. package/components/item-selector/quantity-indicator.tsx +48 -48
  41. package/components/node-tabs/index.tsx +91 -91
  42. package/components/node-tabs/node-image.tsx +31 -31
  43. package/index.ts +12 -12
  44. package/package.json +60 -60
  45. package/service/context.tsx +45 -45
  46. package/service/debug.ts +41 -41
  47. package/service/impls/standalone/actual-line-item.ts +135 -135
  48. package/service/impls/standalone/get-instance.ts +64 -64
  49. package/service/impls/standalone/index.ts +579 -579
  50. package/service/impls/standalone/order/firebase.ts +14 -14
  51. package/service/impls/standalone/order/index.ts +128 -128
  52. package/service/impls/standalone/persistence.ts +33 -33
  53. package/service/path-utils.ts +25 -25
  54. package/service/sep.ts +6 -6
  55. package/tsconfig.json +10 -10
  56. package/types/README.md +1 -1
  57. package/types/category-node.ts +49 -49
  58. package/types/checkout.ts +46 -46
  59. package/types/commerce-config.ts +13 -13
  60. package/types/commerce-service.ts +127 -127
  61. package/types/family.ts +25 -25
  62. package/types/index.ts +15 -15
  63. package/types/item-selector.ts +96 -96
  64. package/types/line-item.ts +29 -29
  65. package/types/multi-family-selector-props.ts +19 -19
  66. package/types/product.ts +20 -20
  67. package/types/promo.ts +9 -9
  68. package/types/selection-ui-specifier.ts +51 -51
  69. package/types/string-mutator.ts +13 -13
  70. package/types/token-separators.ts +7 -7
  71. package/util/analytics.ts +20 -20
  72. package/util/countries.ts +195 -195
  73. package/util/error.ts +34 -34
  74. package/util/index.ts +70 -70
  75. package/util/item-selector-options-accessor.ts +34 -34
  76. package/util/line-item-ref.ts +23 -23
  77. package/util/multi-family-selector-options-accessor.ts +14 -14
  78. package/util/obs-string-mutator.ts +22 -22
  79. package/util/product-media-accessor.ts +58 -58
  80. package/util/promo-codes.ts +108 -108
  81. package/util/selection-ui-specifiers.ts +29 -29
  82. package/util/square-payment.ts +42 -42
  83. package/util/use-sync-sku-param-w-current-item.ts +88 -88
@@ -1,259 +1,259 @@
1
- 'use client'
2
- import React, { useRef, useEffect, type ComponentType } from 'react'
3
- import { reaction, type IReactionDisposer } from 'mobx'
4
- import { observer } from 'mobx-react-lite'
5
-
6
- import { cn } from '@hanzo/ui/util'
7
- import { ApplyTypography, MediaStack } from '@hanzo/ui/primitives'
8
-
9
- import type {
10
- ItemSelectorProps,
11
- ItemSelectorCompProps,
12
- LineItem,
13
- Family,
14
- CategoryNode,
15
- } from '../../types'
16
-
17
- import { useCommerce } from '../../service/context'
18
- import * as pathUtils from '../../service/path-utils'
19
- import { getFacetValuesMutator, ObsStringMutator } from '../../util'
20
-
21
- import NodeTabs from '../node-tabs'
22
- import AddToCartWidget from '../add-to-cart-widget'
23
-
24
- const BuyCard: React.FC<{
25
- skuPath: string
26
-
27
- /** For any selectors that show a list of choices,
28
- * starting with 'scrollAfter' elements,
29
- * the list will scroll, and the card will
30
- * have 'scrollHeightClx' applied to it to define and fix the height.
31
- * This is most like something like '80vh'
32
- * defaults are '5' and 'h-[70vh]'
33
- * */
34
- scrollAfter?: number
35
- scrollHeightClx?: string
36
-
37
- clx?: string
38
- famWidgetClx?: string
39
- addWidgetClx?: string
40
-
41
- selector: ComponentType<ItemSelectorProps>
42
- selectorProps?: ItemSelectorCompProps
43
-
44
- /** Show all items from all sibling families
45
- * If skuPath defines a Family, the first of it's items will
46
- * be selected. The facet widget will just select a the first
47
- * item in the chosen Family without changings the overall set
48
- * of choices. */
49
- allVariants?: boolean
50
-
51
- familyTabAs?: 'image' | 'label' | 'image-and-label'
52
- showItemMedia?: boolean
53
-
54
- onQuantityChanged?: (sku: string, oldV: number, newV: number) => void
55
- mobile?: boolean
56
- }> = observer(({
57
- skuPath,
58
- scrollAfter=5,
59
- scrollHeightClx='h-[80vh]',
60
- clx='',
61
- famWidgetClx='',
62
- addWidgetClx='',
63
- selector: Selector,
64
- selectorProps={
65
- clx: '',
66
- soleItemClx: '',
67
- itemClx: '',
68
- ext: {}
69
- },
70
- familyTabAs='image-and-label',
71
- showItemMedia=true,
72
- allVariants=false,
73
- mobile=false,
74
- onQuantityChanged,
75
- }) => {
76
-
77
- const cmmc = useCommerce()
78
- const inst = useRef<{
79
- level: number,
80
- requestedFamily : Family | undefined
81
- requestedNode: CategoryNode | undefined
82
- currentFamTokenMutator: ObsStringMutator
83
- disposers: IReactionDisposer[]
84
- } | undefined>(undefined)
85
-
86
-
87
- useEffect(() => {
88
-
89
- let requestedFamily = cmmc.getFamilyById(skuPath)
90
- let requestedNode = requestedFamily ? undefined : cmmc.getNodeAtPath(skuPath)
91
- let initialFamily = undefined
92
-
93
- const { paths, level } = pathUtils.getSelectedPaths(skuPath)
94
-
95
- if (level === 0) {
96
- throw new Error('BuyCard.useEffect(): must specify at least at least one Level in skuPath!')
97
- }
98
- if (requestedFamily) {
99
- if (allVariants && level >= 2) {
100
- // select all siblings of requestedFamily.
101
- // ie, go one level back
102
- delete paths[level]
103
- initialFamily = requestedFamily
104
- requestedFamily = undefined
105
- requestedNode = cmmc.getNodeAtPath(pathUtils.getParentPath(skuPath))
106
- }
107
- }
108
- else {
109
- // select siblings paths
110
- if (allVariants) {
111
- paths[level + 1] = [...requestedNode!.subNodes!.map((node) => (node.skuToken))]
112
- }
113
- // Actually select the the first fam at the fam level,
114
- else {
115
- paths[level + 1] = [requestedNode!.subNodes![0].skuToken]
116
- }
117
- }
118
-
119
- const selectedFams = cmmc.selectPaths(paths)
120
- initialFamily = initialFamily ? initialFamily : (requestedFamily ? requestedFamily : selectedFams[0])
121
- cmmc.setCurrentItem(initialFamily.products[0].sku)
122
- const currentFamTokenMutator = new ObsStringMutator(pathUtils.lastToken(initialFamily!.id))
123
-
124
- inst.current = {
125
- level,
126
- requestedFamily,
127
- requestedNode,
128
- currentFamTokenMutator,
129
- disposers: []
130
- }
131
-
132
- if (!allVariants) {
133
- inst.current?.disposers.push(reaction(
134
- () => {
135
- const fams = cmmc.selectedFamilies
136
- return (fams.length > 0) ? fams[0].id : undefined
137
- },
138
- (famId) => {
139
- if (famId && famId !== cmmc.currentItem?.familyId) {
140
- const fam = cmmc.getFamilyById(famId)
141
- if (fam) {
142
- cmmc.setCurrentItem(fam.products[0].sku)
143
- }
144
- }
145
- }
146
- ))
147
- }
148
-
149
- return () => {
150
- inst.current?.disposers.forEach((d) => {d()})
151
- }
152
-
153
- }, [])
154
-
155
- const setFamilyPath = (pathValue: string | null) => {
156
- if (inst.current?.currentFamTokenMutator.get() !== pathValue) {
157
- inst.current?.currentFamTokenMutator.set(pathValue)
158
- }
159
- const found = cmmc.selectedItems.find((item) => (item.familyId.endsWith(pathValue!)))
160
- if (found) {
161
- cmmc.setCurrentItem(found.sku)
162
- }
163
- }
164
-
165
- const selectSku = (sku: string) => {
166
- cmmc.setCurrentItem(sku)
167
- const pathValue = pathUtils.lastToken(cmmc.currentItem!.familyId)
168
- if (pathValue !== inst.current?.currentFamTokenMutator.get()) {
169
- inst.current?.currentFamTokenMutator.set(pathValue)
170
- }
171
- }
172
-
173
- const famTitle = inst.current?.requestedFamily ? inst.current.requestedFamily.title : cmmc.selectedFamilies[0].title
174
-
175
- const itemsToShow = (!cmmc.hasSelection) ? undefined :
176
- allVariants ? cmmc.selectedItems : cmmc.selectedFamilies[0].products as LineItem[]
177
-
178
-
179
- const TitleArea: React.FC<{
180
- title: string
181
- byline?: string
182
- clx?: string
183
- }> = ({
184
- title,
185
- byline,
186
- clx=''
187
- }) => (
188
- <ApplyTypography className={clx}>
189
- <h3>{title}</h3>
190
- {byline && (<h6>{byline}</h6>)}
191
- </ApplyTypography>
192
- )
193
-
194
- const scroll = !!(itemsToShow && itemsToShow.length > scrollAfter)
195
- return (
196
- <div className={cn(
197
- 'px-4 md:px-6 pt-3 pb-4 flex flex-col items-center min-h-[60vh]',
198
- clx,
199
- scroll ? scrollHeightClx : 'h-auto'
200
- )} >
201
- {inst.current?.requestedNode && (<>
202
- <ApplyTypography className={'mb-2 ' + (scroll ? 'shrink-0' : '')}>
203
- <h3>{inst.current!.requestedNode.label}</h3>
204
- {inst.current!.requestedNode.subNodesLabel && (
205
- <h6 className='!text-center font-bold text-muted mt-3'>{inst.current!.requestedNode.subNodesLabel}</h6>
206
- )}
207
- </ApplyTypography>
208
- <NodeTabs
209
- className={cn(
210
- 'grid gap-0 align-stretch justify-normal ' + `grid-cols-${inst.current.requestedNode.subNodes!.length}`,
211
- 'border-b-2 rounded-lg border-level-3 mb-4 -mr-2 -ml-2 max-w-[460px] h-10', // height is needed for iPhone bug
212
- (scroll ? 'shrink-0' : ''),
213
- famWidgetClx
214
- )}
215
- mobile={mobile}
216
- mutator={allVariants ?
217
- {
218
- get: () => (inst.current!.currentFamTokenMutator.get()),
219
- set: setFamilyPath
220
- }
221
- :
222
- getFacetValuesMutator(inst.current.level + 1, cmmc)
223
- }
224
- itemClx='flex-col h-auto gap-0 py-1 px-3'
225
- buttonClx={
226
- 'h-full ' +
227
- '!border-level-3'
228
- }
229
- levelNodes={inst.current.requestedNode.subNodes!}
230
- show={familyTabAs}
231
- />
232
- </>)}
233
- {!inst.current?.requestedNode && famTitle && (
234
- <TitleArea title={famTitle} clx=''/>
235
- )}
236
- {(cmmc.currentItem && showItemMedia) && (
237
- <MediaStack media={cmmc.currentItem} constrainTo={{w: 200, h: 200}} clx={(scroll ? 'shrink-0' : '')}/>
238
- )}
239
- {itemsToShow && (
240
- <Selector
241
- items={itemsToShow}
242
- selectedItemRef={cmmc}
243
- selectSku={selectSku}
244
- {...selectorProps}
245
- scrollable={scroll}
246
- />
247
- )}
248
- {(cmmc.currentItem) && (
249
- <AddToCartWidget
250
- item={cmmc.currentItem}
251
- onQuantityChanged={onQuantityChanged}
252
- className={cn('min-w-[160px] mx-auto mt-4', (scroll ? 'shrink-0' : ''), addWidgetClx)}
253
- />
254
- )}
255
- </div >
256
- )
257
- })
258
-
259
- export default BuyCard
1
+ 'use client'
2
+ import React, { useRef, useEffect, type ComponentType } from 'react'
3
+ import { reaction, type IReactionDisposer } from 'mobx'
4
+ import { observer } from 'mobx-react-lite'
5
+
6
+ import { cn } from '@hanzo/ui/util'
7
+ import { ApplyTypography, MediaStack } from '@hanzo/ui/primitives'
8
+
9
+ import type {
10
+ ItemSelectorProps,
11
+ ItemSelectorCompProps,
12
+ LineItem,
13
+ Family,
14
+ CategoryNode,
15
+ } from '../../types'
16
+
17
+ import { useCommerce } from '../../service/context'
18
+ import * as pathUtils from '../../service/path-utils'
19
+ import { getFacetValuesMutator, ObsStringMutator } from '../../util'
20
+
21
+ import NodeTabs from '../node-tabs'
22
+ import AddToCartWidget from '../add-to-cart-widget'
23
+
24
+ const BuyCard: React.FC<{
25
+ skuPath: string
26
+
27
+ /** For any selectors that show a list of choices,
28
+ * starting with 'scrollAfter' elements,
29
+ * the list will scroll, and the card will
30
+ * have 'scrollHeightClx' applied to it to define and fix the height.
31
+ * This is most like something like '80vh'
32
+ * defaults are '5' and 'h-[70vh]'
33
+ * */
34
+ scrollAfter?: number
35
+ scrollHeightClx?: string
36
+
37
+ clx?: string
38
+ famWidgetClx?: string
39
+ addWidgetClx?: string
40
+
41
+ selector: ComponentType<ItemSelectorProps>
42
+ selectorProps?: ItemSelectorCompProps
43
+
44
+ /** Show all items from all sibling families
45
+ * If skuPath defines a Family, the first of it's items will
46
+ * be selected. The facet widget will just select a the first
47
+ * item in the chosen Family without changings the overall set
48
+ * of choices. */
49
+ allVariants?: boolean
50
+
51
+ familyTabAs?: 'image' | 'label' | 'image-and-label'
52
+ showItemMedia?: boolean
53
+
54
+ onQuantityChanged?: (sku: string, oldV: number, newV: number) => void
55
+ mobile?: boolean
56
+ }> = observer(({
57
+ skuPath,
58
+ scrollAfter=5,
59
+ scrollHeightClx='h-[80vh]',
60
+ clx='',
61
+ famWidgetClx='',
62
+ addWidgetClx='',
63
+ selector: Selector,
64
+ selectorProps={
65
+ clx: '',
66
+ soleItemClx: '',
67
+ itemClx: '',
68
+ ext: {}
69
+ },
70
+ familyTabAs='image-and-label',
71
+ showItemMedia=true,
72
+ allVariants=false,
73
+ mobile=false,
74
+ onQuantityChanged,
75
+ }) => {
76
+
77
+ const cmmc = useCommerce()
78
+ const inst = useRef<{
79
+ level: number,
80
+ requestedFamily : Family | undefined
81
+ requestedNode: CategoryNode | undefined
82
+ currentFamTokenMutator: ObsStringMutator
83
+ disposers: IReactionDisposer[]
84
+ } | undefined>(undefined)
85
+
86
+
87
+ useEffect(() => {
88
+
89
+ let requestedFamily = cmmc.getFamilyById(skuPath)
90
+ let requestedNode = requestedFamily ? undefined : cmmc.getNodeAtPath(skuPath)
91
+ let initialFamily = undefined
92
+
93
+ const { paths, level } = pathUtils.getSelectedPaths(skuPath)
94
+
95
+ if (level === 0) {
96
+ throw new Error('BuyCard.useEffect(): must specify at least at least one Level in skuPath!')
97
+ }
98
+ if (requestedFamily) {
99
+ if (allVariants && level >= 2) {
100
+ // select all siblings of requestedFamily.
101
+ // ie, go one level back
102
+ delete paths[level]
103
+ initialFamily = requestedFamily
104
+ requestedFamily = undefined
105
+ requestedNode = cmmc.getNodeAtPath(pathUtils.getParentPath(skuPath))
106
+ }
107
+ }
108
+ else {
109
+ // select siblings paths
110
+ if (allVariants) {
111
+ paths[level + 1] = [...requestedNode!.subNodes!.map((node) => (node.skuToken))]
112
+ }
113
+ // Actually select the the first fam at the fam level,
114
+ else {
115
+ paths[level + 1] = [requestedNode!.subNodes![0].skuToken]
116
+ }
117
+ }
118
+
119
+ const selectedFams = cmmc.selectPaths(paths)
120
+ initialFamily = initialFamily ? initialFamily : (requestedFamily ? requestedFamily : selectedFams[0])
121
+ cmmc.setCurrentItem(initialFamily.products[0].sku)
122
+ const currentFamTokenMutator = new ObsStringMutator(pathUtils.lastToken(initialFamily!.id))
123
+
124
+ inst.current = {
125
+ level,
126
+ requestedFamily,
127
+ requestedNode,
128
+ currentFamTokenMutator,
129
+ disposers: []
130
+ }
131
+
132
+ if (!allVariants) {
133
+ inst.current?.disposers.push(reaction(
134
+ () => {
135
+ const fams = cmmc.selectedFamilies
136
+ return (fams.length > 0) ? fams[0].id : undefined
137
+ },
138
+ (famId) => {
139
+ if (famId && famId !== cmmc.currentItem?.familyId) {
140
+ const fam = cmmc.getFamilyById(famId)
141
+ if (fam) {
142
+ cmmc.setCurrentItem(fam.products[0].sku)
143
+ }
144
+ }
145
+ }
146
+ ))
147
+ }
148
+
149
+ return () => {
150
+ inst.current?.disposers.forEach((d) => {d()})
151
+ }
152
+
153
+ }, [])
154
+
155
+ const setFamilyPath = (pathValue: string | null) => {
156
+ if (inst.current?.currentFamTokenMutator.get() !== pathValue) {
157
+ inst.current?.currentFamTokenMutator.set(pathValue)
158
+ }
159
+ const found = cmmc.selectedItems.find((item) => (item.familyId.endsWith(pathValue!)))
160
+ if (found) {
161
+ cmmc.setCurrentItem(found.sku)
162
+ }
163
+ }
164
+
165
+ const selectSku = (sku: string) => {
166
+ cmmc.setCurrentItem(sku)
167
+ const pathValue = pathUtils.lastToken(cmmc.currentItem!.familyId)
168
+ if (pathValue !== inst.current?.currentFamTokenMutator.get()) {
169
+ inst.current?.currentFamTokenMutator.set(pathValue)
170
+ }
171
+ }
172
+
173
+ const famTitle = inst.current?.requestedFamily ? inst.current.requestedFamily.title : cmmc.selectedFamilies[0].title
174
+
175
+ const itemsToShow = (!cmmc.hasSelection) ? undefined :
176
+ allVariants ? cmmc.selectedItems : cmmc.selectedFamilies[0].products as LineItem[]
177
+
178
+
179
+ const TitleArea: React.FC<{
180
+ title: string
181
+ byline?: string
182
+ clx?: string
183
+ }> = ({
184
+ title,
185
+ byline,
186
+ clx=''
187
+ }) => (
188
+ <ApplyTypography className={clx}>
189
+ <h3>{title}</h3>
190
+ {byline && (<h6>{byline}</h6>)}
191
+ </ApplyTypography>
192
+ )
193
+
194
+ const scroll = !!(itemsToShow && itemsToShow.length > scrollAfter)
195
+ return (
196
+ <div className={cn(
197
+ 'px-4 md:px-6 pt-3 pb-4 flex flex-col items-center min-h-[60vh]',
198
+ clx,
199
+ scroll ? scrollHeightClx : 'h-auto'
200
+ )} >
201
+ {inst.current?.requestedNode && (<>
202
+ <ApplyTypography className={'mb-2 ' + (scroll ? 'shrink-0' : '')}>
203
+ <h3>{inst.current!.requestedNode.label}</h3>
204
+ {inst.current!.requestedNode.subNodesLabel && (
205
+ <h6 className='!text-center font-bold text-muted mt-3'>{inst.current!.requestedNode.subNodesLabel}</h6>
206
+ )}
207
+ </ApplyTypography>
208
+ <NodeTabs
209
+ className={cn(
210
+ 'grid gap-0 align-stretch justify-normal ' + `grid-cols-${inst.current.requestedNode.subNodes!.length}`,
211
+ 'border-b-2 rounded-lg border-level-3 mb-4 -mr-2 -ml-2 max-w-[460px] h-10', // height is needed for iPhone bug
212
+ (scroll ? 'shrink-0' : ''),
213
+ famWidgetClx
214
+ )}
215
+ mobile={mobile}
216
+ mutator={allVariants ?
217
+ {
218
+ get: () => (inst.current!.currentFamTokenMutator.get()),
219
+ set: setFamilyPath
220
+ }
221
+ :
222
+ getFacetValuesMutator(inst.current.level + 1, cmmc)
223
+ }
224
+ itemClx='flex-col h-auto gap-0 py-1 px-3'
225
+ buttonClx={
226
+ 'h-full ' +
227
+ '!border-level-3'
228
+ }
229
+ levelNodes={inst.current.requestedNode.subNodes!}
230
+ show={familyTabAs}
231
+ />
232
+ </>)}
233
+ {!inst.current?.requestedNode && famTitle && (
234
+ <TitleArea title={famTitle} clx=''/>
235
+ )}
236
+ {(cmmc.currentItem && showItemMedia) && (
237
+ <MediaStack media={cmmc.currentItem} constrainTo={{w: 200, h: 200}} clx={(scroll ? 'shrink-0' : '')}/>
238
+ )}
239
+ {itemsToShow && (
240
+ <Selector
241
+ items={itemsToShow}
242
+ selectedItemRef={cmmc}
243
+ selectSku={selectSku}
244
+ {...selectorProps}
245
+ scrollable={scroll}
246
+ />
247
+ )}
248
+ {(cmmc.currentItem) && (
249
+ <AddToCartWidget
250
+ item={cmmc.currentItem}
251
+ onQuantityChanged={onQuantityChanged}
252
+ className={cn('min-w-[160px] mx-auto mt-4', (scroll ? 'shrink-0' : ''), addWidgetClx)}
253
+ />
254
+ )}
255
+ </div >
256
+ )
257
+ })
258
+
259
+ export default BuyCard