@hanzo/commerce 5.1.3 → 6.1.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 (67) hide show
  1. package/components/{buy-item/select-category-item-card.tsx → buy/_to_deprecate_select-category-item-card.tsx} +22 -32
  2. package/components/{select-category-item-panel.tsx → buy/_to_deprecate_select-category-item-panel.tsx} +16 -22
  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} +10 -6
  5. package/components/buy/buy-button.tsx +31 -0
  6. package/components/buy/buy-card.tsx +267 -0
  7. package/components/buy/buy-drawer.tsx +89 -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 +27 -14
  11. package/components/{cart-panel → cart/cart-panel}/index.tsx +12 -3
  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/index.ts +20 -18
  21. package/components/item/item-media.tsx +51 -0
  22. package/components/item/product-card.tsx +48 -0
  23. package/components/{facet-values-widget → level-nodes-widget}/index.tsx +20 -19
  24. package/components/level-nodes-widget/node-image.tsx +31 -0
  25. package/components/select/carousel-selector.tsx +112 -0
  26. package/components/select/image-selector.tsx +162 -0
  27. package/components/select/radio-selector.tsx +125 -0
  28. package/package.json +3 -2
  29. package/service/context.tsx +4 -4
  30. package/service/impls/standalone/actual-line-item.ts +30 -16
  31. package/service/impls/standalone/index.ts +4 -4
  32. package/service/impls/standalone/standalone-service.ts +94 -64
  33. package/types/buy-ui-spec.ts +8 -0
  34. package/types/category.ts +6 -4
  35. package/types/commerce-service.ts +21 -16
  36. package/types/index.ts +3 -2
  37. package/types/item-selector.ts +34 -6
  38. package/types/line-item.ts +2 -0
  39. package/types/product.ts +5 -5
  40. package/types/tree-node.ts +24 -0
  41. package/util/buy-ui-conf.ts +34 -0
  42. package/util/index.ts +14 -11
  43. package/util/obs-string-mutator.ts +22 -0
  44. package/util/use-sync-sku-param-w-current-item.ts +5 -5
  45. package/components/buy-item/buy-item-button-wrapper.tsx +0 -27
  46. package/components/buy-item/buy-item-button.tsx +0 -34
  47. package/components/buy-item/buy-item-card.tsx +0 -92
  48. package/components/buy-item/buy-item-mobile-drawer.tsx +0 -54
  49. package/components/buy-item/select-category-and-item-widget.tsx +0 -83
  50. package/components/category-item-radio-selector.tsx +0 -55
  51. package/components/category-item-scroll-selector.tsx +0 -40
  52. package/components/facet-values-widget/facet-image.tsx +0 -41
  53. package/components/item-carousel.tsx +0 -80
  54. package/components/product-card.tsx +0 -79
  55. package/types/facet.ts +0 -35
  56. /package/components/{cart-icon.tsx → cart/cart-icon.tsx} +0 -0
  57. /package/components/{payment-step-form → checkout/payment-step-form}/card-icon-row.tsx +0 -0
  58. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/amex.tsx +0 -0
  59. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/diners-club.tsx +0 -0
  60. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/discover.tsx +0 -0
  61. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/jcb.tsx +0 -0
  62. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/mastercard.tsx +0 -0
  63. /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/visa.tsx +0 -0
  64. /package/components/{payment-step-form → checkout/payment-step-form}/cc-button.tsx +0 -0
  65. /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/btc.tsx +0 -0
  66. /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/eth.tsx +0 -0
  67. /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/usdt.tsx +0 -0
@@ -0,0 +1,22 @@
1
+
2
+ import { makeObservable, observable, action } from 'mobx'
3
+ import type { StringMutator } from '../types'
4
+
5
+ class ObsStringMutator implements StringMutator {
6
+
7
+ s: string | null
8
+ constructor(_s: string) {
9
+ this.s = _s
10
+ makeObservable(this, {
11
+ s: observable,
12
+ set: action,
13
+ //get: computed
14
+ })
15
+ }
16
+
17
+ set(v: string | null): void { this.s = v }
18
+ get(): string | null { return this.s }
19
+ }
20
+
21
+ export default ObsStringMutator
22
+
@@ -9,7 +9,7 @@ import {
9
9
  } from 'next-usequerystate'
