@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.
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/__tests__/auth-client.test.ts +105 -0
- package/src/__tests__/security/localStorage-encryption.test.ts +171 -0
- package/src/auth-client.ts +158 -0
- package/src/dashboard-client.ts +60 -0
- package/src/index.ts +88 -0
- package/src/kv-client.ts +316 -0
- package/src/lib/cross-origin-auth.ts +99 -0
- package/src/stubs/captcha.ts +24 -0
- package/src/stubs/hashes.ts +16 -0
- package/src/stubs/index.ts +17 -0
- package/src/stubs/passkey.ts +12 -0
- package/src/stubs/qr-code.ts +10 -0
- package/src/stubs/query.ts +16 -0
- package/src/stubs/realtime.ts +17 -0
- package/src/stubs/use-sync-external-store.ts +12 -0
- package/src/styles.css +141 -0
- package/src/types.ts +14 -0
- package/src/ui/components/auth/auth-callback.tsx +36 -0
- package/src/ui/components/auth/auth-form.tsx +310 -0
- package/src/ui/components/auth/auth-view.tsx +435 -0
- package/src/ui/components/auth/email-otp-button.tsx +53 -0
- package/src/ui/components/auth/forms/email-otp-form.tsx +312 -0
- package/src/ui/components/auth/forms/email-verification-form.tsx +271 -0
- package/src/ui/components/auth/forms/forgot-password-form.tsx +173 -0
- package/src/ui/components/auth/forms/magic-link-form.tsx +196 -0
- package/src/ui/components/auth/forms/recover-account-form.tsx +143 -0
- package/src/ui/components/auth/forms/reset-password-form.tsx +220 -0
- package/src/ui/components/auth/forms/sign-in-form.tsx +323 -0
- package/src/ui/components/auth/forms/sign-up-form.tsx +820 -0
- package/src/ui/components/auth/forms/two-factor-form.tsx +381 -0
- package/src/ui/components/auth/magic-link-button.tsx +54 -0
- package/src/ui/components/auth/one-tap.tsx +53 -0
- package/src/ui/components/auth/otp-input-group.tsx +65 -0
- package/src/ui/components/auth/passkey-button.tsx +91 -0
- package/src/ui/components/auth/provider-button.tsx +155 -0
- package/src/ui/components/auth/sign-out.tsx +25 -0
- package/src/ui/components/auth/wallet-button.tsx +192 -0
- package/src/ui/components/auth-loading.tsx +21 -0
- package/src/ui/components/captcha/captcha.tsx +91 -0
- package/src/ui/components/captcha/recaptcha-badge.tsx +61 -0
- package/src/ui/components/captcha/recaptcha-v2.tsx +58 -0
- package/src/ui/components/captcha/recaptcha-v3.tsx +73 -0
- package/src/ui/components/email/email-template.tsx +216 -0
- package/src/ui/components/form-error.tsx +27 -0
- package/src/ui/components/password-input.tsx +56 -0
- package/src/ui/components/provider-icons.tsx +404 -0
- package/src/ui/components/redirect-to-sign-in.tsx +16 -0
- package/src/ui/components/redirect-to-sign-up.tsx +16 -0
- package/src/ui/components/signed-in.tsx +20 -0
- package/src/ui/components/signed-out.tsx +20 -0
- package/src/ui/components/ui/alert.tsx +66 -0
- package/src/ui/components/ui/button.tsx +70 -0
- package/src/ui/components/ui/card.tsx +92 -0
- package/src/ui/components/ui/checkbox.tsx +66 -0
- package/src/ui/components/ui/field.tsx +248 -0
- package/src/ui/components/ui/form.tsx +165 -0
- package/src/ui/components/ui/input-otp.tsx +77 -0
- package/src/ui/components/ui/input.tsx +21 -0
- package/src/ui/components/ui/label.tsx +23 -0
- package/src/ui/components/ui/separator.tsx +34 -0
- package/src/ui/components/ui/skeleton.tsx +13 -0
- package/src/ui/components/ui/textarea.tsx +18 -0
- package/src/ui/components/user-avatar.tsx +151 -0
- package/src/ui/hooks/use-auth-data.ts +193 -0
- package/src/ui/hooks/use-authenticate.ts +64 -0
- package/src/ui/hooks/use-captcha.tsx +151 -0
- package/src/ui/hooks/use-hydrated.ts +13 -0
- package/src/ui/hooks/use-lang.ts +32 -0
- package/src/ui/hooks/use-success-transition.ts +41 -0
- package/src/ui/hooks/use-theme.ts +39 -0
- package/src/ui/index.ts +46 -0
- package/src/ui/instantdb.ts +1 -0
- package/src/ui/lib/auth-data-cache.ts +90 -0
- package/src/ui/lib/auth-ui-provider.tsx +769 -0
- package/src/ui/lib/gravatar-utils.ts +58 -0
- package/src/ui/lib/image-utils.ts +55 -0
- package/src/ui/lib/instantdb/model-names.ts +24 -0
- package/src/ui/lib/instantdb/use-instant-options.ts +98 -0
- package/src/ui/lib/instantdb/use-list-accounts.ts +38 -0
- package/src/ui/lib/instantdb/use-list-sessions.ts +53 -0
- package/src/ui/lib/instantdb/use-session.ts +55 -0
- package/src/ui/lib/social-providers.ts +150 -0
- package/src/ui/lib/tanstack/auth-ui-provider-tanstack.tsx +49 -0
- package/src/ui/lib/tanstack/use-tanstack-options.ts +112 -0
- package/src/ui/lib/triplit/model-names.ts +24 -0
- package/src/ui/lib/triplit/use-conditional-query.ts +82 -0
- package/src/ui/lib/triplit/use-list-accounts.ts +31 -0
- package/src/ui/lib/triplit/use-list-sessions.ts +33 -0
- package/src/ui/lib/triplit/use-session.ts +42 -0
- package/src/ui/lib/triplit/use-triplit-hooks.ts +68 -0
- package/src/ui/lib/triplit/use-triplit-token.ts +44 -0
- package/src/ui/lib/utils.ts +119 -0
- package/src/ui/lib/view-paths.ts +61 -0
- package/src/ui/lib/wallet.ts +129 -0
- package/src/ui/localization/admin-error-codes.ts +20 -0
- package/src/ui/localization/anonymous-error-codes.ts +6 -0
- package/src/ui/localization/api-key-error-codes.ts +32 -0
- package/src/ui/localization/auth-localization.ts +865 -0
- package/src/ui/localization/base-error-codes.ts +27 -0
- package/src/ui/localization/captcha-error-codes.ts +17 -0
- package/src/ui/localization/email-otp-error-codes.ts +7 -0
- package/src/ui/localization/generic-oauth-error-codes.ts +3 -0
- package/src/ui/localization/haveibeenpwned-error-codes.ts +4 -0
- package/src/ui/localization/multi-session-error-codes.ts +3 -0
- package/src/ui/localization/organization-error-codes.ts +57 -0
- package/src/ui/localization/passkey-error-codes.ts +10 -0
- package/src/ui/localization/phone-number-error-codes.ts +10 -0
- package/src/ui/localization/stripe-localization.ts +12 -0
- package/src/ui/localization/team-error-codes.ts +12 -0
- package/src/ui/localization/two-factor-error-codes.ts +12 -0
- package/src/ui/localization/username-error-codes.ts +9 -0
- package/src/ui/server.ts +4 -0
- package/src/ui/style.css +146 -0
- package/src/ui/tanstack.ts +1 -0
- package/src/ui/triplit.ts +1 -0
- package/src/ui/types/account-options.ts +35 -0
- package/src/ui/types/additional-fields.ts +21 -0
- package/src/ui/types/any-auth-client.ts +6 -0
- package/src/ui/types/api-key.ts +9 -0
- package/src/ui/types/auth-client.ts +41 -0
- package/src/ui/types/auth-hooks.ts +81 -0
- package/src/ui/types/auth-mutators.ts +21 -0
- package/src/ui/types/avatar-options.ts +29 -0
- package/src/ui/types/captcha-options.ts +32 -0
- package/src/ui/types/captcha-provider.ts +7 -0
- package/src/ui/types/credentials-options.ts +38 -0
- package/src/ui/types/delete-user-options.ts +7 -0
- package/src/ui/types/email-verification-options.ts +7 -0
- package/src/ui/types/fetch-error.ts +6 -0
- package/src/ui/types/generic-oauth-options.ts +16 -0
- package/src/ui/types/gravatar-options.ts +21 -0
- package/src/ui/types/image.ts +7 -0
- package/src/ui/types/invitation.ts +10 -0
- package/src/ui/types/link.ts +7 -0
- package/src/ui/types/organization-options.ts +106 -0
- package/src/ui/types/password-validation.ts +16 -0
- package/src/ui/types/profile.ts +15 -0
- package/src/ui/types/refetch.ts +1 -0
- package/src/ui/types/render-toast.ts +9 -0
- package/src/ui/types/sign-up-options.ts +7 -0
- package/src/ui/types/social-options.ts +16 -0
- 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,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
|
+
}
|
package/src/ui/server.ts
ADDED
package/src/ui/style.css
ADDED
|
@@ -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,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
|
+
}
|