@luxfi/core 5.3.0 → 5.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.
- package/commerce/ui/conf.ts +13 -13
- package/commerce/ui/context.tsx +123 -123
- package/commerce/ui/store.ts +289 -289
- package/components/access-code-input.tsx +71 -71
- package/components/auth/auth-listener.tsx +29 -29
- package/components/auth/auth-token/clear-auth-token.tsx +12 -12
- package/components/auth/auth-token/set-auth-token.tsx +16 -16
- package/components/auth/common-auth-domains.ts +16 -16
- package/components/auth/login-panel.tsx +107 -107
- package/components/back-button.tsx +49 -49
- package/components/chat-widget.tsx +85 -85
- package/components/commerce/_to_deprecate_checkout-widget/const.ts +13 -13
- package/components/commerce/_to_deprecate_checkout-widget/index.tsx_ +188 -188
- package/components/commerce/_to_deprecate_checkout-widget/obs-string-set.ts +48 -48
- package/components/commerce/_to_deprecate_checkout-widget/use-anim-clx-set.ts +58 -58
- package/components/commerce/bag-button.tsx +98 -98
- package/components/commerce/buy-button.tsx +34 -34
- package/components/commerce/checkout-button.tsx +129 -129
- package/components/commerce/checkout-panel/cart-accordian.tsx +66 -66
- package/components/commerce/checkout-panel/checkout-panel-props.ts +9 -9
- package/components/commerce/checkout-panel/desktop-bag-carousel.tsx +36 -36
- package/components/commerce/checkout-panel/desktop-cp.tsx +82 -82
- package/components/commerce/checkout-panel/index.tsx +126 -126
- package/components/commerce/checkout-panel/mobile-cp.tsx +66 -66
- package/components/commerce/checkout-panel/policy-links.tsx +29 -29
- package/components/commerce/checkout-panel/steps-indicator.tsx +39 -39
- package/components/commerce/checkout-panel/thank-you.tsx +18 -18
- package/components/commerce/desktop-bag-popup.tsx +78 -78
- package/components/commerce/desktop-nav-menu.tsx +130 -130
- package/components/commerce/drawer/index.tsx +88 -88
- package/components/commerce/drawer/micro.tsx +144 -144
- package/components/commerce/drawer/shell.tsx +85 -85
- package/components/commerce/mobile-bag-drawer.tsx +51 -51
- package/components/commerce/mobile-login-button.tsx +107 -101
- package/components/commerce/mobile-menu-toggle-button.tsx +35 -35
- package/components/commerce/mobile-nav-menu-ai.tsx +50 -47
- package/components/commerce/mobile-nav-menu-item.tsx +49 -49
- package/components/commerce/mobile-nav-menu.tsx +101 -101
- package/components/contact-dialog/contact-form.tsx +113 -113
- package/components/contact-dialog/disclaimer.tsx +13 -13
- package/components/contact-dialog/index.tsx +64 -64
- package/components/copyright.tsx +21 -21
- package/components/drawer-margin.tsx +25 -25
- package/components/footer.tsx +77 -77
- package/components/header/desktop.tsx +51 -50
- package/components/header/index.tsx +50 -52
- package/components/header/mobile.tsx +163 -163
- package/components/header/theme-toggle.tsx +26 -26
- package/components/icons/24k-gold-card.tsx +43 -43
- package/components/icons/ai-chat-act.tsx +47 -47
- package/components/icons/ai-chat.tsx +29 -29
- package/components/icons/anodized-titanium.tsx +45 -45
- package/components/icons/avatar.tsx +11 -11
- package/components/icons/bag-icon.tsx +10 -10
- package/components/icons/blog-act.tsx +14 -14
- package/components/icons/blog.tsx +20 -20
- package/components/icons/bridge-act.tsx +18 -18
- package/components/icons/bridge.tsx +68 -68
- package/components/icons/changelog-act.tsx +15 -15
- package/components/icons/changelog.tsx +21 -21
- package/components/icons/chrome.tsx +45 -45
- package/components/icons/coins-act.tsx +29 -29
- package/components/icons/coins.tsx +20 -20
- package/components/icons/compare-cards-act.tsx +30 -30
- package/components/icons/compare-cards.tsx +21 -21
- package/components/icons/credit-act.tsx +29 -29
- package/components/icons/credit.tsx +20 -20
- package/components/icons/customer-support-act.tsx +27 -27
- package/components/icons/customer-support.tsx +21 -21
- package/components/icons/customers-act.tsx +65 -65
- package/components/icons/customers.tsx +33 -33
- package/components/icons/developer-docs-act.tsx +26 -26
- package/components/icons/developer-docs.tsx +20 -20
- package/components/icons/exchange-act.tsx +27 -27
- package/components/icons/exchange.tsx +21 -21
- package/components/icons/explorer-act.tsx +27 -27
- package/components/icons/explorer.tsx +22 -22
- package/components/icons/faqs-act.tsx +27 -27
- package/components/icons/faqs.tsx +21 -21
- package/components/icons/github.tsx +14 -14
- package/components/icons/guides-act.tsx +26 -26
- package/components/icons/guides.tsx +21 -21
- package/components/icons/gun-metal.tsx +44 -44
- package/components/icons/index.tsx +43 -43
- package/components/icons/integrations-act.tsx +41 -41
- package/components/icons/integrations.tsx +25 -25
- package/components/icons/irradescent.tsx +41 -41
- package/components/icons/launch-subnet.tsx +21 -21
- package/components/icons/launchsubnet-act.tsx +29 -29
- package/components/icons/left-arrow.tsx +11 -11
- package/components/icons/lux-finance-act.tsx +34 -34
- package/components/icons/lux-finance.tsx +23 -23
- package/components/icons/lux-logo.tsx +10 -10
- package/components/icons/lux-pass-act.tsx +41 -41
- package/components/icons/lux-pass.tsx +25 -25
- package/components/icons/lux-quests-act.tsx +15 -15
- package/components/icons/lux-quests.tsx +21 -21
- package/components/icons/market-act.tsx +39 -39
- package/components/icons/market.tsx +24 -24
- package/components/icons/mirrored-titanium.tsx +46 -46
- package/components/icons/more-benefits-act.tsx +29 -29
- package/components/icons/more-benefits.tsx +21 -21
- package/components/icons/open-source-act.tsx +41 -41
- package/components/icons/open-source.tsx +26 -26
- package/components/icons/right-arrow.tsx +10 -10
- package/components/icons/safe-act.tsx +77 -77
- package/components/icons/safe.tsx +37 -37
- package/components/icons/search.tsx +12 -12
- package/components/icons/secure-delivery.tsx +13 -13
- package/components/icons/shop-act.tsx +29 -29
- package/components/icons/shop.tsx +20 -20
- package/components/icons/social-icon.tsx +35 -35
- package/components/icons/social-svg.css +3 -3
- package/components/icons/sterling-silver-card.tsx +44 -44
- package/components/icons/templates-act.tsx +29 -29
- package/components/icons/templates.tsx +21 -21
- package/components/icons/validators-act.tsx +42 -42
- package/components/icons/validators.tsx +41 -41
- package/components/icons/view-all-card-act.tsx +28 -28
- package/components/icons/view-all-card.tsx +20 -20
- package/components/icons/wallet-act.tsx +29 -29
- package/components/icons/wallet.tsx +20 -20
- package/components/icons/warpcast.tsx +58 -58
- package/components/icons/youtube-logo.tsx +59 -59
- package/components/index.ts +25 -25
- package/components/logo.tsx +89 -89
- package/components/main.tsx +27 -27
- package/components/mini-chart/index.tsx +7 -7
- package/components/mini-chart/mini-chart-props.ts +43 -43
- package/components/mini-chart/mini-chart.tsx +85 -85
- package/components/mini-chart/wrapper.tsx +23 -23
- package/components/not-found/index.tsx +28 -28
- package/components/not-found/not-found-content.mdx +5 -5
- package/components/scripts.tsx +24 -24
- package/components/tooltip.tsx +31 -31
- package/environment.d.ts +5 -5
- package/next/analytics/fpixel.ts +15 -15
- package/next/analytics/google-analytics.ts +13 -13
- package/next/analytics/index.ts +3 -3
- package/next/analytics/pixel-analytics.tsx +54 -54
- package/next/font/get-app-router-font-classes.ts +12 -12
- package/next/font/load-and-return-lux-next-fonts-on-import.ts +68 -68
- package/next/font/next-font-desc.ts +27 -27
- package/next/font/pages-router-font-vars.tsx +18 -18
- package/next/head-metadata/from-next/metadata-types.ts +158 -158
- package/next/head-metadata/from-next/opengraph-types.ts +267 -267
- package/next/head-metadata/from-next/twitter-types.ts +92 -92
- package/next/head-metadata/index.tsx +208 -208
- package/next/middleware/determine-device-mw.ts +16 -16
- package/package.json +79 -79
- package/root-layout/WHY_THIS_IS_SEPARATE.txt +1 -1
- package/root-layout/index.tsx +112 -112
- package/server-actions/firebase-app.ts +14 -14
- package/server-actions/index.ts +5 -5
- package/server-actions/store-contact.ts +51 -51
- package/site-def/footer/community.tsx +67 -67
- package/site-def/footer/company.ts +37 -37
- package/site-def/footer/ecosystem.ts +37 -37
- package/site-def/footer/index.tsx +26 -26
- package/site-def/footer/legal.ts +28 -28
- package/site-def/footer/network.ts +45 -45
- package/site-def/footer/svg/warpcast-logo.svg +11 -11
- package/site-def/index.ts +2 -2
- package/site-def/main-nav.tsx +458 -458
- package/style/cart-animation.css +29 -29
- package/style/checkout-animation.css +23 -23
- package/style/drawer-handle-overrides.css +160 -160
- package/style/lux-colors.css +85 -85
- package/style/lux-global.css +50 -47
- package/tailwind/fontFamily.tailwind.lux.ts +18 -18
- package/tailwind/index.ts +2 -2
- package/tailwind/lux-tw-fonts.ts +39 -39
- package/tailwind/tailwind.config.lux-preset.ts +10 -10
- package/tsconfig.json +15 -15
- package/types/chatbot-config.ts +6 -6
- package/types/chatbot-suggested-question.ts +7 -7
- package/types/contact-info.ts +10 -10
- package/types/index.ts +4 -4
- package/types/site-def.ts +43 -43
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { observer } from 'mobx-react-lite'
|
|
4
|
-
|
|
5
|
-
import { ChevronRight } from 'lucide-react'
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
Accordion,
|
|
9
|
-
AccordionContent,
|
|
10
|
-
AccordionItem,
|
|
11
|
-
AccordionTrigger,
|
|
12
|
-
} from '@hanzo/ui/primitives'
|
|
13
|
-
import { cn } from '@hanzo/ui/util'
|
|
14
|
-
|
|
15
|
-
import { useCommerce, CartPanel, formatCurrencyValue } from '@hanzo/commerce'
|
|
16
|
-
|
|
17
|
-
const CartAccordian: React.FC<{
|
|
18
|
-
icon?: React.ReactNode
|
|
19
|
-
clx?: string
|
|
20
|
-
triggerClx?: string
|
|
21
|
-
panelClx?: string
|
|
22
|
-
scrollAfter: number
|
|
23
|
-
scrollHeightClx: string
|
|
24
|
-
}> = observer(({
|
|
25
|
-
icon,
|
|
26
|
-
clx='',
|
|
27
|
-
panelClx='',
|
|
28
|
-
triggerClx='',
|
|
29
|
-
scrollAfter,
|
|
30
|
-
scrollHeightClx
|
|
31
|
-
}) => {
|
|
32
|
-
const cmmc = useCommerce()
|
|
33
|
-
return (
|
|
34
|
-
<Accordion type="single" collapsible className={clx}>
|
|
35
|
-
<AccordionItem value="cart" className='w-full border-b-0'>
|
|
36
|
-
<AccordionTrigger className={'!no-underline group flex justify-between '} headerClx={ triggerClx}>
|
|
37
|
-
<div className='flex gap-0 items-center'>
|
|
38
|
-
{icon}
|
|
39
|
-
<h5 className='text-sm sm:text-xl grow'>
|
|
40
|
-
<span className='group-data-[state=open]:hidden' >Order Total:</span>
|
|
41
|
-
<span className='group-data-[state=closed]:hidden' >Your Order</span>
|
|
42
|
-
</h5>
|
|
43
|
-
</div>
|
|
44
|
-
<div className='flex gap-1 items-center'>
|
|
45
|
-
<h5 className='text-sm sm:text-xl grow truncate'>{formatCurrencyValue(cmmc.promoAppliedCartTotal)}</h5>
|
|
46
|
-
<ChevronRight className="h-5 w-5 -mr-2 shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-90" />
|
|
47
|
-
</div>
|
|
48
|
-
</AccordionTrigger>
|
|
49
|
-
<AccordionContent className='data-[state=open]:mb-4'>
|
|
50
|
-
<CartPanel
|
|
51
|
-
className={cn('w-full', panelClx)}
|
|
52
|
-
scrollAfter={scrollAfter}
|
|
53
|
-
scrollHeightClx={scrollHeightClx}
|
|
54
|
-
listClx='mt-0'
|
|
55
|
-
itemClx='mt-0.5 mb-0'
|
|
56
|
-
totalClx='sticky px-1 pr-2 border-t -bottom-[1px] bg-background'
|
|
57
|
-
showShipping
|
|
58
|
-
showPromoCode
|
|
59
|
-
/>
|
|
60
|
-
</AccordionContent>
|
|
61
|
-
</AccordionItem>
|
|
62
|
-
</Accordion>
|
|
63
|
-
)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
export default CartAccordian
|
|
1
|
+
'use client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { observer } from 'mobx-react-lite'
|
|
4
|
+
|
|
5
|
+
import { ChevronRight } from 'lucide-react'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Accordion,
|
|
9
|
+
AccordionContent,
|
|
10
|
+
AccordionItem,
|
|
11
|
+
AccordionTrigger,
|
|
12
|
+
} from '@hanzo/ui/primitives'
|
|
13
|
+
import { cn } from '@hanzo/ui/util'
|
|
14
|
+
|
|
15
|
+
import { useCommerce, CartPanel, formatCurrencyValue } from '@hanzo/commerce'
|
|
16
|
+
|
|
17
|
+
const CartAccordian: React.FC<{
|
|
18
|
+
icon?: React.ReactNode
|
|
19
|
+
clx?: string
|
|
20
|
+
triggerClx?: string
|
|
21
|
+
panelClx?: string
|
|
22
|
+
scrollAfter: number
|
|
23
|
+
scrollHeightClx: string
|
|
24
|
+
}> = observer(({
|
|
25
|
+
icon,
|
|
26
|
+
clx='',
|
|
27
|
+
panelClx='',
|
|
28
|
+
triggerClx='',
|
|
29
|
+
scrollAfter,
|
|
30
|
+
scrollHeightClx
|
|
31
|
+
}) => {
|
|
32
|
+
const cmmc = useCommerce()
|
|
33
|
+
return (
|
|
34
|
+
<Accordion type="single" collapsible className={clx}>
|
|
35
|
+
<AccordionItem value="cart" className='w-full border-b-0'>
|
|
36
|
+
<AccordionTrigger className={'!no-underline group flex justify-between '} headerClx={ triggerClx}>
|
|
37
|
+
<div className='flex gap-0 items-center'>
|
|
38
|
+
{icon}
|
|
39
|
+
<h5 className='text-sm sm:text-xl grow'>
|
|
40
|
+
<span className='group-data-[state=open]:hidden' >Order Total:</span>
|
|
41
|
+
<span className='group-data-[state=closed]:hidden' >Your Order</span>
|
|
42
|
+
</h5>
|
|
43
|
+
</div>
|
|
44
|
+
<div className='flex gap-1 items-center'>
|
|
45
|
+
<h5 className='text-sm sm:text-xl grow truncate'>{formatCurrencyValue(cmmc.promoAppliedCartTotal)}</h5>
|
|
46
|
+
<ChevronRight className="h-5 w-5 -mr-2 shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-90" />
|
|
47
|
+
</div>
|
|
48
|
+
</AccordionTrigger>
|
|
49
|
+
<AccordionContent className='data-[state=open]:mb-4'>
|
|
50
|
+
<CartPanel
|
|
51
|
+
className={cn('w-full', panelClx)}
|
|
52
|
+
scrollAfter={scrollAfter}
|
|
53
|
+
scrollHeightClx={scrollHeightClx}
|
|
54
|
+
listClx='mt-0'
|
|
55
|
+
itemClx='mt-0.5 mb-0'
|
|
56
|
+
totalClx='sticky px-1 pr-2 border-t -bottom-[1px] bg-background'
|
|
57
|
+
showShipping
|
|
58
|
+
showPromoCode
|
|
59
|
+
/>
|
|
60
|
+
</AccordionContent>
|
|
61
|
+
</AccordionItem>
|
|
62
|
+
</Accordion>
|
|
63
|
+
)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
export default CartAccordian
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
interface CheckoutPanelProps {
|
|
2
|
-
step: number
|
|
3
|
-
stepNames: string[]
|
|
4
|
-
onLeave:() => void
|
|
5
|
-
clx?: string
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
type CheckoutPanelProps as default
|
|
1
|
+
interface CheckoutPanelProps {
|
|
2
|
+
step: number
|
|
3
|
+
stepNames: string[]
|
|
4
|
+
onLeave:() => void
|
|
5
|
+
clx?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
type CheckoutPanelProps as default
|
|
10
10
|
}
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { observer } from 'mobx-react-lite'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
useCommerce,
|
|
7
|
-
CarouselItemSelector,
|
|
8
|
-
type CarouselItemSelectorPropsExt
|
|
9
|
-
} from '@hanzo/commerce'
|
|
10
|
-
|
|
11
|
-
const DesktopBagCarousel: React.FC<{
|
|
12
|
-
constrainTo: {w: number, h: number}
|
|
13
|
-
className?: string
|
|
14
|
-
}> = observer(({
|
|
15
|
-
constrainTo,
|
|
16
|
-
className=''
|
|
17
|
-
|
|
18
|
-
}) => {
|
|
19
|
-
const cmmc = useCommerce()
|
|
20
|
-
return (
|
|
21
|
-
<CarouselItemSelector
|
|
22
|
-
items={cmmc.cartItems}
|
|
23
|
-
selectedItemRef={cmmc}
|
|
24
|
-
scrollable={false} // ignored
|
|
25
|
-
selectSku={cmmc.setCurrentItem.bind(cmmc)}
|
|
26
|
-
clx={className}
|
|
27
|
-
ext={{
|
|
28
|
-
options: {loop: true},
|
|
29
|
-
constrainTo,
|
|
30
|
-
imageOnly: true
|
|
31
|
-
} satisfies CarouselItemSelectorPropsExt}
|
|
32
|
-
/>
|
|
33
|
-
)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
export default DesktopBagCarousel
|
|
1
|
+
'use client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { observer } from 'mobx-react-lite'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
useCommerce,
|
|
7
|
+
CarouselItemSelector,
|
|
8
|
+
type CarouselItemSelectorPropsExt
|
|
9
|
+
} from '@hanzo/commerce'
|
|
10
|
+
|
|
11
|
+
const DesktopBagCarousel: React.FC<{
|
|
12
|
+
constrainTo: {w: number, h: number}
|
|
13
|
+
className?: string
|
|
14
|
+
}> = observer(({
|
|
15
|
+
constrainTo,
|
|
16
|
+
className=''
|
|
17
|
+
|
|
18
|
+
}) => {
|
|
19
|
+
const cmmc = useCommerce()
|
|
20
|
+
return (
|
|
21
|
+
<CarouselItemSelector
|
|
22
|
+
items={cmmc.cartItems}
|
|
23
|
+
selectedItemRef={cmmc}
|
|
24
|
+
scrollable={false} // ignored
|
|
25
|
+
selectSku={cmmc.setCurrentItem.bind(cmmc)}
|
|
26
|
+
clx={className}
|
|
27
|
+
ext={{
|
|
28
|
+
options: {loop: true},
|
|
29
|
+
constrainTo,
|
|
30
|
+
imageOnly: true
|
|
31
|
+
} satisfies CarouselItemSelectorPropsExt}
|
|
32
|
+
/>
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
export default DesktopBagCarousel
|
|
@@ -1,83 +1,83 @@
|
|
|
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
|
-
|
|
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
83
|
export default DesktopCheckoutPanel
|
|
@@ -1,126 +1,126 @@
|
|
|
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
|
+
'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
|