@umituz/react-native-auth 2.6.15 → 2.6.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-auth",
3
- "version": "2.6.15",
3
+ "version": "2.6.17",
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
@@ -170,6 +170,8 @@ export { ProfileSection } from './presentation/components/ProfileSection';
170
170
  export type { ProfileSectionConfig, ProfileSectionProps } from './presentation/components/ProfileSection';
171
171
  export { AccountActions } from './presentation/components/AccountActions';
172
172
  export type { AccountActionsConfig, AccountActionsProps } from './presentation/components/AccountActions';
173
+ export { UserProfileHeader } from './presentation/components/UserProfileHeader';
174
+ export type { UserProfileHeaderProps } from './presentation/components/UserProfileHeader';
173
175
 
174
176
  // =============================================================================
175
177
  // PRESENTATION LAYER - Stores
@@ -0,0 +1,166 @@
1
+ /**
2
+ * User Profile Header Component
3
+ * Displays user avatar, name, and ID
4
+ * Works for both guest and authenticated users
5
+ */
6
+
7
+ import React, { useCallback } from "react";
8
+ import { View, TouchableOpacity, StyleSheet } from "react-native";
9
+ import {
10
+ AtomicIcon,
11
+ AtomicText,
12
+ useAppDesignTokens,
13
+ } from "@umituz/react-native-design-system";
14
+ import { useNavigation } from "@react-navigation/native";
15
+ import { Avatar } from "@umituz/react-native-avatar";
16
+
17
+ export interface UserProfileHeaderProps {
18
+ /** User display name */
19
+ displayName?: string;
20
+ /** User ID */
21
+ userId?: string;
22
+ /** Whether user is anonymous (device-based ID) */
23
+ isAnonymous?: boolean;
24
+ /** Avatar URL (optional) */
25
+ avatarUrl?: string;
26
+ /** Navigation route for account settings */
27
+ accountSettingsRoute?: string;
28
+ /** Custom onPress handler */
29
+ onPress?: () => void;
30
+ /** Custom anonymous user display name */
31
+ anonymousDisplayName?: string;
32
+ /** Custom avatar service URL */
33
+ avatarServiceUrl?: string;
34
+ /** Default user display name when no displayName provided */
35
+ defaultUserDisplayName?: string;
36
+ /** Default anonymous display name */
37
+ defaultAnonymousDisplayName?: string;
38
+ }
39
+
40
+ export const UserProfileHeader: React.FC<UserProfileHeaderProps> = ({
41
+ displayName,
42
+ userId,
43
+ isAnonymous = false,
44
+ avatarUrl,
45
+ accountSettingsRoute,
46
+ onPress,
47
+ anonymousDisplayName,
48
+ avatarServiceUrl,
49
+ defaultUserDisplayName,
50
+ defaultAnonymousDisplayName,
51
+ }) => {
52
+ const tokens = useAppDesignTokens();
53
+ const navigation = useNavigation();
54
+ const colors = tokens.colors;
55
+ const spacing = tokens.spacing;
56
+ const finalDisplayName = displayName || (isAnonymous ? anonymousDisplayName || defaultAnonymousDisplayName || "Anonymous" : defaultUserDisplayName || "User");
57
+ const avatarName = isAnonymous ? anonymousDisplayName || defaultAnonymousDisplayName || "Anonymous" : finalDisplayName;
58
+
59
+ const handlePress = useCallback(() => {
60
+ if (onPress) {
61
+ onPress();
62
+ } else if (accountSettingsRoute) {
63
+ navigation.navigate(accountSettingsRoute as never);
64
+ }
65
+ }, [onPress, accountSettingsRoute, navigation]);
66
+
67
+ const shouldShowChevron = !!(onPress || accountSettingsRoute);
68
+ const isPressable = !!(onPress || accountSettingsRoute);
69
+
70
+ const containerStyle = [
71
+ styles.container,
72
+ {
73
+ backgroundColor: colors.surface,
74
+ paddingHorizontal: spacing.md,
75
+ paddingVertical: spacing.md,
76
+ marginHorizontal: spacing.md,
77
+ },
78
+ ];
79
+
80
+ const content = (
81
+ <>
82
+ <View style={styles.content}>
83
+ <View style={styles.avatarContainer}>
84
+ <Avatar
85
+ uri={avatarUrl}
86
+ name={avatarName}
87
+ size="lg"
88
+ shape="circle"
89
+ />
90
+ </View>
91
+ <View style={[styles.textContainer, { marginLeft: spacing.md }]}>
92
+ <AtomicText
93
+ type="headlineSmall"
94
+ style={[styles.name, { color: colors.textPrimary }]}
95
+ numberOfLines={1}
96
+ >
97
+ {finalDisplayName}
98
+ </AtomicText>
99
+ {userId && (
100
+ <AtomicText
101
+ type="bodySmall"
102
+ style={[styles.id, { color: colors.textSecondary }]}
103
+ numberOfLines={1}
104
+ >
105
+ {userId}
106
+ </AtomicText>
107
+ )}
108
+ </View>
109
+ </View>
110
+ <View style={[styles.chevronContainer, { marginLeft: spacing.sm }]}>
111
+ <AtomicIcon name="chevron-forward" size="md" color="onSurface" />
112
+ </View>
113
+ </>
114
+ );
115
+
116
+ if (isPressable) {
117
+ return (
118
+ <TouchableOpacity
119
+ style={containerStyle}
120
+ onPress={handlePress}
121
+ activeOpacity={0.7}
122
+ >
123
+ {content}
124
+ </TouchableOpacity>
125
+ );
126
+ }
127
+
128
+ return <View style={containerStyle}>{content}</View>;
129
+ };
130
+
131
+ const styles = StyleSheet.create({
132
+ container: {
133
+ flexDirection: "row",
134
+ alignItems: "center",
135
+ justifyContent: "space-between",
136
+ marginTop: 0,
137
+ marginBottom: 0,
138
+ borderRadius: 20,
139
+ minHeight: 80,
140
+ },
141
+ content: {
142
+ flexDirection: "row",
143
+ alignItems: "center",
144
+ flex: 1,
145
+ },
146
+ avatarContainer: {
147
+ justifyContent: "center",
148
+ alignItems: "center",
149
+ },
150
+ textContainer: {
151
+ flex: 1,
152
+ },
153
+ name: {
154
+ fontWeight: "700",
155
+ },
156
+ id: {
157
+ fontWeight: "500",
158
+ opacity: 0.7,
159
+ },
160
+ chevronContainer: {
161
+ justifyContent: "center",
162
+ alignItems: "center",
163
+ },
164
+ });
165
+
166
+
@@ -100,6 +100,22 @@ export function useAuthState(): UseAuthStateResult {
100
100
  };
101
101
  }, []);
102
102
 
103
+ // Debug logging in development
104
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
105
+ console.log("[useAuthState] Current state:", {
106
+ hasUser: !!user,
107
+ userUid: user?.uid,
108
+ userEmail: user?.email,
109
+ userIsAnonymous: user?.isAnonymous,
110
+ isAuthenticated,
111
+ isGuest,
112
+ loading,
113
+ firebaseLoading,
114
+ hasFirebaseUser: !!firebaseUser,
115
+ firebaseUserUid: firebaseUser?.uid,
116
+ });
117
+ }
118
+
103
119
  return {
104
120
  user,
105
121
  isAuthenticated,