@umituz/react-native-localization 3.5.57 → 3.5.58

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-localization",
3
- "version": "3.5.57",
3
+ "version": "3.5.58",
4
4
  "description": "Generic localization system for React Native apps with i18n support",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -4,7 +4,9 @@
4
4
  */
5
5
 
6
6
  import React, { useMemo } from 'react';
7
- import { TouchableOpacity, Text } from 'react-native';
7
+ import { TouchableOpacity, View } from 'react-native';
8
+ // @ts-ignore - Optional peer dependency
9
+ import { useAppDesignTokens, AtomicText } from '@umituz/react-native-design-system';
8
10
  import { useLanguageSwitcher } from './useLanguageSwitcher';
9
11
  import { styles, DEFAULT_CONFIG_VALUES } from './LanguageSwitcher.styles';
10
12
 
@@ -21,41 +23,6 @@ export interface LanguageSwitcherProps {
21
23
  accessibilityLabel?: string;
22
24
  }
23
25
 
24
- const renderContent = (
25
- showFlag: boolean,
26
- showName: boolean,
27
- flag: string | undefined,
28
- nativeName: string,
29
- color: string | undefined,
30
- iconStyle: any,
31
- textStyle: any
32
- ) => {
33
- if (showFlag && showName) {
34
- return (
35
- <>
36
- <Text style={[styles.flag, iconStyle]}>{flag}</Text>
37
- <Text style={[styles.languageName, { color }, textStyle]}>
38
- {nativeName}
39
- </Text>
40
- </>
41
- );
42
- }
43
-
44
- if (showFlag) {
45
- return <Text style={[styles.flag, iconStyle]}>{flag}</Text>;
46
- }
47
-
48
- if (showName) {
49
- return (
50
- <Text style={[styles.languageName, { color }, textStyle]}>
51
- {nativeName}
52
- </Text>
53
- );
54
- }
55
-
56
- return <Text style={[styles.icon, { color }, iconStyle]}>🌐</Text>;
57
- };
58
-
59
26
  export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
60
27
  showName = false,
61
28
  showFlag = true,
@@ -68,6 +35,7 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
68
35
  disabled = false,
69
36
  accessibilityLabel,
70
37
  }) => {
38
+ const tokens = useAppDesignTokens();
71
39
  const { currentLang, handlePress } = useLanguageSwitcher({ onPress, disabled });
72
40
 
73
41
  const accessibilityProps = useMemo(() => ({
@@ -77,9 +45,16 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
77
45
  accessible: true,
78
46
  }), [accessibilityLabel, currentLang.nativeName, disabled]);
79
47
 
48
+ const textColor = color || tokens.colors.textPrimary;
49
+
80
50
  return (
81
51
  <TouchableOpacity
82
- style={[styles.container, style, disabled && styles.disabled]}
52
+ style={[
53
+ styles.container,
54
+ { gap: tokens.spacing.xs },
55
+ style,
56
+ disabled && styles.disabled
57
+ ]}
83
58
  onPress={handlePress}
84
59
  activeOpacity={disabled ? 1 : DEFAULT_CONFIG_VALUES.activeOpacity}
85
60
  hitSlop={DEFAULT_CONFIG_VALUES.hitSlop}
@@ -87,9 +62,27 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
87
62
  disabled={disabled}
88
63
  {...accessibilityProps}
89
64
  >
90
- {renderContent(showFlag, showName, currentLang.flag, currentLang.nativeName, color, iconStyle, textStyle)}
65
+ {showFlag && (
66
+ <AtomicText style={[styles.flag, iconStyle]}>
67
+ {currentLang.flag || '🌐'}
68
+ </AtomicText>
69
+ )}
70
+ {showName && (
71
+ <AtomicText
72
+ type="bodySmall"
73
+ style={[styles.languageName, { color: textColor, fontWeight: '600' }, textStyle]}
74
+ >
75
+ {currentLang.nativeName}
76
+ </AtomicText>
77
+ )}
78
+ {!showFlag && !showName && (
79
+ <AtomicText style={[styles.icon, { color: textColor }, iconStyle]}>
80
+ 🌐
81
+ </AtomicText>
82
+ )}
91
83
  </TouchableOpacity>
92
84
  );
93
85
  };
94
86
 
95
87
  export default LanguageSwitcher;
