@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 +1 -2
- package/src/presentation/components/DisclaimerSetting.tsx +1 -1
- package/src/presentation/components/SettingItem.tsx +62 -65
- package/src/presentation/screens/AppearanceScreen.tsx +26 -11
- package/src/presentation/screens/LanguageSelectionScreen.tsx +3 -2
- package/src/presentation/screens/SettingsScreen.tsx +55 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "1.3.
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
18
|
-
import { AtomicText
|
|
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,
|
|
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
|
-
|
|
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
|
-
<
|
|
55
|
-
<
|
|
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
|
-
</
|
|
67
|
+
</View>
|
|
65
68
|
|
|
66
69
|
{/* Theme Section */}
|
|
67
|
-
<
|
|
68
|
-
<
|
|
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
|
-
</
|
|
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 {
|
|
19
|
-
import { AtomicIcon, AtomicText
|
|
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 {
|
|
21
|
-
import { ScreenLayout
|
|
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 {
|
|
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:
|
|
251
|
-
backgroundColor:
|
|
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:
|
|
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
|
-
<
|
|
271
|
-
<
|
|
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={
|
|
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
|
-
</
|
|
283
|
+
</View>
|
|
281
284
|
)}
|
|
282
285
|
|
|
283
286
|
{/* General Section - Notifications */}
|
|
284
287
|
{features.notifications && (
|
|
285
|
-
<
|
|
286
|
-
<
|
|
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={
|
|
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
|
-
</
|
|
300
|
+
</View>
|
|
296
301
|
)}
|
|
297
302
|
|
|
298
303
|
{/* Development/Test: Show Onboarding */}
|
|
299
304
|
{__DEV__ && useOnboardingStore && (
|
|
300
|
-
<
|
|
301
|
-
<
|
|
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={
|
|
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
|
-
</
|
|
317
|
+
</View>
|
|
311
318
|
)}
|
|
312
319
|
|
|
313
320
|
{/* About & Legal Section */}
|
|
314
321
|
{(features.about || features.legal) && (
|
|
315
|
-
<
|
|
316
|
-
<
|
|
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={
|
|
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 &&
|
|
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={
|
|
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
|
-
</
|
|
349
|
+
</View>
|
|
339
350
|
)}
|
|
340
351
|
|
|
341
352
|
{/* Fallback: Show message if no features are enabled */}
|
|
342
353
|
{!hasAnyFeatures && (
|
|
343
|
-
<
|
|
344
|
-
<
|
|
354
|
+
<View>
|
|
355
|
+
<AtomicText type="labelMedium" color="textSecondary" style={styles.sectionHeader}>
|
|
345
356
|
{t('settings.noOptionsAvailable') || 'No settings available'}
|
|
346
|
-
</
|
|
347
|
-
</
|
|
357
|
+
</AtomicText>
|
|
358
|
+
</View>
|
|
348
359
|
)}
|
|
349
360
|
</ScreenLayout>
|
|
350
361
|
);
|
|
351
362
|
};
|
|
352
363
|
|
|
353
|
-
const
|
|
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:
|
|
359
|
-
paddingBottom:
|
|
360
|
-
paddingTop:
|
|
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:
|
|
366
|
-
marginLeft:
|
|
385
|
+
padding: tokens.spacing.sm,
|
|
386
|
+
marginLeft: tokens.spacing.sm,
|
|
367
387
|
},
|
|
368
388
|
});
|
|
369
389
|
|