@hanzo/commerce 7.3.0 → 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,35 +1,35 @@
1
- import {
2
- ShoppingCart,
3
- Menu,
4
- ChevronLeft,
5
- ChevronRight,
6
- Loader2,
7
- Check,
8
- Plus,
9
- Minus,
10
- ChevronDown,
11
- ChevronsLeft,
12
- ChevronsRight,
13
- Image,
14
- Trash2,
15
- Search,
16
- Barcode
17
- } from "lucide-react"
18
-
19
- export default {
20
- shoppingCart: ShoppingCart,
21
- menu: Menu,
22
- chevronLeft: ChevronLeft,
23
- chevronRight: ChevronRight,
24
- spinner: Loader2,
25
- check: Check,
26
- plus: Plus,
27
- minus: Minus,
28
- chevronDown: ChevronDown,
29
- chevronsLeft: ChevronsLeft,
30
- chevronsRight: ChevronsRight,
31
- placeholder: Image,
32
- trash: Trash2,
33
- search: Search,
34
- barcode: Barcode
1
+ import {
2
+ ShoppingCart,
3
+ Menu,
4
+ ChevronLeft,
5
+ ChevronRight,
6
+ Loader2,
7
+ Check,
8
+ Plus,
9
+ Minus,
10
+ ChevronDown,
11
+ ChevronsLeft,
12
+ ChevronsRight,
13
+ Image,
14
+ Trash2,
15
+ Search,
16
+ Barcode
17
+ } from "lucide-react"
18
+
19
+ export default {
20
+ shoppingCart: ShoppingCart,
21
+ menu: Menu,
22
+ chevronLeft: ChevronLeft,
23
+ chevronRight: ChevronRight,
24
+ spinner: Loader2,
25
+ check: Check,
26
+ plus: Plus,
27
+ minus: Minus,
28
+ chevronDown: ChevronDown,
29
+ chevronsLeft: ChevronsLeft,
30
+ chevronsRight: ChevronsRight,
31
+ placeholder: Image,
32
+ trash: Trash2,
33
+ search: Search,
34
+ barcode: Barcode
35
35
  }
@@ -1,183 +1,183 @@
1
- 'use client'
2
- import React, { useEffect, useRef } from 'react'
3
- import { reaction, type IReactionDisposer } from 'mobx'
4
- import { observer } from 'mobx-react-lite'
5
-
6
- import { Button, buttonVariants } from '@hanzo/ui/primitives'
7
- import { cn, type VariantProps } from '@hanzo/ui/util'
8
-
9
- import Icons from './Icons'
10
- import type { LineItem } from '../types'
11
- import { sendFBEvent, sendGAEvent } from '../util/analytics'
12
-
13
- const AddToCartWidget: React.FC<{
14
- item: LineItem
15
- disabled?: boolean
16
- className?: string
17
- buttonClx?: string
18
- variant?: 'minimal' | 'primary' | 'primary-smaller' | 'outline'
19
- onQuantityChanged?: (sku: string, oldV: number, newV: number) => void
20
- }> = observer(({
21
- item,
22
- variant='primary',
23
- disabled=false,
24
- className='',
25
- buttonClx='',
26
- onQuantityChanged
27
- }) => {
28
-
29
- const reactionDisposer = useRef<IReactionDisposer | undefined>(undefined)
30
- useEffect(() => {
31
- if (onQuantityChanged) {
32
- reactionDisposer.current = reaction(
33
- () => (item.quantity),
34
- (quantity: number, previous: number) => {
35
- onQuantityChanged(item.sku, quantity, previous)
36
- }
37
- )
38
- }
39
- return () => {
40
- if (reactionDisposer.current) {
41
- reactionDisposer.current()
42
- }
43
- }
44
- }, [])
45
-
46
- const ROUNDED_VAL = 'lg'
47
- // no need to safelist, since its used widely
48
- const ROUNDED_CLX = ` rounded-${ROUNDED_VAL} `
49
-
50
- const ghost = variant === 'minimal'
51
- const outline = variant === 'outline'
52
- const primary = variant === 'primary'
53
- const priSmaller = variant === 'primary-smaller'
54
-
55
- let iconClx = ghost ? 'h-4 w-4 md:h-3 md:w-3 text-muted-3 ' : (priSmaller ? 'h-4 w-6 px-0.5 opacity-70' : 'h-5 w-7 px-1 opacity-70 ')
56
- iconClx += ghost ? 'group-hover:text-foreground' : 'group-hover:opacity-100'
57
-
58
- let digitClx = ghost ? 'px-2 md:px-0.5 ' : 'sm:px-2 font-semibold '
59
- digitClx += (ghost || outline) ? 'text-foreground ' : 'text-primary-fg '
60
-
61
- if (disabled) {
62
- return (
63
- <div className={cn('flex flex-row items-stretch' + ROUNDED_CLX + (!(primary || priSmaller) ? 'bg-transparent' : 'bg-primary'), className)}>
64
- <div className={'text-sm flex items-center cursor-default ' + digitClx} >{item.quantity}</div>
65
- </div>
66
- )
67
- }
68
-
69
- const inc = (event: React.MouseEvent<HTMLElement>) => {
70
- item.increment()
71
- event.stopPropagation() // in case we're part of a larger selection UI
72
- sendGAEvent('add_to_cart', {
73
- items: [{
74
- item_id: item.sku,
75
- item_name: item.title,
76
- item_category: item.familyId,
77
- price: item.price,
78
- quantity: item.quantity
79
- }],
80
- value: item.price,
81
- currency: 'USD',
82
- })
83
- sendFBEvent('AddToCart', {
84
- content_ids: [item.sku],
85
- contents: [{
86
- id: item.sku,
87
- quantity: item.quantity
88
- }],
89
- content_name: item.title,
90
- value: item.price,
91
- currency: 'USD',
92
- })
93
- }
94
-
95
- const dec = (event: React.MouseEvent<HTMLElement>) => {
96
- item.decrement()
97
- event.stopPropagation() // in case we're part of a larger selection UI
98
- sendGAEvent('remove_from_cart', {
99
- items: [{
100
- item_id: item.sku,
101
- item_name: item.title,
102
- item_category: item.familyId,
103
- price: item.price,
104
- quantity: item.quantity
105
- }],
106
- value: item.price,
107
- currency: 'USD',
108
- })
109
- }
110
-
111
- return ( item.isInCart ? (
112
- <div className={cn(
113
- 'flex flex-row items-stretch justify-between ',
114
- // should match 'xs' and 'default' button heights
115
- (ghost || priSmaller ? 'h-8' : 'h-9'),
116
- ROUNDED_CLX,
117
- (primary || priSmaller ? 'bg-primary' : 'bg-transparent'),
118
- (outline ? 'border border-muted' : ''),
119
- className
120
- )}>
121
- <Button
122
- aria-label={'Remove a ' + item.title + ' from the cart'}
123
- size={ghost || priSmaller ? 'xs' : 'default'}
124
- variant={primary || priSmaller ? 'primary' : 'ghost'}
125
- rounded={ghost ? 'full' : ROUNDED_VAL}
126
- className={cn(
127
- 'lg:min-w-0 lg:px-2 grow justify-start group',
128
- (ghost || priSmaller ? 'px-1' : 'px-2'),
129
- (outline ? 'hover:bg-transparent' : ''),
130
- buttonClx,
131
- 'h-auto self-stretch' // must be smaller than normal
132
- )}
133
- key='left'
134
- onClick={dec}
135
- >
136
- {(item.quantity > 1) ? (
137
- <Icons.minus className={iconClx} aria-hidden='true'/>
138
- ) : (
139
- <Icons.trash className={iconClx} aria-hidden='true'/>
140
- )}
141
- </Button>
142
- <div className={cn(
143
- 'grow-0 shrink-0 flex items-center cursor-default xs:px-2',
144
- priSmaller || ghost ? 'text-xs' : 'text-sm',
145
- digitClx
146
- )}>
147
- {item.quantity}{ghost ? '' : ' in Bag'}
148
- </div>
149
- <Button
150
- aria-label={'Add another ' + item.title + ' to the cart'}
151
- size={ghost || priSmaller ? 'xs' : 'default'}
152
-
153
- variant={primary || priSmaller ? 'primary' : 'ghost'}
154
- rounded={ghost ? 'full' : ROUNDED_VAL}
155
- className={cn(
156
- 'lg:min-w-0 lg:px-2 grow justify-end group',
157
- (ghost || priSmaller ? 'px-1' : 'px-2'),
158
- (outline ? 'hover:bg-transparent' : ''),
159
- buttonClx,
160
- 'h-auto self-stretch' // must be smaller than normal
161
- )}
162
- onClick={inc}
163
- key='right'
164
- >
165
- <Icons.plus className={iconClx} aria-hidden='true'/>
166
- </Button>
167
- </div>
168
- ) : (
169
- <Button
170
- aria-label={'Add a ' + item.title + ' to cart'}
171
- size={ghost || priSmaller ? 'xs' : 'default'}
172
- variant={ghost ? 'ghost' : (primary || priSmaller ? 'primary' : 'outline')}
173
- rounded={ROUNDED_VAL}
174
- className={cn(buttonClx, className)}
175
- onClick={inc}
176
- >
177
- <span className='m1-1'>Add</span>
178
- <Icons.plus className='h-5 w-5 ml-1' aria-hidden='true'/>
179
- </Button>
180
- ))
181
- })
182
-
183
- export default AddToCartWidget
1
+ 'use client'
2
+ import React, { useEffect, useRef } from 'react'
3
+ import { reaction, type IReactionDisposer } from 'mobx'
4
+ import { observer } from 'mobx-react-lite'
5
+
6
+ import { Button, buttonVariants } from '@hanzo/ui/primitives'
7
+ import { cn, type VariantProps } from '@hanzo/ui/util'
8
+
9
+ import Icons from './Icons'
10
+ import type { LineItem } from '../types'
11
+ import { sendFBEvent, sendGAEvent } from '../util/analytics'
12
+
13
+ const AddToCartWidget: React.FC<{
14
+ item: LineItem
15
+ disabled?: boolean
16
+ className?: string
17
+ buttonClx?: string
18
+ variant?: 'minimal' | 'primary' | 'primary-smaller' | 'outline'
19
+ onQuantityChanged?: (sku: string, oldV: number, newV: number) => void
20
+ }> = observer(({
21
+ item,
22
+ variant='primary',
23
+ disabled=false,
24
+ className='',
25
+ buttonClx='',
26
+ onQuantityChanged
27
+ }) => {
28
+
29
+ const reactionDisposer = useRef<IReactionDisposer | undefined>(undefined)
30
+ useEffect(() => {
31
+ if (onQuantityChanged) {
32
+ reactionDisposer.current = reaction(
33
+ () => (item.quantity),
34
+ (quantity: number, previous: number) => {
35
+ onQuantityChanged(item.sku, quantity, previous)
36
+ }
37
+ )
38
+ }
39
+ return () => {
40
+ if (reactionDisposer.current) {
41
+ reactionDisposer.current()
42
+ }
43
+ }
44
+ }, [])
45
+
46
+ const ROUNDED_VAL = 'lg'
47
+ // no need to safelist, since its used widely
48
+ const ROUNDED_CLX = ` rounded-${ROUNDED_VAL} `
49
+
50
+ const ghost = variant === 'minimal'
51
+ const outline = variant === 'outline'
52
+ const primary = variant === 'primary'
53
+ const priSmaller = variant === 'primary-smaller'
54
+
55
+ let iconClx = ghost ? 'h-4 w-4 md:h-3 md:w-3 text-muted-3 ' : (priSmaller ? 'h-4 w-6 px-0.5 opacity-70' : 'h-5 w-7 px-1 opacity-70 ')
56
+ iconClx += ghost ? 'group-hover:text-foreground' : 'group-hover:opacity-100'
57
+
58
+ let digitClx = ghost ? 'px-2 md:px-0.5 ' : 'sm:px-2 font-semibold '
59
+ digitClx += (ghost || outline) ? 'text-foreground ' : 'text-primary-fg '
60
+
61
+ if (disabled) {
62
+ return (
63
+ <div className={cn('flex flex-row items-stretch' + ROUNDED_CLX + (!(primary || priSmaller) ? 'bg-transparent' : 'bg-primary'), className)}>
64
+ <div className={'text-sm flex items-center cursor-default ' + digitClx} >{item.quantity}</div>
65
+ </div>
66
+ )
67
+ }
68
+
69
+ const inc = (event: React.MouseEvent<HTMLElement>) => {
70
+ item.increment()
71
+ event.stopPropagation() // in case we're part of a larger selection UI
72
+ sendGAEvent('add_to_cart', {
73
+ items: [{
74
+ item_id: item.sku,
75
+ item_name: item.title,
76
+ item_category: item.familyId,
77
+ price: item.price,
78
+ quantity: item.quantity
79
+ }],
80
+ value: item.price,
81
+ currency: 'USD',
82
+ })
83
+ sendFBEvent('AddToCart', {
84
+ content_ids: [item.sku],
85
+ contents: [{
86
+ id: item.sku,
87
+ quantity: item.quantity
88
+ }],
89
+ content_name: item.title,
90
+ value: item.price,
91
+ currency: 'USD',
92
+ })
93
+ }
94
+
95
+ const dec = (event: React.MouseEvent<HTMLElement>) => {
96
+ item.decrement()
97
+ event.stopPropagation() // in case we're part of a larger selection UI
98
+ sendGAEvent('remove_from_cart', {
99
+ items: [{
100
+ item_id: item.sku,
101
+ item_name: item.title,
102
+ item_category: item.familyId,
103
+ price: item.price,
104
+ quantity: item.quantity
105
+ }],
106
+ value: item.price,
107
+ currency: 'USD',
108
+ })
109
+ }
110
+
111
+ return ( item.isInCart ? (
112
+ <div className={cn(
113
+ 'flex flex-row items-stretch justify-between ',
114
+ // should match 'xs' and 'default' button heights
115
+ (ghost || priSmaller ? 'h-8' : 'h-9'),
116
+ ROUNDED_CLX,
117
+ (primary || priSmaller ? 'bg-primary' : 'bg-transparent'),
118
+ (outline ? 'border border-muted' : ''),
119
+ className
120
+ )}>
121
+ <Button
122
+ aria-label={'Remove a ' + item.title + ' from the cart'}
123
+ size={ghost || priSmaller ? 'xs' : 'default'}
124
+ variant={primary || priSmaller ? 'primary' : 'ghost'}
125
+ rounded={ghost ? 'full' : ROUNDED_VAL}
126
+ className={cn(
127
+ 'lg:min-w-0 lg:px-2 grow justify-start group',
128
+ (ghost || priSmaller ? 'px-1' : 'px-2'),
129
+ (outline ? 'hover:bg-transparent' : ''),
130
+ buttonClx,
131
+ 'h-auto self-stretch' // must be smaller than normal
132
+ )}
133
+ key='left'
134
+ onClick={dec}
135
+ >
136
+ {(item.quantity > 1) ? (
137
+ <Icons.minus className={iconClx} aria-hidden='true'/>
138
+ ) : (
139
+ <Icons.trash className={iconClx} aria-hidden='true'/>
140
+ )}
141
+ </Button>
142
+ <div className={cn(
143
+ 'grow-0 shrink-0 flex items-center cursor-default xs:px-2',
144
+ priSmaller || ghost ? 'text-xs' : 'text-sm',
145
+ digitClx
146
+ )}>
147
+ {item.quantity}{ghost ? '' : ' in Bag'}
148
+ </div>
149
+ <Button
150
+ aria-label={'Add another ' + item.title + ' to the cart'}
151
+ size={ghost || priSmaller ? 'xs' : 'default'}
152
+
153
+ variant={primary || priSmaller ? 'primary' : 'ghost'}
154
+ rounded={ghost ? 'full' : ROUNDED_VAL}
155
+ className={cn(
156
+ 'lg:min-w-0 lg:px-2 grow justify-end group',
157
+ (ghost || priSmaller ? 'px-1' : 'px-2'),
158
+ (outline ? 'hover:bg-transparent' : ''),
159
+ buttonClx,
160
+ 'h-auto self-stretch' // must be smaller than normal
161
+ )}
162
+ onClick={inc}
163
+ key='right'
164
+ >
165
+ <Icons.plus className={iconClx} aria-hidden='true'/>
166
+ </Button>
167
+ </div>
168
+ ) : (
169
+ <Button
170
+ aria-label={'Add a ' + item.title + ' to cart'}
171
+ size={ghost || priSmaller ? 'xs' : 'default'}
172
+ variant={ghost ? 'ghost' : (primary || priSmaller ? 'primary' : 'outline')}
173
+ rounded={ROUNDED_VAL}
174
+ className={cn(buttonClx, className)}
175
+ onClick={inc}
176
+ >
177
+ <span className='m1-1'>Add</span>
178
+ <Icons.plus className='h-5 w-5 ml-1' aria-hidden='true'/>
179
+ </Button>
180
+ ))
181
+ })
182
+
183
+ export default AddToCartWidget