@hanzo/commerce 1.0.10 → 1.0.12
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.
package/components/cart.tsx
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import React, { type PropsWithChildren, useState } from 'react'
|
|
3
|
+
import { useRouter } from 'next/navigation'
|
|
3
4
|
import { observer } from 'mobx-react-lite'
|
|
4
5
|
|
|
5
6
|
import { Button } from '@hanzo/ui/primitives'
|
|
6
7
|
import { cn } from '@hanzo/ui/util'
|
|
8
|
+
import { useAuth } from '@hanzo/auth/service'
|
|
7
9
|
|
|
8
10
|
import { persistCart, useCommerce } from '../service'
|
|
9
11
|
import { formatPrice } from '../util'
|
|
10
12
|
|
|
11
13
|
import CartLineItem from './cart-line-item'
|
|
12
|
-
import { useRouter } from 'next/navigation'
|
|
13
|
-
import { useAuth } from '@hanzo/auth/service'
|
|
14
|
-
|
|
15
14
|
|
|
16
15
|
const Cart: React.FC<PropsWithChildren & {
|
|
17
16
|
className?: string
|
|
@@ -24,14 +23,14 @@ const Cart: React.FC<PropsWithChildren & {
|
|
|
24
23
|
hideCheckout=false
|
|
25
24
|
}) => {
|
|
26
25
|
const [loadingCheckout, setLoadingCheckout] = useState(false)
|
|
27
|
-
const
|
|
26
|
+
const cmmc = useCommerce()
|
|
28
27
|
const router = useRouter()
|
|
29
28
|
const auth = useAuth()
|
|
30
29
|
|
|
31
30
|
const checkout = async () => {
|
|
32
31
|
setLoadingCheckout(true)
|
|
33
32
|
if (auth.user) {
|
|
34
|
-
await persistCart(
|
|
33
|
+
await persistCart(cmmc.cartItems, auth.user.email)
|
|
35
34
|
}
|
|
36
35
|
router.push('/checkout')
|
|
37
36
|
}
|
|
@@ -41,14 +40,14 @@ const Cart: React.FC<PropsWithChildren & {
|
|
|
41
40
|
{children}
|
|
42
41
|
<div className='mt-2'>
|
|
43
42
|
{!!children && <div className='h-[1px] w-pr-80 mx-auto bg-muted-3'/>}
|
|
44
|
-
{
|
|
43
|
+
{cmmc.cartItems.length === 0 ? (
|
|
45
44
|
<p className='text-center mt-4'>No items in cart</p>
|
|
46
45
|
) : (<>
|
|
47
|
-
{
|
|
48
|
-
<p className='mt-6 text-right border-t pt-1'>TOTAL: {
|
|
46
|
+
{cmmc.cartItems.map((item, i) => (<CartLineItem isMobile={isMobile} item={item} key={item.sku} className='mb-4 sm:mb-2'/>))}
|
|
47
|
+
<p className='mt-6 text-right border-t pt-1'>TOTAL: {cmmc.cartTotal === 0 ? '0' : formatPrice(cmmc.cartTotal)}</p>
|
|
49
48
|
</>)}
|
|
50
49
|
</div>
|
|
51
|
-
{
|
|
50
|
+
{cmmc.cartItems.length > 0 && !hideCheckout && (
|
|
52
51
|
<>
|
|
53
52
|
{!auth.loggedIn ? (
|
|
54
53
|
<Button size='lg' variant='secondary' rounded='lg' className='mt-12 mx-auto' onClick={() => router.push('/login?redirectUrl=checkout')}>Login</Button>
|
|
@@ -31,15 +31,15 @@ const SelectItemInCategoryView: React.FC<React.HTMLAttributes<HTMLDivElement> &
|
|
|
31
31
|
...props
|
|
32
32
|
}) => {
|
|
33
33
|
|
|
34
|
-
const waiting = (): boolean => (isLoading
|
|
34
|
+
const waiting = (): boolean => (isLoading) // keep for convenience for now
|
|
35
35
|
|
|
36
36
|
const CategoryImage: React.FC<{ className?: string }> = ({ className = '' }) => {
|
|
37
37
|
|
|
38
38
|
if (waiting()) {
|
|
39
39
|
// deliberately not Skeleton to have a better overall pulse effect.
|
|
40
40
|
return <div className={cn(
|
|
41
|
-
'bg-level-1 rounded-xl aspect-square ' +
|
|
42
|
-
' min-h-[100px] sm:min-h-[200px] lg:aspect-auto
|
|
41
|
+
'bg-level-1 rounded-xl aspect-square w-full min-h-1 ', // +
|
|
42
|
+
//' min-h-[100px] sm:min-h-[200px] lg:aspect-auto 2xl:w-auto 2xl:aspect-square',
|
|
43
43
|
className)} />
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -49,7 +49,7 @@ const SelectItemInCategoryView: React.FC<React.HTMLAttributes<HTMLDivElement> &
|
|
|
49
49
|
aria-label='Placeholder'
|
|
50
50
|
role='img'
|
|
51
51
|
aria-roledescription='placeholder'
|
|
52
|
-
className={cn('
|
|
52
|
+
className={cn('w-full flex items-center justify-center aspect-square' , className)}
|
|
53
53
|
>
|
|
54
54
|
<Icons.barcode className='h-9 w-9 text-muted' aria-hidden='true' />
|
|
55
55
|
</div>
|
|
@@ -83,13 +83,13 @@ const SelectItemInCategoryView: React.FC<React.HTMLAttributes<HTMLDivElement> &
|
|
|
83
83
|
<Skeleton className={'min-h-[120px] w-pr-60 mx-auto ' + className} />
|
|
84
84
|
) : (
|
|
85
85
|
<div /* id='CV_AVAIL_AMOUNTS' */ className={cn(
|
|
86
|
-
'w-
|
|
86
|
+
'sm:w-pr-80 sm:mx-auto md:w-full flex flex-col justify-start items-center',
|
|
87
87
|
(soleOption ? 'gap-2' : mobilePicker ? 'gap-4' : 'gap-8'),
|
|
88
88
|
className
|
|
89
89
|
)}>
|
|
90
90
|
<div className='w-full flex flex-col justify-start items-center'>
|
|
91
91
|
<h6 className='text-center font-semibold'>{`Available size${soleOption ? '' : 's'}`}</h6>
|
|
92
|
-
<div className={'h-[1px] bg-muted-3 ' + (mobilePicker ? 'w-pr-55' : 'w-pr-
|
|
92
|
+
<div className={'h-[1px] bg-muted-3 ' + (mobilePicker ? 'w-pr-55' : 'w-pr-80') } />
|
|
93
93
|
</div>
|
|
94
94
|
{soleOption ? (
|
|
95
95
|
<p>{category.products[0].titleAsOption}</p>
|
|
@@ -107,8 +107,8 @@ const SelectItemInCategoryView: React.FC<React.HTMLAttributes<HTMLDivElement> &
|
|
|
107
107
|
products={category.products}
|
|
108
108
|
selectedSku={lineItemRef.item?.sku ?? undefined}
|
|
109
109
|
onValueChange={handleItemSelected}
|
|
110
|
-
groupClx='
|
|
111
|
-
itemClx='flex flex-row gap-2 items-center
|
|
110
|
+
groupClx='grid grid-cols-2 gap-0 gap-y-3 gap-x-8 '
|
|
111
|
+
itemClx='flex flex-row gap-2 items-center'
|
|
112
112
|
/>
|
|
113
113
|
)
|
|
114
114
|
)}
|
|
@@ -128,11 +128,11 @@ const SelectItemInCategoryView: React.FC<React.HTMLAttributes<HTMLDivElement> &
|
|
|
128
128
|
waiting() ? (<Skeleton className={'h-12 w-pr-80 mx-auto ' + className} />) : (
|
|
129
129
|
|
|
130
130
|
<div className={cn('flex flex-col justify-start items-center mb-6', className)}>
|
|
131
|
-
<h3 className='text-lg lg:text-
|
|
132
|
-
<span className='xs:inline
|
|
131
|
+
<h3 className='text-base md:text-lg lg:text-2xl md:mt-[2vw] font-nav text-center'>
|
|
132
|
+
<span className='xs:inline md:hidden'>
|
|
133
133
|
{category.title.split(', ').map((s, i) => (<p key={i}>{s}</p>))}
|
|
134
134
|
</span>
|
|
135
|
-
<span className='xs:hidden
|
|
135
|
+
<span className='xs:hidden md:inline '>
|
|
136
136
|
{category.title}
|
|
137
137
|
</span>
|
|
138
138
|
</h3>
|
|
@@ -174,12 +174,17 @@ const SelectItemInCategoryView: React.FC<React.HTMLAttributes<HTMLDivElement> &
|
|
|
174
174
|
) : (
|
|
175
175
|
<div /* id='CV_OUTERMOST' */>
|
|
176
176
|
<div /* id='CV_OUTER' */ className={cn('w-full flex flex-row justify-between items-stretch gap-6 sm:gap-4', className)} {...props}>
|
|
177
|
-
<div /* id='
|
|
178
|
-
<CategoryImage className='' />
|
|
177
|
+
<div /* id='CV_IMAGE_COL_SEP' */ className={'relative ' + (!isLoading ? 'md:hidden sm:min-w-[185px] xl:flex xl:w-pr-40' : '')}>
|
|
178
|
+
<CategoryImage className='w-full' />
|
|
179
179
|
</div>
|
|
180
|
-
<div /* id='CV_CONTENT_COL */ className='w-pr-
|
|
180
|
+
<div /* id='CV_CONTENT_COL */ className='flex flex-col gap-y-6 xl:w-pr-60'>
|
|
181
|
+
<div /* id='CV_MD_IMAGE_AND_TITLE */ className='hidden md:flex xl:hidden flex-row gap-x-3'>
|
|
182
|
+
<CategoryImage className='min-w-pr-30' />
|
|
183
|
+
<TitleArea className='grow' />
|
|
184
|
+
</div>
|
|
185
|
+
|
|
181
186
|
<div /* id='CV_CONTENT' */ className={'flex flex-col gap-2.5 ' + (isLoading ? 'justify-between h-full' : '')}>
|
|
182
|
-
<TitleArea className='' />
|
|
187
|
+
<TitleArea className='md:hidden xl:flex' />
|
|
183
188
|
<Desc className='' />
|
|
184
189
|
</div>
|
|
185
190
|
<div /* id='CV_CTA_AREA_BIG' */ className='hidden lg:flex p-4 flex-col justify-start items-center gap-6'>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/commerce",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "Library with shopping cart components.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"react-mobile-picker": "^1.0.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@hanzo/auth": "^1.0.
|
|
36
|
+
"@hanzo/auth": "^1.0.12",
|
|
37
37
|
"@hanzo/ui": "^1.0.8",
|
|
38
38
|
"firebase": "^10.8.0",
|
|
39
39
|
"mobx": "^6.12.0",
|
|
@@ -30,7 +30,7 @@ interface CommerceService extends ObsLineItemRef {
|
|
|
30
30
|
* "current" is unrelated to what is "specified",
|
|
31
31
|
* ie, facets' values
|
|
32
32
|
* */
|
|
33
|
-
setCurrentItem(sku: string | undefined):
|
|
33
|
+
setCurrentItem(sku: string | undefined): boolean // was valid sku and was set.
|
|
34
34
|
/**
|
|
35
35
|
* For convenience, so widgets can share state.
|
|
36
36
|
* "current" is unrelated to what is "specified",
|
|
@@ -31,7 +31,7 @@ class StandaloneCommerceService
|
|
|
31
31
|
|
|
32
32
|
private _options : StandaloneServiceOptions
|
|
33
33
|
|
|
34
|
-
private
|
|
34
|
+
private _currentItem: LineItem | undefined = undefined
|
|
35
35
|
|
|
36
36
|
constructor(
|
|
37
37
|
categories: Category[],
|
|
@@ -50,20 +50,20 @@ class StandaloneCommerceService
|
|
|
50
50
|
makeObservable<
|
|
51
51
|
StandaloneCommerceService,
|
|
52
52
|
'_selectedFacets' |
|
|
53
|
-
'
|
|
53
|
+
'_currentItem'
|
|
54
54
|
>(this, {
|
|
55
55
|
_selectedFacets : observable.deep,
|
|
56
|
-
|
|
56
|
+
_currentItem: observable,
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
makeObservable(this, {
|
|
60
60
|
cartItems: computed,
|
|
61
61
|
cartTotal: computed,
|
|
62
62
|
specifiedItems: computed,
|
|
63
|
+
specifiedCategories: computed,
|
|
63
64
|
setCurrentItem: action,
|
|
64
65
|
currentItem: computed,
|
|
65
66
|
item: computed,
|
|
66
|
-
specifiedCategories: computed,
|
|
67
67
|
facetsValue: computed
|
|
68
68
|
/* NOT setFacets. It implements it's action mechanism */
|
|
69
69
|
})
|
|
@@ -85,39 +85,46 @@ class StandaloneCommerceService
|
|
|
85
85
|
)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
setCurrentItem(
|
|
89
|
-
|
|
88
|
+
setCurrentItem(skuToFind: string | undefined): boolean {
|
|
89
|
+
|
|
90
|
+
if (skuToFind === undefined || skuToFind.length === 0) {
|
|
91
|
+
this._currentItem = undefined
|
|
92
|
+
return true
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this._currentItem = ((): LineItem | undefined => {
|
|
96
|
+
const categoriesTried: string[] = []
|
|
97
|
+
if (this.specifiedCategories && this.specifiedCategories.length > 0) {
|
|
98
|
+
|
|
99
|
+
for (let category of this.specifiedCategories) {
|
|
100
|
+
categoriesTried.push(category.id)
|
|
101
|
+
const foundItem =
|
|
102
|
+
(category.products as LineItem[]).find((item) => (item.sku === skuToFind))
|
|
103
|
+
if (foundItem) {
|
|
104
|
+
return foundItem
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let foundItem: LineItem | undefined = undefined
|
|
110
|
+
this._categoryMap.forEach((category, categoryId) => {
|
|
111
|
+
if (foundItem) return
|
|
112
|
+
if (categoriesTried.includes(categoryId)) return
|
|
113
|
+
foundItem = (category.products as LineItem[]).find((item) => (item.sku === skuToFind))
|
|
114
|
+
})
|
|
115
|
+
})();
|
|
116
|
+
|
|
117
|
+
return !!this._currentItem
|
|
90
118
|
}
|
|
91
119
|
|
|
120
|
+
|
|
92
121
|
/* ObsLineItemRef */
|
|
93
122
|
get item(): LineItem | undefined {
|
|
94
123
|
return this.currentItem
|
|
95
124
|
}
|
|
96
125
|
|
|
97
126
|
get currentItem(): LineItem | undefined {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const categoriesTried: string[] = []
|
|
101
|
-
if (this.specifiedCategories && this.specifiedCategories.length > 0) {
|
|
102
|
-
|
|
103
|
-
for (let category of this.specifiedCategories) {
|
|
104
|
-
categoriesTried.push(category.id)
|
|
105
|
-
const foundItem =
|
|
106
|
-
(category.products as LineItem[]).find((item) => (item.sku === this._currentItemSku))
|
|
107
|
-
if (foundItem) {
|
|
108
|
-
return foundItem
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
let foundItem: LineItem | undefined = undefined
|
|
114
|
-
this._categoryMap.forEach((category, categoryId) => {
|
|
115
|
-
if (foundItem) return
|
|
116
|
-
if (categoriesTried.includes(categoryId)) return
|
|
117
|
-
foundItem = (category.products as LineItem[]).find((item) => (item.sku === this._currentItemSku))
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
return foundItem
|
|
127
|
+
return this._currentItem
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
setFacets(sel: FacetsValue): Category[] {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useEffect,
|
|
3
3
|
useRef,
|
|
4
|
+
useState,
|
|
4
5
|
} from 'react'
|
|
5
6
|
import { autorun, toJS, type IReactionDisposer } from 'mobx'
|
|
6
7
|
|
|
@@ -13,6 +14,8 @@ import {
|
|
|
13
14
|
import type { Category, FacetsValue, StringMutator } from '../types'
|
|
14
15
|
import { useCommerce } from '../service'
|
|
15
16
|
|
|
17
|
+
const PLEASE_SELECT_FACETS = 'Please select an option from each group above.'
|
|
18
|
+
|
|
16
19
|
interface GetMutator {
|
|
17
20
|
(level: 1 | 2): StringMutator
|
|
18
21
|
}
|
|
@@ -24,11 +27,9 @@ const useSkuAndFacetParams = (
|
|
|
24
27
|
const cmmc = useCommerce()
|
|
25
28
|
|
|
26
29
|
const encRef = useRef<{
|
|
27
|
-
category: Category | undefined
|
|
28
30
|
usingSkuMode: boolean
|
|
29
31
|
autoRunDisposer: IReactionDisposer | undefined
|
|
30
32
|
}>({
|
|
31
|
-
category: undefined,
|
|
32
33
|
usingSkuMode: false,
|
|
33
34
|
autoRunDisposer: undefined,
|
|
34
35
|
})
|
|
@@ -40,12 +41,15 @@ const useSkuAndFacetParams = (
|
|
|
40
41
|
parseAsString.withDefault('').withOptions({ clearOnDefault: true })
|
|
41
42
|
)
|
|
42
43
|
|
|
43
|
-
const [skuParam, setSkuParam] = useQueryState('sku'
|
|
44
|
+
const [skuParam, setSkuParam] = useQueryState('sku',
|
|
45
|
+
parseAsString.withDefault('').withOptions({ clearOnDefault: true })
|
|
46
|
+
)
|
|
47
|
+
|
|
44
48
|
const [addParam, setAddParam] = useQueryState('add',
|
|
45
49
|
parseAsBoolean.withDefault(false).withOptions({ clearOnDefault: true })
|
|
46
50
|
)
|
|
47
51
|
|
|
48
|
-
|
|
52
|
+
const [message, setMessage] = useState<string | undefined>(undefined)
|
|
49
53
|
|
|
50
54
|
const directMutator: GetMutator = (level: 1 | 2): StringMutator => {
|
|
51
55
|
|
|
@@ -83,70 +87,80 @@ const useSkuAndFacetParams = (
|
|
|
83
87
|
|
|
84
88
|
const setCurrentCategoryFromSku = (sku: string) => {
|
|
85
89
|
const toks: string[] = sku.split('-')
|
|
86
|
-
|
|
90
|
+
cmmc.setFacets({
|
|
87
91
|
1: [toks[1]],
|
|
88
92
|
2: [toks[2]]
|
|
89
93
|
})
|
|
90
|
-
encRef.current.category = categories[0]
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
if (skuParam) {
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
cmmc.currentItem!.
|
|
97
|
-
|
|
97
|
+
// true if a valid sku
|
|
98
|
+
if (cmmc.setCurrentItem(skuParam)) {
|
|
99
|
+
if (addParam && cmmc.currentItem!.quantity === 0) {
|
|
100
|
+
cmmc.currentItem!.increment()
|
|
101
|
+
setAddParam(false)
|
|
102
|
+
}
|
|
103
|
+
// Marks that we've been here so no need to
|
|
104
|
+
// create an autorun() instance twice.
|
|
105
|
+
if (!encRef.current.usingSkuMode) {
|
|
106
|
+
setCurrentCategoryFromSku(skuParam)
|
|
107
|
+
encRef.current.autoRunDisposer = autorun(() => {
|
|
108
|
+
if (cmmc.currentItem && cmmc.currentItem.sku !== skuParam) {
|
|
109
|
+
setSkuParam(cmmc.currentItem.sku)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
setMessage(undefined)
|
|
114
|
+
encRef.current.usingSkuMode = true
|
|
98
115
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (cmmc.currentItem && cmmc.currentItem.sku !== skuParam) {
|
|
105
|
-
setSkuParam(cmmc.currentItem.sku)
|
|
106
|
-
}
|
|
107
|
-
})
|
|
116
|
+
else {
|
|
117
|
+
setSkuParam('')
|
|
118
|
+
// if sent here w an invalid sku,
|
|
119
|
+
// it will effectively put us in facet params mode
|
|
120
|
+
setMessage('Invalid sku. ' + PLEASE_SELECT_FACETS)
|
|
108
121
|
}
|
|
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
122
|
}
|
|
123
|
+
|
|
115
124
|
setLoading && setLoading(false)
|
|
116
|
-
}, [skuParam
|
|
125
|
+
}, [skuParam])
|
|
117
126
|
|
|
118
127
|
// supposed to be when component unmounts
|
|
128
|
+
/*
|
|
119
129
|
useEffect(() => (() => {
|
|
120
130
|
if (encRef.current.autoRunDisposer) {
|
|
121
131
|
//encRef.current.autoRunDisposer() // no idea why this seems to be called prematurely and so many times <shrug>
|
|
122
132
|
}
|
|
123
133
|
}), [])
|
|
134
|
+
*/
|
|
124
135
|
|
|
125
136
|
|
|
126
137
|
// Level Params Mode
|
|
127
138
|
useEffect(() => {
|
|
128
139
|
|
|
129
140
|
if (encRef.current.usingSkuMode) return
|
|
130
|
-
|
|
141
|
+
|
|
131
142
|
const facets: FacetsValue = { }
|
|
132
143
|
if (level1) { facets[1] = [level1] }
|
|
133
144
|
if (level2) { facets[2] = [level2] }
|
|
145
|
+
//console.log(`LEV1: ${level1}, LEV2: ${level2}`)
|
|
134
146
|
if (level1 && level2) {
|
|
135
147
|
const categories = cmmc.setFacets(facets)
|
|
136
|
-
if (categories.length >
|
|
137
|
-
|
|
138
|
-
|
|
148
|
+
if (categories && categories.length > 0) {
|
|
149
|
+
cmmc.setCurrentItem(categories?.[0].products[0].sku)
|
|
150
|
+
setMessage(undefined)
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
cmmc.setCurrentItem(undefined)
|
|
154
|
+
setMessage('Unrecognized facets. ' + PLEASE_SELECT_FACETS)
|
|
139
155
|
}
|
|
140
|
-
encRef.current.category = categories[0]
|
|
141
156
|
}
|
|
142
157
|
else {
|
|
143
|
-
|
|
158
|
+
setMessage(PLEASE_SELECT_FACETS)
|
|
144
159
|
}
|
|
145
160
|
setLoading && setLoading(false)
|
|
146
161
|
}, [level1 , level2])
|
|
147
162
|
|
|
148
163
|
return {
|
|
149
|
-
category: encRef.current.category,
|
|
150
164
|
message,
|
|
151
165
|
getMutator: encRef.current.usingSkuMode ?
|
|
152
166
|
directMutator : paramsMutator
|