@hanzo/commerce 4.4.1 → 4.5.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.
@@ -2,7 +2,7 @@
2
2
  import React from 'react'
3
3
  import { observer } from 'mobx-react-lite'
4
4
 
5
- import { Button, type ButtonSizes } from '@hanzo/ui/primitives'
5
+ import { Button, toast, type ButtonSizes } from '@hanzo/ui/primitives'
6
6
  import { cn } from '@hanzo/ui/util'
7
7
 
8
8
  import { Icons } from './Icons'
@@ -44,6 +44,13 @@ const AddToCartWidget: React.FC<{
44
44
  if (onQuantityChanged) {
45
45
  onQuantityChanged(item.sku, old, old + 1)
46
46
  }
47
+ if (old === 0) {
48
+ toast(`Added ${item.title} to your bag.`)
49
+ }
50
+ else {
51
+ toast(`Changed quantity to ${old + 1} for ${item.title}.`)
52
+ }
53
+
47
54
  }
48
55
 
49
56
  const dec = () => {
@@ -52,6 +59,12 @@ const AddToCartWidget: React.FC<{
52
59
  if (onQuantityChanged) {
53
60
  onQuantityChanged(item.sku, old, old - 1)
54
61
  }
62
+ if (old === 1) {
63
+ toast(`Removed ${item.title} from your bag.`)
64
+ }
65
+ else {
66
+ toast(`Changed quantity to ${old - 1} for ${item.title}.`)
67
+ }
55
68
  }
56
69
 
57
70
  return ( item.isInCart ? (
@@ -9,7 +9,7 @@ import type { ItemSelector, LineItem } from '../../types'
9
9
 
10
10
  import AddToCartWidget from '../add-to-cart-widget'
11
11
  import CategoryItemRadioSelector from '../category-item-radio-selector'
12
- import CategoryItemIOSWheelSelector from '../category-item-ios-wheel-selector'
12
+ import CategoryItemScrollSelector from '../category-item-scroll-selector'
13
13
  import { formatPrice } from '../../util'
14
14
 
15
15
  const SelectCategoryItemCard: React.FC<React.HTMLAttributes<HTMLDivElement> & ItemSelector & {
@@ -52,13 +52,12 @@ const SelectCategoryItemCard: React.FC<React.HTMLAttributes<HTMLDivElement> & It
52
52
  )}>
53
53
  {!noTitle && (<div className={'h-[1px] bg-muted-3 ' + (mobilePicker ? 'w-pr-55' : 'w-pr-60') } /> )}
54
54
  {mobilePicker ? (
55
- <CategoryItemIOSWheelSelector
55
+ <CategoryItemScrollSelector
56
56
  category={category}
57
57
  selectedItemRef={selItemRef}
58
58
  selectSku={selectSku}
59
- height={180}
60
- itemHeight={30}
61
- outerClx='w-full'
59
+ itemClx='h-10 border-b px-4'
60
+ outerClx='min-w-pr-80 h-[180px]' // 80% of 65% parent
62
61
  />
63
62
  ) : (
64
63
  <CategoryItemRadioSelector
@@ -1,5 +1,5 @@
1
1
  'use client'
2
- import React, { useState, type PropsWithChildren } from 'react'
2
+ import React, { type PropsWithChildren } from 'react'
3
3
  import { observer } from 'mobx-react-lite'
4
4
 
5
5
  import { Button } from '@hanzo/ui/primitives'
@@ -9,21 +9,23 @@ import { useCommerce } from '../../service/context'
9
9
  import { formatPrice } from '../../util'
10
10
 
11
11
  import CartLineItem from './cart-line-item'
12
- import CheckoutPanel from '../checkout-panel'
13
12
 
14
13
  const CartPanel: React.FC<PropsWithChildren & {
15
14
  className?: string
16
15
  isMobile?: boolean,
17
16
  noCheckout?: boolean
17
+ onCheckoutOpen?: () => void
18
18
  }> = observer(({
19
19
  /** Children is the heading area. */
20
20
  children,
21
21
  className='',
22
22
  isMobile=false,
23
- noCheckout=false
23
+ noCheckout=false,
24
+ onCheckoutOpen,
24
25
  }) => {
25
-
26
- const [checkoutOpen, setCheckoutOpen] = useState<boolean>(false)
26
+ /* TODO: onCheckoutOpen is a hackish way fix a bug with multiple dialog opened at the same time.
27
+ * Needs refactor with context or so.
28
+ **/
27
29
  const cmmc = useCommerce()
28
30
  if (!cmmc) {
29
31
  return <div />
@@ -48,12 +50,11 @@ const CartPanel: React.FC<PropsWithChildren & {
48
50
  variant='primary'
49
51
  rounded='lg'
50
52
  className='mt-12 mx-auto w-full'
51
- onClick={() => setCheckoutOpen(true)}
53
+ onClick={onCheckoutOpen}
52
54
  >
53
55
  Checkout
54
56
  </Button>
55
57
  )}
56
- {checkoutOpen && <CheckoutPanel open={checkoutOpen} setOpen={setCheckoutOpen}/>}
57
58
  </>)}
58
59
  </div>
59
60
  )
@@ -0,0 +1,40 @@
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 { formatPrice } 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 + ', ' + formatPrice(prod.price)}
33
+ </div>
34
+ </div>
35
+ ))}
36
+ </ScrollArea>
37
+ )
38
+ })
39
+
40
+ export default CategoryItemScrollSelector
@@ -10,7 +10,6 @@ import {
10
10
  AccordionTrigger,
11
11
  Dialog,
12
12
  DialogPortal,
13
- Toaster
14
13
  } from '@hanzo/ui/primitives'
