UNPKG

@bettercone/ui

Version:

Comprehensive Better Auth components: authentication, security, organizations, billing, team management, and usage analytics for React

1,162 lines (1,143 loc) 778 kB
import { clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; import * as z8 from 'zod'; import { Slot } from '@radix-ui/react-slot'; import { cva } from 'class-variance-authority'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import * as ProgressPrimitive from '@radix-ui/react-progress'; import * as SeparatorPrimitive from '@radix-ui/react-separator'; import * as React12 from 'react'; import { createContext, useContext, useRef, useSyncExternalStore, useCallback, useState, useEffect, useMemo, useTransition, Fragment as Fragment$1 } from 'react'; import { Check, UserRoundIcon, CreditCard, Loader2, Settings, ExternalLink, AlertCircle, FileText, Star, TrendingUp, AlertTriangle, Zap, Lock, TrendingDown, XIcon as XIcon$1, CheckIcon, EyeIcon, EyeOffIcon, LockIcon, MailIcon, FingerprintIcon, ArrowLeftIcon, Smartphone, CheckCheck, Copy, Clock, CopyIcon, SmartphoneIcon, LaptopIcon, ShieldCheck, Mail, X, KeyRoundIcon, UploadCloudIcon, Trash2Icon, EllipsisIcon, UserCogIcon, UserXIcon, MenuIcon, ChevronsUpDown, SettingsIcon, PlusCircleIcon, LogInIcon, UserCog, UserPlus, Link2, Unlink, Search, MoreHorizontal, Eye, UserCheck, UserX, Trash2, UserRoundPlus, LogOutIcon, Wallet, Settings2, Upload, CheckCircle2, XCircle, TestTube2, ChevronLeft, ChevronRight, Plus, Key, EyeOff, Fingerprint, Info, Users, Calendar, DollarSign, SendIcon, QrCodeIcon, ChevronDownIcon, BuildingIcon, CircleIcon, ChevronUpIcon, RepeatIcon, UserX2Icon } from 'lucide-react'; import { toast } from 'sonner'; import { sha256 } from '@noble/hashes/sha2.js'; import { bytesToHex } from '@noble/hashes/utils.js'; import * as AvatarPrimitive from '@radix-ui/react-avatar'; import * as RechartsPrimitive from 'recharts'; import { BarChart, CartesianGrid, XAxis, Bar, AreaChart, Area, LineChart, Line } from 'recharts'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm, FormProvider, useFormState, Controller, useFormContext } from 'react-hook-form'; import * as LabelPrimitive from '@radix-ui/react-label'; import { OTPInput } from 'input-otp'; import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; import QRCode from 'react-qr-code'; import * as DialogPrimitive from '@radix-ui/react-dialog'; import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'; import { UAParser } from 'ua-parser-js'; import { Drawer as Drawer$1 } from 'vaul'; import * as SelectPrimitive from '@radix-ui/react-select'; import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'; import * as TabsPrimitive from '@radix-ui/react-tabs'; // src/lib/utils.ts function cn(...inputs) { return twMerge(clsx(inputs)); } function isValidEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } function getLocalizedError({ error, localization }) { if (typeof error === "string") { const key = error; if (typeof key === "string" && localization?.[key]) return localization[key]; } if (error?.error) { if (error.error.code) { const errorCode = error.error.code; if (typeof errorCode === "string" && localization?.[errorCode]) return localization[errorCode]; } return error.error.message || error.error.code || error.error.statusText || localization?.REQUEST_FAILED; } return error?.message || localization?.REQUEST_FAILED || "Request failed"; } function getSearchParam(paramName) { return typeof window !== "undefined" ? new URLSearchParams(window.location.search).get(paramName) : null; } function getViewByPath(viewPaths, path) { for (const key in viewPaths) { if (viewPaths[key] === path) { return key; } } } function getPasswordSchema(passwordValidation, localization) { let schema = z8.string().min(1, { message: localization?.PASSWORD_REQUIRED }); if (passwordValidation?.minLength) { schema = schema.min(passwordValidation.minLength, { message: localization?.PASSWORD_TOO_SHORT }); } if (passwordValidation?.maxLength) { schema = schema.max(passwordValidation.maxLength, { message: localization?.PASSWORD_TOO_LONG }); } if (passwordValidation?.regex) { schema = schema.regex(passwordValidation.regex, { message: localization?.INVALID_PASSWORD }); } return schema; } var buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline" }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9", "icon-sm": "size-8", "icon-lg": "size-10" } }, defaultVariants: { variant: "default", size: "default" } } ); function Button({ className, variant, size, asChild = false, ...props }) { const Comp = asChild ? Slot : "button"; return /* @__PURE__ */ jsx( Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size, className })), ...props } ); } var badgeVariants = cva( "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", { variants: { variant: { default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground" } }, defaultVariants: { variant: "default" } } ); function Badge({ className, variant, asChild = false, ...props }) { const Comp = asChild ? Slot : "span"; return /* @__PURE__ */ jsx( Comp, { "data-slot": "badge", className: cn(badgeVariants({ variant }), className), ...props } ); } function Skeleton({ className, ...props }) { return /* @__PURE__ */ jsx( "div", { className: cn("animate-pulse rounded-md bg-muted", className), ...props } ); } function Progress({ className, value, ...props }) { return /* @__PURE__ */ jsx( ProgressPrimitive.Root, { "data-slot": "progress", className: cn( "bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className ), ...props, children: /* @__PURE__ */ jsx( ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: "bg-primary h-full w-full flex-1 transition-all", style: { transform: `translateX(-${100 - (value || 0)}%)` } } ) } ); } function Separator({ className, orientation = "horizontal", decorative = true, ...props }) { return /* @__PURE__ */ jsx( SeparatorPrimitive.Root, { "data-slot": "separator", decorative, orientation, className: cn( "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", className ), ...props } ); } var Stepper = React12.forwardRef( ({ steps, currentStep, onStepClick, orientation = "horizontal", variant = "default", showTitle = false, showDescription = false, showStatus = false, className }, ref) => { const isVertical = orientation === "vertical"; return /* @__PURE__ */ jsx( "nav", { ref, "aria-label": "Progress", className: cn("w-full", className), children: /* @__PURE__ */ jsx( "ol", { role: "list", className: cn( "flex", isVertical ? "flex-col gap-4" : "items-center justify-between gap-2" ), children: steps.map((step, index) => { const isCurrent = currentStep === step.id; const isCompleted = variant === "controlled" ? step.completed === true : step.completed || step.id < currentStep; const isClickable = onStepClick && (isCompleted || isCurrent); return /* @__PURE__ */ jsxs( "li", { className: cn( "flex items-center", isVertical ? "w-full" : index < steps.length - 1 ? "flex-1" : "", index < steps.length - 1 && !isVertical && "gap-2" ), children: [ /* @__PURE__ */ jsxs( "div", { className: cn( "flex items-center gap-3", isVertical && "w-full" ), children: [ /* @__PURE__ */ jsx( "button", { type: "button", onClick: () => isClickable && onStepClick?.(step.id), disabled: !isClickable, "aria-current": isCurrent ? "step" : void 0, className: cn( "relative flex items-center justify-center rounded-full transition-all", variant === "circle" ? "h-10 w-10" : "h-8 w-8", isCompleted ? "bg-primary text-primary-foreground border-2 border-primary" : isCurrent ? "border-2 border-primary bg-background text-primary" : "border-2 border-muted-foreground/30 bg-background text-muted-foreground", isClickable && "cursor-pointer hover:border-primary hover:text-primary", !isClickable && "cursor-not-allowed opacity-60" ), children: isCompleted ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: step.id }) } ), (showTitle || showDescription) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [ showTitle && /* @__PURE__ */ jsx( "span", { className: cn( "text-sm font-medium", isCurrent ? "text-foreground" : isCompleted ? "text-foreground" : "text-muted-foreground" ), children: step.title } ), showDescription && step.description && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: step.description }), showStatus && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: isCompleted ? "Completed" : isCurrent ? "In progress" : "Pending" }) ] }) ] } ), index < steps.length - 1 && /* @__PURE__ */ jsx( "div", { "aria-hidden": "true", className: cn( isVertical ? "ml-4 h-8 w-0.5" : "h-0.5 flex-1", variant === "bar" && !isVertical && "h-1", isCompleted ? "bg-primary" : "bg-muted" ) } ) ] }, step.id ); }) } ) } ); } ); Stepper.displayName = "Stepper"; // src/lib/auth-data-cache.ts var AuthDataCache = class { constructor() { this.cache = /* @__PURE__ */ new Map(); this.listeners = /* @__PURE__ */ new Map(); this.inFlightRequests = /* @__PURE__ */ new Map(); } get(key) { return this.cache.get(key); } set(key, data) { const entry = { data, timestamp: Date.now(), isRefetching: false }; this.cache.set(key, entry); this.notify(key); } setRefetching(key, isRefetching) { const entry = this.cache.get(key); if (entry) { entry.isRefetching = isRefetching; this.notify(key); } } clear(key) { if (key) { this.cache.delete(key); this.inFlightRequests.delete(key); this.notify(key); } else { this.cache.clear(); this.inFlightRequests.clear(); const keys = Array.from(this.listeners.keys()); for (const key2 of keys) { this.notify(key2); } } } getInFlightRequest(key) { return this.inFlightRequests.get(key); } setInFlightRequest(key, promise) { this.inFlightRequests.set(key, promise); } removeInFlightRequest(key) { this.inFlightRequests.delete(key); } subscribe(key, callback) { if (!this.listeners.has(key)) { this.listeners.set(key, /* @__PURE__ */ new Set()); } this.listeners.get(key).add(callback); return () => { const callbacks = this.listeners.get(key); if (callbacks) { callbacks.delete(callback); if (callbacks.size === 0) { this.listeners.delete(key); } } }; } notify(key) { const callbacks = this.listeners.get(key); if (callbacks) { const callbackArray = Array.from(callbacks); for (const callback of callbackArray) { callback(); } } } }; var authDataCache = new AuthDataCache(); // src/hooks/use-auth-data.ts function useAuthData({ queryFn, cacheKey, staleTime = 1e4 // Default 10 seconds }) { const { hooks: { useSession }, toast: toast5, localization } = useContext(AuthUIContext); const { data: sessionData, isPending: sessionPending } = useSession(); const queryFnRef = useRef(queryFn); queryFnRef.current = queryFn; const stableCacheKey = cacheKey || queryFn.toString(); const cacheEntry = useSyncExternalStore( useCallback( (callback) => authDataCache.subscribe(stableCacheKey, callback), [stableCacheKey] ), useCallback( () => authDataCache.get(stableCacheKey), [stableCacheKey] ), useCallback( () => authDataCache.get(stableCacheKey), [stableCacheKey] ) ); const initialized = useRef(false); const previousUserId = useRef(void 0); const [error, setError] = useState(null); const refetch = useCallback(async () => { const existingRequest = authDataCache.getInFlightRequest(stableCacheKey); if (existingRequest) { try { const result = await existingRequest; if (result.error) { setError(result.error); } else { setError(null); } } catch (err) { setError(err); } return; } if (cacheEntry?.data !== void 0) { authDataCache.setRefetching(stableCacheKey, true); } const fetchPromise = queryFnRef.current(); authDataCache.setInFlightRequest(stableCacheKey, fetchPromise); try { const { data, error: error2 } = await fetchPromise; if (error2) { setError(error2); toast5({ variant: "error", message: getLocalizedError({ error: error2, localization }) }); } else { setError(null); } authDataCache.set(stableCacheKey, data); } catch (err) { const error2 = err; setError(error2); toast5({ variant: "error", message: getLocalizedError({ error: error2, localization }) }); } finally { authDataCache.setRefetching(stableCacheKey, false); authDataCache.removeInFlightRequest(stableCacheKey); } }, [stableCacheKey, toast5, localization, cacheEntry]); useEffect(() => { const currentUserId = sessionData?.user?.id; if (!sessionData) { authDataCache.setRefetching(stableCacheKey, false); authDataCache.clear(stableCacheKey); initialized.current = false; previousUserId.current = void 0; return; } const userIdChanged = previousUserId.current !== void 0 && previousUserId.current !== currentUserId; if (userIdChanged) { authDataCache.clear(stableCacheKey); } const hasCachedData = cacheEntry?.data !== void 0; const isStale = !cacheEntry || Date.now() - cacheEntry.timestamp > staleTime; if (!initialized.current || !hasCachedData || userIdChanged || hasCachedData && isStale) { if (!hasCachedData || isStale) { initialized.current = true; refetch(); } } previousUserId.current = currentUserId; }, [ sessionData, sessionData?.user?.id, stableCacheKey, refetch, cacheEntry, staleTime ]); const isPending = sessionPending || cacheEntry?.data === void 0 && !error; return { data: cacheEntry?.data ?? null, isPending, isRefetching: cacheEntry?.isRefetching ?? false, error, refetch }; } // src/localization/admin-error-codes.ts var ADMIN_ERROR_CODES = { FAILED_TO_CREATE_USER: "Failed to create user", USER_ALREADY_EXISTS: "User already exists", YOU_CANNOT_BAN_YOURSELF: "You cannot ban yourself", YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE: "You are not allowed to change users role", YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS: "You are not allowed to create users", YOU_ARE_NOT_ALLOWED_TO_LIST_USERS: "You are not allowed to list users", YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS: "You are not allowed to list users sessions", YOU_ARE_NOT_ALLOWED_TO_BAN_USERS: "You are not allowed to ban users", YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS: "You are not allowed to impersonate users", YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS: "You are not allowed to revoke users sessions", YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS: "You are not allowed to delete users", YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD: "You are not allowed to set users password", BANNED_USER: "You have been banned from this application" }; // src/localization/anonymous-error-codes.ts var ANONYMOUS_ERROR_CODES = { FAILED_TO_CREATE_USER: "Failed to create user", COULD_NOT_CREATE_SESSION: "Could not create session", ANONYMOUS_USERS_CANNOT_SIGN_IN_AGAIN_ANONYMOUSLY: "Anonymous users cannot sign in again anonymously" }; // src/localization/api-key-error-codes.ts var API_KEY_ERROR_CODES = { INVALID_METADATA_TYPE: "metadata must be an object or undefined", REFILL_AMOUNT_AND_INTERVAL_REQUIRED: "refillAmount is required when refillInterval is provided", REFILL_INTERVAL_AND_AMOUNT_REQUIRED: "refillInterval is required when refillAmount is provided", USER_BANNED: "User is banned", UNAUTHORIZED_SESSION: "Unauthorized or invalid session", KEY_NOT_FOUND: "API Key not found", KEY_DISABLED: "API Key is disabled", KEY_EXPIRED: "API Key has expired", USAGE_EXCEEDED: "API Key has reached its usage limit", KEY_NOT_RECOVERABLE: "API Key is not recoverable", EXPIRES_IN_IS_TOO_SMALL: "The expiresIn is smaller than the predefined minimum value.", EXPIRES_IN_IS_TOO_LARGE: "The expiresIn is larger than the predefined maximum value.", INVALID_REMAINING: "The remaining count is either too large or too small.", INVALID_PREFIX_LENGTH: "The prefix length is either too large or too small.", INVALID_NAME_LENGTH: "The name length is either too large or too small.", METADATA_DISABLED: "Metadata is disabled.", RATE_LIMIT_EXCEEDED: "Rate limit exceeded.", NO_VALUES_TO_UPDATE: "No values to update.", KEY_DISABLED_EXPIRATION: "Custom key expiration values are disabled.", INVALID_API_KEY: "Invalid API key.", INVALID_USER_ID_FROM_API_KEY: "The user id from the API key is invalid.", INVALID_API_KEY_GETTER_RETURN_TYPE: "API Key getter returned an invalid key type. Expected string.", SERVER_ONLY_PROPERTY: "The property you're trying to set can only be set from the server auth instance only." }; // src/localization/base-error-codes.ts var BASE_ERROR_CODES = { USER_NOT_FOUND: "User not found", FAILED_TO_CREATE_USER: "Failed to create user", FAILED_TO_CREATE_SESSION: "Failed to create session", FAILED_TO_UPDATE_USER: "Failed to update user", FAILED_TO_GET_SESSION: "Failed to get session", INVALID_PASSWORD: "Invalid password", INVALID_EMAIL: "Invalid email", INVALID_EMAIL_OR_PASSWORD: "Invalid email or password", SOCIAL_ACCOUNT_ALREADY_LINKED: "Social account already linked", PROVIDER_NOT_FOUND: "Provider not found", INVALID_TOKEN: "Invalid token", ID_TOKEN_NOT_SUPPORTED: "id_token not supported", FAILED_TO_GET_USER_INFO: "Failed to get user info", USER_EMAIL_NOT_FOUND: "User email not found", EMAIL_NOT_VERIFIED: "Email not verified", PASSWORD_TOO_SHORT: "Password too short", PASSWORD_TOO_LONG: "Password too long", USER_ALREADY_EXISTS: "User already exists", EMAIL_CAN_NOT_BE_UPDATED: "Email can not be updated", CREDENTIAL_ACCOUNT_NOT_FOUND: "Credential account not found", SESSION_EXPIRED: "Session expired. Re-authenticate to perform this action.", FAILED_TO_UNLINK_LAST_ACCOUNT: "You can't unlink your last account", ACCOUNT_NOT_FOUND: "Account not found", USER_ALREADY_HAS_PASSWORD: "User already has a password. Provide that to delete the account." }; // src/localization/captcha-error-codes.ts var EXTERNAL_ERROR_CODES = { VERIFICATION_FAILED: "Captcha verification failed", MISSING_RESPONSE: "Missing CAPTCHA response", UNKNOWN_ERROR: "Something went wrong" }; var INTERNAL_ERROR_CODES = { MISSING_SECRET_KEY: "Missing secret key", SERVICE_UNAVAILABLE: "CAPTCHA service unavailable" }; var CAPTCHA_ERROR_CODES = { ...EXTERNAL_ERROR_CODES, ...INTERNAL_ERROR_CODES }; // src/localization/email-otp-error-codes.ts var EMAIL_OTP_ERROR_CODES = { OTP_EXPIRED: "otp expired", INVALID_OTP: "Invalid OTP", INVALID_EMAIL: "Invalid email", USER_NOT_FOUND: "User not found", TOO_MANY_ATTEMPTS: "Too many attempts" }; // src/localization/generic-oauth-error-codes.ts var GENERIC_OAUTH_ERROR_CODES = { INVALID_OAUTH_CONFIGURATION: "Invalid OAuth configuration" }; // src/localization/haveibeenpwned-error-codes.ts var HAVEIBEENPWNED_ERROR_CODES = { PASSWORD_COMPROMISED: "The password you entered has been compromised. Please choose a different password." }; // src/localization/multi-session-error-codes.ts var MULTI_SESSION_ERROR_CODES = { INVALID_SESSION_TOKEN: "Invalid session token" }; // src/localization/organization-error-codes.ts var ORGANIZATION_ERROR_CODES = { YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION: "You are not allowed to create a new organization", YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS: "You have reached the maximum number of organizations", ORGANIZATION_ALREADY_EXISTS: "Organization already exists", ORGANIZATION_NOT_FOUND: "Organization not found", USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION: "User is not a member of the organization", YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_ORGANIZATION: "You are not allowed to update this organization", YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_ORGANIZATION: "You are not allowed to delete this organization", NO_ACTIVE_ORGANIZATION: "No active organization", USER_IS_ALREADY_A_MEMBER_OF_THIS_ORGANIZATION: "User is already a member of this organization", MEMBER_NOT_FOUND: "Member not found", ROLE_NOT_FOUND: "Role not found", YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM: "You are not allowed to create a new team", TEAM_ALREADY_EXISTS: "Team already exists", TEAM_NOT_FOUND: "Team not found", YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER: "You cannot leave the organization as the only owner", YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_MEMBER: "You are not allowed to delete this member", YOU_ARE_NOT_ALLOWED_TO_INVITE_USERS_TO_THIS_ORGANIZATION: "You are not allowed to invite users to this organization", USER_IS_ALREADY_INVITED_TO_THIS_ORGANIZATION: "User is already invited to this organization", INVITATION_NOT_FOUND: "Invitation not found", YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION: "You are not the recipient of the invitation", YOU_ARE_NOT_ALLOWED_TO_CANCEL_THIS_INVITATION: "You are not allowed to cancel this invitation", INVITER_IS_NO_LONGER_A_MEMBER_OF_THE_ORGANIZATION: "Inviter is no longer a member of the organization", YOU_ARE_NOT_ALLOWED_TO_INVITE_USER_WITH_THIS_ROLE: "you are not allowed to invite user with this role", FAILED_TO_RETRIEVE_INVITATION: "Failed to retrieve invitation", YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_TEAMS: "You have reached the maximum number of teams", UNABLE_TO_REMOVE_LAST_TEAM: "Unable to remove last team", YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER: "You are not allowed to update this member", ORGANIZATION_MEMBERSHIP_LIMIT_REACHED: "Organization membership limit reached", YOU_ARE_NOT_ALLOWED_TO_CREATE_TEAMS_IN_THIS_ORGANIZATION: "You are not allowed to create teams in this organization", YOU_ARE_NOT_ALLOWED_TO_DELETE_TEAMS_IN_THIS_ORGANIZATION: "You are not allowed to delete teams in this organization", YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_TEAM: "You are not allowed to update this team", YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_TEAM: "You are not allowed to delete this team", INVITATION_LIMIT_REACHED: "Invitation limit reached" }; // src/localization/passkey-error-codes.ts var PASSKEY_ERROR_CODES = { CHALLENGE_NOT_FOUND: "Challenge not found", YOU_ARE_NOT_ALLOWED_TO_REGISTER_THIS_PASSKEY: "You are not allowed to register this passkey", FAILED_TO_VERIFY_REGISTRATION: "Failed to verify registration", PASSKEY_NOT_FOUND: "Passkey not found", AUTHENTICATION_FAILED: "Authentication failed", UNABLE_TO_CREATE_SESSION: "Unable to create session", FAILED_TO_UPDATE_PASSKEY: "Failed to update passkey" }; // src/localization/phone-number-error-codes.ts var PHONE_NUMBER_ERROR_CODES = { INVALID_PHONE_NUMBER: "Invalid phone number", PHONE_NUMBER_EXIST: "Phone number already exists", INVALID_PHONE_NUMBER_OR_PASSWORD: "Invalid phone number or password", UNEXPECTED_ERROR: "Unexpected error", OTP_NOT_FOUND: "OTP not found", OTP_EXPIRED: "OTP expired", INVALID_OTP: "Invalid OTP", PHONE_NUMBER_NOT_VERIFIED: "Phone number not verified" }; // src/localization/stripe-localization.ts var STRIPE_ERROR_CODES = { SUBSCRIPTION_NOT_FOUND: "Subscription not found", SUBSCRIPTION_PLAN_NOT_FOUND: "Subscription plan not found", ALREADY_SUBSCRIBED_PLAN: "You're already subscribed to this plan", UNABLE_TO_CREATE_CUSTOMER: "Unable to create customer", FAILED_TO_FETCH_PLANS: "Failed to fetch plans", EMAIL_VERIFICATION_REQUIRED: "Email verification is required before you can subscribe to a plan", SUBSCRIPTION_NOT_ACTIVE: "Subscription is not active", SUBSCRIPTION_NOT_SCHEDULED_FOR_CANCELLATION: "Subscription is not scheduled for cancellation" }; // src/localization/two-factor-error-codes.ts var TWO_FACTOR_ERROR_CODES = { OTP_NOT_ENABLED: "OTP not enabled", OTP_HAS_EXPIRED: "OTP has expired", TOTP_NOT_ENABLED: "TOTP not enabled", TWO_FACTOR_NOT_ENABLED: "Two factor isn't enabled", BACKUP_CODES_NOT_ENABLED: "Backup codes aren't enabled", INVALID_BACKUP_CODE: "Invalid backup code", INVALID_CODE: "Invalid code", TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE: "Too many attempts. Please request a new code.", INVALID_TWO_FACTOR_COOKIE: "Invalid two factor cookie" }; // src/localization/username-error-codes.ts var USERNAME_ERROR_CODES = { INVALID_USERNAME_OR_PASSWORD: "invalid username or password", EMAIL_NOT_VERIFIED: "email not verified", UNEXPECTED_ERROR: "unexpected error", USERNAME_IS_ALREADY_TAKEN: "username is already taken. please try another.", USERNAME_TOO_SHORT: "username is too short", USERNAME_TOO_LONG: "username is too long", INVALID_USERNAME: "username is invalid" }; // src/localization/auth-localization.ts var authLocalization = { /** @default "App" */ APP: "App", /** @default "Account" */ ACCOUNT: "Account", /** @default "Accounts" */ ACCOUNTS: "Accounts", /** @default "Manage your currently signed in accounts." */ ACCOUNTS_DESCRIPTION: "Switch between your currently signed in accounts.", /** @default "Sign in to an additional account." */ ACCOUNTS_INSTRUCTIONS: "Sign in to an additional account.", /** @default "Add Account" */ ADD_ACCOUNT: "Add Account", /** @default "Add Passkey" */ ADD_PASSKEY: "Add Passkey", /** @default "Already have an account?" */ ALREADY_HAVE_AN_ACCOUNT: "Already have an account?", /** @default "Avatar" */ AVATAR: "Avatar", /** @default "Click on the avatar to upload a custom one from your files." */ AVATAR_DESCRIPTION: "Click on the avatar to upload a custom one from your files.", /** @default "An avatar is optional but strongly recommended." */ AVATAR_INSTRUCTIONS: "An avatar is optional but strongly recommended.", /** @default "Backup code is required" */ BACKUP_CODE_REQUIRED: "Backup code is required", /** @default "Backup Codes" */ BACKUP_CODES: "Backup Codes", /** @default "Save these backup codes in a secure place. You can use them to access your account if you lose your two-factor authentication method." */ BACKUP_CODES_DESCRIPTION: "Save these backup codes in a secure place. You can use them to access your account if you lose your two-factor authentication method.", /** @default "Backup Code." */ BACKUP_CODE_PLACEHOLDER: "Backup Code", /** @default "Backup Code" */ BACKUP_CODE: "Backup Code", /** @default "Cancel" */ CANCEL: "Cancel", /** @default "Change Password" */ CHANGE_PASSWORD: "Change Password", /** @default "Enter your current password and a new password." */ CHANGE_PASSWORD_DESCRIPTION: "Enter your current password and a new password.", /** @default "Please use 8 characters at minimum." */ CHANGE_PASSWORD_INSTRUCTIONS: "Please use 8 characters at minimum.", /** @default "Your password has been changed." */ CHANGE_PASSWORD_SUCCESS: "Your password has been changed.", /** @default "Confirm Password" */ CONFIRM_PASSWORD: "Confirm Password", /** @default "Confirm Password" */ CONFIRM_PASSWORD_PLACEHOLDER: "Confirm Password", /** @default "Confirm password is required" */ CONFIRM_PASSWORD_REQUIRED: "Confirm password is required", /** @default "Continue with Authenticator" */ CONTINUE_WITH_AUTHENTICATOR: "Continue with Authenticator", /** @default "Copied to clipboard" */ COPIED_TO_CLIPBOARD: "Copied to clipboard", /** @default "Copy to clipboard" */ COPY_TO_CLIPBOARD: "Copy to clipboard", /** @default "Copy all codes" */ COPY_ALL_CODES: "Copy all codes", /** @default "Continue" */ CONTINUE: "Continue", /** @default "Loading..." */ LOADING: "Loading...", /** @default "Current Password" */ CURRENT_PASSWORD: "Current Password", /** @default "Current Password" */ CURRENT_PASSWORD_PLACEHOLDER: "Current Password", /** @default "Current Session" */ CURRENT_SESSION: "Current Session", /** @default "Delete" */ DELETE: "Delete", /** @default "Delete Avatar" */ DELETE_AVATAR: "Delete Avatar", /** @default "Delete Account" */ DELETE_ACCOUNT: "Delete Account", /** @default "Permanently remove your account and all of its contents. This action is not reversible, so please continue with caution." */ DELETE_ACCOUNT_DESCRIPTION: "Permanently remove your account and all of its contents. This action is not reversible, so please continue with caution.", /** @default "Please confirm the deletion of your account. This action is not reversible, so please continue with caution." */ DELETE_ACCOUNT_INSTRUCTIONS: "Please confirm the deletion of your account. This action is not reversible, so please continue with caution.", /** @default "Please check your email to verify the deletion of your account." */ DELETE_ACCOUNT_VERIFY: "Please check your email to verify the deletion of your account.", /** @default "Your account has been deleted." */ DELETE_ACCOUNT_SUCCESS: "Your account has been deleted.", /** @default "Disable Two-Factor" */ DISABLE_TWO_FACTOR: "Disable Two-Factor", /** @default "Choose a provider to login to your account" */ DISABLED_CREDENTIALS_DESCRIPTION: "Choose a provider to login to your account", /** @default "Don't have an account?" */ DONT_HAVE_AN_ACCOUNT: "Don't have an account?", /** @default "Done" */ DONE: "Done", /** @default "Email" */ EMAIL: "Email", /** @default "Enter the email address you want to use to log in." */ EMAIL_DESCRIPTION: "Enter the email address you want to use to log in.", /** @default "Please enter a valid email address." */ EMAIL_INSTRUCTIONS: "Please enter a valid email address.", /** @default "Email is the same" */ EMAIL_IS_THE_SAME: "Email is the same", /** @default "m@example.com" */ EMAIL_PLACEHOLDER: "m@example.com", /** @default "Email address is required" */ EMAIL_REQUIRED: "Email address is required", /** @default "Please check your email to verify the change." */ EMAIL_VERIFY_CHANGE: "Please check your email to verify the change.", /** @default "Please check your email for the verification link." */ EMAIL_VERIFICATION: "Please check your email for the verification link.", /** @default "Enable Two-Factor" */ ENABLE_TWO_FACTOR: "Enable Two-Factor", /** @default "is invalid" */ IS_INVALID: "is invalid", /** @default "is required" */ IS_REQUIRED: "is required", /** @default "is the same" */ IS_THE_SAME: "is the same", /** @default "Forgot authenticator?" */ FORGOT_AUTHENTICATOR: "Forgot authenticator?", /** @default "Forgot Password" */ FORGOT_PASSWORD: "Forgot Password", /** @default "Send reset link" */ FORGOT_PASSWORD_ACTION: "Send reset link", /** @default "Enter your email to reset your password" */ FORGOT_PASSWORD_DESCRIPTION: "Enter your email to reset your password", /** @default "Check your email for the password reset link." */ FORGOT_PASSWORD_EMAIL: "Check your email for the password reset link.", /** @default "Forgot your password?" */ FORGOT_PASSWORD_LINK: "Forgot your password?", /** @default "Link" */ LINK: "Link", /** @default "Magic Link" */ MAGIC_LINK: "Magic Link", /** @default "Send magic link" */ MAGIC_LINK_ACTION: "Send magic link", /** @default "Enter your email to receive a magic link" */ MAGIC_LINK_DESCRIPTION: "Enter your email to receive a magic link", /** @default "Check your email for the magic link" */ MAGIC_LINK_EMAIL: "Check your email for the magic link", /** @default "Email Code" */ EMAIL_OTP: "Email Code", /** @default "Send code" */ EMAIL_OTP_SEND_ACTION: "Send code", /** @default "Verify code" */ EMAIL_OTP_VERIFY_ACTION: "Verify code", /** @default "Enter your email to receive a code" */ EMAIL_OTP_DESCRIPTION: "Enter your email to receive a code", /** @default "Please check your email for the verification code." */ EMAIL_OTP_VERIFICATION_SENT: "Please check your email for the verification code.", /** @default "Name" */ NAME: "Name", /** @default "Please enter your full name, or a display name." */ NAME_DESCRIPTION: "Please enter your full name, or a display name.", /** @default "Please use 32 characters at maximum." */ NAME_INSTRUCTIONS: "Please use 32 characters at maximum.", /** @default "Name" */ NAME_PLACEHOLDER: "Name", /** @default "New Password" */ NEW_PASSWORD: "New Password", /** @default "New Password" */ NEW_PASSWORD_PLACEHOLDER: "New Password", /** @default "New password is required" */ NEW_PASSWORD_REQUIRED: "New password is required", /** @default "One-Time Password" */ ONE_TIME_PASSWORD: "One-Time Password", /** @default "Or continue with" */ OR_CONTINUE_WITH: "Or continue with", /** @default "Passkey" */ PASSKEY: "Passkey", /** @default "Passkeys" */ PASSKEYS: "Passkeys", /** @default "Manage your passkeys for secure access." */ PASSKEYS_DESCRIPTION: "Manage your passkeys for secure access.", /** @default "Securely access your account without a password." */ PASSKEYS_INSTRUCTIONS: "Securely access your account without a password.", /** @default "Personal Account" */ PERSONAL_ACCOUNT: "Personal Account", /** @default "API Keys" */ API_KEYS: "API Keys", /** @default "Manage your API keys for secure access." */ API_KEYS_DESCRIPTION: "Manage your API keys for secure access.", /** @default "Generate API keys to access your account programmatically." */ API_KEYS_INSTRUCTIONS: "Generate API keys to access your account programmatically.", /** @default "Create API Key" */ CREATE_API_KEY: "Create API Key", /** @default "Enter a unique name for your API key to differentiate it from other keys." */ CREATE_API_KEY_DESCRIPTION: "Enter a unique name for your API key to differentiate it from other keys.", /** @default "New API Key" */ API_KEY_NAME_PLACEHOLDER: "New API Key", /** @default "API Key Created" */ API_KEY_CREATED: "API Key Created", /** @default "Please copy your API key and store it in a safe place. For security reasons we cannot show it again." */ CREATE_API_KEY_SUCCESS: "Please copy your API key and store it in a safe place. For security reasons we cannot show it again.", /** @default "Never Expires" */ NEVER_EXPIRES: "Never Expires", /** @default "Expires" */ EXPIRES: "Expires", /** @default "No Expiration" */ NO_EXPIRATION: "No Expiration", /** @default "Create Organization" */ CREATE_ORGANIZATION: "Create Organization", /** @default "Organization" */ ORGANIZATION: "Organization", /** @default "Name" */ ORGANIZATION_NAME: "Name", /** @default "Acme Inc." */ ORGANIZATION_NAME_PLACEHOLDER: "Acme Inc.", /** @default "This is your organization's visible name." */ ORGANIZATION_NAME_DESCRIPTION: "This is your organization's visible name.", /** @default "Please use 32 characters at maximum." */ ORGANIZATION_NAME_INSTRUCTIONS: "Please use 32 characters at maximum.", /** @default "Slug URL" */ ORGANIZATION_SLUG: "Slug URL", /** @default "This is your organization's URL namespace." */ ORGANIZATION_SLUG_DESCRIPTION: "This is your organization's URL namespace.", /** @default "Please use 48 characters at maximum." */ ORGANIZATION_SLUG_INSTRUCTIONS: "Please use 48 characters at maximum.", /** @default "acme-inc" */ ORGANIZATION_SLUG_PLACEHOLDER: "acme-inc", /** @default "Organization created successfully" */ CREATE_ORGANIZATION_SUCCESS: "Organization created successfully", /** @default "Password" */ PASSWORD: "Password", /** @default "Password" */ PASSWORD_PLACEHOLDER: "Password", /** @default "Password is required" */ PASSWORD_REQUIRED: "Password is required", /** @default "Passwords do not match" */ PASSWORDS_DO_NOT_MATCH: "Passwords do not match", /** @default "Providers" */ PROVIDERS: "Providers", /** @default "Connect your account with a third-party service." */ PROVIDERS_DESCRIPTION: "Connect your account with a third-party service.", /** @default "Recover Account" */ RECOVER_ACCOUNT: "Recover Account", /** @default "Recover account" */ RECOVER_ACCOUNT_ACTION: "Recover account", /** @default "Please enter a backup code to access your account" */ RECOVER_ACCOUNT_DESCRIPTION: "Please enter a backup code to access your account", /** @default "Remember me" */ REMEMBER_ME: "Remember me", /** @default "Resend code" */ RESEND_CODE: "Resend code", /** @default "Resend verification email" */ RESEND_VERIFICATION_EMAIL: "Resend Verification Email", /** @default "Reset Password" */ RESET_PASSWORD: "Reset Password", /** @default "Save new password" */ RESET_PASSWORD_ACTION: "Save new password", /** @default "Enter your new password below" */ RESET_PASSWORD_DESCRIPTION: "Enter your new password below", /** @default "Password reset successfully" */ RESET_PASSWORD_SUCCESS: "Password reset successfully", /** @default "Request failed" */ REQUEST_FAILED: "Request failed", /** @default "Revoke" */ REVOKE: "Revoke", /** @default "Delete API Key" */ DELETE_API_KEY: "Delete API Key", /** @default "Are you sure you want to delete this API key?" */ DELETE_API_KEY_CONFIRM: "Are you sure you want to delete this API key?", /** @default "API Key" */ API_KEY: "API Key", /** @default "Sign In" */ SIGN_IN: "Sign In", /** @default "Login" */ SIGN_IN_ACTION: "Login", /** @default "Enter your email below to login to your account" */ SIGN_IN_DESCRIPTION: "Enter your email below to login to your account", /** @default "Enter your username or email below to login to your account" */ SIGN_IN_USERNAME_DESCRIPTION: "Enter your username or email to login to your account", /** @default "Sign in with" */ SIGN_IN_WITH: "Sign in with", /** @default "Sign in anonymously" */ SIGN_IN_ANONYMOUSLY: "Sign in anonymously", /** @default "Continue as guest" */ ANONYMOUS_SIGN_IN: "Continue as guest", /** @default "Sign in with Ethereum" */ SIGN_IN_WITH_ETHEREUM: "Sign in with Ethereum", /** @default "Connect your Ethereum wallet" */ SIWE_SIGN_IN: "Connect your Ethereum wallet", /** @default "Sign Out" */ SIGN_OUT: "Sign Out", /** @default "Sign Up" */ SIGN_UP: "Sign Up", /** @default "Create an account" */ SIGN_UP_ACTION: "Create an account", /** @default "Enter your information to create an account" */ SIGN_UP_DESCRIPTION: "Enter your information to create an account", /** @default "Check your email for the verification link." */ SIGN_UP_EMAIL: "Check your email for the verification link.", /** @default "Sessions" */ SESSIONS: "Sessions", /** @default "Manage your active sessions and revoke access." */ SESSIONS_DESCRIPTION: "Manage your active sessions and revoke access.", /** @default "Set Password" */ SET_PASSWORD: "Set Password", /** @default "Click the button below to receive an email to set up a password for your account." */ SET_PASSWORD_DESCRIPTION: "Click the button below to receive an email to set up a password for your account.", /** @default "Settings" */ SETTINGS: "Settings", /** @default "Save" */ SAVE: "Save", /** @default "Security" */ SECURITY: "Security", /** @default "Switch Account" */ SWITCH_ACCOUNT: "Switch Account", /** @default "Trust this device" */ TRUST_DEVICE: "Trust this device", /** @default "Two-Factor" */ TWO_FACTOR: "Two-Factor", /** @default "Verify code" */ TWO_FACTOR_ACTION: "Verify code", /** @default "Please enter your one-time password to continue" */ TWO_FACTOR_DESCRIPTION: "Please enter your one-time password to continue", /** @default "Add an extra layer of security to your account." */ TWO_FACTOR_CARD_DESCRIPTION: "Add an extra layer of security to your account.", /** @default "Please enter your password to disable 2FA." */ TWO_FACTOR_DISABLE_INSTRUCTIONS: "Please enter your password to disable 2FA.", /** @default "Please enter your password to enable 2FA" */ TWO_FACTOR_ENABLE_INSTRUCTIONS: "Please enter your password to enable 2FA.", /** @default "Two-factor authentication has been enabled" */ TWO_FACTOR_ENABLED: "Two-factor authentication has been enabled", /** @default "Two-Factor Authentication has been disabled" */ TWO_FACTOR_DISABLED: "Two-Factor Authentication has been disabled", /** @default "Two-Factor Authentication" */ TWO_FACTOR_PROMPT: "Two-Factor Authentication", /** @default "Scan the QR Code with your Authenticator" */ TWO_FACTOR_TOTP_LABEL: "Scan the QR Code with your Authenticator", /** @default "Send verification code" */ SEND_VERIFICATION_CODE: "Send verification code", /** @default "Unlink" */ UNLINK: "Unlink", /** @default "Updated successfully" */ UPDATED_SUCCESSFULLY: "updated successfully", /** @default "Username" */ USERNAME: "Username", /** @default "Enter the username you want to use to log in." */ USERNAME_DESCRIPTION: "Enter the username you want to use to log in.", /** @default "Please use 32 characters at maximum." */ USERNAME_INSTRUCTIONS: "Please use 32 characters at maximum.", /** @default "Username" */ USERNAME_PLACEHOLDER: "Username", /** @default "Username or email" */ SIGN_IN_USERNAME_PLACEHOLDER: "Username or email", /** @default "Verify Your Email" */ VERIFY_YOUR_EMAIL: "Verify Your Email", /** @default "Please verify your email address. Check your inbox for the verification email. If you haven't received the email, click the button below to resend." */ VERIFY_YOUR_EMAIL_DESCRIPTION: "Please verify your email address. Check your inbox for the verification email. If you haven't received the email, click the button below to resend.", /** @default "Go back" */ GO_BACK: "Go back", /** @default "Your session is not fresh. Please sign in again." */ SESSION_NOT_FRESH: "Your session is not fresh. Please sign in again.", /** @default "Upload Avatar" */ UPLOAD_AVATAR: "Upload Avatar", /** @default "Logo" */ LOGO: "Logo", /** @default "Click on the logo to upload a custom one from your files." */ LOGO_DESCRIPTION: "Click on the logo to upload a custom one from your files.", /** @default "A logo is optional but strongly recommended." */ LOGO_INSTRUCTIONS: "A logo is optional but strongly recommended.", /** @default "Upload" */ UPLOAD: "Upload", /** @default "Upload Logo" */ UPLOAD_LOGO: "Upload Logo", /** @default "Delete Logo" */ DELETE_LOGO: "Delete Logo", /** @default "Privacy Policy" */ PRIVACY_POLICY: "Privacy Policy", /** @default "Terms of Service" */ TERMS_OF_SERVICE: "Terms of Service", /** @default "This site is protected by reCAPTCHA." */ PROTECTED_BY_RECAPTCHA: "This site is protected by reCAPTCHA.", /** @default "By continuing, you agree to the" */ BY_CONTINUING_YOU_AGREE: "By continuing, you agree to the", /** @default "User" */ USER: "User", /** @default "Organizations" */ ORGANIZATIONS: "Organizations", /** @default "Manage your organizations and memberships." */ ORGANIZATIONS_DESCRIPTION: "Manage your organizations and memberships.", /** @default "Create an organization to collaborate with other users." */ ORGANIZATIONS_INSTRUCTIONS: "Create an organization to collaborate with other users.", /** @default "Leave Organization" */ LEAVE_ORGANIZATION: "Leave Organization", /** @default "Are you sure you want to leave this organization?" */ LEAVE_ORGANIZATION_CONFIRM: "Are you sure you want to leave this organization?", /** @default "You have successfully left the organization." */ LEAVE_ORGANIZATION_SUCCESS: "You have successfully left the organization.", /** @default "Manage Organization" */ MANAGE_ORGANIZATION: "Manage Organization", /** @default "Remove Member" */ REMOVE_MEMBER: "Remove Member", /** @default "Are you sure you want to remove this member from the organization?" */ REMOVE_MEMBER_CONFIRM: "Are you sure you want to remove this member from the organization?", /** @default "Member removed successfully" */ REMOVE_MEMBER_SUCCESS: "Member removed successfully", /** @default "Invite Member" */ INVITE_MEMBER: "Invite Member", /** @default "Members" */ MEMBERS: "Members", /** @default "Add or remove members and manage their roles." */ MEMBERS_DESCRIPTION: "Add or remove members and manage their roles.", /** @default "Invite new members to your organization." */ MEMBERS_INSTRUCTIONS: "Invite new members to your organization.", /** @default "Send an invitation to add a new member to your organization." */ INVITE_MEMBER_DESCRIPTION: "Send an invitation to add a new member to your organization.", /** @default "Role" */ ROLE: "Role", /** @default "Select a role" */ SELECT_ROLE: "Select a role", /** @default "Admin" */ ADMIN: "Admin", /** @default "Member" */ MEMBER: "Member", /** @default "Guest" */ GUEST: "Guest", /** @default "Owner" */ OWNER: "Owner", /** @default "Update the role for this member" */ UPDATE_ROLE_DESCRIPTION: "Update the role for this member", /** @default "Update Role" */ UPDATE_ROLE: "Update Role", /** @default "Member role updated successfully" */ MEMBER_ROLE_UPDATED: "Member role updated successfully", /** @default "Send Invitation" */ SEND_INVITATION: "Send Invitation", /** @default "Invitation sent successfully" */ SEND_INVI