@umituz/react-native-settings 1.3.7 → 1.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-settings",
3
- "version": "1.3.7",
3
+ "version": "1.4.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",
@@ -33,7 +33,6 @@
33
33
  "@umituz/react-native-design-system": "latest",
34
34
  "@umituz/react-native-design-system-theme": "latest",
35
35
  "@umituz/react-native-localization": "latest",
36
- "react-native-paper": "^5.12.3",
37
36
  "expo-linear-gradient": "~14.0.0"
38
37
  },
39
38
  "devDependencies": {
@@ -12,8 +12,7 @@
12
12
  */
13
13
 
14
14
  import React from 'react';
15
- import { View, StyleSheet } from 'react-native';
16
- import { List } from 'react-native-paper';
15
+ import { View, StyleSheet, TouchableOpacity } from 'react-native';
17
16
  import { LinearGradient } from 'expo-linear-gradient';
18
17
  import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
19
18
  import { useAppDesignTokens } from '@umituz/react-native-design-system-theme';
@@ -63,114 +62,198 @@ export const SettingItem: React.FC<SettingItemProps> = ({
63
62
  ? (iconGradient as unknown as readonly [string, string, ...string[]])
64
63
  : [tokens.colors.surface, tokens.colors.surface] as const;
65
64
 
66
- // Render gradient icon container for left prop
67
- const renderLeft = (props: any) => (
68
- <View style={styles.leftContainer}>
69
- <LinearGradient
70
- colors={gradientColors}
71
- start={{ x: 0, y: 0 }}
72
- end={{ x: 1, y: 1 }}
73
- style={styles.iconContainer}
65
+ if (onPress) {
66
+ return (
67
+ <TouchableOpacity
68
+ onPress={onPress}
69
+ disabled={disabled}
70
+ activeOpacity={0.7}
71
+ style={[styles.listItem, disabled && styles.disabled]}
72
+ testID={testID}
74
73
  >
75
- <AtomicIcon name={icon} size="md" color="primary" />
76
- </LinearGradient>
77
- </View>
78
- );
79
-
80
- // Render right side content for right prop
81
- const renderRight = (props: any) => {
82
- if (rightElement) {
83
- return <View style={styles.rightContainer}>{rightElement}</View>;
84
- }
85
-
86
- if (value) {
87
- return (
88
- <View style={styles.rightContainer}>
89
- <AtomicText type="bodyMedium" color="secondary" style={styles.value} numberOfLines={2}>
90
- {value}
91
- </AtomicText>
74
+ {/* Left: Gradient Icon */}
75
+ <View style={styles.leftContainer}>
76
+ <LinearGradient
77
+ colors={gradientColors}
78
+ start={{ x: 0, y: 0 }}
79
+ end={{ x: 1, y: 1 }}
80
+ style={styles.iconContainer}
81
+ >
82
+ <AtomicIcon name={icon} size="md" customColor="#FFFFFF" />
83
+ </LinearGradient>
92
84
  </View>
93
- );
94
- }
95
85
 
96
- // Show chevron if onPress exists and not explicitly disabled
97
- if ((showChevron ?? true) && onPress) {
98
- return (
99
- <View style={styles.rightContainer}>
100
- <AtomicIcon name="ChevronRight" size="sm" color="secondary" style={styles.chevron} />
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"
94
+ >
95
+ {title}
96
+ </AtomicText>
97
+ {description && (
98
+ <AtomicText
99
+ type="bodySmall"
100
+ color="textSecondary"
101
+ style={styles.description}
102
+ numberOfLines={2}
103
+ ellipsizeMode="tail"
104
+ >
105
+ {description}
106
+ </AtomicText>
107
+ )}
101
108
  </View>
102
- );
103
- }
104
109
 
105
- return null;
106
- };
110
+ {/* Right: Value, Chevron, or Custom Element */}
111
+ {rightElement ? (
112
+ <View style={styles.rightContainer}>{rightElement}</View>
113
+ ) : value ? (
114
+ <View style={styles.rightContainer}>
115
+ <AtomicText
116
+ type="bodyMedium"
117
+ color="textSecondary"
118
+ style={styles.value}
119
+ numberOfLines={2}
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}
132
+ />
133
+ </View>
134
+ ) : null}
135
+ </TouchableOpacity>
136
+ );
137
+ }
107
138
 
108
139
  return (
109
- <List.Item
110
- title={title}
111
- description={description}
112
- left={renderLeft}
113
- right={renderRight}
114
- onPress={onPress}
115
- disabled={disabled}
140
+ <View
141
+ style={[styles.listItem, disabled && styles.disabled]}
116
142
  testID={testID}
117
- style={styles.listItem}
118
- titleStyle={styles.title}
119
- descriptionStyle={styles.description}
120
- titleNumberOfLines={2}
121
- titleEllipsizeMode="tail"
122
- descriptionNumberOfLines={2}
123
- descriptionEllipsizeMode="tail"
124
- />
143
+ >
144
+ {/* Left: Gradient Icon */}
145
+ <View style={styles.leftContainer}>
146
+ <LinearGradient
147
+ colors={gradientColors}
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>
125
197
  );
126
198
  };
127
199
 
128
200
  const getStyles = (tokens: DesignTokens) =>
129
201
  StyleSheet.create({
130
202
  listItem: {
131
- paddingVertical: tokens.spacing.sm,
132
- paddingHorizontal: tokens.spacing.md,
133
- minHeight: 64,
203
+ flexDirection: 'row',
204
+ alignItems: 'center',
205
+ paddingVertical: tokens.spacing.md,
206
+ paddingHorizontal: tokens.spacing.lg,
207
+ minHeight: 72,
208
+ },
209
+ disabled: {
210
+ opacity: 0.5,
134
211
  },
135
212
  leftContainer: {
136
213
  marginRight: tokens.spacing.md,
137
214
  justifyContent: 'center',
138
215
  },
139
216
  iconContainer: {
140
- width: 44,
141
- height: 44,
142
- borderRadius: 22,
217
+ width: 48,
218
+ height: 48,
219
+ borderRadius: 24,
143
220
  alignItems: 'center',
144
221
  justifyContent: 'center',
145
222
  overflow: 'hidden',
146
223
  borderWidth: 1,
147
- borderColor: `${tokens.colors.primary}20`,
224
+ borderColor: `${tokens.colors.primary}15`,
225
+ },
226
+ contentContainer: {
227
+ flex: 1,
228
+ justifyContent: 'center',
229
+ minWidth: 0,
148
230
  },
149
231
  title: {
150
232
  fontSize: tokens.typography.bodyLarge.fontSize,
151
233
  fontWeight: '600',
152
- color: tokens.colors.textPrimary,
153
234
  flexShrink: 1,
235
+ lineHeight: tokens.typography.bodyLarge.fontSize * 1.4,
154
236
  },
155
237
  description: {
156
238
  fontSize: tokens.typography.bodySmall.fontSize,
157
- color: tokens.colors.textSecondary,
158
- marginTop: tokens.spacing.xs,
159
- opacity: 0.8,
239
+ marginTop: tokens.spacing.xs / 2,
240
+ opacity: 0.7,
160
241
  flexShrink: 1,
242
+ lineHeight: tokens.typography.bodySmall.fontSize * 1.4,
161
243
  },
162
244
  rightContainer: {
163
245
  justifyContent: 'center',
164
246
  alignItems: 'flex-end',
247
+ marginLeft: tokens.spacing.md,
165
248
  maxWidth: '50%',
166
249
  flexShrink: 0,
167
250
  },
168
251
  value: {
169
252
  fontWeight: '500',
170
- textAlign: 'right',
253
+ lineHeight: tokens.typography.bodyMedium.fontSize * 1.4,
171
254
  },
172
255
  chevron: {
173
- opacity: 0.6,
256
+ opacity: 0.5,
174
257
  },
175
258
  });
176
259
 
@@ -11,11 +11,10 @@
11
11
 
12
12
  import React from 'react';
13
13
  import { View, StyleSheet } from 'react-native';
14
- import { List } from 'react-native-paper';
15
14
 
16
15
  import { useNavigation } from '@react-navigation/native';
17
16
  import { useTheme, useAppDesignTokens, type DesignTokens } from '@umituz/react-native-design-system-theme';
18
- import { AtomicText, ScreenLayout } from '@umituz/react-native-design-system';
17
+ import { AtomicText, ScreenLayout, SectionHeader, SectionContainer } from '@umituz/react-native-design-system';
19
18
  import { useLocalization, getLanguageByCode } from '@umituz/react-native-localization';
20
19
  import { SettingItem } from '../components/SettingItem';
21
20
 
@@ -51,8 +50,8 @@ export const AppearanceScreen: React.FC = () => {
51
50
  </View>
52
51
 
53
52
  {/* Language Section */}
54
- <List.Section>
55
- <List.Subheader style={{ color: tokens.colors.textSecondary }}>{t('settings.language')}</List.Subheader>
53
+ <SectionContainer>
54
+ <SectionHeader>{t('settings.language')}</SectionHeader>
56
55
  <SettingItem
57
56
  icon="Languages"
58
57
  iconGradient={((tokens.colors as any).settingGradients?.language as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
@@ -61,11 +60,11 @@ export const AppearanceScreen: React.FC = () => {
61
60
  onPress={handleLanguagePress}
62
61
  testID="language-button"
63
62
  />
64
- </List.Section>
63
+ </SectionContainer>
65
64
 
66
65
  {/* Theme Section */}
67
- <List.Section>
68
- <List.Subheader style={{ color: tokens.colors.textSecondary }}>{t('settings.appearance.darkMode')}</List.Subheader>
66
+ <SectionContainer>
67
+ <SectionHeader>{t('settings.appearance.darkMode')}</SectionHeader>
69
68
  <SettingItem
70
69
  icon={themeMode === 'dark' ? 'Moon' : 'Sun'}
71
70
  iconGradient={
@@ -78,7 +77,7 @@ export const AppearanceScreen: React.FC = () => {
78
77
  onPress={handleThemeToggle}
79
78
  testID="theme-button"
80
79
  />
81
- </List.Section>
80
+ </SectionContainer>
82
81
  </ScreenLayout>
83
82
  );
84
83
  };
@@ -12,13 +12,12 @@
12
12
  */
13
13
 
14
14
  import React, { useMemo } from 'react';
15
- import { List, Divider } from 'react-native-paper';
16
15
  import { DeviceEventEmitter, Alert, View, TouchableOpacity, StyleSheet } from 'react-native';
17
16
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
18
17
 
19
18
  import { useNavigation, CommonActions } from '@react-navigation/native';
20
19
  import { useTheme, useAppDesignTokens } from '@umituz/react-native-design-system-theme';
21
- import { ScreenLayout, AtomicIcon, AtomicText } from '@umituz/react-native-design-system';
20
+ import { ScreenLayout, AtomicIcon, AtomicText, SectionHeader, SectionContainer, AtomicDivider } from '@umituz/react-native-design-system';
22
21
  import { SettingItem } from '../components/SettingItem';
23
22
  import { getLanguageByCode, useLocalization } from '@umituz/react-native-localization';
24
23
  import { SettingsConfig } from './types';
@@ -261,14 +260,14 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
261
260
  hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
262
261
  testID="close-settings-button"
263
262
  >
264
- <AtomicIcon name="X" size="lg" color="textPrimary" />
263
+ <AtomicIcon name="X" size="lg" color="primary" />
265
264
  </TouchableOpacity>
266
265
  </View>
267
266
 
268
267
  {/* Appearance Section */}
269
268
  {features.appearance && (
270
- <List.Section style={{ marginBottom: 8 }}>
271
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.appearance')}</List.Subheader>
269
+ <SectionContainer>
270
+ <SectionHeader>{t('settings.sections.appearance')}</SectionHeader>
272
271
  <SettingItem
273
272
  icon="Palette"
274
273
  iconGradient={theme.colors.settingGradients.themeLight as unknown as string[]}
@@ -277,13 +276,13 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
277
276
  onPress={handleAppearancePress}
278
277
  testID="appearance-button"
279
278
  />
280
- </List.Section>
279
+ </SectionContainer>
281
280
  )}
282
281
 
283
282
  {/* General Section - Notifications */}
284
283
  {features.notifications && (
285
- <List.Section style={{ marginBottom: 8 }}>
286
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.general')}</List.Subheader>
284
+ <SectionContainer>
285
+ <SectionHeader>{t('settings.sections.general')}</SectionHeader>
287
286
  <SettingItem
288
287
  icon="Bell"
289
288
  iconGradient={theme.colors.settingGradients.notifications as unknown as string[]}
@@ -292,13 +291,13 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
292
291
  onPress={handleNotificationsPress}
293
292
  testID="notifications-button"
294
293
  />
295
- </List.Section>
294
+ </SectionContainer>
296
295
  )}
297
296
 
298
297
  {/* Development/Test: Show Onboarding */}
299
298
  {__DEV__ && useOnboardingStore && (
300
- <List.Section style={{ marginBottom: 8 }}>
301
- <List.Subheader style={{ color: theme.colors.textSecondary }}>Development</List.Subheader>
299
+ <SectionContainer>
300
+ <SectionHeader>Development</SectionHeader>
302
301
  <SettingItem
303
302
  icon="Play"
304
303
  iconGradient={theme.colors.settingGradients.info as unknown as string[]}
@@ -307,13 +306,13 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
307
306
  onPress={handleShowOnboarding}
308
307
  testID="show-onboarding-button"
309
308
  />
310
- </List.Section>
309
+ </SectionContainer>
311
310
  )}
312
311
 
313
312
  {/* About & Legal Section */}
314
313
  {(features.about || features.legal) && (
315
- <List.Section style={{ marginBottom: 8 }}>
316
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.about')}</List.Subheader>
314
+ <SectionContainer>
315
+ <SectionHeader>{t('settings.sections.about')}</SectionHeader>
317
316
  {features.about && (
318
317
  <SettingItem
319
318
  icon="Info"
@@ -324,7 +323,7 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
324
323
  testID="about-button"
325
324
  />
326
325
  )}
327
- {features.about && features.legal && <Divider />}
326
+ {features.about && features.legal && <AtomicDivider />}
328
327
  {features.legal && (
329
328
  <SettingItem
330
329
  icon="FileText"
@@ -335,16 +334,16 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
335
334
  testID="legal-button"
336
335
  />
337
336
  )}
338
- </List.Section>
337
+ </SectionContainer>
339
338
  )}
340
339
 
341
340
  {/* Fallback: Show message if no features are enabled */}
342
341
  {!hasAnyFeatures && (
343
- <List.Section>
344
- <List.Subheader style={{ color: theme.colors.textSecondary }}>
342
+ <SectionContainer>
343
+ <SectionHeader>
345
344
  {t('settings.noOptionsAvailable') || 'No settings available'}
346
- </List.Subheader>
347
- </List.Section>
345
+ </SectionHeader>
346
+ </SectionContainer>
348
347
  )}
349
348
  </ScreenLayout>
350
349
  );