@umituz/react-native-settings 1.4.1 → 1.6.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.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Settings Section Component
3
+ * Single Responsibility: Render a settings section with title and container
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, Text, StyleSheet } from "react-native";
8
+ import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
9
+
10
+ export interface SettingsSectionProps {
11
+ /** Section title */
12
+ title: string;
13
+ /** Section content */
14
+ children: React.ReactNode;
15
+ }
16
+
17
+ export const SettingsSection: React.FC<SettingsSectionProps> = ({
18
+ title,
19
+ children,
20
+ }) => {
21
+ const tokens = useAppDesignTokens();
22
+ const colors = tokens.colors;
23
+
24
+ return (
25
+ <View style={styles.container}>
26
+ <Text style={[styles.title, { color: colors.textSecondary }]}>
27
+ {title}
28
+ </Text>
29
+ <View
30
+ style={[
31
+ styles.content,
32
+ { backgroundColor: `${colors.textSecondary}10` },
33
+ ]}
34
+ >
35
+ {children}
36
+ </View>
37
+ </View>
38
+ );
39
+ };
40
+
41
+ const styles = StyleSheet.create({
42
+ container: {
43
+ marginBottom: 24,
44
+ },
45
+ title: {
46
+ fontSize: 12,
47
+ fontWeight: "700",
48
+ textTransform: "uppercase",
49
+ letterSpacing: 1,
50
+ paddingHorizontal: 16,
51
+ paddingBottom: 8,
52
+ },
53
+ content: {
54
+ borderRadius: 12,
55
+ marginHorizontal: 16,
56
+ overflow: "hidden",
57
+ },
58
+ });
59
+
@@ -0,0 +1,129 @@
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 from "react";
8
+ import { View, Text, TouchableOpacity, StyleSheet, Image } from "react-native";
9
+ import { ChevronRight } from "lucide-react-native";
10
+ import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
11
+ import { useNavigation } from "@react-navigation/native";
12
+
13
+ export interface UserProfileHeaderProps {
14
+ /** User display name */
15
+ displayName?: string;
16
+ /** User ID */
17
+ userId?: string;
18
+ /** Whether user is guest */
19
+ isGuest?: boolean;
20
+ /** Avatar URL (optional) */
21
+ avatarUrl?: string;
22
+ /** Navigation route for account settings */
23
+ accountSettingsRoute?: string;
24
+ /** Custom onPress handler */
25
+ onPress?: () => void;
26
+ }
27
+
28
+ export const UserProfileHeader: React.FC<UserProfileHeaderProps> = ({
29
+ displayName,
30
+ userId,
31
+ isGuest = false,
32
+ avatarUrl,
33
+ accountSettingsRoute = "AccountSettings",
34
+ onPress,
35
+ }) => {
36
+ const tokens = useAppDesignTokens();
37
+ const navigation = useNavigation();
38
+ const colors = tokens.colors;
39
+
40
+ const finalDisplayName = displayName || (isGuest ? "Guest" : "User");
41
+ const finalUserId = userId || "Unknown";
42
+ const avatarName = isGuest ? "Guest" : finalDisplayName;
43
+ const finalAvatarUrl =
44
+ avatarUrl ||
45
+ `https://ui-avatars.com/api/?name=${encodeURIComponent(avatarName)}&background=${colors.primary.replace("#", "")}&color=fff&size=64`;
46
+
47
+ const handlePress = () => {
48
+ if (onPress) {
49
+ onPress();
50
+ } else if (accountSettingsRoute) {
51
+ navigation.navigate(accountSettingsRoute as never);
52
+ }
53
+ };
54
+
55
+ return (
56
+ <TouchableOpacity
57
+ style={[
58
+ styles.container,
59
+ {
60
+ backgroundColor: colors.backgroundPrimary,
61
+ borderColor: colors.borderLight,
62
+ },
63
+ ]}
64
+ onPress={handlePress}
65
+ activeOpacity={0.7}
66
+ >
67
+ <View style={styles.content}>
68
+ <Image
69
+ source={{ uri: finalAvatarUrl }}
70
+ style={[styles.avatar, { borderColor: `${colors.primary}40` }]}
71
+ />
72
+ <View style={styles.textContainer}>
73
+ <Text
74
+ style={[styles.name, { color: colors.textPrimary }]}
75
+ numberOfLines={1}
76
+ >
77
+ {finalDisplayName}
78
+ </Text>
79
+ <Text
80
+ style={[styles.id, { color: colors.textSecondary }]}
81
+ numberOfLines={1}
82
+ >
83
+ ID: {finalUserId.substring(0, 8)}...
84
+ </Text>
85
+ </View>
86
+ </View>
87
+ <ChevronRight size={20} color={colors.textSecondary} />
88
+ </TouchableOpacity>
89
+ );
90
+ };
91
+
92
+ const styles = StyleSheet.create({
93
+ container: {
94
+ flexDirection: "row",
95
+ alignItems: "center",
96
+ justifyContent: "space-between",
97
+ paddingHorizontal: 16,
98
+ paddingVertical: 16,
99
+ marginHorizontal: 16,
100
+ marginTop: 0,
101
+ borderRadius: 12,
102
+ borderWidth: 1,
103
+ },
104
+ content: {
105
+ flexDirection: "row",
106
+ alignItems: "center",
107
+ flex: 1,
108
+ },
109
+ avatar: {
110
+ width: 48,
111
+ height: 48,
112
+ borderRadius: 24,
113
+ borderWidth: 2,
114
+ },
115
+ textContainer: {
116
+ marginLeft: 12,
117
+ flex: 1,
118
+ },
119
+ name: {
120
+ fontSize: 16,
121
+ fontWeight: "600",
122
+ marginBottom: 4,
123
+ },
124
+ id: {
125
+ fontSize: 12,
126
+ fontWeight: "400",
127
+ },
128
+ });
129
+
@@ -14,15 +14,15 @@ import { View, StyleSheet } from 'react-native';
14
14
 
