@luxfi/ui 5.5.3 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +109 -0
  2. package/package.json +81 -73
  3. package/commerce/ui/conf.ts +0 -13
  4. package/commerce/ui/context.tsx +0 -123
  5. package/commerce/ui/store.ts +0 -295
  6. package/components/access-code-input.tsx +0 -71
  7. package/components/analytics.tsx +0 -23
  8. package/components/auth/auth-listener.tsx +0 -29
  9. package/components/auth/auth-token/clear-auth-token.tsx +0 -12
  10. package/components/auth/auth-token/set-auth-token.tsx +0 -16
  11. package/components/auth/common-auth-domains.ts +0 -17
  12. package/components/auth/login-panel.tsx +0 -111
  13. package/components/auth/mobile-login-button.tsx +0 -107
  14. package/components/auth/signup-panel.tsx +0 -113
  15. package/components/back-button.tsx +0 -49
  16. package/components/chat-widget.tsx +0 -85
  17. package/components/commerce/bag-button.tsx +0 -98
  18. package/components/commerce/buy-button.tsx +0 -34
  19. package/components/commerce/checkout-button.tsx +0 -129
  20. package/components/commerce/checkout-panel/cart-accordian.tsx +0 -66
  21. package/components/commerce/checkout-panel/checkout-panel-props.ts +0 -10
  22. package/components/commerce/checkout-panel/desktop-bag-carousel.tsx +0 -36
  23. package/components/commerce/checkout-panel/desktop-cp.tsx +0 -83
  24. package/components/commerce/checkout-panel/index.tsx +0 -126
  25. package/components/commerce/checkout-panel/mobile-cp.tsx +0 -67
  26. package/components/commerce/checkout-panel/policy-links.tsx +0 -29
  27. package/components/commerce/checkout-panel/steps-indicator.tsx +0 -39
  28. package/components/commerce/checkout-panel/thank-you.tsx +0 -18
  29. package/components/commerce/desktop-bag-popup.tsx +0 -78
  30. package/components/commerce/drawer/index.tsx +0 -88
  31. package/components/commerce/drawer/micro.tsx +0 -145
  32. package/components/commerce/drawer/shell.tsx +0 -85
  33. package/components/contact-dialog/contact-form.tsx +0 -116
  34. package/components/contact-dialog/disclaimer.tsx +0 -13
  35. package/components/contact-dialog/index.tsx +0 -64
  36. package/components/copyright.tsx +0 -21
  37. package/components/drawer-margin.tsx +0 -28
  38. package/components/footer.tsx +0 -78
  39. package/components/header/desktop-nav-menu.tsx +0 -204
  40. package/components/header/desktop.tsx +0 -65
  41. package/components/header/index.tsx +0 -50
  42. package/components/header/mobile-bag-drawer.tsx +0 -51
  43. package/components/header/mobile-menu-toggle-button.tsx +0 -35
  44. package/components/header/mobile-nav-menu-ai.tsx +0 -51
  45. package/components/header/mobile-nav-menu-item.tsx +0 -47
  46. package/components/header/mobile-nav-menu.tsx +0 -102
  47. package/components/header/mobile.tsx +0 -170
  48. package/components/header/theme-toggle.tsx +0 -26
  49. package/components/icons/avatar.tsx +0 -11
  50. package/components/icons/bag-icon.tsx +0 -10
  51. package/components/icons/index.ts +0 -6
  52. package/components/icons/left-arrow.tsx +0 -11
  53. package/components/icons/lux-logo.tsx +0 -10
  54. package/components/icons/right-arrow.tsx +0 -10
  55. package/components/icons/social-icon.tsx +0 -35
  56. package/components/icons/social-svg.css +0 -3
  57. package/components/index.ts +0 -26
  58. package/components/logo.tsx +0 -92
  59. package/components/main.tsx +0 -27
  60. package/components/mini-chart/index.tsx +0 -8
  61. package/components/mini-chart/mini-chart-props.ts +0 -44
  62. package/components/mini-chart/mini-chart.tsx +0 -85
  63. package/components/mini-chart/wrapper.tsx +0 -23
  64. package/components/not-found/index.tsx +0 -28
  65. package/components/not-found/not-found-content.mdx +0 -5
  66. package/components/tooltip.tsx +0 -31
  67. package/environment.d.ts +0 -6
  68. package/next/analytics/fpixel.ts +0 -16
  69. package/next/analytics/google-analytics.ts +0 -14
  70. package/next/analytics/index.ts +0 -3
  71. package/next/analytics/pixel-analytics.tsx +0 -55
  72. package/next/font/get-app-router-font-classes.ts +0 -17
  73. package/next/font/load-and-return-lux-next-fonts-on-import.ts +0 -68
  74. package/next/font/local/Druk-Wide-Bold.ttf +0 -0
  75. package/next/font/local/Druk-Wide-Medium.ttf +0 -0
  76. package/next/font/local/InterVariable-Italic.ttf +0 -0
  77. package/next/font/local/InterVariable-Italic.woff2 +0 -0
  78. package/next/font/local/InterVariable.ttf +0 -0
  79. package/next/font/local/InterVariable.woff2 +0 -0
  80. package/next/font/next-font-desc.ts +0 -28
  81. package/next/font/pages-router-font-vars.tsx +0 -18
  82. package/next/head-metadata/from-next/metadata-types.ts +0 -158
  83. package/next/head-metadata/from-next/opengraph-types.ts +0 -267
  84. package/next/head-metadata/from-next/twitter-types.ts +0 -92
  85. package/next/head-metadata/index.tsx +0 -208
  86. package/next/index.ts +0 -2
  87. package/next/middleware/determine-device-mw.ts +0 -29
  88. package/root-layout/WHY_THIS_IS_SEPARATE.txt +0 -2
  89. package/root-layout/index.tsx +0 -112
  90. package/site-def/footer/community.tsx +0 -61
  91. package/site-def/footer/company.ts +0 -37
  92. package/site-def/footer/ecosystem.ts +0 -37
  93. package/site-def/footer/index.tsx +0 -26
  94. package/site-def/footer/legal.ts +0 -28
  95. package/site-def/footer/network.ts +0 -45
  96. package/site-def/footer/svg/warpcast-logo.svg +0 -12
  97. package/site-def/index.ts +0 -4
  98. package/site-def/main-nav.tsx +0 -460
  99. package/style/cart-animation.css +0 -29
  100. package/style/checkout-animation.css +0 -23
  101. package/style/drawer-handle-overrides.css +0 -160
  102. package/style/fonts/COPY_TO_PUBLIC_FOR_NON_NEXT.txt +0 -0
  103. package/style/fonts/Druk-Wide-Bold.ttf +0 -0
  104. package/style/fonts/Druk-Wide-Medium.ttf +0 -0
  105. package/style/fonts/InterVariable-Italic.ttf +0 -0
  106. package/style/fonts/InterVariable-Italic.woff2 +0 -0
  107. package/style/fonts/InterVariable.ttf +0 -0
  108. package/style/fonts/InterVariable.woff2 +0 -0
  109. package/style/lux-colors.css +0 -85
  110. package/style/lux-fonts.css +0 -30
  111. package/style/lux-global-non-next.css +0 -52
  112. package/style/lux-global.css +0 -51
  113. package/tailwind/fontFamily.tailwind.lux.ts +0 -18
  114. package/tailwind/index.ts +0 -2
  115. package/tailwind/lux-tw-fonts.ts +0 -40
  116. package/tailwind/tailwind.config.lux-preset.ts +0 -10
  117. package/tsconfig.json +0 -15
  118. package/types/chatbot-config.ts +0 -7
  119. package/types/chatbot-suggested-question.ts +0 -7
  120. package/types/contact-info.ts +0 -11
  121. package/types/index.ts +0 -4
  122. package/types/site-def.ts +0 -46