88
+
@@ -9,10 +9,7 @@ export const styles = StyleSheet.create({
9
9
  flexDirection: 'row',
10
10
  alignItems: 'center',
11
11
  justifyContent: 'space-between',
12
- padding: 16,
13
- borderRadius: 12,
14
12
  borderWidth: 1,
15
- marginBottom: 8,
16
13
  },
17
14
  selectedLanguageItem: {
18
15
  borderWidth: 2,
@@ -29,18 +26,15 @@ export const styles = StyleSheet.create({
29
26
  languageText: {
30
27
  flex: 1,
31
28
  flexShrink: 1,
32
- marginRight: 12,
33
29
  },
34
30
  nativeName: {
35
- fontSize: 16,
36
- fontWeight: '600',
37
- marginBottom: 4,
31
+ // Styling moved to themedStyles in component for token support
38
32
  },
39
33
  languageName: {
40
- fontSize: 14,
34
+ // Styling moved to themedStyles in component for token support
41
35
  },
42
36
  checkIcon: {
43
- fontSize: 18,
44
- fontWeight: 'bold',
37
+ // Replaced by AtomicIcon
45
38
  },
46
39
  });
40
+
@@ -9,13 +9,12 @@ import React, { useMemo } from 'react';
9
9
  import {
10
10
  View,
11
11
  TouchableOpacity,
12
- Text,
13
12
  type StyleProp,
14
13
  type ViewStyle,
15
14
  type TextStyle,
16
15
  } from 'react-native';
17
16
  // @ts-ignore - Optional peer dependency
18
- import { useAppDesignTokens } from '@umituz/react-native-design-system';
17
+ import { useAppDesignTokens, AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
19
18
  import type { Language } from '../../infrastructure/storage/types/Language';
20
19
  import { styles } from './LanguageItem.styles';
21
20
 
@@ -42,22 +41,24 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
42
41
 
43
42
  const themedStyles = useMemo(() => ({
44
43
  languageItem: {
44
+ padding: tokens.spacing.md,
45
+ borderRadius: tokens.borders.radius.md,
45
46
  backgroundColor: tokens.colors.backgroundSecondary,
46
47
  borderColor: tokens.colors.border,
48
+ marginBottom: tokens.spacing.sm,
47
49
  } as ViewStyle,
48
50
  selectedLanguageItem: {
49
51
  borderColor: tokens.colors.primary,
50
- backgroundColor: tokens.colors.primaryLight,
52
+ backgroundColor: tokens.colors.primaryContainer,
53
+ borderWidth: 2,
51
54
  } as ViewStyle,
52
55
  nativeName: {
53
56
  color: tokens.colors.textPrimary,
57
+ marginBottom: tokens.spacing.xs / 2,
54
58
  } as TextStyle,
55
59
  languageName: {
56
60
  color: tokens.colors.textSecondary,
57
61
  } as TextStyle,
58
- checkIcon: {
59
- color: tokens.colors.primary,
60
- } as TextStyle,
61
62
  }), [tokens]);
62
63
 
63
64
  return (
@@ -66,28 +67,35 @@ export const LanguageItem: React.FC<LanguageItemProps> = ({
66
67
  style={[
67
68
  styles.languageItem,
68
69
  themedStyles.languageItem,
69
- customStyles?.languageItem,
70
70
  isSelected ? [styles.selectedLanguageItem, themedStyles.selectedLanguageItem] : undefined,
71
+ customStyles?.languageItem,
71
72
  ]}
72
73
  onPress={() => onSelect(item.code)}
73
74
  activeOpacity={0.7}
74
75
  >
75
76
  <View style={[styles.languageContent, customStyles?.languageContent]}>
76
- <Text style={[styles.flag, customStyles?.flag]}>
77
+ <AtomicText style={[styles.flag, customStyles?.flag]}>
77
78
  {item.flag || '🌐'}
78
- </Text>
79
- <View style={[styles.languageText, customStyles?.languageText]}>
80
- <Text style={[styles.nativeName, themedStyles.nativeName, customStyles?.nativeName]}>
79
+ </AtomicText>
80
+ <View style={[styles.languageText, { gap: tokens.spacing.xs / 2 }, customStyles?.languageText]}>
81
+ <AtomicText
82
+ type="bodyMedium"
83
+ style={[themedStyles.nativeName, { fontWeight: '700' }, customStyles?.nativeName]}
84
+ >
81
85
  {item.nativeName}
82
- </Text>
83
- <Text style={[styles.languageName, themedStyles.languageName, customStyles?.nativeName]}>
86
+ </AtomicText>
87
+ <AtomicText
88
+ type="labelMedium"
89
+ style={[themedStyles.languageName, customStyles?.nativeName]}
90
+ >
84
91
  {item.name}
85
- </Text>
92
+ </AtomicText>
86
93
  </View>
87
94
  </View>
88
95
  {isSelected && (
89
- <Text style={[styles.checkIcon, themedStyles.checkIcon, customStyles?.flag]}>✓</Text>
96
+ <AtomicIcon name="checkmark" size="sm" color="primary" />
90
97
  )}
91
98
  </TouchableOpacity>
92
99
  );
93
100
  };
101
+
@@ -6,10 +6,11 @@ import { StyleSheet } from 'react-native';
6
6
 
7
7
  export const styles = StyleSheet.create({
8
8
  container: {
9
- flex: 1,
9
+ // Styling handled by ScreenLayout
10
10
  },
11
11
  listContent: {
12
- paddingHorizontal: 20,
13
- paddingBottom: 32,
12
+ // Horizontal padding handled by ScreenLayout contentWrapper
13
+ // Bottom padding handled in component using tokens
14
14
  },
15
15
  });
16
+
@@ -4,11 +4,16 @@
4
4
  */
5
5
 
6
6
  import React from 'react';
7
- import { View, FlatList } from 'react-native';
7
+ import { FlatList } from 'react-native';
8
8
  // @ts-ignore - Optional peer dependency
9
9
  import { useNavigation } from '@react-navigation/native';
10
10
  // @ts-ignore - Optional peer dependency
11
- import { useAppDesignTokens, SearchBar } from '@umituz/react-native-design-system';
11
+ import {
12
+ useAppDesignTokens,
13
+ SearchBar,
14
+ ScreenLayout,
15
+ NavigationHeader
16
+ } from '@umituz/react-native-design-system';
12
17
  import { useLanguageSelection } from '../../infrastructure/hooks/useLanguageSelection';
13
18
  import { LanguageItem } from '../components/LanguageItem';
14
19
  import type { Language } from '../../infrastructure/storage/types/Language';
@@ -17,7 +22,8 @@ import { styles } from './LanguageSelectionScreen.styles';
17
22
  interface LanguageSelectionScreenProps {
18
23
  renderLanguageItem?: (item: Language, isSelected: boolean, onSelect: (code: string) => void) => React.ReactNode;
19
24
  renderSearchInput?: (value: string, onChange: (value: string) => void, placeholder: string) => React.ReactNode;
20
- containerComponent?: React.ComponentType<{ children: React.ReactNode }>;
25
+ headerTitle?: string;
26
+ onBackPress?: () => void;
21
27
  styles?: {
22
28
  container?: any;
23
29
  searchContainer?: any;
@@ -38,7 +44,8 @@ interface LanguageSelectionScreenProps {
38
44
  export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = ({
39
45
  renderLanguageItem,
40
46
  renderSearchInput,
41
- containerComponent: Container,
47
+ headerTitle,
48
+ onBackPress,
42
49
  styles: customStyles,
43
50
  searchPlaceholder = "settings.languageSelection.searchPlaceholder",
44
51
  testID = 'language-selection-screen',
@@ -84,27 +91,53 @@ export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = (
84
91
  value={searchQuery}
85
92
  onChangeText={setSearchQuery}
86
93
  placeholder={searchPlaceholder}
87
- containerStyle={customStyles?.searchContainer}
94
+ containerStyle={[
95
+ { marginBottom: tokens.spacing.md },
96
+ customStyles?.searchContainer
97
+ ]}
88
98
  inputStyle={customStyles?.searchInput}
89
99
  />
90
100
  );
91
101
  };
92
102
 
93
- const content = (
94
- <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }, customStyles?.container]} testID={testID}>
103
+ const handleBack = () => {
104
+ if (onBackPress) {
105
+ onBackPress();
106
+ } else {
107
+ navigation.goBack();
108
+ }
109
+ };
110
+
111
+ return (
112
+ <ScreenLayout
113
+ testID={testID}
114
+ scrollable={false}
115
+ edges={['top', 'bottom', 'left', 'right']}
116
+ backgroundColor={tokens.colors.backgroundPrimary}
117
+ header={
118
+ <NavigationHeader
119
+ title={headerTitle || ""}
120
+ onBackPress={handleBack}
121
+ />
122
+ }
123
+ containerStyle={customStyles?.container}
124
+ >
95
125
  {renderSearchComponent()}
96
126
  <FlatList
97
127
  data={filteredLanguages}
98
128
  renderItem={renderItem}
99
129
  keyExtractor={item => item.code}
100
- contentContainerStyle={[styles.listContent, customStyles?.listContent]}
130
+ contentContainerStyle={[
131
+ styles.listContent,
132
+ { paddingBottom: tokens.spacing.xl },
133
+ customStyles?.listContent
134
+ ]}
101
135
  showsVerticalScrollIndicator={false}
102
136
  keyboardShouldPersistTaps="handled"
103
137
  />
104
- </View>
138
+ </ScreenLayout>
105
139
  );
106
-
107
- return Container ? <Container>{content}</Container> : content;
108
140
  };
109
141
 
110
142
  export default LanguageSelectionScreen;
143
+