15
15
  import { useNavigation } from '@react-navigation/native';
16
16
  import { useDesignSystemTheme, useAppDesignTokens, type DesignTokens } from '@umituz/react-native-design-system-theme';
17
- import { AtomicText, ScreenLayout, SectionHeader, SectionContainer } from '@umituz/react-native-design-system';
17
+ import { AtomicText } from '@umituz/react-native-design-system-atoms';
18
+ import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
18
19
  import { useLocalization, getLanguageByCode } from '@umituz/react-native-localization';
19
20
  import { SettingItem } from '../components/SettingItem';
20
21
 
21
22
  export const AppearanceScreen: React.FC = () => {
22
23
  const { t, currentLanguage } = useLocalization();
23
24
  const navigation = useNavigation();
24
- // Only read themeMode, no toggle logic here - theme logic belongs in theme package
25
- const { themeMode } = useDesignSystemTheme();
25
+ const { themeMode, setThemeMode } = useDesignSystemTheme();
26
26
  const tokens = useAppDesignTokens();
27
27
  const styles = getStyles(tokens);
28
28
 
@@ -35,13 +35,8 @@ export const AppearanceScreen: React.FC = () => {
35
35
  };
36
36
 
37
37
  const handleThemeToggle = () => {
38
- // Theme toggle logic should be handled by app, not this package
39
- // This screen only displays current theme mode
40
- // App should provide toggle functionality via navigation params or event emitter
41
- // For now, just navigate back - app can handle toggle in its own theme management
42
- if (navigation.canGoBack()) {
43
- navigation.goBack();
44
- }
38
+ const newMode = themeMode === 'dark' ? 'light' : 'dark';
39
+ setThemeMode(newMode);
45
40
  };
46
41
 
47
42
  return (
@@ -57,8 +52,10 @@ export const AppearanceScreen: React.FC = () => {
57
52
  </View>
58
53
 
59
54
  {/* Language Section */}
60
- <SectionContainer>
61
- <SectionHeader>{t('settings.language')}</SectionHeader>
55
+ <View style={{ marginBottom: tokens.spacing.md }}>
56
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
57
+ {t('settings.language')}
58
+ </AtomicText>
62
59
  <SettingItem
63
60
  icon="Languages"
64
61
  iconGradient={((tokens.colors as any).settingGradients?.language as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
@@ -67,11 +64,13 @@ export const AppearanceScreen: React.FC = () => {
67
64
  onPress={handleLanguagePress}
68
65
  testID="language-button"
69
66
  />
70
- </SectionContainer>
67
+ </View>
71
68
 
72
69
  {/* Theme Section */}
73
- <SectionContainer>
74
- <SectionHeader>{t('settings.appearance.darkMode')}</SectionHeader>
70
+ <View style={{ marginBottom: tokens.spacing.md }}>
71
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
72
+ {t('settings.appearance.darkMode')}
73
+ </AtomicText>
75
74
  <SettingItem
76
75
  icon={themeMode === 'dark' ? 'Moon' : 'Sun'}
77
76
  iconGradient={
@@ -84,7 +83,7 @@ export const AppearanceScreen: React.FC = () => {
84
83
  onPress={handleThemeToggle}
85
84
  testID="theme-button"
86
85
  />
87
- </SectionContainer>
86
+ </View>
88
87
  </ScreenLayout>
89
88
  );
90
89
  };
@@ -94,11 +93,21 @@ const getStyles = (tokens: DesignTokens) =>
94
93
  header: {
95
94
  paddingBottom: tokens.spacing.lg,
96
95
  paddingTop: tokens.spacing.md,
96
+ paddingHorizontal: tokens.spacing.lg,
97
97
  },
98
98
  headerSubtitle: {
99
99
  marginTop: tokens.spacing.sm,
100
100
  lineHeight: 20,
101
101
  opacity: 0.8,
102
102
  },
103
+ sectionHeader: {
104
+ paddingHorizontal: tokens.spacing.lg,
105
+ paddingTop: tokens.spacing.lg,
106
+ paddingBottom: tokens.spacing.md,
107
+ textTransform: 'uppercase',
108
+ letterSpacing: 1,
109
+ fontWeight: '600',
110
+ fontSize: 12,
111
+ },
103
112
  });
104
113
 
@@ -15,8 +15,9 @@ import {
15
15
  TextInput,
16
16
  } from 'react-native';
17
17
  import { useNavigation } from '@react-navigation/native';
18
- import { useTheme, useAppDesignTokens, withAlpha, STATIC_TOKENS, type DesignTokens } from '@umituz/react-native-design-system-theme';
19
- import { AtomicIcon, AtomicText, ScreenLayout } from '@umituz/react-native-design-system';
18
+ import { useAppDesignTokens, withAlpha, STATIC_TOKENS, type DesignTokens } from '@umituz/react-native-design-system-theme';
19
+ import { AtomicIcon, AtomicText } from '@umituz/react-native-design-system-atoms';
20
+ import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
20
21
  import { useLocalization, searchLanguages, Language, LANGUAGES } from '@umituz/react-native-localization';
21
22
 
22
23
  /**