@umituz/web-dashboard 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +4 -3
  2. package/package.json +2 -12
  3. package/src/index.ts +0 -10
  4. package/src/styles/dashboard.css +93 -544
  5. package/src/domains/auth/components/AuthLayout.tsx +0 -99
  6. package/src/domains/auth/components/ForgotPasswordForm.tsx +0 -167
  7. package/src/domains/auth/components/LoginForm.tsx +0 -222
  8. package/src/domains/auth/components/RegisterForm.tsx +0 -281
  9. package/src/domains/auth/components/ResetPasswordForm.tsx +0 -173
  10. package/src/domains/auth/components/index.ts +0 -11
  11. package/src/domains/auth/components/shared/AuthErrorBanner.tsx +0 -25
  12. package/src/domains/auth/components/shared/EmailInput.tsx +0 -73
  13. package/src/domains/auth/components/shared/PasswordInput.tsx +0 -100
  14. package/src/domains/auth/components/shared/PasswordStrengthIndicator.tsx +0 -63
  15. package/src/domains/auth/components/shared/SocialLoginButtons.tsx +0 -44
  16. package/src/domains/auth/components/shared/SocialProviderIcons.tsx +0 -48
  17. package/src/domains/auth/components/shared/index.ts +0 -20
  18. package/src/domains/auth/hooks/index.ts +0 -8
  19. package/src/domains/auth/hooks/useAuth.ts +0 -230
  20. package/src/domains/auth/index.ts +0 -62
  21. package/src/domains/auth/types/auth.ts +0 -302
  22. package/src/domains/auth/types/index.ts +0 -25
  23. package/src/domains/auth/utils/auth.test.ts +0 -188
  24. package/src/domains/auth/utils/auth.ts +0 -221
  25. package/src/domains/auth/utils/i18nKeys.ts +0 -109
  26. package/src/domains/auth/utils/index.ts +0 -29
  27. package/src/domains/auth/utils/secureToken.ts +0 -33
  28. package/src/domains/auth/utils/validationKeys.ts +0 -23
  29. package/src/domains/session/DemoLogin.tsx +0 -42
  30. package/src/domains/session/OrgSwitcher.tsx +0 -102
  31. package/src/domains/session/SessionContext.tsx +0 -150
  32. package/src/domains/session/inMemoryAuthAdapter.ts +0 -53
  33. package/src/domains/session/index.ts +0 -18
  34. package/src/domains/session/types.ts +0 -47
  35. package/src/domains/session/utils/i18nKeys.ts +0 -12
