@luxfi/core 5.2.12 → 5.2.13

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 (178) hide show
  1. package/commerce/ui/conf.ts +13 -13
  2. package/commerce/ui/context.tsx +126 -126
  3. package/commerce/ui/store.ts +304 -304
  4. package/components/access-code-input.tsx +71 -71
  5. package/components/auth/auth-listener.tsx +29 -29
  6. package/components/auth/auth-token/clear-auth-token.tsx +12 -12
  7. package/components/auth/auth-token/set-auth-token.tsx +16 -16
  8. package/components/auth/common-auth-domains.ts +16 -16
  9. package/components/auth/login-panel.tsx +107 -107
  10. package/components/back-button.tsx +42 -42
  11. package/components/chat-widget.tsx +85 -85
  12. package/components/commerce/add-widget.tsx +20 -20
  13. package/components/commerce/bag-button.tsx +98 -98
  14. package/components/commerce/buy-button.tsx +34 -34
  15. package/components/commerce/checkout-button.tsx +129 -129
  16. package/components/commerce/checkout-panel/dt-bag-carousel.tsx +36 -36
  17. package/components/commerce/checkout-panel/dt-checkout-panel.tsx +84 -84
  18. package/components/commerce/checkout-panel/index.tsx +129 -129
  19. package/components/commerce/checkout-panel/links-row.tsx +21 -21
  20. package/components/commerce/checkout-panel/mb-checkout-panel.tsx +54 -54
  21. package/components/commerce/checkout-panel/steps-indicator.tsx +39 -39
  22. package/components/commerce/checkout-panel/thank-you.tsx +18 -18
  23. package/components/commerce/checkout-widget/const.ts +13 -13
  24. package/components/commerce/checkout-widget/index.tsx +192 -192
  25. package/components/commerce/checkout-widget/obs-string-set.ts +48 -48
  26. package/components/commerce/checkout-widget/use-anim-clx-set.ts +58 -58
  27. package/components/commerce/desktop-bag-popup.tsx +78 -78
  28. package/components/commerce/desktop-nav-menu.tsx +130 -130
  29. package/components/commerce/drawer/index.tsx +99 -99
  30. package/components/commerce/drawer/micro.tsx +144 -144
  31. package/components/commerce/drawer/shell.tsx +85 -85
  32. package/components/commerce/mobile-bag-drawer.tsx +51 -51
  33. package/components/commerce/mobile-login-button.tsx +101 -101
  34. package/components/commerce/mobile-menu-toggle-button.tsx +35 -35
  35. package/components/commerce/mobile-nav-menu-ai.tsx +48 -48
  36. package/components/commerce/mobile-nav-menu-item.tsx +49 -49
  37. package/components/commerce/mobile-nav-menu.tsx +101 -101
  38. package/components/contact-dialog/contact-form.tsx +113 -113
  39. package/components/contact-dialog/disclaimer.tsx +13 -13
  40. package/components/contact-dialog/index.tsx +64 -64
  41. package/components/copyright.tsx +21 -21
  42. package/components/drawer-margin.tsx +25 -25
  43. package/components/footer.tsx +77 -77
  44. package/components/header/desktop.tsx +50 -50
  45. package/components/header/index.tsx +52 -52
  46. package/components/header/mobile.tsx +163 -163
  47. package/components/header/theme-toggle.tsx +26 -26
  48. package/components/icons/24k-gold-card.tsx +43 -43
  49. package/components/icons/ai-chat-act.tsx +47 -47
  50. package/components/icons/ai-chat.tsx +29 -29
  51. package/components/icons/anodized-titanium.tsx +45 -45
  52. package/components/icons/avatar.tsx +11 -11
  53. package/components/icons/bag-icon.tsx +10 -10
  54. package/components/icons/blog-act.tsx +14 -14
  55. package/components/icons/blog.tsx +20 -20
  56. package/components/icons/bridge-act.tsx +18 -18
  57. package/components/icons/bridge.tsx +68 -68
  58. package/components/icons/changelog-act.tsx +15 -15
  59. package/components/icons/changelog.tsx +21 -21
  60. package/components/icons/chrome.tsx +45 -45
  61. package/components/icons/coins-act.tsx +29 -29
  62. package/components/icons/coins.tsx +20 -20
  63. package/components/icons/compare-cards-act.tsx +30 -30
  64. package/components/icons/compare-cards.tsx +21 -21
  65. package/components/icons/credit-act.tsx +29 -29
  66. package/components/icons/credit.tsx +20 -20
  67. package/components/icons/customer-support-act.tsx +27 -27
  68. package/components/icons/customer-support.tsx +21 -21
  69. package/components/icons/customers-act.tsx +65 -65
  70. package/components/icons/customers.tsx +33 -33
  71. package/components/icons/developer-docs-act.tsx +26 -26
  72. package/components/icons/developer-docs.tsx +20 -20
  73. package/components/icons/exchange-act.tsx +27 -27
  74. package/components/icons/exchange.tsx +21 -21
  75. package/components/icons/explorer-act.tsx +27 -27
  76. package/components/icons/explorer.tsx +22 -22
  77. package/components/icons/faqs-act.tsx +27 -27
  78. package/components/icons/faqs.tsx +21 -21
  79. package/components/icons/github.tsx +14 -14
  80. package/components/icons/guides-act.tsx +26 -26
  81. package/components/icons/guides.tsx +21 -21
  82. package/components/icons/gun-metal.tsx +44 -44
  83. package/components/icons/index.tsx +43 -43
  84. package/components/icons/integrations-act.tsx +41 -41
  85. package/components/icons/integrations.tsx +25 -25
  86. package/components/icons/irradescent.tsx +41 -41
  87. package/components/icons/launch-subnet.tsx +21 -21
  88. package/components/icons/launchsubnet-act.tsx +29 -29
  89. package/components/icons/left-arrow.tsx +11 -11
  90. package/components/icons/lux-finance-act.tsx +34 -34
  91. package/components/icons/lux-finance.tsx +23 -23
  92. package/components/icons/lux-logo.tsx +10 -10
  93. package/components/icons/lux-pass-act.tsx +41 -41
  94. package/components/icons/lux-pass.tsx +25 -25
  95. package/components/icons/lux-quests-act.tsx +15 -15
  96. package/components/icons/lux-quests.tsx +21 -21
  97. package/components/icons/market-act.tsx +39 -39
  98. package/components/icons/market.tsx +24 -24
  99. package/components/icons/mirrored-titanium.tsx +46 -46
  100. package/components/icons/more-benefits-act.tsx +29 -29
  101. package/components/icons/more-benefits.tsx +21 -21
  102. package/components/icons/open-source-act.tsx +41 -41
  103. package/components/icons/open-source.tsx +26 -26
  104. package/components/icons/right-arrow.tsx +10 -10
  105. package/components/icons/safe-act.tsx +77 -77
  106. package/components/icons/safe.tsx +37 -37
  107. package/components/icons/search.tsx +12 -12
  108. package/components/icons/secure-delivery.tsx +13 -13
  109. package/components/icons/shop-act.tsx +29 -29
  110. package/components/icons/shop.tsx +20 -20
  111. package/components/icons/social-icon.tsx +35 -35
  112. package/components/icons/social-svg.css +3 -3
  113. package/components/icons/sterling-silver-card.tsx +44 -44
  114. package/components/icons/templates-act.tsx +29 -29
  115. package/components/icons/templates.tsx +21 -21
  116. package/components/icons/validators-act.tsx +42 -42
  117. package/components/icons/validators.tsx +41 -41
  118. package/components/icons/view-all-card-act.tsx +28 -28
  119. package/components/icons/view-all-card.tsx +20 -20
  120. package/components/icons/wallet-act.tsx +29 -29
  121. package/components/icons/wallet.tsx +20 -20
  122. package/components/icons/warpcast.tsx +58 -58
  123. package/components/icons/youtube-logo.tsx +59 -59
  124. package/components/index.ts +27 -27
  125. package/components/logo.tsx +89 -89
  126. package/components/main.tsx +27 -27
  127. package/components/mini-chart/index.tsx +7 -7
  128. package/components/mini-chart/mini-chart-props.ts +43 -43
  129. package/components/mini-chart/mini-chart.tsx +85 -85
  130. package/components/mini-chart/wrapper.tsx +23 -23
  131. package/components/not-found/index.tsx +28 -28
  132. package/components/not-found/not-found-content.mdx +5 -5
  133. package/components/scripts.tsx +24 -24
  134. package/components/tooltip.tsx +31 -31
  135. package/environment.d.ts +5 -5
  136. package/next/analytics/fpixel.ts +15 -15
  137. package/next/analytics/google-analytics.ts +13 -13
  138. package/next/analytics/index.ts +3 -3
  139. package/next/analytics/pixel-analytics.tsx +54 -54
  140. package/next/font/get-app-router-font-classes.ts +12 -12
  141. package/next/font/load-and-return-lux-next-fonts-on-import.ts +68 -68
  142. package/next/font/next-font-desc.ts +27 -27
  143. package/next/font/pages-router-font-vars.tsx +18 -18
  144. package/next/head-metadata/from-next/metadata-types.ts +158 -158
  145. package/next/head-metadata/from-next/opengraph-types.ts +267 -267
  146. package/next/head-metadata/from-next/twitter-types.ts +92 -92
  147. package/next/head-metadata/index.tsx +208 -208
  148. package/next/middleware/determine-device-mw.ts +16 -16
  149. package/package.json +79 -79
  150. package/root-layout/WHY_THIS_IS_SEPARATE.txt +1 -1
  151. package/root-layout/index.tsx +112 -112
  152. package/server-actions/firebase-app.ts +14 -14
  153. package/server-actions/index.ts +5 -5
  154. package/server-actions/store-contact.ts +51 -51
  155. package/site-def/footer/community.tsx +67 -67
  156. package/site-def/footer/company.ts +37 -37
  157. package/site-def/footer/ecosystem.ts +37 -37
  158. package/site-def/footer/index.tsx +26 -26
  159. package/site-def/footer/legal.ts +28 -28
  160. package/site-def/footer/network.ts +45 -45
  161. package/site-def/footer/svg/warpcast-logo.svg +11 -11
  162. package/site-def/index.ts +2 -2
  163. package/site-def/main-nav.tsx +458 -458
  164. package/style/cart-animation.css +29 -29
  165. package/style/checkout-animation.css +23 -23
  166. package/style/drawer-handle-overrides.css +160 -160
  167. package/style/lux-colors.css +85 -85
  168. package/style/lux-global.css +47 -47
  169. package/tailwind/fontFamily.tailwind.lux.ts +18 -18
  170. package/tailwind/index.ts +2 -2
  171. package/tailwind/lux-tw-fonts.ts +39 -39
  172. package/tailwind/tailwind.config.lux-preset.ts +10 -10
  173. package/tsconfig.json +15 -15
  174. package/types/chatbot-config.ts +6 -6
  175. package/types/chatbot-suggested-question.ts +7 -7
  176. package/types/contact-info.ts +10 -10
  177. package/types/index.ts +4 -4
  178. package/types/site-def.ts +43 -43
