@umituz/react-native-settings 1.3.8 → 1.3.10

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.8",
3
+ "version": "1.3.10",
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, Pressable } 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,75 +62,78 @@ 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}
74
- >
75
- <AtomicIcon name={icon} size="md" color="primary" />
76
- </LinearGradient>
77
- </View>
78
- );
65
+ const content = (
66
+ <View style={[styles.listItem, disabled && styles.disabled]}>
67
+ {/* Left: Icon with gradient */}
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}
74
+ >
75
+ <AtomicIcon name={icon} size="md" color="primary" />
76
+ </LinearGradient>
77
+ </View>
79
78
 
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
- }
79
+ {/* Center: Title and description */}
80
+ <View style={styles.contentContainer}>
81
+ <AtomicText type="bodyLarge" color="textPrimary" style={styles.title} numberOfLines={2}>
82
+ {title}
83
+ </AtomicText>
84
+ {description && (
85
+ <AtomicText type="bodySmall" color="textSecondary" style={styles.description} numberOfLines={2}>
86
+ {description}
87
+ </AtomicText>
88
+ )}
89
+ </View>
85
90
 
86
- if (value) {
87
- return (
88
- <View style={styles.rightContainer}>
89
- <AtomicText type="bodyMedium" color="secondary" style={styles.value} numberOfLines={2}>
91
+ {/* Right: Value, chevron, or custom element */}
92
+ <View style={styles.rightContainer}>
93
+ {rightElement ? (
94
+ rightElement
95
+ ) : value ? (
96
+ <AtomicText type="bodyMedium" color="textSecondary" style={styles.value} numberOfLines={2}>
90
97
  {value}
91
98
  </AtomicText>
92
- </View>
93
- );
94
- }
95
-
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} />
101
- </View>
102
- );
103
- }
99
+ ) : (showChevron ?? true) && onPress ? (
100
+ <AtomicIcon name="ChevronRight" size="sm" color="textSecondary" style={styles.chevron} />
101
+ ) : null}
102
+ </View>
103
+ </View>
104
+ );
104
105
 
105
- return null;
106
- };
106
+ if (onPress && !disabled) {
107
+ return (
108
+ <Pressable onPress={onPress} testID={testID} style={styles.pressable}>
109
+ {content}
110
+ </Pressable>
111
+ );
112
+ }
107
113
 
108
- return (
109
- <List.Item
110
- title={title}
111
- description={description}
112
- left={renderLeft}
113
- right={renderRight}
114
- onPress={onPress}
115
- disabled={disabled}
116
- 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
- />
125
- );
114
+ return <View testID={testID}>{content}</View>;
126
115
  };
127
116
 
128
117
  const getStyles = (tokens: DesignTokens) =>
