@umituz/react-native-auth 4.3.69 → 4.3.72

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/package.json +1 -1
  2. package/src/index.ts +1 -11
  3. package/src/infrastructure/services/AnonymousModeService.ts +9 -3
  4. package/src/infrastructure/services/AuthEventService.ts +3 -1
  5. package/src/infrastructure/services/AuthService.ts +3 -1
  6. package/src/infrastructure/utils/authStateHandler.ts +3 -1
  7. package/src/infrastructure/utils/calculators/index.ts +0 -6
  8. package/src/infrastructure/utils/calculators/passwordStrengthCalculator.ts +6 -34
  9. package/src/infrastructure/utils/calculators/userProfileCalculator.ts +0 -29
  10. package/src/infrastructure/utils/listener/authListenerStateHandler.ts +3 -1
  11. package/src/infrastructure/utils/listener/listenerState.util.ts +3 -1
  12. package/src/infrastructure/utils/listener/setupListener.ts +10 -4
  13. package/src/infrastructure/utils/safeCallback.ts +12 -4
  14. package/src/infrastructure/utils/validation/types.ts +7 -11
  15. package/src/init/createAuthInitModule.ts +9 -3
  16. package/src/presentation/components/AccountActions.tsx +19 -8
  17. package/src/presentation/components/AuthErrorDisplay.tsx +6 -5
  18. package/src/presentation/components/AuthHeader.tsx +11 -3
  19. package/src/presentation/components/AuthLink.tsx +7 -12
  20. package/src/presentation/components/PasswordMatchIndicator.tsx +5 -6
  21. package/src/presentation/components/PasswordStrengthIndicator.tsx +14 -17
  22. package/src/presentation/components/SocialLoginButtons.tsx +17 -12
  23. package/src/presentation/hooks/README.md +0 -57
  24. package/src/presentation/hooks/useAccountManagement.md +0 -1
  25. package/src/presentation/hooks/useLoginForm.ts +10 -1
  26. package/src/presentation/hooks/usePasswordPromptNavigation.ts +3 -1
  27. package/src/presentation/providers/AuthProvider.tsx +3 -1
  28. package/src/presentation/screens/AccountScreen.tsx +6 -3
  29. package/src/presentation/screens/LoginScreen.tsx +14 -5
  30. package/src/presentation/screens/RegisterScreen.tsx +14 -11
  31. package/src/presentation/stores/authModalStore.ts +6 -2
  32. package/src/presentation/utils/passwordPromptCallback.ts +3 -1
  33. package/src/presentation/hooks/useProfileEdit.ts +0 -83
  34. package/src/presentation/hooks/useSocialLogin.md +0 -381
  35. package/src/presentation/hooks/useSocialLogin.ts +0 -95
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "4.3.69",
3
+ "version": "4.3.72",
4
4
  "description": "Authentication service for React Native apps - Secure, type-safe, and production-ready. Provider-agnostic design with dependency injection, configurable validation, and comprehensive error handling.",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -32,7 +32,7 @@ export { initializeAuth, isAuthInitialized, resetAuthInitialization } from './in
32
32
  export type { InitializeAuthOptions } from './infrastructure/services/initializeAuth';
33
33
  export { validateEmail, validatePasswordForLogin, validatePasswordForRegister, validatePasswordConfirmation, validateDisplayName } from './infrastructure/utils/AuthValidation';
34
34
  export type { ValidationResult, PasswordStrengthResult, PasswordRequirements } from './infrastructure/utils/AuthValidation';
35
- export type { BaseValidationResult, FormValidationError, FormValidationResult } from './infrastructure/utils/validation/types';
35
+ export type { FormValidationError, FormValidationResult } from './infrastructure/utils/validation/types';
36
36
  export { SECURITY_LIMITS, sanitizeEmail, sanitizePassword, sanitizeName } from './infrastructure/utils/validation/sanitization';
37
37
  export type { SecurityLimitKey } from './infrastructure/utils/validation/sanitization';
38
38
  export { isEmpty, isEmptyEmail, isEmptyPassword, isEmptyName, isNotEmpty, hasContent } from './infrastructure/utils/validation/validationHelpers';
