@luxfi/ui 5.5.3 → 5.5.5

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 (39) hide show
  1. package/LICENSE +29 -0
  2. package/components/auth/callback.tsx +40 -0
  3. package/components/auth/login-panel.tsx +15 -44
  4. package/components/auth/login.tsx +47 -0
  5. package/components/auth/provider.tsx +34 -0
  6. package/components/auth/resume.ts +16 -0
  7. package/components/auth/widget.tsx +80 -0
  8. package/components/chat-widget.tsx +6 -7
  9. package/components/commerce/checkout-panel/desktop-cp.tsx +2 -2
  10. package/components/commerce/checkout-panel/mobile-cp.tsx +2 -2
  11. package/components/footer-nav.tsx +31 -0
  12. package/components/footer.tsx +7 -12
  13. package/components/header/desktop-nav-menu.tsx +4 -6
  14. package/components/header/desktop.tsx +4 -4
  15. package/components/header/index.tsx +1 -1
  16. package/components/header/mobile-nav-menu-ai.tsx +1 -1
  17. package/components/header/mobile-nav-menu.tsx +2 -2
  18. package/components/header/mobile.tsx +3 -3
  19. package/components/icons/index.ts +0 -1
  20. package/components/index.ts +2 -2
  21. package/components/logo.tsx +39 -67
  22. package/components/security/index.tsx +55 -0
  23. package/next/analytics/fpixel.ts +1 -1
  24. package/next/middleware/determine-device-mw.ts +0 -13
  25. package/package.json +31 -28
  26. package/root-layout/index.tsx +3 -10
  27. package/site-def/footer/community.tsx +1 -4
  28. package/site-def/footer/network.ts +2 -2
  29. package/site-def/main-nav.tsx +19 -19
  30. package/style/lux-global.css +49 -0
  31. package/types/site-def.ts +7 -0
  32. package/util/index.ts +11 -0
  33. package/components/auth/auth-listener.tsx +0 -29
  34. package/components/auth/auth-token/clear-auth-token.tsx +0 -12
  35. package/components/auth/auth-token/set-auth-token.tsx +0 -16
  36. package/components/auth/common-auth-domains.ts +0 -17
  37. package/components/auth/mobile-login-button.tsx +0 -107
  38. package/components/auth/signup-panel.tsx +0 -113
  39. package/components/icons/lux-logo.tsx +0 -10
@@ -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,30 @@
1
1
  import React from 'react'
2
2
  import Link from 'next/link'
3
3
 
4
- import { type TShirtSize } from '@hanzo/ui/types'
4
+ import { type TShirtSize } from '@hanzo/ui/types'
5
+ import { Logo as Mark, Wordmark } from '@luxfi/logo'
5
6
 
6
- import { LuxLogo } from './icons'
7
-
8
- const TEXT = 'LUX'
9
- type LogoVariant = 'text-only' | 'logo-only' | 'full'
7
+ /**
8
+ * mark — the triangle alone
9
+ * wordmark — the LUX letterforms alone
10
+ * full — the mark beside the wordmark
11
+ *
12
+ * Both halves come from @luxfi/logo, which is the one home for Lux brand art.
13
+ * This file used to draw its own triangle and set the letters "LUX" in the body
14
+ * font, so every Lux site wore typed text where the wordmark belongs — and no
15
+ * variant could fix it, because neither the mark nor the wordmark was here to
16
+ * ask for. Art lives in the brand package; this composes it.
17
+ */
18
+ type LogoVariant = 'mark' | 'wordmark' | 'full'
10
19
 
20
+ /** Mark height in px, and the wordmark height that stands with it. */
21
+ const SIZE: Record<string, { mark: number, word: number, gap: string }> = {
22
+ xl: { mark: 40, word: 22, gap: 'gap-4' },
23
+ lg: { mark: 40, word: 22, gap: 'gap-4' },
24
+ md: { mark: 32, word: 18, gap: 'gap-3' },
25
+ sm: { mark: 24, word: 13, gap: 'gap-2' },
26
+ xs: { mark: 16, word: 9, gap: 'gap-1.5' },
27
+ }
11
28
 
