@better-auth-ui/core 1.6.1 → 1.6.2

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.
@@ -1,11 +1,12 @@
1
- import type { SocialProvider } from "better-auth/social-providers";
2
- import { type BasePaths } from "../lib/base-paths";
3
- import { type Localization } from "../lib/localization";
4
- import { type ViewPaths } from "../lib/view-paths";
5
- import type { AppearanceConfig } from "./appearance-config";
6
- import type { AvatarConfig } from "./avatar-config";
7
- import type { DeleteUserConfig } from "./delete-user-config";
8
- import type { EmailAndPasswordConfig } from "./email-and-password-config";
1
+ import { SocialProvider } from 'better-auth/social-providers';
2
+ import { BasePaths } from '../lib/base-paths';
3
+ import { Localization } from '../lib/localization';
4
+ import { ViewPaths } from '../lib/view-paths';
5
+ import { AppearanceConfig } from './appearance-config';
6
+ import { AvatarConfig } from './avatar-config';
7
+ import { DeleteUserConfig } from './delete-user-config';
8
+ import { EmailAndPasswordConfig } from './email-and-password-config';
9
+ import { UsernameConfig } from './username-config';
9
10
  /**
10
11
  * Core authentication configuration interface.
11
12
  *
@@ -71,6 +72,11 @@ export interface AuthConfig {
71
72
  * @remarks `ViewPaths`
72
73
  */
73
74
  viewPaths: ViewPaths;