@@ -59,16 +59,10 @@ export {
59
59
  getFirstErrorMessage,
60
60
  // User Profile Calculator
61
61
  calculateUserProfileDisplay,
62
- calculateDisplayName,
63
- hasUserAvatar,
64
- getAvatarUrl,
65
62
  // Password Strength Calculator
66
63
  calculatePasswordRequirements,
67
64
  calculatePasswordsMatch,
68
- calculateConfirmationError,
69
- calculatePasswordValidity,
70
65
  calculatePasswordValidation,
71
- hasMinLength,
72
66
  calculatePasswordStrength,
73
67
  } from './infrastructure/utils/calculators';
74
68
 
@@ -89,10 +83,6 @@ export { useUserProfile } from './presentation/hooks/useUserProfile';
89
83
  export type { UserProfileData, UseUserProfileParams } from './presentation/hooks/useUserProfile';
90
84
  export { useAccountManagement } from './presentation/hooks/useAccountManagement';
91
85
  export type { UseAccountManagementReturn, UseAccountManagementOptions } from './presentation/hooks/useAccountManagement';
92
- export { useProfileEdit } from './presentation/hooks/useProfileEdit';
93
- export type { ProfileEditFormState, UseProfileEditReturn } from './presentation/hooks/useProfileEdit';
94
- export { useSocialLogin } from './presentation/hooks/useSocialLogin';
95
- export type { UseSocialLoginConfig, UseSocialLoginResult } from './presentation/hooks/useSocialLogin';
96
86
  export { useAppleAuth } from './presentation/hooks/useAppleAuth';
97
87
  export type { UseAppleAuthResult } from './presentation/hooks/useAppleAuth';
98
88
  export { useAuthBottomSheet } from './presentation/hooks/useAuthBottomSheet';
@@ -20,7 +20,9 @@ export class AnonymousModeService {
20
20
  this.isAnonymousMode = value === "true";
21
21
  return this.isAnonymousMode;
22
22
  } catch (error) {
23
- console.error('[AnonymousModeService] Failed to load state:', error instanceof Error ? error.message : String(error));
23
+ if (__DEV__) {
24
+ console.error('[AnonymousModeService] Failed to load state:', error instanceof Error ? error.message : String(error));
25
+ }
24
26
  this.isAnonymousMode = false;
25
27
  return false;
26
28
  }
@@ -31,7 +33,9 @@ export class AnonymousModeService {
31
33
  await storageProvider.set(this.storageKey, value.toString());
32
34
  return true;
33
35
  } catch (error) {
34
- console.error('[AnonymousModeService] Failed to save state:', error instanceof Error ? error.message : String(error));
36
+ if (__DEV__) {
37
+ console.error('[AnonymousModeService] Failed to save state:', error instanceof Error ? error.message : String(error));
38
+ }
35
39
  return false;
36
40
  }
37
41
  }
@@ -42,7 +46,9 @@ export class AnonymousModeService {
42
46
  this.isAnonymousMode = false;
43
47
  return true;
44
48
  } catch (error) {
45
- console.error('[AnonymousModeService] Failed to clear state:', error instanceof Error ? error.message : String(error));
49
+ if (__DEV__) {
50
+ console.error('[AnonymousModeService] Failed to clear state:', error instanceof Error ? error.message : String(error));
51
+ }
46
52
  return false;
47
53
  }
48
54
  }
@@ -101,7 +101,9 @@ class AuthEventService {
101
101
  try {
102
102
  listener(payload);
103
103
  } catch (error) {
104
- console.error(`[AuthEventService] Listener error for "${event}":`, error);
104
+ if (__DEV__) {
105
+ console.error(`[AuthEventService] Listener error for "${event}":`, error);
106
+ }
105
107
  }
106
108
  }
107
109
  }
