@erikey/react 0.4.26 → 0.4.28

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 (145) hide show
  1. package/dist/index.mjs +1 -1
  2. package/dist/index.mjs.map +1 -1
  3. package/package.json +2 -1
  4. package/src/__tests__/auth-client.test.ts +105 -0
  5. package/src/__tests__/security/localStorage-encryption.test.ts +171 -0
  6. package/src/auth-client.ts +158 -0
  7. package/src/dashboard-client.ts +60 -0
  8. package/src/index.ts +88 -0
  9. package/src/kv-client.ts +316 -0
  10. package/src/lib/cross-origin-auth.ts +99 -0
  11. package/src/stubs/captcha.ts +24 -0
  12. package/src/stubs/hashes.ts +16 -0
  13. package/src/stubs/index.ts +17 -0
  14. package/src/stubs/passkey.ts +12 -0
  15. package/src/stubs/qr-code.ts +10 -0
  16. package/src/stubs/query.ts +16 -0
  17. package/src/stubs/realtime.ts +17 -0
  18. package/src/stubs/use-sync-external-store.ts +12 -0
  19. package/src/styles.css +141 -0
  20. package/src/types.ts +14 -0
  21. package/src/ui/components/auth/auth-callback.tsx +36 -0
  22. package/src/ui/components/auth/auth-form.tsx +310 -0
  23. package/src/ui/components/auth/auth-view.tsx +435 -0
  24. package/src/ui/components/auth/email-otp-button.tsx +53 -0
  25. package/src/ui/components/auth/forms/email-otp-form.tsx +312 -0
  26. package/src/ui/components/auth/forms/email-verification-form.tsx +271 -0
  27. package/src/ui/components/auth/forms/forgot-password-form.tsx +173 -0
  28. package/src/ui/components/auth/forms/magic-link-form.tsx +196 -0
  29. package/src/ui/components/auth/forms/recover-account-form.tsx +143 -0
  30. package/src/ui/components/auth/forms/reset-password-form.tsx +220 -0
  31. package/src/ui/components/auth/forms/sign-in-form.tsx +323 -0
  32. package/src/ui/components/auth/forms/sign-up-form.tsx +820 -0
  33. package/src/ui/components/auth/forms/two-factor-form.tsx +381 -0
  34. package/src/ui/components/auth/magic-link-button.tsx +54 -0
  35. package/src/ui/components/auth/one-tap.tsx +53 -0
  36. package/src/ui/components/auth/otp-input-group.tsx +65 -0
  37. package/src/ui/components/auth/passkey-button.tsx +91 -0
  38. package/src/ui/components/auth/provider-button.tsx +155 -0
  39. package/src/ui/components/auth/sign-out.tsx +25 -0
  40. package/src/ui/components/auth/wallet-button.tsx +192 -0
  41. package/src/ui/components/auth-loading.tsx +21 -0
  42. package/src/ui/components/captcha/captcha.tsx +91 -0
  43. package/src/ui/components/captcha/recaptcha-badge.tsx +61 -0
  44. package/src/ui/components/captcha/recaptcha-v2.tsx +58 -0
  45. package/src/ui/components/captcha/recaptcha-v3.tsx +73 -0
  46. package/src/ui/components/email/email-template.tsx +216 -0
  47. package/src/ui/components/form-error.tsx +27 -0
  48. package/src/ui/components/password-input.tsx +56 -0
  49. package/src/ui/components/provider-icons.tsx +404 -0
  50. package/src/ui/components/redirect-to-sign-in.tsx +16 -0
  51. package/src/ui/components/redirect-to-sign-up.tsx +16 -0
  52. package/src/ui/components/signed-in.tsx +20 -0
  53. package/src/ui/components/signed-out.tsx +20 -0
  54. package/src/ui/components/ui/alert.tsx +66 -0
  55. package/src/ui/components/ui/button.tsx +70 -0
  56. package/src/ui/components/ui/card.tsx +92 -0
  57. package/src/ui/components/ui/checkbox.tsx +66 -0
  58. package/src/ui/components/ui/field.tsx +248 -0
  59. package/src/ui/components/ui/form.tsx +165 -0
  60. package/src/ui/components/ui/input-otp.tsx +77 -0
  61. package/src/ui/components/ui/input.tsx +21 -0
  62. package/src/ui/components/ui/label.tsx +23 -0
  63. package/src/ui/components/ui/separator.tsx +34 -0
  64. package/src/ui/components/ui/skeleton.tsx +13 -0
  65. package/src/ui/components/ui/textarea.tsx +18 -0
  66. package/src/ui/components/user-avatar.tsx +151 -0
  67. package/src/ui/hooks/use-auth-data.ts +193 -0
  68. package/src/ui/hooks/use-authenticate.ts +64 -0
  69. package/src/ui/hooks/use-captcha.tsx +151 -0
  70. package/src/ui/hooks/use-hydrated.ts +13 -0
  71. package/src/ui/hooks/use-lang.ts +32 -0
  72. package/src/ui/hooks/use-success-transition.ts +41 -0
  73. package/src/ui/hooks/use-theme.ts +39 -0
  74. package/src/ui/index.ts +46 -0
  75. package/src/ui/instantdb.ts +1 -0
  76. package/src/ui/lib/auth-data-cache.ts +90 -0
  77. package/src/ui/lib/auth-ui-provider.tsx +769 -0
  78. package/src/ui/lib/gravatar-utils.ts +58 -0
  79. package/src/ui/lib/image-utils.ts +55 -0
  80. package/src/ui/lib/instantdb/model-names.ts +24 -0
  81. package/src/ui/lib/instantdb/use-instant-options.ts +98 -0
  82. package/src/ui/lib/instantdb/use-list-accounts.ts +38 -0
  83. package/src/ui/lib/instantdb/use-list-sessions.ts +53 -0
  84. package/src/ui/lib/instantdb/use-session.ts +55 -0
  85. package/src/ui/lib/social-providers.ts +150 -0
  86. package/src/ui/lib/tanstack/auth-ui-provider-tanstack.tsx +49 -0
  87. package/src/ui/lib/tanstack/use-tanstack-options.ts +112 -0
  88. package/src/ui/lib/triplit/model-names.ts +24 -0
  89. package/src/ui/lib/triplit/use-conditional-query.ts +82 -0
  90. package/src/ui/lib/triplit/use-list-accounts.ts +31 -0
  91. package/src/ui/lib/triplit/use-list-sessions.ts +33 -0
  92. package/src/ui/lib/triplit/use-session.ts +42 -0
  93. package/src/ui/lib/triplit/use-triplit-hooks.ts +68 -0
  94. package/src/ui/lib/triplit/use-triplit-token.ts +44 -0
  95. package/src/ui/lib/utils.ts +119 -0
  96. package/src/ui/lib/view-paths.ts +61 -0
  97. package/src/ui/lib/wallet.ts +129 -0
  98. package/src/ui/localization/admin-error-codes.ts +20 -0
  99. package/src/ui/localization/anonymous-error-codes.ts +6 -0
  100. package/src/ui/localization/api-key-error-codes.ts +32 -0
  101. package/src/ui/localization/auth-localization.ts +865 -0
  102. package/src/ui/localization/base-error-codes.ts +27 -0
  103. package/src/ui/localization/captcha-error-codes.ts +17 -0
  104. package/src/ui/localization/email-otp-error-codes.ts +7 -0
  105. package/src/ui/localization/generic-oauth-error-codes.ts +3 -0
  106. package/src/ui/localization/haveibeenpwned-error-codes.ts +4 -0
  107. package/src/ui/localization/multi-session-error-codes.ts +3 -0
  108. package/src/ui/localization/organization-error-codes.ts +57 -0
  109. package/src/ui/localization/passkey-error-codes.ts +10 -0
  110. package/src/ui/localization/phone-number-error-codes.ts +10 -0
  111. package/src/ui/localization/stripe-localization.ts +12 -0
  112. package/src/ui/localization/team-error-codes.ts +12 -0
  113. package/src/ui/localization/two-factor-error-codes.ts +12 -0
  114. package/src/ui/localization/username-error-codes.ts +9 -0
  115. package/src/ui/server.ts +4 -0
  116. package/src/ui/style.css +146 -0
  117. package/src/ui/tanstack.ts +1 -0
  118. package/src/ui/triplit.ts +1 -0
  119. package/src/ui/types/account-options.ts +35 -0
  120. package/src/ui/types/additional-fields.ts +21 -0
  121. package/src/ui/types/any-auth-client.ts +6 -0
  122. package/src/ui/types/api-key.ts +9 -0
  123. package/src/ui/types/auth-client.ts +41 -0
  124. package/src/ui/types/auth-hooks.ts +81 -0
  125. package/src/ui/types/auth-mutators.ts +21 -0
  126. package/src/ui/types/avatar-options.ts +29 -0
  127. package/src/ui/types/captcha-options.ts +32 -0
  128. package/src/ui/types/captcha-provider.ts +7 -0
  129. package/src/ui/types/credentials-options.ts +38 -0
  130. package/src/ui/types/delete-user-options.ts +7 -0
  131. package/src/ui/types/email-verification-options.ts +7 -0
  132. package/src/ui/types/fetch-error.ts +6 -0
  133. package/src/ui/types/generic-oauth-options.ts +16 -0
  134. package/src/ui/types/gravatar-options.ts +21 -0
  135. package/src/ui/types/image.ts +7 -0
  136. package/src/ui/types/invitation.ts +10 -0
  137. package/src/ui/types/link.ts +7 -0
  138. package/src/ui/types/organization-options.ts +106 -0
  139. package/src/ui/types/password-validation.ts +16 -0
  140. package/src/ui/types/profile.ts +15 -0
  141. package/src/ui/types/refetch.ts +1 -0
  142. package/src/ui/types/render-toast.ts +9 -0
  143. package/src/ui/types/sign-up-options.ts +7 -0
  144. package/src/ui/types/social-options.ts +16 -0
  145. package/src/ui/types/team-options.ts +47 -0
