@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.
Files changed (80) hide show
  1. package/commerce/ui/context.tsx +13 -16
  2. package/components/access-code-input.tsx +3 -4
  3. package/components/analytics.tsx +8 -17
  4. package/components/auth/callback.tsx +40 -0
  5. package/components/auth/login-panel.tsx +22 -50
  6. package/components/auth/login.tsx +47 -0
  7. package/components/auth/provider.tsx +34 -0
  8. package/components/auth/resume.ts +16 -0
  9. package/components/auth/widget.tsx +80 -0
  10. package/components/back-button.tsx +4 -7
  11. package/components/chat-widget.tsx +9 -11
  12. package/components/commerce/bag-button.tsx +8 -7
  13. package/components/commerce/buy-button.tsx +2 -3
  14. package/components/commerce/checkout-button.tsx +12 -10
  15. package/components/commerce/checkout-panel/cart-accordian.tsx +3 -4
  16. package/components/commerce/checkout-panel/desktop-cp.tsx +7 -8
  17. package/components/commerce/checkout-panel/index.tsx +1 -1
  18. package/components/commerce/checkout-panel/mobile-cp.tsx +5 -5
  19. package/components/commerce/checkout-panel/policy-links.tsx +7 -12
  20. package/components/commerce/checkout-panel/steps-indicator.tsx +1 -1
  21. package/components/commerce/desktop-bag-popup.tsx +1 -1
  22. package/components/commerce/drawer/micro.tsx +30 -30
  23. package/components/commerce/drawer/shell.tsx +3 -5
  24. package/components/contact-dialog/contact-form.tsx +6 -13
  25. package/components/contact-dialog/index.tsx +2 -2
  26. package/components/copyright.tsx +3 -2
  27. package/components/drawer-margin.tsx +2 -2
  28. package/components/footer.tsx +7 -8
  29. package/components/header/desktop-nav-menu.tsx +6 -6
  30. package/components/header/desktop.tsx +9 -9
  31. package/components/header/index.tsx +2 -2
  32. package/components/header/mobile-bag-drawer.tsx +1 -1
  33. package/components/header/mobile-menu-toggle-button.tsx +5 -6
  34. package/components/header/mobile-nav-menu-ai.tsx +14 -13
  35. package/components/header/mobile-nav-menu-item.tsx +12 -11
  36. package/components/header/mobile-nav-menu.tsx +19 -18
  37. package/components/header/mobile.tsx +10 -11
  38. package/components/icons/index.ts +0 -1
  39. package/components/icons/social-icon.tsx +1 -1
  40. package/components/index.ts +2 -2
  41. package/components/logo.tsx +40 -67
  42. package/components/main.tsx +3 -4
  43. package/components/mini-chart/mini-chart.tsx +2 -1
  44. package/components/security/index.tsx +55 -0
  45. package/next/font/font-desc.ts +18 -0
  46. package/next/font/fonts.ts +40 -0
  47. package/next/font/get-app-router-font-classes.ts +14 -12
  48. package/next/font/load-and-return-lux-next-fonts-on-import.ts +16 -24
  49. package/next/font/local/Zen-Variable.woff2 +0 -0
  50. package/next/font/next-font-desc.ts +18 -17
  51. package/next/head-metadata/index.tsx +7 -6
  52. package/next/head-metadata/next-metadata.ts +49 -0
  53. package/next/middleware/determine-device-mw.ts +0 -13
  54. package/package.json +15 -15
  55. package/root-layout/index.tsx +42 -29
  56. package/style/fonts/Zen-Variable.woff2 +0 -0
  57. package/style/lux-colors.css +0 -1
  58. package/style/lux-fonts.css +5 -11
  59. package/style/lux-global-non-next.css +9 -9
  60. package/style/lux-global.css +99 -15
  61. package/tsconfig.json +8 -0
  62. package/types/site-def.ts +7 -0
  63. package/components/auth/auth-listener.tsx +0 -33
  64. package/components/auth/auth-token/clear-auth-token.tsx +0 -12
  65. package/components/auth/auth-token/set-auth-token.tsx +0 -16
  66. package/components/auth/common-auth-domains.ts +0 -17
  67. package/components/auth/mobile-login-button.tsx +0 -112
  68. package/components/auth/signup-panel.tsx +0 -113
  69. package/components/icons/lux-logo.tsx +0 -10
  70. package/next/font/local/Druk-Wide-Bold.ttf +0 -0
  71. package/next/font/local/Druk-Wide-Medium.ttf +0 -0
  72. package/next/head-metadata/from-next/metadata-types.ts +0 -158
  73. package/next/head-metadata/from-next/opengraph-types.ts +0 -267
  74. package/next/head-metadata/from-next/twitter-types.ts +0 -92
  75. package/style/fonts/Druk-Wide-Bold.ttf +0 -0
  76. package/style/fonts/Druk-Wide-Medium.ttf +0 -0
  77. package/tailwind/fontFamily.tailwind.lux.ts +0 -18
  78. package/tailwind/index.ts +0 -2
  79. package/tailwind/lux-tw-fonts.ts +0 -40
  80. 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/util'