10
10
 
11
11
  import { useCommerce } from '../service/context'
12
- import type { FacetsValue } from '../types'
12
+ import type { SelectedPaths } from '../types'
13
13
 
14
14
  const PLEASE_SELECT_FACETS = 'Please select an option from each group.'
15
15
 
@@ -32,7 +32,7 @@ const useSyncSkuParamWithCurrentItem = (
32
32
  useEffect(() => {
33
33
 
34
34
  return reaction(() => ({
35
- specifiedCat: cmmc.specifiedCategories.length === 1 ? cmmc.specifiedCategories[0] : undefined,
35
+ specifiedCat: cmmc.selectedCategories.length === 1 ? cmmc.selectedCategories[0] : undefined,
36
36
  currentItem: cmmc.currentItem
37
37
  }),
38
38
  ({specifiedCat, currentItem}) => {
@@ -55,14 +55,14 @@ const useSyncSkuParamWithCurrentItem = (
55
55
 
56
56
  const setCurrentCategoryFromSku = (sku: string) => {
57
57
  const toks: string[] = sku.split('-')
58
- const fv: FacetsValue = {}
59
- // TODO: confirm that extra trailing nonsense tokens won't break setFacets()
58
+ const fv: SelectedPaths = {}
59
+ // TODO: confirm that extra trailing nonsense tokens won't break selectPaths()
60
60
  for (let i = 1; i < categoryLevel; i++) {
61
61
  if (i in toks) {
62
62
  fv[i] = [toks[i]]
63
63
  }
64
64
  }
65
- cmmc.setFacets(fv)
65
+ cmmc.selectPaths(fv)
66
66
  }
67
67
 
68
68
  // setCI returns true if it's a recognized sku
@@ -1,27 +0,0 @@
1
- 'use client'
2
- import React, {type PropsWithChildren} from 'react'
3
-
4
- import BuyItemPopup from './buy-item-popup'
5
- import BuyItemMobileDrawer from './buy-item-mobile-drawer'
6
-
7
- const BuyItemButtonWrapper: React.FC<{
8
- skuPath: string
9
- desktopTrigger: React.ReactNode
10
- mobileTrigger: React.ReactNode
11
- popupClx?: string
12
- }> = ({
13
- skuPath,
14
- desktopTrigger,
15
- mobileTrigger,
16
- popupClx=''
17
- }) => (<>
18
- <BuyItemPopup skuPath={skuPath} popupClx={popupClx}>
19
- {desktopTrigger}
20
- </BuyItemPopup>
21
- <BuyItemMobileDrawer skuPath={skuPath} trigger={mobileTrigger} />
22
- </>
23
- )
24
-
25
-
26
-
27
- export default BuyItemButtonWrapper
@@ -1,34 +0,0 @@
1
- 'use client'
2
- import React, {type PropsWithChildren} from 'react'
3
-
4
- import { type ButtonVariants, type ButtonSizes, Button } from '@hanzo/ui/primitives'
5
-
6
- import BuyItemPopup from './buy-item-popup'
7
- import BuyItemMobileDrawer from './buy-item-mobile-drawer'
8
- import { cn } from '@hanzo/ui/util'
9
-
10
- const BuyItemButton: React.FC<PropsWithChildren & {
11
- skuPath: string
12
- variant? : ButtonVariants
13
- size?: ButtonSizes
14
- /* rounded?: ButtonRounded // wait for version bump*/
15
- className?: string
16
- popupClx?: string
17
- }> = ({
18
- skuPath,
19
- variant,
20
- size,
21
- children,
22
- className='',
23
- popupClx=''
24
- }) => (<>
25
- <BuyItemPopup skuPath={skuPath} popupClx={popupClx}>
26
- <Button size={size} variant={variant} className={cn(className, 'hidden md:flex')}>{children}</Button>
27
- </BuyItemPopup>
28
- <BuyItemMobileDrawer skuPath={skuPath} trigger={<Button size={size} variant={variant} className={cn(className, 'md:hidden')}>{children}</Button>} />
29
- </>
30
- )
31
-
32
-
33
-
34
- export default BuyItemButton
@@ -1,92 +0,0 @@
1
- 'use client'
2
- import React, { useRef, useEffect } from 'react'
3
- import { autorun } from 'mobx'
4
- import { observer } from 'mobx-react-lite'
5
-
6
- import { cn } from '@hanzo/ui/util'
7
-
8
- import type { FacetsValue } from '../../types'
9
- import { useCommerce } from '../../service/context'
10
- import { getFacetValuesMutator } from '../../util'
11
- import FacetValuesWidget from '../facet-values-widget'
12
- import SelectCategoryItemCard from './select-category-item-card'
13
-
14
-
15
- const BuyItemCard: React.FC<{
16
- skuPath: string
17
- mobile?: boolean
18
- className?: string
19
- onQuantityChanged?: (sku: string, oldV: number, newV: number) => void
20
- }> = observer(({
21
- skuPath,
22
- mobile=false,
23
- className='',
24
- onQuantityChanged
25
- }) => {
26
-
27
- const cmmc = useCommerce()
28
- const levelRef = useRef<number>(-1)
29
-
30
- const cat = cmmc.getCategory(skuPath)
31
- const facets = cat ? undefined : cmmc.getFacetValuesAtSkuPath(skuPath)
32
-
33
- useEffect(() => {
34
-
35
- const toks = skuPath.split('-')
36
- levelRef.current = toks.length - 1
37
- const fsv: FacetsValue = {}
38
- for (let level = 1; level <= levelRef.current; level++ ) {
39
- fsv[level] = [toks[level]]
40
- }
41
- if (facets) {
42
- fsv[levelRef.current + 1] = [facets[0].value]
43
- }
44
- cmmc.setFacets(fsv)
45
-
46
- return autorun(() => {
47
- const cats = cmmc.specifiedCategories
48
- // Original cat was legit
49
- if (cat && (cats.length === 0 || cats[0].id !== cat.id)) {
50
- if (!cmmc.currentItem || cmmc.currentItem.categoryId !== cat.id) {
51
- cmmc.setCurrentItem(cat.products[0].sku)
52
- }
53
- }
54
- else if (cats.length > 0) {
55
- if (!cmmc.currentItem || cmmc.currentItem.categoryId !== cats[0].id) {
56
- cmmc.setCurrentItem(cats[0].products[0].sku)
57
- }
58
- }
59
- })
60
- }, [cat, facets])
61
-
62
- const renderFacetTabs = facets && levelRef.current > 0
63
-
64
- return (
65
- <div className={className} >
66
- {renderFacetTabs && (
67
- <FacetValuesWidget
68
- className={cn('grid gap-0 ' + `grid-cols-${facets.length}` + ' self-start ', 'border-b-2 border-level-3 mb-2 -mr-2 -ml-2')}
69
- isMobile={false}
70
- mutator={getFacetValuesMutator(levelRef.current + 1, cmmc)}
71
- itemClx='flex-col h-auto gap-0 pb-1 pt-3 px-3'
72
- buttonClx={'h-full !rounded-bl-none !rounded-br-none !rounded-tl-lg !rounded-tr-lg ' +
73
- '!border-r !border-t !border-level-3'}
74
- facetValues={facets}
75
- />
76
- )}
77
- {cmmc.specifiedCategories[0] && (
78
- <SelectCategoryItemCard
79
- noTitle
80
- mobile={mobile}
81
- category={cmmc.specifiedCategories[0]}
82
- selectedItemRef={cmmc /* ...conveniently. :) */ }
83
- selectSku={cmmc.setCurrentItem.bind(cmmc)}
84
- className=''
85
- onQuantityChanged={onQuantityChanged}
86
- />
87
- )}
88
- </div >
89
- )
90
- })
91
-
92
- export default BuyItemCard
@@ -1,54 +0,0 @@
1
- 'use client'
2
- import React, { useState, type ReactNode } from 'react'
3
-
4
- //import { X as LucideX} from 'lucide-react'
5
- //import { Sheet, SheetContent, SheetTrigger } from '@hanzo/ui/primitives'
6
-
7
- import {
8
- Drawer,
9
- DrawerTrigger,
10
- DrawerContent,
11
- } from '@hanzo/ui/primitives'
12
-
13
- import { cn } from '@hanzo/ui/util'
14
-
15
- import BuyItemCard from './buy-item-card'
16
-
17
- const BuyItemMobileDrawer: React.FC<{
18
- skuPath: string
19
- trigger: ReactNode
20
- triggerClx?: string
21
- drawerClx?: string
22
- cardClx?: string
23
- }> = ({
24
- skuPath,
25
- trigger,
26
- triggerClx='',
27
- drawerClx='',
28
- cardClx=''
29
- }) => {
30
-
31
- const [open, setOpen] = useState<boolean>(false)
32
-
33
- const onQuantityChanged = (sku: string, oldV: number, newV: number) => {
34
- if (oldV === 0 && newV === 1) {
35
- setTimeout(() => {setOpen(false)}, 150)
36
- }
37
- }
38
-
39
- return (
40
- <Drawer open={open} onOpenChange={setOpen} >
41
- <DrawerTrigger asChild className={triggerClx}>
42
- {trigger}
43
- </DrawerTrigger>
44
- <DrawerContent
45
- className={cn('rounded-tl-xl rounded-tr-xl p-0 overflow-hidden', drawerClx)}
46
- // side="bottom"
47
- >
48
- <BuyItemCard skuPath={skuPath} mobile onQuantityChanged={onQuantityChanged} className={cn("w-full relative ", cardClx)}/>
49
- </DrawerContent>
50
- </Drawer>
51
- )
52
- }
53
-
54
- export default BuyItemMobileDrawer
@@ -1,83 +0,0 @@
1
- 'use client'
2
- import React, { useEffect } from 'react'
3
- import { observer } from 'mobx-react-lite'
4
-
5
- import { ApplyTypography, ListBox } from '@hanzo/ui/primitives'
6
- import { cn } from '@hanzo/ui/util'
7
-
8
- import type { FacetValueDesc, FacetsValue, LineItem } from '../../types'
9
- import { useCommerce } from '../../service/context'
10
- import { formatCurrencyValue } from '../../util'
11
-
12
- import FacetTogglesWidget from '../facet-values-widget'
13
-
14
- const formatItem = (item: LineItem, withQuantity: boolean = false): string => (
15
- `${item.titleAsOption}, ${formatCurrencyValue(item.price)}${(withQuantity && item.quantity > 0) ? ` (${item.quantity})` : ''}`
16
- )
17
-
18
- const SelectCategoryAndItemWidget: React.FC<{
19
- categoryLevel: number
20
- parentLevelToken: string
21
- categoryLevelValues: FacetValueDesc[]
22
- className?: string
23
- }> = observer(({
24
- categoryLevel,
25
- parentLevelToken,
26
- categoryLevelValues,
27
- className=''
28
- }) => {
29
- const comm = useCommerce()
30
-
31
- useEffect(() => {
32
- const facets: FacetsValue = {}
33
- facets[categoryLevel - 1] = [parentLevelToken]
34
- facets[categoryLevel] = [categoryLevelValues[0].value]
35
- comm.setFacets(facets)
36
- comm.setCurrentItem(comm.specifiedCategories[0].products[0].sku)
37
- }, [])
38
-
39
- const onFacetTokenChanged = (token: string): void => {
40
- const facets: FacetsValue = {}
41
- facets[categoryLevel - 1] = [parentLevelToken]
42
- facets[categoryLevel] = [token]
43
- comm.setFacets(facets)
44
- }
45
-
46
- const currentFacetToken = (): string | null => {
47
- if (comm.specifiedCategories.length === 0) return null
48
- const skuPath = comm.specifiedCategories[0].id
49
- const skuPathTokens = skuPath.split('-')
50
- return skuPathTokens.length > 0 ? skuPathTokens[skuPathTokens.length - 1] : null
51
- }
52
-
53
- return (
54
- <div className={cn('flex flex-col justify-start gap-4 items-start pt-3', className)}>
55
- <FacetTogglesWidget
56
- facetValues={categoryLevelValues}
57
- mutator={{
58
- get: currentFacetToken, // computed's are accessed through their get()
59
- set: onFacetTokenChanged
60
- }}
61
- />
62
- {comm.specifiedItems.length === 0 ? (
63
- <ApplyTypography>
64
- <h3>No Items</h3>
65
- </ApplyTypography>
66
- ) : comm.specifiedItems.length === 1 ? (
67
- <ApplyTypography>
68
- <h4>{formatItem(comm.specifiedItems[0])}</h4>
69
- </ApplyTypography>
70
- ) : (
71
- <ListBox<string>
72
- values={comm.specifiedItems.map((it) => (it.sku))}
73
- labels={comm.specifiedItems.map((it) => (formatItem(it)))}
74
- isEqual={(v1: string, v2: string) => (v1 === v2)}
75
- value={comm.currentItem?.sku}
76
- onValueChange={comm.setCurrentItem.bind(comm)}
77
- />
78
- )}
79
- </div>
80
- )
81
- })
82
-
83
- export default SelectCategoryAndItemWidget
@@ -1,55 +0,0 @@
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 { ItemSelector, LineItem, Product } from '../types'
7
- import { formatCurrencyValue } from '../util'
8
- import { cn } from '@hanzo/ui/util'
9
-
10
- const CategoryItemRadioSelector: React.FC<ItemSelector & {
11
- groupClx?: string
12
- itemClx?: string
13
- }> = observer(({
14
- category,
15
- selectedItemRef: itemRef,
16
- selectSku,
17
- groupClx='',
18
- itemClx='',
19
- showPrice=true,
20
- showQuantity=true
21
- }) => {
22
-
23
- const Choice: React.FC<{
24
- item: Product
25
- className?: string
26
- }> = ({
27
- item,
28
- className=''
29
- }) => (
30
- <div className={cn(className, itemClx)}>
31
- <RadioGroupItem value={item.sku} id={item.sku} />
32
- <Label htmlFor={item.sku}>{item.titleAsOption + (showPrice ? (', ' + formatCurrencyValue(item.price)) : '')}</Label>
33
- </div>
34
- )
35
-
36
- return ( category.products.length > 1 ? (
37
- <RadioGroup
38
- className={cn(showQuantity ? 'table' : '', groupClx)}
39
- onValueChange={selectSku}
40
- value={itemRef.item ? itemRef.item.sku : ''}
41
- >
42
- {(category.products as LineItem[]).map((item) => (showQuantity ? (
43
- <div className='table-row' key={item.sku}>
44
- <Choice item={item} className='table-cell pr-2 align-text-top pb-2'/>
45
- <div className='table-cell font-semibold text-sm leading-none align-text-top pb-2'>{ item.quantity > 0 ? `(${item.quantity})` : ' '}</div>
46
- </div>
47
- ) : (
48
- <Choice item={item} className='mb-2' key={item.sku}/>
49
- )))}
50
- </RadioGroup>
51
- ) : (<p>TODO</p>)
52
- )
53
- })
54
-
55
- export default CategoryItemRadioSelector
@@ -1,40 +0,0 @@
1
- 'use client'
2
- import React from 'react'
3
- import { observer } from 'mobx-react-lite'
4
-
5
- import { cn } from '@hanzo/ui/util'
6
- import { ScrollArea } from '@hanzo/ui/primitives'
7
-
8
- import type { ItemSelector } from '../types'
9
- import { formatCurrencyValue } from '../util'
10
-
11
-
12
- const CategoryItemScrollSelector: React.FC<ItemSelector & {
13
- outerClx?: string
14
- itemClx?: string
15
- }> = observer(({
16
- category,
17
- selectedItemRef: iRef,
18
- selectSku,
19
- outerClx='',
20
- itemClx=''
21
- }) => {
22
-
23
- return (
24
- <ScrollArea className={cn('border border-muted-4 rounded-lg', outerClx)}>
25
- {category.products.map((prod) => (
26
- <div key={prod.sku} onClick={() => {selectSku(prod.sku)}}>
27
- <div className={cn(
28
- 'h-10 border-b flex flex-col justify-center px-4',
29
- (iRef.item?.sku === prod.sku) ? 'font-semibold text-accent' : 'text-muted',
30
- itemClx
31
- )}>
32
- {prod.titleAsOption + ', ' + formatCurrencyValue(prod.price)}
33
- </div>
34
- </div>
35
- ))}
36
- </ScrollArea>
37
- )
38
- })
39
-
40
- export default CategoryItemScrollSelector
@@ -1,41 +0,0 @@
1
- import React from 'react'
2
- import Image from 'next/image'
3
-
4
- import type { FacetValueDesc } from '../../types'
5
-
6
- const ICON_SIZE = 20
7
-
8
- const FacetImage: React.FC<{
9
- facetValueDesc: FacetValueDesc
10
- }> = ({
11
- facetValueDesc
12
- }) => {
13
-
14
- const {
15
- img,
16
- imgAR: ar,
17
- label
18
- } = facetValueDesc
19
-
20
- if (!img) {
21
- return null
22
- }
23
-
24
- // url
25
- if (typeof img === 'string') {
26
- return (
27
- <Image
28
- src={img as string}
29
- alt={`Toggle ${label}`}
30
- className={'block mr-1 '}
31
- width={ar ? ar * ICON_SIZE : ICON_SIZE}
32
- height={ICON_SIZE}
33
- />
34
- )
35
- }
36
- // ReactNode
37
- return img as React.ReactNode
38
- }
39
-
40
- export default FacetImage
41
-
@@ -1,80 +0,0 @@
1
- import React from 'react'
2
-
3
- import Spline from '@splinetool/react-spline'
4
-
5
- import { cn } from '@hanzo/ui/util'
6
-
7
- import {
8
- type CarouselOptionsType,
9
- Carousel,
10
- CarouselContent,
11
- CarouselItem,
12
- CarouselPrevious,
13
- CarouselNext
14
- } from '@hanzo/ui/primitives'
15
-
16
- import {
17
- VideoBlockComponent,
18
- ImageBlockComponent,
19
- type ImageBlock,
20
- type Block,
21
- type VideoBlock
22
- } from '@hanzo/ui/blocks'
23
-
24
- import type { LineItem } from '../types'
25
- import type { Dimensions } from '@hanzo/ui/types'
26
-
27
- // Order of precedence of visuals: 3D > MP4 > Image
28
- const ItemCarousel: React.FC<{
29
- items: LineItem[]
30
- constrainTo: Dimensions
31
- options?: CarouselOptionsType
32
- className?: string
33
- itemClx?: string
34
- }> = ({
35
- items,
36
- options,
37
- className='',
38
- constrainTo,
39
- itemClx=''
40
- }) => (
41
- // className: 'w-full max-w-sm mx-auto
42
- // itemClx: 'flex aspect-square items-center justify-center '
43
- <Carousel options={options} className={cn('px-2', className)} >
44
- <CarouselContent>
45
- {items.map(({title, img, video, animation}, index) => (
46
- <CarouselItem key={index} className={cn('p-2 flex flex-row justify-center items-center', itemClx)}>
47
- {animation ? (
48
- <Spline
49
- scene={animation}
50
- className='pointer-events-none' // !aspect-[12/10]
51
- style={{
52
- width: (6/5 * (typeof constrainTo.h === 'number' ? constrainTo.h as number : parseInt(constrainTo.h as string)) ),
53
- height: constrainTo.h
54
- }}
55
- />
56
- ) : video ? (
57
- <VideoBlockComponent
58
- constraint={constrainTo}
59
- block={{blockType: 'video', ...video} satisfies VideoBlock as Block}
60
- />
61
- ) : (
62
- <ImageBlockComponent
63
- block={{
64
- blockType: 'image',
65
- src: img ?? '',
66
- alt: title + ' image',
67
- dim: constrainTo
68
- } satisfies ImageBlock as Block}
69
- className='m-auto'
70
- />
71
- )}
72
- </CarouselItem>
73
- ))}
74
- </CarouselContent>
75
- <CarouselPrevious className='left-1'/>
76
- <CarouselNext className='right-1'/>
77
- </Carousel>
78
- )
79
-
80
- export default ItemCarousel
@@ -1,79 +0,0 @@
1
- import React from 'react'
2
- import Image from 'next/image'
3
-
4
- import {
5
- AspectRatio,
6
- Card,
7
- CardContent,
8
- CardDescription,
9
- CardFooter,
10
- CardHeader,
11
- CardTitle,
12
- } from '@hanzo/ui/primitives'
13
- import type { ImageDef } from '@hanzo/ui/types'
14
- import { cn } from '@hanzo/ui/util'
15
-
16
- import { formatCurrencyValue } from '../util'
17
- import type { LineItem } from '../types'
18
- import { Icons } from './Icons'
19
-
20
- import AddToCartWidget from './add-to-cart-widget'
21
-
22
- interface ProductCardProps extends React.HTMLAttributes<HTMLDivElement> {
23
- item: LineItem
24
- }
25
-
26
- const ProductCard: React.FC<ProductCardProps> = ({
27
- item,
28
- className,
29
- ...props
30
- }) => {
31
-
32
- const ProductImage: React.FC<{className?: string}> = ({className=''}) => (
33
- <Image
34
- src={item.img!}
35
- alt={item.title}
36
- className={className}
37
- loading='lazy'
38
- // width={700}
39
- // height={700}
40
- fill
41
- style={{
42
- objectFit: 'contain',
43
- }}
44
- />
45
- )
46
-
47
- return (
48
- <Card
49
- className={cn('max-h-[360px] lg:min-w-[200px] max-w-[260px] overflow-hidden', className)}
50
- {...props}
51
- >
52
- <CardHeader className='w-full border-b p-6 min-h-[180px] max-h-[240px] relative'>
53
- {item.img ? (
54
- <ProductImage className='p-6' />
55
- ) : (
56
- <div
57
- aria-label='Placeholder'
58
- role='img'
59
- aria-roledescription='placeholder'
60
- className='flex h-full items-center justify-center bg-background'
61
- >
62
- <Icons.barcode className='h-9 w-9 text-muted' aria-hidden='true' />
63
- </div>
64
- )}
65
- </CardHeader>
66
- <CardContent className='grid gap-2.5 p-4'>
67
- <CardTitle className='text-sm sm:text-base flex flex-col justify-start items-center line-clap-3'>
68
- {item.title.split(', ').map((e, i) => (<p key={i}>{e}</p>))}
69
- <p className='mt-1 font-semibold'>{formatCurrencyValue(item.price)}</p>
70
- </CardTitle>
71
- </CardContent>
72
- <CardFooter className='p-4 flex flex-row justify-center'>
73
- <AddToCartWidget item={item}/>
74
- </CardFooter>
75
- </Card>
76
- )
77
- }
78
-
79
- export default ProductCard
package/types/facet.ts DELETED
@@ -1,35 +0,0 @@
1
- import type { ReactNode } from 'react'
2
-
3
- interface FacetValueDesc {
4
- value: string // a token in the sku
5
- label: string
6
- img? : string | ReactNode // icon is required
7
- imgAR? : number // helps with svgs
8
- sub?: FacetValueDesc[]
9
- }
10
-
11
- /* *** FOR EXAMPLE **
12
- {
13
- 1: [ {
14
- token: 'AG',
15
- label: 'Silver',
16
- img: '/assets/img/cart/ui/facets/silver-swatch-200x200.png'
17
- },
18
- ... more FaceValues describing the "type" level (Silver, Gold)
19
- ],
20
- 2 [
21
- {
22
- token: 'B'
23
- label: 'Minted Bar
24
- },
25
- ... more FaceValues describing the "form" level (Bar, Coin, )
26
- ]
27
- }
28
- */
29
- // Which facets tokens are on at each level
30
- type FacetsValue = Record<number, string[]>
31
-
32
- export type {
33
- FacetValueDesc,
34
- FacetsValue
35
- }