@@ -82,7 +82,9 @@ export class AuthService {
82
82
  if (this.anonymousModeService.getIsAnonymousMode() && this.storageProvider) {
83
83
  const success = await this.anonymousModeService.clear(this.storageProvider);
84
84
  if (!success) {
85
- console.warn('[AuthService] Failed to clear anonymous mode from storage');
85
+ if (__DEV__) {
86
+ console.warn('[AuthService] Failed to clear anonymous mode from storage');
87
+ }
86
88
  // Force clear in memory to maintain consistency and prevent stale state
87
89
  // Storage clear failure shouldn't block auth flow, so we force update memory
88
90
  this.anonymousModeService.setAnonymousMode(false);
@@ -49,7 +49,9 @@ export function createAuthStateHandler(
49
49
  try {
50
50
  await ensureUserDocument(user, extras);
51
51
  } catch (error) {
52
- console.error('[AuthStateHandler] Failed to ensure user document:', error);
52
+ if (__DEV__) {
53
+ console.error('[AuthStateHandler] Failed to ensure user document:', error);
54
+ }
53
55
  // Continue execution - don't let user document creation failure block auth flow
54
56
  }
55
57
 
@@ -25,18 +25,12 @@ export {
25
25
  // User Profile Calculator
26
26
  export {
27
27
  calculateUserProfileDisplay,
28
- calculateDisplayName,
29
- hasUserAvatar,
30
- getAvatarUrl,
31
28
  } from "./userProfileCalculator";
32
29
 
33
30
  // Password Strength Calculator
34
31
  export {
35
32
  calculatePasswordRequirements,
36
33
  calculatePasswordsMatch,
37
- calculateConfirmationError,
38
- calculatePasswordValidity,
39
34
  calculatePasswordValidation,
40
- hasMinLength,
41
35
  calculatePasswordStrength,
42
36
  } from "./passwordStrengthCalculator";
@@ -50,31 +50,6 @@ export function calculatePasswordsMatch(
50
50
  return !!(password && confirmPassword && password === confirmPassword);
51
51
  }
52
52
 
53
- /**
54
- * Calculate password confirmation error
55
- */
56
- export function calculateConfirmationError(
57
- password: string,
58
- confirmPassword: string
59
- ): string | null {
60
- if (!confirmPassword) {
61
- return null;
62
- }
63
-
64
- const result = validatePasswordConfirmation(password, confirmPassword);
65
- return result.error ?? null;
66
- }
67
-
68
- /**
69
- * Calculate overall password validity
70
- */
71
- export function calculatePasswordValidity(
72
- requirements: PasswordRequirements,
73
- passwordsMatch: boolean
74
- ): boolean {
75
- return requirements.hasMinLength && passwordsMatch;
76
- }
77
-
78
53
  /**
79
54
  * Calculate all password validation state at once
80
55
  * More efficient than calling individual functions
@@ -91,10 +66,14 @@ export function calculatePasswordValidation(
91
66
  const passwordsMatch = calculatePasswordsMatch(password, confirmPassword);
92
67
 
93
68
  // Calculate confirmation error
94
- const confirmationError = calculateConfirmationError(password, confirmPassword);
69
+ let confirmationError: string | null = null;
70
+ if (confirmPassword) {
71
+ const result = validatePasswordConfirmation(password, confirmPassword);
72
+ confirmationError = result.error ?? null;
73
+ }
95
74
 
96
75
  // Calculate overall validity
97
- const isValid = calculatePasswordValidity(requirements, passwordsMatch);
76
+ const isValid = requirements.hasMinLength && passwordsMatch;
98
77
 
99
78
  return {
100
79
  requirements,
@@ -104,13 +83,6 @@ export function calculatePasswordValidation(
104
83
  };
105
84
  }
106
85
 
107
- /**
108
- * Quick check if password meets minimum length requirement
109
- */
110
- export function hasMinLength(password: string, minLength: number): boolean {
111
- return password.length >= minLength;
112
- }
113
-
114
86
  /**
115
87
  * Calculate password strength score (0-100)
116
88
  * Can be extended for more sophisticated strength calculation
@@ -46,32 +46,3 @@ export function calculateUserProfileDisplay(
46
46
  accountSettingsRoute: accountRoute,
47
47
  };
48
48
  }
49
-
50
- /**
51
- * Get display name for user
52
- * Extracts display name calculation for reusability
53
- */
54
- export function calculateDisplayName(
55
- user: AuthUser,
56
- anonymousDisplayName: string = "Anonymous User"
57
- ): string {
58
- if (user.isAnonymous) {
59
- return anonymousDisplayName;
60
- }
61
-
62
- return user.displayName || user.email || anonymousDisplayName;
63
- }
64
-
65
- /**
66
- * Check if user has avatar
67
- */
68
- export function hasUserAvatar(user: AuthUser): boolean {
69
- return !!user.photoURL;
70
- }
71
-
72
- /**
73
- * Get avatar URL if available
74
- */
75
- export function getAvatarUrl(user: AuthUser): string | undefined {
76
- return user.photoURL || undefined;
77
- }
@@ -42,7 +42,9 @@ export function handleAuthStateChange(
42
42
  // Call user callback with proper error handling for async callbacks
43
43
  safeCallbackSync(onAuthStateChange, [user], '[AuthListener]');
44
44
  } catch (error) {
45
- console.error("[AuthListener] Error handling auth state change:", error);
45
+ if (__DEV__) {
46
+ console.error("[AuthListener] Error handling auth state change:", error);
47
+ }
46
48
  // Ensure we don't leave the app in a bad state
47
49
  store.setInitialized(true);
48
50
  store.setLoading(false);
@@ -119,7 +119,9 @@ export function resetListenerState(): void {
119
119
  try {
120
120
  state.unsubscribe();
121
121
  } catch (error) {
122
- console.error('[ListenerState] Error during unsubscribe:', error);
122
+ if (__DEV__) {
123
+ console.error('[ListenerState] Error during unsubscribe:', error);
124
+ }
123
125
  }
124
126
  }
125
127
  state.initialized = false;
@@ -10,6 +10,8 @@ import { getAuthService } from "../../services/AuthService";
10
10
  import { completeInitialization, setUnsubscribe } from "./listenerState.util";
11
11
  import { handleAuthStateChange } from "./authListenerStateHandler";
12
12
 
13
+ const AUTH_LISTENER_TIMEOUT_MS = 10000;
14
+
13
15
  type StoreActions = AuthActions;
14
16
 
15
17
  /**
@@ -32,15 +34,17 @@ export function setupAuthListener(
32
34
  }
33
35
  }
34
36
 
35
- // Safety timeout: if listener doesn't trigger within 10 seconds, mark as initialized
37
+ // Safety timeout: if listener doesn't trigger within AUTH_LISTENER_TIMEOUT_MS, mark as initialized
36
38
  let hasTriggered = false;
37
39
  const timeout = setTimeout(() => {
38
40
  if (!hasTriggered) {
39
- console.warn("[AuthListener] Auth listener timeout - marking as initialized");
41
+ if (__DEV__) {
42
+ console.warn("[AuthListener] Auth listener timeout - marking as initialized");
43
+ }
40
44
  store.setInitialized(true);
41
45
  store.setLoading(false);
42
46
  }
43
- }, 10000);
47
+ }, AUTH_LISTENER_TIMEOUT_MS);
44
48
 
45
49
  try {
46
50
  const unsubscribe = onIdTokenChanged(auth, (user) => {
@@ -55,7 +59,9 @@ export function setupAuthListener(
55
59
  } catch (error) {
56
60
  clearTimeout(timeout);
57
61
  // If listener setup fails, ensure we clean up and mark as initialized
58
- console.error("[AuthListener] Failed to setup auth listener:", error);
62
+ if (__DEV__) {
63
+ console.error("[AuthListener] Failed to setup auth listener:", error);
64
+ }
59
65
  completeInitialization();
60
66
  store.setLoading(false);
61
67
  store.setInitialized(true);
@@ -34,12 +34,16 @@ export async function safeCallback<T extends unknown[]>(
34
34
  // If callback returns a promise, await it and catch rejections
35
35
  if (result && typeof result.then === 'function') {
36
36
  await result.catch((error) => {
37
- console.error(`${errorPrefix} User callback promise rejected:`, error);
37
+ if (__DEV__) {
38
+ console.error(`${errorPrefix} User callback promise rejected:`, error);
39
+ }
38
40
  });
39
41
  }
40
42
  } catch (error) {
41
43
  // Catch synchronous errors
42
- console.error(`${errorPrefix} User callback error:`, error);
44
+ if (__DEV__) {
45
+ console.error(`${errorPrefix} User callback error:`, error);
46
+ }
43
47
  }
44
48
  }
45
49
 
@@ -70,11 +74,15 @@ export function safeCallbackSync<T extends unknown[]>(
70
74
  // If callback returns a promise, catch rejections but don't await
71
75
  if (result && typeof result.then === 'function') {
72
76
  result.catch((error) => {
73
- console.error(`${errorPrefix} User callback promise rejected:`, error);
77
+ if (__DEV__) {
78
+ console.error(`${errorPrefix} User callback promise rejected:`, error);
79
+ }
74
80
  });
75
81
  }
76
82
  } catch (error) {
77
83
  // Catch synchronous errors
78
- console.error(`${errorPrefix} User callback error:`, error);
84
+ if (__DEV__) {
85
+ console.error(`${errorPrefix} User callback error:`, error);
86
+ }
79
87
  }
80
88
  }
@@ -3,19 +3,12 @@
3
3
  * Shared type definitions for validation results across the application
4
4
  */
5
5
 
6
- /**
7
- * Base validation result
8
- * Common interface for all validation results
9
- */
10
- export interface BaseValidationResult {
11
- isValid: boolean;
12
- }
13
-
14
6
  /**
15
7
  * Single field validation result
16
8
  * Used for validating individual fields (email, password, etc.)
17
9
  */
18
- export interface ValidationResult extends BaseValidationResult {
10
+ export interface ValidationResult {
11
+ isValid: boolean;
19
12
  error?: string;
20
13
  }
21
14
 
@@ -32,7 +25,8 @@ export interface FormValidationError {
32
25
  * Multi-field form validation result
33
26
  * Used for validating entire forms with multiple fields
34
27
  */
35
- export interface FormValidationResult extends BaseValidationResult {
28
+ export interface FormValidationResult {
29
+ isValid: boolean;
36
30
  errors: FormValidationError[];
37
31
  }
38
32
 
@@ -48,6 +42,8 @@ export interface PasswordRequirements {
48
42
  * Password strength validation result
49
43
  * Extends ValidationResult with password-specific requirements
50
44
  */
51
- export interface PasswordStrengthResult extends ValidationResult {
45
+ export interface PasswordStrengthResult {
46
+ isValid: boolean;
47
+ error?: string;
52
48
  requirements: PasswordRequirements;
53
49
  }
@@ -92,7 +92,9 @@ export function createAuthInitModule(
92
92
  try {
93
93
  await onRestorePurchases();
94
94
  } catch (error) {
95
- console.error('[AuthInitModule] Purchase restoration failed:', error instanceof Error ? error.message : String(error));
95
+ if (__DEV__) {
96
+ console.error('[AuthInitModule] Purchase restoration failed:', error instanceof Error ? error.message : String(error));
97
+ }
96
98
  }
97
99
  }
98
100
 
@@ -101,7 +103,9 @@ export function createAuthInitModule(
101
103
  try {
102
104
  await onUserConverted(anonymousId, authenticatedId);
103
105
  } catch (error) {
104
- console.error('[AuthInitModule] onUserConverted callback failed:', error instanceof Error ? error.message : String(error));
106
+ if (__DEV__) {
107
+ console.error('[AuthInitModule] onUserConverted callback failed:', error instanceof Error ? error.message : String(error));
108
+ }
105
109
  }
106
110
  }
107
111
  },
@@ -109,7 +113,9 @@ export function createAuthInitModule(
109
113
 
110
114
  return true;
111
115
  } catch (error) {
112
- console.error('[AuthInitModule] Auth initialization failed:', error instanceof Error ? error.message : String(error));
116
+ if (__DEV__) {
117
+ console.error('[AuthInitModule] Auth initialization failed:', error instanceof Error ? error.message : String(error));
118
+ }
113
119
  throw error;
114
120
  }
115
121
  },
@@ -1,4 +1,10 @@
1
- import React from "react";
1
+ /**
2
+ * Account Actions Component
3
+ * Logout and delete account actions
4
+ * PERFORMANCE: Memoized with useCallback for stable alert action handlers
5
+ */
6
+
7
+ import React, { memo, useCallback } from "react";
2
8
  import { View, TouchableOpacity, StyleSheet } from "react-native";
3
9
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
4
10
  import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system/atoms";
@@ -26,7 +32,7 @@ interface AccountActionsProps {
26
32
  config: AccountActionsConfig;
27
33
  }
28
34
 
29
- export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
35
+ export const AccountActions = memo<AccountActionsProps>(({ config }) => {
30
36
  const tokens = useAppDesignTokens();
31
37
  const alert = useAlert();
32
38
  const {
@@ -46,7 +52,8 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
46
52
  showChangePassword = false,
47
53
  } = config;
48
54
 
49
- const handleLogout = () => {
55
+ // PERFORMANCE: Stable callback references prevent unnecessary re-renders
56
+ const handleLogout = useCallback(() => {
50
57
  alert.show(AlertType.WARNING, AlertMode.MODAL, logoutConfirmTitle, logoutConfirmMessage, {
51
58
  actions: [
52
59
  { id: "cancel", label: cancelText, style: "secondary", onPress: () => {} },
@@ -58,15 +65,17 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
58
65
  try {
59
66
  await onLogout();
60
67
  } catch (error) {
61
- console.error('[AccountActions] Logout failed:', error instanceof Error ? error.message : String(error));
68
+ if (__DEV__) {
69
+ console.error('[AccountActions] Logout failed:', error instanceof Error ? error.message : String(error));
70
+ }
62
71
  }
63
72
  },
64
73
  },
65
74
  ],
66
75
  });
67
- };
76
+ }, [alert, logoutText, logoutConfirmTitle, logoutConfirmMessage, cancelText, onLogout]);
68
77
 
69
- const handleDeleteAccount = () => {
78
+ const handleDeleteAccount = useCallback(() => {
70
79
  alert.show(AlertType.ERROR, AlertMode.MODAL, deleteConfirmTitle, deleteConfirmMessage, {
71
80
  actions: [
72
81
  { id: "cancel", label: cancelText, style: "secondary", onPress: () => {} },
@@ -84,7 +93,7 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
84
93
  },
85
94
  ],
86
95
  });
87
- };
96
+ }, [alert, deleteAccountText, deleteConfirmTitle, deleteConfirmMessage, deleteErrorTitle, deleteErrorMessage, cancelText, onDeleteAccount]);
88
97
 
89
98
  return (
90
99
  <View style={styles.container}>
@@ -109,7 +118,9 @@ export const AccountActions: React.FC<AccountActionsProps> = ({ config }) => {
109
118
  </TouchableOpacity>
110
119
  </View>
111
120
  );
112
- };
121
+ });
122
+
123
+ AccountActions.displayName = 'AccountActions';
113
124
 
114
125
  const styles = StyleSheet.create({
115
126
  container: { gap: 12 },
@@ -1,18 +1,17 @@
1
1
  /**
2
2
  * Auth Error Display Component
3
3
  * Displays authentication errors using design system tokens
4
+ * PERFORMANCE: Memoized to prevent unnecessary re-renders when parent updates
4
5
  */
5
6
 
6
- import React from "react";
7
+ import React, { memo } from "react";
7
8
  import { AlertInline, AlertService, AlertMode } from "@umituz/react-native-design-system/molecules";
8
9
 
9
10
  interface AuthErrorDisplayProps {
10
11
  error: string | null;
11
12
  }
12
13
 
13
- export const AuthErrorDisplay: React.FC<AuthErrorDisplayProps> = ({
14
- error,
15
- }) => {
14
+ export const AuthErrorDisplay = memo<AuthErrorDisplayProps>(({ error }) => {
16
15
  const alert = React.useMemo(() => {
17
16
  if (!error) return null;
18
17
  return AlertService.createErrorAlert(error, undefined, {
@@ -25,7 +24,9 @@ export const AuthErrorDisplay: React.FC<AuthErrorDisplayProps> = ({
25
24
  }
26
25
 
27
26
  return <AlertInline alert={alert} />;
28
- };
27
+ });
28
+
29
+ AuthErrorDisplay.displayName = 'AuthErrorDisplay';
29
30
 
30
31
 
31
32
 
@@ -1,4 +1,10 @@
1
- import React from "react";
1
+ /**
2
+ * Auth Header Component
3
+ * Displays auth screen title and optional subtitle
4
+ * PERFORMANCE: Memoized to prevent unnecessary re-renders
5
+ */
6
+
7
+ import React, { memo } from "react";
2
8
  import { View, StyleSheet } from "react-native";
3
9
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
4
10
  import { AtomicText } from "@umituz/react-native-design-system/atoms";
@@ -8,7 +14,7 @@ interface AuthHeaderProps {
8
14
  subtitle?: string;
9
15
  }
10
16
 
11
- export const AuthHeader: React.FC<AuthHeaderProps> = ({ title, subtitle }) => {
17
+ export const AuthHeader = memo<AuthHeaderProps>(({ title, subtitle }) => {
12
18
  const tokens = useAppDesignTokens();
13
19
 
14
20
  return (
@@ -34,7 +40,9 @@ export const AuthHeader: React.FC<AuthHeaderProps> = ({ title, subtitle }) => {
34
40
  )}
35
41
  </View>
36
42
  );
37
- };
43
+ });
44
+
45
+ AuthHeader.displayName = 'AuthHeader';
38
46
 
39
47
  const styles = StyleSheet.create({
40
48
  header: {
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Auth Link Component
3
3
  * Link text with button for navigation between auth screens
4
+ * PERFORMANCE: Memoized to prevent unnecessary re-renders
4
5
  */
5
6
 
6
- import React from "react";
7
+ import React, { memo } from "react";
7
8
  import { View, StyleSheet } from "react-native";
8
9
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
9
10
  import { AtomicText, AtomicButton } from "@umituz/react-native-design-system/atoms";
@@ -15,20 +16,12 @@ interface AuthLinkProps {
15
16
  disabled?: boolean;
16
17
  }
17
18
 
18
- export const AuthLink: React.FC<AuthLinkProps> = ({
19
- text,
20
- linkText,
21
- onPress,
22
- disabled = false,
23
- }) => {
19
+ export const AuthLink = memo<AuthLinkProps>(({ text, linkText, onPress, disabled = false }) => {
24
20
  const tokens = useAppDesignTokens();
25
21
 
26
22
  return (
27
23
  <View style={[styles.container, { marginTop: tokens.spacing.xs, paddingTop: tokens.spacing.xs }]}>
28
- <AtomicText
29
- type="bodyMedium"
30
- color="textSecondary"
31
- >
24
+ <AtomicText type="bodyMedium" color="textSecondary">
32
25
  {text}{" "}
33
26
  </AtomicText>
34
27
  <AtomicButton
@@ -41,7 +34,9 @@ export const AuthLink: React.FC<AuthLinkProps> = ({
41
34
  </AtomicButton>
42
35
  </View>
43
36
  );
44
- };
37
+ });
38
+
39
+ AuthLink.displayName = 'AuthLink';
45
40
 
46
41
  const styles = StyleSheet.create({
47
42
  container: {
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { memo } from "react";
2
2
  import { View, StyleSheet } from "react-native";
3
3
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
4
4
  import { AtomicText } from "@umituz/react-native-design-system/atoms";
@@ -13,10 +13,7 @@ interface PasswordMatchIndicatorProps {
13
13
  isMatch: boolean;
14
14
  }
15
15
 
16
- export const PasswordMatchIndicator: React.FC<PasswordMatchIndicatorProps> = ({
17
- translations,
18
- isMatch,
19
- }) => {
16
+ export const PasswordMatchIndicator = memo<PasswordMatchIndicatorProps>(({ translations, isMatch }) => {
20
17
  const tokens = useAppDesignTokens();
21
18
  const color = isMatch ? tokens.colors.success : tokens.colors.error;
22
19
  const text = isMatch ? translations.match : translations.noMatch;
@@ -27,7 +24,9 @@ export const PasswordMatchIndicator: React.FC<PasswordMatchIndicatorProps> = ({
27
24
  <AtomicText type="labelSmall" style={{ color }}>{text}</AtomicText>
28
25
  </View>
29
26
  );
30
- };
27
+ });
28
+
29
+ PasswordMatchIndicator.displayName = 'PasswordMatchIndicator';
31
30
 
32
31
  const styles = StyleSheet.create({
33
32
  container: {