@hanzo/commerce 5.1.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/components/{buy-item/select-category-item-card.tsx → buy/_to_deprecate_select-category-item-card.tsx} +20 -31
  2. package/components/{select-category-item-panel.tsx → buy/_to_deprecate_select-category-item-panel.tsx} +12 -20
  3. package/components/{buy-item/buy-item-popup.tsx → buy/_unused_buy-popup.tsx_} +4 -4
  4. package/components/{add-to-cart-widget.tsx → buy/add-to-cart-widget.tsx} +5 -3
  5. package/components/buy/buy-button.tsx +31 -0
  6. package/components/buy/buy-card.tsx +169 -0
  7. package/components/buy/buy-drawer.tsx +78 -0
  8. package/components/buy/buy-trigger-wrapper.tsx +20 -0
  9. package/components/{cart-accordian.tsx → cart/cart-accordian.tsx} +2 -1
  10. package/components/{cart-panel → cart/cart-panel}/cart-line-item.tsx +28 -5
  11. package/components/{cart-panel → cart/cart-panel}/index.tsx +9 -5
  12. package/components/{cart-panel → cart/cart-panel}/promo-code.tsx +3 -3
  13. package/components/{payment-step-form → checkout/payment-step-form}/contact-form.tsx +1 -1
  14. package/components/{payment-step-form → checkout/payment-step-form}/index.tsx +3 -3
  15. package/components/{payment-step-form → checkout/payment-step-form}/methods/bank-transfer.tsx +1 -1
  16. package/components/{payment-step-form → checkout/payment-step-form}/methods/card.tsx +4 -4
  17. package/components/{payment-step-form → checkout/payment-step-form}/methods/crypto.tsx +3 -3
  18. package/components/{payment-step-form → checkout/payment-step-form}/methods/index.ts +1 -1
  19. package/components/{shipping-step-form.tsx → checkout/shipping-step-form.tsx} +4 -4
  20. package/components/facet-values-widget/facet-image.tsx +2 -2
  21. package/components/facet-values-widget/index.tsx +13 -12
  22. package/components/index.ts +19 -17
  23. package/components/item/item-media.tsx +58 -0
  24. package/components/{product-card.tsx → item/product-card.tsx} +5 -7
  25. package/components/select/carousel-selector.tsx +64 -0
  26. package/components/select/image-selector.tsx +125 -0
  27. package/components/select/radio-selector.tsx +66 -0
  28. package/package.json +2 -1
  29. package/service/context.tsx +4 -4
  30. package/service/impls/standalone/index.ts +4 -4
  31. package/service/impls/standalone/standalone-service.ts +74 -62
  32. package/types/commerce-service.ts +20 -16
  33. package/types/index.ts +2 -2
  34. package/types/item-selector.ts +12 -5
  35. package/types/product.ts +1 -0
  36. package/types/tree-node.ts +24 -0
  37. package/util/index.ts +9 -9
  38. package/util/use-sync-sku-param-w-current-item.ts +5 -5
  39. package/components/buy-item/buy-item-button-wrapper.tsx +0 -27
  40. package/components/buy-item/buy-item-button.tsx +0 -34
  41. package/components/buy-item/buy-item-card.tsx +0 -92
  42. package/components/buy-item/buy-item-mobile-drawer.tsx +0 -54
  43. package/components/buy-item/select-category-and-item-widget.tsx +0 -83
  44. package/components/category-item-radio-selector.tsx +0 -55
  45. package/components/category-item-scroll-selector.tsx +0 -40
  46. package/components/item-carousel.tsx +0 -80
  47. package/types/facet.ts +0 -35
  48. /package/components/{cart-icon.tsx → cart/cart-icon.tsx} +0 -0
  49. /package/components/{payment-step-form → checkout/payment-step-form}/card-icon-row.tsx +0 -0
  50. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/amex.tsx +0 -0
  51. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/diners-club.tsx +0 -0
  52. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/discover.tsx +0 -0
  53. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/jcb.tsx +0 -0
  54. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/mastercard.tsx +0 -0
  55. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/visa.tsx +0 -0
  56. /package/components/{payment-step-form → checkout/payment-step-form}/cc-button.tsx +0 -0
  57. /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/btc.tsx +0 -0
  58. /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/eth.tsx +0 -0
  59. /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/usdt.tsx +0 -0
