@umituz/react-native-settings 1.3.9 → 1.3.11

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.9",
3
+ "version": "1.3.11",
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": {
@@ -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>;
@@ -12,13 +12,12 @@
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
- import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
17
+ import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system-atoms';
19
18
  import { useAppDesignTokens } from '@umituz/react-native-design-system-theme';
20
- import type { IconName } from '@umituz/react-native-design-system';
21
- import type { DesignTokens } from '@umituz/react-native-design-system';
19
+ import type { IconName } from '@umituz/react-native-design-system-atoms';
20
+ import type { DesignTokens } from '@umituz/react-native-design-system-theme';
22
21
 
23
22
  interface SettingItemProps {
24
23
  /** Icon name from Lucide library */
@@ -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" customColor={tokens.colors.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,18 +11,18 @@
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';
18
- import { AtomicText, ScreenLayout } from '@umituz/react-native-design-system';
16
+ import { useDesignSystemTheme, useAppDesignTokens, type DesignTokens } from '@umituz/react-native-design-system-theme';
17
+ import { AtomicText } from '@umituz/react-native-design-system-atoms';
18
+ import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
19
19
  import { useLocalization, getLanguageByCode } from '@umituz/react-native-localization';
20
20
  import { SettingItem } from '../components/SettingItem';
21
21
 
22
22
  export const AppearanceScreen: React.FC = () => {
23
23
  const { t, currentLanguage } = useLocalization();
24
24
  const navigation = useNavigation();
25
- const { themeMode, toggleTheme } = useTheme();
25
+ const { themeMode, setThemeMode } = useDesignSystemTheme();
26
26
  const tokens = useAppDesignTokens();
27
27
  const styles = getStyles(tokens);
28
28
 
@@ -35,7 +35,8 @@ export const AppearanceScreen: React.FC = () => {
35
35
  };
36
36
 
37
37
  const handleThemeToggle = () => {
38
- toggleTheme();
38
+ const newMode = themeMode === 'dark' ? 'light' : 'dark';
39
+ setThemeMode(newMode);
39
40
  };
40
41
 
41
42
  return (
@@ -51,8 +52,10 @@ export const AppearanceScreen: React.FC = () => {
51
52
  </View>
52
53
 
53
54
  {/* Language Section */}
54
- <List.Section>
55
- <List.Subheader style={{ color: tokens.colors.textSecondary }}>{t('settings.language')}</List.Subheader>
55
+ <View style={{ marginBottom: tokens.spacing.md }}>
56
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
57
+ {t('settings.language')}
58
+ </AtomicText>
56
59
  <SettingItem
57
60
  icon="Languages"
58
61
  iconGradient={((tokens.colors as any).settingGradients?.language as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
@@ -61,11 +64,13 @@ export const AppearanceScreen: React.FC = () => {
61
64
  onPress={handleLanguagePress}
62
65
  testID="language-button"
63
66
  />
64
- </List.Section>
67
+ </View>
65
68
 
66
69
  {/* Theme Section */}
67
- <List.Section>
68
- <List.Subheader style={{ color: tokens.colors.textSecondary }}>{t('settings.appearance.darkMode')}</List.Subheader>
70
+ <View style={{ marginBottom: tokens.spacing.md }}>
71
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
72
+ {t('settings.appearance.darkMode')}
73
+ </AtomicText>
69
74
  <SettingItem
70
75
  icon={themeMode === 'dark' ? 'Moon' : 'Sun'}
71
76
  iconGradient={
@@ -78,7 +83,7 @@ export const AppearanceScreen: React.FC = () => {
78
83
  onPress={handleThemeToggle}
79
84
  testID="theme-button"
80
85
  />
81
- </List.Section>
86
+ </View>
82
87
  </ScreenLayout>
83
88
  );
84
89
  };
@@ -88,11 +93,21 @@ const getStyles = (tokens: DesignTokens) =>
88
93
  header: {
89
94
  paddingBottom: tokens.spacing.lg,
90
95
  paddingTop: tokens.spacing.md,
96
+ paddingHorizontal: tokens.spacing.lg,
91
97
  },
92
98
  headerSubtitle: {
93
99
  marginTop: tokens.spacing.sm,
94
100
  lineHeight: 20,
95
101
  opacity: 0.8,
96
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
+ },
97
112
  });
98
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
  /**
@@ -12,13 +12,13 @@
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';
21
- import { ScreenLayout, AtomicIcon, AtomicText } from '@umituz/react-native-design-system';
19
+ import { useDesignSystemTheme, useAppDesignTokens } from '@umituz/react-native-design-system-theme';
20
+ import { ScreenLayout } from '@umituz/react-native-design-system-organisms';
21
+ import { AtomicIcon, AtomicText } from '@umituz/react-native-design-system-atoms';
22
22
  import { SettingItem } from '../components/SettingItem';
23
23
  import { getLanguageByCode, useLocalization } from '@umituz/react-native-localization';
24
24
  import { SettingsConfig } from './types';
@@ -87,10 +87,11 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
87
87
  config = {}
88
88
  }) => {
89
89
  const navigation = useNavigation();
90
- const { theme, themeMode } = useTheme();
90
+ const { themeMode } = useDesignSystemTheme();
91
91
  const tokens = useAppDesignTokens();
92
92
  const insets = useSafeAreaInsets();
93
93
  const { currentLanguage, t } = useLocalization();
94
+ const styles = getStyles(tokens);
94
95
 
95
96
  const currentLang = getLanguageByCode(currentLanguage);
96
97
  const languageDisplay = currentLang ? `${currentLang.flag} ${currentLang.nativeName}` : 'English';
@@ -247,12 +248,12 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
247
248
  <View style={[
248
249
  styles.header,
249
250
  {
250
- borderBottomColor: theme.colors.borderLight,
251
- backgroundColor: theme.colors.surface,
251
+ borderBottomColor: tokens.colors.borderLight,
252
+ backgroundColor: tokens.colors.surface,
252
253
  paddingTop: insets.top,
253
254
  }
254
255
  ]}>
255
- <AtomicText type="headlineLarge" style={{ color: theme.colors.textPrimary, flex: 1 }}>
256
+ <AtomicText type="headlineLarge" style={{ color: tokens.colors.textPrimary, flex: 1 }}>
256
257
  {t('navigation.settings') || 'Settings'}
257
258
  </AtomicText>
258
259
  <TouchableOpacity
@@ -267,103 +268,122 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
267
268
 
268
269
  {/* Appearance Section */}
269
270
  {features.appearance && (
270
- <List.Section style={{ marginBottom: 8 }}>
271
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.appearance')}</List.Subheader>
271
+ <View style={{ marginBottom: tokens.spacing.md }}>
272
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
273
+ {t('settings.sections.appearance')}
274
+ </AtomicText>
272
275
  <SettingItem
273
276
  icon="Palette"
274
- iconGradient={theme.colors.settingGradients.themeLight as unknown as string[]}
277
+ iconGradient={((tokens.colors as any).settingGradients?.themeLight as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
275
278
  title={t('settings.appearance.title')}
276
279
  description={t('settings.appearance.themeDescription')}
277
280
  onPress={handleAppearancePress}
278
281
  testID="appearance-button"
279
282
  />
280
- </List.Section>
283
+ </View>
281
284
  )}
282
285
 
283
286
  {/* General Section - Notifications */}
284
287
  {features.notifications && (
285
- <List.Section style={{ marginBottom: 8 }}>
286
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.general')}</List.Subheader>
288
+ <View style={{ marginBottom: tokens.spacing.md }}>
289
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
290
+ {t('settings.sections.general')}
291
+ </AtomicText>
287
292
  <SettingItem
288
293
  icon="Bell"
289
- iconGradient={theme.colors.settingGradients.notifications as unknown as string[]}
294
+ iconGradient={((tokens.colors as any).settingGradients?.notifications as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
290
295
  title={t('settings.notifications.title')}
291
296
  description={t('settings.notifications.description')}
292
297
  onPress={handleNotificationsPress}
293
298
  testID="notifications-button"
294
299
  />
295
- </List.Section>
300
+ </View>
296
301
  )}
297
302
 
298
303
  {/* Development/Test: Show Onboarding */}
299
304
  {__DEV__ && useOnboardingStore && (
300
- <List.Section style={{ marginBottom: 8 }}>
301
- <List.Subheader style={{ color: theme.colors.textSecondary }}>Development</List.Subheader>
305
+ <View style={{ marginBottom: tokens.spacing.md }}>
306
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
307
+ Development
308
+ </AtomicText>
302
309
  <SettingItem
303
310
  icon="Play"
304
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
311
+ iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
305
312
  title="Show Onboarding (Dev)"
306
313
  description="Navigate to onboarding screen"
307
314
  onPress={handleShowOnboarding}
308
315
  testID="show-onboarding-button"
309
316
  />
310
- </List.Section>
317
+ </View>
311
318
  )}
312
319
 
313
320
  {/* About & Legal Section */}
314
321
  {(features.about || features.legal) && (
315
- <List.Section style={{ marginBottom: 8 }}>
316
- <List.Subheader style={{ color: theme.colors.textSecondary }}>{t('settings.sections.about')}</List.Subheader>
322
+ <View style={{ marginBottom: tokens.spacing.md }}>
323
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
324
+ {t('settings.sections.about')}
325
+ </AtomicText>
317
326
  {features.about && (
318
327
  <SettingItem
319
328
  icon="Info"
320
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
329
+ iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
321
330
  title={t('settings.about.title')}
322
331
  description={t('settings.about.description')}
323
332
  onPress={handleAboutPress}
324
333
  testID="about-button"
325
334
  />
326
335
  )}
327
- {features.about && features.legal && <Divider />}
336
+ {features.about && features.legal && (
337
+ <View style={{ height: 1, backgroundColor: tokens.colors.borderLight, marginVertical: tokens.spacing.sm }} />
338
+ )}
328
339
  {features.legal && (
329
340
  <SettingItem
330
341
  icon="FileText"
331
- iconGradient={theme.colors.settingGradients.info as unknown as string[]}
342
+ iconGradient={((tokens.colors as any).settingGradients?.info as unknown as string[]) || [tokens.colors.primary, tokens.colors.secondary]}
332
343
  title={t('settings.legal.title')}
333
344
  description={t('settings.legal.description')}
334
345
  onPress={handleLegalPress}
335
346
  testID="legal-button"
336
347
  />
337
348
  )}
338
- </List.Section>
349
+ </View>
339
350
  )}
340
351
 
341
352
  {/* Fallback: Show message if no features are enabled */}
342
353
  {!hasAnyFeatures && (
343
- <List.Section>
344
- <List.Subheader style={{ color: theme.colors.textSecondary }}>
354
+ <View>
355
+ <AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
345
356
  {t('settings.noOptionsAvailable') || 'No settings available'}
346
- </List.Subheader>
347
- </List.Section>
357
+ </AtomicText>
358
+ </View>
348
359
  )}
349
360
  </ScreenLayout>
350
361
  );
351
362
  };
352
363
 
353
- const styles = StyleSheet.create({
364
+ const getStyles = (tokens: any) => StyleSheet.create({
354
365
  header: {
355
366
  flexDirection: 'row',
356
367
  alignItems: 'center',
357
368
  justifyContent: 'space-between',
358
- paddingHorizontal: 16,
359
- paddingBottom: 12,
360
- paddingTop: 12,
369
+ paddingHorizontal: tokens.spacing.md,
370
+ paddingBottom: tokens.spacing.md,
371
+ paddingTop: tokens.spacing.md,
361
372
  borderBottomWidth: 1,
362
373
  zIndex: 1000,
363
374
  },
375
+ sectionHeader: {
376
+ paddingHorizontal: tokens.spacing.lg,
377
+ paddingTop: tokens.spacing.lg,
378
+ paddingBottom: tokens.spacing.md,
379
+ textTransform: 'uppercase',
380
+ letterSpacing: 1,
381
+ fontWeight: '600',
382
+ fontSize: 12,
383
+ },
364
384
  closeButton: {
365
- padding: 8,
366
- marginLeft: 8,
385
+ padding: tokens.spacing.sm,
386
+ marginLeft: tokens.spacing.sm,
367
387
  },
368
388
  });
369
389