@@ -0,0 +1,216 @@
1
+ import {
2
+ Body,
3
+ Button,
4
+ Container,
5
+ Head,
6
+ Heading,
7
+ Hr,
8
+ Html,
9
+ Img,
10
+ Link,
11
+ Preview,
12
+ Section,
13
+ Tailwind,
14
+ Text
15
+ } from "@react-email/components"
16
+ import type { ReactNode } from "react"
17
+
18
+ import { cn } from "../../lib/utils"
19
+
20
+ export interface EmailTemplateClassNames {
21
+ body?: string
22
+ button?: string
23
+ container?: string
24
+ image?: string
25
+ content?: string
26
+ footer?: string
27
+ heading?: string
28
+ hr?: string
29
+ link?: string
30
+ }
31
+
32
+ export interface EmailTemplateProps {
33
+ classNames?: EmailTemplateClassNames
34
+ action?: string
35
+ /** @default process.env.BASE_URL || process.env.NEXT_PUBLIC_BASE_URL */
36
+ baseUrl?: string
37
+ content: ReactNode
38
+ heading: ReactNode
39
+ /** @default `${baseUrl}/apple-touch-icon.png` */
40
+ imageUrl?: string
41
+ preview?: string
42
+ /** @default process.env.SITE_NAME || process.env.NEXT_PUBLIC_SITE_NAME */
43
+ siteName?: string
44
+ url?: string
45
+ /** @default "vercel" */
46
+ variant?: "vercel"
47
+ }
48
+
49
+ export const EmailTemplate = ({
50
+ classNames,
51
+ action,
52
+ baseUrl,
53
+ content,
54
+ heading,
55
+ imageUrl,
56
+ preview,
57
+ siteName,
58
+ variant = "vercel",
59
+ url
60
+ }: EmailTemplateProps) => {
61
+ baseUrl =
62
+ baseUrl || process.env.BASE_URL || process.env.NEXT_PUBLIC_BASE_URL
63
+ imageUrl = imageUrl || `${baseUrl}/apple-touch-icon.png`
64
+ siteName =
65
+ siteName || process.env.SITE_NAME || process.env.NEXT_PUBLIC_SITE_NAME
66
+ preview = preview || (typeof heading === "string" ? heading : undefined)
67
+
68
+ return (
69
+ <Html>
70
+ <Head>
71
+ <meta name="x-apple-disable-message-reformatting" />
72
+ <meta content="light dark" name="color-scheme" />
73
+ <meta content="light dark" name="supported-color-schemes" />
74
+
75
+ <style type="text/css">
76
+ {`
77
+ :root {
78
+ color-scheme: light dark;
79
+ supported-color-schemes: light dark;
80
+ }
81
+ `}
82
+ </style>
83
+
84
+ <style type="text/css">
85
+ {`
86
+ html, body {
87
+ background-color: #ffffff;
88
+ color: #000000;
89
+ }
90
+
91
+ a {
92
+ color: #000000;
93
+ }
94
+
95
+ .border-color {
96
+ border-color: #eaeaea;
97
+ }
98
+
99
+ .action-button {
100
+ background-color: #000000 !important;
101
+ color: #ffffff !important;
102
+ }
103
+
104
+ @media (prefers-color-scheme: dark) {
105
+ html, body {
106
+ background-color: #000000 !important;
107
+ color: #ffffff !important;
108
+ }
109
+
110
+ a {
111
+ color: #ffffff;
112
+ }
113
+
114
+ .border-color {
115
+ border-color: #333333 !important;
116
+ }
117
+
118
+ .action-button {
119
+ background-color: rgb(38, 38, 38) !important;
120
+ color: #ffffff !important;
121
+ }
122
+ }
123
+ `}
124
+ </style>
125
+ </Head>
126
+
127
+ {preview && <Preview>{preview}</Preview>}
128
+
129
+ <Tailwind>
130
+ <Body
131
+ className={cn(
132
+ "mx-auto my-auto px-2 font-sans",
133
+ classNames?.body
134
+ )}
135
+ >
136
+ <Container className="mx-auto my-[40px] max-w-[465px] rounded border border-color border-solid p-[20px]">
137
+ <Section className="mt-[32px]">
138
+ <Img
139
+ alt={siteName}
140
+ className={cn(
141
+ "mx-auto my-0 rounded-full",
142
+ classNames?.image
143
+ )}
144
+ height="40"
145
+ src={imageUrl}
146
+ width="40"
147
+ />
148
+ </Section>
149
+
150
+ <Heading
151
+ className={cn(
152
+ "mx-0 my-[30px] p-0 text-center font-bold text-[24px]",
153
+ classNames?.heading
154
+ )}
155
+ >
156
+ {heading}
157
+ </Heading>
158
+
159
+ <Text
160
+ className={cn(
161
+ "text-[14px] leading-[24px]",
162
+ classNames?.content
163
+ )}
164
+ >
165
+ {content}
166
+ </Text>
167
+
168
+ {action && url && (
169
+ <Section className="mt-[32px] mb-[32px] text-center">
170
+ <Button
171
+ className={cn(
172
+ "action-button rounded px-5 py-3 text-center font-semibold text-[12px] no-underline",
173
+ classNames?.button
174
+ )}
175
+ href={url}
176
+ >
177
+ {action}
178
+ </Button>
179
+ </Section>
180
+ )}
181
+
182
+ <Hr
183
+ className={cn(
184
+ "mx-0 my-[26px] w-full border border-color border-solid",
185
+ classNames?.hr
186
+ )}
187
+ />
188
+
189
+ <Text
190
+ className={cn(
191
+ "text-[#666666] text-[12px] leading-[24px]",
192
+ classNames?.footer
193
+ )}
194
+ >
195
+ {siteName && <>{siteName} </>}
196
+
197
+ {baseUrl && (
198
+ <Link
199
+ className={cn(
200
+ "no-underline",
201
+ classNames?.link
202
+ )}
203
+ href={baseUrl}
204
+ >
205
+ {baseUrl
206
+ ?.replace("https://", "")
207
+ .replace("http://", "")}
208
+ </Link>
209
+ )}
210
+ </Text>
211
+ </Container>
212
+ </Body>
213
+ </Tailwind>
214
+ </Html>
215
+ )
216
+ }
@@ -0,0 +1,27 @@
1
+ "use client"
2
+
3
+ import { AlertCircle } from "lucide-react"
4
+ import { useFormState } from "react-hook-form"
5
+
6
+ import { cn } from "../lib/utils"
7
+ import type { AuthFormClassNames } from "./auth/auth-form"
8
+ import { Alert, AlertDescription, AlertTitle } from "./ui/alert"
9
+
10
+ export interface FormErrorProps {
11
+ title?: string
12
+ classNames?: AuthFormClassNames
13
+ }
14
+
15
+ export function FormError({ title, classNames }: FormErrorProps) {
16
+ const { errors } = useFormState()
17
+
18
+ if (!errors.root?.message) return null
19
+
20
+ return (
21
+ <Alert variant="destructive" className={cn(classNames?.error)}>
22
+ <AlertCircle className="self-center" />
23
+ <AlertTitle>{title || "Error"}</AlertTitle>
24
+ <AlertDescription>{errors.root.message}</AlertDescription>
25
+ </Alert>
26
+ )
27
+ }
@@ -0,0 +1,56 @@
1
+ "use client"
2
+
3
+ import { EyeIcon, EyeOffIcon } from "lucide-react"
4
+ import { type ComponentProps, useState } from "react"
5
+
6
+ import { cn } from "../lib/utils"
7
+ import { Button } from "./ui/button"
8
+ import { Input } from "./ui/input"
9
+
10
+ export function PasswordInput({
11
+ className,
12
+ enableToggle,
13
+ onChange,
14
+ ...props
15
+ }: ComponentProps<typeof Input> & { enableToggle?: boolean }) {
16
+ const [disabled, setDisabled] = useState(true)
17
+ const [isVisible, setIsVisible] = useState(false)
18
+
19
+ return (
20
+ <div className="relative">
21
+ <Input
22
+ className={cn(enableToggle && "pr-10", className)}
23
+ {...props}
24
+ type={isVisible && enableToggle ? "text" : "password"}
25
+ onChange={(event) => {
26
+ setDisabled(!event.target.value)
27
+ onChange?.(event)
28
+ }}
29
+ />
30
+
31
+ {enableToggle && (
32
+ <>
33
+ <Button
34
+ className="!bg-transparent absolute top-0 right-0"
35
+ disabled={disabled}
36
+ size="icon"
37
+ type="button"
38
+ variant="ghost"
39
+ onClick={() => setIsVisible(!isVisible)}
40
+ >
41
+ {isVisible ? <EyeIcon /> : <EyeOffIcon />}
42
+ </Button>
43
+
44
+ <style>{`
45
+ .hide-password-toggle::-ms-reveal,
46
+ .hide-password-toggle::-ms-clear {
47
+ visibility: hidden;
48
+ pointer-events: none;
49
+ display: none;
50
+ }
51
+ `}</style>
52
+ </>
53
+ )}
54
+ </div>
55
+ )
56
+ }