@@ -1,302 +0,0 @@
1
- /**
2
- * Auth Types
3
- *
4
- * Type definitions for authentication system
5
- */
6
-
7
- import type { ComponentType, ReactElement } from "react";
8
-
9
- /**
10
- * Translation function contract. Auth components stay i18n-agnostic;
11
- * the consumer plugs in their i18n library of choice.
12
- * Interpolation params follow the i18next convention (`{{placeholder}}`).
13
- */
14
- export type Translate = (key: string, params?: Record<string, unknown>) => string;
15
-
16
- /**
17
- * User credentials for login
18
- */
19
- export interface LoginCredentials {
20
- /** Email address */
21
- email: string;
22
- /** Password */
23
- password: string;
24
- }
25
-
26
- /**
27
- * Registration data
28
- */
29
- export interface RegisterData {
30
- /** Email address */
31
- email: string;
32
- /** Password */
33
- password: string;
34
- /** Full name */
35
- name?: string;
36
- /** Additional user data */
37
- metadata?: Record<string, unknown>;
38
- }
39
-
40
- /**
41
- * Password reset request
42
- */
43
- export interface ForgotPasswordData {
44
- /** Email address */
45
- email: string;
46
- }
47
-
48
- /**
49
- * Password reset confirmation
50
- */
51
- export interface ResetPasswordData {
52
- /** Reset token from email */
53
- token: string;
54
- /** New password */
55
- password: string;
56
- /** Password confirmation */
57
- confirmPassword: string;
58
- }
59
-
60
- /**
61
- * Auth state
62
- */
63
- export interface AuthState {
64
- /** Is user authenticated */
65
- isAuthenticated: boolean;
66
- /** Current user data */
67
- user: User | null;
68
- /** Is authentication loading */
69
- isLoading: boolean;
70
- /** Authentication error */
71
- error: string | null;
72
- }
73
-
74
- /**
75
- * User profile
76
- */
77
- export interface User {
78
- /** Unique user ID */
79
- id: string;
80
- /** Email address */
81
- email: string;
82
- /** Display name */
83
- name?: string;
84
- /** Profile avatar URL */
85
- avatar?: string;
86
- /** Email verification status */
87
- emailVerified?: boolean;
88
- /** Additional user data */
89
- metadata?: Record<string, unknown>;
90
- /** Account creation date */
91
- createdAt?: string;
92
- /** Last login date */
93
- lastLoginAt?: string;
94
- }
95
-
96
- /**
97
- * Auth actions
98
- */
99
- export interface AuthActions {
100
- /** Login with email/password */
101
- login: (credentials: LoginCredentials) => Promise<User>;
102
- /** Register new account */
103
- register: (data: RegisterData) => Promise<User>;
104
- /** Logout current user */
105
- logout: () => Promise<void>;
106
- /** Send password reset email */
107
- forgotPassword: (data: ForgotPasswordData) => Promise<void>;
108
- /** Reset password with token */
109
- resetPassword: (data: ResetPasswordData) => Promise<void>;
110
- /** Update user profile */
111
- updateProfile: (data: Partial<User>) => Promise<User>;
112
- /** Refresh authentication session */
113
- refresh: () => Promise<User | null>;
114
- }
115
-
116
- /**
117
- * Auth component props
118
- */
119
- export interface AuthComponentProps {
120
- /** Current auth state */
121
- authState: AuthState;
122
- /** Auth actions */
123
- authActions: AuthActions;
124
- /** Update auth state */
125
- setAuthState: (state: Partial<AuthState>) => void;
126
- }
127
-
128
- /**
129
- * Auth step configuration
130
- */
131
- export interface AuthStep {
132
- /** Step identifier */
133
- id: string;
134
- /** Step title */
135
- title: string;
136
- /** Step description */
137
- description?: string;
138
- /** Custom component */
139
- component?: ComponentType<AuthComponentProps> | ReactElement;
140
- /** Validation function */
141
- validate?: (data: Record<string, unknown>) => boolean;
142
- }
143
-
144
- /**
145
- * Auth configuration
146
- */
147
- export interface AuthConfig {
148
- /** Brand/application name */
149
- brandName: string;
150
- /** Brand tagline */
151
- brandTagline?: string;
152
- /** Login route */
153
- loginRoute: string;
154
- /** Register route */
155
- registerRoute: string;
156
- /** Forgot password route */
157
- forgotPasswordRoute?: string;
158
- /** Route after successful login */
159
- afterLoginRoute: string;
160
- /** Route after logout */
161
- afterLogoutRoute: string;
162
- /** Show social login options */
163
- showSocialLogin?: boolean;
164
- /** Available social providers */
165
- socialProviders?: SocialProvider[];
166
- /** Public home route (header "back" link). Falls back to `afterLoginRoute`. */
167
- homeRoute?: string;
168
- /** Footer links (rendered only when provided — no defaults that 404) */
169
- footerLinks?: Array<{ label: string; href: string }>;
170
- /** Enable remember me */
171
- enableRememberMe?: boolean;
172
- /** Enable email verification */
173
- requireEmailVerification?: boolean;
174
- /** Auth steps (for multi-step onboarding) */
175
- steps?: AuthStep[];
176
- /** Additional configuration */
177
- metadata?: Record<string, unknown>;
178
- }
179
-
180
- /**
181
- * Social login provider
182
- */
183
- export interface SocialProvider {
184
- /** Provider ID */
185
- id: string;
186
- /** Display name */
187
- name: string;
188
- /** Icon/emoji */
189
- icon: string;
190
- /** Color theme */
191
- color?: string;
192
- /** Scopes to request */
193
- scopes?: string[];
194
- }
195
-
196
- /**
197
- * Auth layout props
198
- */
199
- export interface AuthLayoutProps {
200
- /** Auth configuration */
201
- config: AuthConfig;
202
- /** Current auth state */
203
- authState?: AuthState;
204
- /** Auth actions */
205
- authActions?: AuthActions;
206
- /** Optional translation function for layout strings (falls back to embedded English) */
207
- translate?: Translate;
208
- /** Social provider login handler (receives the provider id) */
209
- onSocialLogin?: (providerId: string) => void | Promise<void>;
210
- /** Children content */
211
- children?: React.ReactNode;
212
- }
213
-
214
- /**
215
- * Login form props
216
- */
217
- export interface LoginFormProps {
218
- /** Auth configuration */
219
- config: AuthConfig;
220
- /** Initial credentials */
221
- defaultCredentials?: Partial<LoginCredentials>;
222
- /** Show remember me checkbox */
223
- showRememberMe?: boolean;
224
- /** Show forgot password link */
225
- showForgotPassword?: boolean;
226
- /** Show register link */
227
- showRegisterLink?: boolean;
228
- /** Show social login buttons */
229
- showSocialLogin?: boolean;
230
- /**
231
- * Allow the built-in mock login (accepts ANY credentials) for demos.
232
- * Defaults to false — without `onLoginAttempt` the form reports a
233
- * configuration error instead of silently "logging in".
234
- */
235
- enableMockAuth?: boolean;
236
- /** Custom login handler (receives credentials, returns user) */
237
- onLoginAttempt?: (credentials: LoginCredentials) => Promise<User>;
238
- /** On successful login (called after onLoginAttempt or mock auth succeeds) */
239
- onLoginSuccess?: (user: User) => void | Promise<void>;
240
- /** On login error */
241
- onLoginError?: (error: string) => void;
242
- /** Google login handler */
243
- onGoogleLogin?: () => void | Promise<void>;
244
- /** Apple login handler */
245
- onAppleLogin?: () => void | Promise<void>;
246
- }
247
-
248
- /**
249
- * Register form props
250
- */
251
- export interface RegisterFormProps {
252
- /** Auth configuration */
253
- config: AuthConfig;
254
- /** Initial registration data */
255
- defaultData?: Partial<RegisterData>;
256
- /** Show terms checkbox */
257
- showTerms?: boolean;
258
- /** Show login link */
259
- showLoginLink?: boolean;
260
- /** Require password confirmation */
261
- requirePasswordConfirm?: boolean;
262
- /** Show social login buttons */
263
- showSocialLogin?: boolean;
264
- /** Custom register handler (receives register data, returns user) - overrides mock auth */
265
- onRegisterAttempt?: (data: RegisterData) => Promise<User>;
266
- /** On successful registration (called after onRegisterAttempt or mock auth succeeds) */
267
- onRegisterSuccess?: (user: User) => void | Promise<void>;
268
- /** On registration error */
269
- onRegisterError?: (error: string) => void;
270
- /** Google login handler */
271
- onGoogleLogin?: () => void | Promise<void>;
272
- /** Apple login handler */
273
- onAppleLogin?: () => void | Promise<void>;
274
- }
275
-
276
- /**
277
- * Forgot password form props
278
- */
279
- export interface ForgotPasswordFormProps {
280
- /** Auth configuration */
281
- config: AuthConfig;
282
- /** Submit handler — receives the entered email and performs the reset request */
283
- onSuccess?: (data: { email: string }) => void | Promise<void>;
284
- /** On error */
285
- onError?: (error: string) => void;
286
- /** Show back to login link */
287
- showBackLink?: boolean;
288
- }
289
-
290
- /**
291
- * Reset password form props
292
- */
293
- export interface ResetPasswordFormProps {
294
- /** Auth configuration */
295
- config: AuthConfig;
296
- /** Reset token */
297
- token: string;
298
- /** Submit handler — receives the token and the new password */
299
- onSuccess?: (data: { token: string; password: string }) => void | Promise<void>;
300
- /** On error */
301
- onError?: (error: string) => void;
302
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * Auth Types
3
- *
4
- * Export all auth-related types
5
- */
6
-
7
- export type {
8
- LoginCredentials,
9
- RegisterData,
10
- ForgotPasswordData,
11
- ResetPasswordData,
12
- AuthState,
13
- User,
14
- AuthActions,
15
- AuthComponentProps,
16
- AuthStep,
17
- AuthConfig,
18
- SocialProvider,
19
- AuthLayoutProps,
20
- LoginFormProps,
21
- RegisterFormProps,
22
- ForgotPasswordFormProps,
23
- ResetPasswordFormProps,
24
- Translate,
25
- } from "./auth";
@@ -1,188 +0,0 @@
1
- /**
2
- * Tests for pure auth utility functions.
3
- */
4
-
5
- import { describe, it, expect } from "vitest";
6
- import {
7
- isValidEmail,
8
- isValidPassword,
9
- validateLogin,
10
- validateRegister,
11
- validateResetPassword,
12
- getUserDisplayName,
13
- getUserInitials,
14
- calculatePasswordStrength,
15
- getPasswordStrengthBand,
16
- maskEmail,
17
- sanitizeInput,
18
- } from "./auth";
19
- import { generateResetToken } from "./secureToken";
20
- import { AUTH_VALIDATION_KEYS } from "./validationKeys";
21
-
22
- describe("isValidEmail", () => {
23
- it("accepts plain addresses", () => {
24
- expect(isValidEmail("user@example.com")).toBe(true);
25
- });
26
-
27
- it("rejects missing local part, domain, or TLD", () => {
28
- expect(isValidEmail("@example.com")).toBe(false);
29
- expect(isValidEmail("user@")).toBe(false);
30
- expect(isValidEmail("user@example")).toBe(false);
31
- expect(isValidEmail("user example.com")).toBe(false);
32
- });
33
- });
34
-
35
- describe("isValidPassword", () => {
36
- it("enforces the minimum length", () => {
37
- expect(isValidPassword("short")).toBe(false);
38
- expect(isValidPassword("longenough")).toBe(true);
39
- });
40
-
41
- it("honors a custom minimum", () => {
42
- expect(isValidPassword("12345678", 12)).toBe(false);
43
- expect(isValidPassword("123456789012", 12)).toBe(true);
44
- });
45
- });
46
-
47
- describe("validateLogin", () => {
48
- it("passes valid credentials", () => {
49
- expect(validateLogin({ email: "a@b.co", password: "x".repeat(8) })).toEqual({ valid: true });
50
- });
51
-
52
- it("requires an email first", () => {
53
- expect(validateLogin({ email: "", password: "x" })).toEqual({
54
- valid: false,
55
- error: AUTH_VALIDATION_KEYS.emailRequired,
56
- });
57
- });
58
-
59
- it("rejects a malformed email", () => {
60
- expect(validateLogin({ email: "nope", password: "x" })).toEqual({
61
- valid: false,
62
- error: AUTH_VALIDATION_KEYS.emailInvalid,
63
- });
64
- });
65
-
66
- it("requires a password", () => {
67
- expect(validateLogin({ email: "a@b.co", password: "" })).toEqual({
68
- valid: false,
69
- error: AUTH_VALIDATION_KEYS.passwordRequired,
70
- });
71
- });
72
- });
73
-
74
- describe("validateRegister", () => {
75
- const base = { email: "a@b.co", password: "longenough1" };
76
-
77
- it("passes with minimal data", () => {
78
- expect(validateRegister(base)).toEqual({ valid: true });
79
- });
80
-
81
- it("requires a name when asked to", () => {
82
- expect(validateRegister(base, true)).toEqual({
83
- valid: false,
84
- error: AUTH_VALIDATION_KEYS.nameRequired,
85
- });
86
- });
87
-
88
- it("enforces password length", () => {
89
- expect(validateRegister({ ...base, password: "short" })).toEqual({
90
- valid: false,
91
- error: AUTH_VALIDATION_KEYS.passwordTooShort,
92
- });
93
- });
94
-
95
- it("checks confirmation when required", () => {
96
- expect(
97
- validateRegister({ ...base, confirmPassword: "different" }, false, true),
98
- ).toEqual({
99
- valid: false,
100
- error: AUTH_VALIDATION_KEYS.passwordsDoNotMatch,
101
- });
102
- });
103
-
104
- it("accepts matching confirmation when required (the RegisterForm call shape)", () => {
105
- expect(
106
- validateRegister({ ...base, name: "A", confirmPassword: base.password }, false, true),
107
- ).toEqual({ valid: true });
108
- });
109
- });
110
-
111
- describe("validateResetPassword", () => {
112
- const base = { token: "tok", password: "longenough", confirmPassword: "longenough" };
113
-
114
- it("passes matching valid data", () => {
115
- expect(validateResetPassword(base)).toEqual({ valid: true });
116
- });
117
-
118
- it("requires a token", () => {
119
- expect(validateResetPassword({ ...base, token: "" })).toEqual({
120
- valid: false,
121
- error: AUTH_VALIDATION_KEYS.invalidResetToken,
122
- });
123
- });
124
-
125
- it("rejects mismatched confirmation", () => {
126
- expect(validateResetPassword({ ...base, confirmPassword: "other" })).toEqual({
127
- valid: false,
128
- error: AUTH_VALIDATION_KEYS.passwordsDoNotMatch,
129
- });
130
- });
131
- });
132
-
133
- describe("display helpers", () => {
134
- it("getUserDisplayName prefers name, then email, then null", () => {
135
- expect(getUserDisplayName({ id: "1", name: "Ada", email: "a@b.co" } as never)).toBe("Ada");
136
- expect(getUserDisplayName({ id: "1", email: "a@b.co" } as never)).toBe("a@b.co");
137
- expect(getUserDisplayName(null)).toBeNull();
138
- });
139
-
140
- it("getUserInitials uses first and last name parts", () => {
141
- expect(getUserInitials({ id: "1", name: "Ada Lovelace" } as never)).toBe("AL");
142
- expect(getUserInitials({ id: "1", name: "ada" } as never)).toBe("AD");
143
- expect(getUserInitials(null)).toBeNull();
144
- });
145
- });
146
-
147
- describe("password strength", () => {
148
- it("scores a strong password at 100", () => {
149
- expect(calculatePasswordStrength("Str0ng!Password")).toBe(100);
150
- expect(getPasswordStrengthBand("Str0ng!Password")).toBe("strong");
151
- });
152
-
153
- it("scores a weak password low", () => {
154
- expect(getPasswordStrengthBand("abc")).toBe("weak");
155
- });
156
-
157
- it("never exceeds 100", () => {
158
- expect(calculatePasswordStrength("aaaaaaaaaaaaaaaaaaaa!A1")).toBeLessThanOrEqual(100);
159
- });
160
- });
161
-
162
- describe("maskEmail", () => {
163
- it("masks the local part", () => {
164
- expect(maskEmail("umit@example.com")).toBe("u***@example.com");
165
- });
166
-
167
- it("returns null for invalid input", () => {
168
- expect(maskEmail("not-an-email")).toBeNull();
169
- });
170
- });
171
-
172
- describe("sanitizeInput", () => {
173
- it("trims and truncates", () => {
174
- expect(sanitizeInput(" hello ")).toBe("hello");
175
- expect(sanitizeInput("abcdef", 3)).toBe("abc");
176
- });
177
- });
178
-
179
- describe("generateResetToken", () => {
180
- it("produces a hex string of 2 * length chars", () => {
181
- const token = generateResetToken(16);
182
- expect(token).toMatch(/^[0-9a-f]{32}$/);
183
- });
184
-
185
- it("produces different tokens on each call", () => {
186
- expect(generateResetToken()).not.toBe(generateResetToken());
187
- });
188
- });