@better-auth-ui/solid 1.6.19

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 (270) hide show
  1. package/dist/components/auth/email/email-changed.d.ts +59 -0
  2. package/dist/components/auth/email/email-changed.js +264 -0
  3. package/dist/components/auth/email/email-styles.d.ts +48 -0
  4. package/dist/components/auth/email/email-styles.js +107 -0
  5. package/dist/components/auth/email/email-verification.d.ts +51 -0
  6. package/dist/components/auth/email/email-verification.js +212 -0
  7. package/dist/components/auth/email/index.d.ts +9 -0
  8. package/dist/components/auth/email/magic-link.d.ts +53 -0
  9. package/dist/components/auth/email/magic-link.js +213 -0
  10. package/dist/components/auth/email/new-device.d.ts +77 -0
  11. package/dist/components/auth/email/new-device.js +326 -0
  12. package/dist/components/auth/email/organization-invitation.d.ts +70 -0
  13. package/dist/components/auth/email/organization-invitation.js +260 -0
  14. package/dist/components/auth/email/otp-email.d.ts +49 -0
  15. package/dist/components/auth/email/otp-email.js +191 -0
  16. package/dist/components/auth/email/password-changed.d.ts +56 -0
  17. package/dist/components/auth/email/password-changed.js +236 -0
  18. package/dist/components/auth/email/reset-password.d.ts +51 -0
  19. package/dist/components/auth/email/reset-password.js +212 -0
  20. package/dist/email.d.ts +18 -0
  21. package/dist/email.js +10 -0
  22. package/dist/hooks/auth/use-authenticate.d.ts +3 -0
  23. package/dist/hooks/auth/use-authenticate.js +18 -0
  24. package/dist/hooks/auth/use-sign-out.d.ts +2 -0
  25. package/dist/hooks/auth/use-sign-out.js +17 -0
  26. package/dist/hooks/auth/use-user.d.ts +213 -0
  27. package/dist/hooks/auth/use-user.js +13 -0
  28. package/dist/hooks/use-auth-mutation.d.ts +6 -0
  29. package/dist/hooks/use-auth-mutation.js +11 -0
  30. package/dist/hooks/use-auth-query.d.ts +5 -0
  31. package/dist/hooks/use-auth-query.js +17 -0
  32. package/dist/index.d.ts +48 -0
  33. package/dist/index.js +68 -0
  34. package/dist/lib/auth-client.d.ts +26 -0
  35. package/dist/lib/auth-config.d.ts +12 -0
  36. package/dist/lib/auth-config.js +21 -0
  37. package/dist/lib/auth-plugin.d.ts +16 -0
  38. package/dist/lib/auth-provider.d.ts +12 -0
  39. package/dist/lib/auth-provider.js +36 -0
  40. package/dist/lib/auth-server.d.ts +16 -0
  41. package/dist/lib/auth-utils.d.ts +3 -0
  42. package/dist/lib/auth-utils.js +12 -0
  43. package/dist/lib/fetch-options-provider.d.ts +23 -0
  44. package/dist/lib/fetch-options-provider.js +29 -0
  45. package/dist/lib/mutation-invalidator.d.ts +11 -0
  46. package/dist/lib/mutation-invalidator.js +20 -0
  47. package/dist/lib/provider-icons.d.ts +8 -0
  48. package/dist/lib/provider-icons.js +5 -0
  49. package/dist/mutations/api-key/create-api-key-mutation.d.ts +71 -0
  50. package/dist/mutations/api-key/create-api-key-mutation.js +12 -0
  51. package/dist/mutations/api-key/delete-api-key-mutation.d.ts +23 -0
  52. package/dist/mutations/api-key/delete-api-key-mutation.js +12 -0
  53. package/dist/mutations/auth/request-password-reset-mutation.d.ts +11 -0
  54. package/dist/mutations/auth/request-password-reset-mutation.js +8 -0
  55. package/dist/mutations/auth/reset-password-mutation.d.ts +13 -0
  56. package/dist/mutations/auth/reset-password-mutation.js +8 -0
  57. package/dist/mutations/auth/send-verification-email-mutation.d.ts +11 -0
  58. package/dist/mutations/auth/send-verification-email-mutation.js +8 -0
  59. package/dist/mutations/auth/sign-in-email-mutation.d.ts +15 -0
  60. package/dist/mutations/auth/sign-in-email-mutation.js +8 -0
  61. package/dist/mutations/auth/sign-in-social-mutation.d.ts +53 -0
  62. package/dist/mutations/auth/sign-in-social-mutation.js +8 -0
  63. package/dist/mutations/auth/sign-out-mutation.d.ts +6 -0
  64. package/dist/mutations/auth/sign-out-mutation.js +8 -0
  65. package/dist/mutations/auth/sign-up-email-mutation.d.ts +17 -0
  66. package/dist/mutations/auth/sign-up-email-mutation.js +8 -0
  67. package/dist/mutations/auth-mutation-options.d.ts +10 -0
  68. package/dist/mutations/auth-mutation-options.js +19 -0
  69. package/dist/mutations/create-auth-mutation.d.ts +10 -0
  70. package/dist/mutations/create-auth-mutation.js +20 -0
  71. package/dist/mutations/magic-link/sign-in-magic-link-mutation.d.ts +19 -0
  72. package/dist/mutations/magic-link/sign-in-magic-link-mutation.js +8 -0
  73. package/dist/mutations/multi-session/revoke-multi-session-mutation.d.ts +19 -0
  74. package/dist/mutations/multi-session/revoke-multi-session-mutation.js +12 -0
  75. package/dist/mutations/multi-session/set-active-session-mutation.d.ts +19 -0
  76. package/dist/mutations/multi-session/set-active-session-mutation.js +13 -0
  77. package/dist/mutations/organization/accept-invitation-mutation.d.ts +18 -0
  78. package/dist/mutations/organization/accept-invitation-mutation.js +12 -0
  79. package/dist/mutations/organization/cancel-invitation-mutation.d.ts +18 -0
  80. package/dist/mutations/organization/cancel-invitation-mutation.js +12 -0
  81. package/dist/mutations/organization/check-slug-mutation.d.ts +18 -0
  82. package/dist/mutations/organization/check-slug-mutation.js +15 -0
  83. package/dist/mutations/organization/create-organization-mutation.d.ts +38 -0
  84. package/dist/mutations/organization/create-organization-mutation.js +12 -0
  85. package/dist/mutations/organization/delete-organization-mutation.d.ts +18 -0
  86. package/dist/mutations/organization/delete-organization-mutation.js +12 -0
  87. package/dist/mutations/organization/index.d.ts +13 -0
  88. package/dist/mutations/organization/index.js +13 -0
  89. package/dist/mutations/organization/invite-member-mutation.d.ts +30 -0
  90. package/dist/mutations/organization/invite-member-mutation.js +12 -0
  91. package/dist/mutations/organization/leave-organization-mutation.d.ts +18 -0
  92. package/dist/mutations/organization/leave-organization-mutation.js +12 -0
  93. package/dist/mutations/organization/metadata.d.ts +13 -0
  94. package/dist/mutations/organization/metadata.js +27 -0
  95. package/dist/mutations/organization/reject-invitation-mutation.d.ts +18 -0
  96. package/dist/mutations/organization/reject-invitation-mutation.js +12 -0
  97. package/dist/mutations/organization/remove-member-mutation.d.ts +22 -0
  98. package/dist/mutations/organization/remove-member-mutation.js +12 -0
  99. package/dist/mutations/organization/set-active-organization-mutation.d.ts +24 -0
  100. package/dist/mutations/organization/set-active-organization-mutation.js +35 -0
  101. package/dist/mutations/organization/update-member-role-mutation.d.ts +26 -0
  102. package/dist/mutations/organization/update-member-role-mutation.js +12 -0
  103. package/dist/mutations/organization/update-organization-mutation.d.ts +42 -0
  104. package/dist/mutations/organization/update-organization-mutation.js +12 -0
  105. package/dist/mutations/organization/utils.d.ts +8 -0
  106. package/dist/mutations/organization/utils.js +17 -0
  107. package/dist/mutations/passkey/add-passkey-mutation.d.ts +73 -0
  108. package/dist/mutations/passkey/add-passkey-mutation.js +12 -0
  109. package/dist/mutations/passkey/delete-passkey-mutation.d.ts +19 -0
  110. package/dist/mutations/passkey/delete-passkey-mutation.js +12 -0
  111. package/dist/mutations/passkey/sign-in-passkey-mutation.d.ts +50 -0
  112. package/dist/mutations/passkey/sign-in-passkey-mutation.js +9 -0
  113. package/dist/mutations/settings/change-email-mutation.d.ts +11 -0
  114. package/dist/mutations/settings/change-email-mutation.js +8 -0
  115. package/dist/mutations/settings/change-password-mutation.d.ts +13 -0
  116. package/dist/mutations/settings/change-password-mutation.js +8 -0
  117. package/dist/mutations/settings/delete-user-mutation.d.ts +13 -0
  118. package/dist/mutations/settings/delete-user-mutation.js +8 -0
  119. package/dist/mutations/settings/link-social-mutation.d.ts +35 -0
  120. package/dist/mutations/settings/link-social-mutation.js +8 -0
  121. package/dist/mutations/settings/revoke-session-mutation.d.ts +19 -0
  122. package/dist/mutations/settings/revoke-session-mutation.js +12 -0
  123. package/dist/mutations/settings/unlink-account-mutation.d.ts +23 -0
  124. package/dist/mutations/settings/unlink-account-mutation.js +12 -0
  125. package/dist/mutations/settings/update-user-mutation.d.ts +6 -0
  126. package/dist/mutations/settings/update-user-mutation.js +8 -0
  127. package/dist/mutations/use-session-scoped-mutation.d.ts +17 -0
  128. package/dist/mutations/use-session-scoped-mutation.js +17 -0
  129. package/dist/mutations/username/is-username-available-mutation.d.ts +9 -0
  130. package/dist/mutations/username/is-username-available-mutation.js +8 -0
  131. package/dist/mutations/username/sign-in-username-mutation.d.ts +15 -0
  132. package/dist/mutations/username/sign-in-username-mutation.js +9 -0
  133. package/dist/plugins/captcha-plugin.d.ts +29 -0
  134. package/dist/plugins/captcha-plugin.js +26 -0
  135. package/dist/plugins.d.ts +2 -0
  136. package/dist/plugins.js +2 -0
  137. package/dist/queries/api-key/list-api-keys-query.d.ts +44 -0
  138. package/dist/queries/api-key/list-api-keys-query.js +17 -0
  139. package/dist/queries/auth/session-query.d.ts +22 -0
  140. package/dist/queries/auth/session-query.js +32 -0
  141. package/dist/queries/auth-query-options.d.ts +14 -0
  142. package/dist/queries/auth-query-options.js +17 -0
  143. package/dist/queries/create-user-scoped-query.d.ts +25 -0
  144. package/dist/queries/create-user-scoped-query.js +29 -0
  145. package/dist/queries/multi-session/list-device-sessions-query.d.ts +23 -0
  146. package/dist/queries/multi-session/list-device-sessions-query.js +17 -0
  147. package/dist/queries/organization/active-organization-query.d.ts +37 -0
  148. package/dist/queries/organization/active-organization-query.js +26 -0
  149. package/dist/queries/organization/full-organization-query.d.ts +35 -0
  150. package/dist/queries/organization/full-organization-query.js +25 -0
  151. package/dist/queries/organization/has-permission-query.d.ts +23 -0
  152. package/dist/queries/organization/has-permission-query.js +31 -0
  153. package/dist/queries/organization/index.d.ts +7 -0
  154. package/dist/queries/organization/index.js +7 -0
  155. package/dist/queries/organization/list-invitations-query.d.ts +29 -0
  156. package/dist/queries/organization/list-invitations-query.js +29 -0
  157. package/dist/queries/organization/list-members-query.d.ts +53 -0
  158. package/dist/queries/organization/list-members-query.js +29 -0
  159. package/dist/queries/organization/list-organizations-query.d.ts +23 -0
  160. package/dist/queries/organization/list-organizations-query.js +25 -0
  161. package/dist/queries/organization/list-user-invitations-query.d.ts +29 -0
  162. package/dist/queries/organization/list-user-invitations-query.js +25 -0
  163. package/dist/queries/organization/plugin.d.ts +1 -0
  164. package/dist/queries/organization/plugin.js +8 -0
  165. package/dist/queries/organization/utils.d.ts +16 -0
  166. package/dist/queries/organization/utils.js +18 -0
  167. package/dist/queries/passkey/list-passkeys-query.d.ts +23 -0
  168. package/dist/queries/passkey/list-passkeys-query.js +17 -0
  169. package/dist/queries/settings/account-info-query.d.ts +35 -0
  170. package/dist/queries/settings/account-info-query.js +17 -0
  171. package/dist/queries/settings/list-accounts-query.d.ts +23 -0
  172. package/dist/queries/settings/list-accounts-query.js +17 -0
  173. package/dist/queries/settings/list-sessions-query.d.ts +24 -0
  174. package/dist/queries/settings/list-sessions-query.js +17 -0
  175. package/dist/server/queries/auth/session-query.d.ts +19 -0
  176. package/dist/server/queries/auth/session-query.js +13 -0
  177. package/dist/server.d.ts +7 -0
  178. package/dist/server.js +7 -0
  179. package/package.json +63 -0
  180. package/src/components/auth/email/email-changed.tsx +305 -0
  181. package/src/components/auth/email/email-styles.tsx +139 -0
  182. package/src/components/auth/email/email-verification.tsx +249 -0
  183. package/src/components/auth/email/index.ts +9 -0
  184. package/src/components/auth/email/magic-link.tsx +254 -0
  185. package/src/components/auth/email/new-device.tsx +347 -0
  186. package/src/components/auth/email/organization-invitation.tsx +322 -0
  187. package/src/components/auth/email/otp-email.tsx +239 -0
  188. package/src/components/auth/email/password-changed.tsx +279 -0
  189. package/src/components/auth/email/reset-password.tsx +250 -0
  190. package/src/email.ts +49 -0
  191. package/src/hooks/auth/use-authenticate.ts +30 -0
  192. package/src/hooks/auth/use-sign-out.ts +23 -0
  193. package/src/hooks/auth/use-user.ts +19 -0
  194. package/src/hooks/use-auth-mutation.ts +35 -0
  195. package/src/hooks/use-auth-query.ts +33 -0
  196. package/src/index.ts +48 -0
  197. package/src/lib/auth-client.ts +43 -0
  198. package/src/lib/auth-config.ts +46 -0
  199. package/src/lib/auth-plugin.ts +20 -0
  200. package/src/lib/auth-provider.tsx +60 -0
  201. package/src/lib/auth-server.ts +25 -0
  202. package/src/lib/auth-utils.ts +25 -0
  203. package/src/lib/fetch-options-provider.tsx +77 -0
  204. package/src/lib/mutation-invalidator.tsx +82 -0
  205. package/src/lib/provider-icons.ts +10 -0
  206. package/src/mutations/api-key/create-api-key-mutation.ts +40 -0
  207. package/src/mutations/api-key/delete-api-key-mutation.ts +40 -0
  208. package/src/mutations/auth/request-password-reset-mutation.ts +15 -0
  209. package/src/mutations/auth/reset-password-mutation.ts +16 -0
  210. package/src/mutations/auth/send-verification-email-mutation.ts +15 -0
  211. package/src/mutations/auth/sign-in-email-mutation.ts +17 -0
  212. package/src/mutations/auth/sign-in-social-mutation.ts +16 -0
  213. package/src/mutations/auth/sign-out-mutation.ts +13 -0
  214. package/src/mutations/auth/sign-up-email-mutation.ts +17 -0
  215. package/src/mutations/auth-mutation-options.ts +62 -0
  216. package/src/mutations/create-auth-mutation.ts +44 -0
  217. package/src/mutations/magic-link/sign-in-magic-link-mutation.ts +15 -0
  218. package/src/mutations/multi-session/revoke-multi-session-mutation.ts +40 -0
  219. package/src/mutations/multi-session/set-active-session-mutation.ts +43 -0
  220. package/src/mutations/organization/accept-invitation-mutation.ts +38 -0
  221. package/src/mutations/organization/cancel-invitation-mutation.ts +38 -0
  222. package/src/mutations/organization/check-slug-mutation.ts +36 -0
  223. package/src/mutations/organization/create-organization-mutation.ts +37 -0
  224. package/src/mutations/organization/delete-organization-mutation.ts +37 -0
  225. package/src/mutations/organization/index.ts +13 -0
  226. package/src/mutations/organization/invite-member-mutation.ts +38 -0
  227. package/src/mutations/organization/leave-organization-mutation.ts +37 -0
  228. package/src/mutations/organization/metadata.ts +103 -0
  229. package/src/mutations/organization/reject-invitation-mutation.ts +38 -0
  230. package/src/mutations/organization/remove-member-mutation.ts +38 -0
  231. package/src/mutations/organization/set-active-organization-mutation.ts +110 -0
  232. package/src/mutations/organization/update-member-role-mutation.ts +38 -0
  233. package/src/mutations/organization/update-organization-mutation.ts +37 -0
  234. package/src/mutations/organization/utils.ts +51 -0
  235. package/src/mutations/passkey/add-passkey-mutation.ts +40 -0
  236. package/src/mutations/passkey/delete-passkey-mutation.ts +40 -0
  237. package/src/mutations/passkey/sign-in-passkey-mutation.ts +17 -0
  238. package/src/mutations/settings/change-email-mutation.ts +17 -0
  239. package/src/mutations/settings/change-password-mutation.ts +16 -0
  240. package/src/mutations/settings/delete-user-mutation.ts +16 -0
  241. package/src/mutations/settings/link-social-mutation.ts +16 -0
  242. package/src/mutations/settings/revoke-session-mutation.ts +38 -0
  243. package/src/mutations/settings/unlink-account-mutation.ts +38 -0
  244. package/src/mutations/settings/update-user-mutation.ts +17 -0
  245. package/src/mutations/use-session-scoped-mutation.ts +64 -0
  246. package/src/mutations/username/is-username-available-mutation.ts +15 -0
  247. package/src/mutations/username/sign-in-username-mutation.ts +17 -0
  248. package/src/plugins/captcha-plugin.tsx +64 -0
  249. package/src/plugins.ts +2 -0
  250. package/src/queries/api-key/list-api-keys-query.ts +93 -0
  251. package/src/queries/auth/session-query.ts +81 -0
  252. package/src/queries/auth-query-options.ts +57 -0
  253. package/src/queries/create-user-scoped-query.ts +107 -0
  254. package/src/queries/multi-session/list-device-sessions-query.ts +107 -0
  255. package/src/queries/organization/active-organization-query.ts +127 -0
  256. package/src/queries/organization/full-organization-query.ts +111 -0
  257. package/src/queries/organization/has-permission-query.ts +121 -0
  258. package/src/queries/organization/index.ts +7 -0
  259. package/src/queries/organization/list-invitations-query.ts +124 -0
  260. package/src/queries/organization/list-members-query.ts +124 -0
  261. package/src/queries/organization/list-organizations-query.ts +113 -0
  262. package/src/queries/organization/list-user-invitations-query.ts +114 -0
  263. package/src/queries/organization/plugin.ts +11 -0
  264. package/src/queries/organization/utils.ts +88 -0
  265. package/src/queries/passkey/list-passkeys-query.ts +93 -0
  266. package/src/queries/settings/account-info-query.ts +94 -0
  267. package/src/queries/settings/list-accounts-query.ts +94 -0
  268. package/src/queries/settings/list-sessions-query.ts +96 -0
  269. package/src/server/queries/auth/session-query.ts +56 -0
  270. package/src/server.ts +7 -0
