@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,91 +1,91 @@
1
- 'use client'
2
- import React, { useState } from 'react'
3
-
4
- import { ToggleGroup, ToggleGroupItem} from "@hanzo/ui/primitives"
5
- import { cn } from '@hanzo/ui/util'
6
-
7
- import type { CategoryNode, StringMutator, StringArrayMutator } from '../../types'
8
- import NodeImage from './node-image'
9
-
10
- const NodeTabs: React.FC<{
11
- levelNodes: CategoryNode[]
12
- mutator: StringMutator | StringArrayMutator
13
- multiple?: boolean
14
- className?: string
15
- buttonClx?: string
16
- itemClx?: string
17
- mobile?: boolean
18
- tabSize?: string
19
- show?: 'image' | 'label' | 'image-and-label'
20
- }> = ({
21
- levelNodes,
22
- mutator,
23
- multiple=false,
24
- buttonClx='',
25
- itemClx='',
26
- className='',
27
- mobile=false,
28
- tabSize,
29
- show='image-and-label'
30
- }) => {
31
-
32
- const [last, setLast] = useState<string | undefined>(undefined)
33
-
34
- const handleChangeMultiple = (selected: string[]) => {
35
- (mutator as StringArrayMutator).set(selected)
36
- setLast(selected.length === 1 ? selected[0] : undefined)
37
- }
38
-
39
- const handleChangeSingle = (selected: string) => {
40
- (mutator as StringMutator).set(selected)
41
- if (selected) { setLast(selected) }
42
- }
43
-
44
- const roundedToSpread: any = {}
45
- if (multiple) {
46
- roundedToSpread.rounded = 'xl'
47
- }
48
-
49
- const val = multiple ?
50
- (mutator as StringArrayMutator).get()
51
- :
52
- (mutator as StringMutator).get()
53
-
54
- return (
55
- <ToggleGroup
56
- type={multiple ? 'multiple' : 'single'}
57
- value={val}
58
- variant='default'
59
- size={tabSize ? tabSize : (mobile ? 'sm' : 'default')}
60
- onValueChange={multiple ? handleChangeMultiple : handleChangeSingle}
61
- className={className}
62
- {...roundedToSpread}
63
- >
64
- {levelNodes.map((treeNode, index) => {
65
- const roundedToSpread: any = {}
66
- if (!multiple) {
67
- roundedToSpread.rounded = 'none'
68
- if (index === 0) { roundedToSpread.rounded = 'llg' }
69
- else if (index === levelNodes.length - 1) { roundedToSpread.rounded = 'rlg' }
70
- }
71
- return (
72
- <ToggleGroupItem
73
- key={treeNode.skuToken}
74
- value={treeNode.skuToken}
75
- disabled={(last && last === treeNode.skuToken || treeNode.skuToken === mutator.get())}
76
- aria-label={`Select ${treeNode.label}`}
77
- {...roundedToSpread}
78
- className={buttonClx}
79
- >
80
- <span className={cn('flex flex-row justify-center gap-1 h-6 items-center', itemClx)} >
81
- {!(show === 'label') && (<NodeImage treeNode={treeNode} />) }
82
- {(!(show === 'image') || !treeNode.img) && (<span className='whitespace-nowrap'>{treeNode.label}</span>)}
83
- </span>
84
- </ToggleGroupItem>
85
- )
86
- })}
87
- </ToggleGroup>
88
- )
89
- }
90
-
91
- export default NodeTabs
1
+ 'use client'
2
+ import React, { useState } from 'react'
3
+
4
+ import { ToggleGroup, ToggleGroupItem} from "@hanzo/ui/primitives"
5
+ import { cn } from '@hanzo/ui/util'
6
+
7
+ import type { CategoryNode, StringMutator, StringArrayMutator } from '../../types'
8
+ import NodeImage from './node-image'
9
+
10
+ const NodeTabs: React.FC<{
11
+ levelNodes: CategoryNode[]
12
+ mutator: StringMutator | StringArrayMutator
13
+ multiple?: boolean
14
+ className?: string
15
+ buttonClx?: string
16
+ itemClx?: string
17
+ mobile?: boolean
18
+ tabSize?: string
19
+ show?: 'image' | 'label' | 'image-and-label'
20
+ }> = ({
21
+ levelNodes,
22
+ mutator,
23
+ multiple=false,
24
+ buttonClx='',
25
+ itemClx='',
26
+ className='',
27
+ mobile=false,
28
+ tabSize,
29
+ show='image-and-label'
30
+ }) => {
31
+
32
+ const [last, setLast] = useState<string | undefined>(undefined)
33
+
34
+ const handleChangeMultiple = (selected: string[]) => {
35
+ (mutator as StringArrayMutator).set(selected)
36
+ setLast(selected.length === 1 ? selected[0] : undefined)
37
+ }
38
+
39
+ const handleChangeSingle = (selected: string) => {
40
+ (mutator as StringMutator).set(selected)
41
+ if (selected) { setLast(selected) }
42
+ }
43
+
44
+ const roundedToSpread: any = {}
45
+ if (multiple) {
46
+ roundedToSpread.rounded = 'xl'
47
+ }
48
+
49
+ const val = multiple ?
50
+ (mutator as StringArrayMutator).get()
51
+ :
52
+ (mutator as StringMutator).get()
53
+
54
+ return (
55
+ <ToggleGroup
56
+ type={multiple ? 'multiple' : 'single'}
57
+ value={val}
58
+ variant='default'
59
+ size={tabSize ? tabSize : (mobile ? 'sm' : 'default')}
60
+ onValueChange={multiple ? handleChangeMultiple : handleChangeSingle}
61
+ className={className}
62
+ {...roundedToSpread}
63
+ >
64
+ {levelNodes.map((treeNode, index) => {
65
+ const roundedToSpread: any = {}
66
+ if (!multiple) {
67
+ roundedToSpread.rounded = 'none'
68
+ if (index === 0) { roundedToSpread.rounded = 'llg' }
69
+ else if (index === levelNodes.length - 1) { roundedToSpread.rounded = 'rlg' }
70
+ }
71
+ return (
72
+ <ToggleGroupItem
73
+ key={treeNode.skuToken}
74
+ value={treeNode.skuToken}
75
+ disabled={(last && last === treeNode.skuToken || treeNode.skuToken === mutator.get())}
76
+ aria-label={`Select ${treeNode.label}`}
77
+ {...roundedToSpread}
78
+ className={buttonClx}
79
+ >
80
+ <span className={cn('flex flex-row justify-center gap-1 h-6 items-center', itemClx)} >
81
+ {!(show === 'label') && (<NodeImage treeNode={treeNode} />) }
82
+ {(!(show === 'image') || !treeNode.img) && (<span className='whitespace-nowrap'>{treeNode.label}</span>)}
83
+ </span>
84
+ </ToggleGroupItem>
85
+ )
86
+ })}
87
+ </ToggleGroup>
88
+ )
89
+ }
90
+
91
+ export default NodeTabs
@@ -1,31 +1,31 @@
1
- import React from 'react'
2
- import Image from 'next/image'
3
-
4
- import type { CategoryNode } from '../../types'
5
-
6
- const ICON_SIZE = 20
7
-
8
- const NodeImage: React.FC<{
9
- treeNode: CategoryNode
10
- }> = ({
11
- treeNode: {
12
- img,
13
- imgAR: ar,
14
- label
15
- }
16
- }) => {
17
-
18
- if (!img) { return null }
19
- // treat as URL
20
- return (typeof img === 'string') ? (
21
- <Image
22
- src={img as string}
23
- alt={`Toggle ${label}`}
24
- className={'block mr-1 '}
25
- width={ar ? ar * ICON_SIZE : ICON_SIZE}
26
- height={ICON_SIZE}
27
- />
28
- ) : (img as React.ReactNode)
29
- }
30
-
31
- export default NodeImage
1
+ import React from 'react'
2
+ import Image from 'next/image'
3
+
4
+ import type { CategoryNode } from '../../types'
5
+
6
+ const ICON_SIZE = 20
7
+
8
+ const NodeImage: React.FC<{
9
+ treeNode: CategoryNode
10
+ }> = ({
11
+ treeNode: {
12
+ img,
13
+ imgAR: ar,
14
+ label
15
+ }
16
+ }) => {
17
+
18
+ if (!img) { return null }
19
+ // treat as URL
20
+ return (typeof img === 'string') ? (
21
+ <Image
22
+ src={img as string}
23
+ alt={`Toggle ${label}`}
24
+ className={'block mr-1 '}
25
+ width={ar ? ar * ICON_SIZE : ICON_SIZE}
26
+ height={ICON_SIZE}
27
+ />
28
+ ) : (img as React.ReactNode)
29
+ }
30
+
31
+ export default NodeImage
package/index.ts CHANGED
@@ -1,13 +1,13 @@
1
- export * from './service/context'
2
- export * from './components'
3
- // Impl-dependent, so leave w impl
4
- export type { StandaloneServiceOptions as ServiceOptions } from './service/impls/standalone'
5
- export {
6
- useSyncSkuParamWithCurrentItem,
7
- getFacetValuesMutator,
8
- formatCurrencyValue,
9
- ProductMediaAccessor,
10
- LineItemRef
11
- } from './util'
12
-
1
+ export * from './service/context'
2
+ export * from './components'
3
+ // Impl-dependent, so leave w impl
4
+ export type { StandaloneServiceOptions as ServiceOptions } from './service/impls/standalone'
5
+ export {
6
+ useSyncSkuParamWithCurrentItem,
7
+ getFacetValuesMutator,
8
+ formatCurrencyValue,
9
+ ProductMediaAccessor,
10
+ LineItemRef
11
+ } from './util'
12
+
13
13
  export * from './util/selection-ui-specifiers'
