@luxfi/ui 5.5.3 → 6.0.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/README.md +109 -0
- package/package.json +81 -73
- package/commerce/ui/conf.ts +0 -13
- package/commerce/ui/context.tsx +0 -123
- package/commerce/ui/store.ts +0 -295
- package/components/access-code-input.tsx +0 -71
- package/components/analytics.tsx +0 -23
- package/components/auth/auth-listener.tsx +0 -29
- package/components/auth/auth-token/clear-auth-token.tsx +0 -12
- package/components/auth/auth-token/set-auth-token.tsx +0 -16
- package/components/auth/common-auth-domains.ts +0 -17
- package/components/auth/login-panel.tsx +0 -111
- package/components/auth/mobile-login-button.tsx +0 -107
- package/components/auth/signup-panel.tsx +0 -113
- package/components/back-button.tsx +0 -49
- package/components/chat-widget.tsx +0 -85
- package/components/commerce/bag-button.tsx +0 -98
- package/components/commerce/buy-button.tsx +0 -34
- package/components/commerce/checkout-button.tsx +0 -129
- package/components/commerce/checkout-panel/cart-accordian.tsx +0 -66
- package/components/commerce/checkout-panel/checkout-panel-props.ts +0 -10
- package/components/commerce/checkout-panel/desktop-bag-carousel.tsx +0 -36
- package/components/commerce/checkout-panel/desktop-cp.tsx +0 -83
- package/components/commerce/checkout-panel/index.tsx +0 -126
- package/components/commerce/checkout-panel/mobile-cp.tsx +0 -67
- package/components/commerce/checkout-panel/policy-links.tsx +0 -29
- package/components/commerce/checkout-panel/steps-indicator.tsx +0 -39
- package/components/commerce/checkout-panel/thank-you.tsx +0 -18
- package/components/commerce/desktop-bag-popup.tsx +0 -78
- package/components/commerce/drawer/index.tsx +0 -88
- package/components/commerce/drawer/micro.tsx +0 -145
- package/components/commerce/drawer/shell.tsx +0 -85
- package/components/contact-dialog/contact-form.tsx +0 -116
- package/components/contact-dialog/disclaimer.tsx +0 -13
- package/components/contact-dialog/index.tsx +0 -64
- package/components/copyright.tsx +0 -21
- package/components/drawer-margin.tsx +0 -28
- package/components/footer.tsx +0 -78
- package/components/header/desktop-nav-menu.tsx +0 -204
- package/components/header/desktop.tsx +0 -65
- package/components/header/index.tsx +0 -50
- package/components/header/mobile-bag-drawer.tsx +0 -51
- package/components/header/mobile-menu-toggle-button.tsx +0 -35
- package/components/header/mobile-nav-menu-ai.tsx +0 -51
- package/components/header/mobile-nav-menu-item.tsx +0 -47
- package/components/header/mobile-nav-menu.tsx +0 -102
- package/components/header/mobile.tsx +0 -170
- package/components/header/theme-toggle.tsx +0 -26
- package/components/icons/avatar.tsx +0 -11
- package/components/icons/bag-icon.tsx +0 -10
- package/components/icons/index.ts +0 -6
- package/components/icons/left-arrow.tsx +0 -11
- package/components/icons/lux-logo.tsx +0 -10
- package/components/icons/right-arrow.tsx +0 -10
- package/components/icons/social-icon.tsx +0 -35
- package/components/icons/social-svg.css +0 -3
- package/components/index.ts +0 -26
- package/components/logo.tsx +0 -92
- package/components/main.tsx +0 -27
- package/components/mini-chart/index.tsx +0 -8
- package/components/mini-chart/mini-chart-props.ts +0 -44
- package/components/mini-chart/mini-chart.tsx +0 -85
- package/components/mini-chart/wrapper.tsx +0 -23
- package/components/not-found/index.tsx +0 -28
- package/components/not-found/not-found-content.mdx +0 -5
- package/components/tooltip.tsx +0 -31
- package/environment.d.ts +0 -6
- package/next/analytics/fpixel.ts +0 -16
- package/next/analytics/google-analytics.ts +0 -14
- package/next/analytics/index.ts +0 -3
- package/next/analytics/pixel-analytics.tsx +0 -55
- package/next/font/get-app-router-font-classes.ts +0 -17
- package/next/font/load-and-return-lux-next-fonts-on-import.ts +0 -68
- package/next/font/local/Druk-Wide-Bold.ttf +0 -0
- package/next/font/local/Druk-Wide-Medium.ttf +0 -0
- package/next/font/local/InterVariable-Italic.ttf +0 -0
- package/next/font/local/InterVariable-Italic.woff2 +0 -0
- package/next/font/local/InterVariable.ttf +0 -0
- package/next/font/local/InterVariable.woff2 +0 -0
- package/next/font/next-font-desc.ts +0 -28
- package/next/font/pages-router-font-vars.tsx +0 -18
- package/next/head-metadata/from-next/metadata-types.ts +0 -158
- package/next/head-metadata/from-next/opengraph-types.ts +0 -267
- package/next/head-metadata/from-next/twitter-types.ts +0 -92
- package/next/head-metadata/index.tsx +0 -208
- package/next/index.ts +0 -2
- package/next/middleware/determine-device-mw.ts +0 -29
- package/root-layout/WHY_THIS_IS_SEPARATE.txt +0 -2
- package/root-layout/index.tsx +0 -112
- package/site-def/footer/community.tsx +0 -61
- package/site-def/footer/company.ts +0 -37
- package/site-def/footer/ecosystem.ts +0 -37
- package/site-def/footer/index.tsx +0 -26
- package/site-def/footer/legal.ts +0 -28
- package/site-def/footer/network.ts +0 -45
- package/site-def/footer/svg/warpcast-logo.svg +0 -12
- package/site-def/index.ts +0 -4
- package/site-def/main-nav.tsx +0 -460
- package/style/cart-animation.css +0 -29
- package/style/checkout-animation.css +0 -23
- package/style/drawer-handle-overrides.css +0 -160
- package/style/fonts/COPY_TO_PUBLIC_FOR_NON_NEXT.txt +0 -0
- package/style/fonts/Druk-Wide-Bold.ttf +0 -0
- package/style/fonts/Druk-Wide-Medium.ttf +0 -0
- package/style/fonts/InterVariable-Italic.ttf +0 -0
- package/style/fonts/InterVariable-Italic.woff2 +0 -0
- package/style/fonts/InterVariable.ttf +0 -0
- package/style/fonts/InterVariable.woff2 +0 -0
- package/style/lux-colors.css +0 -85
- package/style/lux-fonts.css +0 -30
- package/style/lux-global-non-next.css +0 -52
- package/style/lux-global.css +0 -51
- package/tailwind/fontFamily.tailwind.lux.ts +0 -18
- package/tailwind/index.ts +0 -2
- package/tailwind/lux-tw-fonts.ts +0 -40
- package/tailwind/tailwind.config.lux-preset.ts +0 -10
- package/tsconfig.json +0 -15
- package/types/chatbot-config.ts +0 -7
- package/types/chatbot-suggested-question.ts +0 -7
- package/types/contact-info.ts +0 -11
- package/types/index.ts +0 -4
- package/types/site-def.ts +0 -46
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { type PropsWithChildren } from 'react'
|
|
3
|
-
import { observer } from 'mobx-react-lite'
|
|
4
|
-
|
|
5
|
-
import { ScrollArea, StepIndicator } from '@hanzo/ui/primitives'
|
|
6
|
-
import { AuthWidget } from '@hanzo/auth/components'
|
|
7
|
-
import { CartPanel, useCommerce } from '@hanzo/commerce'
|
|
8
|
-
import { cn } from '@hanzo/ui/util'
|
|
9
|
-
|
|
10
|
-
import { BackButton, Logo, Tooltip } from '../..'
|
|
11
|
-
import DesktopBagCarousel from './desktop-bag-carousel'
|
|
12
|
-
import LinksRow from './policy-links'
|
|
13
|
-
import type CheckoutPanelProps from './checkout-panel-props'
|
|
14
|
-
|
|
15
|
-
const DesktopCheckoutPanel: React.FC<PropsWithChildren & CheckoutPanelProps> = observer(({
|
|
16
|
-
step,
|
|
17
|
-
stepNames,
|
|
18
|
-
onLeave,
|
|
19
|
-
clx='',
|
|
20
|
-
children
|
|
21
|
-
}) => {
|
|
22
|
-
|
|
23
|
-
const cmmc = useCommerce()
|
|
24
|
-
return (
|
|
25
|
-
<div /* id='CHECKOUT_PANEL' */ className={cn('grid grid-cols-2', clx)}>
|
|
26
|
-
<div key={1} className='w-full h-full bg-background flex flex-row items-start justify-end'>
|
|
27
|
-
<div className='w-full h-full max-w-[750px] relative flex flex-col items-stretch justify-start px-8 pb-8'>
|
|
28
|
-
<div key={1} className='h-[80px] grow-0 flex flex-row items-center z-10' >
|
|
29
|
-
<Logo size='md' href='/' onClick={onLeave} variant='text-only' outerClx='logo-outer-tooltip-class' />
|
|
30
|
-
<Tooltip select='.logo-outer-tooltip-class' text='home' position='right' offset={6}/>
|
|
31
|
-
</div>
|
|
32
|
-
<BackButton
|
|
33
|
-
size='sm'
|
|
34
|
-
clx={
|
|
35
|
-
'z-10 absolute top-14 left-6 !px-0 aspect-square ' +
|
|
36
|
-
'rounded-full hover:!bg-level-3 ' +
|
|
37
|
-
'back-button-tooltip-class '
|
|
38
|
-
}
|
|
39
|
-
onBack={onLeave}
|
|
40
|
-
/>
|
|
41
|
-
<Tooltip select='.back-button-tooltip-class' text='back' position='right' offset={5}/>
|
|
42
|
-
<div key={2} className={cn(
|
|
43
|
-
'w-full grow min-h-0 max-w-[550px] mx-auto flex flex-col gap-3',
|
|
44
|
-
(cmmc.cartItems.length > 4 ? 'justify-between' : 'justify-start gap-10 pt-10')
|
|
45
|
-
)}>
|
|
46
|
-
<DesktopBagCarousel className='grow-0 h-[260px] w-[360px] lg:w-[420px] mx-auto -mt-8' constrainTo={{w: 250, h: 250}}/>
|
|
47
|
-
<CartPanel
|
|
48
|
-
className='w-full border-none p-0'
|
|
49
|
-
itemClx='mb-2'
|
|
50
|
-
totalClx='sticky bottom-0 bg-background'
|
|
51
|
-
listClx='pr-3'
|
|
52
|
-
scrollAfter={4}
|
|
53
|
-
scrollHeightClx='min-h-[50vh] grow'
|
|
54
|
-
showPromoCode
|
|
55
|
-
showShipping
|
|
56
|
-
selectItems
|
|
57
|
-
/>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
<div key={2} className='w-full h-full flex flex-col bg-level-1 min-h-screen justify-between'>
|
|
62
|
-
<ScrollArea className='w-full flex flex-row items-start justify-start overflow-y-auto'>
|
|
63
|
-
<div className='h-full w-full max-w-[750px] relative flex flex-col items-center px-8 pt-0'>
|
|
64
|
-
<div key={1} className='bg-level-1 sticky h-[80px] bg-[#aaaaff] w-full top-0 flex justify-center items-end'>
|
|
65
|
-
<AuthWidget noLogin className='hidden md:flex absolute top-4 right-4 '/>
|
|
66
|
-
<StepIndicator dotSizeRem={1.35} steps={stepNames} currentStep={step} className='gap-2 text-base w-pr-70' />
|
|
67
|
-
</div>
|
|
68
|
-
<div key={2} className='w-full max-w-[550px] mx-auto py-8'>
|
|
69
|
-
{children}
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
</ScrollArea>
|
|
73
|
-
<div className='w-full max-w-[750px] relative flex flex-col items-center px-8 pt-0'>
|
|
74
|
-
<div className='w-full max-w-[550px] mx-auto flex flex-col items-center'>
|
|
75
|
-
<LinksRow clx='w-full' />
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
export default DesktopCheckoutPanel
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { useLayoutEffect, useRef, useState } from 'react'
|
|
3
|
-
|
|
4
|
-
import { capitalize, cn } from '@hanzo/ui/util'
|
|
5
|
-
|
|
6
|
-
import { useCommerce, ShippingStepForm, PaymentStepForm } from '@hanzo/commerce'
|
|
7
|
-
import type { CheckoutStep } from '@hanzo/commerce/types'
|
|
8
|
-
|
|
9
|
-
import ThankYou from './thank-you'
|
|
10
|
-
|
|
11
|
-
const STEPS = [
|
|
12
|
-
{
|
|
13
|
-
name: 'payment',
|
|
14
|
-
Comp: PaymentStepForm
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
name: 'delivery',
|
|
18
|
-
Comp: ShippingStepForm
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: 'done',
|
|
22
|
-
label: 'Done!',
|
|
23
|
-
Comp: ThankYou
|
|
24
|
-
}
|
|
25
|
-
] satisfies CheckoutStep[]
|
|
26
|
-
|
|
27
|
-
const STEP_NAMES = STEPS.map((s) => (s.label ? s.label : capitalize(s.name)))
|
|
28
|
-
|
|
29
|
-
import DesktopCP from './desktop-cp'
|
|
30
|
-
import MobileCP from './mobile-cp'
|
|
31
|
-
|
|
32
|
-
const CheckoutPanel: React.FC<{
|
|
33
|
-
clx?: string
|
|
34
|
-
}> = ({
|
|
35
|
-
clx=''
|
|
36
|
-
}) => {
|
|
37
|
-
|
|
38
|
-
const cmmc = useCommerce()
|
|
39
|
-
|
|
40
|
-
// For sites that don't initialize cmmc
|
|
41
|
-
if (!cmmc) {
|
|
42
|
-
console.log("CHECKOUT PANEL: cmmc svc undefined!")
|
|
43
|
-
return <></>
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const [stepIndex, setStepIndex] = useState<number>(0)
|
|
47
|
-
const [orderId, setOrderId] = useState<string | undefined>(undefined)
|
|
48
|
-
|
|
49
|
-
// Step.name or 'first' or 'next' or 'last'
|
|
50
|
-
const setStep = (name: string): void => {
|
|
51
|
-
|
|
52
|
-
if (name === 'first') {
|
|
53
|
-
setStepIndex(0)
|
|
54
|
-
}
|
|
55
|
-
else if (name === 'last') {
|
|
56
|
-
setStepIndex(STEPS.length - 1)
|
|
57
|
-
}
|
|
58
|
-
else if (name === 'next') {
|
|
59
|
-
if (stepIndex <= STEPS.length - 2) {
|
|
60
|
-
setStepIndex(stepIndex + 1)
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
throw new Error('CheckoutPanel.setStep(): Attempting to advance past last step!')
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
const indexFound = STEPS.findIndex((el) => (el.name === name))
|
|
68
|
-
if (indexFound !== -1) {
|
|
69
|
-
setStepIndex(indexFound)
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
throw new Error('CheckoutPanel.setStep(): Step named ' + name + ' not found!')
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const _close = () => {
|
|
78
|
-
setStep('first')
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Determine if mobile or desktop layout based on visibility of desktopElement
|
|
82
|
-
// This prevents issues with multiple instances of 3rd party e-commerce widgets
|
|
83
|
-
// from ever being in the DOM.
|
|
84
|
-
// https://stackoverflow.com/a/21696585/11378853
|
|
85
|
-
const desktopElement = useRef<HTMLDivElement | null>(null)
|
|
86
|
-
const [layout, setLayout] = useState<'mobile' | 'desktop' | undefined>(undefined)
|
|
87
|
-
|
|
88
|
-
useLayoutEffect(() => {
|
|
89
|
-
const checkLayout = () => {
|
|
90
|
-
setLayout(!!desktopElement.current?.offsetParent ? 'desktop' : 'mobile')
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// initial layout check
|
|
94
|
-
checkLayout()
|
|
95
|
-
|
|
96
|
-
window.addEventListener('resize', checkLayout)
|
|
97
|
-
return () => {
|
|
98
|
-
window.removeEventListener('resize', checkLayout)
|
|
99
|
-
}
|
|
100
|
-
}, [])
|
|
101
|
-
|
|
102
|
-
const StepToRender = STEPS[stepIndex].Comp
|
|
103
|
-
|
|
104
|
-
return (<>
|
|
105
|
-
<DesktopCP
|
|
106
|
-
clx={cn('h-full', clx, 'hidden md:flex')}
|
|
107
|
-
onLeave={_close}
|
|
108
|
-
step={stepIndex}
|
|
109
|
-
stepNames={STEP_NAMES}
|
|
110
|
-
>
|
|
111
|
-
{/* Element required to determine if DesktopCP is visible. See above. */}
|
|
112
|
-
<div ref={desktopElement}/>
|
|
113
|
-
{layout === 'desktop' && <StepToRender onDone={() => {setStep('next')}} orderId={orderId} setOrderId={setOrderId}/>}
|
|
114
|
-
</DesktopCP>
|
|
115
|
-
<MobileCP
|
|
116
|
-
clx={cn('w-full h-full overflow-y-auto', clx, 'md:hidden' )}
|
|
117
|
-
onLeave={_close}
|
|
118
|
-
step={stepIndex}
|
|
119
|
-
stepNames={STEP_NAMES}
|
|
120
|
-
>
|
|
121
|
-
{layout === 'mobile' && <StepToRender onDone={() => {setStep('next')}} orderId={orderId} setOrderId={setOrderId}/>}
|
|
122
|
-
</MobileCP>
|
|
123
|
-
</>)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export default CheckoutPanel
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { type PropsWithChildren } from 'react'
|
|
3
|
-
|
|
4
|
-
import { StepIndicator } from '@hanzo/ui/primitives'
|
|
5
|
-
import { cn } from '@hanzo/ui/util'
|
|
6
|
-
import { AuthWidget } from '@hanzo/auth/components'
|
|
7
|
-
|
|
8
|
-
import { BackButton, Logo } from '../..'
|
|
9
|
-
import BagButton from '../bag-button'
|
|
10
|
-
import PolicyLinks from './policy-links'
|
|
11
|
-
import CartAccordian from './cart-accordian'
|
|
12
|
-
import type CheckoutPanelProps from './checkout-panel-props'
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const MobileCheckoutPanel: React.FC<PropsWithChildren & CheckoutPanelProps> = ({
|
|
16
|
-
step,
|
|
17
|
-
stepNames,
|
|
18
|
-
onLeave,
|
|
19
|
-
clx='',
|
|
20
|
-
children
|
|
21
|
-
}) => (
|
|
22
|
-
|
|
23
|
-
<div /* id='MOBILE_GRID' */ className={cn('bg-background flex flex-col justify-start px-4 pt-[101px]', clx)}>
|
|
24
|
-
<div className='fixed z-11 top-0 h-[45px] w-full flex justify-between items-stretch bg-background'>
|
|
25
|
-
<div className='flex items-stretch gap-1 grow-0'>
|
|
26
|
-
<BackButton
|
|
27
|
-
size='sm'
|
|
28
|
-
clx={
|
|
29
|
-
'-ml-5 !px-0 aspect-square h-full ' +
|
|
30
|
-
'rounded-full active:!bg-level-3 '
|
|
31
|
-
}
|
|
32
|
-
onBack={onLeave}
|
|
33
|
-
/>
|
|
34
|
-
<Logo size='xs' variant='text-only' href='/' onClick={onLeave} outerClx='-ml-2'/>
|
|
35
|
-
</div>
|
|
36
|
-
<StepIndicator
|
|
37
|
-
dotSizeRem={1}
|
|
38
|
-
steps={stepNames}
|
|
39
|
-
currentStep={step}
|
|
40
|
-
className='relative grow mx-2 top-[14px] text-xs font-semibold w-full'
|
|
41
|
-
/>
|
|
42
|
-
|
|
43
|
-
{/* 72px by observation (for centering). Need wrapper div since 'noLogin' returns null if no logged in user */}
|
|
44
|
-
<div className='w-[72px] grow-0 shrink-0 flex items-center justify-center'><AuthWidget noLogin className=''/></div>
|
|
45
|
-
</div>
|
|
46
|
-
<CartAccordian
|
|
47
|
-
icon={
|
|
48
|
-
<BagButton
|
|
49
|
-
animateOnHover={false}
|
|
50
|
-
showIfEmpty
|
|
51
|
-
size='sm'
|
|
52
|
-
className='mr-1 relative w-5 h-6 sm:w-6 sm:h-7'
|
|
53
|
-
iconClx='fill-foreground'
|
|
54
|
-
/>
|
|
55
|
-
}
|
|
56
|
-
clx='flex items-center justify-center w-full'
|
|
57
|
-
triggerClx='bg-background fixed z-11 top-[45px] left-0 right-0 !m-0 px-4'
|
|
58
|
-
panelClx='!py-0'
|
|
59
|
-
scrollAfter={3}
|
|
60
|
-
scrollHeightClx='h-[385px]'
|
|
61
|
-
/>
|
|
62
|
-
{children}
|
|
63
|
-
<PolicyLinks clx='mt-auto mb-3 pt-2' />
|
|
64
|
-
</div>
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
export default MobileCheckoutPanel
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import Link from 'next/link'
|
|
3
|
-
|
|
4
|
-
import { Separator, buttonVariants } from '@hanzo/ui/primitives'
|
|
5
|
-
import { cn } from '@hanzo/ui/util'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const linkClx = buttonVariants({
|
|
9
|
-
variant: 'linkMuted',
|
|
10
|
-
size: 'link',
|
|
11
|
-
rounded: 'none',
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
const PolicyLinks: React.FC<{
|
|
15
|
-
clx?: string
|
|
16
|
-
}> = ({
|
|
17
|
-
clx=''
|
|
18
|
-
}) => (
|
|
19
|
-
<div className={cn('flex flex-col items-center', clx)}>
|
|
20
|
-
<Separator/>
|
|
21
|
-
<div className='flex gap-4 py-2 text-sm'>
|
|
22
|
-
{/* TODO: add Refund policy and Privacy policy links */}
|
|
23
|
-
<Link className={linkClx} href=''>refund policy</Link>
|
|
24
|
-
<Link className={linkClx} href=''>privacy policy</Link>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
export default PolicyLinks
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Breadcrumb,
|
|
3
|
-
BreadcrumbItem,
|
|
4
|
-
BreadcrumbLink,
|
|
5
|
-
BreadcrumbList,
|
|
6
|
-
BreadcrumbSeparator
|
|
7
|
-
} from '@hanzo/ui/primitives'
|
|
8
|
-
import { cn } from '@hanzo/ui/util'
|
|
9
|
-
|
|
10
|
-
const StepsIndicator: React.FC<{
|
|
11
|
-
currentStep: number
|
|
12
|
-
stepNames: string[]
|
|
13
|
-
className?: string
|
|
14
|
-
}> = ({
|
|
15
|
-
currentStep,
|
|
16
|
-
stepNames,
|
|
17
|
-
className=''
|
|
18
|
-
}) => (
|
|
19
|
-
<Breadcrumb className={className}>
|
|
20
|
-
<BreadcrumbList>
|
|
21
|
-
{stepNames.map((name, i) => (
|
|
22
|
-
<>
|
|
23
|
-
<BreadcrumbItem key={`item-${i}`}>
|
|
24
|
-
<BreadcrumbLink className={cn(
|
|
25
|
-
currentStep >= i ? '!text-foreground hover:text-foreground' : 'hover:text-muted-2',
|
|
26
|
-
'text-xxs sm:text-sm'
|
|
27
|
-
)}
|
|
28
|
-
>
|
|
29
|
-
{name}
|
|
30
|
-
</BreadcrumbLink>
|
|
31
|
-
</BreadcrumbItem>
|
|
32
|
-
{i !== stepNames.length - 1 && <BreadcrumbSeparator key={`sep-${i}`}/>}
|
|
33
|
-
</>
|
|
34
|
-
))}
|
|
35
|
-
</BreadcrumbList>
|
|
36
|
-
</Breadcrumb>
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
export default StepsIndicator
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import Link from 'next/link'
|
|
3
|
-
|
|
4
|
-
import { ApplyTypography } from '@hanzo/ui/primitives'
|
|
5
|
-
|
|
6
|
-
import type { CheckoutStepComponentProps } from '@hanzo/commerce/types'
|
|
7
|
-
|
|
8
|
-
const ThankYou: React.FC<CheckoutStepComponentProps> = ({}) => (
|
|
9
|
-
<ApplyTypography className='flex flex-col gap-4 text-center mt-10'>
|
|
10
|
-
<h3>Thank you for your order!</h3>
|
|
11
|
-
<h6>Once your payment has been confirmed, you'll recieve an email with additional information.</h6>
|
|
12
|
-
<p>
|
|
13
|
-
While you wait, we cordially invite you to join the <Link href='https://warpcast.com/~/channel/lux'>Lux Channel</Link> on <Link href='https://warpcast.com/~/invite-page/227706?id=fbc9ca91'>Warpcast</Link>.
|
|
14
|
-
</p>
|
|
15
|
-
</ApplyTypography>
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
export default ThankYou
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React, { useState, useEffect } from 'react'
|
|
3
|
-
import { useRouter } from 'next/navigation'
|
|
4
|
-
|
|
5
|
-
import { X } from 'lucide-react'
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
Popover,
|
|
9
|
-
PopoverContent,
|
|
10
|
-
PopoverTrigger,
|
|
11
|
-
PopoverClose,
|
|
12
|
-
} from "@hanzo/ui/primitives"
|
|
13
|
-
|
|
14
|
-
import { cn } from '@hanzo/ui/util'
|
|
15
|
-
import { CartPanel, useCommerce } from '@hanzo/commerce'
|
|
16
|
-
|
|
17
|
-
import { Bag } from '../icons'
|
|
18
|
-
import sendGAEvent from '../../next/analytics/google-analytics'
|
|
19
|
-
|
|
20
|
-
const DesktopBagPopup: React.FC<{
|
|
21
|
-
triggerClx?: string
|
|
22
|
-
popupClx?: string
|
|
23
|
-
trigger: React.ReactNode
|
|
24
|
-
}> = ({
|
|
25
|
-
triggerClx='',
|
|
26
|
-
popupClx='',
|
|
27
|
-
trigger
|
|
28
|
-
}) => {
|
|
29
|
-
const cmmc = useCommerce()
|
|
30
|
-
|
|
31
|
-
const [bagOpen, setBagOpen] = useState<boolean>(false)
|
|
32
|
-
const router = useRouter()
|
|
33
|
-
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (bagOpen) {
|
|
36
|
-
sendGAEvent('view_cart', {
|
|
37
|
-
items: cmmc.cartItems.map((item) => ({
|
|
38
|
-
item_id: item.sku,
|
|
39
|
-
item_name: item.title,
|
|
40
|
-
item_category: item.familyId,
|
|
41
|
-
price: item.price,
|
|
42
|
-
quantity: item.quantity
|
|
43
|
-
})),
|
|
44
|
-
value: cmmc.cartTotal,
|
|
45
|
-
currency: 'USD',
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
}, [bagOpen])
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<Popover open={bagOpen} onOpenChange={setBagOpen}>
|
|
52
|
-
<PopoverTrigger className={triggerClx}>
|
|
53
|
-
{trigger}
|
|
54
|
-
</PopoverTrigger>
|
|
55
|
-
<PopoverContent sideOffset={28} className={cn('relative flex flex-col p-0 px-4 pb-4 pt-2', popupClx)}>
|
|
56
|
-
<PopoverClose className='absolute z-above-content right-2 top-2 self-end hover:bg-level-3 text-muted hover:text-accent p-1 rounded-full'><X className='w-5 h-5'/></PopoverClose>
|
|
57
|
-
<CartPanel
|
|
58
|
-
handleCheckout={() => {router.push('/checkout')}}
|
|
59
|
-
className='mt-4 mb-4 border-none py-0 px-4'
|
|
60
|
-
listClx='rounded-sm pr-3'
|
|
61
|
-
scrollAfter={5}
|
|
62
|
-
scrollHeightClx='h-[70vh]'
|
|
63
|
-
itemClx='mt-3'
|
|
64
|
-
totalClx='sticky px-1 pr-2 -bottom-[1px] bg-level-1'
|
|
65
|
-
buttonClx='max-w-[220px] flex-none'
|
|
66
|
-
>
|
|
67
|
-
<div className='flex flex-row items-center flex-none justify-center '>
|
|
68
|
-
<Bag className='mr-2 relative w-6 h-7 fill-foreground ' />
|
|
69
|
-
<p className='font-heading text-foreground text-default'>Your Bag</p>
|
|
70
|
-
</div>
|
|
71
|
-
<div className='h-[1px] w-pr-80 bg-muted-3 mx-auto mt-1.5 flex-none'/>
|
|
72
|
-
</CartPanel>
|
|
73
|
-
</PopoverContent>
|
|
74
|
-
</Popover>
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export default DesktopBagPopup
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { useRouter } from 'next/navigation'
|
|
4
|
-
import { observer } from 'mobx-react-lite'
|
|
5
|
-
|
|
6
|
-
import { CarouselBuyCard } from '@hanzo/commerce'
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
useSelectAndBuy,
|
|
10
|
-
useCommerceDrawer,
|
|
11
|
-
} from '../../../commerce/ui/context'
|
|
12
|
-
|
|
13
|
-
import CommerceDrawer from './shell'
|
|
14
|
-
import CheckoutButton from '../checkout-button'
|
|
15
|
-
import Micro from './micro'
|
|
16
|
-
|
|
17
|
-
const CommerceUIComponent: React.FC = observer(() => {
|
|
18
|
-
|
|
19
|
-
const buy = useSelectAndBuy()
|
|
20
|
-
const drawer = useCommerceDrawer()
|
|
21
|
-
const router = useRouter()
|
|
22
|
-
|
|
23
|
-
const handleCheckout = (): void => {
|
|
24
|
-
router.push('/checkout')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const handleHandleClicked = (): void => {
|
|
28
|
-
|
|
29
|
-
if (drawer.state === 'full') {
|
|
30
|
-
buy.hideVariants()
|
|
31
|
-
}
|
|
32
|
-
else if (drawer.state === 'micro') {
|
|
33
|
-
buy.showRecentVariants()
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const handleItemClicked = () => {
|
|
38
|
-
buy.showRecentVariants()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const handleCloseGesture = (): boolean => {
|
|
42
|
-
if (drawer.state === 'full') {
|
|
43
|
-
buy.hideVariants()
|
|
44
|
-
return true // "handled!"
|
|
45
|
-
}
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<CommerceDrawer
|
|
51
|
-
handleHandleClicked={handleHandleClicked}
|
|
52
|
-
handleCloseGesture={handleCloseGesture}
|
|
53
|
-
drawerClx='flex flex-col'
|
|
54
|
-
>
|
|
55
|
-
{drawer.state === 'full' && (
|
|
56
|
-
/* The actual drawer is larger than the visible area (due to awkward
|
|
57
|
-
vaul impl. So we have to ask the drawer for its currect snappoint
|
|
58
|
-
and constrain layout to that.
|
|
59
|
-
*/
|
|
60
|
-
<div style={{height: drawer.snapPointPx - 24 /* fudge factor for handle area */}} >
|
|
61
|
-
<CarouselBuyCard
|
|
62
|
-
skuPath={buy.currentSkuPath!}
|
|
63
|
-
checkoutButton={
|
|
64
|
-
<CheckoutButton
|
|
65
|
-
handleCheckout={handleCheckout}
|
|
66
|
-
className='w-full min-w-[160px] sm:max-w-[320px]'
|
|
67
|
-
/>
|
|
68
|
-
}
|
|
69
|
-
clx='justify-between h-full pb-3 gap-8'
|
|
70
|
-
addBtnClx='w-full min-w-[160px] sm:max-w-[320px]'
|
|
71
|
-
buttonsAreaClx='grow-0 shrink-0 mt-0'
|
|
72
|
-
selectorClx='max-w-[475px] justify-between grow'
|
|
73
|
-
|
|
74
|
-
/>
|
|
75
|
-
</div>
|
|
76
|
-
)}
|
|
77
|
-
{drawer.state === 'micro' && (
|
|
78
|
-
<Micro
|
|
79
|
-
handleCheckout={handleCheckout}
|
|
80
|
-
handleItemClicked={handleItemClicked}
|
|
81
|
-
clx='w-full px-2 sm:w-[460px] sm:mx-auto md:w-[550px]'
|
|
82
|
-
/>
|
|
83
|
-
)}
|
|
84
|
-
</CommerceDrawer>
|
|
85
|
-
)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
export default CommerceUIComponent
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { observer } from 'mobx-react-lite'
|
|
4
|
-
|
|
5
|
-
import { Button, Image } from '@hanzo/ui/primitives'
|
|
6
|
-
import { cn, } from '@hanzo/ui/util'
|
|
7
|
-
import type { LineItem } from '@hanzo/commerce/types'
|
|
8
|
-
import { useCommerce, formatCurrencyValue } from '@hanzo/commerce'
|
|
9
|
-
|
|
10
|
-
import CheckoutButton from '../checkout-button'
|
|
11
|
-
import { useCommerceDrawer } from '../../../commerce/ui/context'
|
|
12
|
-
|
|
13
|
-
const CN = {
|
|
14
|
-
// h: mind padding!
|
|
15
|
-
mobile: { w: 36, h: 32 },
|
|
16
|
-
sm: { w: 60, h: 34 },
|
|
17
|
-
desktop: { w: 60, h: 32 },
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const Info: React.FC<{
|
|
21
|
-
item: LineItem
|
|
22
|
-
clx?: string
|
|
23
|
-
}> = ({
|
|
24
|
-
item,
|
|
25
|
-
clx=''
|
|
26
|
-
}) => {
|
|
27
|
-
|
|
28
|
-
const cmmc = useCommerce()
|
|
29
|
-
const family = cmmc.getFamilyById(item.familyId)
|
|
30
|
-
|
|
31
|
-
let topLine = family!.title
|
|
32
|
-
if (item.sku.startsWith('LXM-AG') || item.sku.startsWith('LXM-AU')) {
|
|
33
|
-
topLine = family!.parentTitle + ', ' + family!.title
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const optionLabel = item.optionLabelShort ?? item.optionLabel
|
|
37
|
-
const priceStr = formatCurrencyValue(item.price)
|
|
38
|
-
|
|
39
|
-
return (<>
|
|
40
|
-
<div className={cn('sm:hidden flex flex-col !text-muted items-stretch whitespace-nowrap text-ellipsis ', clx)}>
|
|
41
|
-
<p className='text-left text-xs'>{topLine}</p>
|
|
42
|
-
<div className='flex justify-between text-xxs'>
|
|
43
|
-
<div>{optionLabel}</div>
|
|
44
|
-
<div className='pl-2.5'>{priceStr}</div>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
<div className={cn('hidden sm:flex !text-muted flex-col items-stretch whitespace-nowrap text-ellipsis text-xs', clx)}>
|
|
48
|
-
<p className='text-left'>{topLine}</p>
|
|
49
|
-
<div className='flex justify-between'>
|
|
50
|
-
<div>{optionLabel}</div>
|
|
51
|
-
<div className='pl-2.5'>{priceStr}</div>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
</>)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const PROMPT_COMMON_CLX = 'block absolute top-0 left-0 bg-transparent duration-400 transition-opacity'
|
|
58
|
-
|
|
59
|
-
const Micro: React.FC<{
|
|
60
|
-
clx?: string
|
|
61
|
-
handleCheckout: () => void
|
|
62
|
-
handleItemClicked: () => void
|
|
63
|
-
}> = observer(({
|
|
64
|
-
clx='',
|
|
65
|
-
handleCheckout,
|
|
66
|
-
handleItemClicked
|
|
67
|
-
}) => {
|
|
68
|
-
|
|
69
|
-
const drawer = useCommerceDrawer()
|
|
70
|
-
const cmmc = useCommerce()
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<div className={cn(
|
|
74
|
-
(drawer.showRecent ? 'grid grid-cols-2' : 'flex justify-center items-center '),
|
|
75
|
-
(drawer.showRecent ? ((drawer.isMobile) ? '-mt-3' : '-mt-3') : ''),
|
|
76
|
-
'gap-2 md:gap-3 relative',
|
|
77
|
-
clx
|
|
78
|
-
)}>
|
|
79
|
-
{drawer.showRecent && (
|
|
80
|
-
<div className={'flex flex-col items-stretch ' + (drawer.isMobile ? 'justify-start' : 'group')}>
|
|
81
|
-
<p className={'relative text-muted text-xxs md:text-xs leading-none pl-1 self-start ' + (drawer.isMobile ? 'top-[3px]' : 'top-[1px]')}>
|
|
82
|
-
<span className='invisible'>scrictly for layout</span>
|
|
83
|
-
{drawer.isMobile ? (
|
|
84
|
-
<span className={PROMPT_COMMON_CLX}>tap for options:</span>
|
|
85
|
-
) : (<>
|
|
86
|
-
<span className={PROMPT_COMMON_CLX + ' group-hover:opacity-0'}>recent item:</span>
|
|
87
|
-
<span className={PROMPT_COMMON_CLX + ' opacity-0 group-hover:opacity-100'}>view options:</span>
|
|
88
|
-
</>)}
|
|
89
|
-
</p>
|
|
90
|
-
<Button
|
|
91
|
-
variant='ghost'
|
|
92
|
-
rounded={drawer.isMobile ? 'md' : 'lg'}
|
|
93
|
-
size={drawer.isMobile ? 'sm' : 'default'}
|
|
94
|
-
onClick={handleItemClicked}
|
|
95
|
-
className={cn(
|
|
96
|
-
'box-content',
|
|
97
|
-
'flex flex-row justify-between items-center gap-1',
|
|
98
|
-
'-ml-1.5',
|
|
99
|
-
'overflow-hidden ',
|
|
100
|
-
'px-1 md:px-2 py-[2px]',
|
|
101
|
-
'border border-transparent group-hover:border-muted-3',
|
|
102
|
-
'group-hover:!bg-transparent',
|
|
103
|
-
'!min-w-0'
|
|
104
|
-
)}
|
|
105
|
-
>
|
|
106
|
-
{cmmc.recentItem?.item.img && (<>
|
|
107
|
-
<Image def={cmmc.recentItem.item.img} constrainTo={CN.mobile} preload className='sm:hidden grow-0 shrink-0'/>
|
|
108
|
-
<Image def={cmmc.recentItem.item.img} constrainTo={CN.sm} preload className='hidden sm:block md:hidden grow-0 shrink-0'/>
|
|
109
|
-
<Image def={cmmc.recentItem.item.img} constrainTo={CN.desktop} preload className='hidden md:block grow-0 shrink-0'/>
|
|
110
|
-
</>)}
|
|
111
|
-
{cmmc.recentItem && (
|
|
112
|
-
<div className='grow w-full'>
|
|
113
|
-
<Info item={cmmc.recentItem.item} clx='w-full'/>
|
|
114
|
-
</div>
|
|
115
|
-
)}
|
|
116
|
-
</Button>
|
|
117
|
-
</div>
|
|
118
|
-
)}
|
|
119
|
-
{drawer.showCheckout && (
|
|
120
|
-
<div className={cn(
|
|
121
|
-
'flex flex-col w-full',
|
|
122
|
-
(drawer.showRecent ? 'items-stretch' : 'items-center' ),
|
|
123
|
-
(drawer.isMobile ? 'justify-start' : 'justify-center')
|
|
124
|
-
)}>
|
|
125
|
-
{drawer.showRecent && <p className='invisible text-muted text-xxs md:text-xs leading-none pl-1 self-start'>for layout</p>}
|
|
126
|
-
<CheckoutButton
|
|
127
|
-
handleCheckout={handleCheckout}
|
|
128
|
-
variant='primary'
|
|
129
|
-
size={drawer.isMobile ? 'xs' : 'lg'}
|
|
130
|
-
rounded={drawer.isMobile ? 'md' : 'lg'}
|
|
131
|
-
centerText={drawer.isMobile ? !drawer.showRecent : true}
|
|
132
|
-
className={cn(drawer.isMobile ?
|
|
133
|
-
(drawer.showRecent ? 'pl-3.5 pr-2.5' : 'min-w-[320px]')
|
|
134
|
-
:
|
|
135
|
-
(drawer.showRecent ? '' : 'w-[320px]'),
|
|
136
|
-
'text-sm font-semibold'
|
|
137
|
-
)}
|
|
138
|
-
/>
|
|
139
|
-
</div>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
|
-
)
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
export default Micro
|