@@ -0,0 +1,239 @@
1
+ import {
2
+ Body,
3
+ Container,
4
+ Head,
5
+ Heading,
6
+ Hr,
7
+ Html,
8
+ Img,
9
+ Preview,
10
+ Section,
11
+ Tailwind,
12
+ Text
13
+ } from "@solidjs-email/main"
14
+ import type { JSX } from "solid-js"
15
+ import { Show } from "solid-js"
16
+ import {
17
+ type EmailClassNames,
18
+ type EmailColors,
19
+ EmailStyles
20
+ } from "./email-styles"
21
+
22
+ function cn(...classes: Array<string | false | null | undefined>) {
23
+ return classes.filter(Boolean).join(" ")
24
+ }
25
+
26
+ const otpEmailLocalization = {
27
+ YOUR_VERIFICATION_CODE_IS_CODE:
28
+ "Your verification code is {verificationCode}",
29
+ LOGO: "Logo",
30
+ VERIFY_YOUR_EMAIL: "Verify your email",
31
+ WE_NEED_TO_VERIFY_YOUR_EMAIL_ADDRESS:
32
+ "We need to verify your email address {email} before you can access your {appName} account. Enter the code below in your open browser window.",
33
+ THIS_CODE_EXPIRES_IN_MINUTES:
34
+ "This code expires in {expirationMinutes} minutes.",
35
+ EMAIL_SENT_BY: "Email sent by {appName}.",
36
+ IF_YOU_DIDNT_REQUEST_THIS_EMAIL:
37
+ "If you didn't request this email, you can safely ignore it. Someone else might have typed your email address by mistake.",
38
+ POWERED_BY_BETTER_AUTH: "Powered by {betterAuth}"
39
+ }
40
+
41
+ export type OtpEmailEmailLocalization = typeof otpEmailLocalization
42
+
43
+ export interface OtpEmailProps {
44
+ verificationCode: string
45
+ email?: string
46
+ appName?: string
47
+ expirationMinutes?: number
48
+ logoURL?: string | { light: string; dark: string }
49
+ classNames?: EmailClassNames
50
+ colors?: EmailColors
51
+ poweredBy?: boolean
52
+ darkMode?: boolean
53
+ head?: JSX.Element
54
+ localization?: Partial<OtpEmailEmailLocalization>
55
+ }
56
+
57
+ function cleanSentence(value: string) {
58
+ return value.replace(/\s{2,}/g, " ").replace(" .", ".")
59
+ }
60
+
61
+ export function OtpEmail(props: OtpEmailProps) {
62
+ const expirationMinutes = () => props.expirationMinutes ?? 10
63
+ const darkMode = () => props.darkMode ?? true
64
+ const localization = () => ({
65
+ ...OtpEmail.localization,
66
+ ...props.localization
67
+ })
68
+ const previewText = () =>
69
+ localization().YOUR_VERIFICATION_CODE_IS_CODE.replace(
70
+ "{verificationCode}",
71
+ props.verificationCode
72
+ )
73
+ const contentText = () =>
74
+ cleanSentence(
75
+ localization()
76
+ .WE_NEED_TO_VERIFY_YOUR_EMAIL_ADDRESS.replace(
77
+ "{email}",
78
+ props.email || ""
79
+ )
80
+ .replace("{appName}", props.appName || "")
81
+ )
82
+
83
+ return (
84
+ <Html>
85
+ <Head>
86
+ <meta content="light dark" name="color-scheme" />
87
+ <meta content="light dark" name="supported-color-schemes" />
88
+ <EmailStyles colors={props.colors} darkMode={darkMode()} />
89
+ {props.head}
90
+ </Head>
91
+
92
+ <Preview>{previewText()}</Preview>
93
+
94
+ <Tailwind>
95
+ <Body
96
+ class={cn("bg-background", props.classNames?.body)}
97
+ style={{ "font-family": "Arial, Helvetica, sans-serif" }}
98
+ >
99
+ <Container
100
+ class={cn(
101
+ "mx-auto my-auto max-w-xl px-2 py-10",
102
+ props.classNames?.container
103
+ )}
104
+ >
105
+ <Section
106
+ class={cn(
107
+ "rounded-none border border-border bg-card p-8 text-card-foreground",
108
+ props.classNames?.card
109
+ )}
110
+ >
111
+ {props.logoURL &&
112
+ (typeof props.logoURL === "string" ? (
113
+ <Img
114
+ alt={props.appName || localization().LOGO}
115
+ class={cn("mx-auto mb-8", props.classNames?.logo)}
116
+ height={48}
117
+ src={props.logoURL}
118
+ width={48}
119
+ />
120
+ ) : (
121
+ <>
122
+ <Img
123
+ alt={props.appName || localization().LOGO}
124
+ class={cn(
125
+ "logo-light mx-auto mb-8",
126
+ props.classNames?.logo
127
+ )}
128
+ height={48}
129
+ src={props.logoURL.light}
130
+ width={48}
131
+ />
132
+ <Img
133
+ alt={props.appName || localization().LOGO}
134
+ class={cn(
135
+ "logo-dark hidden mx-auto mb-8",
136
+ props.classNames?.logo
137
+ )}
138
+ height={48}
139
+ src={props.logoURL.dark}
140
+ width={48}
141
+ />
142
+ </>
143
+ ))}
144
+
145
+ <Heading
146
+ class={cn(
147
+ "mb-5 font-semibold text-2xl",
148
+ props.classNames?.title
149
+ )}
150
+ >
151
+ {localization().VERIFY_YOUR_EMAIL}
152
+ </Heading>
153
+
154
+ <Text
155
+ class={cn("font-normal text-sm", props.classNames?.content)}
156
+ >
157
+ {contentText()}
158
+ </Text>
159
+
160
+ <Section
161
+ class={cn(
162
+ "my-6 border border-border bg-muted p-6",
163
+ props.classNames?.codeBlock
164
+ )}
165
+ >
166
+ <Text
167
+ class={cn(
168
+ "m-0 text-center font-semibold text-4xl tracking-widest",
169
+ props.classNames?.title
170
+ )}
171
+ >
172
+ {props.verificationCode}
173
+ </Text>
174
+ </Section>
175
+
176
+ <Hr
177
+ class={cn(
178
+ "my-6 w-full border border-border border-solid",
179
+ props.classNames?.separator
180
+ )}
181
+ />
182
+
183
+ <Text
184
+ class={cn(
185
+ "mb-3 text-muted-foreground text-xs",
186
+ props.classNames?.description
187
+ )}
188
+ >
189
+ {localization().THIS_CODE_EXPIRES_IN_MINUTES.replace(
190
+ "{expirationMinutes}",
191
+ expirationMinutes().toString()
192
+ )}
193
+ <Show when={props.appName}>
194
+ {(appName) =>
195
+ ` ${localization().EMAIL_SENT_BY.replace("{appName}", appName())}`
196
+ }
197
+ </Show>
198
+ </Text>
199
+
200
+ <Text
201
+ class={cn(
202
+ "mt-3 text-muted-foreground text-xs",
203
+ props.classNames?.description
204
+ )}
205
+ >
206
+ {localization().IF_YOU_DIDNT_REQUEST_THIS_EMAIL}
207
+ </Text>
208
+
209
+ <Show when={props.poweredBy}>
210
+ <Text
211
+ class={cn(
212
+ "mt-4 mb-0 text-center text-[11px] text-muted-foreground",
213
+ props.classNames?.poweredBy
214
+ )}
215
+ >
216
+ {localization().POWERED_BY_BETTER_AUTH.replace(
217
+ "{betterAuth}",
218
+ "better-auth"
219
+ )}
220
+ </Text>
221
+ </Show>
222
+ </Section>
223
+ </Container>
224
+ </Body>
225
+ </Tailwind>
226
+ </Html>
227
+ )
228
+ }
229
+
230
+ OtpEmail.localization = otpEmailLocalization
231
+
232
+ OtpEmail.PreviewProps = {
233
+ verificationCode: "069420",
234
+ email: "m@example.com",
235
+ appName: "Better Auth",
236
+ darkMode: true
237
+ } satisfies OtpEmailProps
238
+
239
+ export default OtpEmail
@@ -0,0 +1,279 @@
1
+ import {
2
+ Body,
3
+ Button,
4
+ Container,
5
+ Head,
6
+ Heading,
7
+ Hr,
8
+ Html,
9
+ Img,
10
+ Preview,
11
+ Section,
12
+ Tailwind,
13
+ Text
14
+ } from "@solidjs-email/main"
15
+ import type { JSX } from "solid-js"
16
+ import { Show } from "solid-js"
17
+ import {
18
+ type EmailClassNames,
19
+ type EmailColors,
20
+ EmailStyles
21
+ } from "./email-styles"
22
+
23
+ function cn(...classes: Array<string | false | null | undefined>) {
24
+ return classes.filter(Boolean).join(" ")
25
+ }
26
+
27
+ const passwordChangedEmailLocalization = {
28
+ YOUR_PASSWORD_HAS_BEEN_CHANGED: "Your password has been changed",
29
+ LOGO: "Logo",
30
+ PASSWORD_CHANGED_SUCCESSFULLY: "Password changed successfully",
31
+ PASSWORD_FOR_YOUR_ACCOUNT_CHANGED:
32
+ "The password for your {appName} account {userEmail} has been changed successfully.",
33
+ CHANGED_AT: "Changed at",
34
+ IF_YOU_MADE_THIS_CHANGE:
35
+ "If you made this change, you can safely ignore this email. Your account is secure.",
36
+ I_DIDNT_MAKE_THIS_CHANGE: "I didn't make this change",
37
+ EMAIL_SENT_BY: "Email sent by {appName}.",
38
+ IF_YOU_DIDNT_AUTHORIZE_THIS_CHANGE:
39
+ "If you didn't authorize this change, please contact support immediately {supportEmail} to secure your account.",
40
+ POWERED_BY_BETTER_AUTH: "Powered by {betterAuth}"
41
+ }
42
+
43
+ export type PasswordChangedEmailLocalization =
44
+ typeof passwordChangedEmailLocalization
45
+
46
+ export interface PasswordChangedEmailProps {
47
+ email?: string
48
+ timestamp?: string
49
+ secureAccountURL?: string
50
+ appName?: string
51
+ supportEmail?: string
52
+ logoURL?: string | { light: string; dark: string }
53
+ classNames?: EmailClassNames
54
+ colors?: EmailColors
55
+ poweredBy?: boolean
56
+ darkMode?: boolean
57
+ head?: JSX.Element
58
+ localization?: Partial<PasswordChangedEmailLocalization>
59
+ }
60
+
61
+ function cleanSentence(value: string) {
62
+ return value.replace(/\s{2,}/g, " ").replace(" .", ".")
63
+ }
64
+
65
+ export function PasswordChangedEmail(props: PasswordChangedEmailProps) {
66
+ const darkMode = () => props.darkMode ?? true
67
+ const localization = () => ({
68
+ ...PasswordChangedEmail.localization,
69
+ ...props.localization
70
+ })
71
+ const accountText = () =>
72
+ cleanSentence(
73
+ localization()
74
+ .PASSWORD_FOR_YOUR_ACCOUNT_CHANGED.replace(
75
+ "{appName}",
76
+ props.appName || ""
77
+ )
78
+ .replace("{userEmail}", props.email || "")
79
+ )
80
+ const supportText = () =>
81
+ cleanSentence(
82
+ localization().IF_YOU_DIDNT_AUTHORIZE_THIS_CHANGE.replace(
83
+ "{supportEmail}",
84
+ props.supportEmail || ""
85
+ )
86
+ )
87
+
88
+ return (
89
+ <Html>
90
+ <Head>
91
+ <meta content="light dark" name="color-scheme" />
92
+ <meta content="light dark" name="supported-color-schemes" />
93
+ <EmailStyles colors={props.colors} darkMode={darkMode()} />
94
+ {props.head}
95
+ </Head>
96
+
97
+ <Preview>{localization().YOUR_PASSWORD_HAS_BEEN_CHANGED}</Preview>
98
+
99
+ <Tailwind>
100
+ <Body
101
+ class={cn("bg-background", props.classNames?.body)}
102
+ style={{ "font-family": "Arial, Helvetica, sans-serif" }}
103
+ >
104
+ <Container
105
+ class={cn(
106
+ "mx-auto my-auto max-w-xl px-2 py-10",
107
+ props.classNames?.container
108
+ )}
109
+ >
110
+ <Section
111
+ class={cn(
112
+ "rounded-none border border-border bg-card p-8 text-card-foreground",
113
+ props.classNames?.card
114
+ )}
115
+ >
116
+ {props.logoURL &&
117
+ (typeof props.logoURL === "string" ? (
118
+ <Img
119
+ alt={props.appName || localization().LOGO}
120
+ class={cn("mx-auto mb-8", props.classNames?.logo)}
121
+ height={48}
122
+ src={props.logoURL}
123
+ width={48}
124
+ />
125
+ ) : (
126
+ <>
127
+ <Img
128
+ alt={props.appName || localization().LOGO}
129
+ class={cn(
130
+ "logo-light mx-auto mb-8",
131
+ props.classNames?.logo
132
+ )}
133
+ height={48}
134
+ src={props.logoURL.light}
135
+ width={48}
136
+ />
137
+ <Img
138
+ alt={props.appName || localization().LOGO}
139
+ class={cn(
140
+ "logo-dark hidden mx-auto mb-8",
141
+ props.classNames?.logo
142
+ )}
143
+ height={48}
144
+ src={props.logoURL.dark}
145
+ width={48}
146
+ />
147
+ </>
148
+ ))}
149
+
150
+ <Heading
151
+ class={cn(
152
+ "m-0 mb-5 font-semibold text-2xl",
153
+ props.classNames?.title
154
+ )}
155
+ >
156
+ {localization().PASSWORD_CHANGED_SUCCESSFULLY}
157
+ </Heading>
158
+
159
+ <Text
160
+ class={cn("font-normal text-sm", props.classNames?.content)}
161
+ >
162
+ {accountText()}
163
+ </Text>
164
+
165
+ <Show when={props.timestamp}>
166
+ {(timestamp) => (
167
+ <Section
168
+ class={cn(
169
+ "my-6 border border-border bg-muted p-4",
170
+ props.classNames?.codeBlock
171
+ )}
172
+ >
173
+ <Text
174
+ class={cn(
175
+ "m-0 mb-2 text-muted-foreground text-xs",
176
+ props.classNames?.description
177
+ )}
178
+ >
179
+ {localization().CHANGED_AT}:
180
+ </Text>
181
+ <Text
182
+ class={cn(
183
+ "m-0 font-semibold text-sm",
184
+ props.classNames?.content
185
+ )}
186
+ >
187
+ {timestamp()}
188
+ </Text>
189
+ </Section>
190
+ )}
191
+ </Show>
192
+
193
+ <Text
194
+ class={cn("font-normal text-sm", props.classNames?.content)}
195
+ >
196
+ {localization().IF_YOU_MADE_THIS_CHANGE}
197
+ </Text>
198
+
199
+ <Show when={props.secureAccountURL}>
200
+ {(secureAccountURL) => (
201
+ <Section class="mt-6">
202
+ <Button
203
+ class={cn(
204
+ "inline-block whitespace-nowrap rounded-none bg-primary px-6 py-2.5 font-medium text-primary-foreground text-sm no-underline",
205
+ props.classNames?.button
206
+ )}
207
+ href={secureAccountURL()}
208
+ >
209
+ {localization().I_DIDNT_MAKE_THIS_CHANGE}
210
+ </Button>
211
+ </Section>
212
+ )}
213
+ </Show>
214
+
215
+ <Hr
216
+ class={cn(
217
+ "my-6 w-full border border-border border-solid",
218
+ props.classNames?.separator
219
+ )}
220
+ />
221
+
222
+ <Show when={props.appName}>
223
+ {(appName) => (
224
+ <Text
225
+ class={cn(
226
+ "mb-3 text-muted-foreground text-xs",
227
+ props.classNames?.description
228
+ )}
229
+ >
230
+ {localization().EMAIL_SENT_BY.replace(
231
+ "{appName}",
232
+ appName()
233
+ )}
234
+ </Text>
235
+ )}
236
+ </Show>
237
+
238
+ <Text
239
+ class={cn(
240
+ "mt-3 text-muted-foreground text-xs",
241
+ props.classNames?.description
242
+ )}
243
+ >
244
+ {supportText()}
245
+ </Text>
246
+
247
+ <Show when={props.poweredBy}>
248
+ <Text
249
+ class={cn(
250
+ "mt-4 mb-0 text-center text-[11px] text-muted-foreground",
251
+ props.classNames?.poweredBy
252
+ )}
253
+ >
254
+ {localization().POWERED_BY_BETTER_AUTH.replace(
255
+ "{betterAuth}",
256
+ "better-auth"
257
+ )}
258
+ </Text>
259
+ </Show>
260
+ </Section>
261
+ </Container>
262
+ </Body>
263
+ </Tailwind>
264
+ </Html>
265
+ )
266
+ }
267
+
268
+ PasswordChangedEmail.localization = passwordChangedEmailLocalization
269
+
270
+ PasswordChangedEmail.PreviewProps = {
271
+ email: "m@example.com",
272
+ timestamp: "February 10, 2025 at 4:20 PM UTC",
273
+ secureAccountURL: "https://better-auth-ui.com/settings/security",
274
+ appName: "Better Auth",
275
+ supportEmail: "support@example.com",
276
+ darkMode: true
277
+ } satisfies PasswordChangedEmailProps
278
+
279
+ export default PasswordChangedEmail