package/package.json CHANGED
@@ -1,60 +1,60 @@
1
- {
2
- "name": "@hanzo/commerce",
3
- "version": "7.3.0",
4
- "description": "e-commerce framework.",
5
- "publishConfig": {
6
- "registry": "https://registry.npmjs.org/",
7
- "access": "public",
8
- "scope": "@hanzo"
9
- },
10
- "author": "Hanzo AI, Inc.",
11
- "license": "BSD-3-Clause",
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/hanzoai/react-sdk.git",
15
- "directory": "packages/commerce"
16
- },
17
- "keywords": [
18
- "cart",
19
- "hanzoai",
20
- "hanzo"
21
- ],
22
- "scripts": {
23
- "lat": "npm show @hanzo/commerce version",
24
- "pub": "npm publish",
25
- "tc": "tsc"
26
- },
27
- "exports": {
28
- ".": "./index.ts",
29
- "./types": "./types/index.ts",
30
- "./debug": "./service/debug.ts"
31
- },
32
- "dependencies": {
33
- "ethers": "^6.12.0",
34
- "next-usequerystate": "^1.17.1",
35
- "react-square-web-payments-sdk": "^3.2.1",
36
- "square": "^35.1.0"
37
- },
38
- "peerDependencies": {
39
- "@hanzo/auth": "^2.4.10",
40
- "@hanzo/ui": "^3.8.31",
41
- "@hookform/resolvers": "^3.3.4",
42
- "@radix-ui/react-radio-group": "^1.1.3",
43
- "firebase": "^10.8.0",
44
- "lucide-react": "^0.344.0",
45
- "mobx": "^6.12.3",
46
- "mobx-react-lite": "^4.0.7",
47
- "mobx-utils": "^6.0.8",
48
- "next": "14.2.3",
49
- "react": "^18.3.1",
50
- "react-dom": "^18.3.1",
51
- "react-hook-form": "^7.51.4",
52
- "zod": "3.23.8"
53
- },
54
- "devDependencies": {
55
- "@types/react": "^18.3.1",
56
- "@types/react-dom": "^18.3.0",
57
- "cross-fetch": "^4.0.0",
58
- "typescript": "^5.4.5"
59
- }
60
- }
1
+ {
2
+ "name": "@hanzo/commerce",
3
+ "version": "7.3.2",
4
+ "description": "e-commerce framework.",
5
+ "publishConfig": {
6
+ "registry": "https://registry.npmjs.org/",
7
+ "access": "public",
8
+ "scope": "@hanzo"
9
+ },
10
+ "author": "Hanzo AI, Inc.",
11
+ "license": "BSD-3-Clause",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/hanzoai/react-sdk.git",
15
+ "directory": "pkg/commerce"
16
+ },
17
+ "keywords": [
18
+ "cart",
19
+ "hanzoai",
20
+ "hanzo"
21
+ ],
22
+ "scripts": {
23
+ "lat": "npm show @hanzo/commerce version",
24
+ "pub": "npm publish",
25
+ "tc": "tsc"
26
+ },
27
+ "exports": {
28
+ ".": "./index.ts",
29
+ "./types": "./types/index.ts",
30
+ "./debug": "./service/debug.ts"
31
+ },
32
+ "dependencies": {
33
+ "ethers": "^6.12.0",
34
+ "next-usequerystate": "^1.17.1",
35
+ "react-square-web-payments-sdk": "^3.2.1",
36
+ "square": "^35.1.0"
37
+ },
38
+ "peerDependencies": {
39
+ "@hanzo/auth": "^2.4.18",
40
+ "@hanzo/ui": "^3.8.36",
41
+ "@hookform/resolvers": "^3.3.4",
42
+ "@radix-ui/react-radio-group": "^1.1.3",
43
+ "firebase": "^10.8.0",
44
+ "lucide-react": "^0.344.0",
45
+ "mobx": "^6.12.3",
46
+ "mobx-react-lite": "^4.0.7",
47
+ "mobx-utils": "^6.0.8",
48
+ "next": "14.2.3",
49
+ "react": "^18.3.1",
50
+ "react-dom": "^18.3.1",
51
+ "react-hook-form": "^7.51.4",
52
+ "zod": "3.23.8"
53
+ },
54
+ "devDependencies": {
55
+ "@types/react": "^18.3.1",
56
+ "@types/react-dom": "^18.3.0",
57
+ "cross-fetch": "^4.0.0",
58
+ "typescript": "^5.4.5"
59
+ }
60
+ }
@@ -1,45 +1,45 @@
1
- 'use client'
2
- import React, {
3
- createContext,
4
- useContext,
5
- useRef,
6
- type PropsWithChildren,
7
- } from 'react'
8
-
9
- // https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
10
- import { enableStaticRendering } from 'mobx-react-lite'
11
- enableStaticRendering(typeof window === "undefined")
12
-
13
- import type CommerceService from '../types/commerce-service'
14
- import type { CommerceConfig } from '../types'
15
- import { getInstance } from './impls/standalone'
16
-
17
- const CommerceContext = createContext<CommerceService | undefined>(undefined)
18
-
19
- const useCommerce = (): CommerceService => {
20
- return useContext(CommerceContext) as CommerceService
21
- }
22
-
23
- const CommerceProvider: React.FC<PropsWithChildren & {
24
- config: CommerceConfig
25
- }> = ({
26
- children,
27
- config
28
- }) => {
29
-
30
- // TODO: Inject Promo fixture here from siteDef
31
- const service = getInstance(config)
32
- const valueRef = useRef<CommerceService>(service)
33
-
34
- return (
35
- <CommerceContext.Provider value={valueRef.current}>
36
- {children}
37
- </CommerceContext.Provider>
38
- )
39
- }
40
-
41
- export {
42
- useCommerce,
43
- CommerceProvider
44
- }
45
-
1
+ 'use client'
2
+ import React, {
3
+ createContext,
4
+ useContext,
5
+ useRef,
6
+ type PropsWithChildren,
7
+ } from 'react'
8
+
9
+ // https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
10
+ import { enableStaticRendering } from 'mobx-react-lite'
11
+ enableStaticRendering(typeof window === "undefined")
12
+
13
+ import type CommerceService from '../types/commerce-service'
14
+ import type { CommerceConfig } from '../types'
15
+ import { getInstance } from './impls/standalone'
16
+
17
+ const CommerceContext = createContext<CommerceService | undefined>(undefined)
18
+
19
+ const useCommerce = (): CommerceService => {
20
+ return useContext(CommerceContext) as CommerceService
21
+ }
22
+
23
+ const CommerceProvider: React.FC<PropsWithChildren & {
24
+ config: CommerceConfig
25
+ }> = ({
26
+ children,
27
+ config
28
+ }) => {
29
+
30
+ // TODO: Inject Promo fixture here from siteDef
31
+ const service = getInstance(config)
32
+ const valueRef = useRef<CommerceService>(service)
33
+
34
+ return (
35
+ <CommerceContext.Provider value={valueRef.current}>
36
+ {children}
37
+ </CommerceContext.Provider>
38
+ )
39
+ }
40
+
41
+ export {
42
+ useCommerce,
43
+ CommerceProvider
44
+ }
45
+
package/service/debug.ts CHANGED
@@ -1,41 +1,41 @@
1
- import type { CategoryNode, CategoryNodeRole, Family, LineItem } from '../types'
2
-
3
- // Node recursion
4
- export const categoryNodeDump = (node: CategoryNode, level: number = 0): void => {
5
- const spacers: string[] = []
6
- for (let i = 0; i < level; i++) {
7
- spacers.push('----')
8
- }
9
- console.log("NODE:" + spacers.join(''), node.skuToken)
10
- node.subNodes?.forEach((sn: CategoryNode) => {categoryNodeDump(sn, level + 1)})
11
- }
12
-
13
- export const selectedFamiliesDump = (result: Family[]): string => {
14
- const toDisplay = result.map((c) => (c.id))
15
- return JSON.stringify(toDisplay, null, 2)
16
- }
17
-
18
- export const peekDump = (result : {
19
- role: CategoryNodeRole
20
- family: Family | undefined
21
- families: Family[] | undefined
22
- node: CategoryNode | undefined
23
- item: LineItem | undefined
24
- } | string): string => {
25
-
26
- if (typeof result === 'string') {
27
- return result
28
- }
29
-
30
- const toDisplay = {
31
- role: result.role,
32
- item: result.item ? result.item.sku : 'UNDEF',
33
- family: result.family ? result.family.id : 'UNDEF',
34
- families: result.families ? result.families.map((f) => (f.id)) : 'UNDEF',
35
- node: result.node ?
36
- (result.node.skuToken + (result.node.label ? (': ' + result.node.label) : ''))
37
- :
38
- 'UNDEF'
39
- }
40
- return JSON.stringify(toDisplay, null, 2)
41
- }
1
+ import type { CategoryNode, CategoryNodeRole, Family, LineItem } from '../types'
2
+
3
+ // Node recursion
4
+ export const categoryNodeDump = (node: CategoryNode, level: number = 0): void => {
5
+ const spacers: string[] = []
6
+ for (let i = 0; i < level; i++) {
7
+ spacers.push('----')
8
+ }
9
+ console.log("NODE:" + spacers.join(''), node.skuToken)
10
+ node.subNodes?.forEach((sn: CategoryNode) => {categoryNodeDump(sn, level + 1)})
11
+ }
12
+
13
+ export const selectedFamiliesDump = (result: Family[]): string => {
14
+ const toDisplay = result.map((c) => (c.id))
15
+ return JSON.stringify(toDisplay, null, 2)
16
+ }
17
+
18
+ export const peekDump = (result : {
19
+ role: CategoryNodeRole
20
+ family: Family | undefined
21
+ families: Family[] | undefined
22
+ node: CategoryNode | undefined
23
+ item: LineItem | undefined
24
+ } | string): string => {
25
+
26
+ if (typeof result === 'string') {
27
+ return result
28
+ }
29
+
30
+ const toDisplay = {
31
+ role: result.role,
32
+ item: result.item ? result.item.sku : 'UNDEF',
33
+ family: result.family ? result.family.id : 'UNDEF',
34
+ families: result.families ? result.families.map((f) => (f.id)) : 'UNDEF',
35
+ node: result.node ?
36
+ (result.node.skuToken + (result.node.label ? (': ' + result.node.label) : ''))
37
+ :
38
+ 'UNDEF'
39
+ }
40
+ return JSON.stringify(toDisplay, null, 2)
41
+ }