@umituz/react-native-settings 5.2.52 → 5.3.1

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-settings",
3
- "version": "5.2.52",
3
+ "version": "5.3.1",
4
4
  "description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -20,6 +20,7 @@
20
20
  "./cloud-sync": "./src/domains/cloud-sync/index.ts",
21
21
  "./dev": "./src/domains/dev/index.ts",
22
22
  "./video-tutorials": "./src/domains/video-tutorials/index.ts",
23
+ "./account": "./src/account.ts",
23
24
  "./package.json": "./package.json"
24
25
  },
25
26
  "scripts": {
@@ -75,6 +76,11 @@
75
76
  "react-native-safe-area-context": ">=4.0.0",
76
77
  "zustand": ">=5.0.0"
77
78
  },
79
+ "peerDependenciesMeta": {
80
+ "@umituz/react-native-auth": {
81
+ "optional": true
82
+ }
83
+ },
78
84
  "devDependencies": {
79
85
  "@expo/vector-icons": "^15.0.0",
80
86
  "@gorhom/bottom-sheet": "^5.2.8",
package/src/account.ts ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @umituz/react-native-settings/account
3
+ *
4
+ * Subpath export for apps that use @umituz/react-native-auth.
5
+ * Import auth-dependent hooks and components from here.
6
+ *
7
+ * Usage:
8
+ * import {
9
+ * useSettingsScreenConfigWithAuth,
10
+ * AccountScreen,
11
+ * ProfileSection,
12
+ * } from '@umituz/react-native-settings/account';
13
+ *
14
+ * // Pass AccountScreen and ProfileSection as props to SettingsStackNavigator:
15
+ * <SettingsStackNavigator
16
+ * AccountScreenComponent={AccountScreen}
17
+ * ProfileSectionComponent={ProfileSection}
18
+ * ...
19
+ * />
20
+ */
21
+
22
+ import { useMemo } from "react";
23
+ import { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
24
+ import { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
25
+ import type { UseSettingsScreenConfigParams, SettingsScreenConfigResult } from './presentation/hooks/useSettingsScreenConfig';
26
+ import type { AppInfo } from './presentation/navigation/types';
27
+
28
+ // Auth components - inject these into SettingsStackNavigator props
29
+ export { AccountScreen, ProfileSection } from "@umituz/react-native-auth";
30
+
31
+ // Auth hooks (re-export for direct use if needed)
32
+ export { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
33
+
34
+ // Auth types
35
+ export type { AccountScreenConfig } from "@umituz/react-native-auth";
36
+
37
+ // Base hook (accepts authData param)
38
+ export { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
39
+
40
+ // Re-export types
41
+ export type {
42
+ UseSettingsScreenConfigParams,
43
+ SettingsScreenConfigResult,
44
+ SettingsFeatures,
45
+ AuthData,
46
+ } from './presentation/hooks/useSettingsScreenConfig';
47
+
48
+ export type { AccountConfig } from './presentation/navigation/types';
49
+
50
+ /**
51
+ * Convenience wrapper that auto-injects auth data from @umituz/react-native-auth.
52
+ * Drop-in replacement for the old useSettingsScreenConfig that called auth hooks internally.
53
+ *
54
+ * Usage:
55
+ * const { settingsConfig, userProfile, accountConfig, ... } = useSettingsScreenConfigWithAuth({ appInfo, ... });
56
+ */
57
+ export const useSettingsScreenConfigWithAuth = (
58
+ params: Omit<UseSettingsScreenConfigParams, 'authData'>
59
+ ): SettingsScreenConfigResult => {
60
+ const { user, loading, isAuthReady } = useAuth();
61
+ const userProfileData = useUserProfile({});
62
+ const { handleRatePress, handleSignOut, handleDeleteAccount, handleSignIn } =
63
+ useAuthHandlers(params.appInfo as AppInfo, params.translations?.errors);
64
+
65
+ const authData = useMemo(() => ({
66
+ user,
67
+ loading,
68
+ isAuthReady,
69
+ userProfileData,
70
+ handleRatePress,
71
+ handleSignOut,
72
+ handleDeleteAccount,
73
+ handleSignIn,
74
+ }), [user, loading, isAuthReady, userProfileData, handleRatePress, handleSignOut, handleDeleteAccount, handleSignIn]);
75
+
76
+ return useSettingsScreenConfig({
77
+ ...params,
78
+ authData,
79
+ });
80
+ };
package/src/index.ts CHANGED
@@ -37,11 +37,13 @@ export {
37
37
  useResetSettingsMutation
38
38
  } from './presentation/hooks/mutations/useSettingsMutations';
39
39
 
40
- export { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
40
+ // useSettingsScreenConfig is available from '@umituz/react-native-settings/account'
41
+ // for apps that use @umituz/react-native-auth
41
42
  export type {
42
43
  UseSettingsScreenConfigParams,
43
44
  SettingsScreenConfigResult,
44
45
  SettingsFeatures,
46
+ AuthData,
45
47
  } from './presentation/hooks/useSettingsScreenConfig';
46
48
 
47
49
 
@@ -2,20 +2,18 @@
2
2
  * useSettingsScreenConfig Hook
3
3
  *
4
4
  * One-stop hook for settings screen configuration.
5
- * Handles auth, feedback, and all settings config internally.
6
- * Apps pass subscription config from subscription package.
5
+ * Auth features are optional - pass authData for apps that use @umituz/react-native-auth.
6
+ * For apps WITH auth, use the convenience wrapper from '@umituz/react-native-settings/account'.
7
7
  */
8
8
 
9
9
  import { useMemo } from "react";
10
- import { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
11
10
  import { createUserProfileDisplay } from "../utils/userProfileUtils";
12
11
  import { createAccountConfig } from "../utils/accountConfigUtils";
13
12
  import { translateFAQData } from "../utils/faqTranslator";
14
13
  import { useSettingsConfigFactory } from "../utils/settingsConfigFactory";
15
14
  import type { SettingsConfig, SettingsTranslations } from "../screens/types";
16
15
  import type { FeedbackFormData } from "../utils/config-creators";
17
- import type { AppInfo, FAQData, UserProfileDisplay, AdditionalScreen } from "../navigation/types";
18
- import type { AccountScreenConfig } from "@umituz/react-native-auth";
16
+ import type { AppInfo, FAQData, UserProfileDisplay, AdditionalScreen, AccountConfig } from "../navigation/types";
19
17
 
20
18
  export interface SettingsFeatures {
21
19
  notifications?: boolean;
@@ -31,6 +29,18 @@ export interface SettingsFeatures {
31
29
  subscription?: boolean;
32
30
  }
33
31
 
32
+ /** Optional auth data - provide this if your app uses @umituz/react-native-auth */
33
+ export interface AuthData {
34
+ user: { displayName?: string | null; uid?: string; isAnonymous?: boolean; photoURL?: string | null } | null;
35
+ loading: boolean;
36
+ isAuthReady: boolean;
37
+ userProfileData: { displayName?: string; userId?: string; avatarUrl?: string } | null;
38
+ handleRatePress: () => void;
39
+ handleSignOut: () => Promise<void>;
40
+ handleDeleteAccount: () => Promise<void>;
41
+ handleSignIn: () => void;
42
+ }
43
+
34
44
  export interface UseSettingsScreenConfigParams {
35
45
  appInfo: AppInfo;
36
46
  faqData?: FAQData;
@@ -39,21 +49,38 @@ export interface UseSettingsScreenConfigParams {
39
49
  additionalScreens?: AdditionalScreen[];
40
50
  features?: SettingsFeatures;
41
51
  translations?: SettingsTranslations;
52
+ /** Auth data - optional. For apps with auth, provide this or use '@umituz/react-native-settings/account' */
53
+ authData?: AuthData;
42
54
  }
43
55
 
44
56
  export interface SettingsScreenConfigResult {
45
57
  settingsConfig: SettingsConfig;
46
58
  userProfile: UserProfileDisplay;
47
- accountConfig: AccountScreenConfig;
59
+ accountConfig: AccountConfig | null;
48
60
  translatedFaqData: FAQData | undefined;
49
61
  isLoading: boolean;
50
62
  isAuthReady: boolean;
51
63
  }
52
64
 
65
+ /** Default auth state for apps without authentication */
66
+ const DEFAULT_AUTH: AuthData = {
67
+ user: null,
68
+ loading: false,
69
+ isAuthReady: true,
70
+ userProfileData: null,
71
+ handleRatePress: () => {},
72
+ handleSignOut: async () => {},
73
+ handleDeleteAccount: async () => {},
74
+ handleSignIn: () => {},
75
+ };
76
+
53
77
  export const useSettingsScreenConfig = (
54
78
  params: UseSettingsScreenConfigParams
55
79
  ): SettingsScreenConfigResult => {
56
- const { appInfo, faqData, isPremium, onFeedbackSubmit, features = {}, translations } = params;
80
+ const { appInfo, faqData, isPremium, onFeedbackSubmit, features = {}, translations, authData } = params;
81
+
82
+ const auth = authData || DEFAULT_AUTH;
83
+ const { user, loading, isAuthReady, userProfileData, handleRatePress, handleSignOut, handleDeleteAccount, handleSignIn } = auth;
57
84
 
58
85
  const {
59
86
  notifications: showNotifications = true,
@@ -69,13 +96,6 @@ export const useSettingsScreenConfig = (
69
96
  subscription: showSubscription = true,
70
97
  } = features;
71
98
 
72
- const { user, loading, isAuthReady } = useAuth();
73
- const userProfileData = useUserProfile({});
74
-
75
- // Use centralized auth handlers
76
- const { handleRatePress, handleSignOut, handleDeleteAccount, handleSignIn } =
77
- useAuthHandlers(appInfo, translations?.errors);
78
-
79
99
  // Use settings config factory
80
100
  const baseSettingsConfig = useSettingsConfigFactory({
81
101
  onFeedbackSubmit,
@@ -136,21 +156,26 @@ export const useSettingsScreenConfig = (
136
156
  }, [baseSettingsConfig, translations]);
137
157
 
138
158
  const userProfile = useMemo(() => createUserProfileDisplay({
139
- profileData: userProfileData,
159
+ profileData: userProfileData || undefined,
140
160
  onSignIn: handleSignIn,
141
161
  }), [userProfileData, handleSignIn]);
142
162
 
143
- const accountConfig = useMemo(() => createAccountConfig({
144
- displayName: userProfileData?.displayName || user?.displayName || undefined,
145
- userId: userProfileData?.userId || user?.uid || undefined,
146
- photoURL: user?.photoURL || undefined,
147
- isAnonymous: user?.isAnonymous,
148
- avatarUrl: userProfileData?.avatarUrl,
149
- onSignIn: handleSignIn,
150
- onLogout: handleSignOut,
151
- onDeleteAccount: handleDeleteAccount,
152
- translations: translations?.account as any,
153
- }), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, translations]);
163
+ const accountConfig = useMemo(() => {
164
+ // Skip account config if no auth data is provided
165
+ if (!authData) return null;
166
+
167
+ return createAccountConfig({
168
+ displayName: userProfileData?.displayName || user?.displayName || undefined,
169
+ userId: userProfileData?.userId || user?.uid || undefined,
170
+ photoURL: user?.photoURL || undefined,
171
+ isAnonymous: user?.isAnonymous,
172
+ avatarUrl: userProfileData?.avatarUrl,
173
+ onSignIn: handleSignIn,
174
+ onLogout: handleSignOut,
175
+ onDeleteAccount: handleDeleteAccount,
176
+ translations: translations?.account as any,
177
+ });
178
+ }, [authData, user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, translations]);
154
179
 
155
180
  const translatedFaqData = useMemo(() =>
156
181
  translateFAQData(faqData, appInfo),
@@ -2,7 +2,6 @@ import { useMemo } from 'react';
2
2
  import type { StackScreen } from "@umituz/react-native-design-system";
3
3
  import { LanguageSelectionScreen } from "../../../domains/localization";
4
4
  import { NotificationSettingsScreen } from "../../../domains/notifications";
5
- import { AccountScreen } from "@umituz/react-native-auth";
6
5
  import { SettingsScreen } from "../../screens/SettingsScreen";
7
6
  import { AppearanceScreen } from "../../screens/AppearanceScreen";
8
7
  import { FAQScreen } from "../../../domains/faqs";
@@ -29,6 +28,8 @@ export interface UseSettingsScreensProps extends SettingsStackNavigatorProps {
29
28
  legalProps: LegalScreenProps;
30
29
  notificationTranslations: NotificationSettingsTranslations;
31
30
  quietHoursTranslations: QuietHoursTranslations;
31
+ /** Optional AccountScreen component from @umituz/react-native-auth. If not provided, account screen is skipped. */
32
+ AccountScreenComponent?: React.ComponentType<any>;
32
33
  }
33
34
 
34
35
  export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[] => {
@@ -51,6 +52,8 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
51
52
  gamificationConfig,
52
53
  videoTutorialConfig,
53
54
  accountConfig,
55
+ AccountScreenComponent,
56
+ ProfileSectionComponent,
54
57
  } = props;
55
58
 
56
59
  const translations = config?.translations?.features;
@@ -69,6 +72,7 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
69
72
  showHeader,
70
73
  showCloseButton,
71
74
  onClose,
75
+ ProfileSectionComponent,
72
76
  }
73
77
  );
74
78
 
@@ -119,8 +123,8 @@ export const useSettingsScreens = (props: UseSettingsScreensProps): StackScreen[
119
123
  });
120
124
 
121
125
  const accountScreen = createConditionalScreen(
122
- !!accountConfig,
123
- () => createScreenWithProps("Account", AccountScreen as any, { config: accountConfig })
126
+ !!(accountConfig && AccountScreenComponent),
127
+ () => createScreenWithProps("Account", AccountScreenComponent as any, { config: accountConfig })
124
128
  );
125
129
 
126
130
  const videoTutorialScreen = createScreenWithProps("VideoTutorial", VideoTutorialsScreen as any, {
@@ -88,11 +88,41 @@ export interface FAQData {
88
88
  }
89
89
 
90
90
  /**
91
- * Import AccountScreenConfig from auth package
91
+ * Account Configuration (locally defined to avoid hard dependency on auth package)
92
+ * Compatible with @umituz/react-native-auth's AccountScreenConfig
92
93
  */
93
- import type { AccountScreenConfig } from "@umituz/react-native-auth";
94
-
95
- export type AccountConfig = AccountScreenConfig;
94
+ export interface AccountConfig {
95
+ profile: {
96
+ displayName?: string;
97
+ userId?: string;
98
+ isAnonymous: boolean;
99
+ avatarUrl?: string;
100
+ accountSettingsRoute?: string;
101
+ benefits?: string[];
102
+ };
103
+ accountActions?: {
104
+ logoutText: string;
105
+ deleteAccountText: string;
106
+ changePasswordText?: string;
107
+ logoutConfirmTitle: string;
108
+ logoutConfirmMessage: string;
109
+ deleteConfirmTitle: string;
110
+ deleteConfirmMessage: string;
111
+ deleteErrorTitle?: string;
112
+ deleteErrorMessage?: string;
113
+ cancelText: string;
114
+ onLogout: () => Promise<void>;
115
+ onDeleteAccount: () => Promise<void>;
116
+ onChangePassword?: () => void;
117
+ showChangePassword?: boolean;
118
+ };
119
+ isAnonymous: boolean;
120
+ editProfileText?: string;
121
+ onEditProfile?: () => void;
122
+ onSignIn?: () => void;
123
+ title?: string;
124
+ PasswordPromptComponent?: React.ReactNode;
125
+ }
96
126
 
97
127
  /**
98
128
  * Settings Stack Navigator Props
@@ -115,4 +145,8 @@ export interface SettingsStackNavigatorProps {
115
145
  onClose?: () => void;
116
146
  gamificationConfig?: import("../../domains/gamification").GamificationSettingsConfig;
117
147
  videoTutorialConfig?: import("../../domains/video-tutorials").VideoTutorialsScreenProps;
148
+ /** Injected AccountScreen component from @umituz/react-native-auth (via account subpath). If not provided, account screen is not registered. */
149
+ AccountScreenComponent?: React.ComponentType<any>;
150
+ /** Injected ProfileSection component from @umituz/react-native-auth (via account subpath). If not provided, profile section is not rendered. */
151
+ ProfileSectionComponent?: React.ComponentType<any>;
118
152
  }
@@ -53,6 +53,8 @@ export interface SettingsScreenProps {
53
53
  showHeader?: boolean;
54
54
  /** Password prompt modal component */
55
55
  PasswordPromptComponent?: React.ReactNode;
56
+ /** Injected ProfileSection component from @umituz/react-native-auth (via account subpath) */
57
+ ProfileSectionComponent?: React.ComponentType<any>;
56
58
  }
57
59
 
58
60
  export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
@@ -72,6 +74,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
72
74
  devSettings,
73
75
  gamificationConfig,
74
76
  PasswordPromptComponent,
77
+ ProfileSectionComponent,
75
78
  } = props;
76
79
 
77
80
  const {
@@ -111,6 +114,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
111
114
  customSections={customSections}
112
115
  devSettings={devSettings}
113
116
  gamificationConfig={gamificationConfig}
117
+ ProfileSectionComponent={ProfileSectionComponent}
114
118
  />
115
119
  )}
116
120
  </ScreenLayout>
@@ -29,6 +29,7 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
29
29
  emptyStateText,
30
30
  devSettings,
31
31
  gamificationConfig,
32
+ ProfileSectionComponent,
32
33
  }) => {
33
34
  const translations = normalizedConfig.translations;
34
35
  const { level } = useGamification(gamificationConfig);
@@ -48,9 +49,10 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
48
49
  return (
49
50
  <View style={styles.container}>
50
51
  {showUserProfile && (
51
- <ProfileSectionLoader
52
- userProfile={userProfile}
52
+ <ProfileSectionLoader
53
+ userProfile={userProfile}
53
54
  translations={translations?.profile}
55
+ ProfileSectionComponent={ProfileSectionComponent}
54
56
  />
55
57
  )}
56
58
 
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
2
  import { View, StyleSheet } from "react-native";
3
- import { ProfileSection } from "@umituz/react-native-auth";
4
3
  import { useAppNavigation } from "@umituz/react-native-design-system";
5
4
 
6
5
  export interface ProfileSectionLoaderProps {
@@ -17,9 +16,11 @@ export interface ProfileSectionLoaderProps {
17
16
  anonymousName?: string;
18
17
  signIn?: string;
19
18
  };
19
+ /** Injected ProfileSection component from @umituz/react-native-auth (via account subpath) */
20
+ ProfileSectionComponent?: React.ComponentType<any>;
20
21
  }
21
22
 
22
- export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.memo(({ userProfile, translations }) => {
23
+ export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.memo(({ userProfile, translations, ProfileSectionComponent }) => {
23
24
  const navigation = useAppNavigation();
24
25
 
25
26
  const handlePress = React.useCallback(() => {
@@ -36,11 +37,11 @@ export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.m
36
37
  return translations?.anonymousName || "";
37
38
  }, [translations]);
38
39
 
39
- if (!userProfile) return null;
40
+ if (!userProfile || !ProfileSectionComponent) return null;
40
41
 
41
42
  return (
42
43
  <View style={styles.profileContainer}>
43
- <ProfileSection
44
+ <ProfileSectionComponent
44
45
  profile={{
45
46
  displayName: userProfile.displayName || anonymousDisplayName,
46
47
  userId: userProfile.userId,
@@ -56,7 +57,7 @@ export const ProfileSectionLoader: React.FC<ProfileSectionLoaderProps> = React.m
56
57
  />
57
58
  </View>
58
59
  );
59
- }, (prev, next) => prev.userProfile === next.userProfile && prev.translations === next.translations);
60
+ }, (prev, next) => prev.userProfile === next.userProfile && prev.translations === next.translations && prev.ProfileSectionComponent === next.ProfileSectionComponent);
60
61
 
61
62
  ProfileSectionLoader.displayName = "ProfileSectionLoader";
62
63
 
@@ -48,4 +48,6 @@ export interface SettingsContentProps {
48
48
  emptyStateText?: string;
49
49
  devSettings?: DevSettingsProps;
50
50
  gamificationConfig?: GamificationSettingsConfig;
51
+ /** Injected ProfileSection component from @umituz/react-native-auth (via account subpath) */
52
+ ProfileSectionComponent?: React.ComponentType<any>;
51
53
  }
@@ -4,7 +4,7 @@
4
4
  * Helper functions for creating account screen configurations.
5
5
  */
6
6
 
7
- import type { AccountScreenConfig } from "@umituz/react-native-auth";
7
+ import type { AccountConfig as AccountScreenConfig } from "../navigation/types";
8
8
 
9
9
  export interface AccountTranslations {
10
10
  editProfile?: string;