@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.
- package/README.md +133 -17
- package/package.json +2 -1
- package/src/index.ts +11 -0
- package/src/presentation/components/DisclaimerSetting.tsx +1 -1
- package/src/presentation/components/SettingItem.tsx +135 -227
- package/src/presentation/components/SettingsFooter.tsx +46 -0
- package/src/presentation/components/SettingsSection.tsx +59 -0
- package/src/presentation/components/UserProfileHeader.tsx +129 -0
- package/src/presentation/screens/AppearanceScreen.tsx +25 -16
- package/src/presentation/screens/LanguageSelectionScreen.tsx +3 -2
- package/src/presentation/screens/SettingsScreen.tsx +182 -285
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install @umituz/react-native-settings
|
|
|
20
20
|
## Peer Dependencies
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
npm install zustand @umituz/react-native-storage @umituz/react-native-design-system @umituz/react-native-design-system-theme @umituz/react-native-localization @umituz/react-native-notifications react-native-paper expo-linear-gradient
|
|
23
|
+
npm install zustand lucide-react-native @umituz/react-native-storage @umituz/react-native-design-system @umituz/react-native-design-system-theme @umituz/react-native-localization @umituz/react-native-notifications react-native-paper expo-linear-gradient
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
@@ -55,8 +55,25 @@ const MyComponent = () => {
|
|
|
55
55
|
```tsx
|
|
56
56
|
import { SettingsScreen } from '@umituz/react-native-settings';
|
|
57
57
|
|
|
58
|
-
//
|
|
58
|
+
// Basic usage
|
|
59
59
|
<Stack.Screen name="Settings" component={SettingsScreen} />
|
|
60
|
+
|
|
61
|
+
// With user profile header
|
|
62
|
+
<SettingsScreen
|
|
63
|
+
showUserProfile={true}
|
|
64
|
+
userProfile={{
|
|
65
|
+
displayName: "John Doe",
|
|
66
|
+
userId: "user123",
|
|
67
|
+
isGuest: false,
|
|
68
|
+
accountSettingsRoute: "AccountSettings",
|
|
69
|
+
}}
|
|
70
|
+
config={{
|
|
71
|
+
appearance: true,
|
|
72
|
+
notifications: true,
|
|
73
|
+
about: true,
|
|
74
|
+
legal: true,
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
60
77
|
```
|
|
61
78
|
|
|
62
79
|
### Appearance Screen
|
|
@@ -81,17 +98,82 @@ import { LanguageSelectionScreen } from '@umituz/react-native-settings';
|
|
|
81
98
|
|
|
82
99
|
```tsx
|
|
83
100
|
import { SettingItem } from '@umituz/react-native-settings';
|
|
101
|
+
import { Palette, Bell } from 'lucide-react-native';
|
|
84
102
|
|
|
103
|
+
// Basic setting item
|
|
85
104
|
<SettingItem
|
|
86
|
-
icon=
|
|
87
|
-
title="
|
|
88
|
-
|
|
89
|
-
value="Dark"
|
|
105
|
+
icon={Palette}
|
|
106
|
+
title="Appearance"
|
|
107
|
+
value="Theme and language settings"
|
|
90
108
|
onPress={() => navigation.navigate('Appearance')}
|
|
91
|
-
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
// With switch
|
|
112
|
+
<SettingItem
|
|
113
|
+
icon={Bell}
|
|
114
|
+
title="Notifications"
|
|
115
|
+
showSwitch={true}
|
|
116
|
+
switchValue={enabled}
|
|
117
|
+
onSwitchChange={setEnabled}
|
|
118
|
+
/>
|
|
119
|
+
|
|
120
|
+
// Custom colors
|
|
121
|
+
<SettingItem
|
|
122
|
+
icon={Palette}
|
|
123
|
+
title="Appearance"
|
|
124
|
+
iconColor="#F59E0B"
|
|
125
|
+
titleColor="#F59E0B"
|
|
126
|
+
onPress={() => {}}
|
|
92
127
|
/>
|
|
93
128
|
```
|
|
94
129
|
|
|
130
|
+
### Settings Section Component
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { SettingsSection, SettingItem } from '@umituz/react-native-settings';
|
|
134
|
+
import { Palette, Bell } from 'lucide-react-native';
|
|
135
|
+
|
|
136
|
+
<SettingsSection title="APP SETTINGS">
|
|
137
|
+
<SettingItem
|
|
138
|
+
icon={Palette}
|
|
139
|
+
title="Appearance"
|
|
140
|
+
value="Theme and language settings"
|
|
141
|
+
onPress={() => navigation.navigate('Appearance')}
|
|
142
|
+
/>
|
|
143
|
+
<SettingItem
|
|
144
|
+
icon={Bell}
|
|
145
|
+
title="Notifications"
|
|
146
|
+
showSwitch={true}
|
|
147
|
+
switchValue={enabled}
|
|
148
|
+
onSwitchChange={setEnabled}
|
|
149
|
+
isLast={true}
|
|
150
|
+
/>
|
|
151
|
+
</SettingsSection>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### User Profile Header Component
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { UserProfileHeader } from '@umituz/react-native-settings';
|
|
158
|
+
|
|
159
|
+
<UserProfileHeader
|
|
160
|
+
displayName="John Doe"
|
|
161
|
+
userId="user123"
|
|
162
|
+
isGuest={false}
|
|
163
|
+
avatarUrl="https://example.com/avatar.jpg"
|
|
164
|
+
accountSettingsRoute="AccountSettings"
|
|
165
|
+
onPress={() => navigation.navigate('AccountSettings')}
|
|
166
|
+
/>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Settings Footer Component
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { SettingsFooter } from '@umituz/react-native-settings';
|
|
173
|
+
|
|
174
|
+
<SettingsFooter versionText="Version 1.0.0" />
|
|
175
|
+
```
|
|
176
|
+
|
|
95
177
|
### Disclaimer Setting Component
|
|
96
178
|
|
|
97
179
|
```tsx
|
|
@@ -122,7 +204,14 @@ Direct access to Zustand store.
|
|
|
122
204
|
|
|
123
205
|
### `SettingsScreen`
|
|
124
206
|
|
|
125
|
-
|
|
207
|
+
Modern settings screen with organized sections and optional user profile header.
|
|
208
|
+
|
|
209
|
+
**Props:**
|
|
210
|
+
- `config?: SettingsConfig` - Configuration for which features to show
|
|
211
|
+
- `showUserProfile?: boolean` - Show user profile header
|
|
212
|
+
- `userProfile?: UserProfileHeaderProps` - User profile props
|
|
213
|
+
- `showFooter?: boolean` - Show footer with version
|
|
214
|
+
- `footerText?: string` - Custom footer text
|
|
126
215
|
|
|
127
216
|
### `AppearanceScreen`
|
|
128
217
|
|
|
@@ -134,19 +223,46 @@ Language selection screen with search functionality.
|
|
|
134
223
|
|
|
135
224
|
### `SettingItem`
|
|
136
225
|
|
|
137
|
-
|
|
226
|
+
Modern setting item component with Lucide icons and switch support.
|
|
138
227
|
|
|
139
228
|
**Props:**
|
|
140
|
-
- `icon:
|
|
229
|
+
- `icon: React.ComponentType` - Icon component from lucide-react-native
|
|
141
230
|
- `title: string` - Main title text
|
|
142
|
-
- `
|
|
143
|
-
- `value?: string` - Optional value to display on right
|
|
231
|
+
- `value?: string` - Optional description/value text (shown below title)
|
|
144
232
|
- `onPress?: () => void` - Callback when pressed
|
|
145
|
-
- `
|
|
146
|
-
- `
|
|
147
|
-
- `
|
|
148
|
-
- `
|
|
149
|
-
- `
|
|
233
|
+
- `showSwitch?: boolean` - Show switch instead of chevron
|
|
234
|
+
- `switchValue?: boolean` - Switch value
|
|
235
|
+
- `onSwitchChange?: (value: boolean) => void` - Switch change handler
|
|
236
|
+
- `isLast?: boolean` - Is last item (no divider)
|
|
237
|
+
- `iconColor?: string` - Custom icon color
|
|
238
|
+
- `titleColor?: string` - Custom title color
|
|
239
|
+
|
|
240
|
+
### `SettingsSection`
|
|
241
|
+
|
|
242
|
+
Section container with title and styled content area.
|
|
243
|
+
|
|
244
|
+
**Props:**
|
|
245
|
+
- `title: string` - Section title (uppercase)
|
|
246
|
+
- `children: React.ReactNode` - Section content
|
|
247
|
+
|
|
248
|
+
### `UserProfileHeader`
|
|
249
|
+
|
|
250
|
+
User profile header with avatar, name, and ID.
|
|
251
|
+
|
|
252
|
+
**Props:**
|
|
253
|
+
- `displayName?: string` - User display name
|
|
254
|
+
- `userId?: string` - User ID
|
|
255
|
+
- `isGuest?: boolean` - Whether user is guest
|
|
256
|
+
- `avatarUrl?: string` - Custom avatar URL
|
|
257
|
+
- `accountSettingsRoute?: string` - Navigation route for account settings
|
|
258
|
+
- `onPress?: () => void` - Custom onPress handler
|
|
259
|
+
|
|
260
|
+
### `SettingsFooter`
|
|
261
|
+
|
|
262
|
+
Footer component displaying app version.
|
|
263
|
+
|
|
264
|
+
**Props:**
|
|
265
|
+
- `versionText?: string` - Custom version text (optional)
|
|
150
266
|
|
|
151
267
|
### `DisclaimerSetting`
|
|
152
268
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Settings management for React Native apps - user preferences, theme, language, notifications",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"react": ">=18.2.0",
|
|
30
30
|
"react-native": ">=0.74.0",
|
|
31
31
|
"zustand": "^5.0.2",
|
|
32
|
+
"lucide-react-native": "^0.468.0",
|
|
32
33
|
"@umituz/react-native-storage": "latest",
|
|
33
34
|
"@umituz/react-native-design-system": "latest",
|
|
34
35
|
"@umituz/react-native-design-system-theme": "latest",
|
package/src/index.ts
CHANGED
|
@@ -48,5 +48,16 @@ export type { SettingsConfig } from './presentation/screens/types';
|
|
|
48
48
|
// =============================================================================
|
|
49
49
|
|
|
50
50
|
export { SettingItem } from './presentation/components/SettingItem';
|
|
51
|
+
export type { SettingItemProps } from './presentation/components/SettingItem';
|
|
52
|
+
|
|
53
|
+
export { SettingsSection } from './presentation/components/SettingsSection';
|
|
54
|
+
export type { SettingsSectionProps } from './presentation/components/SettingsSection';
|
|
55
|
+
|
|
56
|
+
export { SettingsFooter } from './presentation/components/SettingsFooter';
|
|
57
|
+
export type { SettingsFooterProps } from './presentation/components/SettingsFooter';
|
|
58
|
+
|
|
59
|
+
export { UserProfileHeader } from './presentation/components/UserProfileHeader';
|
|
60
|
+
export type { UserProfileHeaderProps } from './presentation/components/UserProfileHeader';
|
|
61
|
+
|
|
51
62
|
export { DisclaimerSetting } from './presentation/components/DisclaimerSetting';
|
|
52
63
|
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
} from 'react-native';
|
|
28
28
|
|
|
29
29
|
import { useAppDesignTokens, withAlpha } from '@umituz/react-native-design-system-theme';
|
|
30
|
-
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
|
|
30
|
+
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system-atoms';
|
|
31
31
|
import { useLocalization } from '@umituz/react-native-localization';
|
|
32
32
|
|
|
33
33
|
type DesignTokens = ReturnType<typeof useAppDesignTokens>;
|
|
@@ -1,259 +1,167 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Modern
|
|
5
|
-
* - Wraps Paper List.Item for Material Design compliance
|
|
6
|
-
* - Custom gradient icon backgrounds (LinearGradient)
|
|
7
|
-
* - Lucide icons integration (AtomicIcon)
|
|
8
|
-
* - Automatic theme-aware styling
|
|
9
|
-
* - Built-in ripple effects
|
|
10
|
-
* - Accessibility support
|
|
11
|
-
* - Fixed title truncation with proper layout constraints
|
|
2
|
+
* Setting Item Component
|
|
3
|
+
* Single Responsibility: Render a single settings item
|
|
4
|
+
* Modern design with Lucide icons and switch support
|
|
12
5
|
*/
|
|
13
6
|
|
|
14
|
-
import React from
|
|
15
|
-
import { View,
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system-theme';
|
|
19
|
-
import type { IconName } from '@umituz/react-native-design-system';
|
|
20
|
-
import type { DesignTokens } from '@umituz/react-native-design-system';
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { View, Text, TouchableOpacity, StyleSheet, Switch } from "react-native";
|
|
9
|
+
import { ChevronRight } from "lucide-react-native";
|
|
10
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
21
11
|
|
|
22
|
-
interface SettingItemProps {
|
|
23
|
-
/** Icon
|
|
24
|
-
icon:
|
|
12
|
+
export interface SettingItemProps {
|
|
13
|
+
/** Icon component from lucide-react-native */
|
|
14
|
+
icon: React.ComponentType<{ size?: number; color?: string }>;
|
|
25
15
|
/** Main title text */
|
|
26
16
|
title: string;
|
|
27
|
-
/** Optional description text */
|
|
28
|
-
description?: string;
|
|
29
|
-
/** Optional value to display on the right */
|
|
17
|
+
/** Optional description/value text */
|
|
30
18
|
value?: string;
|
|
31
19
|
/** Callback when pressed */
|
|
32
20
|
onPress?: () => void;
|
|
33
|
-
/** Show
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
|
|
21
|
+
/** Show switch instead of chevron */
|
|
22
|
+
showSwitch?: boolean;
|
|
23
|
+
/** Switch value */
|
|
24
|
+
switchValue?: boolean;
|
|
25
|
+
/** Switch change handler */
|
|
26
|
+
onSwitchChange?: (value: boolean) => void;
|
|
27
|
+
/** Is last item in section (no divider) */
|
|
28
|
+
isLast?: boolean;
|
|
29
|
+
/** Custom icon color */
|
|
30
|
+
iconColor?: string;
|
|
31
|
+
/** Custom title color */
|
|
32
|
+
titleColor?: string;
|
|
43
33
|
}
|
|
44
34
|
|
|
45
35
|
export const SettingItem: React.FC<SettingItemProps> = ({
|
|
46
|
-
icon,
|
|
36
|
+
icon: Icon,
|
|
47
37
|
title,
|
|
48
|
-
description,
|
|
49
38
|
value,
|
|
50
39
|
onPress,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
40
|
+
showSwitch = false,
|
|
41
|
+
switchValue,
|
|
42
|
+
onSwitchChange,
|
|
43
|
+
isLast = false,
|
|
44
|
+
iconColor,
|
|
45
|
+
titleColor,
|
|
56
46
|
}) => {
|
|
57
47
|
const tokens = useAppDesignTokens();
|
|
58
|
-
const
|
|
48
|
+
const colors = tokens.colors;
|
|
59
49
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
? (iconGradient as unknown as readonly [string, string, ...string[]])
|
|
63
|
-
: [tokens.colors.surface, tokens.colors.surface] as const;
|
|
64
|
-
|
|
65
|
-
if (onPress) {
|
|
66
|
-
return (
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
67
52
|
<TouchableOpacity
|
|
53
|
+
style={[
|
|
54
|
+
styles.container,
|
|
55
|
+
{ backgroundColor: colors.backgroundPrimary },
|
|
56
|
+
]}
|
|
68
57
|
onPress={onPress}
|
|
69
|
-
disabled={
|
|
58
|
+
disabled={showSwitch}
|
|
70
59
|
activeOpacity={0.7}
|
|
71
|
-
style={[styles.listItem, disabled && styles.disabled]}
|
|
72
|
-
testID={testID}
|
|
73
60
|
>
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
</View>
|
|
85
|
-
|
|
86
|
-
{/* Center: Title and Description */}
|
|
87
|
-
<View style={styles.contentContainer}>
|
|
88
|
-
<AtomicText
|
|
89
|
-
type="bodyLarge"
|
|
90
|
-
color={disabled ? "textDisabled" : "onSurface"}
|
|
91
|
-
style={styles.title}
|
|
92
|
-
numberOfLines={2}
|
|
93
|
-
ellipsizeMode="tail"
|
|
61
|
+
<View style={styles.content}>
|
|
62
|
+
<View
|
|
63
|
+
style={[
|
|
64
|
+
styles.iconContainer,
|
|
65
|
+
{
|
|
66
|
+
backgroundColor: iconColor
|
|
67
|
+
? `${iconColor}15`
|
|
68
|
+
: `${colors.primary}15`,
|
|
69
|
+
},
|
|
70
|
+
]}
|
|
94
71
|
>
|
|
95
|
-
{
|
|
96
|
-
</
|
|
97
|
-
{
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
72
|
+
<Icon size={20} color={iconColor || colors.primary} />
|
|
73
|
+
</View>
|
|
74
|
+
<View style={styles.textContainer}>
|
|
75
|
+
<Text
|
|
76
|
+
style={[
|
|
77
|
+
styles.title,
|
|
78
|
+
{ color: titleColor || colors.textPrimary },
|
|
79
|
+
]}
|
|
80
|
+
numberOfLines={1}
|
|
104
81
|
>
|
|
105
|
-
{
|
|
106
|
-
</
|
|
107
|
-
|
|
82
|
+
{title}
|
|
83
|
+
</Text>
|
|
84
|
+
{value && !showSwitch && (
|
|
85
|
+
<Text
|
|
86
|
+
style={[styles.value, { color: colors.textSecondary }]}
|
|
87
|
+
numberOfLines={1}
|
|
88
|
+
>
|
|
89
|
+
{value}
|
|
90
|
+
</Text>
|
|
91
|
+
)}
|
|
92
|
+
</View>
|
|
108
93
|
</View>
|
|
109
94
|
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
textAlign="right"
|
|
121
|
-
>
|
|
122
|
-
{value}
|
|
123
|
-
</AtomicText>
|
|
124
|
-
</View>
|
|
125
|
-
) : (showChevron ?? true) ? (
|
|
126
|
-
<View style={styles.rightContainer}>
|
|
127
|
-
<AtomicIcon
|
|
128
|
-
name="ChevronRight"
|
|
129
|
-
size="sm"
|
|
130
|
-
color="textSecondary"
|
|
131
|
-
style={styles.chevron}
|
|
95
|
+
<View style={styles.rightContainer}>
|
|
96
|
+
{showSwitch ? (
|
|
97
|
+
<Switch
|
|
98
|
+
value={switchValue}
|
|
99
|
+
onValueChange={onSwitchChange}
|
|
100
|
+
trackColor={{
|
|
101
|
+
false: `${colors.textSecondary}30`,
|
|
102
|
+
true: colors.primary,
|
|
103
|
+
}}
|
|
104
|
+
thumbColor="#FFFFFF"
|
|
132
105
|
/>
|
|
133
|
-
|
|
134
|
-
|
|
106
|
+
) : (
|
|
107
|
+
<ChevronRight size={18} color={colors.textSecondary} />
|
|
108
|
+
)}
|
|
109
|
+
</View>
|
|
135
110
|
</TouchableOpacity>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
111
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
start={{ x: 0, y: 0 }}
|
|
149
|
-
end={{ x: 1, y: 1 }}
|
|
150
|
-
style={styles.iconContainer}
|
|
151
|
-
>
|
|
152
|
-
<AtomicIcon name={icon} size="md" customColor="#FFFFFF" />
|
|
153
|
-
</LinearGradient>
|
|
154
|
-
</View>
|
|
155
|
-
|
|
156
|
-
{/* Center: Title and Description */}
|
|
157
|
-
<View style={styles.contentContainer}>
|
|
158
|
-
<AtomicText
|
|
159
|
-
type="bodyLarge"
|
|
160
|
-
color={disabled ? "textDisabled" : "onSurface"}
|
|
161
|
-
style={styles.title}
|
|
162
|
-
numberOfLines={2}
|
|
163
|
-
ellipsizeMode="tail"
|
|
164
|
-
>
|
|
165
|
-
{title}
|
|
166
|
-
</AtomicText>
|
|
167
|
-
{description && (
|
|
168
|
-
<AtomicText
|
|
169
|
-
type="bodySmall"
|
|
170
|
-
color="textSecondary"
|
|
171
|
-
style={styles.description}
|
|
172
|
-
numberOfLines={2}
|
|
173
|
-
ellipsizeMode="tail"
|
|
174
|
-
>
|
|
175
|
-
{description}
|
|
176
|
-
</AtomicText>
|
|
177
|
-
)}
|
|
178
|
-
</View>
|
|
179
|
-
|
|
180
|
-
{/* Right: Value, Chevron, or Custom Element */}
|
|
181
|
-
{rightElement ? (
|
|
182
|
-
<View style={styles.rightContainer}>{rightElement}</View>
|
|
183
|
-
) : value ? (
|
|
184
|
-
<View style={styles.rightContainer}>
|
|
185
|
-
<AtomicText
|
|
186
|
-
type="bodyMedium"
|
|
187
|
-
color="textSecondary"
|
|
188
|
-
style={styles.value}
|
|
189
|
-
numberOfLines={2}
|
|
190
|
-
textAlign="right"
|
|
191
|
-
>
|
|
192
|
-
{value}
|
|
193
|
-
</AtomicText>
|
|
194
|
-
</View>
|
|
195
|
-
) : null}
|
|
196
|
-
</View>
|
|
112
|
+
{!isLast && (
|
|
113
|
+
<View
|
|
114
|
+
style={[
|
|
115
|
+
styles.divider,
|
|
116
|
+
{ backgroundColor: `${colors.textSecondary}20` },
|
|
117
|
+
]}
|
|
118
|
+
/>
|
|
119
|
+
)}
|
|
120
|
+
</>
|
|
197
121
|
);
|
|
198
122
|
};
|
|
199
123
|
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
rightContainer: {
|
|
245
|
-
justifyContent: 'center',
|
|
246
|
-
alignItems: 'flex-end',
|
|
247
|
-
marginLeft: tokens.spacing.md,
|
|
248
|
-
maxWidth: '50%',
|
|
249
|
-
flexShrink: 0,
|
|
250
|
-
},
|
|
251
|
-
value: {
|
|
252
|
-
fontWeight: '500',
|
|
253
|
-
lineHeight: tokens.typography.bodyMedium.fontSize * 1.4,
|
|
254
|
-
},
|
|
255
|
-
chevron: {
|
|
256
|
-
opacity: 0.5,
|
|
257
|
-
},
|
|
258
|
-
});
|
|
259
|
-
|
|
124
|
+
const styles = StyleSheet.create({
|
|
125
|
+
container: {
|
|
126
|
+
flexDirection: "row",
|
|
127
|
+
alignItems: "center",
|
|
128
|
+
justifyContent: "space-between",
|
|
129
|
+
paddingHorizontal: 16,
|
|
130
|
+
paddingVertical: 14,
|
|
131
|
+
},
|
|
132
|
+
content: {
|
|
133
|
+
flexDirection: "row",
|
|
134
|
+
alignItems: "center",
|
|
135
|
+
flex: 1,
|
|
136
|
+
},
|
|
137
|
+
iconContainer: {
|
|
138
|
+
width: 40,
|
|
139
|
+
height: 40,
|
|
140
|
+
borderRadius: 8,
|
|
141
|
+
justifyContent: "center",
|
|
142
|
+
alignItems: "center",
|
|
143
|
+
marginRight: 12,
|
|
144
|
+
},
|
|
145
|
+
textContainer: {
|
|
146
|
+
flex: 1,
|
|
147
|
+
minWidth: 0,
|
|
148
|
+
},
|
|
149
|
+
title: {
|
|
150
|
+
fontSize: 16,
|
|
151
|
+
fontWeight: "500",
|
|
152
|
+
},
|
|
153
|
+
value: {
|
|
154
|
+
fontSize: 12,
|
|
155
|
+
fontWeight: "400",
|
|
156
|
+
marginTop: 2,
|
|
157
|
+
},
|
|
158
|
+
rightContainer: {
|
|
159
|
+
flexDirection: "row",
|
|
160
|
+
alignItems: "center",
|
|
161
|
+
gap: 8,
|
|
162
|
+
},
|
|
163
|
+
divider: {
|
|
164
|
+
height: 1,
|
|
165
|
+
marginLeft: 68,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Footer Component
|
|
3
|
+
* Single Responsibility: Display app version information
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
8
|
+
import { useLocalization } from "@umituz/react-native-localization";
|
|
9
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system-theme";
|
|
10
|
+
|
|
11
|
+
export interface SettingsFooterProps {
|
|
12
|
+
/** Custom version text (optional) */
|
|
13
|
+
versionText?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const SettingsFooter: React.FC<SettingsFooterProps> = ({
|
|
17
|
+
versionText,
|
|
18
|
+
}) => {
|
|
19
|
+
const { t } = useLocalization();
|
|
20
|
+
const tokens = useAppDesignTokens();
|
|
21
|
+
const colors = tokens.colors;
|
|
22
|
+
|
|
23
|
+
const displayText =
|
|
24
|
+
versionText ||
|
|
25
|
+
`${t("settings.about.version")} ${t("settings.about.versionNumber")}`;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<View style={styles.container}>
|
|
29
|
+
<Text style={[styles.text, { color: colors.textSecondary }]}>
|
|
30
|
+
{displayText}
|
|
31
|
+
</Text>
|
|
32
|
+
</View>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const styles = StyleSheet.create({
|
|
37
|
+
container: {
|
|
38
|
+
paddingVertical: 24,
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
},
|
|
41
|
+
text: {
|
|
42
|
+
fontSize: 12,
|
|
43
|
+
fontWeight: "500",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|