@hanzo/commerce 1.0.8 → 1.0.9

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,10 +2,7 @@ export { default as AddToCartWidget } from './add-to-cart-widget'
2
2
  export { default as Cart } from './cart'
3
3
  export { default as CartLineItem } from './cart-line-item'
4
4
  export { default as FacetsWidget } from './facets-widget'
5
- export { default as FacetTogglesWidget,
6
- type FacetMutatorSingle,
7
- type FacetMutatorMultiple
8
- } from './facet-toggles-widget'
5
+ export { default as FacetTogglesWidget } from './facet-toggles-widget'
9
6
  export { default as ProductCard } from './product-card'
10
7
  export { default as ProductSelectionMobilePicker } from './product-selection-mobile-picker'
11
8
  export { default as ProductSelectionRadioGroup } from './product-selection-radio-group'
@@ -56,7 +56,7 @@ const SelectCategoryAndItemWidget: React.FC<{
56
56
  <FacetTogglesWidget
57
57
  facetValues={categoryLevelValues}
58
58
  mutator={{
59
- val: currentFacetToken.get(),
59
+ get: currentFacetToken.get, // computed's are accessed through their get()
60
60
  set: onFacetTokenChanged
61
61
  }}
62
62
  />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/commerce",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Library with shopping cart components.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -29,17 +29,18 @@
29
29
  "dependencies": {
30
30
  "@hookform/resolvers": "^3.3.2",
31
31
  "lucide-react": "^0.307.0",
32
+ "next-usequerystate": "^1.17.0",
32
33
  "react-mobile-picker": "^1.0.0"
33
34
  },
34
35
  "peerDependencies": {
35
- "@hanzo/ui": "^1.0.8",
36
36
  "@hanzo/auth": "^1.0.9",
37
- "next": "^14.1.0",
38
- "react": "^18.2.0",
39
- "react-dom": "^18.2.0",
37
+ "@hanzo/ui": "^1.0.8",
38
+ "firebase": "^10.8.0",
40
39
  "mobx": "^6.12.0",
41
40
  "mobx-react-lite": "^4.0.5",
42
- "firebase": "^10.8.0"
41
+ "next": "^14.1.0",
42
+ "react": "^18.2.0",
43
+ "react-dom": "^18.2.0"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/react": "^18.2.48",
@@ -64,7 +64,7 @@ class StandaloneCommerceService
64
64
  currentItem: computed,
65
65
  item: computed,
66
66
  specifiedCategories: computed,
67
- facets: computed
67
+ facetsValue: computed
68
68
  /* NOT setFacets. It implements it's action mechanism */
69
69
  })
70
70
 
@@ -130,8 +130,12 @@ class StandaloneCommerceService
130
130
  return this.specifiedCategories
131
131
  }
132
132
 
