@luxfi/ui 5.5.4 → 5.5.6
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/context.tsx +13 -16
- package/components/access-code-input.tsx +3 -4
- package/components/analytics.tsx +8 -17
- package/components/auth/callback.tsx +40 -0
- package/components/auth/login-panel.tsx +22 -50
- package/components/auth/login.tsx +47 -0
- package/components/auth/provider.tsx +34 -0
- package/components/auth/resume.ts +16 -0
- package/components/auth/widget.tsx +80 -0
- package/components/back-button.tsx +4 -7
- package/components/chat-widget.tsx +9 -11
- package/components/commerce/bag-button.tsx +8 -7
- package/components/commerce/buy-button.tsx +2 -3
- package/components/commerce/checkout-button.tsx +12 -10
- package/components/commerce/checkout-panel/cart-accordian.tsx +3 -4
- package/components/commerce/checkout-panel/desktop-cp.tsx +7 -8
- package/components/commerce/checkout-panel/index.tsx +1 -1
- package/components/commerce/checkout-panel/mobile-cp.tsx +5 -5
- package/components/commerce/checkout-panel/policy-links.tsx +7 -12
- package/components/commerce/checkout-panel/steps-indicator.tsx +1 -1
- package/components/commerce/desktop-bag-popup.tsx +1 -1
- package/components/commerce/drawer/micro.tsx +30 -30
- package/components/commerce/drawer/shell.tsx +3 -5
- package/components/contact-dialog/contact-form.tsx +6 -13
- package/components/contact-dialog/index.tsx +2 -2
- package/components/copyright.tsx +3 -2
- package/components/drawer-margin.tsx +2 -2
- package/components/footer.tsx +7 -8
- package/components/header/desktop-nav-menu.tsx +6 -6
- package/components/header/desktop.tsx +9 -9
- package/components/header/index.tsx +2 -2
- package/components/header/mobile-bag-drawer.tsx +1 -1
- package/components/header/mobile-menu-toggle-button.tsx +5 -6
- package/components/header/mobile-nav-menu-ai.tsx +14 -13
- package/components/header/mobile-nav-menu-item.tsx +12 -11
- package/components/header/mobile-nav-menu.tsx +19 -18
- package/components/header/mobile.tsx +10 -11
- package/components/icons/index.ts +0 -1
- package/components/icons/social-icon.tsx +1 -1
- package/components/index.ts +2 -2
- package/components/logo.tsx +40 -67
- package/components/main.tsx +3 -4
- package/components/mini-chart/mini-chart.tsx +2 -1
- package/components/security/index.tsx +55 -0
- package/next/font/font-desc.ts +18 -0
- package/next/font/fonts.ts +40 -0
- package/next/font/get-app-router-font-classes.ts +14 -12
- package/next/font/load-and-return-lux-next-fonts-on-import.ts +16 -24
- package/next/font/local/Zen-Variable.woff2 +0 -0
- package/next/font/next-font-desc.ts +18 -17
- package/next/head-metadata/index.tsx +7 -6
- package/next/head-metadata/next-metadata.ts +49 -0
- package/next/middleware/determine-device-mw.ts +0 -13
- package/package.json +15 -15
- package/root-layout/index.tsx +42 -29
- package/style/fonts/Zen-Variable.woff2 +0 -0
- package/style/lux-colors.css +0 -1
- package/style/lux-fonts.css +5 -11
- package/style/lux-global-non-next.css +9 -9
- package/style/lux-global.css +99 -15
- package/tsconfig.json +8 -0
- package/types/site-def.ts +7 -0
- package/components/auth/auth-listener.tsx +0 -33
- 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/mobile-login-button.tsx +0 -112
- package/components/auth/signup-panel.tsx +0 -113
- package/components/icons/lux-logo.tsx +0 -10
- package/next/font/local/Druk-Wide-Bold.ttf +0 -0
- package/next/font/local/Druk-Wide-Medium.ttf +0 -0
- 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/style/fonts/Druk-Wide-Bold.ttf +0 -0
- package/style/fonts/Druk-Wide-Medium.ttf +0 -0
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { type PropsWithChildren } from 'react'
|
|
2
2
|
|
|
3
|
-
import { cn } from '@hanzo/ui
|
|
4
|
-
import
|
|
3
|
+
import { Box, cn } from '@hanzo/ui'
|
|
4
|
+
import AuthWidget from '../auth/widget'
|
|
5
5
|
|
|
6
6
|
import Logo, { type LogoVariant } from '../logo'
|
|
7
7
|
|
|
@@ -25,24 +25,24 @@ const DesktopHeader: React.FC<{
|
|
|
25
25
|
noAuth=false,
|
|
26
26
|
noCommerce=false,
|
|
27
27
|
children,
|
|
28
|
-
logoVariant='
|
|
28
|
+
logoVariant='full'
|
|
29
29
|
}) => {
|
|
30
30
|
const [isMenuOpened, setIsMenuOpen] = React.useState(false);
|
|
31
31
|
|
|
32
32
|
// TODO move 13px into a size class and configure twMerge to recognize say, 'text-size-nav'
|
|
33
33
|
// (vs be beat out by 'text-color-nav')
|
|
34
34
|
return (
|
|
35
|
-
<header id='DESKTOP_HEADER' className={cn(
|
|
35
|
+
<Box tag="header" id='DESKTOP_HEADER' className={cn(
|
|
36
36
|
'bg-[rgba(0, 0, 0, 0.5)] !backdrop-blur-3xl fixed z-header top-0 left-0 right-0',
|
|
37
37
|
className,
|
|
38
38
|
isMenuOpened ? ' h-full' : ''
|
|
39
39
|
)} >
|
|
40
40
|
{/* md or larger */}
|
|
41
|
-
<
|
|
41
|
+
<Box className={
|
|
42
42
|
'flex flex-row h-[80px] items-center justify-between ' +
|
|
43
43
|
'mx-[24px] w-full max-w-screen'
|
|
44
44
|
}>
|
|
45
|
-
<Logo size={logoVariant === '
|
|
45
|
+
<Logo size={logoVariant === 'mark' ? 'lg' : 'md'} href='/' outerClx='hidden lg:flex' key='two' variant={logoVariant} />
|
|
46
46
|
<Logo size='sm' href='/' outerClx='hidden md:flex lg:hidden' key='one' variant={logoVariant} />
|
|
47
47
|
{/* md or larger */}
|
|
48
48
|
<div className='flex w-full gap-4 items-center justify-center'>
|
|
@@ -52,11 +52,11 @@ const DesktopHeader: React.FC<{
|
|
|
52
52
|
{!noCommerce && (
|
|
53
53
|
<DesktopBagPopup popupClx='w-[340px]' trigger={<BagButton className='text-primary -mr-[3px] lg:min-w-0' />} />
|
|
54
54
|
)}
|
|
55
|
-
<AuthWidget
|
|
55
|
+
{!noAuth && <AuthWidget />}
|
|
56
56
|
{children}
|
|
57
57
|
</div>
|
|
58
|
-
</
|
|
59
|
-
</
|
|
58
|
+
</Box>
|
|
59
|
+
</Box>
|
|
60
60
|
)
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -5,7 +5,7 @@ import type { SiteDef } from '../../site-def'
|
|
|
5
5
|
|
|
6
6
|
import DesktopHeader from './desktop'
|
|
7
7
|
import MobileHeader from './mobile'
|
|
8
|
-
import { cn } from '@hanzo/ui
|
|
8
|
+
import { cn } from '@hanzo/ui'
|
|
9
9
|
import { type LogoVariant } from '../logo'
|
|
10
10
|
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ const Header: React.FC<{
|
|
|
18
18
|
siteDef,
|
|
19
19
|
className = '',
|
|
20
20
|
children,
|
|
21
|
-
logoVariant='
|
|
21
|
+
logoVariant='full'
|
|
22
22
|
}) => {
|
|
23
23
|
|
|
24
24
|
// TODO
|
|
@@ -4,8 +4,7 @@ import React, { useState } from 'react'
|
|
|
4
4
|
import { Plus } from 'lucide-react'
|
|
5
5
|
|
|
6
6
|
import { Button } from '@hanzo/ui/primitives'
|
|
7
|
-
import { cn } from '@hanzo/ui
|
|
8
|
-
|
|
7
|
+
import { cn, css } from '@hanzo/ui'
|
|
9
8
|
const MobileMenuToggleButton: React.FC<{
|
|
10
9
|
open: boolean
|
|
11
10
|
setOpen: (b: boolean) => void
|
|
@@ -20,14 +19,14 @@ const MobileMenuToggleButton: React.FC<{
|
|
|
20
19
|
<Button
|
|
21
20
|
variant='ghost'
|
|
22
21
|
size='default'
|
|
23
|
-
|
|
22
|
+
className={cn('rounded-full', cn('p-0 aspect-square hover:bg-background sm:hover:bg-level-1 active:scale-75', className))}
|
|
24
23
|
onClick={() => {setOpen(!open)}}
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
>
|
|
27
|
-
<Plus width={28} height={28}
|
|
26
|
+
<Plus width={28} height={28} style={css(
|
|
28
27
|
'block h-full will-change-transform transition-transform transition-scale transition-duration-[1500] ' +
|
|
29
28
|
(open ? 'rotate-[135deg] scale-110' : 'rotate-none')
|
|
30
|
-
} />
|
|
29
|
+
)} />
|
|
31
30
|
</Button>
|
|
32
31
|
)
|
|
33
32
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import React, { useState } from 'react'
|
|
3
|
+
import { Box, cn, css } from '@hanzo/ui'
|
|
3
4
|
import { ArrowRight, Plus } from 'lucide-react'
|
|
4
5
|
import { Button, Card } from '@hanzo/ui/primitives'
|
|
5
6
|
import { Logo } from '..'
|
|
@@ -13,22 +14,22 @@ const MobileNavMenuAI: React.FC<MobileNavMenuAIProps> = ({ setMenuOpen }) => {
|
|
|
13
14
|
|
|
14
15
|
return (
|
|
15
16
|
<>
|
|
16
|
-
<
|
|
17
|
+
<Box className="w-full text-2xl cursor-pointer">
|
|
17
18
|
<div className='flex justify-between'>
|
|
18
|
-
<Logo variant='
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
<Logo variant='wordmark' size='md' outerClx={'p-6 h-full'} />
|
|
20
|
+
<Box tag="span" className={cn('grid', 'block h-full aspect-square hover:bg-background sm:hover:bg-level-1 active:scale-75 text-foreground will-change-transform transition-transform transition-scale transition-duration-[1500] mt-6 mr-6 ' +
|
|
21
|
+
(!open ? 'rotate-none' : 'rotate-[135deg] scale-110'))}>
|
|
22
|
+
<Plus width={28} height={28} style={css('w-full h-full')} onClick={() => setMenuOpen(false)} />
|
|
23
|
+
</Box>
|
|
23
24
|
</div>
|
|
24
|
-
<
|
|
25
|
-
<
|
|
25
|
+
<Box className="flex items-center gap-5 border-b border-[#3A3A3A] mt-4 rounded-full bg-muted-4 mx-6">
|
|
26
|
+
<Box className="text-muted-1 font-bold flex-1 flex justify-between min-h-12 items-center px-2" onClick={() => setIsOpen(true)}>
|
|
26
27
|
<span className='text-base pl-2 font-light'>Ask AI a question</span>
|
|
27
28
|
<ArrowRight />
|
|
28
|
-
</
|
|
29
|
-
</
|
|
30
|
-
</
|
|
31
|
-
<
|
|
29
|
+
</Box>
|
|
30
|
+
</Box>
|
|
31
|
+
</Box>
|
|
32
|
+
<Box className={
|
|
32
33
|
'fixed bottom-0 sm:bottom-16 right-0 w-full h-full ' +
|
|
33
34
|
'sm:max-w-[400px] sm:max-h-[550px] sm:px-4 z-floating ' +
|
|
34
35
|
(isOpen ? 'flex' : 'hidden')
|
|
@@ -42,7 +43,7 @@ const MobileNavMenuAI: React.FC<MobileNavMenuAIProps> = ({ setMenuOpen }) => {
|
|
|
42
43
|
</div>
|
|
43
44
|
<iframe src="https://lux.chat/iframe" className='h-full' />
|
|
44
45
|
</Card>
|
|
45
|
-
</
|
|
46
|
+
</Box>
|
|
46
47
|
|
|
47
48
|
</>
|
|
48
49
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
|
+
import { Box } from '@hanzo/ui'
|
|
2
3
|
import Link from 'next/link'
|
|
3
4
|
|
|
4
5
|
import type { LinkDefExtended } from '../../site-def/main-nav'
|
|
@@ -16,30 +17,30 @@ const MobileNavMenuItem: React.FC<{
|
|
|
16
17
|
|
|
17
18
|
return (
|
|
18
19
|
<>
|
|
19
|
-
<
|
|
20
|
+
<Box className="w-full flex items-center px-5 py-3 gap-[27px] text-2xl cursor-pointer" onClick={() => setIsOpen(true)}>
|
|
20
21
|
<span className='block w-[18px] h-[22px] items-center'>{link.icon}</span>
|
|
21
22
|
<span className='flex-1'>{link.title}</span>
|
|
22
23
|
<RightArrow className='' />
|
|
23
|
-
</
|
|
24
|
-
<
|
|
24
|
+
</Box>
|
|
25
|
+
<Box className={`fixed left-0 top-0 w-screen h-screen ${isOpen ? 'block' : 'hidden'}`} style={{ backgroundColor: 'black' }}>
|
|
25
26
|
<MobileNavMenuAI setMenuOpen={setMenuOpen} />
|
|
26
|
-
<
|
|
27
|
+
<Box className="w-full flex items-center px-5 py-3 gap-[27px] text-2xl font-bold" onClick={() => setIsOpen(false)}>
|
|
27
28
|
<LeftArrow />
|
|
28
|
-
<span className="text-white">{link.title}</
|
|
29
|
-
</
|
|
30
|
-
<
|
|
29
|
+
<Box tag="span" className="text-white">{link.title}</Box>
|
|
30
|
+
</Box>
|
|
31
|
+
<Box className="flex flex-col">
|
|
31
32
|
{link.childMenu?.map((menu, index) => {
|
|
32
33
|
return (
|
|
33
34
|
<Link href={menu.href}>
|
|
34
|
-
<
|
|
35
|
+
<Box className="w-full flex items-center px-5 py-3 gap-[27px] text-2xl" key={index}>
|
|
35
36
|
<span className='w-[18px] h-[22px] self-center flex items-center justify-center'>{menu.icon}</span>
|
|
36
37
|
<span className='flex-1'>{menu.title}</span>
|
|
37
|
-
</
|
|
38
|
+
</Box>
|
|
38
39
|
</Link>
|
|
39
40
|
)
|
|
40
41
|
})}
|
|
41
|
-
</
|
|
42
|
-
</
|
|
42
|
+
</Box>
|
|
43
|
+
</Box>
|
|
43
44
|
</>
|
|
44
45
|
)
|
|
45
46
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import type { LinkDef } from '@hanzo/ui/types'
|
|
4
|
-
import { cn } from '@hanzo/ui
|
|
4
|
+
import { Box, cn, css } from '@hanzo/ui'
|
|
5
5
|
import type { LinkDefExtended, ChildMenu } from '../../site-def/main-nav'
|
|
6
6
|
import MobileNavMenuAI from './mobile-nav-menu-ai'
|
|
7
7
|
import MobileNavMenuItem from './mobile-nav-menu-item'
|
|
8
|
-
import
|
|
8
|
+
import AuthWidget from '../auth/widget'
|
|
9
9
|
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@hanzo/ui/primitives'
|
|
10
10
|
import { ChevronDown } from 'lucide-react'
|
|
11
11
|
import Link from 'next/link'
|
|
@@ -28,9 +28,9 @@ const MobileNav: React.FC<{
|
|
|
28
28
|
setMenuOpen
|
|
29
29
|
}) => (
|
|
30
30
|
links.length > 0 ? (
|
|
31
|
-
<
|
|
31
|
+
<Box className={cn('flex flex-col h-full', className)}>
|
|
32
32
|
<MobileNavMenuAI setMenuOpen={setMenuOpen} />
|
|
33
|
-
<
|
|
33
|
+
<Box className="flex flex-col flex-1 overflow-auto">
|
|
34
34
|
<Accordion type="single" collapsible className='w-full h-full'>
|
|
35
35
|
{links.map((el, index) => {
|
|
36
36
|
const itemClx = (commonItemClx) ? (typeof commonItemClx === 'string' ? commonItemClx : commonItemClx(el)) : ''
|
|
@@ -50,14 +50,14 @@ const MobileNav: React.FC<{
|
|
|
50
50
|
return (
|
|
51
51
|
<AccordionItem key={index} value={el.title ? el.title : ""} className='!no-underline !border-0 px-6'>
|
|
52
52
|
<AccordionTrigger className={cn(internalClx, itemClx, '')}>
|
|
53
|
-
<
|
|
53
|
+
<Box className={cn(internalClx, itemClx, 'flex items-center justify-between w-full pl-3 text-base font-normal leading-6')}>
|
|
54
54
|
{el.title}
|
|
55
|
-
</
|
|
56
|
-
<ChevronDown
|
|
55
|
+
</Box>
|
|
56
|
+
<ChevronDown style={css('w-4 h-4 mr-3')} />
|
|
57
57
|
</AccordionTrigger>
|
|
58
58
|
<AccordionContent>
|
|
59
59
|
{el.childMenu && (
|
|
60
|
-
<
|
|
60
|
+
<Box className="px-4">
|
|
61
61
|
{Object.entries(el.childMenu.reduce((acc, child) => {
|
|
62
62
|
const group = acc[child.groupName ? child.groupName : ""] || []
|
|
63
63
|
group.push(child)
|
|
@@ -65,27 +65,28 @@ const MobileNav: React.FC<{
|
|
|
65
65
|
return acc
|
|
66
66
|
}, {} as { [key: string]: ChildMenu[] })).map(([groupName, children]) => (
|
|
67
67
|
<div key={groupName}>
|
|
68
|
-
<
|
|
68
|
+
<Box className="mt-4 mb-4 font-light text-muted-1">{groupName}</Box>
|
|
69
69
|
{children.map((child, childIndex) => (
|
|
70
|
-
<
|
|
71
|
-
<
|
|
70
|
+
<Box key={childIndex} className="m-2">
|
|
71
|
+
<Box className="flex items-center py-1">
|
|
72
72
|
<span>
|
|
73
73
|
{child.icon && child.icon}
|
|
74
74
|
</span>
|
|
75
75
|
<Link
|
|
76
76
|
href={child.href}
|
|
77
|
-
className="text-muted-2 hover:underline ml-5 hover:text-primary"
|
|
78
77
|
target={child.newTab ? '_blank' : '_self'}
|
|
79
78
|
rel="noopener noreferrer"
|
|
80
79
|
>
|
|
80
|
+
<Box tag="span" className="text-muted-2 hover:underline ml-5 hover:text-primary">
|
|
81
81
|
{child.title}
|
|
82
|
+
</Box>
|
|
82
83
|
</Link>
|
|
83
|
-
</
|
|
84
|
-
</
|
|
84
|
+
</Box>
|
|
85
|
+
</Box>
|
|
85
86
|
))}
|
|
86
87
|
</div>
|
|
87
88
|
))}
|
|
88
|
-
</
|
|
89
|
+
</Box>
|
|
89
90
|
)}
|
|
90
91
|
</AccordionContent>
|
|
91
92
|
</AccordionItem>
|
|
@@ -93,9 +94,9 @@ const MobileNav: React.FC<{
|
|
|
93
94
|
}
|
|
94
95
|
})}
|
|
95
96
|
</Accordion>
|
|
96
|
-
</
|
|
97
|
-
<
|
|
98
|
-
</
|
|
97
|
+
</Box>
|
|
98
|
+
<AuthWidget className='text-2xl z-10' handleLogin={() => { setMenuState('login') }} />
|
|
99
|
+
</Box>
|
|
99
100
|
) : null
|
|
100
101
|
);
|
|
101
102
|
|
|
@@ -3,10 +3,9 @@ import React, { useState, useEffect } from 'react'
|
|
|
3
3
|
import { useRouter } from 'next/navigation'
|
|
4
4
|
|
|
5
5
|
import type { LinkDef } from '@hanzo/ui/types'
|
|
6
|
-
import { cn } from '@hanzo/ui
|
|
7
|
-
|
|
6
|
+
import { Box, cn } from '@hanzo/ui'
|
|
8
7
|
import { CartPanel, useCommerce } from '@hanzo/commerce'
|
|
9
|
-
import
|
|
8
|
+
import Login from '../auth/login'
|
|
10
9
|
import sendGAEvent from '../../next/analytics/google-analytics'
|
|
11
10
|
|
|
12
11
|
import { Avatar, Bag } from '../icons'
|
|
@@ -89,22 +88,22 @@ const MobileHeader: React.FC<{
|
|
|
89
88
|
}
|
|
90
89
|
// header element MUST be fixed, and NOT sticky. Or else drawer breaks on mobile browsers
|
|
91
90
|
return (<>
|
|
92
|
-
<header id='MOBILE_HEADER' className={cn(
|
|
91
|
+
<Box tag="header" id='MOBILE_HEADER' className={cn(
|
|
93
92
|
`bg-background fixed z-header top-0 left-0 w-full ${menuOpen() ? 'hidden' : 'block'}`,
|
|
94
93
|
className
|
|
95
94
|
)}>
|
|
96
95
|
{/* smaller than md: mobile style drawer menu; h-11 is 44px, the standard mobile header height */}
|
|
97
96
|
<div className='w-full h-full flex flex-row justify-between items-center font-bold pr-5'>
|
|
98
|
-
<Logo href='/' size='md' outerClx={'p-6 h-full'} variant='
|
|
97
|
+
<Logo href='/' size='md' outerClx={'p-6 h-full'} variant='wordmark' />
|
|
99
98
|
{/* Not that key to the cross-fade effect
|
|
100
99
|
is that this is **on top of** the logo. */}
|
|
101
100
|
{menuOpen() && (
|
|
102
|
-
<
|
|
101
|
+
<Box className={'absolute left-0 top-0 bottom-0 right-0 pl-8 ' +
|
|
103
102
|
'flex flex-row ' +
|
|
104
103
|
'bg-background animate-mobile-menu-open'
|
|
105
104
|
}>
|
|
106
105
|
<Avatar className='self-center ' />
|
|
107
|
-
</
|
|
106
|
+
</Box>
|
|
108
107
|
)}
|
|
109
108
|
<div className='flex gap-0 flex-row'>
|
|
110
109
|
<BagButton className='text-primary -mr-[3px]' onClick={openBag} />
|
|
@@ -112,7 +111,7 @@ const MobileHeader: React.FC<{
|
|
|
112
111
|
</div>
|
|
113
112
|
|
|
114
113
|
</div>
|
|
115
|
-
</
|
|
114
|
+
</Box>
|
|
116
115
|
{!noCommerce && (
|
|
117
116
|
<MobileBagDrawer
|
|
118
117
|
className=''
|
|
@@ -123,13 +122,13 @@ const MobileHeader: React.FC<{
|
|
|
123
122
|
)}
|
|
124
123
|
|
|
125
124
|
{menuOpen() && (
|
|
126
|
-
<
|
|
125
|
+
<Box className={
|
|
127
126
|
'fixed top-0 left-0 w-full h-full ' +
|
|
128
127
|
// z must below header itself
|
|
129
128
|
'flex flex-column bg-background z-below-header animate-mobile-menu-open'
|
|
130
129
|
}>
|
|
131
130
|
{(!!!noAuth && menuState === 'login') ? (
|
|
132
|
-
<
|
|
131
|
+
<Login onSuccess={onLoginChanged} className='sm:animate-in sm:zoom-in-90 m-auto w-full max-w-sm px-8' />
|
|
133
132
|
) : (
|
|
134
133
|
(!!!noCommerce && menuState === 'bag') ? (
|
|
135
134
|
|
|
@@ -162,7 +161,7 @@ const MobileHeader: React.FC<{
|
|
|
162
161
|
/>
|
|
163
162
|
)
|
|
164
163
|
)}
|
|
165
|
-
</
|
|
164
|
+
</Box>
|
|
166
165
|
) /* menuOpen */}
|
|
167
166
|
</>)
|
|
168
167
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { default as Avatar } from './avatar'
|
|
2
2
|
export { default as Bag } from './bag-icon'
|
|
3
3
|
export { default as LeftArrow } from './left-arrow'
|
|
4
|
-
export { default as LuxLogo } from './lux-logo'
|
|
5
4
|
export { default as RightArrow } from './right-arrow'
|
|
6
5
|
export { default as SocialIcon, type SocialIconProps } from './social-icon'
|
package/components/index.ts
CHANGED
|
@@ -10,7 +10,8 @@ export { default as Main } from './main'
|
|
|
10
10
|
export { default as MiniChart } from './mini-chart'
|
|
11
11
|
export { default as NotFound } from './not-found'
|
|
12
12
|
|
|
13
|
-
export { default as
|
|
13
|
+
export { default as Auth } from './auth/provider'
|
|
14
|
+
export { default as Login } from './auth/login'
|
|
14
15
|
export { default as BackButton } from './back-button'
|
|
15
16
|
export { default as BuyDrawer } from './commerce/drawer'
|
|
16
17
|
export { default as DrawerMargin } from './drawer-margin'
|
|
@@ -18,7 +19,6 @@ export { default as BuyButton } from './commerce/buy-button'
|
|
|
18
19
|
export { default as CheckoutButton } from './commerce/checkout-button'
|
|
19
20
|
export { default as CheckoutPanel } from './commerce/checkout-panel'
|
|
20
21
|
export { default as LoginPanel } from './auth/login-panel'
|
|
21
|
-
export { default as SignupPanel } from './auth/signup-panel'
|
|
22
22
|
export { default as Analytics } from './analytics'
|
|
23
23
|
export { default as Tooltip } from './tooltip'
|
|
24
24
|
|
package/components/logo.tsx
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import { Box, css } from '@hanzo/ui'
|
|
2
3
|
import Link from 'next/link'
|
|
3
4
|
|
|
4
|
-
import { type TShirtSize
|
|
5
|
+
import { type TShirtSize } from '@hanzo/ui/types'
|
|
6
|
+
import { Logo as Mark, Wordmark } from '@luxfi/logo'
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* mark — the triangle alone
|
|
10
|
+
* wordmark — the LUX letterforms alone
|
|
11
|
+
* full — the mark beside the wordmark
|
|
12
|
+
*
|
|
13
|
+
* Both halves come from @luxfi/logo, which is the one home for Lux brand art.
|
|
14
|
+
* This file used to draw its own triangle and set the letters "LUX" in the body
|
|
15
|
+
* font, so every Lux site wore typed text where the wordmark belongs — and no
|
|
16
|
+
* variant could fix it, because neither the mark nor the wordmark was here to
|
|
17
|
+
* ask for. Art lives in the brand package; this composes it.
|
|
18
|
+
*/
|
|
19
|
+
type LogoVariant = 'mark' | 'wordmark' | 'full'
|
|
10
20
|
|
|
21
|
+
/** Mark height in px, and the wordmark height that stands with it. */
|
|
22
|
+
const SIZE: Record<string, { mark: number, word: number, gap: string }> = {
|
|
23
|
+
xl: { mark: 40, word: 22, gap: 'gap-4' },
|
|
24
|
+
lg: { mark: 40, word: 22, gap: 'gap-4' },
|
|
25
|
+
md: { mark: 32, word: 18, gap: 'gap-3' },
|
|
26
|
+
sm: { mark: 24, word: 13, gap: 'gap-2' },
|
|
27
|
+
xs: { mark: 16, word: 9, gap: 'gap-1.5' },
|
|
28
|
+
}
|
|
11
29
|
|
|
12
30
|
const Logo: React.FC<{
|
|
13
31
|
size?: TShirtSize
|
|
@@ -15,74 +33,29 @@ const Logo: React.FC<{
|
|
|
15
33
|
onClick?: () => void
|
|
16
34
|
href?: string
|
|
17
35
|
outerClx?: string
|
|
18
|
-
textClx?: string
|
|
19
36
|
}> = ({
|
|
20
|
-
size,
|
|
37
|
+
size = 'md',
|
|
21
38
|
href, // no default please!
|
|
22
|
-
outerClx='',
|
|
23
|
-
|
|
24
|
-
variant='full',
|
|
39
|
+
outerClx = '',
|
|
40
|
+
variant = 'full',
|
|
25
41
|
onClick,
|
|
26
42
|
}) => {
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
icon: ''
|
|
32
|
-
}
|
|
33
|
-
:
|
|
34
|
-
(variant === 'text-only') ?
|
|
35
|
-
{
|
|
36
|
-
span: '',
|
|
37
|
-
icon: 'hidden'
|
|
38
|
-
}
|
|
39
|
-
:
|
|
40
|
-
{
|
|
41
|
-
span: '',
|
|
42
|
-
icon: ''
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (size === 'lg' || size === 'xl' ) { // for safety
|
|
46
|
-
classes.icon = 'h-10 w-10 mr-4 color-inherit '
|
|
47
|
-
classes.span = 'text-3xl '
|
|
48
|
-
}
|
|
49
|
-
// match lux.network
|
|
50
|
-
else if (size === 'md') {
|
|
51
|
-
classes.icon = 'h-[32px] w-[32px] mr-[12px] color-inherit '
|
|
52
|
-
classes.span = 'text-[1.8rem]/[1.8rem] tracking-tighter '
|
|
53
|
-
}
|
|
54
|
-
else if (size === 'sm' ) {
|
|
55
|
-
classes.icon = 'h-6 w-6 mr-2 color-inherit '
|
|
56
|
-
classes.span = 'text-lg '
|
|
57
|
-
}
|
|
58
|
-
// xs
|
|
59
|
-
else {
|
|
60
|
-
classes.icon = 'h-4 w-4 mr-1 color-inherit '
|
|
61
|
-
classes.span = 'text-base '
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
classes.icon += toAdd.icon
|
|
65
|
-
classes.span += toAdd.span
|
|
66
|
-
|
|
43
|
+
const s = SIZE[size as string] ?? SIZE.md
|
|
44
|
+
const clx = 'flex flex-row items-center ' + s.gap + ' '
|
|
45
|
+
+ (href ? 'hover:opacity-80 cursor-pointer ' : 'cursor-default ')
|
|
46
|
+
+ outerClx
|
|
67
47
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
48
|
+
// White on both counts: the Lux ground is black and the brand's accent is
|
|
49
|
+
// white, so the mark and the letters carry the same value.
|
|
50
|
+
const art = (<>
|
|
51
|
+
{variant !== 'wordmark' && <Mark variant='white' size={s.mark} />}
|
|
52
|
+
{variant !== 'mark' && <Wordmark height={s.word} />}
|
|
53
|
+
</>)
|
|
73
54
|
|
|
74
|
-
return (
|
|
75
|
-
href
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<span className={spanClasses}>{TEXT}</span>
|
|
79
|
-
</Link>
|
|
80
|
-
) : (
|
|
81
|
-
<span className={outerClasses} onClick={onClick}>
|
|
82
|
-
<LuxLogo className={classes.icon} />
|
|
83
|
-
<span className={spanClasses}>{TEXT}</span>
|
|
84
|
-
</span>
|
|
85
|
-
)
|
|
55
|
+
return href ? (
|
|
56
|
+
<Link href={href} style={css(clx)} onClick={onClick}>{art}</Link>
|
|
57
|
+
) : (
|
|
58
|
+
<Box tag="span" className={clx} onClick={onClick}>{art}</Box>
|
|
86
59
|
)
|
|
87
60
|
}
|
|
88
61
|
|
package/components/main.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { type PropsWithChildren } from 'react'
|
|
2
|
-
import { cn } from '@hanzo/ui
|
|
3
|
-
|
|
2
|
+
import { Box, cn } from '@hanzo/ui'
|
|
4
3
|
const Main: React.FC<PropsWithChildren & {
|
|
5
4
|
id?: string
|
|
6
5
|
className?: string
|
|
@@ -13,7 +12,7 @@ const Main: React.FC<PropsWithChildren & {
|
|
|
13
12
|
standardWidth=true,
|
|
14
13
|
id
|
|
15
14
|
}) => (
|
|
16
|
-
<main id={id ?? 'LUX_UI_MAIN'} className={cn(
|
|
15
|
+
<Box tag="main" id={id ?? 'LUX_UI_MAIN'} className={cn(
|
|
17
16
|
'flex flex-col justify-start items-center',
|
|
18
17
|
'px-4 md:px-6 lg:px-8',
|
|
19
18
|
standardWidth ? 'max-w-screen-2xl w-full lg:mx-auto' : '',
|
|
@@ -21,7 +20,7 @@ const Main: React.FC<PropsWithChildren & {
|
|
|
21
20
|
className
|
|
22
21
|
)}>
|
|
23
22
|
{children}
|
|
24
|
-
</
|
|
23
|
+
</Box>
|
|
25
24
|
)
|
|
26
25
|
|
|
27
26
|
export default Main
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import React, { useEffect, useRef } from 'react'
|
|
4
|
+
import { Box } from '@hanzo/ui'
|
|
4
5
|
import { type MiniChartProps } from './mini-chart-props'
|
|
5
6
|
|
|
6
7
|
const MiniChart: React.FC<MiniChartProps> = ({
|
|
@@ -77,7 +78,7 @@ const MiniChart: React.FC<MiniChartProps> = ({
|
|
|
77
78
|
<div style={containerStyles} className='tradingview-widget-container h-[150px]' ref={containerRef} />
|
|
78
79
|
<div className='tradingview-widget-copyright border-t w-full invisible'>
|
|
79
80
|
<a href={`https://www.tradingview.com/symbols/${symbol}${exchange ? `/?exchange=${exchange}` : '' }`} rel="noopener" target="_blank">
|
|
80
|
-
<span className="text-[--hz-ui-primary]">{symbol} quotes</
|
|
81
|
+
<Box tag="span" className="text-[--hz-ui-primary]">{symbol} quotes</Box></a> by TradingView
|
|
81
82
|
</div>
|
|
82
83
|
</>)
|
|
83
84
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { ApplyTypography } from '@hanzo/ui/primitives'
|
|
4
|
+
|
|
5
|
+
import type { SiteDef } from '../../site-def'
|
|
6
|
+
import Footer from '../footer'
|
|
7
|
+
import Header from '../header'
|
|
8
|
+
import Main from '../main'
|
|
9
|
+
|
|
10
|
+
const Security: React.FC<{
|
|
11
|
+
contact: string
|
|
12
|
+
header?: boolean
|
|
13
|
+
siteDef: SiteDef
|
|
14
|
+
}> = ({
|
|
15
|
+
contact,
|
|
16
|
+
header = false,
|
|
17
|
+
siteDef
|
|
18
|
+
}) => (<>
|
|
19
|
+
{header && <Header siteDef={siteDef} />}
|
|
20
|
+
<Main className='px-8 sm:px-10 pb-16'>
|
|
21
|
+
<ApplyTypography className='w-full max-w-[46rem] mx-auto flex flex-col gap-6 pt-12'>
|
|
22
|
+
<h1>Reporting a security problem</h1>
|
|
23
|
+
<p>
|
|
24
|
+
Email <a href={`mailto:${contact}`}>{contact}</a>. Tell us what you found and how to
|
|
25
|
+
reproduce it. Send it to us before you tell anyone else, and do not open a public issue.
|
|
26
|
+
</p>
|
|
27
|
+
<p>
|
|
28
|
+
A real report from a stranger is worth more than another internal review. We read every one.
|
|
29
|
+
</p>
|
|
30
|
+
<h2>What happens next</h2>
|
|
31
|
+
<p>
|
|
32
|
+
Someone will read your report and reply. If we can reproduce the problem we will tell you
|
|
33
|
+
what we are doing about it, and tell you again once it is fixed. If we cannot reproduce it
|
|
34
|
+
we will say so and ask you for what we are missing.
|
|
35
|
+
</p>
|
|
36
|
+
<h2>While you are looking</h2>
|
|
37
|
+
<p>
|
|
38
|
+
Test against accounts and data that are your own. Do not read, change, or keep data that
|
|
39
|
+
belongs to someone else. If you reach it by accident, stop, and say so in your report.
|
|
40
|
+
</p>
|
|
41
|
+
<p>
|
|
42
|
+
Do not run anything that degrades the service for other people. No load testing, no denial
|
|
43
|
+
of service, no mass automated scanning, and no social engineering of our staff or our users.
|
|
44
|
+
</p>
|
|
45
|
+
<h2>For scanners</h2>
|
|
46
|
+
<p>
|
|
47
|
+
This page is the policy named by{' '}
|
|
48
|
+
<a href='/.well-known/security.txt'>/.well-known/security.txt</a>, per RFC 9116.
|
|
49
|
+
</p>
|
|
50
|
+
</ApplyTypography>
|
|
51
|
+
</Main>
|
|
52
|
+
<Footer siteDef={siteDef} />
|
|
53
|
+
</>)
|
|
54
|
+
|
|
55
|
+
export default Security
|