@@ -1,85 +0,0 @@
1
- 'use client'
2
- import React, {type PropsWithChildren } from 'react'
3
- import { observer } from 'mobx-react-lite'
4
-
5
- import {
6
- Drawer,
7
- DrawerContent,
8
- DrawerHandle,
9
- type DrawerProps,
10
- } from '@hanzo/ui/primitives'
11
- import { cn } from '@hanzo/ui/util'
12
-
13
- import '../../../style/drawer-handle-overrides.css'
14
- import { useCommerceDrawer } from '../../../commerce/ui/context'
15
-
16
- const CommerceDrawer: React.FC<PropsWithChildren &
17
- Omit<DrawerProps,
18
- 'onOpenChange' |
19
- 'open' |
20
- 'snapPoints' |
21
- 'modal' |
22
- 'setActiveSnapPoint' |
23
- 'activeSnapPoint'
24
- > &
25
- {
26
- handleHandleClicked: () => void
27
- drawerClx?: string
28
- }
29
- > = observer(({
30
- children,
31
- handleHandleClicked,
32
- drawerClx='',
33
- ...rest
34
- }) => {
35
-
36
- const drawer = useCommerceDrawer()
37
-
38
- return (
39
- <Drawer
40
- open={drawer.open}
41
- onOpenChange={() => {}}
42
- modal={drawer.modal}
43
- snapPoints={drawer.points}
44
- activeSnapPoint={drawer.activePoint}
45
- setActiveSnapPoint={drawer.onActivePointChanged.bind(drawer)}
46
- fastDragSkipsToEnd={false}
47
- dragHandleOnly={true}
48
- handleHandleClicked={handleHandleClicked}
49
- extendHandleDragRegion={false}
50
- // debugOutput
51
- {...rest}
52
- >
53
- <DrawerContent
54
- defaultHandle={false}
55
- className={cn(
56
- 'border-0',
57
- drawer.isMobile ? 'pt-5' : 'pt-6',
58
- 'w-full h-full',
59
- )}
60
- // https://github.com/radix-ui/primitives/discussions/935
61
- onOpenAutoFocus={(e) => {e.preventDefault()}}
62
- >
63
- <DrawerHandle
64
- className={cn(
65
- 'absolute top-0 left-0 right-0 mx-auto z-10',
66
- 'flex justify-center items-start',
67
- 'border-t rounded-t-lg border-muted-3',
68
- drawer.isMobile ? 'h-5 touch-pan-y' : 'h-6',
69
- )}
70
- >
71
- <div className={cn(
72
- // pseudo-handle
73
- 'rounded-[3px] bg-level-3',
74
- drawer.isMobile ? 'w-[155px] mt-[5px] h-1.5' : 'w-[180px] mt-[3px] h-2.5 hover:bg-level-4',
75
- !drawer.isMobile ? 'cursor-grab active:cursor-grabbing' : '',
76
- )} />
77
- </DrawerHandle>
78
- {children}
79
- </DrawerContent>
80
- </Drawer>
81
- )
82
- })
83
-
84
-
85
- export default CommerceDrawer
@@ -1,116 +0,0 @@
1
- 'use client'
2
-
3
- import React, { useTransition } from 'react'
4
-
5
- import { useForm, type SubmitHandler, type ControllerRenderProps } from 'react-hook-form'
6
- import { z } from 'zod'
7
- import { zodResolver } from '@hookform/resolvers/zod'
8
-
9
- // @ts-ignore
10
- import validator from 'validator'
11
-
12
- import { Loader2 } from 'lucide-react'
13
-
14
- import {
15
- Button,
16
- Input,
17
- } from '@hanzo/ui/primitives'
18
-
19
- import {
20
- Form,
21
- FormControl,
22
- FormField,
23
- FormItem,
24
- FormMessage,
25
- } from '@hanzo/ui/form'
26
-
27
- import type { SubmitServerAction } from '@hanzo/ui/types'
28
- import type { ContactInfo } from '../../types'
29
-
30
- const ContactFormSchema = z.object({
31
- email: z
32
- .string()
33
- .min(1, { message: "Email must be provided." })
34
- .email("Invalid email."),
35
- phone: z
36
- .string()
37
- .min(1, { message: "Telephone must be provided." })
38
- .refine(validator.isMobilePhone, { message: "Invalid format." })
39
- })
40
-
41
- type ContactFormSchemaType = z.infer<typeof ContactFormSchema>
42
-
43
- const ContactForm: React.FC<{
44
- onSubmit: (data: ContactFormSchemaType, enc: any) => void
45
- enclosure: any
46
- }> = ({
47
- onSubmit: _onSubmit,
48
- enclosure
49
- }) => {
50
-
51
- const form = useForm<ContactFormSchemaType>({
52
- resolver: zodResolver(ContactFormSchema),
53
- defaultValues: {
54
- email: '',
55
- phone: '',
56
- },
57
- })
58
-
59
- const [isPending, startTransition] = useTransition()
60
-
61
- const onSubmit: SubmitHandler<ContactFormSchemaType> = (data) => {
62
- // https://github.com/orgs/react-hook-form/discussions/10757#discussioncomment-6672403
63
- // @ts-ignore
64
- startTransition(async () => {
65
- await _onSubmit(data, enclosure)
66
- })
67
- }
68
-
69
- const MyFormItem: React.FC<{
70
- field: ControllerRenderProps<ContactFormSchemaType, 'email'> | ControllerRenderProps<ContactFormSchemaType, 'phone'>
71
- placeholder: string
72
- }> = ({
73
- field,
74
- placeholder
75
- }) => (
76
- <FormItem className="space-y-0" >
77
- <FormControl>
78
- <Input placeholder={placeholder} {...field} className="mt-0 text-foreground"/>
79
- </FormControl>
80
- <div className="flex flex-row justify-start items-stretch gap-2">
81
- <FormMessage />
82
- </div>
83
- </FormItem>
84
- )
85
-
86
- return (
87
- <Form {...form}>
88
- <form onSubmit={form.handleSubmit(onSubmit)} className="w-3/4">
89
- <div className='flex flex-col justify-start items-stretch mt-4'>
90
- <FormField
91
- control={form.control}
92
- name='email'
93
- render={({ field }) => ( <MyFormItem field={field} placeholder='email'/> )}
94
- />
95
- <FormField
96
- control={form.control}
97
- name='phone'
98
- // @ts-ignore
99
- render={({ field }) => ( <MyFormItem field={field} placeholder='phone'/> )}
100
- />
101
- <Button disabled={isPending} type='submit' className='bg-primary text-primary-fg hover:bg-primary-hover'>
102
- {isPending ? (<>
103
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
104
- Please wait
105
- </>
106
- ) : (
107
- <>Submit</>
108
- )}
109
- </Button>
110
- </div>
111
- </form>
112
- </Form>
113
- )
114
- }
115
-
116
- export default ContactForm
@@ -1,13 +0,0 @@
1
- import React from 'react'
2
-
3
- const Disclaimer: React.FC = () => (
4
- <div>
5
- By entering your mobile number and submitting, you consent to receive text messages from Lux at the number provided.
6
- Message and data rates may apply. Message frequency varies.
7
- You can unsubscribe at any time by replying STOP.
8
- View our <a href='/privacy'>Privacy Policy</a> and <a href='/terms'>Terms & conditions</a>.
9
- </div>
10
- )
11
-
12
- export default Disclaimer
13
-
@@ -1,64 +0,0 @@
1
- 'use client'
2
-
3
- import React, { useState } from 'react'
4
-
5
- import type { ButtonModalProps} from '@hanzo/ui/types'
6
-
7
- import {
8
- Button,
9
- Dialog,
10
- DialogContent,
11
- DialogDescription,
12
- DialogHeader,
13
- DialogTitle,
14
- DialogTrigger,
15
- } from '@hanzo/ui/primitives'
16
-
17
- import ContactForm from './contact-form'
18
- import Disclaimer from './disclaimer'
19
-
20
- const ContactDialog: React.FC<ButtonModalProps> = ({
21
- open,
22
- onOpenChange,
23
- buttonText,
24
- buttonProps,
25
- title,
26
- byline,
27
- action,
28
- actionEnclosure
29
- }) => {
30
- const [success, setSuccess] = useState(false)
31
-
32
- const onSubmit = async (formData: any, enclosure: any) => {
33
- const result = await action(formData, enclosure)
34
- if (result.success) {
35
- setSuccess(true)
36
- }
37
- }
38
-
39
- return (
40
- <Dialog open={open} onOpenChange={onOpenChange} >
41
- <DialogTrigger asChild>
42
- <Button {...buttonProps} >{buttonText}</Button>
43
- </DialogTrigger>
44
- <DialogContent className="sm:max-w-[500px] p-0 gap-0 bg-background border">
45
- <DialogHeader className='py-6 text-foreground'>
46
- <DialogTitle className='text-4xl text-center text-inherit'>{title}</DialogTitle>
47
- {byline && (<DialogDescription className='text-inherit text-lg text-center'>{byline} </DialogDescription>)}
48
- </DialogHeader>
49
- <div className='px-8 pb-8 rounded-e-lg flex flex-col justify-start items-center'>
50
- {success ? (
51
- <p>{actionEnclosure?.reply}</p>
52
- ) : (
53
- <ContactForm onSubmit={onSubmit} enclosure={actionEnclosure}/>
54
- )}
55
- <div className='text-muted-1 text-xs mt-4' >
56
- <Disclaimer />
57
- </div>
58
- </div>
59
- </DialogContent>
60
- </Dialog>
61
- )
62
- }
63
-
64
- export default ContactDialog
@@ -1,21 +0,0 @@
1
- import React from 'react'
2
-
3
- const FIRST = 2020
4
-
5
- const Copyright: React.FC<{
6
- className?: string
7
- }> = ({
8
- className=''
9
- }) => {
10
-
11
- const year = new Date().getFullYear()
12
- const yearString = (year > FIRST) ? `${FIRST} - ${year}` : FIRST.toString()
13
-
14
- return (
15
- <div className={className}>
16
- {`Copyright © ${yearString}`}&nbsp;<br className='sm:hidden'/>Lux Partners Limited.&nbsp;<br className='md:hidden'/>&nbsp;All rights reserved.
17
- </div>
18
- )
19
- }
20
-
21
- export default Copyright
@@ -1,28 +0,0 @@
1
- 'use client'
2
- import React from 'react'
3
-
4
- import { cn } from '@hanzo/ui/util'
5
- import { useCommerceDrawer } from '@luxfi/ui/commerce'
6
- import { observer } from 'mobx-react-lite'
7
-
8
- const DrawerMargin: React.FC<{
9
- clx?: string
10
- }> = observer(({
11
- clx=''
12
- }) => {
13
-
14
- const drawer = useCommerceDrawer()
15
- if (!drawer) {
16
- throw new Error("DrawerMargin must be used with a CommerceUIContext!")
17
- }
18
- return (
19
- <div
20
- className={cn('transition-height', clx)}
21
- style={{
22
- height: drawer.state === 'micro' ? drawer.microHeight : 0
23
- }}
24
- />
25
- )
26
- })
27
-
28
- export default DrawerMargin
@@ -1,78 +0,0 @@
1
- import React from 'react'
2
-
3
- import type { LinkDef } from '@hanzo/ui/types'
4
- import { NavItems } from '@hanzo/ui/primitives'
5
- import { cn } from '@hanzo/ui/util'
6
-
7
- import Copyright from './copyright'
8
- import type { SiteDef } from '../site-def'
9
- import { legal } from '../site-def/footer/legal'
10
- import Logo from './logo'
11
-
12
- const Footer: React.FC<{
13
- siteDef: SiteDef,
14
- className?: string,
15
- noHorizPadding?: boolean
16
- }> = ({
17
- siteDef,
18
- className='',
19
- noHorizPadding=false
20
- }) => {
21
-
22
- const { footer, aboveCopyright } = siteDef
23
- const smGridCols = Math.floor(footer.length/2)
24
- const smGridColsClx = `sm:grid-cols-${smGridCols} `
25
- const _aboveCopyright = (typeof aboveCopyright === 'undefined') ? legal : aboveCopyright
26
-
27
- return (
28
- <footer className={cn('grow flex flex-col justify-between gap-6 pb-[2vh]', className)}>
29
- <div className={
30
- (noHorizPadding ? '' : 'px-5 md:px-8 ') +
31
- 'grid grid-cols-2 gap-4 gap-y-6 md:gap-x-6 lg:gap-8 ' + smGridColsClx +
32
- 'md:w-full sm:justify-items-center md:mx-0 lg:w-full ' +
33
- 'md:flex md:flex-row md:justify-between px-[24px]'
34
- }>
35
- <div className='hidden lg:flex flex-col' key={0}>
36
- <Logo size='md' variant='text-only' />
37
- </div>
38
- {footer.map((defs: LinkDef[], index: number) => {
39
-
40
- const xsColSpanClx = ((index === footer.length - 1) && (footer.length % 2 === 1)) ?
41
- 'xs:col-span-2 xs:mx-auto md:col-span-1 md:mx-0 ' : ''
42
-
43
- return (
44
- <NavItems
45
- items={defs}
46
- currentAs={siteDef.currentAs}
47
- as='nav'
48
- className={cn('sm:min-w-[150px] md:min-w-0 flex flex-col justify-start items-start ' +
49
- 'gap-[11px] sm:gap-[12px] md:gap-[15px] ',
50
- xsColSpanClx
51
- )}
52
- key={index + 1}
53
- itemClx={(def: LinkDef) => ((def.variant === 'linkFG') ?
54
- 'font-nav text-[15px]/[1.3] font-medium tracking-normal text-muted-1 sm:hover:text-foreground transition-color duration-500'
55
- :
56
- 'text-[15px]/[1.1] font-normal tracking-[0.2px] text-muted-1 sm:hover:text-foreground transition-color duration-500'
57
- )}
58
- />
59
- )
60
- })}
61
- </div>
62
- <div className='md:mt-[2vh]'>
63
- {_aboveCopyright.length > 0 && (
64
- <NavItems
65
- items={_aboveCopyright}
66
- as='div'
67
- className={'flex flex-row justify-center gap-4 mb-2'}
68
- itemClx={'text-sm text-center text-muted-2 underline hover:text-foreground'}
69
- />
70
- )}
71
- <Copyright className='text-sm text-center text-muted-3'/>
72
- </div>
73
- </footer>
74
- )
75
- }
76
-
77
- export default Footer
78
- // flex flex-col justify-between gap-6
@@ -1,204 +0,0 @@
1
- 'use client'
2
-
3
- import * as React from 'react'
4
- import Link from 'next/link'
5
- import { cn } from '@hanzo/ui/util'
6
- import type { ChildMenu, LinkDefExtended } from '../../site-def/main-nav'
7
- import {
8
- NavigationMenu,
9
- NavigationMenuContent,
10
- NavigationMenuItem,
11
- NavigationMenuLink,
12
- NavigationMenuList,
13
- NavigationMenuTrigger,
14
- navigationMenuTriggerStyle
15
- } from '@hanzo/ui/primitives'
16
-
17
- const DesktopNav: React.FC<{
18
- links: LinkDefExtended[],
19
- isMenuOpened: boolean,
20
- setIsMenuOpen: React.Dispatch<React.SetStateAction<boolean>>
21
- }> = ({ links, isMenuOpened, setIsMenuOpen }) => {
22
-
23
- React.useEffect(() => {
24
- const preventScroll = (e: WheelEvent | TouchEvent) => {
25
- e.preventDefault()
26
- }
27
-
28
- if (isMenuOpened) {
29
- window.addEventListener('wheel', preventScroll, { passive: false })
30
- window.addEventListener('touchmove', preventScroll, { passive: false })
31
- window.addEventListener('keydown', preventScrollKeys, { passive: false })
32
- } else {
33
- window.removeEventListener('wheel', preventScroll)
34
- window.removeEventListener('touchmove', preventScroll)
35
- window.removeEventListener('keydown', preventScrollKeys)
36
- }
37
-
38
- return () => {
39
- window.removeEventListener('wheel', preventScroll)
40
- window.removeEventListener('touchmove', preventScroll)
41
- window.removeEventListener('keydown', preventScrollKeys)
42
- }
43
- }, [isMenuOpened])
44
-
45
- const preventScrollKeys = (e: KeyboardEvent) => {
46
- if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ' '].includes(e.key)) {
47
- e.preventDefault()
48
- }
49
- }
50
-
51
- const handleMouseEnter = React.useCallback(() => {
52
- setIsMenuOpen(true)
53
- }, [setIsMenuOpen])
54
-
55
- const handleMouseLeave = React.useCallback(() => {
56
- setIsMenuOpen(false)
57
- }, [setIsMenuOpen])
58
-
59
- const handleContentMouseMove = () => {
60
- setIsMenuOpen(false)
61
- }
62
-
63
- const menuHiddenClass = !isMenuOpened ? 'invisible' : ''
64
-
65
- return links.length > 0 ? (
66
- <NavigationMenu>
67
- <NavigationMenuList>
68
- {links.map((el, index) => (
69
- <NavigationMenuItem key={index} className='!m-0'>
70
- {el.isAIMenu ? (
71
- <Link href={el.href} legacyBehavior passHref>
72
- <NavigationMenuLink className={cn(navigationMenuTriggerStyle(), ' text-muted-1 bg-transparent')}>
73
- {el.title}
74
- </NavigationMenuLink>
75
- </Link>
76
- ) : el.title === 'Cards' ? (
77
- <>
78
- <NavigationMenuTrigger
79
- className='text-muted-1 bg-transparent'
80
- onMouseEnter={handleMouseEnter}
81
- onFocus={handleMouseEnter}
82
- onMouseLeave={handleMouseLeave}
83
- onBlur={handleMouseLeave}
84
- >
85
- <Link href={el.href} legacyBehavior passHref>
86
- {el.title}
87
- </Link>
88
- </NavigationMenuTrigger>
89
- <NavigationMenuContent
90
- className={cn('fixed left-0 top-14 pt-6 w-screen h-full border-0 !backdrop-blur-3xl bg-transparent mt-0', menuHiddenClass)}
91
- onMouseEnter={handleMouseEnter}
92
- onMouseLeave={handleMouseLeave}
93
- >
94
- <div className='flex justify-center items-start'>
95
- <div
96
- className='grid xl:grid-cols-3 w-full justify-center max-w-[750px]'
97
- onMouseLeave={handleContentMouseMove}
98
- >
99
- {GroupChildMenu({ childs: el.childMenu, isCards: true })}
100
- </div>
101
- </div>
102
- </NavigationMenuContent>
103
- </>
104
- ) : (
105
- <>
106
- <NavigationMenuTrigger
107
- className='text-muted-1 bg-transparent'
108
- onMouseEnter={handleMouseEnter}
109
- onFocus={handleMouseEnter}
110
- onMouseLeave={handleMouseLeave}
111
- onBlur={handleMouseLeave}
112
- >
113
- {
114
- el.href && el.href !== '' ?
115
- <Link href={el.href} legacyBehavior passHref>
116
- {el.title}
117
- </Link> : <>{el.title}</>
118
- }
119
- </NavigationMenuTrigger>
120
- <NavigationMenuContent
121
- className={cn('fixed left-0 top-14 pt-6 w-screen h-full border-0 !backdrop-blur-3xl bg-transparent mt-0', menuHiddenClass)}
122
- onMouseEnter={handleMouseEnter}
123
- onMouseLeave={handleMouseLeave}
124
- >
125
- <div
126
- className='flex flex-row w-full justify-center'
127
- onMouseLeave={handleContentMouseMove}
128
- >
129
- {GroupChildMenu({ childs: el.childMenu })}
130
- </div>
131
- </NavigationMenuContent>
132
- </>
133
- )}
134
- </NavigationMenuItem>
135
- ))}
136
- </NavigationMenuList>
137
- </NavigationMenu>
138
- ) : null
139
- }
140
-
141
- export default DesktopNav
142
-
143
- const ListItem = React.forwardRef<
144
- React.ElementRef<'a'>,
145
- React.ComponentPropsWithoutRef<'a'>
146
- >(({ className, title, children, ...props }, ref) => (
147
- <li key={title}>
148
- <NavigationMenuLink asChild>
149
- <a
150
- ref={ref}
151
- className={cn(
152
- 'block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:text-accent-foreground focus:bg-level-1 focus:text-accent-foreground text-muted-1 hover:text-primary hover:bg-transparent duration-1000 ease-in-out',
153
- className
154
- )}
155
- {...props}
156
- >
157
- <div className='text-sm font-medium leading-none'>{title}</div>
158
- <p className='line-clamp-3 text-sm leading-snug text-muted-1'>
159
- {children}
160
- </p>
161
- </a>
162
- </NavigationMenuLink>
163
- </li>
164
- ))
165
- ListItem.displayName = 'ListItem'
166
-
167
- const GroupChildMenu = (params: { childs: ChildMenu[] | undefined, isCards?: boolean }) => {
168
- const { childs, isCards = false } = params
169
-
170
- if (!childs) {
171
- return null
172
- }
173
-
174
- const groupedChildMenus = childs.reduce((grouped: Record<string, ChildMenu[]>, childLink) => {
175
- if (childLink.groupName) {
176
- grouped[childLink.groupName] = grouped[childLink.groupName] || []
177
- grouped[childLink.groupName].push(childLink)
178
- }
179
- return grouped
180
- }, {})
181
-
182
- const getChildExtraClass = (index: number) => {
183
- if (isCards && (index === 3 || index === 4)) {
184
- return 'xl:-mt-32'
185
- }
186
- return ''
187
- }
188
-
189
- return Object.entries(groupedChildMenus).map(([groupName, childLinks], index) => (
190
- <div key={groupName} className={cn('py-4 px-4 ', getChildExtraClass(index))}>
191
- <h2 className='text-muted-1'>{groupName}</h2>
192
- <ul className='w-[200px] gap-3 md:w-[250px] lg:w-[250px]'>
193
- {childLinks.map((link) => (
194
- <div className='flex justify-start items-center' key={link.title}>
195
- {link.icon}
196
- <ListItem key={link.title} title={link.title} href={link.href} className='ml-[14px]'>
197
- {link.contents}
198
- </ListItem>
199
- </div>
200
- ))}
201
- </ul>
202
- </div>
203
- ))
204
- }
@@ -1,65 +0,0 @@
1
- import React, { type PropsWithChildren } from 'react'
2
-
3
- import { cn } from '@hanzo/ui/util'
4
- import { AuthWidget } from '@hanzo/auth/components'
5
-
6
- import Logo, { type LogoVariant } from '../logo'
7
-
8
- import DesktopBagPopup from '../commerce/desktop-bag-popup'
9
- import BagButton from '../commerce/bag-button'
10
- import DesktopNav from './desktop-nav-menu'
11
-
12
-
13
- import type { LinkDef } from '@hanzo/ui/types'
14
-
15
- const DesktopHeader: React.FC<{
16
- currentAs: string | undefined
17
- links: LinkDef[]
18
- className?: string
19
- noAuth?: boolean
20
- noCommerce?: boolean
21
- logoVariant?: LogoVariant
22
- } & PropsWithChildren> = ({
23
- links,
24
- className = '',
25
- noAuth=false,
26
- noCommerce=false,
27
- children,
28
- logoVariant='text-only'
29
- }) => {
30
- const [isMenuOpened, setIsMenuOpen] = React.useState(false);
31
-
32
- // TODO move 13px into a size class and configure twMerge to recognize say, 'text-size-nav'
33
- // (vs be beat out by 'text-color-nav')
34
- return (
35
- <header id='DESKTOP_HEADER' className={cn(
36
- 'bg-[rgba(0, 0, 0, 0.5)] !backdrop-blur-3xl fixed z-header top-0 left-0 right-0',
37
- className,
38
- isMenuOpened ? ' h-full' : ''
39
- )} >
40
- {/* md or larger */}
41
- <div className={
42
- 'flex flex-row h-[80px] items-center justify-between ' +
43
- 'mx-[24px] w-full max-w-screen'
44
- }>
45
- <Logo size={logoVariant === 'logo-only' ? 'lg' : 'md'} href='/' outerClx='hidden lg:flex' key='two' variant={logoVariant} />
46
- <Logo size='sm' href='/' outerClx='hidden md:flex lg:hidden' key='one' variant={logoVariant} />
47
- {/* md or larger */}
48
- <div className='flex w-full gap-4 items-center justify-center'>
49
- <DesktopNav links={links} isMenuOpened={isMenuOpened} setIsMenuOpen={setIsMenuOpen} />
50
- </div>
51
- <div className='flex items-center'>
52
- {!noCommerce && (
53
- <DesktopBagPopup popupClx='w-[340px]' trigger={<BagButton className='text-primary -mr-[3px] lg:min-w-0' />} />
54
- )}
55
- <AuthWidget noLogin={noAuth}/>
56
- {children}
57
- </div>
58
- </div>
59
- </header>
60
- )
61
- }
62
-
63
- export default DesktopHeader
64
-
65
-