129
118
  StyleSheet.create({
119
+ pressable: {
120
+ borderRadius: tokens.borders.radius.md,
121
+ },
130
122
  listItem: {
123
+ flexDirection: 'row',
124
+ alignItems: 'center',
131
125
  paddingVertical: tokens.spacing.sm,
132
126
  paddingHorizontal: tokens.spacing.md,
133
127
  minHeight: 64,
134
128
  },
129
+ disabled: {
130
+ opacity: 0.5,
131
+ },
132
+ contentContainer: {
133
+ flex: 1,
134
+ marginLeft: tokens.spacing.md,
135
+ marginRight: tokens.spacing.md,
136
+ },
135
137
  leftContainer: {
136
138
  marginRight: tokens.spacing.md,
137
139
  justifyContent: 'center',
@@ -147,17 +149,12 @@ const getStyles = (tokens: DesignTokens) =>
147
149
  borderColor: `${tokens.colors.primary}20`,
148
150
  },
149
151
  title: {
150
- fontSize: tokens.typography.bodyLarge.fontSize,
151
152
  fontWeight: '600',
152
- color: tokens.colors.textPrimary,
153
- flexShrink: 1,
153
+ marginBottom: tokens.spacing.xs,
154
154
  },
155
155
  description: {
156
- fontSize: tokens.typography.bodySmall.fontSize,
157
- color: tokens.colors.textSecondary,
158
156
  marginTop: tokens.spacing.xs,
159
157
  opacity: 0.8,
160
- flexShrink: 1,
161
158
  },
162
159
  rightContainer: {
163
160
  justifyContent: 'center',
@@ -11,10 +11,9 @@
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
- import { useTheme, useAppDesignTokens, type DesignTokens } from '@umituz/react-native-design-system-theme';
16
+ import { useDesignSystemTheme, useAppDesignTokens, type DesignTokens } from '@umituz/react-native-design-system-theme';
18
17
  import { AtomicText, ScreenLayout } from '@umituz/react-native-design-system';
19
18
  import { useLocalization, getLanguageByCode } from '@umituz/react-native-localization';
20
19
  import { SettingItem } from '../components/SettingItem';
@@ -22,7 +21,7 @@ import { SettingItem } from '../components/SettingItem';
22
21
  export const AppearanceScreen: React.FC = () => {
23
22
  const { t, currentLanguage } = useLocalization();
24
23
  const navigation = useNavigation();
25
- const { themeMode, toggleTheme } = useTheme();
24
+ const { themeMode, setThemeMode } = useDesignSystemTheme();
26
25
  const tokens = useAppDesignTokens();
27
26
  const styles = getStyles(tokens);
28
27
 
@@ -35,7 +34,8 @@ export const AppearanceScreen: React.FC = () => {
35
34
  };
36
35
 
37
36
  const handleThemeToggle = () => {
38
- toggleTheme();
37
+ const newMode = themeMode === 'dark' ? 'light' : 'dark';
38
+ setThemeMode(newMode);
39
39
  };
40
40
 
41
41
  return (
@@ -51,8 +51,10 @@ export const AppearanceScreen: React.FC = () => {
51
51
  </View>
52
52
 
53
53
  {/* Language Section */}
54
- <List.Section>
55
- <List.Subheader style={{ color: tokens.colors.textSecondary }}>{t('settings.language')}</List.Subheader>
54
+ <View style={{ marginBottom: tokens.spacing.md }}>
55
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
56
+ {t('settings.language')}
57
+ </AtomicText>
56
58
  <SettingItem
57
59
  icon="Languages"
58
60
  iconGradient={((tokens.colors as any).settingGradients?.language as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
@@ -61,11 +63,13 @@ export const AppearanceScreen: React.FC = () => {
61
63
  onPress={handleLanguagePress}
62
64
  testID="language-button"
63
65
  />
64
- </List.Section>
66
+ </View>
65
67
 
66
68
  {/* Theme Section */}
67
- <List.Section>
68
- <List.Subheader style={{ color: tokens.colors.textSecondary }}>{t('settings.appearance.darkMode')}</List.Subheader>
69
+ <View style={{ marginBottom: tokens.spacing.md }}>
70
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
71
+ {t('settings.appearance.darkMode')}
72
+ </AtomicText>
69
73
  <SettingItem
70
74
  icon={themeMode === 'dark' ? 'Moon' : 'Sun'}
71
75
  iconGradient={
@@ -78,7 +82,7 @@ export const AppearanceScreen: React.FC = () => {
78
82
  onPress={handleThemeToggle}
79
83
  testID="theme-button"
80
84
  />
81
- </List.Section>
85
+ </View>
82
86
  </ScreenLayout>
83
87
  );
84
88
  };
@@ -88,11 +92,21 @@ const getStyles = (tokens: DesignTokens) =>
88
92
  header: {
89
93
  paddingBottom: tokens.spacing.lg,
90
94
  paddingTop: tokens.spacing.md,
95
+ paddingHorizontal: tokens.spacing.lg,
91
96
  },
92
97
  headerSubtitle: {
93
98
  marginTop: tokens.spacing.sm,
94
99
  lineHeight: 20,
95
100
  opacity: 0.8,
96
101
  },
102
+ sectionHeader: {
103
+ paddingHorizontal: tokens.spacing.lg,
104
+ paddingTop: tokens.spacing.lg,
105
+ paddingBottom: tokens.spacing.md,
106
+ textTransform: 'uppercase',
107
+ letterSpacing: 1,
108
+ fontWeight: '600',
109
+ fontSize: 12,
110
+ },
97
111
  });
98
112
 
@@ -15,7 +15,7 @@ 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';
18
+ import { useAppDesignTokens, withAlpha, STATIC_TOKENS, type DesignTokens } from '@umituz/react-native-design-system-theme';
19
19
  import { AtomicIcon, AtomicText, ScreenLayout } from '@umituz/react-native-design-system';
20
20
  import { useLocalization, searchLanguages, Language, LANGUAGES } from '@umituz/react-native-localization';
21
21
 
@@ -12,12 +12,11 @@
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
- import { useTheme, useAppDesignTokens } from '@umituz/react-native-design-system-theme';
19
+ import { useDesignSystemTheme, useAppDesignTokens } from '@umituz/react-native-design-system-theme';
21
20
  import { ScreenLayout, AtomicIcon, AtomicText } from '@umituz/react-native-design-system';
22
21
  import { SettingItem } from '../components/SettingItem';
23
22
  import { getLanguageByCode, useLocalization } from '@umituz/react-native-localization';
@@ -87,10 +86,11 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
87
86
  config = {}
88
87
  }) => {
89
88
  const navigation = useNavigation();
90
- const { theme, themeMode } = useTheme();
89
+ const { themeMode } = useDesignSystemTheme();
91
90
  const tokens = useAppDesignTokens();
92
91
  const insets = useSafeAreaInsets();
93
92
  const { currentLanguage, t } = useLocalization();
93
+ const styles = getStyles(tokens);
94
94
 
95
95
  const currentLang = getLanguageByCode(currentLanguage);
96
96
  const languageDisplay = currentLang ? `${currentLang.flag} ${currentLang.nativeName}` : 'English';
@@ -247,12 +247,12 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
247
247
  <View style={[
248
248
  styles.header,
249
249
  {
250
- borderBottomColor: theme.colors.borderLight,
251
- backgroundColor: theme.colors.surface,
250
+ borderBottomColor: tokens.colors.borderLight,
251
+ backgroundColor: tokens.colors.surface,
252
252
  paddingTop: insets.top,
253
253
  }
254
254
  ]}>
255
- <AtomicText type="headlineLarge" style={{ color: theme.colors.textPrimary, flex: 1 }}>
255
+ <AtomicText type="headlineLarge" style={{ color: tokens.colors.textPrimary, flex: 1 }}>
256
256
  {t('navigation.settings') || 'Settings'}
257
257
  </AtomicText>
258
258
  <TouchableOpacity
@@ -267,103 +267,122 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
267
267
 
268
268
  {/* Appearance Section */}
269
269
  {features.appearance && (
270
- <List.Section style={{ marginBottom: 8 }}>
271
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.appearance')}</List.Subheader>
270
+ <View style={{ marginBottom: tokens.spacing.md }}>
271
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
272
+ {t('settings.sections.appearance')}
273
+ </AtomicText>
272
274
  <SettingItem
273
275
  icon="Palette"
274
- iconGradient={theme.colors.settingGradients.themeLight as unknown as string[]}
276
+ iconGradient={((tokens.colors as any).settingGradients?.themeLight as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
275
277
  title={t('settings.appearance.title')}
276
278
  description={t('settings.appearance.themeDescription')}
277
279
  onPress={handleAppearancePress}
278
280
  testID="appearance-button"
279
281
  />
280
- </List.Section>
282
+ </View>
281
283
  )}
282
284
 
283
285
  {/* General Section - Notifications */}
284
286
  {features.notifications && (
285
- <List.Section style={{ marginBottom: 8 }}>
286
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.general')}</List.Subheader>
287
+ <View style={{ marginBottom: tokens.spacing.md }}>
288
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
289
+ {t('settings.sections.general')}
290
+ </AtomicText>
287
291
  <SettingItem
288
292
  icon="Bell"
289
- iconGradient={theme.colors.settingGradients.notifications as unknown as string[]}
293
+ iconGradient={((tokens.colors as any).settingGradients?.notifications as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
290
294
  title={t('settings.notifications.title')}
291
295
  description={t('settings.notifications.description')}
292
296
  onPress={handleNotificationsPress}
293
297
  testID="notifications-button"
294
298
  />
295
- </List.Section>
299
+ </View>
296
300
  )}
297
301
 
298
302
  {/* Development/Test: Show Onboarding */}
299
303
  {__DEV__ && useOnboardingStore && (
300
- <List.Section style={{ marginBottom: 8 }}>
301
- <List.Subheader style={{ color: theme.colors.textSecondary }}>Development</List.Subheader>
304
+ <View style={{ marginBottom: tokens.spacing.md }}>
305
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
306
+ Development
307
+ </AtomicText>
302
308
  <SettingItem
303
309
  icon="Play"
304
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
310
+ iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
305
311
  title="Show Onboarding (Dev)"
306
312
  description="Navigate to onboarding screen"
307
313
  onPress={handleShowOnboarding}
308
314
  testID="show-onboarding-button"
309
315
  />
310
- </List.Section>
316
+ </View>
311
317
  )}
312
318
 
313
319
  {/* About & Legal Section */}
314
320
  {(features.about || features.legal) && (
315
- <List.Section style={{ marginBottom: 8 }}>
316
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.about')}</List.Subheader>
321
+ <View style={{ marginBottom: tokens.spacing.md }}>
322
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
323
+ {t('settings.sections.about')}
324
+ </AtomicText>
317
325
  {features.about && (
318
326
  <SettingItem
319
327
  icon="Info"
320
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
328
+ iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
321
329
  title={t('settings.about.title')}
322
330
  description={t('settings.about.description')}
323
331
  onPress={handleAboutPress}
324
332
  testID="about-button"
325
333
  />
326
334
  )}
327
- {features.about && features.legal && <Divider />}
335
+ {features.about && features.legal && (
336
+ <View style={{ height: 1, backgroundColor: tokens.colors.borderLight, marginVertical: tokens.spacing.sm }} />
337
+ )}
328
338
  {features.legal && (
329
339
  <SettingItem
330
340
  icon="FileText"
331
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
341
+ iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
332
342
  title={t('settings.legal.title')}
333
343
  description={t('settings.legal.description')}
334
344
  onPress={handleLegalPress}
335
345
  testID="legal-button"
336
346
  />
337
347
  )}
338
- </List.Section>
348
+ </View>
339
349
  )}
340
350
 
341
351
  {/* Fallback: Show message if no features are enabled */}
342
352
  {!hasAnyFeatures && (
343
- <List.Section>
344
- <List.Subheader style={{ color: theme.colors.textSecondary }}>
353
+ <View>
354
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
345
355
  {t('settings.noOptionsAvailable') || 'No settings available'}
346
- </List.Subheader>
347
- </List.Section>
356
+ </AtomicText>
357
+ </View>
348
358
  )}
349
359
  </ScreenLayout>
350
360
  );
351
361
  };
352
362
 
353
- const styles = StyleSheet.create({
363
+ const getStyles = (tokens: any) => StyleSheet.create({
354
364
  header: {
355
365
  flexDirection: 'row',
356
366
  alignItems: 'center',
357
367
  justifyContent: 'space-between',
358
- paddingHorizontal: 16,
359
- paddingBottom: 12,
360
- paddingTop: 12,
368
+ paddingHorizontal: tokens.spacing.md,
369
+ paddingBottom: tokens.spacing.md,
370
+ paddingTop: tokens.spacing.md,
361
371
  borderBottomWidth: 1,
362
372
  zIndex: 1000,
363
373
  },
374
+ sectionHeader: {
375
+ paddingHorizontal: tokens.spacing.lg,
376
+ paddingTop: tokens.spacing.lg,
377
+ paddingBottom: tokens.spacing.md,
378
+ textTransform: 'uppercase',
379
+ letterSpacing: 1,
380
+ fontWeight: '600',
381
+ fontSize: 12,
382
+ },
364
383
  closeButton: {
365
- padding: 8,
366
- marginLeft: 8,
384
+ padding: tokens.spacing.sm,
385
+ marginLeft: tokens.spacing.sm,
367
386
  },
368
387
  });
369
388