@umituz/react-native-settings 5.4.22 → 5.4.24

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.
Files changed (21) hide show
  1. package/package.json +1 -1
  2. package/src/domains/feedback/presentation/components/FeedbackForm.styles.ts +8 -2
  3. package/src/domains/gamification/components/AchievementItem.tsx +3 -2
  4. package/src/domains/gamification/components/GamificationScreen/GamificationScreen.tsx +2 -1
  5. package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -37
  6. package/src/domains/gamification/components/styles/achievementItemStyles.ts +75 -68
  7. package/src/domains/localization/infrastructure/components/LanguageSwitcher.styles.ts +28 -25
  8. package/src/domains/localization/infrastructure/components/LanguageSwitcher.tsx +6 -6
  9. package/src/domains/localization/presentation/components/LanguageItem.styles.ts +47 -33
  10. package/src/domains/localization/presentation/components/LanguageItem.tsx +9 -29
  11. package/src/domains/localization/scripts/prepublish.js +0 -36
  12. package/src/domains/localization/scripts/setup-languages.js +0 -85
  13. package/src/domains/localization/scripts/sync-translations.js +0 -124
  14. package/src/domains/localization/scripts/translate-missing.js +0 -211
  15. package/src/domains/localization/scripts/utils/file-parser.js +0 -104
  16. package/src/domains/localization/scripts/utils/key-detector.js +0 -45
  17. package/src/domains/localization/scripts/utils/key-extractor.js +0 -105
  18. package/src/domains/localization/scripts/utils/object-helper.js +0 -29
  19. package/src/domains/localization/scripts/utils/sync-helper.js +0 -49
  20. package/src/domains/localization/scripts/utils/translation-config.js +0 -116
  21. package/src/domains/localization/scripts/utils/translator.js +0 -91
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-settings",
3
- "version": "5.4.22",
3
+ "version": "5.4.24",
4
4
  "description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification - expo-store-review and expo-device now lazy loaded",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./dist/index.d.ts",
@@ -1,7 +1,8 @@
1
1
  import { StyleSheet } from "react-native";