@@ -1,102 +1,102 @@
1
- 'use client'
2
- import React from 'react'
3
- import type { LinkDef } from '@hanzo/ui/types'
4
- import { cn } from '@hanzo/ui/util'
5
- import type { LinkDefExtended, ChildMenu } from '../../site-def/main-nav'
6
- import MobileNavMenuAI from './mobile-nav-menu-ai'
7
- import MobileNavMenuItem from './mobile-nav-menu-item'
8
- import MobileAuthWidget from './mobile-login-button'
9
- import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@hanzo/ui/primitives'
10
- import { ChevronDown } from 'lucide-react'
11
- import Link from 'next/link'
12
-
13
- const MobileNav: React.FC<{
14
- currentAs: string | undefined
15
- links: LinkDefExtended[]
16
- className?: string
17
- commonItemClx?: string | ((def: LinkDef) => string)
18
- setChatbotOpen: (open: boolean) => void
19
- setMenuOpen: (open: boolean) => void
20
- setMenuState: (arg: 'closed' | 'nav' | 'login' | 'bag') => void
21
- }> = ({
22
- currentAs,
23
- links,
24
- setMenuState,
25
- className = '',
26
- commonItemClx,
27
- setChatbotOpen,
28
- setMenuOpen
29
- }) => (
30
- links.length > 0 ? (
31
- <div className={cn('flex flex-col h-full', className)}>
32
- <MobileNavMenuAI setMenuOpen={setMenuOpen} />
33
- <div className="flex flex-col flex-1 overflow-auto">
34
- <Accordion type="single" collapsible className='w-full h-full'>
35
- {links.map((el, index) => {
36
- const itemClx = (commonItemClx) ? (typeof commonItemClx === 'string' ? commonItemClx : commonItemClx(el)) : ''
37
- const variant = el.variant ?? 'link'
38
- let internalClx = variant === 'link'
39
- ? ' text-muted hover:text-foreground active:text-accent rounded-none'
40
- : ' min-w-0'
41
-
42
- if (currentAs && currentAs === el.href) {
43
- internalClx += ' pointer-events-none'
44
- if (variant === 'link') {
45
- internalClx += ' text-accent'
46
- }
47
- }
48
-
49
- if (!el.isAIMenu) {
50
- return (
51
- <AccordionItem key={index} value={el.title ? el.title : ""} className='!no-underline !border-0'>
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')}>
54
- {el.title}
55
- </div>
56
- <ChevronDown className="w-4 h-4 mr-3" />
57
- </AccordionTrigger>
58
- <AccordionContent>
59
- {el.childMenu && (
60
- <div className="px-4">
61
- {Object.entries(el.childMenu.reduce((acc, child) => {
62
- const group = acc[child.groupName ? child.groupName : ""] || []
63
- group.push(child)
64
- acc[child.groupName ? child.groupName : ""] = group
65
- return acc
66
- }, {} as { [key: string]: ChildMenu[] })).map(([groupName, children]) => (
67
- <div key={groupName}>
68
- <div className="mt-4 mb-4 font-light text-muted-1">{groupName}</div>
69
- {children.map((child, childIndex) => (
70
- <div key={childIndex} className="m-2">
71
- <div className="flex items-center py-1">
72
- <span>
73
- {child.icon && child.icon}
74
- </span>
75
- <Link
76
- href={child.href}
77
- className="text-muted-2 hover:underline ml-5 hover:text-primary"
78
- target={child.newTab ? '_blank' : '_self'}
79
- rel="noopener noreferrer"
80
- >
81
- {child.title}
82
- </Link>
83
- </div>
84
- </div>
85
- ))}
86
- </div>
87
- ))}
88
- </div>
89
- )}
90
- </AccordionContent>
91
- </AccordionItem>
92
- )
93
- }
94
- })}
95
- </Accordion>
96
- </div>
97
- <MobileAuthWidget className='text-2xl z-10' handleLogin={() => { setMenuState('login') }} />
98
- </div>
99
- ) : null
100
- );
101
-
1
+ 'use client'
2
+ import React from 'react'
3
+ import type { LinkDef } from '@hanzo/ui/types'
4
+ import { cn } from '@hanzo/ui/util'
5
+ import type { LinkDefExtended, ChildMenu } from '../../site-def/main-nav'
6
+ import MobileNavMenuAI from './mobile-nav-menu-ai'
7
+ import MobileNavMenuItem from './mobile-nav-menu-item'
8
+ import MobileAuthWidget from './mobile-login-button'
9
+ import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@hanzo/ui/primitives'
10
+ import { ChevronDown } from 'lucide-react'
11
+ import Link from 'next/link'
12
+
13
+ const MobileNav: React.FC<{
14
+ currentAs: string | undefined
15
+ links: LinkDefExtended[]
16
+ className?: string
17
+ commonItemClx?: string | ((def: LinkDef) => string)
18
+ setChatbotOpen: (open: boolean) => void
19
+ setMenuOpen: (open: boolean) => void
20
+ setMenuState: (arg: 'closed' | 'nav' | 'login' | 'bag') => void
21
+ }> = ({
22
+ currentAs,
23
+ links,
24
+ setMenuState,
25
+ className = '',
26
+ commonItemClx,
27
+ setChatbotOpen,
28
+ setMenuOpen
29
+ }) => (
30
+ links.length > 0 ? (
31
+ <div className={cn('flex flex-col h-full', className)}>
32
+ <MobileNavMenuAI setMenuOpen={setMenuOpen} />
33
+ <div className="flex flex-col flex-1 overflow-auto">
34
+ <Accordion type="single" collapsible className='w-full h-full'>
35
+ {links.map((el, index) => {
36
+ const itemClx = (commonItemClx) ? (typeof commonItemClx === 'string' ? commonItemClx : commonItemClx(el)) : ''
37
+ const variant = el.variant ?? 'link'
38
+ let internalClx = variant === 'link'
39
+ ? ' text-muted hover:text-foreground active:text-accent rounded-none'
40
+ : ' min-w-0'
41
+
42
+ if (currentAs && currentAs === el.href) {
43
+ internalClx += ' pointer-events-none'
44
+ if (variant === 'link') {
45
+ internalClx += ' text-accent'
46
+ }
47
+ }
48
+
49
+ if (!el.isAIMenu) {
50
+ return (
51
+ <AccordionItem key={index} value={el.title ? el.title : ""} className='!no-underline !border-0'>
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')}>
54
+ {el.title}
55
+ </div>
56
+ <ChevronDown className="w-4 h-4 mr-3" />
57
+ </AccordionTrigger>
58
+ <AccordionContent>
59
+ {el.childMenu && (
60
+ <div className="px-4">
61
+ {Object.entries(el.childMenu.reduce((acc, child) => {
62
+ const group = acc[child.groupName ? child.groupName : ""] || []
63
+ group.push(child)
64
+ acc[child.groupName ? child.groupName : ""] = group
65
+ return acc
66
+ }, {} as { [key: string]: ChildMenu[] })).map(([groupName, children]) => (
67
+ <div key={groupName}>
68
+ <div className="mt-4 mb-4 font-light text-muted-1">{groupName}</div>
69
+ {children.map((child, childIndex) => (
70
+ <div key={childIndex} className="m-2">
71
+ <div className="flex items-center py-1">
72
+ <span>
73
+ {child.icon && child.icon}
74
+ </span>
75
+ <Link
76
+ href={child.href}
77
+ className="text-muted-2 hover:underline ml-5 hover:text-primary"
78
+ target={child.newTab ? '_blank' : '_self'}
79
+ rel="noopener noreferrer"
80
+ >
81
+ {child.title}
82
+ </Link>
83
+ </div>
84
+ </div>
85
+ ))}
86
+ </div>
87
+ ))}
88
+ </div>
89
+ )}
90
+ </AccordionContent>
91
+ </AccordionItem>
92
+ )
93
+ }
94
+ })}
95
+ </Accordion>
96
+ </div>
97
+ <MobileAuthWidget className='text-2xl z-10' handleLogin={() => { setMenuState('login') }} />
98
+ </div>
99
+ ) : null
100
+ );
101
+
102
102
  export default MobileNav;