4
- import { AuthWidget } from '@hanzo/auth/components'
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='text-only'
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
- <div className={
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 === 'logo-only' ? 'lg' : 'md'} href='/' outerClx='hidden lg:flex' key='two' variant={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 noLogin={noAuth}/>
55
+ {!noAuth && <AuthWidget />}
56
56
  {children}
57
57
  </div>
58
- </div>
59
- </header>
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/util'
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='text-only'
21
+ logoVariant='full'
22
22
  }) => {
23
23
 
24
24
  // TODO
@@ -2,7 +2,7 @@
2
2
  import React from 'react'
3
3
 
4
4
  import { Drawer, DrawerContent} from '@hanzo/ui/primitives'
5
- import { cn } from '@hanzo/ui/util'
5
+ import { cn } from '@hanzo/ui'
6
6
  import { CartPanel } from '@hanzo/commerce'
7
7
 
8
8
  import BagButton from '../commerce/bag-button'
@@ -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/util'
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
- rounded='full'
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
- className={cn('p-0 aspect-square hover:bg-background sm:hover:bg-level-1 active:scale-75', className)}
24
+
26
25
  >
27
- <Plus width={28} height={28} className={
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
- <div className="w-full text-2xl cursor-pointer">
17
+ <Box className="w-full text-2xl cursor-pointer">
17
18
  <div className='flex justify-between'>
18
- <Logo variant='text-only' size='md' outerClx={'p-6 h-full'} />
19
- <Plus width={28} height={28} className={
20
- '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
- } onClick={() => setMenuOpen(false)} />
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
- <div className="flex items-center gap-5 border-b border-[#3A3A3A] mt-4 rounded-full bg-muted-4 mx-6">
25
- <div className="text-muted-1 font-bold flex-1 flex justify-between min-h-12 items-center px-2" onClick={() => setIsOpen(true)}>
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
- </div>
29
- </div>
30
- </div>
31
- <div className={
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
- </div>
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
- <div className="w-full flex items-center px-5 py-3 gap-[27px] text-2xl cursor-pointer" onClick={() => setIsOpen(true)}>
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
- </div>
24
- <div className={`fixed left-0 top-0 w-screen h-screen ${isOpen ? 'block' : 'hidden'}`} style={{ backgroundColor: 'black' }}>
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
- <div className="w-full flex items-center px-5 py-3 gap-[27px] text-2xl font-bold" onClick={() => setIsOpen(false)}>
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}</span>
29
- </div>
30
- <div className="flex flex-col">
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
- <div className="w-full flex items-center px-5 py-3 gap-[27px] text-2xl" key={index}>
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
- </div>
38
+ </Box>
38
39
  </Link>
39
40
  )
40
41
  })}