2
2
  import type { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
3
+ import { withAlpha } from "@umituz/react-native-design-system/theme";
3
4
 
4
- export const getFeedbackFormStyles = (_tokens: ReturnType<typeof useAppDesignTokens>) =>
5
+ export const getFeedbackFormStyles = (tokens: ReturnType<typeof useAppDesignTokens>) =>
5
6
  StyleSheet.create({
6
7
  container: {
7
8
  width: "100%",
@@ -25,7 +26,7 @@ export const getFeedbackFormStyles = (_tokens: ReturnType<typeof useAppDesignTok
25
26
  alignItems: "center",
26
27
  marginVertical: 32,
27
28
  paddingVertical: 16,
28
- backgroundColor: "rgba(255,255,255,0.02)",
29
+ backgroundColor: withAlpha(tokens.colors.primary, 0.05),
29
30
  borderRadius: 16,
30
31
  },
31
32
  ratingLabel: {
@@ -34,6 +35,7 @@ export const getFeedbackFormStyles = (_tokens: ReturnType<typeof useAppDesignTok
34
35
  letterSpacing: 1,
35
36
  marginBottom: 16,
36
37
  textTransform: "uppercase",
38
+ color: tokens.colors.textSecondary,
37
39
  },
38
40
  stars: {
39
41
  flexDirection: "row",
@@ -52,10 +54,14 @@ export const getFeedbackFormStyles = (_tokens: ReturnType<typeof useAppDesignTok
52
54
  borderRadius: 16,
53
55
  padding: 16,
54
56
  fontSize: 15,
57
+ color: tokens.colors.textPrimary,
58
+ backgroundColor: tokens.colors.surfaceSecondary,
59
+ borderColor: tokens.colors.border,
55
60
  },
56
61
  errorText: {
57
62
  marginTop: 8,
58
63
  fontWeight: "600",
64
+ color: tokens.colors.error,
59
65
  },
60
66
  submitButton: {
61
67
  width: "100%",
@@ -8,7 +8,7 @@ import { View } from "react-native";
8
8
  import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system/atoms";
9
9
  import { useAppDesignTokens, withAlpha } from "@umituz/react-native-design-system/theme";
10
10
  import type { AchievementItemProps } from "./types/AchievementItemProps";
11
- import { achievementItemStyles as styles } from "./styles/achievementItemStyles";
11
+ import { createAchievementItemStyles } from "./styles/achievementItemStyles";
12
12
 
13
13
  export const AchievementItem: React.FC<AchievementItemProps> = ({
14
14
  title,
@@ -28,6 +28,7 @@ export const AchievementItem: React.FC<AchievementItemProps> = ({
28
28
  lockedOpacity,
29
29
  }) => {
30
30
  const tokens = useAppDesignTokens();
31
+ const styles = createAchievementItemStyles(tokens);
31
32
  const finalAccentColor = accentColor || tokens.colors.primary;
32
33
  const finalBackgroundColor = backgroundColor || tokens.colors.surface;
33
34
  const finalTextColor = textColor || tokens.colors.textPrimary;
@@ -61,7 +62,7 @@ export const AchievementItem: React.FC<AchievementItemProps> = ({
61
62
  </AtomicText>
62
63
  {isUnlocked && (
63
64
  <View style={[styles.checkmark, { backgroundColor: finalAccentColor }]}>
64
- <AtomicText style={[styles.checkmarkText, { color: tokens.colors.background }]}>
65
+ <AtomicText style={[styles.checkmarkText, { color: tokens.colors.onPrimary || '#FFFFFF' }]}>
65
66
 
66
67
  </AtomicText>
67
68
  </View>
@@ -14,7 +14,7 @@ import { LevelProgress } from "../LevelProgress";
14
14
  import { StreakDisplay } from "../StreakDisplay";
15
15
  import { StatsGrid } from "./StatsGrid";
16
16
  import { AchievementsList } from "./AchievementsList";
17
- import { styles } from "./styles";
17
+ import { createStyles } from "./styles";
18
18
  import type { GamificationScreenProps } from "./types";
19
19
 
20
20
  /**
@@ -39,6 +39,7 @@ export const GamificationScreenInner: React.FC<GamificationScreenProps> = ({
39
39
  }) => {
40
40
  const _navigation = useAppNavigation();
41
41
  const tokens = useAppDesignTokens();
42
+ const styles = createStyles(tokens);
42
43
 
43
44
  // Use tokens for fallbacks
44
45
  const finalAccentColor = accentColor || tokens.colors.primary;
@@ -3,41 +3,47 @@
3
3
  */
4
4
 
5
5
  import { StyleSheet } from "react-native";
6
+ import type { DesignTokens } from "@umituz/react-native-design-system/theme";
6
7
 
7
- export const styles = StyleSheet.create({
8
- container: {
9
- flex: 1,
10
- },
11
- scrollView: {
12
- flex: 1,
13
- },
14
- scrollContent: {
15
- padding: 16,
16
- paddingBottom: 32,
17
- },
18
- header: {
19
- marginBottom: 20,
20
- },
21
- title: {
22
- fontSize: 28,
23
- fontWeight: "bold",
24
- },
25
- section: {
26
- marginBottom: 24,
27
- },
28
- sectionTitle: {
29
- fontSize: 18,
30
- fontWeight: "600",
31
- marginBottom: 12,
32
- },
33
- statsGrid: {
34
- flexDirection: "row",
35
- flexWrap: "wrap",
36
- gap: 12,
37
- },
38
- emptyText: {
39
- fontSize: 14,
40
- textAlign: "center",
41
- paddingVertical: 20,
42
- },
43
- });
8
+ export const createStyles = (tokens: DesignTokens) =>
9
+ StyleSheet.create({
10
+ container: {
11
+ flex: 1,
12
+ backgroundColor: tokens.colors.backgroundPrimary,
13
+ },
14
+ scrollView: {
15
+ flex: 1,
16
+ },
17
+ scrollContent: {
18
+ padding: tokens.spacing.md,
19
+ paddingBottom: tokens.spacing.xl,
20
+ },
21
+ header: {
22
+ marginBottom: tokens.spacing.lg,
23
+ },
24
+ title: {
25
+ fontSize: 28,
26
+ fontWeight: "bold",
27
+ color: tokens.colors.textPrimary,
28
+ },
29
+ section: {
30
+ marginBottom: tokens.spacing.xl,
31
+ },
32
+ sectionTitle: {
33
+ fontSize: 18,
34
+ fontWeight: "600",
35
+ marginBottom: tokens.spacing.md,
36
+ color: tokens.colors.textPrimary,
37
+ },
38
+ statsGrid: {
39
+ flexDirection: "row",
40
+ flexWrap: "wrap",
41
+ gap: tokens.spacing.md,
42
+ },
43
+ emptyText: {
44
+ fontSize: 14,
45
+ textAlign: "center",
46
+ paddingVertical: tokens.spacing.lg,
47
+ color: tokens.colors.textSecondary,
48
+ },
49
+ });
@@ -3,72 +3,79 @@
3
3
  */
4
4
 
5
5
  import { StyleSheet } from 'react-native';
6
+ import type { DesignTokens } from "@umituz/react-native-design-system/theme";
6
7
 
7
- export const achievementItemStyles = StyleSheet.create({
8
- container: {
9
- flexDirection: "row",
10
- alignItems: "center",
11
- padding: 12,
12
- borderRadius: 12,
13
- marginBottom: 8,
14
- },
15
- iconContainer: {
16
- width: 48,
17
- height: 48,
18
- borderRadius: 24,
19
- alignItems: "center",
20
- justifyContent: "center",
21
- marginRight: 12,
22
- },
23
- content: {
24
- flex: 1,
25
- },
26
- header: {
27
- flexDirection: "row",
28
- alignItems: "center",
29
- justifyContent: "space-between",
30
- marginBottom: 4,
31
- },
32
- title: {
33
- fontSize: 16,
34
- fontWeight: "600",
35
- flex: 1,
36
- },
37
- checkmark: {
38
- width: 20,
39
- height: 20,
40
- borderRadius: 10,
41
- alignItems: "center",
42
- justifyContent: "center",
43
- marginLeft: 8,
44
- },
45
- checkmarkText: {
46
- fontSize: 12,
47
- fontWeight: "bold",
48
- },
49
- description: {
50
- fontSize: 13,
51
- lineHeight: 18,
52
- },
53
- progressContainer: {
54
- marginTop: 8,
55
- flexDirection: "row",
56
- alignItems: "center",
57
- gap: 8,
58
- },
59
- progressBar: {
60
- flex: 1,
61
- height: 4,
62
- borderRadius: 2,
63
- overflow: "hidden",
64
- },
65
- progressFill: {
66
- height: "100%",
67
- borderRadius: 2,
68
- },
69
- progressText: {
70
- fontSize: 11,
71
- minWidth: 40,
72
- textAlign: "right",
73
- },
74
- });
8
+ export const createAchievementItemStyles = (tokens: DesignTokens) =>
9
+ StyleSheet.create({
10
+ container: {
11
+ flexDirection: "row",
12
+ alignItems: "center",
13
+ padding: tokens.spacing.md,
14
+ borderRadius: tokens.borders.radius.md,
15
+ marginBottom: tokens.spacing.sm,
16
+ borderWidth: 1,
17
+ borderColor: tokens.colors.borderLight,
18
+ },
19
+ iconContainer: {
20
+ width: 48,
21
+ height: 48,
22
+ borderRadius: 24,
23
+ alignItems: "center",
24
+ justifyContent: "center",
25
+ marginRight: tokens.spacing.md,
26
+ },
27
+ content: {
28
+ flex: 1,
29
+ },
30
+ header: {
31
+ flexDirection: "row",
32
+ alignItems: "center",
33
+ justifyContent: "space-between",
34
+ marginBottom: 4,
35
+ },
36
+ title: {
37
+ fontSize: 16,
38
+ fontWeight: "600",
39
+ flex: 1,
40
+ color: "inherit",
41
+ },
42
+ checkmark: {
43
+ width: 20,
44
+ height: 20,
45
+ borderRadius: 10,
46
+ alignItems: "center",
47
+ justifyContent: "center",
48
+ marginLeft: 8,
49
+ },
50
+ checkmarkText: {
51
+ fontSize: 12,
52
+ fontWeight: "bold",
53
+ },
54
+ description: {
55
+ fontSize: 13,
56
+ lineHeight: 18,
57
+ color: "inherit",
58
+ },
59
+ progressContainer: {
60
+ marginTop: 8,
61
+ flexDirection: "row",
62
+ alignItems: "center",
63
+ gap: 8,
64
+ },
65
+ progressBar: {
66
+ flex: 1,
67
+ height: 4,
68
+ borderRadius: 2,
69
+ overflow: "hidden",
70
+ },
71
+ progressFill: {
72
+ height: "100%",
73
+ borderRadius: 2,
74
+ },
75
+ progressText: {
76
+ fontSize: 11,
77
+ minWidth: 40,
78
+ textAlign: "right",
79
+ color: "inherit",
80
+ },
81
+ });
@@ -3,36 +3,39 @@
3
3
  */
4
4
 
5
5
  import { StyleSheet } from 'react-native';
6
+ import type { DesignTokens } from "@umituz/react-native-design-system/theme";
6
7
 
7
8
  const DEFAULT_CONFIG = {
8
9
  defaultIconSize: 20,
9
10
  };
10
11
 
11
- export const styles = StyleSheet.create({
12
- container: {
13
- flexDirection: 'row',
14
- alignItems: 'center',
15
- gap: 8,
16
- paddingHorizontal: 4,
17
- paddingVertical: 4,
18
- },
19
- disabled: {
20
- opacity: 0.5,
21
- },
22
- flag: {
23
- fontSize: DEFAULT_CONFIG.defaultIconSize,
24
- textAlign: 'center',
25
- },
26
- languageName: {
27
- fontSize: 14,
28
- fontWeight: '600',
29
- textAlign: 'center',
30
- },
31
- icon: {
32
- fontSize: DEFAULT_CONFIG.defaultIconSize,
33
- textAlign: 'center',
34
- },
35
- });
12
+ export const createLanguageSwitcherStyles = (tokens: DesignTokens) =>
13
+ StyleSheet.create({
14
+ container: {
15
+ flexDirection: 'row',
16
+ alignItems: 'center',
17
+ gap: tokens.spacing.sm,
18
+ paddingHorizontal: tokens.spacing.xs,
19
+ paddingVertical: tokens.spacing.xs,
20
+ },
21
+ disabled: {
22
+ opacity: 0.5,
23
+ },
24
+ flag: {
25
+ fontSize: DEFAULT_CONFIG.defaultIconSize,
26
+ textAlign: 'center',
27
+ },
28
+ languageName: {
29
+ fontSize: 14,
30
+ fontWeight: '600',
31
+ textAlign: 'center',
32
+ color: tokens.colors.textPrimary,
33
+ },
34
+ icon: {
35
+ fontSize: DEFAULT_CONFIG.defaultIconSize,
36
+ textAlign: 'center',
37
+ },
38
+ });
36
39
 
37
40
  export const DEFAULT_CONFIG_VALUES = {
38
41
  hitSlop: { top: 10, bottom: 10, left: 10, right: 10 } as const,
@@ -8,7 +8,7 @@ import { TouchableOpacity, type StyleProp, type ViewStyle, type TextStyle } from
8
8
  import { AtomicText } from '@umituz/react-native-design-system/atoms';
9
9
  import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
10
10
  import { useLanguageSwitcher } from './useLanguageSwitcher';
11
- import { styles, DEFAULT_CONFIG_VALUES } from './LanguageSwitcher.styles';
11
+ import { createLanguageSwitcherStyles, DEFAULT_CONFIG_VALUES } from './LanguageSwitcher.styles';
12
12
 
13
13
  export interface LanguageSwitcherProps {
14
14
  showName?: boolean;
@@ -36,6 +36,7 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
36
36
  accessibilityLabel,
37
37
  }) => {
38
38
  const tokens = useAppDesignTokens();
39
+ const styles = createLanguageSwitcherStyles(tokens);
39
40
  const { currentLang, handlePress } = useLanguageSwitcher({ onPress, disabled });
40
41
 
41
42
  const accessibilityProps = useMemo(() => ({
@@ -50,9 +51,8 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
50
51
  return (
51
52
  <TouchableOpacity
52
53
  style={[
53
- styles.container,
54
- { gap: tokens.spacing.xs },
55
- style,
54
+ styles.container,
55
+ style,
56
56
  disabled && styles.disabled
57
57
  ]}
58
58
  onPress={handlePress}
@@ -68,8 +68,8 @@ export const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
68
68
  </AtomicText>
69
69
  )}
70
70
  {showName && (
71
- <AtomicText
72
- type="bodySmall"
71
+ <AtomicText
72
+ type="bodySmall"
73
73
  style={[styles.languageName, { color: textColor, fontWeight: '600' }, textStyle]}
74
74
  >
75
75
  {currentLang.nativeName}
@@ -3,38 +3,52 @@
3
3
  */
4
4
 
5
5
  import { StyleSheet } from 'react-native';
6
+ import type { DesignTokens } from "@umituz/react-native-design-system/theme";
6
7
 
7
- export const styles = StyleSheet.create({
8
- languageItem: {
9
- flexDirection: 'row',
10
- alignItems: 'center',
11
- justifyContent: 'space-between',
12
- borderWidth: 1,
13
- },
14
- selectedLanguageItem: {
15
- borderWidth: 2,
16
- },
17
- languageContent: {
18
- flexDirection: 'row',
19
- alignItems: 'center',
20
- flex: 1,
21
- },
22
- flag: {
23
- fontSize: 24,
24
- marginRight: 16,
25
- },
26
- languageText: {
27
- flex: 1,
28
- flexShrink: 1,
29
- },
30
- nativeName: {
31
- // Styling moved to themedStyles in component for token support
32
- },
33
- languageName: {
34
- // Styling moved to themedStyles in component for token support
35
- },
36
- checkIcon: {
37
- // Replaced by AtomicIcon
38
- },
39
- });
8
+ export const createLanguageItemStyles = (tokens: DesignTokens) =>
9
+ StyleSheet.create({
10
+ languageItem: {
11
+ flexDirection: 'row',
12
+ alignItems: 'center',
13
+ justifyContent: 'space-between',
14
+ borderWidth: 1,
15
+ borderColor: tokens.colors.borderLight,
16
+ backgroundColor: tokens.colors.surface,
17
+ borderRadius: tokens.borders.radius.md,
18
+ marginBottom: tokens.spacing.sm,
19
+ overflow: 'hidden',
20
+ },
21
+ selectedLanguageItem: {
22
+ borderWidth: 2,
23
+ borderColor: tokens.colors.primary,
24
+ },
25
+ languageContent: {
26
+ flexDirection: 'row',
27
+ alignItems: 'center',
28
+ flex: 1,
29
+ padding: tokens.spacing.md,
30
+ },
31
+ flag: {
32
+ fontSize: 24,
33
+ marginRight: tokens.spacing.md,
34
+ },
35
+ languageText: {
36
+ flex: 1,
37
+ flexShrink: 1,
38
+ },
39
+ nativeName: {
40
+ fontSize: 16,
41
+ fontWeight: '500',
42
+ color: tokens.colors.textPrimary,
43
+ marginBottom: 2,
44
+ },
45
+ languageName: {
46
+ fontSize: 14,
47
+ color: tokens.colors.textSecondary,
48
+ },
49
+ checkIcon: {
50
+ padding: tokens.spacing.md,
51
+ // Replaced by AtomicIcon
52
+ },
53
+ });
40
54
 
@@ -17,7 +17,7 @@ import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system/atoms
17
17
  import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
18
18
  import type { Language } from '../../infrastructure/storage/types/Language';
19
19
  import { ICON_PATHS } from '../../../../utils/iconPaths';
20
- import { styles } from './LanguageItem.styles';
20
+ import { createLanguageItemStyles } from './LanguageItem.styles';
21
21
 
22
22
  interface LanguageItemProps {
23
23
  item: Language;
@@ -42,29 +42,9 @@ export const LanguageItem: React.FC<LanguageItemProps> = React.memo(({
42
42
  customStyles,
43
43
  }) => {
44
44
  const tokens = useAppDesignTokens();
45
+ const styles = createLanguageItemStyles(tokens);
45
46
 
46
47
  const themedStyles = useMemo(() => ({
47
- languageItem: {
48
- paddingHorizontal: tokens.spacing.md,
49
- paddingVertical: tokens.spacing.md,
50
- borderRadius: tokens.borders.radius.lg,
51
- backgroundColor: tokens.colors.surfaceSecondary,
52
- marginBottom: tokens.spacing.md,
53
- flexDirection: 'row' as const,
54
- alignItems: 'center' as const,
55
- justifyContent: 'space-between' as const,
56
- } as ViewStyle,
57
- selectedLanguageItem: {
58
- backgroundColor: tokens.colors.surface,
59
- borderColor: tokens.colors.primary,
60
- borderWidth: 1.5,
61
- } as ViewStyle,
62
- nativeName: {
63
- color: tokens.colors.textPrimary,
64
- } as TextStyle,
65
- languageName: {
66
- color: tokens.colors.textSecondary,
67
- } as TextStyle,
68
48
  flagContainer: {
69
49
  width: 44,
70
50
  height: 44,
@@ -80,8 +60,8 @@ export const LanguageItem: React.FC<LanguageItemProps> = React.memo(({
80
60
  <TouchableOpacity
81
61
  testID="language-item-test"
82
62
  style={[
83
- themedStyles.languageItem,
84
- isSelected && themedStyles.selectedLanguageItem,
63
+ styles.languageItem,
64
+ isSelected && styles.selectedLanguageItem,
85
65
  customStyles?.languageItem,
86
66
  ]}
87
67
  onPress={() => {
@@ -110,15 +90,15 @@ export const LanguageItem: React.FC<LanguageItemProps> = React.memo(({
110
90
  )}
111
91
  </View>
112
92
  <View style={[styles.languageText, customStyles?.languageText]}>
113
- <AtomicText
93
+ <AtomicText
114
94
  type="bodyLarge"
115
- style={[themedStyles.nativeName, { fontWeight: '600' }, customStyles?.nativeName]}
95
+ style={[styles.nativeName, { fontWeight: '600' }, customStyles?.nativeName]}
116
96
  >
117
97
  {item.nativeName}
118
98
  </AtomicText>
119
- <AtomicText
120
- type="labelMedium"
121
- style={[themedStyles.languageName, customStyles?.nativeName]}
99
+ <AtomicText
100
+ type="labelMedium"
101
+ style={[styles.languageName, customStyles?.nativeName]}
122
102
  >
123
103
  {item.name}
124
104
  </AtomicText>
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Pre-Publish Script
5
- * Basic checks before publishing
6
- */
7
-
8
- import fs from 'fs';
9
- import path from 'path';
10
- import { fileURLToPath } from 'url';
11
-
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = path.dirname(__filename);
14
-
15
- const PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
16
- const SRC_DIR = path.join(PACKAGE_ROOT, 'src');
17
-
18
- if (!fs.existsSync(SRC_DIR)) {
19
- console.error('❌ src directory not found');
20
- process.exit(1);
21
- }
22
-
23
- const mainFiles = [
24
- 'src/index.ts',
25
- 'src/infrastructure/config/i18n.ts',
26
- ];
27
-
28
- for (const file of mainFiles) {
29
- const filePath = path.join(PACKAGE_ROOT, file);
30
- if (!fs.existsSync(filePath)) {
31
- console.error(`❌ Missing mandatory file: ${file}`);
32
- process.exit(1);
33
- }
34
- }
35
-
36
- console.log('✅ Pre-publish checks passed!');