@@ -1,113 +1,113 @@
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
- Form,
18
- FormControl,
19
- FormField,
20
- FormItem,
21
- FormMessage,
22
- } from '@hanzo/ui/primitives'
23
-
24
- import type { SubmitServerAction } from '@hanzo/ui/types'
25
- import type { ContactInfo } from '../../types'
26
-
27
- const ContactFormSchema = z.object({
28
- email: z
29
- .string()
30
- .min(1, { message: "Email must be provided." })
31
- .email("Invalid email."),
32
- phone: z
33
- .string()
34
- .min(1, { message: "Telephone must be provided." })
35
- .refine(validator.isMobilePhone, { message: "Invalid format." })
36
- })
37
-
38
- type ContactFormSchemaType = z.infer<typeof ContactFormSchema>
39
-
40
- const ContactForm: React.FC<{
41
- onSubmit: (data: ContactFormSchemaType, enc: any) => void
42
- enclosure: any
43
- }> = ({
44
- onSubmit: _onSubmit,
45
- enclosure
46
- }) => {
47
-
48
- const form = useForm<ContactFormSchemaType>({
49
- resolver: zodResolver(ContactFormSchema),
50
- defaultValues: {
51
- email: '',
52
- phone: '',
53
- },
54
- })
55
-
56
- const [isPending, startTransition] = useTransition()
57
-
58
- const onSubmit: SubmitHandler<ContactFormSchemaType> = (data) => {
59
- // https://github.com/orgs/react-hook-form/discussions/10757#discussioncomment-6672403
60
- // @ts-ignore
61
- startTransition(async () => {
62
- await _onSubmit(data, enclosure)
63
- })
64
- }
65
-
66
- const MyFormItem: React.FC<{
67
- field: ControllerRenderProps<ContactFormSchemaType, 'email'> | ControllerRenderProps<ContactFormSchemaType, 'phone'>
68
- placeholder: string
69
- }> = ({
70
- field,
71
- placeholder
72
- }) => (
73
- <FormItem className="space-y-0" >
74
- <FormControl>
75
- <Input placeholder={placeholder} {...field} className="mt-0 text-foreground"/>
76
- </FormControl>
77
- <div className="flex flex-row justify-start items-stretch gap-2">
78
- <FormMessage />
79
- </div>
80
- </FormItem>
81
- )
82
-
83
- return (
84
- <Form {...form}>
85
- <form onSubmit={form.handleSubmit(onSubmit)} className="w-3/4">
86
- <div className='flex flex-col justify-start items-stretch mt-4'>
87
- <FormField
88
- control={form.control}
89
- name='email'
90
- render={({ field }) => ( <MyFormItem field={field} placeholder='email'/> )}
91
- />
92
- <FormField
93
- control={form.control}
94
- name='phone'
95
- // @ts-ignore
96
- render={({ field }) => ( <MyFormItem field={field} placeholder='phone'/> )}
97
- />
98
- <Button disabled={isPending} type='submit' className='bg-primary text-primary-fg hover:bg-primary-hover'>
99
- {isPending ? (<>
100
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
101
- Please wait
102
- </>
103
- ) : (
104
- <>Submit</>
105
- )}
106
- </Button>
107
- </div>
108
- </form>
109
- </Form>
110
- )
111
- }
112
-
113
- export default ContactForm
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
+ Form,
18
+ FormControl,
19
+ FormField,
20
+ FormItem,
21
+ FormMessage,
22
+ } from '@hanzo/ui/primitives'
23
+
24
+ import type { SubmitServerAction } from '@hanzo/ui/types'
25
+ import type { ContactInfo } from '../../types'
26
+
27
+ const ContactFormSchema = z.object({
28
+ email: z
29
+ .string()
30
+ .min(1, { message: "Email must be provided." })
31
+ .email("Invalid email."),
32
+ phone: z
33
+ .string()
34
+ .min(1, { message: "Telephone must be provided." })
35
+ .refine(validator.isMobilePhone, { message: "Invalid format." })
36
+ })
37
+
38
+ type ContactFormSchemaType = z.infer<typeof ContactFormSchema>
39
+
40
+ const ContactForm: React.FC<{
41
+ onSubmit: (data: ContactFormSchemaType, enc: any) => void
42
+ enclosure: any
43
+ }> = ({
44
+ onSubmit: _onSubmit,
45
+ enclosure
46
+ }) => {
47
+
48
+ const form = useForm<ContactFormSchemaType>({
49
+ resolver: zodResolver(ContactFormSchema),
50
+ defaultValues: {
51
+ email: '',
52
+ phone: '',
53
+ },
54
+ })
55
+
56
+ const [isPending, startTransition] = useTransition()
57
+
58
+ const onSubmit: SubmitHandler<ContactFormSchemaType> = (data) => {
59
+ // https://github.com/orgs/react-hook-form/discussions/10757#discussioncomment-6672403
60
+ // @ts-ignore
61
+ startTransition(async () => {
62
+ await _onSubmit(data, enclosure)
63
+ })
64
+ }
65
+
66
+ const MyFormItem: React.FC<{
67
+ field: ControllerRenderProps<ContactFormSchemaType, 'email'> | ControllerRenderProps<ContactFormSchemaType, 'phone'>
68
+ placeholder: string
69
+ }> = ({
70
+ field,
71
+ placeholder
72
+ }) => (
73
+ <FormItem className="space-y-0" >
74
+ <FormControl>
75
+ <Input placeholder={placeholder} {...field} className="mt-0 text-foreground"/>
76
+ </FormControl>
77
+ <div className="flex flex-row justify-start items-stretch gap-2">
78
+ <FormMessage />
79
+ </div>
80
+ </FormItem>
81
+ )
82
+
83
+ return (
84
+ <Form {...form}>
85
+ <form onSubmit={form.handleSubmit(onSubmit)} className="w-3/4">
86
+ <div className='flex flex-col justify-start items-stretch mt-4'>
87
+ <FormField
88
+ control={form.control}
89
+ name='email'
90
+ render={({ field }) => ( <MyFormItem field={field} placeholder='email'/> )}
91
+ />
92
+ <FormField
93
+ control={form.control}
94
+ name='phone'
95
+ // @ts-ignore
96
+ render={({ field }) => ( <MyFormItem field={field} placeholder='phone'/> )}
97
+ />
98
+ <Button disabled={isPending} type='submit' className='bg-primary text-primary-fg hover:bg-primary-hover'>
99
+ {isPending ? (<>
100
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
101
+ Please wait
102
+ </>
103
+ ) : (
104
+ <>Submit</>
105
+ )}
106
+ </Button>
107
+ </div>
108
+ </form>
109
+ </Form>
110
+ )
111
+ }
112
+
113
+ export default ContactForm
@@ -1,13 +1,13 @@
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
+ 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 +1,64 @@
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
+ '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 +1,21 @@
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 Ltd.&nbsp;<br className='md:hidden'/>&nbsp;All rights reserved.
17
- </div>
18
- )
19
- }
20
-
21
- export default Copyright
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 Ltd (Isle of Man) and Lux Industries Inc (Delaware, USA).&nbsp;<br className='md:hidden'/>&nbsp;All rights reserved.
17
+ </div>
18
+ )
19
+ }
20
+
21
+ export default Copyright