12
29
  const Logo: React.FC<{
13
30
  size?: TShirtSize
@@ -15,74 +32,29 @@ const Logo: React.FC<{
15
32
  onClick?: () => void
16
33
  href?: string
17
34
  outerClx?: string
18
- textClx?: string
19
35
  }> = ({
20
- size,
36
+ size = 'md',
21
37
  href, // no default please!
22
- outerClx='',
23
- textClx='',
24
- variant='full',
38
+ outerClx = '',
39
+ variant = 'full',
25
40
  onClick,
26
41
  }) => {
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
-
42
+ const s = SIZE[size as string] ?? SIZE.md
43
+ const clx = 'flex flex-row items-center ' + s.gap + ' '
44
+ + (href ? 'hover:opacity-80 cursor-pointer ' : 'cursor-default ')
45
+ + outerClx
67
46
 
68
- const outerClasses = 'flex flex-row items-center ' + outerClx
69
- const spanClasses = 'inline-block font-bold font-heading '
70
- + textClx
71
- + (href ? ' hover:text-accent cursor-pointer ' : ' cursor-default ')
72
- + classes.span
47
+ // White on both counts: the Lux ground is black and the brand's accent is
48
+ // white, so the mark and the letters carry the same value.
49
+ const art = (<>
50
+ {variant !== 'wordmark' && <Mark variant='white' size={s.mark} />}
51
+ {variant !== 'mark' && <Wordmark height={s.word} />}
52
+ </>)
73
53
 
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
- )
54
+ return href ? (
55
+ <Link href={href} className={clx} onClick={onClick}>{art}</Link>
56
+ ) : (
57
+ <span className={clx} onClick={onClick}>{art}</span>
86
58
  )
87
59
  }
88
60
 
@@ -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
@@ -4,7 +4,7 @@ declare global {
4
4
  }
5
5
  }
6
6
 
7
- export const FB_PIXEL_ID = process.env.NEXT_PUBLIC_FACEBOOK_PIXEL_ID
7
+ export const FB_PIXEL_ID = process.env.NEXT_PUBLIC_FACEBOOK_PIXEL_ID || ''
8
8
 