41
- </div>
42
- </div>
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/util'
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 MobileAuthWidget from '../auth/mobile-login-button'
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
- <div className={cn('flex flex-col h-full', className)}>
31
+ <Box className={cn('flex flex-col h-full', className)}>
32
32
  <MobileNavMenuAI setMenuOpen={setMenuOpen} />
33
- <div className="flex flex-col flex-1 overflow-auto">
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
- <div className={cn(internalClx, itemClx, 'flex items-center justify-between w-full pl-3 text-base font-normal leading-6')}>
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
- </div>
56
- <ChevronDown className="w-4 h-4 mr-3" />
55
+ </Box>
56
+ <ChevronDown style={css('w-4 h-4 mr-3')} />
57
57
  </AccordionTrigger>
58
58
  <AccordionContent>
59
59
  {el.childMenu && (
60
- <div className="px-4">
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
- <div className="mt-4 mb-4 font-light text-muted-1">{groupName}</div>
68
+ <Box className="mt-4 mb-4 font-light text-muted-1">{groupName}</Box>
69
69
  {children.map((child, childIndex) => (
70
- <div key={childIndex} className="m-2">
71
- <div className="flex items-center py-1">
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
- </div>
84
- </div>
84
+ </Box>
85
+ </Box>
85
86
  ))}
86
87
  </div>
87
88
  ))}
88
- </div>
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
- </div>
97
- <MobileAuthWidget className='text-2xl z-10' handleLogin={() => { setMenuState('login') }} />
98
- </div>
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/util'
7
-
6
+ import { Box, cn } from '@hanzo/ui'
8
7
  import { CartPanel, useCommerce } from '@hanzo/commerce'
9
- import { LoginPanel } from '@hanzo/auth/components'
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='text-only' />
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
- <div className={'absolute left-0 top-0 bottom-0 right-0 pl-8 ' +
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
- </div>
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
- </header>
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
- <div className={
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
- <LoginPanel noHeading onLoginChanged={onLoginChanged} className='sm:animate-in sm:zoom-in-90' />
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
- </div>
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'
@@ -2,7 +2,7 @@ import React from 'react'
2
2
 
3
3
  import { SocialIcon as BaseSocialIcon } from 'react-social-icons'
4
4
 
5
- import { cn } from '@hanzo/ui/util'
5
+ import { cn } from '@hanzo/ui'
6
6
  import './social-svg.css'
7
7
 
8
8
  interface SocialIconProps {
@@ -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 AuthListener } from './auth/auth-listener'
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
 
@@ -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 } from '@hanzo/ui/types'
5
+ import { type TShirtSize } from '@hanzo/ui/types'
6
+ import { Logo as Mark, Wordmark } from '@luxfi/logo'
5
7
 
6
- import { LuxLogo } from './icons'
7
-
8
- const TEXT = 'LUX'
9
- type LogoVariant = 'text-only' | 'logo-only' | 'full'
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
- textClx='',
24
- variant='full',
39
+ outerClx = '',
40
+ variant = 'full',
25
41
  onClick,
26
42
  }) => {
27
- let classes: any = {}
28
- const toAdd = (variant === 'logo-only') ?
29
- {
30
- span: 'hidden',
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
- const outerClasses = 'flex flex-row items-center ' + outerClx
69
- const spanClasses = 'inline-block font-bold font-heading '
70
- + textClx
71
- + (href ? ' hover:opacity-80 cursor-pointer ' : ' cursor-default ')
72
- + classes.span
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
- <Link href={href} className={outerClasses} onClick={onClick} >
77
- <LuxLogo className={classes.icon} />
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
 
@@ -1,6 +1,5 @@
1
1
  import React, { type PropsWithChildren } from 'react'
2
- import { cn } from '@hanzo/ui/util'
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
- </main>
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</span></a>&nbsp;by TradingView
81
+ <Box tag="span" className="text-[--hz-ui-primary]">{symbol} quotes</Box></a>&nbsp;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