@@ -19,9 +19,9 @@ import {
19
19
  } from '@hanzo/ui/primitives'
20
20
 
21
21
  import Eth from '../crypto-icons/eth'
22
- import { useCommerce } from '../../../service/context'
23
- import type { PaymentMethodComponentProps } from '../../../types'
24
- import { sendFBEvent, sendGAEvent } from '../../../util/analytics'
22
+ import { useCommerce } from '../../../../service/context'
23
+ import type { PaymentMethodComponentProps } from '../../../../types'
24
+ import { sendFBEvent, sendGAEvent } from '../../../../util/analytics'
25
25
 
26
26
  import ContactForm from '../contact-form'
27
27
 
@@ -1,4 +1,4 @@
1
- import type { PaymentMethodDesc } from '../../../types'
1
+ import type { PaymentMethodDesc } from '../../../../types'
2
2
 
3
3
  import Card from './card'
4
4
  import Crypto from './crypto'
@@ -19,12 +19,12 @@ import {
19
19
  SelectValue
20
20
  } from '@hanzo/ui/primitives'
21
21
 
22
- import { useCommerce } from '../service/context'
22
+ import { useCommerce } from '../../service/context'
23
23
 
24
- import countries from '../util/countries'
25
- import { sendGAEvent } from '../util/analytics'
24
+ import countries from '../../util/countries'
25
+ import { sendGAEvent } from '../../util/analytics'
26
26
 
27
- import type { CheckoutStepComponentProps } from '../types'
27
+ import type { CheckoutStepComponentProps } from '../../types'
28
28
 