9
9
  export const pageview = () => {
10
10
  window.fbq('track', 'PageView')
@@ -1,6 +1,5 @@
1
1
  import { NextRequest, NextResponse, userAgent } from 'next/server'
2
2
  import { getSelectorsByUserAgent } from 'react-device-detect'
3
- import { setCookie } from 'cookies-next'
4
3
 
5
4
  // writed this way so they can be chained :)
6
5
  const determineDeviceMW = async (request: NextRequest) => {
@@ -10,18 +9,6 @@ const determineDeviceMW = async (request: NextRequest) => {
10
9
  const agent = isMobileOnly ? 'phone' : (isTablet ? 'tablet' : (isDesktop ? 'desktop' : 'unknown'))
11
10
  const { nextUrl: url } = request
12
11
  //console.log(`\n=== from ${url.href} on a *${agent && agent.toUpperCase()}* device. ===\n`)
13
- const auth_token = url.searchParams.get('auth-token')
14
- if (auth_token) {
15
- setCookie('auth-token', auth_token, {
16
- domain: url.hostname,
17
- path: '/',
18
- sameSite: 'none',
19
- secure: true,
20
- httpOnly: false,
21
- expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30), // 30 days
22
- })
23
- url.searchParams.delete('auth-token')
24
- }
25
12
  url.searchParams.set('agent', agent)
26
13
  return NextResponse.rewrite(url)
27
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxfi/ui",
3
- "version": "5.5.3",
3
+ "version": "5.5.5",
4
4
  "description": "Library that contains shared UI primitives, support for a common design system, and other boilerplate support.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -18,29 +18,25 @@
18
18
  "hanzo",
19
19
  "luxdefi"
20
20
  ],
21
- "scripts": {
22
- "lat": "npm show @luxfi/ui version",
23
- "pub": "npm publish",
24
- "build": "tsc",
25
- "tc": "tsc",
26
- "clean": "rm -rf node_modules"
27
- },
28
21
  "exports": {
29
22
  ".": "./components/index.ts",
23
+ "./auth-callback": "./components/auth/callback.tsx",
24
+ "./security": "./components/security/index.tsx",
30
25
  "./commerce": "./commerce/ui/context.tsx",
31
26
  "./root-layout": "./root-layout/index.tsx",
32
27
  "./next": "./next/index.ts",
33
28
  "./style/": "./style/",
34
29
  "./site-def": "./site-def/index.ts",
35
- "./tailwind": "./tailwind/index.ts"
30
+ "./tailwind": "./tailwind/index.ts",
31
+ "./util": "./util/index.ts"
36
32
  },
37
33
  "dependencies": {
38
- "@next/third-parties": "^14.1.0",
39
- "cookies-next": "^4.1.1",
34
+ "@luxfi/logo": "^1.0.10",
35
+ "@next/third-parties": "^16.1.0",
40
36
  "date-fns": "^3.6.0",
41
37
  "embla-carousel-autoplay": "^8.1.6",
42
- "firebase": "10.12.0",
43
38
  "framer-motion": "^11.2.12",
39
+ "markdown-to-jsx": "^7.4.7",
44
40
  "react-device-detect": "^2.2.3",
45
41
  "react-social-icons": "^6.4.0",
46
42
  "react-tooltip": "^5.26.4",
@@ -48,19 +44,19 @@
48
44
  "usehooks-ts": "^3.1.0"
49
45
  },
50
46
  "peerDependencies": {
51
- "@hanzo/auth": "catalog:",
52
- "@hanzo/commerce": "catalog:",
53
- "@hanzo/ui": "catalog:",
54
- "@luxfi/menu-icons": "1.0.2",
47
+ "@hanzo/iam": "0.21.9",
48
+ "@hanzo/commerce": "7.6.4",
49
+ "@hanzo/ui": "5.3.34",
50
+ "@luxfi/menu-icons": "^1.0.2",
55
51
  "@hookform/resolvers": "^3.3.2",
56
- "lucide-react": "catalog:",
52
+ "lucide-react": "0.470.0",
57
53
  "mobx": "^6.12.3",
58
54
  "mobx-react-lite": "^4.0.7",
59
- "next": "catalog:",
60
- "next-themes": "^0.2.1",
61
- "react": "catalog:",
62
- "react-dom": "catalog:",
63
- "react-hook-form": "catalog:",
55
+ "next": "16.1.0",
56
+ "next-themes": "^0.4.0",
57
+ "react": "19.2.0",
58
+ "react-dom": "19.2.0",
59
+ "react-hook-form": "7.54.2",
64
60
  "validator": "^13.11.0",
65
61
  "zod": "3.23.8"
66
62
  },
@@ -71,11 +67,18 @@
71
67
  "@types/facebook-pixel": "^0.0.30",
72
68
  "@types/gtag.js": "^0.0.19",
73
69
  "@types/mdx": "^2.0.9",
74
- "@types/node": "catalog:",
75
- "@types/react": "catalog:",
76
- "@types/react-dom": "catalog:",
70
+ "@types/node": "22.10.6",
71
+ "@types/react": "19.0.2",
72
+ "@types/react-dom": "19.0.2",
77
73
  "@types/validator": "^13.12.1",
78
- "tailwindcss": "catalog:",
79
- "typescript": "catalog:"
74
+ "tailwindcss": "3.4.17",
75
+ "typescript": "5.7.3"
76
+ },
77
+ "scripts": {
78
+ "lat": "npm show @luxfi/ui version",
79
+ "pub": "npm publish",
80
+ "build": "tsc",
81
+ "tc": "tsc",
82
+ "clean": "rm -rf node_modules"
80
83
  }
81
- }
84
+ }
@@ -2,15 +2,13 @@ import React, { type PropsWithChildren } from 'react'
2
2
  import type { Viewport } from 'next'
3
3
 
4
4
  import { Toaster } from '@hanzo/ui/primitives'
5
- import { AuthServiceProvider } from '@hanzo/auth/service'
6
- import type { AuthServiceConf } from '@hanzo/auth/types'
7
5
  import { CommerceProvider } from '@hanzo/commerce'
8
6
 
9
7
  import getAppRouterBodyFontClasses from '../next/font/get-app-router-font-classes'
10
8
  import { FacebookPixelHead } from '../next/analytics/pixel-analytics'
11
9
 
12
10
  import { CommerceUIProvider } from '../commerce/ui/context'
13
- import { AuthListener, ChatWidget, Header, Analytics } from '../components'
11
+ import { Auth, ChatWidget, Header, Analytics } from '../components'
14
12
 
15
13
  import CommerceDrawer from '../components/commerce/drawer'