15
14
  import { cn } from '@hanzo/ui/util'
16
15
  import { AuthWidget } from '@hanzo/auth/components'
@@ -26,13 +25,18 @@ import { formatPrice, useCommerce } from '../..'
26
25
 
27
26
  const CheckoutPanel: React.FC<{
28
27
  open: boolean
29
- setOpen: (open: boolean) => void
28
+ onCheckoutClose: () => void
30
29
  }> = observer(({
31
30
  open,
32
- setOpen
31
+ onCheckoutClose
33
32
  }) => {
34
33
 
35
34
  const cmmc = useCommerce()
35
+
36
+ // For sites that don't initialize cmmc
37
+ if (!cmmc) {
38
+ return <></>
39
+ }
36
40
 
37
41
  const [step, setStep] = useState<number>(1)
38
42
  const [orderId, setOrderId] = useState<string>()
@@ -62,7 +66,7 @@ const CheckoutPanel: React.FC<{
62
66
 
63
67
  const onClose = () => {
64
68
  setStep(1)
65
- setOpen(false)
69
+ onCheckoutClose()
66
70
  }
67
71
 
68
72
  return (
@@ -98,9 +102,8 @@ const CheckoutPanel: React.FC<{
98
102
  </Accordion>
99
103
  </div>
100
104
  </div>
101
- <div className='bg-level-1 flex flex-row items-start justify-start'>
102
- <div className='h-full w-full max-w-[750px] relative flex flex-col gap-8 sm:gap-14 md:overflow-y-auto px-6 pb-6'>
103
- <Toaster/>
105
+ <div className='bg-level-1 flex flex-row items-start justify-start md:overflow-y-auto'>
106
+ <div className='h-full w-full max-w-[750px] relative flex flex-col gap-8 sm:gap-14 px-8 pb-6 pt-6 md:pt-14'>
104
107
  <AuthWidget hideLogin className='hidden md:flex absolute top-4 right-4 '/>
105
108
  <StepIndicator steps={steps} currentStep={step} className='flex gap-2 mx-auto items-center text-xxs sm:text-base' />
106
109
  {steps[step].element}
@@ -18,7 +18,7 @@ const InfoField: React.FC<{
18
18
  }) => {
19
19
  const copyToClipboard = (label: string, text: string) => {
20
20
  navigator.clipboard.writeText(text)
21
- toast({title: `${label} copied to clipboard`})
21
+ toast(`${label} copied to clipboard`)
22
22
  }
23
23
 
24
24
  return (
@@ -116,7 +116,7 @@ const PayWithCrypto: React.FC<{
116
116
  })
117
117
  }
118
118
  } catch (err) {
119
- toast({title: 'Please switch your wallet to the Ethereum network.'})
119
+ toast('Please switch your wallet to the Ethereum network.')
120
120
  return
121
121
  }
122
122
 
@@ -161,7 +161,7 @@ const PayWithCrypto: React.FC<{
161
161
  } catch (err) {
162
162
  console.log(err)
163
163
  // :aa TODO string table
164
- toast({title: 'Not enough funds in your wallet'})
164
+ toast('Not enough funds in your wallet')
165
165
  }
166
166
  })()
167
167
  }
@@ -5,7 +5,7 @@ export { default as BuyItemCard } from './buy-item/buy-item-card'
5
5
  export { default as BuyItemPopup } from './buy-item/buy-item-popup'
6
6
  export { default as CartPanel } from './cart-panel'
7
7
  export { default as CheckoutPanel } from './checkout-panel'
8
- export { default as CategoryItemIOSWheelSelector } from './category-item-ios-wheel-selector'
8
+ export { default as CategoryItemIOSWheelSelector } from './category-item-scroll-selector'
9
9
  export { default as CategoryItemRadioSelector } from './category-item-radio-selector'
10
10
  export { default as FacetValuesWidget } from './facet-values-widget'
11
11
  export { default as ProductCard } from './product-card'
