@hanzo/commerce 7.0.2 → 7.0.4

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.
@@ -9,11 +9,9 @@ import { cn, type VariantProps } from '@hanzo/ui/util'
9
9
  import Icons from './Icons'
10
10
  import type { LineItem } from '../types'
11
11
  import { sendFBEvent, sendGAEvent } from '../util/analytics'
12
- import { useCommerceUI } from '..'
13
12
 
14
13
  const AddToCartWidget: React.FC<{
15
14
  item: LineItem
16
- registerAdd?: boolean
17
15
  disabled?: boolean
18
16
  className?: string
19
17
  buttonClx?: string
@@ -22,26 +20,19 @@ const AddToCartWidget: React.FC<{
22
20
  }> = observer(({
23
21
  item,
24
22
  variant='primary',
25
- registerAdd=true,
26
23
  disabled=false,
27
24
  className='',
28
25
  buttonClx='',
29
26
  onQuantityChanged
30
27
  }) => {
31
28
 
32
- const ui = useCommerceUI()
33
-
34
29
  const reactionDisposer = useRef<IReactionDisposer | undefined>(undefined)
35
-
36
30
  useEffect(() => {
37
- // Only tell the micro-drawer
38
- // if we're not part of the cart ui,
39
- // or part of the main drawer.
40
- if (registerAdd && variant !== 'minimal') {
31
+ if (onQuantityChanged) {
41
32
  reactionDisposer.current = reaction(
42
33
  () => (item.quantity),
43
34
  (quantity: number, previous: number) => {
44
- ui.itemQuantityChanged(item, quantity, previous)
35
+ onQuantityChanged(item.sku, quantity, previous)
45
36
  }
46
37
  )
47
38
  }
@@ -75,11 +66,7 @@ const AddToCartWidget: React.FC<{
75
66
  }
76
67
 
77
68
  const inc = () => {
78
- const old = item.quantity
79
69
  item.increment()
80
- if (onQuantityChanged) {
81
- onQuantityChanged(item.sku, old, old + 1)
82
- }
83
70
  sendGAEvent('add_to_cart', {
84
71
  items: [{
85
72
  item_id: item.sku,
@@ -104,11 +91,7 @@ const AddToCartWidget: React.FC<{
104
91
  }
105
92
 
106
93
  const dec = () => {
107
- const old = item.quantity
108
94
  item.decrement()
109
- if (onQuantityChanged) {
110
- onQuantityChanged(item.sku, old, old - 1)
111
- }
112
95
  sendGAEvent('remove_from_cart', {
113
96
  items: [{
114
97
  item_id: item.sku,
@@ -86,7 +86,7 @@ const BuyCard: React.FC<{
86
86
 
87
87
  useEffect(() => {
88
88
 
89
- let requestedFamily = cmmc.getFamily(skuPath)
89
+ let requestedFamily = cmmc.getFamilyById(skuPath)
90
90
  let requestedNode = requestedFamily ? undefined : cmmc.getNodeAtPath(skuPath)
91
91
  let initialFamily = undefined
92
92
 
@@ -137,7 +137,7 @@ const BuyCard: React.FC<{
137
137
  },
138
138
  (famId) => {
139
139
  if (famId && famId !== cmmc.currentItem?.familyId) {
140
- const fam = cmmc.getFamily(famId)
140
+ const fam = cmmc.getFamilyById(famId)
141
141
  if (fam) {
142
142
  cmmc.setCurrentItem(fam.products[0].sku)
143
143
  }
@@ -248,7 +248,6 @@ const BuyCard: React.FC<{
248
248
  {(cmmc.currentItem) && (
249
249
  <AddToCartWidget
250
250
  item={cmmc.currentItem}
251
- registerAdd={false}
252
251
  onQuantityChanged={onQuantityChanged}
253
252
  className={cn('min-w-[160px] mx-auto mt-4', (scroll ? 'shrink-0' : ''), addWidgetClx)}
254
253
  />
@@ -203,7 +203,6 @@ const CarouselBuyCard: React.FC<{
203
203
  <div className={clx}>
204
204
  <AddToCartWidget
205
205
  item={cmmc.currentItem}
206
- registerAdd={true}
207
206
  onQuantityChanged={onQuantityChanged}
208
207
  variant={cmmc.cartEmpty ? 'primary' : 'outline'}
209
208
  className={addBtnClx}
@@ -61,7 +61,7 @@ const CartLineItem: React.FC<{
61
61
  </div>
62
62
  <div className='flex flex-row items-center justify-between w-full'>
63
63
  <div className='flex flex-row items-center'>
64
- <AddToCartWidget variant='minimal' registerAdd={false} item={item} buttonClx='!h-8 md:!h-6' />
64
+ <AddToCartWidget variant='minimal' item={item} buttonClx='!h-8 md:!h-6' />
65
65
  {item.quantity > 1 && (<span className='pl-2.5'>{'@' + formatCurrencyValue(item.price)}</span>)}
66
66
  </div>
67
67
  <div className='flex flex-row gap-1 items-center justify-end'>
@@ -1,5 +1,4 @@
1
1
  export { default as AddToCartWidget } from './add-to-cart-widget'
2
- export { default as BuyButton } from './buy/buy-button'
3
2
  export { default as CarouselBuyCard } from './buy/carousel-buy-card'
4
3
 
5
4
  export { default as CartAccordian } from './cart/cart-accordian'
package/context/index.tsx CHANGED
@@ -4,7 +4,6 @@ import React, {
4
4
  useContext,
5
5
  useRef,
6
6
  type PropsWithChildren,
7
- useEffect
8
7
  } from 'react'
9
8
 
10
9
  // https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
@@ -15,21 +14,11 @@ import type { ServiceOptions } from '..'
15
14
  import type CommerceService from '../types/commerce-service'
16
15
  import getInstance from '../service/get-instance'
17
16
  import type { Family, CategoryNode, SelectionUISpecifier } from '../types'
18
- import { type CommerceUI, CommerceUIStore } from './commerce-ui'
19
17
 
20
- type CommerceContextValue = {
21
- service: CommerceService
22
- ui: CommerceUI
23
- }
24
-
25
- const CommerceContext = createContext<CommerceContextValue | undefined>(undefined)
18
+ const CommerceContext = createContext<CommerceService | undefined>(undefined)
26
19
 
27
20
  const useCommerce = (): CommerceService => {
28
- return (useContext(CommerceContext) as CommerceContextValue)?.service
29
- }
30
-
31
- const useCommerceUI = (): CommerceUI => {
32
- return (useContext(CommerceContext) as CommerceContextValue)?.ui
21
+ return useContext(CommerceContext) as CommerceService
33
22
  }
34
23
 
35
24
  const CommerceProvider: React.FC<PropsWithChildren & {
@@ -37,29 +26,17 @@ const CommerceProvider: React.FC<PropsWithChildren & {
37
26
  rootNode: CategoryNode
38
27
  options?: ServiceOptions
39
28
  uiSpecs?: Record<string, SelectionUISpecifier>
40
- DEBUG_NO_TICK?: boolean
41
29
  }> = ({
42
30
  children,
43
31
  families,
44
32
  rootNode,
45
33
  options,
46
- uiSpecs,
47
- DEBUG_NO_TICK=false
34
+ uiSpecs
48
35
  }) => {
49
36
 
50
- useEffect(() => {
51
- if (DEBUG_NO_TICK) return
52
- const intervalId = setInterval(() => {
53
- (valueRef.current.ui as CommerceUIStore).tick()
54
- }, 250)
55
- return () => { clearInterval(intervalId) }
56
- }, [])
57
-
58
37
  // TODO: Inject Promo fixture here from siteDef
59
38
  const service = getInstance(families, rootNode, options, uiSpecs)
60
- const ui = new CommerceUIStore(service)
61
-
62
- const valueRef = useRef<CommerceContextValue>({service, ui})
39
+ const valueRef = useRef<CommerceService>(service)
63
40
 
64
41
  return (
65
42
  <CommerceContext.Provider value={valueRef.current}>
@@ -70,7 +47,6 @@ const CommerceProvider: React.FC<PropsWithChildren & {
70
47
 
71
48
  export {
72
49
  useCommerce,
73
- useCommerceUI,
74
50
  CommerceProvider
75
51
  }
76
52
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/commerce",
3
- "version": "7.0.2",
3
+ "version": "7.0.4",
4
4
  "description": "e-commerce framework.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -26,7 +26,8 @@
26
26
  },
27
27
  "exports": {
28
28
  ".": "./index.ts",
29
- "./types": "./types/index.ts"
29
+ "./types": "./types/index.ts",
30
+ "./service": "./service/index.ts"
30
31
  },
31
32
  "dependencies": {
32
33
  "ethers": "^6.12.0",
@@ -35,8 +36,8 @@
35
36
  "square": "^35.1.0"
36
37
  },
37
38
  "peerDependencies": {
38
- "@hanzo/auth": "^2.4.5",
39
- "@hanzo/ui": "^3.7.0",
39
+ "@hanzo/auth": "^2.4.6",
40
+ "@hanzo/ui": "^3.7.23",
40
41
  "@hookform/resolvers": "^3.3.4",
41
42
  "@radix-ui/react-radio-group": "^1.1.3",
42
43
  "firebase": "^10.8.0",
@@ -45,14 +46,14 @@
45
46
  "mobx-react-lite": "^4.0.5",
46
47
  "mobx-utils": "^6.0.8",
47
48
  "next": "14.1.3",
48
- "react": "^18.2.0",
49
- "react-dom": "^18.2.0",
50
- "react-hook-form": "^7.51.3",
51
- "zod": "3.21.4"
49
+ "react": "^18.3.1",
50
+ "react-dom": "^18.3.1",
51
+ "react-hook-form": "^7.51.4",
52
+ "zod": "3.23.8"
52
53
  },
53
54
  "devDependencies": {
54
- "@types/react": "^18.2.79",
55
- "@types/react-dom": "^18.2.25",
55
+ "@types/react": "^18.3.1",
56
+ "@types/react-dom": "^18.3.0",
56
57
  "cross-fetch": "^4.0.0",
57
58
  "typescript": "^5.4.5"
58
59
  }
@@ -81,7 +81,7 @@ class ActualLineItem
81
81
  const title = this.fullTitle ?
82
82
  this.fullTitle
83
83
  :
84
- ((cmmc.getFamily(this.familyId)?.title ?? this.familyTitle) + ', ' + this.optionLabel)
84
+ ((cmmc.getFamilyById(this.familyId)?.title ?? this.familyTitle) + ', ' + this.optionLabel)
85
85
 
86
86
  return({
87
87
  sku: this.sku,
@@ -110,7 +110,7 @@ class StandaloneService
110
110
  })
111
111
  }
112
112
 
113
- getFamily(id: string): Family | undefined {
113
+ getFamilyById(id: string): Family | undefined {
114
114
  return this._familyMap.get(id)
115
115
  }
116
116
 
@@ -343,14 +343,13 @@ class StandaloneService
343
343
  this._promo = promo
344
344
  }
345
345
 
346
- setCurrentItem(skuToFind: string | undefined): boolean {
346
+ getItemBySku = (skuToFind: string | undefined): LineItem | undefined => {
347
347
 
348
348
  if (skuToFind === undefined || skuToFind.length === 0) {
349
- this._currentItem = undefined
350
- return true
349
+ return undefined
351
350
  }
352
- // self calling function
353
- this._currentItem = ((): ActualLineItem | undefined => {
351
+ // Self-calling
352
+ const found = ((): ActualLineItem | undefined => {
354
353
 
355
354
  const familiesTried: string[] = []
356
355
  if (this.selectedFamilies && this.selectedFamilies.length > 0) {
@@ -370,8 +369,19 @@ class StandaloneService
370
369
  }
371
370
  }
372
371
  return undefined
373
- })(); // necessary semi
372
+ })(); // Self-calling, necessary semi
373
+
374
+ return found
375
+ }
374
376
 
377
+ setCurrentItem = (skuToFind: string | undefined): boolean => {
378
+
379
+ if (skuToFind === undefined || skuToFind.length === 0) {
380
+ this._currentItem = undefined
381
+ return true
382
+ }
383
+ // self calling function
384
+ this._currentItem = this.getItemBySku(skuToFind) as ActualLineItem | undefined
375
385
  this.setCurrentFamily(this._currentItem ? this._currentItem.familyId : undefined)
376
386
  return !!this._currentItem
377
387
  }
@@ -0,0 +1 @@
1
+ export * from './debug'
package/tsconfig.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
- "extends": "../tsconfig.hanzo-modules.base.json",
2
+ "extends": "../tsconfig.hanzo.base.json",
3
3
  "include": [
4
4
  "**/*.ts",
5
- "**/*.tsx", "types/string-mutator.ts",
5
+ "**/*.tsx",
6
6
  ],
7
7
  "exclude": [
8
8
  "node_modules",
@@ -112,7 +112,8 @@ interface CommerceService extends ObsLineItemRef, ObsFamilyRef {
112
112
  get currentFamily(): Family | undefined
113
113
 
114
114
  // utility
115
- getFamily(id: string): Family | undefined
115
+ getFamilyById(id: string): Family | undefined
116
+ getItemBySku(sku: string): LineItem | undefined
116
117
  }
117
118
 
118
119
 
@@ -1,35 +0,0 @@
1
- 'use client'
2
- import React, {type PropsWithChildren} from 'react'
3
-
4
- import { Button, buttonVariants } from '@hanzo/ui/primitives'
5
- import { type VariantProps } from '@hanzo/ui/util'
6
-
7
- import { cn } from '@hanzo/ui/util'
8
- import { useCommerceUI } from '../..'
9
-
10
- const BuyButton: React.FC<
11
- PropsWithChildren &
12
- VariantProps<typeof buttonVariants> &
13
- {
14
- skuPath: string
15
- className?: string
16
- }
17
- > = ({
18
- skuPath,
19
- children,
20
- className='',
21
- ...rest
22
- }) => {
23
-
24
- const ui = useCommerceUI()
25
- const handleClick = () => { ui.showBuyOptions(skuPath) }
26
-
27
- return (
28
- <Button onClick={handleClick} {...rest} className={cn(className, '')}>
29
- {children}
30
- </Button>
31
- )
32
- }
33
-
34
-
35
- export default BuyButton
@@ -1,101 +0,0 @@
1
- import {
2
- action,
3
- computed,
4
- makeObservable,
5
- observable,
6
- } from 'mobx'
7
- import type { CommerceService, LineItem, ObsLineItemRef } from '../types'
8
-
9
-
10
- interface CommerceUI extends ObsLineItemRef {
11
- showBuyOptions: (skuPath: string) => void
12
- hideBuyOptions: () => void
13
- get buyOptionsSkuPath(): string | undefined
14
-
15
- itemQuantityChanged(item: LineItem, val: number, prevVal: number): void
16
- }
17
-
18
- class CommerceUIStore implements CommerceUI {
19
-
20
- static readonly TIMEOUT = 1500
21
- _buyOptionsSkuPath: string | undefined = undefined
22
- _paused: boolean = false
23
- _activeItem: LineItem | undefined = undefined
24
- _lastActivity: number | undefined = undefined
25
- _service: CommerceService
26
-
27
- constructor(s: CommerceService) {
28
- this._service = s
29
- makeObservable(this, {
30
- _buyOptionsSkuPath: observable,
31
- _activeItem: observable.shallow,
32
- showBuyOptions: action,
33
- hideBuyOptions: action,
34
- buyOptionsSkuPath: computed,
35
- itemQuantityChanged: action,
36
- tick: action,
37
- item: computed
38
- })
39
- }
40
-
41
- showBuyOptions = (skuPath: string): void => {
42
- this._service.setCurrentItem(undefined)
43
- this._buyOptionsSkuPath = skuPath
44
- this._paused = true
45
- }
46
-
47
- hideBuyOptions = (): void => {
48
- this._buyOptionsSkuPath = undefined
49
- this._paused = false
50
- if (this._lastActivity) {
51
- this._lastActivity = Date.now()
52
- }
53
- }
54
-
55
- get buyOptionsSkuPath(): string | undefined {
56
- return this._buyOptionsSkuPath
57
- }
58
-
59
- tick = () => {
60
- if (
61
- !this._paused
62
- &&
63
- this._lastActivity
64
- &&
65
- (Date.now() - this._lastActivity >= CommerceUIStore.TIMEOUT)
66
- ) {
67
- this._activeItem = undefined
68
- this._lastActivity = undefined
69
- }
70
- }
71
-
72
- itemQuantityChanged = (item: LineItem, val: number, oldVal: number, ): void => {
73
-
74
- if (val === 0) {
75
- if (this._activeItem?.sku === item.sku) {
76
- this._activeItem = undefined
77
- this._lastActivity = undefined
78
- }
79
- // otherwise ignore
80
- }
81
- else if (val < oldVal) {
82
- if (this._activeItem?.sku === item.sku) {
83
- this._lastActivity = Date.now()
84
- }
85
- // otherwise ignore
86
- }
87
- else {
88
- this._activeItem = item
89
- this._lastActivity = Date.now()
90
- }
91
- }
92
-
93
- get item(): LineItem | undefined {
94
- return this._activeItem
95
- }
96
- }
97
-
98
- export {
99
- CommerceUIStore,
100
- type CommerceUI
101
- }