@hanzo/commerce 6.2.4 → 6.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/buy/_to_deprecate_select-family-item-card.tsx +0 -1
- package/components/buy/_to_deprecate_select-family-item-panel.tsx +1 -1
- package/components/buy/add-to-cart-widget.tsx +9 -7
- package/components/buy/buy-card.tsx +3 -4
- package/components/buy/carousel-buy-card.tsx +120 -85
- package/components/buy/multi-family/all-variants-carousel.tsx +257 -0
- package/components/{select-family → buy/multi-family}/family-carousel/index.tsx +7 -17
- package/components/{select-family → buy/multi-family}/family-carousel/slide.tsx +3 -3
- package/components/{select-family → buy/multi-family}/family-carousel/state.ts +6 -2
- package/components/buy/multi-family/index.ts +2 -0
- package/components/buy/{foo.txt → please-keep.txt} +1 -1
- package/components/buy/single-family-selector.tsx +90 -0
- package/components/buy/title-and-byline.tsx +25 -0
- package/components/cart/cart-panel/cart-line-item.tsx +1 -1
- package/components/index.ts +1 -2
- package/components/item-selector/button.tsx +28 -18
- package/components/item-selector/carousel/index.tsx +197 -0
- package/components/item-selector/carousel/slider.tsx +40 -0
- package/components/{select-family/level-nodes-widget → node-tabs}/index.tsx +3 -3
- package/components/{select-family/level-nodes-widget → node-tabs}/node-image.tsx +1 -1
- package/package.json +3 -3
- package/service/impls/standalone/actual-line-item.ts +3 -1
- package/service/impls/standalone/standalone-service.ts +41 -4
- package/types/category-node.ts +21 -9
- package/types/commerce-service.ts +12 -13
- package/types/family.ts +7 -1
- package/types/index.ts +4 -3
- package/types/item-selector.ts +46 -9
- package/types/multi-family-selector-props.ts +20 -0
- package/types/selection-ui-specifier.ts +37 -21
- package/util/index.ts +3 -0
- package/util/item-selector-options-accessor.ts +32 -0
- package/util/multi-family-selector-options-accessor.ts +15 -0
- package/util/promo-codes.ts +71 -9
- package/util/selection-ui-specifiers.ts +1 -5
- package/components/item-selector/carousel.tsx +0 -162
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { useCallback, useEffect, useRef } from 'react'
|
|
3
|
-
import { reaction } from 'mobx'
|
|
4
|
-
import { observer } from 'mobx-react-lite'
|
|
5
|
-
|
|
6
|
-
import { cn } from '@hanzo/ui/util'
|
|
7
|
-
import type { Dimensions } from '@hanzo/ui/types'
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
type CarouselOptions,
|
|
11
|
-
type CarouselApi,
|
|
12
|
-
Carousel,
|
|
13
|
-
CarouselContent,
|
|
14
|
-
CarouselItem,
|
|
15
|
-
CarouselPrevious,
|
|
16
|
-
CarouselNext,
|
|
17
|
-
ApplyTypography,
|
|
18
|
-
MediaStack
|
|
19
|
-
} from '@hanzo/ui/primitives'
|
|
20
|
-
|
|
21
|
-
import type { ItemSelectorProps, LineItem } from '../../types'
|
|
22
|
-
import { formatCurrencyValue } from '../../util'
|
|
23
|
-
|
|
24
|
-
import QuantityIndicator from '../quantity-indicator'
|
|
25
|
-
|
|
26
|
-
const DEFAULT_CONSTRAINT = {w: 250, h: 250}
|
|
27
|
-
|
|
28
|
-
interface CarouselItemSelectorPropsExt {
|
|
29
|
-
constrainTo: Dimensions
|
|
30
|
-
options?: CarouselOptions
|
|
31
|
-
/** Do not show Family and / or Item title and Price */
|
|
32
|
-
imageOnly?: boolean
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const ItemSlide: React.FC<{
|
|
36
|
-
item: LineItem,
|
|
37
|
-
constrainTo: Dimensions
|
|
38
|
-
imageOnly: boolean
|
|
39
|
-
showFamily: boolean
|
|
40
|
-
showPrice: boolean
|
|
41
|
-
showQuantity: boolean
|
|
42
|
-
clx?: string
|
|
43
|
-
}> = ({
|
|
44
|
-
item,
|
|
45
|
-
constrainTo,
|
|
46
|
-
showFamily,
|
|
47
|
-
imageOnly,
|
|
48
|
-
showPrice,
|
|
49
|
-
showQuantity,
|
|
50
|
-
clx=''
|
|
51
|
-
}) => {
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<CarouselItem className={cn('p-2 flex flex-col justify-center items-center', clx)}>
|
|
55
|
-
{!imageOnly && (
|
|
56
|
-
<ApplyTypography className='flex flex-col items-center !gap-2 [&>*]:!m-0'>
|
|
57
|
-
{showFamily && (<h4>{item.familyTitle}</h4>)}
|
|
58
|
-
<h6>{item.optionLabel}</h6>
|
|
59
|
-
{item.byline && (<p>{item.byline}</p>)}
|
|
60
|
-
</ApplyTypography>
|
|
61
|
-
)}
|
|
62
|
-
<MediaStack media={item} constrainTo={constrainTo} clx='my-4' />
|
|
63
|
-
{!imageOnly && (showPrice || showQuantity) && (
|
|
64
|
-
<ApplyTypography className='flex flex-row items-center !gap-2 [&>*]:!m-0'>
|
|
65
|
-
{showPrice && (<p>{formatCurrencyValue(item.price)}</p>)}
|
|
66
|
-
{showQuantity && (
|
|
67
|
-
<QuantityIndicator
|
|
68
|
-
item={item}
|
|
69
|
-
clx='h-[26px] ml-1'
|
|
70
|
-
iconClx='fill-foreground'
|
|
71
|
-
digitClx='not-typography font-semibold text-primary-fg leading-none font-sans text-xs'
|
|
72
|
-
/>
|
|
73
|
-
)}
|
|
74
|
-
</ApplyTypography>
|
|
75
|
-
)}
|
|
76
|
-
</CarouselItem>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const CarouselItemSelector: React.FC<ItemSelectorProps> = observer(({
|
|
81
|
-
items,
|
|
82
|
-
selectSku,
|
|
83
|
-
selectedItemRef: itemRef,
|
|
84
|
-
scrollable, // ignored
|
|
85
|
-
clx='',
|
|
86
|
-
itemClx='',
|
|
87
|
-
options={},
|
|
88
|
-
ext={
|
|
89
|
-
options: {loop: true},
|
|
90
|
-
constrainTo: DEFAULT_CONSTRAINT,
|
|
91
|
-
imageOnly: false
|
|
92
|
-
} satisfies CarouselItemSelectorPropsExt
|
|
93
|
-
}) => {
|
|
94
|
-
|
|
95
|
-
const showFamily = 'showFamily' in options ? options.showFamily! : false
|
|
96
|
-
const showPrice = 'showPrice' in options ? options.showPrice! : true
|
|
97
|
-
const showQuantity = 'showQuantity' in options ? options.showQuantity! : false
|
|
98
|
-
|
|
99
|
-
const carouselOptions = 'options' in ext ? ext.options : undefined
|
|
100
|
-
const constrainTo = 'constrainTo' in ext ? ext.constrainTo : DEFAULT_CONSTRAINT
|
|
101
|
-
const imageOnly = 'imageOnly' in ext ? ext.imageOnly : false
|
|
102
|
-
|
|
103
|
-
const elbaApiRef = useRef<CarouselApi | undefined>(undefined)
|
|
104
|
-
const dontRespondRef = useRef<boolean>(false)
|
|
105
|
-
|
|
106
|
-
const setApi = (api: CarouselApi) => {elbaApiRef.current = api}
|
|
107
|
-
|
|
108
|
-
const onSelect = useCallback((emblaApi: CarouselApi) => {
|
|
109
|
-
if (dontRespondRef.current) {
|
|
110
|
-
dontRespondRef.current = false
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
const index = emblaApi.selectedScrollSnap()
|
|
114
|
-
if (index !== -1) {
|
|
115
|
-
selectSku(items[index].sku)
|
|
116
|
-
}
|
|
117
|
-
dontRespondRef.current = false
|
|
118
|
-
}, [])
|
|
119
|
-
|
|
120
|
-
useEffect(() => {
|
|
121
|
-
return reaction(
|
|
122
|
-
() => ({item: itemRef.item}),
|
|
123
|
-
({item}) => {
|
|
124
|
-
if (elbaApiRef.current) {
|
|
125
|
-
const index = items.findIndex((el) => (el.sku === item?.sku))
|
|
126
|
-
if (index !== -1) {
|
|
127
|
-
dontRespondRef.current = true
|
|
128
|
-
elbaApiRef.current.scrollTo(index)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
)
|
|
133
|
-
}, [])
|
|
134
|
-
|
|
135
|
-
return (
|
|
136
|
-
<Carousel options={carouselOptions} className={cn('w-full px-2', clx)} onCarouselSelect={onSelect} setApi={setApi}>
|
|
137
|
-
<CarouselContent>
|
|
138
|
-
{items.map((item) => (
|
|
139
|
-
<ItemSlide
|
|
140
|
-
key={item.sku}
|
|
141
|
-
item={item}
|
|
142
|
-
{...{
|
|
143
|
-
showFamily,
|
|
144
|
-
showPrice,
|
|
145
|
-
showQuantity,
|
|
146
|
-
constrainTo,
|
|
147
|
-
imageOnly
|
|
148
|
-
}}
|
|
149
|
-
clx={itemClx}
|
|
150
|
-
/>
|
|
151
|
-
))}
|
|
152
|
-
</CarouselContent>
|
|
153
|
-
<CarouselPrevious className='left-1'/>
|
|
154
|
-
<CarouselNext className='right-1'/>
|
|
155
|
-
</Carousel>
|
|
156
|
-
)
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
export {
|
|
160
|
-
type CarouselItemSelectorPropsExt,
|
|
161
|
-
CarouselItemSelector as default
|
|
162
|
-
}
|