@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,27 @@
1
+ export const BASE_ERROR_CODES = {
2
+ USER_NOT_FOUND: "User not found",
3
+ FAILED_TO_CREATE_USER: "Failed to create user",
4
+ FAILED_TO_CREATE_SESSION: "Failed to create session",
5
+ FAILED_TO_UPDATE_USER: "Failed to update user",
6
+ FAILED_TO_GET_SESSION: "Failed to get session",
7
+ INVALID_PASSWORD: "Invalid password",
8
+ INVALID_EMAIL: "Invalid email",
9
+ INVALID_EMAIL_OR_PASSWORD: "Invalid email or password",
10
+ SOCIAL_ACCOUNT_ALREADY_LINKED: "Social account already linked",
11
+ PROVIDER_NOT_FOUND: "Provider not found",
12
+ INVALID_TOKEN: "Invalid token",
13
+ ID_TOKEN_NOT_SUPPORTED: "id_token not supported",
14
+ FAILED_TO_GET_USER_INFO: "Failed to get user info",
15
+ USER_EMAIL_NOT_FOUND: "User email not found",
16
+ EMAIL_NOT_VERIFIED: "Email not verified",
17
+ PASSWORD_TOO_SHORT: "Password too short",
18
+ PASSWORD_TOO_LONG: "Password too long",
19
+ USER_ALREADY_EXISTS: "User already exists",
20
+ EMAIL_CAN_NOT_BE_UPDATED: "Email can not be updated",
21
+ CREDENTIAL_ACCOUNT_NOT_FOUND: "Credential account not found",
22
+ SESSION_EXPIRED: "Session expired. Re-authenticate to perform this action.",
23
+ FAILED_TO_UNLINK_LAST_ACCOUNT: "You can't unlink your last account",
24
+ ACCOUNT_NOT_FOUND: "Account not found",
25
+ USER_ALREADY_HAS_PASSWORD:
26
+ "User already has a password. Provide that to delete the account."
27
+ }
@@ -0,0 +1,17 @@
1
+ // These error codes are returned by the API
2
+ const EXTERNAL_ERROR_CODES = {
3
+ VERIFICATION_FAILED: "Captcha verification failed",
4
+ MISSING_RESPONSE: "Missing CAPTCHA response",
5
+ UNKNOWN_ERROR: "Something went wrong"
6
+ }
7
+
8
+ // These error codes are only visible in the server logs
9
+ const INTERNAL_ERROR_CODES = {
10
+ MISSING_SECRET_KEY: "Missing secret key",
11
+ SERVICE_UNAVAILABLE: "CAPTCHA service unavailable"
12
+ }
13
+
14
+ export const CAPTCHA_ERROR_CODES = {
15
+ ...EXTERNAL_ERROR_CODES,
16
+ ...INTERNAL_ERROR_CODES
17
+ }
@@ -0,0 +1,7 @@
1
+ export const EMAIL_OTP_ERROR_CODES = {
2
+ OTP_EXPIRED: "otp expired",
3
+ INVALID_OTP: "Invalid OTP",
4
+ INVALID_EMAIL: "Invalid email",
5
+ USER_NOT_FOUND: "User not found",
6
+ TOO_MANY_ATTEMPTS: "Too many attempts"
7
+ }
@@ -0,0 +1,3 @@
1
+ export const GENERIC_OAUTH_ERROR_CODES = {
2
+ INVALID_OAUTH_CONFIGURATION: "Invalid OAuth configuration"
3
+ }
@@ -0,0 +1,4 @@
1
+ export const HAVEIBEENPWNED_ERROR_CODES = {
2
+ PASSWORD_COMPROMISED:
3
+ "The password you entered has been compromised. Please choose a different password."
4
+ }
@@ -0,0 +1,3 @@
1
+ export const MULTI_SESSION_ERROR_CODES = {
2
+ INVALID_SESSION_TOKEN: "Invalid session token"
3
+ }
@@ -0,0 +1,57 @@
1
+ export const ORGANIZATION_ERROR_CODES = {
2
+ YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION:
3
+ "You are not allowed to create a new organization",
4
+ YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS:
5
+ "You have reached the maximum number of organizations",
6
+ ORGANIZATION_ALREADY_EXISTS: "Organization already exists",
7
+ ORGANIZATION_NOT_FOUND: "Organization not found",
8
+ USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION:
9
+ "User is not a member of the organization",
10
+ YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_ORGANIZATION:
11
+ "You are not allowed to update this organization",
12
+ YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_ORGANIZATION:
13
+ "You are not allowed to delete this organization",
14
+ NO_ACTIVE_ORGANIZATION: "No active organization",
15
+ USER_IS_ALREADY_A_MEMBER_OF_THIS_ORGANIZATION:
16
+ "User is already a member of this organization",
17
+ MEMBER_NOT_FOUND: "Member not found",
18
+ ROLE_NOT_FOUND: "Role not found",
19
+ YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM:
20
+ "You are not allowed to create a new team",
21
+ TEAM_ALREADY_EXISTS: "Team already exists",
22
+ TEAM_NOT_FOUND: "Team not found",
23
+ YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER:
24
+ "You cannot leave the organization as the only owner",
25
+ YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_MEMBER:
26
+ "You are not allowed to delete this member",
27
+ YOU_ARE_NOT_ALLOWED_TO_INVITE_USERS_TO_THIS_ORGANIZATION:
28
+ "You are not allowed to invite users to this organization",
29
+ USER_IS_ALREADY_INVITED_TO_THIS_ORGANIZATION:
30
+ "User is already invited to this organization",
31
+ INVITATION_NOT_FOUND: "Invitation not found",
32
+ YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION:
33
+ "You are not the recipient of the invitation",
34
+ YOU_ARE_NOT_ALLOWED_TO_CANCEL_THIS_INVITATION:
35
+ "You are not allowed to cancel this invitation",
36
+ INVITER_IS_NO_LONGER_A_MEMBER_OF_THE_ORGANIZATION:
37
+ "Inviter is no longer a member of the organization",
38
+ YOU_ARE_NOT_ALLOWED_TO_INVITE_USER_WITH_THIS_ROLE:
39
+ "you are not allowed to invite user with this role",
40
+ FAILED_TO_RETRIEVE_INVITATION: "Failed to retrieve invitation",
41
+ YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_TEAMS:
42
+ "You have reached the maximum number of teams",
43
+ UNABLE_TO_REMOVE_LAST_TEAM: "Unable to remove last team",
44
+ YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER:
45
+ "You are not allowed to update this member",
46
+ ORGANIZATION_MEMBERSHIP_LIMIT_REACHED:
47
+ "Organization membership limit reached",
48
+ YOU_ARE_NOT_ALLOWED_TO_CREATE_TEAMS_IN_THIS_ORGANIZATION:
49
+ "You are not allowed to create teams in this organization",
50
+ YOU_ARE_NOT_ALLOWED_TO_DELETE_TEAMS_IN_THIS_ORGANIZATION:
51
+ "You are not allowed to delete teams in this organization",
52
+ YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_TEAM:
53
+ "You are not allowed to update this team",
54
+ YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_TEAM:
55
+ "You are not allowed to delete this team",
56
+ INVITATION_LIMIT_REACHED: "Invitation limit reached"
57
+ }
@@ -0,0 +1,10 @@
1
+ export const PASSKEY_ERROR_CODES = {
2
+ CHALLENGE_NOT_FOUND: "Challenge not found",
3
+ YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY:
4
+ "You are not allowed to register this passkey",
5
+ FAILED_TO_VERIFY_REGISTRATION: "Failed to verify registration",
6
+ PASSKEY_NOT_FOUND: "Passkey not found",
7
+ AUTHENTICATION_FAILED: "Authentication failed",
8
+ UNABLE_TO_CREATE_SESSION: "Unable to create session",
9
+ FAILED_TO_UPDATE_PASSKEY: "Failed to update passkey"
10
+ }
@@ -0,0 +1,10 @@
1
+ export const PHONE_NUMBER_ERROR_CODES = {
2
+ INVALID_PHONE_NUMBER: "Invalid phone number",
3
+ PHONE_NUMBER_EXIST: "Phone number already exists",
4
+ INVALID_PHONE_NUMBER_OR_PASSWORD: "Invalid phone number or password",
5
+ UNEXPECTED_ERROR: "Unexpected error",
6
+ OTP_NOT_FOUND: "OTP not found",
7
+ OTP_EXPIRED: "OTP expired",
8
+ INVALID_OTP: "Invalid OTP",
9
+ PHONE_NUMBER_NOT_VERIFIED: "Phone number not verified"
10
+ }
@@ -0,0 +1,12 @@
1
+ export const STRIPE_ERROR_CODES = {
2
+ SUBSCRIPTION_NOT_FOUND: "Subscription not found",
3
+ SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found",
4
+ ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan",
5
+ UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer",
6
+ FAILED_TO_FETCH_PLANS: "Failed to fetch plans",
7
+ EMAIL_VERIFICATION_REQUIRED:
8
+ "Email verification is required before you can subscribe to a plan",
9
+ SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active",
10
+ SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION:
11
+ "Subscription is not scheduled for cancellation"
12
+ }
@@ -0,0 +1,12 @@
1
+ export const TEAM_ERROR_CODES = {
2
+ TEAM_LIMIT_REACHED: "Team limit reached for this organization",
3
+ TEAM_MEMBER_LIMIT_REACHED: "Team member limit reached for this team",
4
+ TEAM_NOT_FOUND: "Team not found",
5
+ TEAM_MEMBER_NOT_FOUND: "Team member not found",
6
+ TEAM_NAME_TOO_LONG: "Team name is too long",
7
+ CANNOT_REMOVE_LAST_TEAM: "Cannot remove the last team",
8
+ NOT_ORGANIZATION_MEMBER: "User is not a member of the organization",
9
+ ALREADY_TEAM_MEMBER: "User is already a member of this team",
10
+ INSUFFICIENT_TEAM_PERMISSIONS:
11
+ "Insufficient permissions to perform this action on team"
12
+ }
@@ -0,0 +1,12 @@
1
+ export const TWO_FACTOR_ERROR_CODES = {
2
+ OTP_NOT_ENABLED: "OTP not enabled",
3
+ OTP_HAS_EXPIRED: "OTP has expired",
4
+ TOTP_NOT_ENABLED: "TOTP not enabled",
5
+ TWO_FACTOR_NOT_ENABLED: "Two factor isn't enabled",
6
+ BACKUP_CODES_NOT_ENABLED: "Backup codes aren't enabled",
7
+ INVALID_BACKUP_CODE: "Invalid backup code",
8
+ INVALID_CODE: "Invalid code",
9
+ TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE:
10
+ "Too many attempts. Please request a new code.",
11
+ INVALID_TWO_FACTOR_COOKIE: "Invalid two factor cookie"
12
+ }
@@ -0,0 +1,9 @@
1
+ export const USERNAME_ERROR_CODES = {
2
+ INVALID_USERNAME_OR_PASSWORD: "invalid username or password",
3
+ EMAIL_NOT_VERIFIED: "email not verified",
4
+ UNEXPECTED_ERROR: "unexpected error",
5
+ USERNAME_IS_ALREADY_TAKEN: "username is already taken. please try another.",
6
+ USERNAME_TOO_SHORT: "username is too short",
7
+ USERNAME_TOO_LONG: "username is too long",
8
+ INVALID_USERNAME: "username is invalid"
9
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./components/email/email-template"
2
+ export { getViewByPath } from "./lib/utils"
3
+ export * from "./lib/view-paths"
4
+ export * from "./localization/auth-localization"
@@ -0,0 +1,146 @@
1
+ /* Team color variables - users can override these in their own CSS */
2
+ :root {
3
+ --team-1: oklch(0.646 0.222 41.116);
4
+ --team-2: oklch(0.6 0.118 184.704);
5
+ --team-3: oklch(0.398 0.07 227.392);
6
+ --team-4: oklch(0.828 0.189 84.429);
7
+ --team-5: oklch(0.769 0.188 70.08);
8
+ }
9
+
10
+ /*
11
+ * Animation CSS for SDK components
12
+ *
13
+ * These styles are bundled with the SDK to ensure they work regardless of
14
+ * consumer's Tailwind configuration. Uses @layer for cascade control so
15
+ * consumers can override with their own Tailwind utilities if needed.
16
+ *
17
+ * This solves the problem where consumer's Tailwind purges animation classes
18
+ * because they only exist in the SDK's minified bundle.
19
+ */
20
+
21
+ /* Keyframes for enter/exit animations (from tailwindcss-animate) */
22
+ @keyframes enter {
23
+ from {
24
+ opacity: var(--tw-enter-opacity, 1);
25
+ transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0)
26
+ scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1))
27
+ rotate(var(--tw-enter-rotate, 0));
28
+ }
29
+ }
30
+
31
+ @keyframes exit {
32
+ to {
33
+ opacity: var(--tw-exit-opacity, 1);
34
+ transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0)
35
+ scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1))
36
+ rotate(var(--tw-exit-rotate, 0));
37
+ }
38
+ }
39
+
40
+ /* Animation base classes */
41
+ .animate-in {
42
+ animation-name: enter;
43
+ animation-duration: 150ms;
44
+ --tw-enter-opacity: initial;
45
+ --tw-enter-scale: initial;
46
+ --tw-enter-rotate: initial;
47
+ --tw-enter-translate-x: initial;
48
+ --tw-enter-translate-y: initial;
49
+ }
50
+
51
+ .animate-out {
52
+ animation-name: exit;
53
+ animation-duration: 150ms;
54
+ --tw-exit-opacity: initial;
55
+ --tw-exit-scale: initial;
56
+ --tw-exit-rotate: initial;
57
+ --tw-exit-translate-x: initial;
58
+ --tw-exit-translate-y: initial;
59
+ }
60
+
61
+ /* Opacity variants */
62
+ .fade-in-0 { --tw-enter-opacity: 0; }
63
+ .fade-out-0 { --tw-exit-opacity: 0; }
64
+
65
+ /* Scale variants */
66
+ .zoom-in-95 { --tw-enter-scale: 0.95; }
67
+ .zoom-out-95 { --tw-exit-scale: 0.95; }
68
+
69
+ /* Slide variants */
70
+ .slide-in-from-top-2 { --tw-enter-translate-y: -0.5rem; }
71
+ .slide-in-from-bottom-2 { --tw-enter-translate-y: 0.5rem; }
72
+ .slide-in-from-left-2 { --tw-enter-translate-x: -0.5rem; }
73
+ .slide-in-from-right-2 { --tw-enter-translate-x: 0.5rem; }
74
+
75
+ /* Data attribute variants for Radix UI components */
76
+ [data-state="open"].animate-in {
77
+ animation-name: enter;
78
+ animation-duration: 150ms;
79
+ }
80
+
81
+ [data-state="closed"].animate-out {
82
+ animation-name: exit;
83
+ animation-duration: 150ms;
84
+ }
85
+
86
+ [data-state="open"].fade-in-0,
87
+ .data-\[state\=open\]\:fade-in-0[data-state="open"] {
88
+ --tw-enter-opacity: 0;
89
+ }
90
+
91
+ [data-state="closed"].fade-out-0,
92
+ .data-\[state\=closed\]\:fade-out-0[data-state="closed"] {
93
+ --tw-exit-opacity: 0;
94
+ }
95
+
96
+ [data-state="open"].zoom-in-95,
97
+ .data-\[state\=open\]\:zoom-in-95[data-state="open"] {
98
+ --tw-enter-scale: 0.95;
99
+ }
100
+
101
+ [data-state="closed"].zoom-out-95,
102
+ .data-\[state\=closed\]\:zoom-out-95[data-state="closed"] {
103
+ --tw-exit-scale: 0.95;
104
+ }
105
+
106
+ /* Slide variants with data-side for dropdown positioning */
107
+ [data-side="bottom"].slide-in-from-top-2,
108
+ .data-\[side\=bottom\]\:slide-in-from-top-2[data-side="bottom"] {
109
+ --tw-enter-translate-y: -0.5rem;
110
+ }
111
+
112
+ [data-side="top"].slide-in-from-bottom-2,
113
+ .data-\[side\=top\]\:slide-in-from-bottom-2[data-side="top"] {
114
+ --tw-enter-translate-y: 0.5rem;
115
+ }
116
+
117
+ [data-side="left"].slide-in-from-right-2,
118
+ .data-\[side\=left\]\:slide-in-from-right-2[data-side="left"] {
119
+ --tw-enter-translate-x: 0.5rem;
120
+ }
121
+
122
+ [data-side="right"].slide-in-from-left-2,
123
+ .data-\[side\=right\]\:slide-in-from-left-2[data-side="right"] {
124
+ --tw-enter-translate-x: -0.5rem;
125
+ }
126
+
127
+ /* Tailwind's data attribute variant syntax support */
128
+ .data-\[state\=open\]\:animate-in[data-state="open"] {
129
+ animation-name: enter;
130
+ animation-duration: 150ms;
131
+ --tw-enter-opacity: initial;
132
+ --tw-enter-scale: initial;
133
+ --tw-enter-rotate: initial;
134
+ --tw-enter-translate-x: initial;
135
+ --tw-enter-translate-y: initial;
136
+ }
137
+
138
+ .data-\[state\=closed\]\:animate-out[data-state="closed"] {
139
+ animation-name: exit;
140
+ animation-duration: 150ms;
141
+ --tw-exit-opacity: initial;
142
+ --tw-exit-scale: initial;
143
+ --tw-exit-rotate: initial;
144
+ --tw-exit-translate-x: initial;
145
+ --tw-exit-translate-y: initial;
146
+ }
@@ -0,0 +1 @@
1
+ export * from "./lib/tanstack/auth-ui-provider-tanstack"
@@ -0,0 +1 @@
1
+ export * from "./lib/triplit/use-triplit-hooks"
@@ -0,0 +1,35 @@
1
+ import type { AccountViewPaths } from "../lib/view-paths"
2
+
3
+ export type AccountOptions = {
4
+ /**
5
+ * Base path for account-scoped views
6
+ * @default "/account"
7
+ */
8
+ basePath?: string
9
+ /**
10
+ * Array of fields to show in Account Settings
11
+ * @default ["image", "name"]
12
+ */
13
+ fields: string[]
14
+ /**
15
+ * Customize account view paths
16
+ */
17
+ viewPaths?: Partial<AccountViewPaths>
18
+ }
19
+
20
+ export type AccountOptionsContext = {
21
+ /**
22
+ * Base path for account-scoped views
23
+ * @default "/account"
24
+ */
25
+ basePath: string
26
+ /**
27
+ * Array of fields to show in Account Settings
28
+ * @default ["image", "name"]
29
+ */
30
+ fields: string[]
31
+ /**
32
+ * Customize account view paths
33
+ */
34
+ viewPaths: AccountViewPaths
35
+ }
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from "react"
2
+
3
+ export type FieldType = "string" | "number" | "boolean"
4
+
5
+ export interface AdditionalField {
6
+ description?: ReactNode
7
+ instructions?: ReactNode
8
+ label: ReactNode
9
+ placeholder?: string
10
+ required?: boolean
11
+ type: FieldType
12
+ /**
13
+ * Render a multi-line textarea for string fields
14
+ */
15
+ multiline?: boolean
16
+ validate?: (value: string) => Promise<boolean>
17
+ }
18
+
19
+ export interface AdditionalFields {
20
+ [key: string]: AdditionalField
21
+ }
@@ -0,0 +1,6 @@
1
+ import type { createAuthClient } from "better-auth/react"
2
+
3
+ export type AnyAuthClient = Omit<
4
+ ReturnType<typeof createAuthClient>,
5
+ "signUp" | "getSession"
6
+ >
@@ -0,0 +1,9 @@
1
+ export type ApiKey = {
2
+ id: string
3
+ name?: string | null
4
+ start?: string | null
5
+ expiresAt?: Date | null
6
+ createdAt: Date
7
+ updatedAt: Date
8
+ metadata?: Record<string, unknown> | null
9
+ }
@@ -0,0 +1,41 @@
1
+ import { passkeyClient } from "@better-auth/passkey/client"
2
+ import {
3
+ anonymousClient,
4
+ apiKeyClient,
5
+ emailOTPClient,
6
+ genericOAuthClient,
7
+ magicLinkClient,
8
+ multiSessionClient,
9
+ oneTapClient,
10
+ organizationClient,
11
+ twoFactorClient,
12
+ usernameClient
13
+ } from "better-auth/client/plugins"
14
+ import { createAuthClient } from "better-auth/react"
15
+
16
+ export const authClient = createAuthClient({
17
+ plugins: [
18
+ apiKeyClient(),
19
+ multiSessionClient(),
20
+ passkeyClient(),
21
+ oneTapClient({
22
+ clientId: ""
23
+ }),
24
+ genericOAuthClient(),
25
+ anonymousClient(),
26
+ usernameClient(),
27
+ magicLinkClient(),
28
+ emailOTPClient(),
29
+ twoFactorClient(),
30
+ organizationClient({
31
+ teams: {
32
+ enabled: true
33
+ }
34
+ })
35
+ ]
36
+ })
37
+
38
+ export type AuthClient = typeof authClient
39
+
40
+ export type Session = AuthClient["$Infer"]["Session"]["session"]
41
+ export type User = AuthClient["$Infer"]["Session"]["user"]
@@ -0,0 +1,81 @@
1
+ import type { Passkey } from "@better-auth/passkey"
2
+ import type { BetterFetchError } from "@better-fetch/fetch"
3
+ import type { Account, User } from "better-auth"
4
+ import type { Member } from "better-auth/plugins/organization"
5
+ import type { AnyAuthClient } from "./any-auth-client"
6
+ import type { ApiKey } from "./api-key"
7
+ import type { AuthClient } from "./auth-client"
8
+ import type { Invitation } from "./invitation"
9
+ import type { Refetch } from "./refetch"
10
+
11
+ type AnyAuthSession = AnyAuthClient["$Infer"]["Session"]
12
+
13
+ type AuthHook<T> = {
14
+ isPending: boolean
15
+ data?: T | null
16
+ error?: BetterFetchError | null
17
+ refetch?: Refetch
18
+ }
19
+
20
+ export type AuthHooks = {
21
+ useSession: () => ReturnType<AnyAuthClient["useSession"]>
22
+ useListAccounts: () => AuthHook<Account[]>
23
+ useAccountInfo: (
24
+ params: Parameters<AuthClient["accountInfo"]>[0]
25
+ ) => AuthHook<{ user: User }>
26
+ useListDeviceSessions: () => AuthHook<AnyAuthClient["$Infer"]["Session"][]>
27
+ useListSessions: () => AuthHook<AnyAuthSession["session"][]>
28
+ useListPasskeys: () => AuthHook<Passkey[]>
29
+ useListApiKeys: () => AuthHook<ApiKey[]>
30
+ useActiveOrganization: () => Partial<
31
+ ReturnType<AuthClient["useActiveOrganization"]>
32
+ >
33
+ useListOrganizations: () => Partial<
34
+ ReturnType<AuthClient["useListOrganizations"]>
35
+ >
36
+ useHasPermission: (
37
+ params: Parameters<AuthClient["organization"]["hasPermission"]>[0]
38
+ ) => AuthHook<{
39
+ error: null
40
+ success: boolean
41
+ }>
42
+ useInvitation: (
43
+ params: Parameters<AuthClient["organization"]["getInvitation"]>[0]
44
+ ) => AuthHook<
45
+ Invitation & {
46
+ organizationName: string
47
+ organizationSlug: string
48
+ organizationLogo?: string
49
+ }
50
+ >
51
+ useListInvitations: (
52
+ params: Parameters<AuthClient["organization"]["listInvitations"]>[0]
53
+ ) => AuthHook<Invitation[]>
54
+ useListUserInvitations: () => AuthHook<Invitation[]>
55
+ useListMembers: (
56
+ params: Parameters<AuthClient["organization"]["listMembers"]>[0]
57
+ ) => AuthHook<{
58
+ members: (Member & { user?: Partial<User> | null })[]
59
+ total: number
60
+ }>
61
+ useListTeams: (params?: { organizationId?: string }) => AuthHook<Team[]>
62
+ useListTeamMembers: (params: { teamId?: string }) => AuthHook<TeamMember[]>
63
+ useListUserTeams: () => AuthHook<Team[]>
64
+ useIsRestoring?: () => boolean
65
+ }
66
+
67
+ export type Team = {
68
+ id: string
69
+ name: string
70
+ organizationId: string
71
+ createdAt: Date
72
+ updatedAt: Date
73
+ }
74
+
75
+ export type TeamMember = {
76
+ id: string
77
+ teamId: string
78
+ userId: string
79
+ createdAt: Date
80
+ user?: Partial<User> | null
81
+ }
@@ -0,0 +1,21 @@
1
+ type MutateFn<T = Record<string, unknown>> = (
2
+ params: T
3
+ ) => Promise<unknown> | Promise<void>
4
+
5
+ export interface AuthMutators {
6
+ deleteApiKey: MutateFn<{ keyId: string }>
7
+ deletePasskey: MutateFn<{ id: string }>
8
+ revokeDeviceSession: MutateFn<{ sessionToken: string }>
9
+ revokeSession: MutateFn<{ token: string }>
10
+ setActiveSession: MutateFn<{ sessionToken: string }>
11
+ updateOrganization: MutateFn<{
12
+ organizationId: string
13
+ data: Record<string, unknown>
14
+ }>
15
+ updateTeam: MutateFn<{
16
+ teamId: string
17
+ data: Record<string, unknown>
18
+ }>
19
+ updateUser: MutateFn
20
+ unlinkAccount: MutateFn<{ providerId: string; accountId?: string }>
21
+ }
@@ -0,0 +1,29 @@
1
+ import type { Image } from "./image"
2
+
3
+ export type AvatarOptions = {
4
+ /**
5
+ * Upload an avatar image and return the URL string
6
+ * @remarks `(file: File) => Promise<string>`
7
+ */
8
+ upload?: (file: File) => Promise<string | undefined | null>
9
+ /**
10
+ * Delete a previously uploaded avatar image from your storage/CDN
11
+ * @remarks `(url: string) => Promise<void>`
12
+ */
13
+ delete?: (url: string) => Promise<void>
14
+ /**
15
+ * Avatar size for resizing
16
+ * @default 128 (or 256 if upload is provided)
17
+ */
18
+ size: number
19
+ /**
20
+ * File extension for avatar uploads
21
+ * @default "png"
22
+ */
23
+ extension: string
24
+ /**
25
+ * Custom Image component for rendering avatar images
26
+ * @default AvatarImage from Radix UI
27
+ */
28
+ Image?: Image
29
+ }
@@ -0,0 +1,32 @@
1
+ import type { CaptchaProvider } from "./captcha-provider"
2
+
3
+ export type CaptchaOptions = {
4
+ /**
5
+ * Captcha site key
6
+ */
7
+ siteKey: string
8
+ /**
9
+ * Captcha provider type
10
+ */
11
+ provider: CaptchaProvider
12
+ /**
13
+ * Hide the captcha badge
14
+ * @default false
15
+ */
16
+ hideBadge?: boolean
17
+ /**
18
+ * Use recaptcha.net domain instead of google.com
19
+ * @default false
20
+ */
21
+ recaptchaNet?: boolean
22
+ /**
23
+ * Enable enterprise mode for Google reCAPTCHA
24
+ * @default false
25
+ */
26
+ enterprise?: boolean
27
+ /**
28
+ * Overrides the default array of paths where captcha validation is enforced
29
+ * @default ["/sign-up/email", "/sign-in/email", "/forget-password"]
30
+ */
31
+ endpoints?: string[]
32
+ }
@@ -0,0 +1,7 @@
1
+ export type CaptchaProvider =
2
+ | "cloudflare-turnstile"
3
+ | "google-recaptcha-v2-checkbox"
4
+ | "google-recaptcha-v2-invisible"
5
+ | "google-recaptcha-v3"
6
+ | "hcaptcha"
7
+ | "captchafox"