@@ -12,7 +12,7 @@ import { Icons } from './Icons'
12
12
 
13
13
  import AddToCartWidget from './add-to-cart-widget'
14
14
  import CategoryItemRadioSelector from './category-item-radio-selector'
15
- import CategoryItemIOSWheelSelector from './category-item-ios-wheel-selector'
15
+ import CategoryItemScrollSelector from './category-item-scroll-selector'
16
16
 
17
17
  const SelectCategoryItemPanel: React.FC<
18
18
  React.HTMLAttributes<HTMLDivElement> & ItemSelector &
@@ -89,14 +89,13 @@ const SelectCategoryItemPanel: React.FC<
89
89
  <div className={'h-[1px] bg-muted-3 ' + (mobilePicker ? 'w-pr-55' : 'w-pr-60') } />
90
90
  </div>
91
91
  {mobilePicker ? (
92
- <CategoryItemIOSWheelSelector
92
+ <CategoryItemScrollSelector
93
93
  category={category}
94
94
  selectedItemRef={selectedItemRef}
95
95
  selectSku={selectSku}
96
96
  showQuantity={showQuantity}
97
- height={180}
98
- itemHeight={30}
99
- outerClx='mb-4'
97
+ itemClx='h-10 border-b px-4'
98
+ outerClx='mb-4 h-[180px]'
100
99
  />
101
100
  ) : (
102
101
  <CategoryItemRadioSelector
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/commerce",
3
- "version": "4.4.1",
3
+ "version": "4.5.0",
4
4
  "description": "Library with shopping cart components.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -33,20 +33,19 @@
33
33
  "dependencies": {
34
34
  "ethers": "^6.11.1",
35
35
  "next-usequerystate": "^1.17.0",
36
- "react-mobile-picker": "^1.0.0",
37
36
  "react-square-web-payments-sdk": "^3.2.1",
38
37
  "square": "^35.0.0"
39
38
  },
40
39
  "peerDependencies": {
41
- "@hanzo/auth": "^2.2.0",
42
- "@hanzo/ui": "^3.0.2",
40
+ "@hanzo/auth": "^2.2.1",
41
+ "@hanzo/ui": "^3.0.7",
43
42
  "@hookform/resolvers": "^3.3.4",
44
43
  "firebase": "^10.8.0",
45
44
  "lucide-react": "^0.307.0",
46
45
  "mobx": "^6.12.0",
47
46
  "mobx-react-lite": "^4.0.5",
48
47
  "mobx-utils": "^6.0.8",
49
- "next": "^14.1.0",
48
+ "next": "14.1.3",
50
49
  "react": "^18.2.0",
51
50
  "react-dom": "^18.2.0",
52
51
  "react-hook-form": "7.50.1",
@@ -1,62 +0,0 @@
1
- 'use client'
2
- import React from 'react'
3
- import Picker from 'react-mobile-picker'
4
- import { observer } from 'mobx-react-lite'
5
-
6
- import type { ItemSelector } from '../types'
7
- import { formatPrice } from '../util'
8
- import { cn } from '@hanzo/ui/util'
9
-
10
- // from source code
11
- interface PickerItemRenderProps {
12
- selected: boolean;
13
- }
14
-
15
- const CategoryItemIOSWheelSelector: React.FC<ItemSelector & {
16
- height?: number
17
- itemHeight?: number
18
- outerClx?: string
19
- itemClx?: string
20
- }> = observer(({
21
- category,
22
- selectedItemRef: iRef,
23
- selectSku,
24
- height,
25
- itemHeight,
26
- outerClx='',
27
- itemClx=''
28
- }) => {
29
-
30
- // @ts-ignore
31
- const onChange = (val, ignore) => {
32
- console.log("WHEEL: ", val.item)
33
- selectSku(val.item)
34
- }
35
-
36
- return (
37
- <div className={cn('border border-muted-4 rounded-lg px-2', outerClx)}>
38
- <Picker
39
- className=''
40
- value={iRef.item ? {item: iRef.item.sku} : {item: undefined}}
41
- onChange={onChange}
42
- wheelMode="natural"
43
- height={height}
44
- itemHeight={itemHeight}
45
- >
46
- <Picker.Column name="item">
47
- {category.products.map((prod) => (
48
- <Picker.Item key={prod.sku} value={prod.sku}>
49
- {({ selected }: PickerItemRenderProps) => (
50
- <div className={cn(selected ? 'font-semibold text-accent' : 'text-muted', itemClx)}>
51
- {prod.titleAsOption + ', ' + formatPrice(prod.price)}
52
- </div>
53
- )}
54
- </Picker.Item>
55
- ))}
56
- </Picker.Column>
57
- </Picker>
58
- </div>
59
- )
60
- })
61
-
62
- export default CategoryItemIOSWheelSelector