29
29
  const shippingFormSchema = z.object({
30
30
  addressLine1: z.string().min(2, 'Address must be at least 2 characters.'),
@@ -1,12 +1,12 @@
1
1
  import React from 'react'
2
2
  import Image from 'next/image'
3
3
 
4
- import type { FacetValueDesc } from '../../types'
4
+ import type { ProductTreeNode } from '../../types'
5
5
 
6
6
  const ICON_SIZE = 20
7
7
 
8
8
  const FacetImage: React.FC<{
9
- facetValueDesc: FacetValueDesc
9
+ facetValueDesc: ProductTreeNode
10
10
  }> = ({
11
11
  facetValueDesc
12
12
  }) => {
@@ -4,18 +4,19 @@ import React, { useState } from 'react'
4
4
  import { ToggleGroup, ToggleGroupItem} from "@hanzo/ui/primitives"
5
5
  import { cn } from '@hanzo/ui/util'
6
6
 
7
- import type { FacetValueDesc, StringMutator, StringArrayMutator } from '../../types'
7
+ import type { ProductTreeNode, StringMutator, StringArrayMutator } from '../../types'
8
8
  import FacetImage from './facet-image'
9
9
 
10
10
  const FacetValuesWidget: React.FC<{
11
- facetValues: FacetValueDesc[]
11
+ facetValues: ProductTreeNode[]
12
12
  mutator: StringMutator | StringArrayMutator
13
13
  multiple?: boolean
14
14
  className?: string
15
15
  buttonClx?: string
16
16
  itemClx?: string
17
- isMobile?: boolean
17
+ mobile?: boolean
18
18
  tabSize?: string
19
+ show?: 'image' | 'label' | 'image-and-label'
19
20
  }> = ({
20
21
  facetValues,
21
22
  mutator,
@@ -23,8 +24,9 @@ const FacetValuesWidget: React.FC<{
23
24
  buttonClx='',
24
25
  itemClx='',
25
26
  className='',
26
- isMobile=false,
27
- tabSize
27
+ mobile=false,
28
+ tabSize,
29
+ show='image-and-label'
28
30
  }) => {
29
31
 
30
32
  const [last, setLast] = useState<string | undefined>(undefined)
@@ -54,7 +56,7 @@ const FacetValuesWidget: React.FC<{
54
56
  type={multiple ? 'multiple' : 'single'}
55
57
  value={val}
56
58
  variant='default'
57
- size={tabSize ? tabSize : (isMobile ? 'sm' : 'default')}
59
+ size={tabSize ? tabSize : (mobile ? 'sm' : 'default')}
58
60
  onValueChange={multiple ? handleChangeMultiple : handleChangeSingle}
59
61
  className={className}
60
62
  {...roundedToSpread}
@@ -68,16 +70,16 @@ const FacetValuesWidget: React.FC<{
68
70
  }
69
71
  return (
70
72
  <ToggleGroupItem
71
- key={fv.value}
72
- value={fv.value}
73
- disabled={(last && last === fv.value || fv.value === mutator.get())}
73
+ key={fv.skuToken}
74
+ value={fv.skuToken}
75
+ disabled={(last && last === fv.skuToken || fv.skuToken === mutator.get())}
74
76
  aria-label={`Select ${fv.label}`}
75
77
  {...roundedToSpread}
76
78
  className={buttonClx}
77
79
  >
78
80
  <span className={cn('flex flex-row justify-center gap-1 h-6 items-center', itemClx)} >
79
- <FacetImage facetValueDesc={fv} />
80
- {(!isMobile || !fv.img) && (<span className='whitespace-nowrap'>{fv.label}</span>)}
81
+ {!(show === 'label') && (<FacetImage facetValueDesc={fv} />) }
82
+ {(!(show === 'image') || !fv.img) && (<span className='whitespace-nowrap'>{fv.label}</span>)}
81
83
  </span>
82
84
  </ToggleGroupItem>
83
85
  )
@@ -85,6 +87,5 @@ const FacetValuesWidget: React.FC<{
85
87
  </ToggleGroup>
86
88
  )
87
89
  }
88
- // hidden md:block
89
90
 
90
91
  export default FacetValuesWidget
@@ -1,18 +1,20 @@
1
- export { default as AddToCartWidget } from './add-to-cart-widget'
2
- export { default as BuyItemButtonWrapper } from './buy-item/buy-item-button-wrapper'
3
- export { default as BuyItemButton } from './buy-item/buy-item-button'
4
- export { default as BuyItemCard } from './buy-item/buy-item-card'
5
- export { default as BuyItemPopup } from './buy-item/buy-item-popup'
6
- export { default as CartAccordian } from './cart-accordian'
7
- export { default as CartPanel } from './cart-panel'
8
- export { default as CategoryItemIOSWheelSelector } from './category-item-scroll-selector'
9
- export { default as CategoryItemRadioSelector } from './category-item-radio-selector'
1
+ export { default as AddToCartWidget } from './buy/add-to-cart-widget'
2
+ export { default as BuyTriggerWrapper } from './buy/buy-trigger-wrapper'
3
+ export { default as BuyButton } from './buy/buy-button'
4
+ export { default as BuyCard } from './buy/buy-card'
5
+ export { default as BuyDrawer } from './buy/buy-drawer'
6
+
7
+ export { default as CartAccordian } from './cart/cart-accordian'
8
+ export { default as CartPanel } from './cart/cart-panel'
9
+
10
10
  export { default as FacetValuesWidget } from './facet-values-widget'
11
- export { default as ItemCarousel } from './item-carousel'
12
- export { default as PaymentStepForm } from './payment-step-form'
13
- export { default as ProductCard } from './product-card'
14
- export { default as SelectCategoryAndItemWidget } from './buy-item/select-category-and-item-widget'
15
- export { default as SelectCategoryItemCard } from './buy-item/select-category-item-card'
16
- export { default as SelectCategoryItemPanel } from './select-category-item-panel'
17
- export { default as ShippingStepForm } from './shipping-step-form'
18
- export { Icons } from './Icons'
11
+
12
+ export { default as PaymentStepForm } from './checkout/payment-step-form'
13
+ export { default as ShippingStepForm } from './checkout/shipping-step-form'
14
+
15
+ export { default as ProductCard } from './item/product-card'
16
+ export { Icons } from './Icons'
17
+
18
+ export { default as ImageItemSelector } from './select/image-selector'
19
+ export { default as RadioItemSelector } from './select/radio-selector'
20
+ export { default as CarouselItemSelector, type CarouselItemSelectorPropsExt } from './select/carousel-selector'
@@ -0,0 +1,58 @@
1
+ import React from 'react'
2
+
3
+ import Spline from '@splinetool/react-spline'
4
+
5
+ import type { Dimensions } from '@hanzo/ui/types'
6
+ import { cn } from '@hanzo/ui/util'
7
+
8
+ import {
9
+ VideoBlockComponent,
10
+ ImageBlockComponent,
11
+ type ImageBlock,
12
+ type Block,
13
+ type VideoBlock
14
+ } from '@hanzo/ui/blocks'
15
+ import type { LineItem } from '../../types'
16
+
17
+ const ItemMedia: React.FC<{
18
+ item: LineItem
19
+ constrainTo?: Dimensions
20
+ clx?: string
21
+ }> = ({
22
+ item,
23
+ constrainTo: cnst = {w: 250, h: 250},
24
+ clx=''
25
+ }) => {
26
+
27
+ const {title, img, video, animation} = item
28
+ // Order of precedence: 3D > MP4 > Image
29
+ return animation ? (
30
+ <Spline
31
+ scene={animation}
32
+ className={cn(clx, 'pointer-events-none')}
33
+ style={{
34
+ // // !aspect-[12/10]
35
+ width: (6/5 * (typeof cnst.h === 'number' ? cnst.h as number : parseInt(cnst.h as string)) ),
36
+ height: cnst.h
37
+ }}
38
+ />
39
+ ) : video ? (
40
+ <VideoBlockComponent
41
+ constraint={cnst}
42
+ block={{blockType: 'video', ...video} satisfies VideoBlock as Block}
43
+ className={clx}
44
+ />
45
+ ) : (
46
+ <ImageBlockComponent
47
+ block={{
48
+ blockType: 'image',
49
+ src: img ?? '',
50
+ alt: title + ' image',
51
+ dim: cnst
52
+ } satisfies ImageBlock as Block}
53
+ className={cn('m-auto', clx)}
54
+ />
55
+ )
56
+ }
57
+
58
+ export default ItemMedia
@@ -2,22 +2,20 @@ import React from 'react'
2
2
  import Image from 'next/image'
3
3
 
4
4
  import {
5
- AspectRatio,
6
5
  Card,
7
6
  CardContent,
8
- CardDescription,
9
7
  CardFooter,
10
8
  CardHeader,
11
9
  CardTitle,
12
10
  } from '@hanzo/ui/primitives'
13
- import type { ImageDef } from '@hanzo/ui/types'
11
+
14
12
  import { cn } from '@hanzo/ui/util'
15
13
 
16
- import { formatCurrencyValue } from '../util'
17
- import type { LineItem } from '../types'
18
- import { Icons } from './Icons'
14
+ import { formatCurrencyValue } from '../../util'
15
+ import type { LineItem } from '../../types'
16
+ import { Icons } from '../Icons'
19
17
 
20
- import AddToCartWidget from './add-to-cart-widget'
18
+ import AddToCartWidget from '../buy/add-to-cart-widget'
21
19
 
22
20
  interface ProductCardProps extends React.HTMLAttributes<HTMLDivElement> {
23
21
  item: LineItem
@@ -0,0 +1,64 @@
1
+ import React from 'react'
2
+
3
+ import Spline from '@splinetool/react-spline'
4
+
5
+ import type { Dimensions } from '@hanzo/ui/types'
6
+ import { cn } from '@hanzo/ui/util'
7
+ import ItemMedia from '../item/item-media'
8
+
9
+ import {
10
+ type CarouselOptionsType,
11
+ Carousel,
12
+ CarouselContent,
13
+ CarouselItem,
14
+ CarouselPrevious,
15
+ CarouselNext
16
+ } from '@hanzo/ui/primitives'
17
+
18
+ import {
19
+ VideoBlockComponent,
20
+ ImageBlockComponent,
21
+ type ImageBlock,
22
+ type Block,
23
+ type VideoBlock
24
+ } from '@hanzo/ui/blocks'
25
+
26
+ import type { ItemSelectorProps } from '../../types'
27
+
28
+ interface CarouselItemSelectorPropsExt {
29
+ constrainTo: Dimensions
30
+ options?: CarouselOptionsType
31
+ noSelection?: boolean // "display only" mode
32
+ }
33
+
34
+ const CarouselItemSelector: React.FC<ItemSelectorProps> = ({
35
+ items,
36
+ clx='',
37
+ itemClx='',
38
+ ext={
39
+ options: {},
40
+ constrainTo: {w: 250, h: 250}
41
+ } satisfies CarouselItemSelectorPropsExt
42
+ }) => {
43
+
44
+ const { options, constrainTo} = ext
45
+
46
+ return (
47
+ <Carousel options={options} className={cn('px-2', clx)} >
48
+ <CarouselContent>
49
+ {items.map((item, index) => (
50
+ <CarouselItem key={index} className={cn('p-2 flex flex-row justify-center items-center', itemClx)}>
51
+ <ItemMedia item={item} constrainTo={constrainTo} clx='' />
52
+ </CarouselItem>
53
+ ))}
54
+ </CarouselContent>
55
+ <CarouselPrevious className='left-1'/>
56
+ <CarouselNext className='right-1'/>
57
+ </Carousel>
58
+ )
59
+ }
60
+
61
+ export {
62
+ type CarouselItemSelectorPropsExt,
63
+ CarouselItemSelector as default
64
+ }
@@ -0,0 +1,125 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import Image from 'next/image'
4
+ import { observer } from 'mobx-react-lite'
5
+
6
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
7
+ import { Label, RadioGroup, RadioGroupItem } from '@hanzo/ui/primitives'
8
+ import type { ItemSelectorProps, LineItem } from '../../types'
9
+ import { formatCurrencyValue } from '../../util'
10
+ import { cn } from '@hanzo/ui/util'
11
+ import type { Dimensions } from '@hanzo/ui/types'
12
+
13
+ const ImageRadioGroupItem = React.forwardRef<
14
+ React.ElementRef<typeof RadioGroupPrimitive.Item>,
15
+ Omit<React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>, 'value' | 'id'> & {
16
+ item: LineItem,
17
+ imgSizePx: number
18
+ }
19
+ >(({
20
+ item,
21
+ imgSizePx,
22
+ className,
23
+ ...props
24
+ }, ref) => {
25
+
26
+ let dim: Dimensions
27
+ if (item.imgAR) {
28
+ if (item.imgAR >= 1) {
29
+ dim = {
30
+ w: imgSizePx,
31
+ h: imgSizePx / item.imgAR
32
+ }
33
+ }
34
+ else {
35
+ dim = {
36
+ w: imgSizePx * item.imgAR,
37
+ h: imgSizePx
38
+ }
39
+ }
40
+ }
41
+ else {
42
+ dim = {
43
+ w: imgSizePx,
44
+ h: imgSizePx
45
+ }
46
+ }
47
+
48
+ return (
49
+ <RadioGroupPrimitive.Item
50
+ ref={ref}
51
+ className={cn(
52
+ "ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
53
+ className
54
+ )}
55
+ {...props}
56
+ id={item.sku}
57
+ value={item.sku}
58
+ >
59
+ {!!item.img ? (
60
+ <Image src={item.img} alt={item.title + ' image'} height={dim.h} width={dim.w} className=''/>
61
+ ) : ( // placeholder so things align
62
+ <div style={{height: dim.h, width: dim.w}}/>
63
+ )}
64
+ </RadioGroupPrimitive.Item>
65
+ )
66
+ })
67
+ ImageRadioGroupItem.displayName = 'ImageRadioGroupItem'
68
+
69
+ const ImageItemSelector: React.FC<ItemSelectorProps> = observer(({
70
+ items,
71
+ selectedItemRef: itemRef,
72
+ selectSku,
73
+ clx='',
74
+ itemClx='',
75
+ soleItemClx='',
76
+ showPrice=true,
77
+ showQuantity=true
78
+ }) => {
79
+
80
+ const Choice: React.FC<{
81
+ item: LineItem
82
+ className?: string
83
+ }> = ({
84
+ item,
85
+ className=''
86
+ }) => (
87
+ <div className={cn('flex items-center mb-1', className, itemClx)}>
88
+ <ImageRadioGroupItem item={item} imgSizePx={40} className='mr-2 border-2 border-transparent rounded-sm data-[state=checked]:border-foreground'/>
89
+ <Label htmlFor={item.sku}>{item.titleAsOption + (showPrice ? (', ' + formatCurrencyValue(item.price)) : '')}</Label>
90
+ </div>
91
+ )
92
+
93
+ const SoleChoice: React.FC<{
94
+ item: LineItem
95
+ className?: string
96
+ }> = ({
97
+ item,
98
+ className=''
99
+ }) => (
100
+ <div className={cn(className, soleItemClx)}>
101
+ {item.titleAsOption + (showPrice ? (', ' + formatCurrencyValue(item.price)) : '')}
102
+ </div>
103
+ )
104
+
105
+ return items.length > 1 ? (
106
+ <RadioGroup
107
+ className={cn('gap-0', showQuantity ? 'table' : '', clx)}
108
+ onValueChange={selectSku}
109
+ value={itemRef.item ? itemRef.item.sku : ''}
110
+ >
111
+ {items.map((item) => (showQuantity ? (
112
+ <div className='table-row' key={item.sku}>
113
+ <Choice item={item} className='table-cell pr-2 align-text-top pb-3'/>
114
+ <div className='table-cell font-semibold text-sm leading-none align-text-top pb-3'>{ item.quantity > 0 ? `(${item.quantity})` : ' '}</div>
115
+ </div>
116
+ ) : (
117
+ <Choice item={item} className='mb-3' key={item.sku}/>
118
+ )))}
119
+ </RadioGroup>
120
+ ) : (
121
+ <SoleChoice item={items[0]} className=''/>
122
+ )
123
+ })
124
+
125
+ export default ImageItemSelector
@@ -0,0 +1,66 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import { observer } from 'mobx-react-lite'
4
+
5
+ import { Label, RadioGroup, RadioGroupItem } from '@hanzo/ui/primitives'
6
+ import type { ItemSelectorProps, LineItem } from '../../types'
7
+ import { formatCurrencyValue } from '../../util'
8
+ import { cn } from '@hanzo/ui/util'
9
+
10
+ const RadioItemSelector: React.FC<ItemSelectorProps> = observer(({
11
+ items,
12
+ selectedItemRef: itemRef,
13
+ selectSku,
14
+ clx='',
15
+ itemClx='',
16
+ soleItemClx='',
17
+ showPrice=true,
18
+ showQuantity=true
19
+ }) => {
20
+
21
+ const Choice: React.FC<{
22
+ item: LineItem
23
+ className?: string
24
+ }> = ({
25
+ item,
26
+ className=''
27
+ }) => (
28
+ <div className={cn(className, itemClx)}>
29
+ <RadioGroupItem value={item.sku} id={item.sku} className='mr-2'/>
30
+ <Label htmlFor={item.sku}>{item.titleAsOption + (showPrice ? (', ' + formatCurrencyValue(item.price)) : '')}</Label>
31
+ </div>
32
+ )
33
+
34
+ const SoleChoice: React.FC<{
35
+ item: LineItem
36
+ className?: string
37
+ }> = ({
38
+ item,
39
+ className=''
40
+ }) => (
41
+ <div className={cn(className, soleItemClx)}>
42
+ {item.titleAsOption + (showPrice ? (', ' + formatCurrencyValue(item.price)) : '')}
43
+ </div>
44
+ )
45
+
46
+ return items.length > 1 ? (
47
+ <RadioGroup
48
+ className={cn('gap-0', showQuantity ? 'table' : '', clx)}
49
+ onValueChange={selectSku}
50
+ value={itemRef.item ? itemRef.item.sku : ''}
51
+ >
52
+ {items.map((item) => (showQuantity ? (
53
+ <div className='table-row' key={item.sku}>
54
+ <Choice item={item} className='table-cell pr-2 align-text-top pb-2'/>
55
+ <div className='table-cell font-semibold text-sm leading-none align-text-top pb-2'>{ item.quantity > 0 ? `(${item.quantity})` : ' '}</div>
56
+ </div>
57
+ ) : (
58
+ <Choice item={item} className='mb-2' key={item.sku}/>
59
+ )))}
60
+ </RadioGroup>
61
+ ) : (
62
+ <SoleChoice item={items[0]} className=''/>
63
+ )
64
+ })
65
+
66
+ export default RadioItemSelector
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/commerce",
3
- "version": "5.1.2",
3
+ "version": "6.0.0",
4
4
  "description": "Library with shopping cart components.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -42,6 +42,7 @@
42
42
  "@hanzo/auth": "^2.3.3",
43
43
  "@hanzo/ui": "^3.1.0",
44
44
  "@hookform/resolvers": "^3.3.4",
45
+ "@radix-ui/react-radio-group": "^1.1.3",
45
46
  "firebase": "^10.8.0",
46
47
  "lucide-react": "^0.307.0",
47
48
  "mobx": "^6.12.0",
@@ -9,7 +9,7 @@ enableStaticRendering(typeof window === "undefined")
9
9
  import type CommerceService from '../types/commerce-service'
10
10
  import type { ServiceOptions } from '..'
11
11
  import getServiceSingleton from './impls'
12
- import type { Category, FacetValueDesc } from '../types'
12
+ import type { Category, ProductTreeNode } from '../types'
13
13
 
14
14
  const CommerceServiceContext = createContext<CommerceService | undefined>(undefined)
15
15
 
@@ -20,17 +20,17 @@ const useCommerce = (): CommerceService => {
20
20
 
21
21
  const CommerceServiceProvider: React.FC<PropsWithChildren & {
22
22
  productsByCategory: Category[]
23
- rootFacet: FacetValueDesc
23
+ rootNode: ProductTreeNode
24
24
  options?: ServiceOptions
25
25
  }> = ({
26
26
  children,
27
27
  productsByCategory,
28
- rootFacet,
28
+ rootNode,
29
29
  options
30
30
  }) => {
31
31
 
32
32
  // TODO: Inject Promo fixture here
33
- const serviceRef = useRef<CommerceService>(getServiceSingleton(productsByCategory, rootFacet, options))
33
+ const serviceRef = useRef<CommerceService>(getServiceSingleton(productsByCategory, rootNode, options))
34
34
  return (
35
35
  <CommerceServiceContext.Provider value={serviceRef.current}>
36
36
  {children}
@@ -1,6 +1,6 @@
1
1
  import { enableStaticRendering } from 'mobx-react-lite'
2
2
 
3
- import type { CommerceService, Category, FacetValueDesc } from '../../../types'
3
+ import type { CommerceService, Category, ProductTreeNode } from '../../../types'
4
4
  import StandaloneService, {type StandaloneServiceOptions} from './standalone-service'
5
5
 
6
6
  import { readSnapshot, listenAndWriteSnapshots } from './localStorage'
@@ -19,7 +19,7 @@ let instance: StandaloneService | undefined = undefined
19
19
 
20
20
  export const getInstance = (
21
21
  categories: Category[],
22
- rootFacet: FacetValueDesc,
22
+ rootNode: ProductTreeNode,
23
23
  options?: StandaloneServiceOptions
24
24
  ): CommerceService => {
25
25
 
@@ -31,7 +31,7 @@ export const getInstance = (
31
31
  //_log("NEW INSTANCE FOR SERVER")
32
32
  return new StandaloneService(
33
33
  categories,
34
- rootFacet,
34
+ rootNode,
35
35
  options
36
36
  )
37
37
  }
@@ -42,7 +42,7 @@ export const getInstance = (
42
42
  const snapShot = readSnapshot()
43
43
  instance = new StandaloneService(
44
44
  categories,
45
- rootFacet,
45
+ rootNode,
46
46
  options,
47
47
  snapShot
48
48
  )