@luxfi/core 5.1.6 → 5.2.0
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/commerce/ui/conf.ts +1 -1
- package/components/commerce/drawer/index.tsx +1 -3
- package/components/commerce/drawer/micro.tsx +29 -21
- package/components/commerce/drawer/shell.tsx +17 -13
- package/package.json +1 -1
- package/root-layout/index.tsx +1 -7
- package/types/index.ts +0 -1
- package/types/site-def.ts +1 -1
- package/commerce/data/AUTO-GEN-bullion-by-family.json +0 -34
- package/commerce/data/EDIT-ME-bullion-market-prices.ts +0 -12
- package/commerce/data/assign-prices.ts +0 -50
- package/commerce/data/assign-videos-by-family-group.ts +0 -14
- package/commerce/data/bullion-price-1oz.ts +0 -5
- package/commerce/data/index.ts +0 -18
- package/conf/index.ts +0 -52
- package/conf/lux-commerce-options.ts +0 -6
- package/types/commerce-config.ts +0 -10
package/commerce/ui/conf.ts
CHANGED
@@ -30,9 +30,7 @@ const CommerceUIComponent: React.FC = observer(() => {
|
|
30
30
|
// see handleCloseGesture()
|
31
31
|
const setOpen = (b: boolean): void => {
|
32
32
|
if (!b) {
|
33
|
-
console.log("ON CLOSE")
|
34
33
|
if (!drawer.closedByUser) {
|
35
|
-
console.log("syncing closed state to UI gesture")
|
36
34
|
drawer.setClosedByUser(true)
|
37
35
|
}
|
38
36
|
}
|
@@ -107,7 +105,7 @@ const CommerceUIComponent: React.FC = observer(() => {
|
|
107
105
|
<Micro
|
108
106
|
handleCheckout={handleCheckout}
|
109
107
|
handleItemClicked={handleItemClicked}
|
110
|
-
clx='w-full sm:w-[460px] sm:mx-auto md:w-[550px]'
|
108
|
+
clx='w-full px-2 sm:w-[460px] sm:mx-auto md:w-[550px]'
|
111
109
|
/>
|
112
110
|
)}
|
113
111
|
</CommerceDrawer>
|
@@ -12,17 +12,9 @@ import { useCommerceDrawer, useRecentActivity } from '../../../commerce/ui/conte
|
|
12
12
|
|
13
13
|
const CN = {
|
14
14
|
// h: mind padding!
|
15
|
-
mobile: { w: 36, h:
|
16
|
-
sm: { w: 60, h:
|
17
|
-
desktop: { w: 60, h:
|
18
|
-
}
|
19
|
-
|
20
|
-
const renderTitle = (item: LineItem): React.ReactNode => {
|
21
|
-
const toks = item.title.split(', ')
|
22
|
-
if (toks.length === 2) {
|
23
|
-
return <><p>{toks[0]},</p><p className=''>{toks[1]}</p></>
|
24
|
-
}
|
25
|
-
return <p>{item.title}</p>
|
15
|
+
mobile: { w: 36, h: 32 },
|
16
|
+
sm: { w: 60, h: 34 },
|
17
|
+
desktop: { w: 60, h: 32 },
|
26
18
|
}
|
27
19
|
|
28
20
|
const Info: React.FC<{
|
@@ -62,6 +54,7 @@ const Info: React.FC<{
|
|
62
54
|
</>)
|
63
55
|
}
|
64
56
|
|
57
|
+
const PROMPT_COMMON_CLX = 'block absolute top-0 left-0 bg-transparent duration-400 transition-opacity'
|
65
58
|
|
66
59
|
const Micro: React.FC<{
|
67
60
|
clx?: string
|
@@ -75,32 +68,45 @@ const Micro: React.FC<{
|
|
75
68
|
|
76
69
|
const drawer = useCommerceDrawer()
|
77
70
|
const recent = useRecentActivity()
|
71
|
+
const mobile = drawer.isMobile
|
78
72
|
|
79
73
|
return (
|
80
74
|
<div className={cn(
|
81
|
-
'
|
82
|
-
(drawer.showAdded ? '
|
75
|
+
(drawer.showAdded ? 'grid grid-cols-2' : 'flex justify-center items-center '),
|
76
|
+
(drawer.showAdded ? ((drawer.isMobile) ? '-mt-3' : '-mt-3') : ''),
|
83
77
|
'gap-2 md:gap-3 relative',
|
84
78
|
clx
|
85
79
|
)}>
|
86
80
|
{drawer.showAdded && (
|
87
|
-
<div className='
|
88
|
-
<p className='text-muted text-xxs md:text-xs leading-none pl-1'
|
81
|
+
<div className={'flex flex-col items-stretch ' + (drawer.isMobile ? 'justify-start' : 'group')}>
|
82
|
+
<p className={'relative text-muted text-xxs md:text-xs leading-none pl-1 self-start ' + (drawer.isMobile ? 'top-[3px]' : 'top-[1px]')}>
|
83
|
+
<span className='invisible'>scrictly for layout</span>
|
84
|
+
{drawer.isMobile ? (
|
85
|
+
<span className={PROMPT_COMMON_CLX}>tap for options:</span>
|
86
|
+
) : (<>
|
87
|
+
<span className={PROMPT_COMMON_CLX + ' group-hover:opacity-0'}>recent item:</span>
|
88
|
+
<span className={PROMPT_COMMON_CLX + ' opacity-0 group-hover:opacity-100'}>view options:</span>
|
89
|
+
</>)}
|
90
|
+
</p>
|
89
91
|
<Button
|
90
92
|
variant='ghost'
|
91
|
-
rounded='
|
93
|
+
rounded={drawer.isMobile ? 'md' : 'lg'}
|
94
|
+
size={drawer.isMobile ? 'default' : 'lg'}
|
92
95
|
onClick={handleItemClicked}
|
93
96
|
className={cn(
|
97
|
+
'box-content',
|
94
98
|
'flex flex-row justify-between items-center gap-1',
|
95
99
|
'-ml-1.5',
|
96
100
|
'overflow-hidden ',
|
97
|
-
'px-1
|
101
|
+
'px-1 md:px-2 py-[2px]',
|
102
|
+
'border border-transparent group-hover:border-muted-3',
|
103
|
+
'group-hover:!bg-transparent '
|
98
104
|
)}
|
99
105
|
>
|
100
106
|
{recent.item?.img && (<>
|
101
107
|
<Image def={recent.item.img} constrainTo={CN.mobile} preload className='sm:hidden grow-0 shrink-0'/>
|
102
|
-
<Image def={recent.item.img} constrainTo={CN.sm} preload className='hidden sm:
|
103
|
-
<Image def={recent.item.img} constrainTo={CN.desktop} preload className='hidden md:
|
108
|
+
<Image def={recent.item.img} constrainTo={CN.sm} preload className='hidden sm:block md:hidden grow-0 shrink-0'/>
|
109
|
+
<Image def={recent.item.img} constrainTo={CN.desktop} preload className='hidden md:block grow-0 shrink-0'/>
|
104
110
|
</>)}
|
105
111
|
{recent.item && (
|
106
112
|
<div className='grow w-full'>
|
@@ -112,9 +118,11 @@ const Micro: React.FC<{
|
|
112
118
|
)}
|
113
119
|
{drawer.showCheckout && (
|
114
120
|
<div className={cn(
|
115
|
-
'flex flex-col
|
116
|
-
(drawer.showAdded ? 'items-stretch' : 'items-center
|
121
|
+
'flex flex-col w-full',
|
122
|
+
(drawer.showAdded ? 'items-stretch' : 'items-center' ),
|
123
|
+
(drawer.isMobile ? 'justify-start' : 'justify-center')
|
117
124
|
)}>
|
125
|
+
{drawer.showAdded && <p className='invisible text-muted text-xxs md:text-xs leading-none pl-1 self-start'>for layout</p>}
|
118
126
|
<CheckoutButton
|
119
127
|
handleCheckout={handleCheckout}
|
120
128
|
variant='primary'
|
@@ -1,10 +1,7 @@
|
|
1
1
|
'use client'
|
2
2
|
import React, {type PropsWithChildren } from 'react'
|
3
3
|
|
4
|
-
import { X as LucideX} from 'lucide-react'
|
5
|
-
|
6
4
|
import {
|
7
|
-
Button,
|
8
5
|
Drawer,
|
9
6
|
DrawerContent,
|
10
7
|
DrawerHandle,
|
@@ -48,29 +45,36 @@ const CommerceDrawer: React.FC<PropsWithChildren &
|
|
48
45
|
fastDragSkipsToEnd={false}
|
49
46
|
dragHandleOnly={true}
|
50
47
|
handleHandleClicked={handleHandleClicked}
|
48
|
+
extendHandleDragRegion={false}
|
51
49
|
// debugOutput
|
52
50
|
{...rest}
|
53
51
|
>
|
54
52
|
<DrawerContent
|
55
53
|
defaultHandle={false}
|
56
54
|
className={cn(
|
57
|
-
|
58
|
-
(micro ? (mobile ? 'mt-4 pt-1.5' : 'mt-5 pt-4') : 'mt-5 pt-5'),
|
59
|
-
'
|
55
|
+
'border-0',
|
56
|
+
//(micro ? (mobile ? 'mt-4 pt-1.5' : 'mt-5 pt-4') : 'mt-5 pt-5'),
|
57
|
+
mobile ? 'pt-5' : 'pt-6',
|
58
|
+
'w-full h-full',
|
60
59
|
)}
|
61
60
|
// https://github.com/radix-ui/primitives/discussions/935
|
62
61
|
onOpenAutoFocus={(e) => {e.preventDefault()}}
|
63
62
|
>
|
64
63
|
<DrawerHandle
|
65
64
|
className={cn(
|
66
|
-
'absolute left-0 right-0 mx-auto z-10',
|
67
|
-
'
|
68
|
-
|
69
|
-
|
70
|
-
'[&>[vaul-handle-hitarea]]:hidden',
|
71
|
-
//(!micro ? 'bg-level-3 hover:bg-level-2 ' : 'bg-level-1 hover:bg-level-2 ')
|
65
|
+
'absolute top-0 left-0 right-0 mx-auto z-10',
|
66
|
+
'flex justify-center items-start',
|
67
|
+
'border-t rounded-t-lg border-muted-2',
|
68
|
+
mobile ? 'h-5 touch-pan-y' : 'h-6',
|
72
69
|
)}
|
73
|
-
|
70
|
+
>
|
71
|
+
<div className={cn(
|
72
|
+
// pseudo-handle
|
73
|
+
'rounded-[3px] bg-level-3',
|
74
|
+
mobile ? 'w-[155px] mt-[5px] h-1.5' : 'w-[180px] mt-[3px] h-2.5 hover:bg-level-4',
|
75
|
+
!mobile ? 'cursor-grab active:cursor-grabbing' : '',
|
76
|
+
)} />
|
77
|
+
</DrawerHandle>
|
74
78
|
{children}
|
75
79
|
</DrawerContent>
|
76
80
|
</Drawer>
|
package/package.json
CHANGED
package/root-layout/index.tsx
CHANGED
@@ -15,7 +15,6 @@ import { AuthListener, ChatWidget, Header, Scripts } from '../components'
|
|
15
15
|
|
16
16
|
import CommerceDrawer from '../components/commerce/drawer'
|
17
17
|
|
18
|
-
import { selectionUISpecifiers } from '../conf'
|
19
18
|
import type SiteDef from '../types/site-def'
|
20
19
|
|
21
20
|
import '../style/lux-global.css'
|
@@ -90,12 +89,7 @@ async function RootLayout({
|
|
90
89
|
<Scripts/>
|
91
90
|
<AuthServiceProvider user={currentUser} conf={{} as AuthServiceConf}>
|
92
91
|
{siteDef?.commerce ? (
|
93
|
-
<CommerceProvider
|
94
|
-
rootNode={siteDef.commerce!.rootNode}
|
95
|
-
families={siteDef.commerce!.families}
|
96
|
-
options={siteDef.commerce!.options}
|
97
|
-
uiSpecs={selectionUISpecifiers}
|
98
|
-
>
|
92
|
+
<CommerceProvider config={siteDef.commerce!} >
|
99
93
|
<CommerceUIProvider >
|
100
94
|
<Guts />
|
101
95
|
<CommerceDrawer />
|
package/types/index.ts
CHANGED
@@ -2,4 +2,3 @@ export type { ContactInfo, ContactInfoFields } from './contact-info'
|
|
2
2
|
export type { default as SiteDef } from './site-def'
|
3
3
|
export type { default as ChatbotSuggestedQuestion } from './chatbot-suggested-question'
|
4
4
|
export type { default as ChatbotConfig } from './chatbot-config'
|
5
|
-
export type { default as CommerceConfig } from './commerce-config'
|
package/types/site-def.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
|
3
3
|
import type { LinkDef } from '@hanzo/ui/types'
|
4
|
+
import type { CommerceConfig } from '@hanzo/commerce/types'
|
4
5
|
|
5
|
-
import type CommerceConfig from './commerce-config'
|
6
6
|
import type ChatbotConfig from './chatbot-config'
|
7
7
|
|
8
8
|
interface SiteDef {
|
@@ -1,34 +0,0 @@
|
|
1
|
-
[
|
2
|
-
{
|
3
|
-
"id": "LXM-AG-B",
|
4
|
-
"title": "Minted Bar",
|
5
|
-
"parentTitle": "Lux Silver",
|
6
|
-
"desc": "Get unprecedented access to silver with 1:1 asset-backed Lux Silver NFTs, sovereign ownership of physical silver without management fees, and mine-direct discount pricing.",
|
7
|
-
"img": {
|
8
|
-
"src": "/assets/commerce/silver/product/silver-bar-pt-800x800.png",
|
9
|
-
"dim": {
|
10
|
-
"w": 800,
|
11
|
-
"h": 800
|
12
|
-
}
|
13
|
-
},
|
14
|
-
"products": [
|
15
|
-
{
|
16
|
-
"id": "fce17569-a86c-4f69-bc61-ab435ed0c46f",
|
17
|
-
"sku": "LXM-AG-B-1_OZ",
|
18
|
-
"fullTitle": "Lux Silver, 1oz Minted Bar",
|
19
|
-
"optionLabel": "1oz",
|
20
|
-
"familyTitle": "Minted Bar",
|
21
|
-
"familyId": "LXM-AG-B",
|
22
|
-
"desc": "Get unprecedented access to silver with 1:1 asset-backed Lux Silver NFTs, sovereign ownership of physical silver without management fees, and mine-direct discount pricing.",
|
23
|
-
"price": 0,
|
24
|
-
"img": {
|
25
|
-
"src": "/assets/commerce/silver/product/silver-bar-pt-800x800.png",
|
26
|
-
"dim": {
|
27
|
-
"w": 800,
|
28
|
-
"h": 800
|
29
|
-
}
|
30
|
-
}
|
31
|
-
}
|
32
|
-
]
|
33
|
-
}
|
34
|
-
]
|
@@ -1,50 +0,0 @@
|
|
1
|
-
import type { Family } from '@hanzo/commerce/types'
|
2
|
-
|
3
|
-
import prices from './EDIT-ME-bullion-market-prices'
|
4
|
-
|
5
|
-
const sep = {
|
6
|
-
tok: '-',
|
7
|
-
subTok: '_',
|
8
|
-
decimal: '.'
|
9
|
-
}
|
10
|
-
|
11
|
-
const GRAMS_PER_OZ = 28.3495
|
12
|
-
|
13
|
-
const tree: any = {}
|
14
|
-
for (let key in prices) {
|
15
|
-
const values = prices[key as keyof typeof prices]
|
16
|
-
tree[key] = {
|
17
|
-
oz: values.market1oz * (1 - values.discount),
|
18
|
-
g: values.market1oz * (1 - values.discount) / GRAMS_PER_OZ
|
19
|
-
}
|
20
|
-
}
|
21
|
-
|
22
|
-
// LXB-AU-B-1_OZ, LXB-AU-B-2.5_g
|
23
|
-
const priceFromSKU = (
|
24
|
-
sku: string
|
25
|
-
) => {
|
26
|
-
const tokens = sku.split(sep.tok)
|
27
|
-
const type_ = tokens[1].toLowerCase()
|
28
|
-
|
29
|
-
const quanAndUnit = tokens[tokens.length - 1]
|
30
|
-
const quanAndUnitToks = quanAndUnit.split(sep.subTok)
|
31
|
-
let quantity = quanAndUnitToks[0].includes(sep.decimal) ? parseFloat(quanAndUnitToks[0].split(sep.decimal).join('.')) : parseInt(quanAndUnitToks[0])
|
32
|
-
let unit = quanAndUnitToks[1].toLowerCase()
|
33
|
-
if (unit === 'kg') {
|
34
|
-
quantity *= 1000
|
35
|
-
unit = 'g'
|
36
|
-
}
|
37
|
-
else if (unit === 'lb') {
|
38
|
-
quantity *= 16
|
39
|
-
unit = 'oz'
|
40
|
-
}
|
41
|
-
|
42
|
-
return tree[type_][unit] * quantity
|
43
|
-
}
|
44
|
-
|
45
|
-
export default (c: Family): Family => {
|
46
|
-
for (let prod of c.products) {
|
47
|
-
prod.price = priceFromSKU(prod.sku)
|
48
|
-
}
|
49
|
-
return c
|
50
|
-
}
|
@@ -1,14 +0,0 @@
|
|
1
|
-
import type { VideoDef } from '@hanzo/ui/types'
|
2
|
-
import type { Family } from '@hanzo/commerce/types'
|
3
|
-
|
4
|
-
export default (fam: Family, map: Map<string, VideoDef>): Family => {
|
5
|
-
if (fam.parentTitle) {
|
6
|
-
for (let prod of fam.products) {
|
7
|
-
const video = map.get(fam.parentTitle)
|
8
|
-
if (video) {
|
9
|
-
prod.video = video
|
10
|
-
}
|
11
|
-
}
|
12
|
-
}
|
13
|
-
return fam
|
14
|
-
}
|
package/commerce/data/index.ts
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
import type { VideoDef } from '@hanzo/ui/types'
|
2
|
-
|
3
|
-
import bullionByFamily from './AUTO-GEN-bullion-by-family.json'
|
4
|
-
|
5
|
-
import assignPrices from './assign-prices'
|
6
|
-
import assignVideosByFamilyGroup from './assign-videos-by-family-group'
|
7
|
-
|
8
|
-
export const getBullionFamilies = (videoMap: Map<string, VideoDef>) => (
|
9
|
-
bullionByFamily.map(
|
10
|
-
(fam) => (assignPrices(fam))).map(
|
11
|
-
(fam) => (assignVideosByFamilyGroup(fam, videoMap)
|
12
|
-
)
|
13
|
-
)
|
14
|
-
)
|
15
|
-
|
16
|
-
export { default as serviceOptions } from '../../conf/lux-commerce-options'
|
17
|
-
export { default as bullionPrice1oz } from './bullion-price-1oz'
|
18
|
-
|
package/conf/index.ts
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
import type { SelectionUISpecifier } from '@hanzo/commerce/types'
|
2
|
-
|
3
|
-
export { default as commerceServiceOptions } from './lux-commerce-options'
|
4
|
-
|
5
|
-
export const selectionUISpecifiers = {
|
6
|
-
|
7
|
-
'LXM-CN': {
|
8
|
-
singleFamily: {
|
9
|
-
type: 'carousel',
|
10
|
-
options: {
|
11
|
-
familyTitle: 'long',
|
12
|
-
showByline: false,
|
13
|
-
showPrice: true,
|
14
|
-
}
|
15
|
-
}
|
16
|
-
},
|
17
|
-
'LXM-FC': {
|
18
|
-
singleFamily: {
|
19
|
-
type: 'carousel',
|
20
|
-
options: {
|
21
|
-
//showQuantity: true
|
22
|
-
}
|
23
|
-
}
|
24
|
-
},
|
25
|
-
'LXM-CR': {
|
26
|
-
multiFamily: {
|
27
|
-
type: 'all-variants-carousel',
|
28
|
-
selectorOptions: {
|
29
|
-
showParentTitle: false,
|
30
|
-
showItemSwatches: true
|
31
|
-
},
|
32
|
-
itemOptions: {
|
33
|
-
familyTitle: 'long',
|
34
|
-
showFamilyByline: true,
|
35
|
-
showPrice: false,
|
36
|
-
}
|
37
|
-
}
|
38
|
-
},
|
39
|
-
'LXM-AG': {
|
40
|
-
multiFamily: {
|
41
|
-
type: 'all-variants-carousel',
|
42
|
-
selectorOptions: {
|
43
|
-
showParentTitle: true,
|
44
|
-
showItemSwatches: false
|
45
|
-
},
|
46
|
-
itemOptions: {
|
47
|
-
familyTitle: 'long',
|
48
|
-
}
|
49
|
-
}
|
50
|
-
},
|
51
|
-
|
52
|
-
} satisfies Record<string, SelectionUISpecifier>
|
package/types/commerce-config.ts
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
import type { ServiceOptions } from '@hanzo/commerce'
|
2
|
-
import type { CategoryNode, Family } from '@hanzo/commerce/types'
|
3
|
-
|
4
|
-
interface CommerceConfig {
|
5
|
-
families: Family[]
|
6
|
-
rootNode: CategoryNode
|
7
|
-
options?: ServiceOptions
|
8
|
-
}
|
9
|
-
|
10
|
-
export { type CommerceConfig as default }
|