@luxfi/core 5.0.7 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
- package/commerce/{data/index.ts → index.ts} +1 -1
- package/components/commerce/buy-drawer/drawer.tsx +4 -46
- package/components/commerce/buy-drawer/index.tsx +17 -215
- package/components/commerce/checkout-button.tsx +14 -27
- package/components/commerce/checkout-widget/index.tsx +37 -143
- package/components/commerce/checkout-widget/use-anim-clx-set.ts +1 -3
- package/components/commerce/checkout-widget/use-lagging-item-ref.ts +30 -0
- package/components/header/desktop.tsx +1 -1
- package/components/index.ts +8 -2
- package/conf/index.ts +0 -2
- package/package.json +10 -12
- package/root-layout/index.tsx +4 -6
- package/tsconfig.json +4 -4
- package/commerce/ui-context/commerce-ui.ts +0 -118
- package/commerce/ui-context/index.tsx +0 -50
- package/components/commerce/add-widget.tsx +0 -20
- package/components/commerce/buy-button.tsx +0 -34
- package/style/drawer-handle-overrides.css +0 -154
- /package/commerce/{data/AUTO-GEN-bullion-by-family.json → AUTO-GEN-bullion-by-family.json} +0 -0
- /package/commerce/{data/EDIT-ME-bullion-market-prices.ts → EDIT-ME-bullion-market-prices.ts} +0 -0
- /package/commerce/{data/assign-prices.ts → assign-prices.ts} +0 -0
- /package/commerce/{data/assign-videos-by-family-group.ts → assign-videos-by-family-group.ts} +0 -0
- /package/commerce/{data/bullion-price-1oz.ts → bullion-price-1oz.ts} +0 -0
- /package/{conf/lux-commerce-options.ts → commerce/lux-service-options.ts} +0 -0
@@ -13,6 +13,6 @@ export const getBullionFamilies = (videoMap: Map<string, VideoDef>) => (
|
|
13
13
|
)
|
14
14
|
)
|
15
15
|
|
16
|
-
export { default as serviceOptions } from '
|
16
|
+
export { default as serviceOptions } from './lux-service-options'
|
17
17
|
export { default as bullionPrice1oz } from './bullion-price-1oz'
|
18
18
|
|
@@ -3,70 +3,29 @@ import React, {type PropsWithChildren } from 'react'
|
|
3
3
|
|
4
4
|
import { X as LucideX} from 'lucide-react'
|
5
5
|
|
6
|
-
import {
|
7
|
-
Button,
|
8
|
-
Drawer,
|
9
|
-
DrawerContent,
|
10
|
-
DrawerHandle,
|
11
|
-
type DrawerProps,
|
12
|
-
useDrawerContext
|
13
|
-
} from '@hanzo/ui/primitives'
|
6
|
+
import { Button, Drawer, DrawerContent, type DrawerProps } from '@hanzo/ui/primitives'
|
14
7
|
import { cn } from '@hanzo/ui/util'
|
15
8
|
|
16
|
-
import '../../../style/drawer-handle-overrides.css'
|
17
|
-
|
18
9
|
const CommerceDrawer: React.FC<PropsWithChildren &
|
19
10
|
Omit<DrawerProps, 'onOpenChange'> &
|
20
11
|
{
|
21
12
|
setOpen: (b: boolean) => void
|
22
|
-
handleHandleClicked: () => void
|
23
13
|
drawerClx?: string
|
24
|
-
setActiveSPIndexSetter?: (fn: (snapPoint: number | string | null) => void) => void
|
25
14
|
}
|
26
15
|
> = ({
|
27
16
|
children,
|
28
17
|
open,
|
29
18
|
setOpen,
|
30
19
|
modal,
|
31
|
-
snapPoints,
|
32
|
-
setActiveSnapPoint,
|
33
|
-
activeSnapPoint,
|
34
|
-
handleHandleClicked,
|
35
|
-
setActiveSPIndexSetter,
|
36
20
|
drawerClx='',
|
37
21
|
...rest
|
38
|
-
}) =>
|
39
|
-
|
40
|
-
|
41
|
-
return (
|
22
|
+
}) => (
|
42
23
|
// @ts-ignore
|
43
|
-
<Drawer
|
44
|
-
|
45
|
-
onOpenChange={setOpen}
|
46
|
-
modal={modal}
|
47
|
-
snapPoints={snapPoints}
|
48
|
-
setActiveSnapPoint={setActiveSnapPoint}
|
49
|
-
activeSnapPoint={activeSnapPoint}
|
50
|
-
fastDragSkipsToEnd={false}
|
51
|
-
handleOnly={true}
|
52
|
-
setActiveSPIndexSetter={setActiveSPIndexSetter}
|
53
|
-
|
54
|
-
|
55
|
-
{...rest}
|
56
|
-
>
|
57
|
-
<DrawerContent defaultHandle={false} className={cn(
|
24
|
+
<Drawer open={open} onOpenChange={setOpen} modal={modal} {...rest}>
|
25
|
+
<DrawerContent modal={modal} className={cn(
|
58
26
|
'rounded-t-xl mt-6 pt-6',
|
59
27
|
drawerClx
|
60
28
|
)}>
|
61
|
-
|
62
|
-
<DrawerHandle
|
63
|
-
className={
|
64
|
-
'absolute left-0 right-0 mx-auto top-2 ' +
|
65
|
-
'w-[100px] h-3 rounded-full bg-level-3 hover:bg-level-2 shrink-0'
|
66
|
-
}
|
67
|
-
handleClick={handleHandleClicked}
|
68
|
-
/>
|
69
|
-
|
70
29
|
{children}
|
71
30
|
<Button
|
72
31
|
variant='ghost'
|
@@ -79,7 +38,6 @@ const CommerceDrawer: React.FC<PropsWithChildren &
|
|
79
38
|
</DrawerContent>
|
80
39
|
</Drawer>
|
81
40
|
)
|
82
|
-
}
|
83
41
|
|
84
42
|
|
85
43
|
export default CommerceDrawer
|
@@ -1,242 +1,44 @@
|
|
1
1
|
'use client'
|
2
|
-
import React
|
3
|
-
import {
|
4
|
-
import { action, computed, makeObservable, observable, reaction, type IReactionDisposer } from 'mobx'
|
2
|
+
import React from 'react'
|
3
|
+
import { useRouter } from 'next/navigation'
|
5
4
|
import { observer } from 'mobx-react-lite'
|
6
5
|
|
7
|
-
import {
|
8
|
-
|
9
|
-
import { useCommerceUI } from '../../../commerce/ui-context'
|
6
|
+
import { useCommerceUI, CarouselBuyCard } from '@hanzo/commerce'
|
10
7
|
|
11
8
|
import CommerceDrawer from './drawer'
|
12
9
|
import CheckoutButton from '../checkout-button'
|
13
10
|
|
14
|
-
const BUY = '700px'
|
15
|
-
const MICRO = '120px'
|
16
|
-
const BOTH = [MICRO, BUY]
|
17
|
-
const BUY_ONLY = [BUY]
|
18
|
-
const MICRO_ONLY = [MICRO]
|
19
|
-
|
20
|
-
type DrawerMode = 'checkout' | 'added' | 'buy' | 'buy-added' | 'buy-checkout' | 'none' | 'closed' // manually
|
21
|
-
type DrawerState = 'micro' | 'buy' | 'closed'
|
22
|
-
|
23
|
-
const MODE_TO_STATE = {
|
24
|
-
checkout: 'micro',
|
25
|
-
added: 'micro',
|
26
|
-
buy: 'buy',
|
27
|
-
'buy-checkout': 'buy',
|
28
|
-
'buy-added': 'buy',
|
29
|
-
none: 'closed',
|
30
|
-
closed: 'closed'
|
31
|
-
} satisfies Record<DrawerMode, DrawerState>
|
32
|
-
|
33
|
-
const MODE_TO_POINTS = {
|
34
|
-
checkout: MICRO_ONLY,
|
35
|
-
added: BOTH,
|
36
|
-
buy: BUY_ONLY,
|
37
|
-
'buy-checkout': BOTH,
|
38
|
-
'buy-added': BOTH,
|
39
|
-
none: BOTH,
|
40
|
-
closed: BOTH
|
41
|
-
}
|
42
|
-
|
43
|
-
|
44
|
-
class ObsDrawerState {
|
45
|
-
|
46
|
-
_mode: DrawerMode = 'none'
|
47
|
-
|
48
|
-
constructor() {
|
49
|
-
makeObservable(this, {
|
50
|
-
_mode: observable,
|
51
|
-
setMode: action,
|
52
|
-
mode: computed,
|
53
|
-
state: computed,
|
54
|
-
points: computed,
|
55
|
-
modal: computed,
|
56
|
-
activePoint: computed
|
57
|
-
})
|
58
|
-
}
|
59
|
-
|
60
|
-
get mode(): DrawerMode {return this._mode}
|
61
|
-
get state(): DrawerState { return MODE_TO_STATE[this._mode] }
|
62
|
-
get points(): (number | string)[] { return MODE_TO_POINTS[this._mode] }
|
63
|
-
get modal(): boolean { return this.state !== 'micro' }
|
64
|
-
get activePoint(): number | string | null {
|
65
|
-
if (this.state === 'buy') return BUY
|
66
|
-
if (this.state === 'micro') return MICRO
|
67
|
-
return null
|
68
|
-
}
|
69
|
-
|
70
|
-
setMode = (m: DrawerMode) => {this._mode = m}
|
71
|
-
}
|
72
|
-
|
73
11
|
const CommerceUIComponent: React.FC = observer(() => {
|
74
12
|
|
75
|
-
const cmmc = useCommerce()
|
76
13
|
const ui = useCommerceUI()
|
77
14
|
const router = useRouter()
|
78
|
-
const isCheckout = usePathname() === '/checkout'
|
79
|
-
|
80
|
-
const stateRef = useRef<ObsDrawerState>(new ObsDrawerState())
|
81
|
-
const reactionDisposers = useRef<IReactionDisposer[]>([])
|
82
|
-
|
83
|
-
const [activeSnapPoint, setActiveSnapPoint] = useState<string | number | null>(null)
|
84
|
-
const setterRef = useRef<((index: number ) => void) | undefined>(undefined)
|
85
|
-
|
86
|
-
useEffect(() => {
|
87
|
-
|
88
|
-
reactionDisposers.current.push(reaction(
|
89
|
-
|
90
|
-
() => ({
|
91
|
-
buy: !!ui.buyOptionsSkuPath,
|
92
|
-
added: !isCheckout && ui.item,
|
93
|
-
checkout: !isCheckout && !cmmc.cartEmpty,
|
94
|
-
closed: ui.closed
|
95
|
-
}),
|
96
|
-
({buy, added, checkout, closed}) => {
|
97
|
-
let mode: DrawerMode = 'none' // TODO: 'closed'
|
98
|
-
if (buy) {
|
99
|
-
if (added) {
|
100
|
-
mode = 'buy-added'
|
101
|
-
}
|
102
|
-
else if (checkout) {
|
103
|
-
mode = 'buy-checkout'
|
104
|
-
}
|
105
|
-
else {
|
106
|
-
mode = 'buy'
|
107
|
-
}
|
108
|
-
}
|
109
|
-
else {
|
110
|
-
if (closed) {
|
111
|
-
mode = 'closed'
|
112
|
-
}
|
113
|
-
else if (added) {
|
114
|
-
mode = 'added'
|
115
|
-
}
|
116
|
-
else if (checkout) {
|
117
|
-
mode = 'checkout'
|
118
|
-
}
|
119
|
-
}
|
120
|
-
stateRef.current.setMode(mode)
|
121
|
-
},
|
122
|
-
{equals: (val, prev) => (
|
123
|
-
val.buy === prev.buy
|
124
|
-
&&
|
125
|
-
val.added === prev.added
|
126
|
-
&&
|
127
|
-
val.checkout === prev.checkout
|
128
|
-
&&
|
129
|
-
val.closed === prev.closed
|
130
|
-
)}
|
131
|
-
)),
|
132
|
-
reactionDisposers.current.push(reaction(
|
133
|
-
() => ( stateRef.current.state ),
|
134
|
-
(s) => {
|
135
|
-
if (s === 'buy') {
|
136
|
-
//setterRef.current?.(stateRef.current.points.length - 1)
|
137
|
-
setActiveSnapPoint(BUY)
|
138
|
-
}
|
139
|
-
else if (s === 'micro') {
|
140
|
-
//setterRef.current?.(0)
|
141
|
-
setActiveSnapPoint(MICRO)
|
142
|
-
}
|
143
|
-
}
|
144
|
-
))
|
145
|
-
return () => {
|
146
|
-
reactionDisposers.current?.forEach((d) => {d()})
|
147
|
-
}
|
148
|
-
}, [isCheckout])
|
149
|
-
|
150
|
-
const _setActiveSnapPoint = (pt: string | number | null): void => {
|
151
|
-
console.log("ON CHANGE: ", pt)
|
152
|
-
setActiveSnapPoint(pt)
|
153
|
-
}
|
154
15
|
|
155
16
|
const handleCheckout = () => {
|
156
17
|
router.push('/checkout')
|
157
18
|
}
|
158
19
|
|
159
|
-
const reallyOnlyCloseDrawer = (b: boolean) => {
|
160
20
|
// Should only ever be called internally to close
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
const handleHandleClicked = () => {
|
165
|
-
console.log("HANDLE CLICKED")
|
166
|
-
|
167
|
-
if (stateRef.current.state === 'buy') {
|
168
|
-
const toks = stateRef.current.mode.split('-')
|
169
|
-
if (toks.length <= 1) {
|
170
|
-
console.log("CLOSING 'BUY' ... ")
|
171
|
-
ui.hideBuyOptions()
|
172
|
-
}
|
173
|
-
else {
|
174
|
-
console.log("CLOSING 'BUY' to ", toks[1])
|
175
|
-
ui.hideBuyOptions()
|
176
|
-
}
|
177
|
-
}
|
178
|
-
else if (stateRef.current.state === 'micro') {
|
179
|
-
if (stateRef.current.mode === 'checkout') {
|
180
|
-
console.log(" CLOSING 'CHECKOUT' ... ")
|
181
|
-
ui.setClosed(true)
|
182
|
-
}
|
183
|
-
else if (stateRef.current.mode === 'added') {
|
184
|
-
console.log(" OPENING 'ADDED' ... ")
|
185
|
-
ui.showBuyOptions(ui.item?.sku ?? '')
|
186
|
-
}
|
187
|
-
}
|
188
|
-
}
|
189
|
-
|
190
|
-
const handleCloseGesture = () => {
|
191
|
-
if (stateRef.current.state === 'buy') {
|
192
|
-
console.log(" CLOSING 'BUY' ... ")
|
193
|
-
const toks = stateRef.current.mode.split('-')
|
194
|
-
if (toks.length <= 1) {
|
195
|
-
stateRef.current.setMode('none')
|
196
|
-
}
|
197
|
-
else {
|
198
|
-
stateRef.current.setMode(toks[1] as DrawerMode) // 'checkout' or 'added'
|
199
|
-
}
|
200
|
-
return true // "handled!"
|
21
|
+
const reallyOnlyCloseDrawer = (b: boolean) => {
|
22
|
+
if (!b ) {
|
23
|
+
ui.hideBuyOptions()
|
201
24
|
}
|
202
|
-
console.log("DEFAULT CLOSE ACTION")
|
203
|
-
return false
|
204
25
|
}
|
205
26
|
|
206
|
-
|
207
|
-
const setActiveSPIndexSetter = (fn: (index: number ) => void): void => {
|
208
|
-
setterRef.current = fn
|
209
|
-
}
|
210
|
-
|
211
|
-
|
212
27
|
return (
|
213
28
|
<CommerceDrawer
|
214
|
-
open={
|
29
|
+
open={!!ui.buyOptionsSkuPath}
|
215
30
|
setOpen={reallyOnlyCloseDrawer}
|
216
|
-
drawerClx={'w-full
|
217
|
-
snapPoints={stateRef.current.points}
|
218
|
-
modal={stateRef.current.modal}
|
219
|
-
activeSnapPoint={activeSnapPoint}
|
220
|
-
setActiveSnapPoint={_setActiveSnapPoint}
|
221
|
-
handleHandleClicked={handleHandleClicked}
|
222
|
-
setActiveSPIndexSetter={setActiveSPIndexSetter}
|
223
|
-
handleCloseGesture={handleCloseGesture}
|
31
|
+
drawerClx={'w-full md:max-w-[550px] md:mx-auto lg:max-w-[50vw]'}
|
224
32
|
>
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
selectorClx='max-w-[475px]'
|
235
|
-
/>
|
236
|
-
)}
|
237
|
-
{stateRef.current.state === 'micro' && (
|
238
|
-
<p>Mode: {stateRef.current.mode}</p>
|
239
|
-
)}
|
33
|
+
<CarouselBuyCard
|
34
|
+
skuPath={ui.buyOptionsSkuPath!}
|
35
|
+
checkoutButton={
|
36
|
+
<CheckoutButton handleCheckout={handleCheckout} className='w-full min-w-[160px] sm:max-w-[320px]'/>
|
37
|
+
}
|
38
|
+
clx='w-full'
|
39
|
+
addBtnClx='w-full min-w-[160px] sm:max-w-[320px]'
|
40
|
+
selectorClx='max-w-[475px]'
|
41
|
+
/>
|
240
42
|
</CommerceDrawer>
|
241
43
|
)
|
242
44
|
})
|
@@ -2,6 +2,7 @@
|
|
2
2
|
import React, { useEffect, useRef } from 'react'
|
3
3
|
import { observable, type IObservableValue, reaction } from 'mobx'
|
4
4
|
import { observer } from 'mobx-react-lite'
|
5
|
+
import { type LucideProps } from 'lucide-react'
|
5
6
|
|
6
7
|
import { Button, type ButtonProps } from '@hanzo/ui/primitives'
|
7
8
|
import { cn } from '@hanzo/ui/util'
|
@@ -11,15 +12,11 @@ import * as Icons from '../icons'
|
|
11
12
|
|
12
13
|
const IconAndQuantity: React.FC<{
|
13
14
|
animateOnQuantityChange?: boolean
|
14
|
-
showArrow?: boolean
|
15
|
-
showQuantity?: boolean
|
16
15
|
clx?: string
|
17
16
|
iconClx?: string
|
18
17
|
digitClx?: string
|
19
18
|
}> = observer(({
|
20
|
-
animateOnQuantityChange=
|
21
|
-
showArrow=true,
|
22
|
-
showQuantity=true,
|
19
|
+
animateOnQuantityChange=true,
|
23
20
|
clx='',
|
24
21
|
iconClx='',
|
25
22
|
digitClx=''
|
@@ -50,7 +47,6 @@ const IconAndQuantity: React.FC<{
|
|
50
47
|
|
51
48
|
return (
|
52
49
|
<div className={cn('flex items-center justify-center', clx)}>
|
53
|
-
{showQuantity && (
|
54
50
|
<div className={cn(
|
55
51
|
'relative flex items-center justify-center mr-1',
|
56
52
|
((wiggleRef.current.get() === 'more') ?
|
@@ -64,13 +60,12 @@ const IconAndQuantity: React.FC<{
|
|
64
60
|
'absolute left-0 right-0 top-0 bottom-0',
|
65
61
|
digitClx
|
66
62
|
)}>
|
67
|
-
<div style={{
|
63
|
+
<div style={{color: 'white' /* tailwind bug? */, fontSize: '11px', position: 'relative', top: '1px' }}>{cmmc.cartQuantity}</div>
|
68
64
|
</div>
|
69
65
|
)}
|
70
66
|
<Icons.bag width='19' height='24' className={cn('relative -top-[3px] opacity-70' , iconClx)} aria-hidden="true" />
|
71
67
|
</div>
|
72
|
-
|
73
|
-
{showArrow && (<span style={{fontSize: '17px',}}>›</span>)}
|
68
|
+
<span style={{fontSize: '17px',}}>›</span>
|
74
69
|
</div>
|
75
70
|
)
|
76
71
|
})
|
@@ -78,7 +73,6 @@ const IconAndQuantity: React.FC<{
|
|
78
73
|
const CheckoutButton: React.FC<ButtonProps & {
|
79
74
|
handleCheckout: () => void
|
80
75
|
showQuantity?: boolean
|
81
|
-
showArrow?: boolean
|
82
76
|
animateOnQuantityChange?: boolean
|
83
77
|
centerText?: boolean
|
84
78
|
}> = ({
|
@@ -87,10 +81,8 @@ const CheckoutButton: React.FC<ButtonProps & {
|
|
87
81
|
rounded='lg',
|
88
82
|
className,
|
89
83
|
showQuantity=true,
|
90
|
-
showArrow=true,
|
91
84
|
animateOnQuantityChange=true,
|
92
85
|
centerText=true,
|
93
|
-
children,
|
94
86
|
...rest
|
95
87
|
}) => {
|
96
88
|
|
@@ -101,27 +93,22 @@ const CheckoutButton: React.FC<ButtonProps & {
|
|
101
93
|
variant={variant}
|
102
94
|
rounded={rounded}
|
103
95
|
className={cn(
|
104
|
-
'flex justify-between items-stretch group',
|
105
|
-
showQuantity ? (centerText ? 'px-1.5' : 'pl-2.5 pr-1.5') : '',
|
106
96
|
className,
|
97
|
+
'flex justify-between items-stretch',
|
98
|
+
showQuantity ? (centerText ? 'px-1.5' : 'pl-2.5 pr-1.5') : ''
|
107
99
|
)}
|
108
100
|
>
|
109
|
-
{centerText && (
|
101
|
+
{showQuantity && centerText && (
|
102
|
+
<IconAndQuantity clx='invisible' />
|
103
|
+
)}
|
104
|
+
<div className='flex justify-center items-center'>Checkout</div>
|
105
|
+
{showQuantity && (
|
110
106
|
<IconAndQuantity
|
111
|
-
|
112
|
-
|
113
|
-
|
107
|
+
animateOnQuantityChange={animateOnQuantityChange}
|
108
|
+
iconClx='fill-fg-foreground'
|
109
|
+
digitClx='text-primary-fg leading-none font-bold font-sans'
|
114
110
|
/>
|
115
111
|
)}
|
116
|
-
{children ?? (<div className='flex justify-center items-center'>Checkout</div>)}
|
117
|
-
<IconAndQuantity
|
118
|
-
clx='group-hover:scale-105 transition-scale transition-duration-300'
|
119
|
-
animateOnQuantityChange={animateOnQuantityChange}
|
120
|
-
showArrow={showArrow}
|
121
|
-
showQuantity={showQuantity}
|
122
|
-
iconClx='fill-background'
|
123
|
-
digitClx='text-foreground group-hover:opacity-80 leading-none font-bold font-sans'
|
124
|
-
/>
|
125
112
|
</Button>
|
126
113
|
)
|
127
114
|
}
|
@@ -1,104 +1,18 @@
|
|
1
1
|
'use client'
|
2
|
-
import React
|
2
|
+
import React from 'react'
|
3
3
|
import { createPortal } from 'react-dom'
|
4
4
|
import { usePathname, useRouter } from 'next/navigation'
|
5
5
|
import { observer } from 'mobx-react-lite'
|
6
6
|
|
7
7
|
import { cn } from '@hanzo/ui/util'
|
8
|
-
import { useStepAnimation } from '@hanzo/ui/util-client'
|
9
|
-
|
10
8
|
import { Image } from '@hanzo/ui/primitives'
|
11
9
|
|
12
|
-
import { useCommerceUI } from '
|
10
|
+
import { useCommerceUI } from '@hanzo/commerce'
|
13
11
|
|
14
12
|
import CheckoutButton from '../checkout-button'
|
15
13
|
import useAnimationClxSet from './use-anim-clx-set'
|
14
|
+
import useLaggingItemRef from './use-lagging-item-ref'
|
16
15
|
import CONST from './const'
|
17
|
-
import type { LineItem } from '@hanzo/commerce/types'
|
18
|
-
|
19
|
-
const transStyle = (t: { transition: string, from : string, to: string } | undefined) : any => (
|
20
|
-
t ? {
|
21
|
-
transitionProperty: t.transition,
|
22
|
-
transitionTimingFunction: CONST.animTimingFn,
|
23
|
-
transitionDuration: `${CONST.animDurationMs}ms`
|
24
|
-
} : {}
|
25
|
-
)
|
26
|
-
|
27
|
-
const transClx = (on: boolean, t: { transition: string, from : string, to: string } | undefined) : string => (
|
28
|
-
on ? (t?.from ?? '') : (t?.to ?? '')
|
29
|
-
)
|
30
|
-
|
31
|
-
const VARS: any = {
|
32
|
-
BR: {
|
33
|
-
pos: 'bottom-[24px] right-[66px]',
|
34
|
-
width: 'w-initial',
|
35
|
-
centerText: false,
|
36
|
-
coClx: 'w-auto',
|
37
|
-
infoClx: 'w-auto',
|
38
|
-
activeItemAnim: {
|
39
|
-
co: {
|
40
|
-
transition: 'none',
|
41
|
-
from : 'px-3 gap-2.5',
|
42
|
-
to: ''
|
43
|
-
},
|
44
|
-
coText: {
|
45
|
-
transition: 'max-width',
|
46
|
-
from : 'max-w-[100px]',
|
47
|
-
to: 'max-w-[0px]'
|
48
|
-
},
|
49
|
-
info: {
|
50
|
-
transition: 'transform, opacity',
|
51
|
-
from : 'scale-x-100 opacity-100 origin-right',
|
52
|
-
to: 'scale-x-0 opacity-0 origin-right'
|
53
|
-
}
|
54
|
-
},
|
55
|
-
showArrow: true
|
56
|
-
},
|
57
|
-
TR: {
|
58
|
-
pos: 'top-[48px] md:top-[80px] right-[28px]',
|
59
|
-
width: 'w-initial',
|
60
|
-
centerText: false,
|
61
|
-
showQuantity: false,
|
62
|
-
showArrow: true,
|
63
|
-
coClx: 'w-auto px-3 gap-1',
|
64
|
-
infoClx: 'w-auto',
|
65
|
-
activeItemAnim: {
|
66
|
-
co: {
|
67
|
-
transition: 'none',
|
68
|
-
from : 'px-3 gap-2.5',
|
69
|
-
to: ''
|
70
|
-
},
|
71
|
-
coText: {
|
72
|
-
transition: 'max-width',
|
73
|
-
from : 'max-w-[100px]',
|
74
|
-
to: 'max-w-[0px]'
|
75
|
-
},
|
76
|
-
info: {
|
77
|
-
transition: 'transform',
|
78
|
-
from : 'scale-x-100 origin-right',
|
79
|
-
to: 'scale-x-0 origin-right'
|
80
|
-
}
|
81
|
-
},
|
82
|
-
},
|
83
|
-
TRIO: {
|
84
|
-
pos: 'top-[48px] md:top-[70px] right-[28px]',
|
85
|
-
centerText: false,
|
86
|
-
showQuantity: true,
|
87
|
-
showArrow: true,
|
88
|
-
width: 'w-initial',
|
89
|
-
coClx: 'hidden',
|
90
|
-
infoClx: 'w-auto',
|
91
|
-
activeItemAnim: {
|
92
|
-
info: {
|
93
|
-
transition: 'transform, opacity',
|
94
|
-
from : 'scale-x-100 opacity-100',
|
95
|
-
to: 'scale-x-50 opacity-0'
|
96
|
-
}
|
97
|
-
},
|
98
|
-
}
|
99
|
-
}
|
100
|
-
|
101
|
-
const v = 'TR'
|
102
16
|
|
103
17
|
const CheckoutWidget: React.FC<{
|
104
18
|
clx?: string
|
@@ -112,78 +26,58 @@ const CheckoutWidget: React.FC<{
|
|
112
26
|
const clxSet = useAnimationClxSet(isCheckout)
|
113
27
|
|
114
28
|
const itemRef = useCommerceUI()
|
115
|
-
|
116
|
-
// for rendering content after itemRef.item() would return false
|
117
|
-
const persistentRef = useRef<LineItem | undefined>(undefined)
|
118
|
-
|
119
|
-
// Doing double duty of being initial step fn for StepAnimation,
|
120
|
-
// and also capturing the item for persistentRef :)
|
121
|
-
const initialStepFn = (): boolean => {
|
122
|
-
if (!!itemRef.item && !persistentRef.current) {
|
123
|
-
persistentRef.current = itemRef.item
|
124
|
-
}
|
125
|
-
return !!itemRef.item
|
126
|
-
}
|
127
|
-
const steps = useStepAnimation(initialStepFn, [CONST.animDurationMs, CONST.animDurationMs, CONST.animDurationMs])
|
29
|
+
const laggingRef = useLaggingItemRef(itemRef, CONST.animDurationMs)
|
128
30
|
|
129
31
|
const handleCheckout = () => { router.push('/checkout')}
|
130
32
|
|
131
33
|
return globalThis?.document?.body && createPortal(
|
132
34
|
(<div
|
133
35
|
className={cn(
|
134
|
-
|
135
|
-
'z-below-modal-2 fixed ',
|
136
|
-
|
137
|
-
'rounded-lg',
|
36
|
+
'min-w-[160px] sm:max-w-[320px] w-[calc(100%-72px)] ml-2 !h-10',
|
37
|
+
'z-below-modal-2 fixed bottom-[20px] left-0 right-0',
|
38
|
+
'rounded-lg bg-background',
|
138
39
|
'flex',
|
139
|
-
|
140
|
-
steps.notPast(1) ? 'gap-2' : '',
|
40
|
+
itemRef.item ? 'gap-2' : '',
|
141
41
|
clxSet.asArray.join(' ')
|
142
42
|
)}
|
143
|
-
style={
|
43
|
+
style={laggingRef.item ? {} : CONST.shadowStyle}
|
144
44
|
>
|
145
45
|
<div
|
146
46
|
className={cn(
|
147
47
|
'flex flex-row justify-between items-center',
|
148
|
-
|
149
|
-
|
150
|
-
steps.notPast(1) ? 'px-3 border rounded-lg bg-level-1 border-muted-3' : ''
|
48
|
+
itemRef.item ? CONST.compWidthClx.itemInfo : 'w-0',
|
49
|
+
laggingRef.item ? 'px-3 border rounded-lg border-muted-3' : ''
|
151
50
|
)}
|
152
|
-
style={
|
51
|
+
style={{
|
52
|
+
transitionProperty: 'width',
|
53
|
+
transitionTimingFunction: CONST.animTimingFn,
|
54
|
+
transitionDuration: `${CONST.animDurationMs}ms`
|
55
|
+
}}
|
153
56
|
>
|
154
|
-
{
|
155
|
-
<Image def={
|
156
|
-
)
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
57
|
+
{laggingRef.item?.img ? (
|
58
|
+
<Image def={laggingRef.item.img} constrainTo={CONST.itemImgConstraint} preload className='grow-0 shrink-0'/>
|
59
|
+
) : ( // placeholder so things align
|
60
|
+
<div style={{height: CONST.itemImgConstraint.h, width: CONST.itemImgConstraint.w}} className='bg-level-3 grow-0 shrink-0'/>
|
61
|
+
)}
|
62
|
+
|
63
|
+
<div className='text-muted grow ml-1'>
|
64
|
+
{laggingRef.item && (<>
|
65
|
+
<p className='whitespace-nowrap text-sm'>{laggingRef.item.title}</p>
|
66
|
+
<p className='whitespace-nowrap text-xxs' >recently added...</p>
|
67
|
+
</>)}
|
68
|
+
</div>
|
161
69
|
</div>
|
162
70
|
<CheckoutButton
|
163
71
|
handleCheckout={handleCheckout}
|
164
|
-
centerText={
|
165
|
-
variant='primary'
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
)}
|
174
|
-
style={transStyle(VARS[v].activeItemAnim.co)}
|
175
|
-
>
|
176
|
-
<div
|
177
|
-
className={cn(
|
178
|
-
'overflow-hidden',
|
179
|
-
'flex justify-center items-center',
|
180
|
-
transClx(steps.notPast(2), VARS[v].activeItemAnim.coText),
|
181
|
-
)}
|
182
|
-
style={transStyle(VARS[v].activeItemAnim.coText)}
|
183
|
-
>
|
184
|
-
Checkout
|
185
|
-
</div>
|
186
|
-
</CheckoutButton>
|
72
|
+
centerText={!!!itemRef.item}
|
73
|
+
variant='primary' rounded='lg'
|
74
|
+
className={cn(itemRef.item ? CONST.compWidthClx.checkout : 'w-full')}
|
75
|
+
style={{
|
76
|
+
transitionProperty: 'width',
|
77
|
+
transitionTimingFunction: CONST.animTimingFn,
|
78
|
+
transitionDuration: `${CONST.animDurationMs}ms`
|
79
|
+
}}
|
80
|
+
/>
|
187
81
|
</div>),
|
188
82
|
globalThis?.document?.body
|
189
83
|
)
|
@@ -1,10 +1,8 @@
|
|
1
1
|
import { useEffect, useRef } from 'react'
|
2
2
|
import { reaction, runInAction} from 'mobx'
|
3
3
|
|
4
|
-
import { useCommerce } from '@hanzo/commerce'
|
5
|
-
|
6
4
|
import ObsStringSet from './obs-string-set'
|
7
|
-
import { useCommerceUI } from '
|
5
|
+
import { useCommerce, useCommerceUI } from '@hanzo/commerce'
|
8
6
|
|
9
7
|
export default (isCheckout: boolean): ObsStringSet => {
|
10
8
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
2
|
+
import { reaction } from 'mobx'
|
3
|
+
|
4
|
+
import type { LineItem, ObsLineItemRef } from "@hanzo/commerce/types"
|
5
|
+
import { LineItemRef } from '@hanzo/commerce'
|
6
|
+
|
7
|
+
export default (orig: ObsLineItemRef, lagMs: number): ObsLineItemRef => {
|
8
|
+
|
9
|
+
// a ref that is synced to 'orig', but persists for lagMs longer
|
10
|
+
// so ui does not jump while animating out.
|
11
|
+
// (Fascilitates for start and end states in animation)
|
12
|
+
const laggingRef = useRef<LineItemRef>(new LineItemRef())
|
13
|
+
|
14
|
+
useEffect(() => (
|
15
|
+
reaction(
|
16
|
+
() => (orig.item),
|
17
|
+
(item: LineItem | undefined) => {
|
18
|
+
if (item) {
|
19
|
+
laggingRef.current.set(item)
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
setTimeout(() => { laggingRef.current.set(undefined) }, lagMs)
|
23
|
+
}
|
24
|
+
},
|
25
|
+
{equals: (val, prev) => (val?.sku === prev?.sku)}
|
26
|
+
)
|
27
|
+
), [])
|
28
|
+
|
29
|
+
return laggingRef.current
|
30
|
+
}
|
@@ -29,7 +29,7 @@ const DesktopHeader: React.FC<{
|
|
29
29
|
{/* md or larger */}
|
30
30
|
<div className={
|
31
31
|
'flex flex-row h-[80px] items-center justify-between ' +
|
32
|
-
'px-[
|
32
|
+
'px-[8px] w-full mx-auto max-w-screen'
|
33
33
|
}>
|
34
34
|
<Logo size='md' href='/' className='hidden lg:flex' key='two' layout='text-only'/>
|
35
35
|
<Logo size='sm' href='/' className='hidden md:flex lg:hidden' key='one' layout='text-only'/>
|
package/components/index.ts
CHANGED
@@ -10,12 +10,18 @@ export { default as MiniChart } from './mini-chart'
|
|
10
10
|
export { default as NotFound } from './not-found'
|
11
11
|
|
12
12
|
export { default as AuthListener } from './auth/auth-listener'
|
13
|
-
export { default as AddWidget } from './commerce/add-widget'
|
14
13
|
export { default as BuyDrawer } from './commerce/buy-drawer'
|
15
|
-
export { default as BuyButton } from './commerce/buy-button'
|
16
14
|
export { default as CheckoutButton } from './commerce/checkout-button'
|
17
15
|
export { default as CheckoutPanel } from './commerce/checkout-panel'
|
18
16
|
export { default as CheckoutWidget } from './commerce/checkout-widget'
|
19
17
|
export { default as LoginPanel } from './auth/login-panel'
|
20
18
|
export { default as Scripts } from './scripts'
|
21
19
|
|
20
|
+
|
21
|
+
/* PLEASE KEEP
|
22
|
+
export {
|
23
|
+
default as HeadMetadata,
|
24
|
+
getTitleFromTemplateString,
|
25
|
+
TwitterComponent
|
26
|
+
} from './head-metadata'
|
27
|
+
*/
|
package/conf/index.ts
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@luxfi/core",
|
3
|
-
"version": "5.0
|
3
|
+
"version": "5.1.0",
|
4
4
|
"description": "Library that contains shared UI primitives, support for a common design system, and other boilerplate support.",
|
5
5
|
"publishConfig": {
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
@@ -27,7 +27,7 @@
|
|
27
27
|
},
|
28
28
|
"exports": {
|
29
29
|
".": "./components/index.ts",
|
30
|
-
"./commerce
|
30
|
+
"./commerce": "./commerce/index.ts",
|
31
31
|
"./root-layout": "./root-layout/index.tsx",
|
32
32
|
"./server-actions": "./server-actions/index.ts",
|
33
33
|
"./next": "./next/index.ts",
|
@@ -38,8 +38,8 @@
|
|
38
38
|
},
|
39
39
|
"dependencies": {
|
40
40
|
"@hanzo/auth": "2.4.6",
|
41
|
-
"@hanzo/commerce": "7.0.
|
42
|
-
"@hanzo/ui": "3.7.
|
41
|
+
"@hanzo/commerce": "7.0.2",
|
42
|
+
"@hanzo/ui": "3.7.0",
|
43
43
|
"@next/third-parties": "^14.1.0",
|
44
44
|
"cookies-next": "^4.1.1",
|
45
45
|
"date-fns": "^3.6.0",
|
@@ -50,15 +50,13 @@
|
|
50
50
|
"peerDependencies": {
|
51
51
|
"@hookform/resolvers": "^3.3.2",
|
52
52
|
"lucide-react": "^0.344.0",
|
53
|
-
"mobx": "^6.12.0",
|
54
|
-
"mobx-react-lite": "^4.0.5",
|
55
53
|
"next": "14.1.3",
|
56
54
|
"next-themes": "^0.2.1",
|
57
|
-
"react": "^18.
|
58
|
-
"react-dom": "^18.
|
59
|
-
"react-hook-form": "^7.51.
|
55
|
+
"react": "^18.2.0",
|
56
|
+
"react-dom": "^18.2.0",
|
57
|
+
"react-hook-form": "^7.51.3",
|
60
58
|
"validator": "^13.11.0",
|
61
|
-
"zod": "3.
|
59
|
+
"zod": "3.21.4"
|
62
60
|
},
|
63
61
|
"devDependencies": {
|
64
62
|
"@mdx-js/loader": "^3.0.0",
|
@@ -66,8 +64,8 @@
|
|
66
64
|
"@types/facebook-pixel": "^0.0.30",
|
67
65
|
"@types/gtag.js": "^0.0.19",
|
68
66
|
"@types/mdx": "^2.0.9",
|
69
|
-
"@types/react": "^18.
|
70
|
-
"@types/react-dom": "^18.
|
67
|
+
"@types/react": "^18.2.64",
|
68
|
+
"@types/react-dom": "^18.2.18",
|
71
69
|
"tailwindcss": "^3.4.2",
|
72
70
|
"typescript": "5.3.3"
|
73
71
|
}
|
package/root-layout/index.tsx
CHANGED
@@ -10,10 +10,9 @@ import { CommerceProvider } from '@hanzo/commerce'
|
|
10
10
|
import getAppRouterBodyFontClasses from '../next/font/get-app-router-font-classes'
|
11
11
|
import { FacebookPixelHead } from '../next/analytics/pixel-analytics'
|
12
12
|
|
13
|
-
import { CommerceUIProvider } from '../commerce/ui-context'
|
14
13
|
import { AuthListener, ChatWidget, Header, Scripts } from '../components'
|
15
|
-
|
16
14
|
import BuyDrawer from '../components/commerce/buy-drawer'
|
15
|
+
import CheckoutWidget from '../components/commerce/checkout-widget'
|
17
16
|
|
18
17
|
import { selectionUISpecifiers } from '../conf'
|
19
18
|
import type SiteDef from '../types/site-def'
|
@@ -100,10 +99,9 @@ const RootLayout: React.FC<PropsWithChildren & {
|
|
100
99
|
options={siteDef.commerce!.options}
|
101
100
|
uiSpecs={selectionUISpecifiers}
|
102
101
|
>
|
103
|
-
<
|
104
|
-
|
105
|
-
|
106
|
-
</CommerceUIProvider>
|
102
|
+
<Guts />
|
103
|
+
<BuyDrawer />
|
104
|
+
<CheckoutWidget />
|
107
105
|
</CommerceProvider>
|
108
106
|
) : (
|
109
107
|
<Guts />
|
package/tsconfig.json
CHANGED
@@ -1,118 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
action,
|
3
|
-
computed,
|
4
|
-
makeObservable,
|
5
|
-
observable,
|
6
|
-
} from 'mobx'
|
7
|
-
import type { CommerceService, LineItem, ObsLineItemRef } from '@hanzo/commerce/types'
|
8
|
-
|
9
|
-
|
10
|
-
interface CommerceUI extends ObsLineItemRef {
|
11
|
-
showBuyOptions: (skuPath: string) => void
|
12
|
-
hideBuyOptions: () => void
|
13
|
-
get buyOptionsSkuPath(): string | undefined
|
14
|
-
|
15
|
-
itemQuantityChanged(sku: string, val: number, prevVal: number): void
|
16
|
-
|
17
|
-
get closed(): boolean
|
18
|
-
setClosed(b: boolean): void
|
19
|
-
|
20
|
-
}
|
21
|
-
|
22
|
-
class CommerceUIStore implements CommerceUI {
|
23
|
-
|
24
|
-
static readonly TIMEOUT = 1500
|
25
|
-
_buyOptionsSkuPath: string | undefined = undefined
|
26
|
-
_closed: boolean = false
|
27
|
-
_paused: boolean = false
|
28
|
-
_activeItem: LineItem | undefined = undefined
|
29
|
-
_lastActivity: number | undefined = undefined
|
30
|
-
_service: CommerceService
|
31
|
-
|
32
|
-
constructor(s: CommerceService) {
|
33
|
-
this._service = s
|
34
|
-
makeObservable(this, {
|
35
|
-
_buyOptionsSkuPath: observable,
|
36
|
-
_activeItem: observable.shallow,
|
37
|
-
_closed: observable,
|
38
|
-
showBuyOptions: action,
|
39
|
-
hideBuyOptions: action,
|
40
|
-
buyOptionsSkuPath: computed,
|
41
|
-
itemQuantityChanged: action,
|
42
|
-
setClosed: action,
|
43
|
-
closed: computed,
|
44
|
-
tick: action,
|
45
|
-
item: computed
|
46
|
-
})
|
47
|
-
}
|
48
|
-
|
49
|
-
showBuyOptions = (skuPath: string): void => {
|
50
|
-
this._service.setCurrentItem(undefined)
|
51
|
-
this._buyOptionsSkuPath = skuPath
|
52
|
-
this._paused = true
|
53
|
-
this._closed = false
|
54
|
-
}
|
55
|
-
|
56
|
-
hideBuyOptions = (): void => {
|
57
|
-
this._buyOptionsSkuPath = undefined
|
58
|
-
this._paused = false
|
59
|
-
if (this._lastActivity) {
|
60
|
-
this._lastActivity = Date.now()
|
61
|
-
}
|
62
|
-
}
|
63
|
-
|
64
|
-
get buyOptionsSkuPath(): string | undefined {
|
65
|
-
return this._buyOptionsSkuPath
|
66
|
-
}
|
67
|
-
|
68
|
-
tick = () => {
|
69
|
-
if (
|
70
|
-
!this._paused
|
71
|
-
&&
|
72
|
-
this._lastActivity
|
73
|
-
&&
|
74
|
-
(Date.now() - this._lastActivity >= CommerceUIStore.TIMEOUT)
|
75
|
-
) {
|
76
|
-
this._activeItem = undefined
|
77
|
-
this._lastActivity = undefined
|
78
|
-
}
|
79
|
-
}
|
80
|
-
|
81
|
-
itemQuantityChanged = (sku: string, val: number, oldVal: number): void => {
|
82
|
-
|
83
|
-
if (val === 0) {
|
84
|
-
if (this._activeItem?.sku === sku) {
|
85
|
-
this._activeItem = undefined
|
86
|
-
this._lastActivity = undefined
|
87
|
-
}
|
88
|
-
// otherwise ignore
|
89
|
-
}
|
90
|
-
else if (val < oldVal) {
|
91
|
-
if (this._activeItem?.sku === sku) {
|
92
|
-
this._lastActivity = Date.now()
|
93
|
-
}
|
94
|
-
// otherwise ignore
|
95
|
-
}
|
96
|
-
else {
|
97
|
-
this._activeItem = this._service.getItemBySku(sku)
|
98
|
-
this._lastActivity = Date.now()
|
99
|
-
}
|
100
|
-
}
|
101
|
-
|
102
|
-
get item(): LineItem | undefined {
|
103
|
-
return this._activeItem
|
104
|
-
}
|
105
|
-
|
106
|
-
get closed(): boolean {
|
107
|
-
return this._closed
|
108
|
-
}
|
109
|
-
|
110
|
-
setClosed = (b: boolean): void => { this._closed = b}
|
111
|
-
|
112
|
-
dispose = () => {}
|
113
|
-
}
|
114
|
-
|
115
|
-
export {
|
116
|
-
CommerceUIStore,
|
117
|
-
type CommerceUI
|
118
|
-
}
|
@@ -1,50 +0,0 @@
|
|
1
|
-
'use client'
|
2
|
-
import React, {
|
3
|
-
createContext,
|
4
|
-
useContext,
|
5
|
-
useRef,
|
6
|
-
type PropsWithChildren,
|
7
|
-
useEffect
|
8
|
-
} from 'react'
|
9
|
-
|
10
|
-
// https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
|
11
|
-
import { enableStaticRendering } from 'mobx-react-lite'
|
12
|
-
enableStaticRendering(typeof window === "undefined")
|
13
|
-
|
14
|
-
import { type CommerceUI, CommerceUIStore } from './commerce-ui'
|
15
|
-
import { useCommerce } from '@hanzo/commerce'
|
16
|
-
|
17
|
-
const CommerceUIContext = createContext<CommerceUIStore | undefined>(undefined)
|
18
|
-
|
19
|
-
const useCommerceUI = (): CommerceUI => {
|
20
|
-
return useContext(CommerceUIContext) as CommerceUIStore
|
21
|
-
}
|
22
|
-
|
23
|
-
const CommerceUIProvider: React.FC<PropsWithChildren & {
|
24
|
-
DEBUG_NO_TICK?: boolean
|
25
|
-
}> = ({
|
26
|
-
children,
|
27
|
-
DEBUG_NO_TICK=false
|
28
|
-
}) => {
|
29
|
-
|
30
|
-
const cmmc = useCommerce()
|
31
|
-
const valueRef = useRef<CommerceUIStore>(new CommerceUIStore(cmmc))
|
32
|
-
|
33
|
-
useEffect(() => {
|
34
|
-
|
35
|
-
//valueRef.current = new CommerceUIStore(cmmc)
|
36
|
-
return () => { valueRef.current?.dispose() }
|
37
|
-
}, [])
|
38
|
-
|
39
|
-
return (
|
40
|
-
<CommerceUIContext.Provider value={valueRef.current}>
|
41
|
-
{children}
|
42
|
-
</CommerceUIContext.Provider>
|
43
|
-
)
|
44
|
-
}
|
45
|
-
|
46
|
-
export {
|
47
|
-
useCommerceUI,
|
48
|
-
CommerceUIProvider
|
49
|
-
}
|
50
|
-
|
@@ -1,20 +0,0 @@
|
|
1
|
-
'use client'
|
2
|
-
import React from 'react'
|
3
|
-
|
4
|
-
import type { LineItem } from '@hanzo/commerce/types'
|
5
|
-
import { AddToCartWidget } from '@hanzo/commerce'
|
6
|
-
|
7
|
-
import { useCommerceUI } from '../../commerce/ui-context'
|
8
|
-
|
9
|
-
const AddWidget: React.FC<{
|
10
|
-
item: LineItem
|
11
|
-
disabled?: boolean
|
12
|
-
className?: string
|
13
|
-
buttonClx?: string
|
14
|
-
variant?: 'minimal' | 'primary' | 'outline'
|
15
|
-
}> = (props) => {
|
16
|
-
const ui = useCommerceUI()
|
17
|
-
return <AddToCartWidget {...props} onQuantityChanged={ui.itemQuantityChanged}/>
|
18
|
-
}
|
19
|
-
|
20
|
-
export default AddWidget
|
@@ -1,34 +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 '../../commerce/ui-context'
|
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
|
-
export default BuyButton
|
@@ -1,154 +0,0 @@
|
|
1
|
-
[vaul-drawer] {
|
2
|
-
touch-action: none;
|
3
|
-
transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
|
4
|
-
}
|
5
|
-
|
6
|
-
[vaul-drawer][vaul-drawer-direction='bottom'] {
|
7
|
-
transform: translate3d(0, 100%, 0);
|
8
|
-
}
|
9
|
-
|
10
|
-
[vaul-drawer][vaul-drawer-direction='top'] {
|
11
|
-
transform: translate3d(0, -100%, 0);
|
12
|
-
}
|
13
|
-
|
14
|
-
[vaul-drawer][vaul-drawer-direction='left'] {
|
15
|
-
transform: translate3d(-100%, 0, 0);
|
16
|
-
}
|
17
|
-
|
18
|
-
[vaul-drawer][vaul-drawer-direction='right'] {
|
19
|
-
transform: translate3d(100%, 0, 0);
|
20
|
-
}
|
21
|
-
|
22
|
-
.vaul-dragging .vaul-scrollable [vault-drawer-direction='top'] {
|
23
|
-
overflow-y: hidden !important;
|
24
|
-
}
|
25
|
-
.vaul-dragging .vaul-scrollable [vault-drawer-direction='bottom'] {
|
26
|
-
overflow-y: hidden !important;
|
27
|
-
}
|
28
|
-
|
29
|
-
.vaul-dragging .vaul-scrollable [vault-drawer-direction='left'] {
|
30
|
-
overflow-x: hidden !important;
|
31
|
-
}
|
32
|
-
|
33
|
-
.vaul-dragging .vaul-scrollable [vault-drawer-direction='right'] {
|
34
|
-
overflow-x: hidden !important;
|
35
|
-
}
|
36
|
-
|
37
|
-
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='top'] {
|
38
|
-
transform: translate3d(0, var(--snap-point-height, 0), 0);
|
39
|
-
}
|
40
|
-
|
41
|
-
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='bottom'] {
|
42
|
-
transform: translate3d(0, var(--snap-point-height, 0), 0);
|
43
|
-
}
|
44
|
-
|
45
|
-
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='left'] {
|
46
|
-
transform: translate3d(var(--snap-point-height, 0), 0, 0);
|
47
|
-
}
|
48
|
-
|
49
|
-
[vaul-drawer][vaul-drawer-visible='true'][vaul-drawer-direction='right'] {
|
50
|
-
transform: translate3d(var(--snap-point-height, 0), 0, 0);
|
51
|
-
}
|
52
|
-
|
53
|
-
[vaul-overlay] {
|
54
|
-
opacity: 0;
|
55
|
-
transition: opacity 0.5s cubic-bezier(0.32, 0.72, 0, 1);
|
56
|
-
}
|
57
|
-
|
58
|
-
[vaul-overlay][vaul-drawer-visible='true'] {
|
59
|
-
opacity: 1;
|
60
|
-
}
|
61
|
-
|
62
|
-
[vaul-drawer]::after {
|
63
|
-
content: '';
|
64
|
-
position: absolute;
|
65
|
-
background: inherit;
|
66
|
-
background-color: inherit;
|
67
|
-
}
|
68
|
-
|
69
|
-
[vaul-drawer][vaul-drawer-direction='top']::after {
|
70
|
-
top: initial;
|
71
|
-
bottom: 100%;
|
72
|
-
left: 0;
|
73
|
-
right: 0;
|
74
|
-
height: 200%;
|
75
|
-
}
|
76
|
-
|
77
|
-
[vaul-drawer][vaul-drawer-direction='bottom']::after {
|
78
|
-
top: 100%;
|
79
|
-
bottom: initial;
|
80
|
-
left: 0;
|
81
|
-
right: 0;
|
82
|
-
height: 200%;
|
83
|
-
}
|
84
|
-
|
85
|
-
[vaul-drawer][vaul-drawer-direction='left']::after {
|
86
|
-
left: initial;
|
87
|
-
right: 100%;
|
88
|
-
top: 0;
|
89
|
-
bottom: 0;
|
90
|
-
width: 200%;
|
91
|
-
}
|
92
|
-
|
93
|
-
[vaul-drawer][vaul-drawer-direction='right']::after {
|
94
|
-
left: 100%;
|
95
|
-
right: initial;
|
96
|
-
top: 0;
|
97
|
-
bottom: 0;
|
98
|
-
width: 200%;
|
99
|
-
}
|
100
|
-
|
101
|
-
[vaul-handle] {
|
102
|
-
/* opacity: 0.8; */
|
103
|
-
touch-action: pan-y;
|
104
|
-
cursor: grab;
|
105
|
-
}
|
106
|
-
|
107
|
-
/* [vaul-handle]:hover, */
|
108
|
-
[vaul-handle]:active {
|
109
|
-
opacity: 1;
|
110
|
-
}
|
111
|
-
|
112
|
-
[vaul-handle]:active {
|
113
|
-
cursor: grabbing;
|
114
|
-
}
|
115
|
-
|
116
|
-
[vaul-handle-hitarea] {
|
117
|
-
position: absolute;
|
118
|
-
left: 50%;
|
119
|
-
top: 50%;
|
120
|
-
transform: translate(-50%, -50%);
|
121
|
-
width: max(100%, 2.75rem); /* 44px */
|
122
|
-
height: max(100%, 2.75rem); /* 44px */
|
123
|
-
touch-action: inherit;
|
124
|
-
}
|
125
|
-
|
126
|
-
[vaul-overlay][vaul-snap-points='true']:not([vaul-snap-points-overlay='true']):not([data-state='closed']) {
|
127
|
-
opacity: 0;
|
128
|
-
}
|
129
|
-
|
130
|
-
[vaul-overlay][vaul-snap-points-overlay='true']:not([vaul-drawer-visible='false']) {
|
131
|
-
opacity: 1;
|
132
|
-
}
|
133
|
-
|
134
|
-
/* This will allow us to not animate via animation, but still benefit from delaying unmount via Radix. */
|
135
|
-
@keyframes fake-animation {
|
136
|
-
from {
|
137
|
-
}
|
138
|
-
to {
|
139
|
-
}
|
140
|
-
}
|
141
|
-
|
142
|
-
@media (pointer: fine) {
|
143
|
-
[vaul-handle-hitarea] {
|
144
|
-
width: 100%;
|
145
|
-
height: 100%;
|
146
|
-
}
|
147
|
-
}
|
148
|
-
|
149
|
-
@media (hover: hover) and (pointer: fine) {
|
150
|
-
[vaul-drawer] {
|
151
|
-
user-select: none;
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
File without changes
|
/package/commerce/{data/EDIT-ME-bullion-market-prices.ts → EDIT-ME-bullion-market-prices.ts}
RENAMED
File without changes
|
File without changes
|
/package/commerce/{data/assign-videos-by-family-group.ts → assign-videos-by-family-group.ts}
RENAMED
File without changes
|
File without changes
|
File without changes
|