16
14
 
@@ -57,10 +55,6 @@ function RootLayout({
57
55
  chatbot?: boolean
58
56
  } & PropsWithChildren) {
59
57
 
60
- // For static export, we don't have server-side auth
61
- // User auth will be handled client-side via AuthListener
62
- const currentUser = null
63
-
64
58
  const Guts: React.FC = () => (<>
65
59
  {showHeader && <Header siteDef={siteDef}/>}
66
60
  {children}
@@ -87,7 +81,7 @@ function RootLayout({
87
81
  display: 'none', // see analytics.tsx
88
82
  }}>
89
83
  <Analytics/>
90
- <AuthServiceProvider user={currentUser} conf={{} as AuthServiceConf}>
84
+ <Auth app={siteDef.app}>
91
85
  {siteDef?.commerce ? (
92
86
  <CommerceProvider config={siteDef.commerce!} >
93
87
  <CommerceUIProvider >
@@ -98,8 +92,7 @@ function RootLayout({
98
92
  ) : (
99
93
  <Guts />
100
94
  )}
101
- <AuthListener/>
102
- </AuthServiceProvider>
95
+ </Auth>
103
96
  <Toaster position='top-center' duration={3000}/>
104
97
  </body>
105
98
  </html>
@@ -2,9 +2,6 @@ import type { LinkDef } from '@hanzo/ui/types'
2
2
 
3
3
  import { SocialIcon } from '../../components/icons'
4
4
 
5
- // @ts-ignore (will build in project that has @svgr support)
6
- import SVG_warp_logo from './svg/warpcast-logo.svg'
7
-
8
5
  const SOC_ICON_SIZE = 18
9
6
 
10
7
  export default [
@@ -16,7 +13,7 @@ export default [
16
13
  {
17
14
  title: 'Lux Channel',
18
15
  href: 'https://warpcast.com/~/channel/lux',
19
- icon: <SVG_warp_logo width={SOC_ICON_SIZE} height={SOC_ICON_SIZE} /> //<SocialIcon network='warpcast' size={SOC_ICON_SIZE} />
16
+ icon: <SocialIcon network='x' size={SOC_ICON_SIZE} />
20
17
  },
21
18
  {
22
19
  title: 'Lux Discussions',
@@ -23,8 +23,8 @@ export default [
23
23
  href: "https://safe.lux.network/",
24
24
  },
25
25
  {
26
- title: 'Lux Validator',
27
- href: "https://lux.network/validator",
26
+ title: 'Lux Build',
27
+ href: "https://lux.build",
28
28
  },
29
29
  {
30
30
  title: 'Lux Coin',
@@ -153,7 +153,7 @@ export default [
153
153
  title: "More benefits",
154
154
  icon: <MoreBenefits width={25} height={25} />,
155
155
  icon_act: <MoreBenefitsAct width={27} height={27} />,
156
- href: "#",
156
+ href: "https://lux.credit/compare",
157
157
  newTab: false,
158
158
  contents:"See what's truly unique"
159
159
  },
@@ -225,7 +225,7 @@ export default [
225
225
  title: "Shop",
226
226
  icon: <Shop width={25} height={25} />,
227
227
  icon_act: <ShopAct width={27} height={27}/>,
228
- href: "https://lux.market",
228
+ href: "https://lux.shop",
229
229
  newTab: false,
230
230
  contents:"Find any Lux product for sale"
231
231
  },
@@ -279,7 +279,7 @@ export default [
279
279
  title: "Explorer",
280
280
  icon: <Explorer width={25} height={25} />,
281
281
  icon_act: <ExplorerAct width={27} height={27}/>,
282
- href: "https://explorer.lux.network/",
282
+ href: "https://explore.lux.network/",
283
283
  newTab: false,
284
284
  contents:"All transactions"
285
285
  },
@@ -324,16 +324,16 @@ export default [
324
324
  title: "Validators",
325
325
  icon: <Validators width={25} height={25} />,
326
326
  icon_act: <ValidatorsAct width={27} height={27}/>,
327
- href: "https://lux.market/validator",
327
+ href: "https://lux.build",
328
328
  newTab: false,
329
- contents:"Own a part of the network"
329
+ contents:"Stake, delegate, and manage"
330
330
  },
331
331
  {
332
332
  groupName:'Get Access',
333
333
  title: "Developer docs",
334
334
  icon: <DeveloperDocs width={25} height={25} />,
335
335
  icon_act: <DeveloperDocsAct width={27} height={27}/>,
336
- href: "#",
336
+ href: "https://docs.lux.network",
337
337
  newTab: false,
338
338
  contents:"Software explained"
339
339
  },
@@ -342,7 +342,7 @@ export default [
342
342
  title: "Open Source",
343
343
  icon: <OpenSource width={25} height={25} />,
344
344
  icon_act: <OpenSourceAct width={27} height={27}/>,
345
- href: "#",
345
+ href: "https://github.com/luxfi",
346
346
  newTab: false,
347
347
  contents:"Accessible for everyone"
348
348
  },
@@ -351,7 +351,7 @@ export default [
351
351
  title: "Lux Pass",
352
352
  icon: <LuxPass width={25} height={25} />,
353
353
  icon_act: <LuxPassAct width={27} height={27}/>,
354
- href: "#",
354
+ href: "https://lux.market/pass",
355
355
  newTab: false,
356
356
  contents:"All access pass to network"
357
357
  },
@@ -360,7 +360,7 @@ export default [
360
360
  {
361
361
  title: "Resources",
362
362
  icon: '',
363
- href: "",
363
+ href: "https://docs.lux.network",
364
364
  newTab: false,
365
365
  details: "",
366
366
  childMenu: [
@@ -369,7 +369,7 @@ export default [
369
369
  title: "Resource Center",
370
370
  icon: <AIChat width={25} height={25} />,
371
371
  icon_act: <AIChatAct width={27} height={27}/>,
372
- href: "#",
372
+ href: "https://docs.lux.network",
373
373
  newTab: false,
374
374
  contents:"Dynamic solutions"
375
375
  },
@@ -378,7 +378,7 @@ export default [
378
378
  title: "Integrations",
379
379
  icon: <Integration width={25} height={25} />,
380
380
  icon_act: <IntegrationAct width={27} height={27}/>,
381
- href: "#",
381
+ href: "https://docs.lux.network/integrations",
382
382
  newTab: false,
383
383
  contents:"Simplified onboarding"
384
384
  },
@@ -387,7 +387,7 @@ export default [
387
387
  title: "Templates",
388
388
  icon: <Templates width={25} height={25} />,
389
389
  icon_act: <TemplatesAct width={27} height={27}/>,
390
- href: "#",
390
+ href: "https://docs.lux.network/templates",
391
391
  newTab: false,
392
392
  contents:"Speedy app development"
393
393
  },
@@ -396,7 +396,7 @@ export default [
396
396
  title: "Guides",
397
397
  icon: <Guides width={25} height={25} />,
398
398
  icon_act: <GuidesAct width={27} height={27}/>,
399
- href: "#",
399
+ href: "https://docs.lux.network/guides",
400
400
  newTab: false,
401
401
  contents:"Find help quickly"
402
402
  },
@@ -405,7 +405,7 @@ export default [
405
405
  title: "Customers",
406
406
  icon: <Customers width={25} height={25} />,
407
407
  icon_act: <CustomersAct width={27} height={27}/>,
408
- href: "#",
408
+ href: "https://lux.partners",
409
409
  newTab: false,
410
410
  contents:"Trusted by the best teams"
411
411
  },
@@ -414,7 +414,7 @@ export default [
414
414
  title: "Blog",
415
415
  icon: <Blog width={25} height={25} />,
416
416
  icon_act: <BlogAct width={27} height={27}/>,
417
- href: "#",
417
+ href: "https://blog.lux.network",
418
418
  newTab: false,
419
419
  contents:"Latest posts and changes"
420
420
  },
@@ -423,7 +423,7 @@ export default [
423
423
  title: "Changelog",
424
424
  icon: <ChangeLog width={25} height={25} />,
425
425
  icon_act: <ChangeLogAct width={27} height={27} />,
426
- href: "#",
426
+ href: "https://docs.lux.network/changelog",
427
427
  newTab: false,
428
428
  contents:"Manage deployments"
429
429
  },
@@ -432,7 +432,7 @@ export default [
432
432
  title: "Developer docs",
433
433
  icon: <DeveloperDocs width={25} height={25} />,
434
434
  icon_act: <DeveloperDocsAct width={25} height={25}/>,
435
- href: "#",
435
+ href: "https://docs.lux.network",
436
436
  newTab: false,
437
437
  contents:"Software explained"
438
438
  },
@@ -441,7 +441,7 @@ export default [
441
441
  title: "Customer Support",
442
442
  icon: <CustomerSupport width={25} height={25} />,
443
443
  icon_act: <CustomerSupportAct width={27} height={27}/>,
444
- href: "#",
444
+ href: "mailto:support@lux.network",
445
445
  newTab: false,
446
446
  contents:"Dedicated help, 24/7"
447
447
  },
@@ -450,7 +450,7 @@ export default [
450
450
  title: "FAQs",
451
451
  icon: <FAQs width={25} height={25} />,
452
452
  icon_act: <FAQsAct width={27} height={27}/>,
453
- href: "#",
453
+ href: "https://docs.lux.network/faq",
454
454
  newTab: false,
455
455
  contents:"Common queries"
456
456
  }
@@ -18,6 +18,55 @@ div.nextjs-toast-errors-parent[data-nextjs-toast="true"] {
18
18
  @apply uppercase;
19
19
  }
20
20
 
21
+ /* Hanzo IAM's sign-in views ship structure, not skin. This is the one place
22
+ * that markup meets the Lux surface -- colours come from lux-colors so the
23
+ * form follows the theme like everything else.
24
+ */
25
+ .hanzo-iam-card,
26
+ .hanzo-iam-form {
27
+ @apply flex flex-col gap-3 w-full;
28
+ }
29
+
30
+ .hanzo-iam-form input {
31
+ @apply w-full rounded-sm px-3 py-2 text-base;
32
+ background-color: var(--hz-ui-bg-1);
33
+ color: var(--hz-ui-fg-body);
34
+ border: 1px solid var(--hz-ui-bg-2);
35
+ }
36
+
37
+ .hanzo-iam-form input::placeholder {
38
+ color: var(--hz-ui-fg-3);
39
+ }
40
+
41
+ .hanzo-iam-form input:focus {
42
+ outline: none;
43
+ border-color: var(--hz-ui-fg-body);
44
+ }
45
+
46
+ .hanzo-iam-btn {
47
+ @apply w-full rounded-sm px-3 py-2 text-base font-semibold cursor-pointer;
48
+ background-color: var(--hz-ui-bg-inverted);
49
+ color: var(--hz-ui-fg-inverted);
50
+ }
51
+
52
+ .hanzo-iam-btn:hover {
53
+ background-color: var(--hz-ui-bg-inverted-hover);
54
+ }
55
+
56
+ .hanzo-iam-btn:disabled {
57
+ @apply opacity-50 cursor-default;
58
+ }
59
+
60
+ .hanzo-iam-divider {
61
+ @apply text-sm uppercase;
62
+ color: var(--hz-ui-fg-3);
63
+ }
64
+
65
+ .hanzo-iam-error {
66
+ @apply text-sm;
67
+ color: hsl(0 70% 60%);
68
+ }
69
+
21
70
  /* Specific style fixes for react-square-web-payments-sdk -
22
71
  * reduce gap between card input and pay button
23
72
  */
package/types/site-def.ts CHANGED
@@ -7,6 +7,13 @@ import type ChatbotConfig from './chatbot-config'
7
7
 
8
8
  interface SiteDef {
9
9
 
10
+ /**
11
+ * Short name of this site, which with the org names the IAM application it
12
+ * signs in as: 'quest' is the client `lux-quest` on lux.id. Required, so a
13
+ * site cannot ship a login button that belongs to no one.
14
+ */
15
+ app: string
16
+
10
17
  /** url of this site. All nav links in the system will show it in 'current' state */
11
18
  currentAs?: string
12
19
 
package/util/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { compiler } from 'markdown-to-jsx'
2
+
3
+ // Compiles markdown to JSX. `wrapper: null` yields the bare nodes rather than
4
+ // a wrapping element, so callers can drop the result straight into a
5
+ // ReactNode-typed field. Inline HTML (<br/>, <cite>) is parsed natively.
6
+ export const markdown = (s: string, options?: any) => (
7
+ compiler(s, {
8
+ wrapper: null,
9
+ ...options
10
+ })
11
+ )