133
- get facets(): FacetsValue {
134
- return this._selectedFacets
133
+ get facetsValue(): FacetsValue {
134
+ const result: FacetsValue = {}
135
+ for( let level in this._selectedFacets ) {
136
+ result[level] = [...this._selectedFacets[level]]
137
+ }
138
+ return result
135
139
  }
136
140
 
137
141
  get specifiedCategories(): Category[] {
package/util/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  export function toTitleCase(str: string) {
2
3
  return str.replace(
3
4
  /\w\S*/g,
@@ -23,3 +24,5 @@ export function formatPrice(price: number): string {
23
24
  currency: 'USD',
24
25
  });
25
26
  }
27
+
28
+ export { default as useSkuAndFacetParams } from './use-sku-and-facet-params'
@@ -0,0 +1,157 @@
1
+ import {
2
+ useEffect,
3
+ useRef,
4
+ } from 'react'
5
+ import { autorun, toJS, type IReactionDisposer } from 'mobx'
6
+
7
+ import {
8
+ useQueryState,
9
+ parseAsString,
10
+ parseAsBoolean,
11
+ } from 'next-usequerystate'
12
+
13
+ import type { Category, FacetsValue, StringMutator } from '../types'
14
+ import { useCommerce } from '../service'
15
+
16
+ interface GetMutator {
17
+ (level: 1 | 2): StringMutator
18
+ }
19
+
20
+ const useSkuAndFacetParams = (
21
+ setLoading?: (l: boolean) => void
22
+ ) => {
23
+
24
+ const cmmc = useCommerce()
25
+
26
+ const encRef = useRef<{
27
+ category: Category | undefined
28
+ usingSkuMode: boolean
29
+ autoRunDisposer: IReactionDisposer | undefined
30
+ }>({
31
+ category: undefined,
32
+ usingSkuMode: false,
33
+ autoRunDisposer: undefined,
34
+ })
35
+
36
+ const [level1, setLevel1] = useQueryState('lev1',
37
+ parseAsString.withDefault('').withOptions({ clearOnDefault: true })
38
+ )
39
+ const [level2, setLevel2] = useQueryState('lev2',
40
+ parseAsString.withDefault('').withOptions({ clearOnDefault: true })
41
+ )
42
+
43
+ const [skuParam, setSkuParam] = useQueryState('sku')
44
+ const [addParam, setAddParam] = useQueryState('add',
45
+ parseAsBoolean.withDefault(false).withOptions({ clearOnDefault: true })
46
+ )
47
+
48
+ let message = ''
49
+
50
+ const directMutator: GetMutator = (level: 1 | 2): StringMutator => {
51
+
52
+ const setLevel = (value: string, level: 1 | 2 ): void => {
53
+ const facets = cmmc.facetsValue
54
+ facets[level] = [value]
55
+ cmmc.setFacets(facets)
56
+ }
57
+
58
+ const getLevelValueSafe = (level: 1 | 2): string | null => {
59
+ const facets = cmmc.facetsValue
60
+ if (!(level in facets) || facets[level].length === 0 ) {
61
+ return null
62
+ }
63
+ return facets[level][0]
64
+ }
65
+
66
+ return {
67
+ get: () => (getLevelValueSafe(level)),
68
+ set: (v: string) => {setLevel(v, level)}
69
+ }
70
+ }
71
+
72
+ const paramsMutator: GetMutator = (level: 1 | 2): StringMutator => {
73
+ return level === 1 ? {
74
+ get: () => (level1),
75
+ set: setLevel1
76
+ } : {
77
+ get: () => (level2),
78
+ set: setLevel2
79
+ }
80
+ }
81
+
82
+ useEffect(() => {
83
+
84
+ const setCurrentCategoryFromSku = (sku: string) => {
85
+ const toks: string[] = sku.split('-')
86
+ const categories = cmmc.setFacets({
87
+ 1: [toks[1]],
88
+ 2: [toks[2]]
89
+ })
90
+ encRef.current.category = categories[0]
91
+ }
92
+
93
+ if (skuParam) {
94
+ cmmc.setCurrentItem(skuParam)
95
+ if (addParam && cmmc.currentItem!.quantity === 0) {
96
+ cmmc.currentItem!.increment()
97
+ setAddParam(false)
98
+ }
99
+ // Marks that we've been here so no need to
100
+ // create an autorun() instance twice.
101
+ if (!encRef.current.usingSkuMode) {
102
+ setCurrentCategoryFromSku(skuParam)
103
+ encRef.current.autoRunDisposer = autorun(() => {
104
+ if (cmmc.currentItem && cmmc.currentItem.sku !== skuParam) {
105
+ setSkuParam(cmmc.currentItem.sku)
106
+ }
107
+ })
108
+ }
109
+ encRef.current.usingSkuMode = true
110
+ }
111
+ else if (encRef.current.category) {
112
+ //const catMutators = [{val: level1, set: setLevel1} , {val: level2, set: setLevel2}]
113
+ cmmc.setCurrentItem(encRef.current.category.products[0].sku)
114
+ }
115
+ setLoading && setLoading(false)
116
+ }, [skuParam, encRef.current.category])
117
+
118
+ // supposed to be when component unmounts
119
+ useEffect(() => (() => {
120
+ if (encRef.current.autoRunDisposer) {
121
+ //encRef.current.autoRunDisposer() // no idea why this seems to be called prematurely and so many times <shrug>
122
+ }
123
+ }), [])
124
+
125
+
126
+ // Level Params Mode
127
+ useEffect(() => {
128
+
129
+ if (encRef.current.usingSkuMode) return
130
+
131
+ const facets: FacetsValue = { }
132
+ if (level1) { facets[1] = [level1] }
133
+ if (level2) { facets[2] = [level2] }
134
+ if (level1 && level2) {
135
+ const categories = cmmc.setFacets(facets)
136
+ if (categories.length > 1) {
137
+ console.error("CAT", categories.map((c) => (c.title)))
138
+ throw new Error ( "CategoryContents: More than one specified Category should never be possible with this UI!")
139
+ }
140
+ encRef.current.category = categories[0]
141
+ }
142
+ else {
143
+ message = 'Please select an option from each group above.'
144
+ }
145
+ setLoading && setLoading(false)
146
+ }, [level1 , level2])
147
+
148
+ return {
149
+ category: encRef.current.category,
150
+ message,
151
+ getMutator: encRef.current.usingSkuMode ?
152
+ directMutator : paramsMutator
153
+ }
154
+
155
+ }
156
+
157
+ export default useSkuAndFacetParams