75
+ /**
76
+ * Username plugin configuration
77
+ * @remarks `UsernameConfig`
78
+ */
79
+ username: UsernameConfig;
74
80
  /**
75
81
  * Function to navigate to a new path
76
82
  * @param options - Navigation options with href and optional replace flag
@@ -1,35 +1,42 @@
1
- import { basePaths } from "../lib/base-paths";
2
- import { localization } from "../lib/localization";
3
- import { resizeAvatar } from "../lib/utils";
4
- import { viewPaths } from "../lib/view-paths";
5
- export const defaultAuthConfig = {
6
- appearance: {
7
- themes: ["system", "light", "dark"]
8
- },
9
- avatar: {
10
- enabled: true,
11
- resize: resizeAvatar,
12
- size: 256,
13
- extension: "png"
14
- },
15
- basePaths,
16
- baseURL: "",
17
- emailAndPassword: {
18
- enabled: true,
19
- forgotPassword: true,
20
- rememberMe: false,
21
- minPasswordLength: 8,
22
- maxPasswordLength: 128
23
- },
24
- redirectTo: "/",
25
- viewPaths,
26
- localization,
27
- navigate: ({ to, replace }) => {
28
- if (replace) {
29
- window.location.replace(to);
30
- }
31
- else {
32
- window.location.href = to;
33
- }
34
- }
1
+ import { basePaths as e } from "../lib/base-paths.js";
2
+ import { localization as t } from "../lib/localization.js";
3
+ import { resizeAvatar as n } from "../lib/utils.js";
4
+ import { viewPaths as r } from "../lib/view-paths.js";
5
+ //#region src/config/auth-config.ts
6
+ var i = {
7
+ appearance: { themes: [
8
+ "system",
9
+ "light",
10
+ "dark"
11
+ ] },
12
+ avatar: {
13
+ enabled: !0,
14
+ resize: n,
15
+ size: 256,
16
+ extension: "png"
17
+ },
18
+ basePaths: e,
19
+ baseURL: "",
20
+ emailAndPassword: {
21
+ enabled: !0,
22
+ forgotPassword: !0,
23
+ rememberMe: !1,
24
+ minPasswordLength: 8,
25
+ maxPasswordLength: 128
26
+ },
27
+ redirectTo: "/",
28
+ viewPaths: r,
29
+ localization: t,
30
+ username: {
31
+ enabled: !1,
32
+ displayUsername: !0,
33
+ isUsernameAvailable: !0,
34
+ minUsernameLength: 3,
35
+ maxUsernameLength: 30
36
+ },
37
+ navigate: ({ to: e, replace: t }) => {
38
+ t ? window.location.replace(e) : window.location.href = e;
39
+ }
35
40
  };
41
+ //#endregion
42
+ export { i as defaultAuthConfig };
@@ -1,5 +1,6 @@
1
- export * from "./appearance-config";
2
- export * from "./auth-config";
3
- export * from "./avatar-config";
4
- export * from "./delete-user-config";
5
- export * from "./email-and-password-config";
1
+ export * from './appearance-config';
2
+ export * from './auth-config';
3
+ export * from './avatar-config';
4
+ export * from './delete-user-config';
5
+ export * from './email-and-password-config';
6
+ export * from './username-config';
@@ -0,0 +1,18 @@
1
+ export interface UsernameConfig {
2
+ /** Whether the username plugin is enabled */
3
+ enabled: boolean;
4
+ /** Whether to use displayUsername for the visible username field */
5
+ displayUsername: boolean;
6
+ /** Whether to check username availability on sign-up and user profile */
7
+ isUsernameAvailable: boolean;
8
+ /**
9
+ * Minimum allowed username length
10
+ * @default 3
11
+ */
12
+ minUsernameLength: number;
13
+ /**
14
+ * Maximum allowed username length
15
+ * @default 30
16
+ */
17
+ maxUsernameLength: number;
18
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export * from "./config";
2
- export * from "./lib/base-paths";
3
- export * from "./lib/localization";
4
- export * from "./lib/provider-names";
5
- export * from "./lib/utils";
6
- export * from "./lib/view-paths";
1
+ export * from './config';
2
+ export * from './lib/base-paths';
3
+ export * from './lib/localization';
4
+ export * from './lib/provider-names';
5
+ export * from './lib/utils';
6
+ export * from './lib/view-paths';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
- export * from "./config";
2
- export * from "./lib/base-paths";
3
- export * from "./lib/localization";
4
- export * from "./lib/provider-names";
5
- export * from "./lib/utils";
6
- export * from "./lib/view-paths";
1
+ import { basePaths as e } from "./lib/base-paths.js";
2
+ import { localization as t } from "./lib/localization.js";
3
+ import { deepmerge as n, fileToBase64 as r, resizeAvatar as i } from "./lib/utils.js";
4
+ import { viewPaths as a } from "./lib/view-paths.js";
5
+ import { defaultAuthConfig as o } from "./config/auth-config.js";
6
+ import { getProviderName as s, providerNames as c } from "./lib/provider-names.js";
7
+ export { e as basePaths, n as deepmerge, o as defaultAuthConfig, r as fileToBase64, s as getProviderName, t as localization, c as providerNames, i as resizeAvatar, a as viewPaths };
@@ -1,5 +1,8 @@
1
- export const basePaths = {
2
- auth: "/auth",
3
- settings: "/settings",
4
- organization: "/organization"
1
+ //#region src/lib/base-paths.ts
2
+ var e = {
3
+ auth: "/auth",
4
+ settings: "/settings",
5
+ organization: "/organization"
5
6
  };
7
+ //#endregion
8
+ export { e as basePaths };
@@ -74,6 +74,16 @@ export declare const localization: {
74
74
  signUp: string;
75
75
  /** @remarks `"Switch Account"` */
76
76
  switchAccount: string;
77
+ /** @remarks `"Username"` */
78
+ username: string;
79
+ /** @remarks `"Username is available"` */
80
+ usernameAvailable: string;
81
+ /** @remarks `"Enter your username or email"` */
82
+ usernameOrEmailPlaceholder: string;
83
+ /** @remarks `"Enter your username"` */
84
+ usernamePlaceholder: string;
85
+ /** @remarks `"Username is already taken. Please try another."` */
86
+ usernameTaken: string;
77
87
  /** @remarks `"Verification email sent!"` */
78
88
  verificationEmailSent: string;
79
89
  /** @remarks `"Verify your email"` */
@@ -1,184 +1,103 @@
1
- export const localization = {
2
- auth: {
3
- /** @remarks `"Account"` */
4
- account: "Account",
5
- /** @remarks `"Add Account"` */
6
- addAccount: "Add Account",
7
- /** @remarks `"Already have an account?"` */
8
- alreadyHaveAnAccount: "Already have an account?",
9
- /** @remarks `"Confirm password"` */
10
- confirmPassword: "Confirm password",
11
- /** @remarks `"Confirm your password"` */
12
- confirmPasswordPlaceholder: "Confirm your password",
13
- /** @remarks `"Continue with {{provider}}"` */
14
- continueWith: "Continue with {{provider}}",
15
- /** @remarks `"Email"` */
16
- email: "Email",
17
- /** @remarks `"Enter your email"` */
18
- emailPlaceholder: "Enter your email",
19
- /** @remarks `"Forgot Password"` */
20
- forgotPassword: "Forgot Password",
21
- /** @remarks `"Forgot password?"` */
22
- forgotPasswordLink: "Forgot password?",
23
- /** @remarks `"Hide password"` */
24
- hidePassword: "Hide password",
25
- /** @remarks `"Invalid reset password token"` */
26
- invalidResetPasswordToken: "Invalid reset password token",
27
- /** @remarks `"Magic Link"` */
28
- magicLink: "Magic Link",
29
- /** @remarks `"Magic link sent to your email"` */
30
- magicLinkSent: "Magic link sent to your email",
31
- /** @remarks `"Name"` */
32
- name: "Name",
33
- /** @remarks `"Enter your name"` */
34
- namePlaceholder: "Enter your name",
35
- /** @remarks `"Need to create an account?"` */
36
- needToCreateAnAccount: "Need to create an account?",
37
- /** @remarks `"New password"` */
38
- newPassword: "New password",
39
- /** @remarks `"Enter your new password"` */
40
- newPasswordPlaceholder: "Enter your new password",
41
- /** @remarks `"OR"` */
42
- or: "OR",
43
- /** @remarks `"Passkey"` */
44
- passkey: "Passkey",
45
- /** @remarks `"Password"` */
46
- password: "Password",
47
- /** @remarks `"Enter your password"` */
48
- passwordPlaceholder: "Enter your password",
49
- /** @remarks `"Password reset email sent"` */
50
- passwordResetEmailSent: "Password reset email sent",
51
- /** @remarks `"Password reset successfully"` */
52
- passwordResetSuccess: "Password reset successfully",
53
- /** @remarks `"Passwords do not match"` */
54
- passwordsDoNotMatch: "Passwords do not match",
55
- /** @remarks `"Remember me"` */
56
- rememberMe: "Remember me",
57
- /** @remarks `"Remember your password?"` */
58
- rememberYourPassword: "Remember your password?",
59
- /** @remarks `"Resend"` */
60
- resend: "Resend",
61
- /** @remarks `"Reset Password"` */
62
- resetPassword: "Reset Password",
63
- /** @remarks `"Send Magic Link"` */
64
- sendMagicLink: "Send Magic Link",
65
- /** @remarks `"Send reset link"` */
66
- sendResetLink: "Send reset link",
67
- /** @remarks `"Show password"` */
68
- showPassword: "Show password",
69
- /** @remarks `"Sign In"` */
70
- signIn: "Sign In",
71
- /** @remarks `"Sign Out"` */
72
- signOut: "Sign Out",
73
- /** @remarks `"Sign Up"` */
74
- signUp: "Sign Up",
75
- /** @remarks `"Switch Account"` */
76
- switchAccount: "Switch Account",
77
- /** @remarks `"Verification email sent!"` */
78
- verificationEmailSent: "Verification email sent!",
79
- /** @remarks `"Verify your email"` */
80
- verifyYourEmail: "Verify your email"
81
- },
82
- settings: {
83
- /** @remarks `"Account"` */
84
- account: "Account",
85
- /** @remarks `"Account unlinked"` */
86
- accountUnlinked: "Account unlinked",
87
- /** @remarks `"Active"` */
88
- active: "Active",
89
- /** @remarks `"Active sessions"` */
90
- activeSessions: "Active sessions",
91
- /** @remarks `"Avatar"` */
92
- avatar: "Avatar",
93
- /** @remarks `"Current session"` */
94
- currentSession: "Current session",
95
- /** @remarks `"Avatar changed successfully"` */
96
- avatarChangedSuccess: "Avatar changed successfully",
97
- /** @remarks `"Avatar deleted successfully"` */
98
- avatarDeletedSuccess: "Avatar deleted successfully",
99
- /** @remarks `"Change avatar"` */
100
- changeAvatar: "Change avatar",
101
- /** @remarks `"Delete avatar"` */
102
- deleteAvatar: "Delete avatar",
103
- /** @remarks `"Link"` */
104
- link: "Link",
105
- /** @remarks `"Linked accounts"` */
106
- linkedAccounts: "Linked accounts",
107
- /** @remarks `"Link your {{provider}} account"` */
108
- linkProvider: "Link your {{provider}} account",
109
- /** @remarks `"Appearance"` */
110
- appearance: "Appearance",
111
- /** @remarks `"Cancel"` */
112
- cancel: "Cancel",
113
- /** @remarks `"Change email"` */
114
- changeEmail: "Change email",
115
- /** @remarks `"Check your email to confirm the change"` */
116
- changeEmailSuccess: "Check your email to confirm the change",
117
- /** @remarks `"Change password"` */
118
- changePassword: "Change password",
119
- /** @remarks `"Password changed successfully"` */
120
- changePasswordSuccess: "Password changed successfully",
121
- /** @remarks `"Current password"` */
122
- currentPassword: "Current password",
123
- /** @remarks `"Enter your current password"` */
124
- currentPasswordPlaceholder: "Enter your current password",
125
- /** @remarks `"Dark"` */
126
- dark: "Dark",
127
- /** @remarks `"Danger zone"` */
128
- dangerZone: "Danger zone",
129
- /** @remarks `"Delete user"` */
130
- deleteUser: "Delete user",
131
- /** @remarks `"Permanently remove your account and all associated data. This cannot be undone."` */
132
- deleteUserDescription: "Permanently remove your account and all associated data. This cannot be undone.",
133
- /** @remarks `"Check your email to confirm account deletion."` */
134
- deleteUserVerificationSent: "Check your email to confirm account deletion.",
135
- /** @remarks `"Your account has been deleted."` */
136
- deleteUserSuccess: "Your account has been deleted.",
137
- /** @remarks `"Light"` */
138
- light: "Light",
139
- /** @remarks `"Manage accounts"` */
140
- manageAccounts: "Manage accounts",
141
- /** @remarks `"Add passkey"` */
142
- addPasskey: "Add passkey",
143
- /** @remarks `"Delete"` */
144
- delete: "Delete",
145
- /** @remarks `"Passkeys"` */
146
- passkeys: "Passkeys",
147
- /** @remarks `"Manage your passkeys for secure access."` */
148
- passkeysDescription: "Manage your passkeys for secure access.",
149
- /** @remarks `"Securely access your account without a password."` */
150
- passkeysInstructions: "Securely access your account without a password.",
151
- /** @remarks `"Profile"` */
152
- profile: "Profile",
153
- /** @remarks `"Profile updated successfully"` */
154
- profileUpdatedSuccess: "Profile updated successfully",
155
- /** @remarks `"Revoke"` */
156
- revoke: "Revoke",
157
- /** @remarks `"Revoke session"` */
158
- revokeSession: "Revoke session",
159
- /** @remarks `"Session revoked successfully"` */
160
- revokeSessionSuccess: "Session revoked successfully",
161
- /** @remarks `"Save changes"` */
162
- saveChanges: "Save changes",
163
- /** @remarks `"Set password"` */
164
- setPassword: "Set password",
165
- /** @remarks `"You don't have a password yet. Request a reset link to set one up."` */
166
- setPasswordDescription: "You don't have a password yet. Request a reset link to set one up.",
167
- /** @remarks `"Security"` */
168
- security: "Security",
169
- /** @remarks `"Settings"` */
170
- settings: "Settings",
171
- /** @remarks `"System"` */
172
- system: "System",
173
- /** @remarks `"Theme"` */
174
- theme: "Theme",
175
- /** @remarks `"Unlink {{provider}}"` */
176
- unlinkProvider: "Unlink {{provider}}",
177
- /** @remarks `"Update email"` */
178
- updateEmail: "Update email",
179
- /** @remarks `"Update password"` */
180
- updatePassword: "Update password",
181
- /** @remarks `"Upload avatar"` */
182
- uploadAvatar: "Upload avatar"
183
- }
1
+ //#region src/lib/localization.ts
2
+ var e = {
3
+ auth: {
4
+ account: "Account",
5
+ addAccount: "Add Account",
6
+ alreadyHaveAnAccount: "Already have an account?",
7
+ confirmPassword: "Confirm password",
8
+ confirmPasswordPlaceholder: "Confirm your password",
9
+ continueWith: "Continue with {{provider}}",
10
+ email: "Email",
11
+ emailPlaceholder: "Enter your email",
12
+ forgotPassword: "Forgot Password",
13
+ forgotPasswordLink: "Forgot password?",
14
+ hidePassword: "Hide password",
15
+ invalidResetPasswordToken: "Invalid reset password token",
16
+ magicLink: "Magic Link",
17
+ magicLinkSent: "Magic link sent to your email",
18
+ name: "Name",
19
+ namePlaceholder: "Enter your name",
20
+ needToCreateAnAccount: "Need to create an account?",
21
+ newPassword: "New password",
22
+ newPasswordPlaceholder: "Enter your new password",
23
+ or: "OR",
24
+ passkey: "Passkey",
25
+ password: "Password",
26
+ passwordPlaceholder: "Enter your password",
27
+ passwordResetEmailSent: "Password reset email sent",
28
+ passwordResetSuccess: "Password reset successfully",
29
+ passwordsDoNotMatch: "Passwords do not match",
30
+ rememberMe: "Remember me",
31
+ rememberYourPassword: "Remember your password?",
32
+ resend: "Resend",
33
+ resetPassword: "Reset Password",
34
+ sendMagicLink: "Send Magic Link",
35
+ sendResetLink: "Send reset link",
36
+ showPassword: "Show password",
37
+ signIn: "Sign In",
38
+ signOut: "Sign Out",
39
+ signUp: "Sign Up",
40
+ switchAccount: "Switch Account",
41
+ username: "Username",
42
+ usernameAvailable: "Username is available",
43
+ usernameOrEmailPlaceholder: "Enter your username or email",
44
+ usernamePlaceholder: "Enter your username",
45
+ usernameTaken: "Username is already taken. Please try another.",
46
+ verificationEmailSent: "Verification email sent!",
47
+ verifyYourEmail: "Verify your email"
48
+ },
49
+ settings: {
50
+ account: "Account",
51
+ accountUnlinked: "Account unlinked",
52
+ active: "Active",
53
+ activeSessions: "Active sessions",
54
+ avatar: "Avatar",
55
+ currentSession: "Current session",
56
+ avatarChangedSuccess: "Avatar changed successfully",
57
+ avatarDeletedSuccess: "Avatar deleted successfully",
58
+ changeAvatar: "Change avatar",
59
+ deleteAvatar: "Delete avatar",
60
+ link: "Link",
61
+ linkedAccounts: "Linked accounts",
62
+ linkProvider: "Link your {{provider}} account",
63
+ appearance: "Appearance",
64
+ cancel: "Cancel",
65
+ changeEmail: "Change email",
66
+ changeEmailSuccess: "Check your email to confirm the change",
67
+ changePassword: "Change password",
68
+ changePasswordSuccess: "Password changed successfully",
69
+ currentPassword: "Current password",
70
+ currentPasswordPlaceholder: "Enter your current password",
71
+ dark: "Dark",
72
+ dangerZone: "Danger zone",
73
+ deleteUser: "Delete user",
74
+ deleteUserDescription: "Permanently remove your account and all associated data. This cannot be undone.",
75
+ deleteUserVerificationSent: "Check your email to confirm account deletion.",
76
+ deleteUserSuccess: "Your account has been deleted.",
77
+ light: "Light",
78
+ manageAccounts: "Manage accounts",
79
+ addPasskey: "Add passkey",
80
+ delete: "Delete",
81
+ passkeys: "Passkeys",
82
+ passkeysDescription: "Manage your passkeys for secure access.",
83
+ passkeysInstructions: "Securely access your account without a password.",
84
+ profile: "Profile",
85
+ profileUpdatedSuccess: "Profile updated successfully",
86
+ revoke: "Revoke",
87
+ revokeSession: "Revoke session",
88
+ revokeSessionSuccess: "Session revoked successfully",
89
+ saveChanges: "Save changes",
90
+ setPassword: "Set password",
91
+ setPasswordDescription: "You don't have a password yet. Request a reset link to set one up.",
92
+ security: "Security",
93
+ settings: "Settings",
94
+ system: "System",
95
+ theme: "Theme",
96
+ unlinkProvider: "Unlink {{provider}}",
97
+ updateEmail: "Update email",
98
+ updatePassword: "Update password",
99
+ uploadAvatar: "Upload avatar"
100
+ }
184
101
  };
102
+ //#endregion
103
+ export { e as localization };
@@ -1,4 +1,4 @@
1
- import type { SocialProvider } from "better-auth/social-providers";
1
+ import { SocialProvider } from 'better-auth/social-providers';
2
2
  /**
3
3
  * Mapping of social authentication provider identifiers to their human-readable display names.
4
4
  */
@@ -1,50 +1,43 @@
1
- /**
2
- * Mapping of social authentication provider identifiers to their human-readable display names.
3
- */
4
- export const providerNames = {
5
- apple: "Apple",
6
- atlassian: "Atlassian",
7
- cognito: "Cognito",
8
- discord: "Discord",
9
- dropbox: "Dropbox",
10
- facebook: "Facebook",
11
- figma: "Figma",
12
- github: "GitHub",
13
- gitlab: "GitLab",
14
- google: "Google",
15
- huggingface: "Hugging Face",
16
- kakao: "Kakao",
17
- kick: "Kick",
18
- line: "LINE",
19
- linear: "Linear",
20
- linkedin: "LinkedIn",
21
- microsoft: "Microsoft",
22
- naver: "Naver",
23
- notion: "Notion",
24
- paybin: "Paybin",
25
- paypal: "PayPal",
26
- polar: "Polar",
27
- railway: "Railway",
28
- reddit: "Reddit",
29
- roblox: "Roblox",
30
- salesforce: "Salesforce",
31
- slack: "Slack",
32
- spotify: "Spotify",
33
- tiktok: "TikTok",
34
- twitch: "Twitch",
35
- twitter: "X",
36
- vercel: "Vercel",
37
- vk: "VK",
38
- wechat: "WeChat",
39
- zoom: "Zoom"
1
+ //#region src/lib/provider-names.ts
2
+ var e = {
3
+ apple: "Apple",
4
+ atlassian: "Atlassian",
5
+ cognito: "Cognito",
6
+ discord: "Discord",
7
+ dropbox: "Dropbox",
8
+ facebook: "Facebook",
9
+ figma: "Figma",
10
+ github: "GitHub",
11
+ gitlab: "GitLab",
12
+ google: "Google",
13
+ huggingface: "Hugging Face",
14
+ kakao: "Kakao",
15
+ kick: "Kick",
16
+ line: "LINE",
17
+ linear: "Linear",
18
+ linkedin: "LinkedIn",
19
+ microsoft: "Microsoft",
20
+ naver: "Naver",
21
+ notion: "Notion",
22
+ paybin: "Paybin",
23
+ paypal: "PayPal",
24
+ polar: "Polar",
25
+ railway: "Railway",
26
+ reddit: "Reddit",
27
+ roblox: "Roblox",
28
+ salesforce: "Salesforce",
29
+ slack: "Slack",
30
+ spotify: "Spotify",
31
+ tiktok: "TikTok",
32
+ twitch: "Twitch",
33
+ twitter: "X",
34
+ vercel: "Vercel",
35
+ vk: "VK",
36
+ wechat: "WeChat",
37
+ zoom: "Zoom"
40
38
  };
41
- /**
42
- * Get the human-readable display name for an authentication provider.
43
- *
44
- * @param provider - The provider identifier (e.g., "github", "google").
45
- * @returns The mapped display name for `provider` if available, otherwise `provider` with its first character capitalized.
46
- */
47
- export function getProviderName(provider) {
48
- return (providerNames[provider] ||
49
- provider.charAt(0).toUpperCase() + provider.slice(1));
39
+ function t(t) {
40
+ return e[t] || t.charAt(0).toUpperCase() + t.slice(1);
50
41
  }
42
+ //#endregion
43
+ export { t as getProviderName, e as providerNames };
package/dist/lib/utils.js CHANGED
@@ -1,116 +1,48 @@
1
- /**
2
- * Type guard that checks whether a value is a non-null, non-array object.
3
- */
4
- function isObject(item) {
5
- return item !== null && typeof item === "object" && !Array.isArray(item);
1
+ //#region src/lib/utils.ts
2
+ function e(e) {
3
+ return typeof e == "object" && !!e && !Array.isArray(e);
6
4
  }
7
- /**
8
- * Type guard that checks whether a value is a plain object suitable for deep merging.
9
- * Excludes `Date`, `RegExp`, and other special object types.
10
- */
11
- function isPlainObject(item) {
12
- if (!isObject(item))
13
- return false;
14
- // Handle special object types that should not be merged
15
- if (item instanceof Date)
16
- return false;
17
- if (item instanceof RegExp)
18
- return false;
19
- return true;
5
+ function t(t) {
6
+ return !(!e(t) || t instanceof Date || t instanceof RegExp);
20
7
  }
21
- /**
22
- * Resize and square-crop an image file for use as an avatar.
23
- *
24
- * The image is center-cropped to a square, scaled down to at most {@link size} pixels,
25
- * and converted to the specified output format.
26
- *
27
- * @param file - The source image file.
28
- * @param size - Max dimension in pixels for the output image.
29
- * @param extension - Output format. Use `"inherit"` to keep the original format.
30
- * @returns A promise that resolves to the processed `File`.
31
- */
32
- export function resizeAvatar(file, size = 256, extension = "png") {
33
- const MAX_SIZE = size;
34
- const resolvedExtension = extension === "inherit" ? file.name.split(".").pop() : extension;
35
- const mimeType = extension === "inherit"
36
- ? file.type
37
- : `image/${extension === "jpg" ? "jpeg" : extension}`;
38
- return new Promise((resolve, reject) => {
39
- const img = new Image();
40
- const url = URL.createObjectURL(file);
41
- img.onload = () => {
42
- URL.revokeObjectURL(url);
43
- const { naturalWidth: w, naturalHeight: h } = img;
44
- const side = Math.min(w, h);
45
- const cropX = (w - side) / 2;
46
- const cropY = (h - side) / 2;
47
- const outSize = Math.min(side, MAX_SIZE);
48
- const canvas = document.createElement("canvas");
49
- canvas.width = outSize;
50
- canvas.height = outSize;
51
- const ctx = canvas.getContext("2d");
52
- if (!ctx) {
53
- reject(new Error("Could not get canvas context"));
54
- return;
55
- }
56
- ctx.drawImage(img, cropX, cropY, side, side, 0, 0, outSize, outSize);
57
- canvas.toBlob((blob) => {
58
- if (!blob) {
59
- reject(new Error("Could not create blob from canvas"));
60
- return;
61
- }
62
- resolve(new File([blob], file.name.replace(/\.[^.]+$/, `.${resolvedExtension}`), {
63
- type: mimeType
64
- }));
65
- }, mimeType, 1);
66
- };
67
- img.onerror = () => {
68
- URL.revokeObjectURL(url);
69
- reject(new Error("Failed to load image"));
70
- };
71
- img.src = url;
72
- });
8
+ function n(e, t = 256, n = "png") {
9
+ let r = t, i = n === "inherit" ? e.name.split(".").pop() : n, a = n === "inherit" ? e.type : `image/${n === "jpg" ? "jpeg" : n}`;
10
+ return new Promise((t, n) => {
11
+ let o = new Image(), s = URL.createObjectURL(e);
12
+ o.onload = () => {
13
+ URL.revokeObjectURL(s);
14
+ let { naturalWidth: c, naturalHeight: l } = o, u = Math.min(c, l), d = (c - u) / 2, f = (l - u) / 2, p = Math.min(u, r), m = document.createElement("canvas");
15
+ m.width = p, m.height = p;
16
+ let h = m.getContext("2d");
17
+ if (!h) {
18
+ n(/* @__PURE__ */ Error("Could not get canvas context"));
19
+ return;
20
+ }
21
+ h.drawImage(o, d, f, u, u, 0, 0, p, p), m.toBlob((r) => {
22
+ if (!r) {
23
+ n(/* @__PURE__ */ Error("Could not create blob from canvas"));
24
+ return;
25
+ }
26
+ t(new File([r], e.name.replace(/\.[^.]+$/, `.${i}`), { type: a }));
27
+ }, a, 1);
28
+ }, o.onerror = () => {
29
+ URL.revokeObjectURL(s), n(/* @__PURE__ */ Error("Failed to load image"));
30
+ }, o.src = s;
31
+ });
73
32
  }
74
- /**
75
- * Convert a `File` to a base64-encoded data URL string.
76
- *
77
- * @param file - The file to encode.
78
- * @returns A promise that resolves to the base64 data URL.
79
- */
80
- export function fileToBase64(file) {
81
- return new Promise((resolve, reject) => {
82
- const reader = new FileReader();
83
- reader.onload = () => resolve(reader.result);
84
- reader.onerror = () => reject(new Error("Failed to read file"));
85
- reader.readAsDataURL(file);
86
- });
33
+ function r(e) {
34
+ return new Promise((t, n) => {
35
+ let r = new FileReader();
36
+ r.onload = () => t(r.result), r.onerror = () => n(/* @__PURE__ */ Error("Failed to read file")), r.readAsDataURL(e);
37
+ });
87
38
  }
88
- /**
89
- * Recursively merge `source` into `target`, producing a new object.
90
- *
91
- * - Plain objects are merged key-by-key; nested objects are merged recursively.
92
- * - `undefined` values in `source` are skipped (existing `target` values are preserved).
93
- * - Non-plain values (arrays, `Date`, `RegExp`, primitives, functions) in `source`
94
- * replace the corresponding `target` value outright.
95
- *
96
- * @param target - The base object.
97
- * @param source - Partial overrides to apply on top of `target`.
98
- * @returns A new merged object of type `T`.
99
- */
100
- export function deepmerge(target, source) {
101
- if (isPlainObject(target) && isPlainObject(source)) {
102
- const result = { ...target };
103
- for (const [key, value] of Object.entries(source)) {
104
- if (value === undefined)
105
- continue; // skip undefineds
106
- if (key in target) {
107
- result[key] = deepmerge(target[key], value);
108
- }
109
- else {
110
- result[key] = value;
111
- }
112
- }
113
- return result;
114
- }
115
- return source;
39
+ function i(e, n) {
40
+ if (t(e) && t(n)) {
41
+ let t = { ...e };
42
+ for (let [r, a] of Object.entries(n)) a !== void 0 && (r in e ? t[r] = i(e[r], a) : t[r] = a);
43
+ return t;
44
+ }
45
+ return n;
116
46
  }
47
+ //#endregion
48
+ export { i as deepmerge, r as fileToBase64, n as resizeAvatar };
@@ -1,14 +1,17 @@
1
- export const viewPaths = {
2
- auth: {
3
- signIn: "sign-in",
4
- signUp: "sign-up",
5
- magicLink: "magic-link",
6
- forgotPassword: "forgot-password",
7
- resetPassword: "reset-password",
8
- signOut: "sign-out"
9
- },
10
- settings: {
11
- account: "account",
12
- security: "security"
13
- }
1
+ //#region src/lib/view-paths.ts
2
+ var e = {
3
+ auth: {
4
+ signIn: "sign-in",
5
+ signUp: "sign-up",
6
+ magicLink: "magic-link",
7
+ forgotPassword: "forgot-password",
8
+ resetPassword: "reset-password",
9
+ signOut: "sign-out"
10
+ },
11
+ settings: {
12
+ account: "account",
13
+ security: "security"
14
+ }
14
15
  };
16
+ //#endregion
17
+ export { e as viewPaths };
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@better-auth-ui/core",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "type": "module",
5
5
  "scripts": {
6
- "build": "tsc",
6
+ "build": "vite build",
7
7
  "dev": "tsc --watch",
8
8
  "test": "vitest"
9
9
  },
@@ -15,16 +15,16 @@
15
15
  "types": "./dist/index.d.ts",
16
16
  "exports": {
17
17
  ".": {
18
- "import": "./dist/index.js",
19
- "types": "./dist/index.d.ts"
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
20
  }
21
21
  },
22
22
  "devDependencies": {
23
- "better-auth": "^1.6.4",
23
+ "better-auth": "^1.6.5",
24
24
  "vitest": "^4.1.4"
25
25
  },
26
26
  "peerDependencies": {
27
- "better-auth": ">=1.6.4"
27
+ "better-auth": ">=1.6.5"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
@@ -8,6 +8,7 @@ import type { AppearanceConfig } from "./appearance-config"
8
8
  import type { AvatarConfig } from "./avatar-config"
9
9
  import type { DeleteUserConfig } from "./delete-user-config"
10
10
  import type { EmailAndPasswordConfig } from "./email-and-password-config"
11
+ import type { UsernameConfig } from "./username-config"
11
12
 
12
13
  /**
13
14
  * Core authentication configuration interface.
@@ -74,6 +75,11 @@ export interface AuthConfig {
74
75
  * @remarks `ViewPaths`
75
76
  */
76
77
  viewPaths: ViewPaths
78
+ /**
79
+ * Username plugin configuration
80
+ * @remarks `UsernameConfig`
81
+ */
82
+ username: UsernameConfig
77
83
  /**
78
84
  * Function to navigate to a new path
79
85
  * @param options - Navigation options with href and optional replace flag
@@ -109,6 +115,13 @@ export const defaultAuthConfig: AuthConfig = {
109
115
  redirectTo: "/",
110
116
  viewPaths,
111
117
  localization,
118
+ username: {
119
+ enabled: false,
120
+ displayUsername: true,
121
+ isUsernameAvailable: true,
122
+ minUsernameLength: 3,
123
+ maxUsernameLength: 30
124
+ },
112
125
  navigate: ({ to, replace }) => {
113
126
  if (replace) {
114
127
  window.location.replace(to)
@@ -3,3 +3,4 @@ export * from "./auth-config"
3
3
  export * from "./avatar-config"
4
4
  export * from "./delete-user-config"
5
5
  export * from "./email-and-password-config"
6
+ export * from "./username-config"
@@ -0,0 +1,18 @@
1
+ export interface UsernameConfig {
2
+ /** Whether the username plugin is enabled */
3
+ enabled: boolean
4
+ /** Whether to use displayUsername for the visible username field */
5
+ displayUsername: boolean
6
+ /** Whether to check username availability on sign-up and user profile */
7
+ isUsernameAvailable: boolean
8
+ /**
9
+ * Minimum allowed username length
10
+ * @default 3
11
+ */
12
+ minUsernameLength: number
13
+ /**
14
+ * Maximum allowed username length
15
+ * @default 30
16
+ */
17
+ maxUsernameLength: number
18
+ }
@@ -111,6 +111,21 @@ export const localization = {
111
111
  /** @remarks `"Switch Account"` */
112
112
  switchAccount: "Switch Account",
113
113
 
114
+ /** @remarks `"Username"` */
115
+ username: "Username",
116
+
117
+ /** @remarks `"Username is available"` */
118
+ usernameAvailable: "Username is available",
119
+
120
+ /** @remarks `"Enter your username or email"` */
121
+ usernameOrEmailPlaceholder: "Enter your username or email",
122
+
123
+ /** @remarks `"Enter your username"` */
124
+ usernamePlaceholder: "Enter your username",
125
+
126
+ /** @remarks `"Username is already taken. Please try another."` */
127
+ usernameTaken: "Username is already taken. Please try another.",
128
+
114
129
  /** @remarks `"Verification email sent!"` */
115
130
  verificationEmailSent: "Verification email sent!",
116
131
 
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,5 +0,0 @@
1
- export * from "./appearance-config";
2
- export * from "./auth-config";
3
- export * from "./avatar-config";
4
- export * from "./delete-user-config";
5
- export * from "./email-and-password-config";