@umituz/react-native-design-system 1.14.0 → 2.0.0

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 (87) hide show
  1. package/package.json +26 -19
  2. package/src/atoms/AtomicAvatar.tsx +161 -0
  3. package/src/atoms/AtomicButton.tsx +241 -0
  4. package/src/atoms/AtomicChip.tsx +226 -0
  5. package/src/atoms/AtomicDatePicker.tsx +255 -0
  6. package/src/atoms/AtomicFab.tsx +99 -0
  7. package/src/atoms/AtomicIcon.tsx +149 -0
  8. package/src/atoms/AtomicInput.tsx +308 -0
  9. package/src/atoms/AtomicPicker.tsx +310 -0
  10. package/src/atoms/AtomicProgress.tsx +149 -0
  11. package/src/atoms/AtomicText.tsx +55 -0
  12. package/src/atoms/__tests__/AtomicButton.test.tsx +107 -0
  13. package/src/atoms/__tests__/AtomicIcon.test.tsx +110 -0
  14. package/src/atoms/__tests__/AtomicInput.test.tsx +195 -0
  15. package/src/atoms/datepicker/components/DatePickerButton.tsx +112 -0
  16. package/src/atoms/datepicker/components/DatePickerModal.tsx +143 -0
  17. package/src/atoms/fab/styles/fabStyles.ts +98 -0
  18. package/src/atoms/fab/types/index.ts +88 -0
  19. package/src/atoms/index.ts +70 -0
  20. package/src/atoms/input/hooks/useInputState.ts +63 -0
  21. package/src/atoms/input/styles/inputStylesHelper.ts +120 -0
  22. package/src/atoms/picker/components/PickerChips.tsx +57 -0
  23. package/src/atoms/picker/components/PickerModal.tsx +214 -0
  24. package/src/atoms/picker/styles/pickerStyles.ts +223 -0
  25. package/src/atoms/picker/types/index.ts +42 -0
  26. package/src/index.ts +148 -79
  27. package/src/molecules/ConfirmationModal.tsx +42 -0
  28. package/src/molecules/ConfirmationModalContent.tsx +87 -0
  29. package/src/molecules/ConfirmationModalMain.tsx +91 -0
  30. package/src/molecules/FormField.tsx +155 -0
  31. package/src/molecules/IconContainer.tsx +79 -0
  32. package/src/molecules/ListItem.tsx +35 -0
  33. package/src/molecules/ScreenHeader.tsx +171 -0
  34. package/src/molecules/SearchBar.tsx +198 -0
  35. package/src/molecules/confirmation-modal/components.tsx +94 -0
  36. package/src/molecules/confirmation-modal/index.ts +7 -0
  37. package/src/molecules/confirmation-modal/styles/confirmationModalStyles.ts +133 -0
  38. package/src/molecules/confirmation-modal/types/index.ts +41 -0
  39. package/src/molecules/confirmation-modal/useConfirmationModal.ts +50 -0
  40. package/src/molecules/index.ts +19 -0
  41. package/src/molecules/listitem/index.ts +6 -0
  42. package/src/molecules/listitem/styles/listItemStyles.ts +37 -0
  43. package/src/molecules/listitem/types/index.ts +21 -0
  44. package/src/organisms/AppHeader.tsx +136 -0
  45. package/src/organisms/FormContainer.tsx +169 -0
  46. package/src/organisms/ScreenLayout.tsx +183 -0
  47. package/src/organisms/index.ts +31 -0
  48. package/src/responsive/config.ts +139 -0
  49. package/src/responsive/deviceDetection.ts +155 -0
  50. package/src/responsive/gridUtils.ts +79 -0
  51. package/src/responsive/index.ts +52 -0
  52. package/src/responsive/platformConstants.ts +98 -0
  53. package/src/responsive/responsive.ts +61 -0
  54. package/src/responsive/responsiveLayout.ts +137 -0
  55. package/src/responsive/responsiveSizing.ts +134 -0
  56. package/src/responsive/useResponsive.ts +140 -0
  57. package/src/responsive/validation.ts +158 -0
  58. package/src/theme/core/BaseTokens.ts +42 -0
  59. package/src/theme/core/ColorPalette.ts +29 -0
  60. package/src/theme/core/CustomColors.ts +122 -0
  61. package/src/theme/core/NavigationTheme.ts +72 -0
  62. package/src/theme/core/TokenFactory.ts +103 -0
  63. package/src/theme/core/colors/ColorUtils.ts +53 -0
  64. package/src/theme/core/colors/DarkColors.ts +146 -0
  65. package/src/theme/core/colors/LightColors.ts +146 -0
  66. package/src/theme/core/constants/DesignConstants.ts +31 -0
  67. package/src/theme/core/themes.ts +118 -0
  68. package/src/theme/core/tokens/BaseTokens.ts +144 -0
  69. package/src/theme/core/tokens/Borders.ts +43 -0
  70. package/src/theme/core/tokens/Sizes.ts +51 -0
  71. package/src/theme/core/tokens/Spacing.ts +38 -0
  72. package/src/theme/core/tokens/Typography.ts +143 -0
  73. package/src/theme/hooks/useAppDesignTokens.ts +45 -0
  74. package/src/theme/hooks/useCommonStyles.ts +248 -0
  75. package/src/theme/hooks/useThemedStyles.ts +68 -0
  76. package/src/theme/index.ts +94 -0
  77. package/src/theme/infrastructure/globalThemeStore.ts +69 -0
  78. package/src/theme/infrastructure/storage/ThemeStorage.ts +93 -0
  79. package/src/theme/infrastructure/stores/themeStore.ts +109 -0
  80. package/src/typography/__tests__/colorValidationUtils.test.ts +180 -0
  81. package/src/typography/__tests__/textColorUtils.test.ts +185 -0
  82. package/src/typography/__tests__/textStyleUtils.test.ts +168 -0
  83. package/src/typography/domain/entities/TypographyTypes.ts +88 -0
  84. package/src/typography/index.ts +53 -0
  85. package/src/typography/presentation/utils/colorValidationUtils.ts +133 -0
  86. package/src/typography/presentation/utils/textColorUtils.ts +205 -0
  87. package/src/typography/presentation/utils/textStyleUtils.ts +159 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "1.14.0",
4
- "description": "Universal design system for React Native apps - Domain-Driven Design architecture with Material Design 3 components",
3
+ "version": "2.0.0",
4
+ "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography and responsive utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
7
7
  "exports": {
@@ -11,7 +11,12 @@
11
11
  "require": "./src/index.ts",
12
12
  "default": "./src/index.ts"
13
13
  },
14
- "./src/index.ts": "./src/index.ts",
14
+ "./atoms": "./src/atoms/index.ts",
15
+ "./molecules": "./src/molecules/index.ts",
16
+ "./organisms": "./src/organisms/index.ts",
17
+ "./theme": "./src/theme/index.ts",
18
+ "./typography": "./src/typography/index.ts",
19
+ "./responsive": "./src/responsive/index.ts",
15
20
  "./package.json": "./package.json"
16
21
  },
17
22
  "scripts": {
@@ -27,8 +32,12 @@
27
32
  "material-design-3",
28
33
  "ui-components",
29
34
  "atomic-design",
30
- "ddd",
31
- "domain-driven-design"
35
+ "atoms",
36
+ "molecules",
37
+ "organisms",
38
+ "theme",
39
+ "typography",
40
+ "responsive"
32
41
  ],
33
42
  "author": "Ümit UZ <umit@umituz.com>",
34
43
  "license": "MIT",
@@ -39,15 +48,10 @@
39
48
  "peerDependencies": {
40
49
  "@expo/vector-icons": ">=15.0.0",
41
50
  "@gorhom/bottom-sheet": ">=5.0.0",
51
+ "@react-native-async-storage/async-storage": ">=2.0.0",
42
52
  "@react-native-community/datetimepicker": ">=8.0.0",
43
53
  "@react-navigation/native": ">=6.0.0",
44
- "@umituz/react-native-bottom-sheet": "latest",
45
- "@umituz/react-native-design-system-atoms": "latest",
46
- "@umituz/react-native-design-system-molecules": "latest",
47
- "@umituz/react-native-design-system-organisms": "latest",
48
- "@umituz/react-native-design-system-responsive": "latest",
49
- "@umituz/react-native-design-system-theme": "latest",
50
- "@umituz/react-native-design-system-typography": "latest",
54
+ "@umituz/react-native-icons": "latest",
51
55
  "expo-linear-gradient": ">=15.0.0",
52
56
  "react": ">=19.0.0",
53
57
  "react-native": ">=0.81.0",
@@ -63,22 +67,25 @@
63
67
  },
64
68
  "@react-navigation/native": {
65
69
  "optional": true
70
+ },
71
+ "@gorhom/bottom-sheet": {
72
+ "optional": true
66
73
  }
67
74
  },
68
75
  "devDependencies": {
76
+ "@eslint/js": "^9.39.2",
69
77
  "@expo/vector-icons": "^15.0.0",
70
78
  "@gorhom/bottom-sheet": "^5.0.0",
71
79
  "@react-native-async-storage/async-storage": "2.2.0",
72
80
  "@react-native-community/datetimepicker": "^8.4.4",
73
81
  "@react-navigation/native": "^6.0.0",
74
82
  "@types/react": "~19.1.0",
75
- "@umituz/react-native-bottom-sheet": "latest",
76
- "@umituz/react-native-design-system-atoms": "latest",
77
- "@umituz/react-native-design-system-molecules": "latest",
78
- "@umituz/react-native-design-system-organisms": "latest",
79
- "@umituz/react-native-design-system-responsive": "latest",
80
- "@umituz/react-native-design-system-theme": "latest",
81
- "@umituz/react-native-design-system-typography": "latest",
83
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
84
+ "@typescript-eslint/parser": "^8.50.0",
85
+ "@umituz/react-native-icons": "latest",
86
+ "eslint": "^9.39.2",
87
+ "eslint-plugin-react": "^7.37.5",
88
+ "eslint-plugin-react-hooks": "^7.0.1",
82
89
  "react": "19.1.0",
83
90
  "react-native": "0.81.5",
84
91
  "react-native-gesture-handler": "^2.20.0",
@@ -0,0 +1,161 @@
1
+ /**
2
+ * AtomicAvatar - Universal Avatar Component
3
+ *
4
+ * Displays user profile images with fallback to initials
5
+ * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
+ *
7
+ * Atomic Design Level: ATOM
8
+ * Purpose: User profile image display
9
+ *
10
+ * Usage:
11
+ * - User profile pictures
12
+ * - Contact avatars
13
+ * - Group member avatars
14
+ * - Default user placeholders
15
+ */
16
+
17
+ import React from 'react';
18
+ import { View, Image, StyleSheet, ViewStyle, ImageStyle, ImageSourcePropType } from 'react-native';
19
+ import { AtomicText } from './AtomicText';
20
+ import { useAppDesignTokens } from '../theme';
21
+
22
+ // =============================================================================
23
+ // TYPE DEFINITIONS
24
+ // =============================================================================
25
+
26
+ export interface AtomicAvatarProps {
27
+ /** Image source (URI or require) */
28
+ source?: ImageSourcePropType;
29
+ /** User's name for fallback initials */
30
+ name?: string;
31
+ /** Size of the avatar */
32
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
33
+ /** Custom size in pixels */
34
+ customSize?: number;
35
+ /** Background color for fallback */
36
+ backgroundColor?: string;
37
+ /** Text color for initials */
38
+ textColor?: string;
39
+ /** Border radius (default: circular) */
40
+ borderRadius?: number;
41
+ /** Border width */
42
+ borderWidth?: number;
43
+ /** Border color */
44
+ borderColor?: string;
45
+ /** Style overrides */
46
+ style?: ViewStyle | ViewStyle[];
47
+ /** Image style overrides */
48
+ imageStyle?: ImageStyle | ImageStyle[];
49
+ /** Test ID for testing */
50
+ testID?: string;
51
+ }
52
+
53
+ // =============================================================================
54
+ // COMPONENT IMPLEMENTATION
55
+ // =============================================================================
56
+
57
+ export const AtomicAvatar: React.FC<AtomicAvatarProps> = ({
58
+ source,
59
+ name,
60
+ size = 'md',
61
+ customSize,
62
+ backgroundColor,
63
+ textColor,
64
+ borderRadius,
65
+ borderWidth = 0,
66
+ borderColor,
67
+ style,
68
+ imageStyle,
69
+ testID,
70
+ }) => {
71
+ const tokens = useAppDesignTokens();
72
+
73
+ const avatarSize = customSize || tokens.avatarSizes[size];
74
+ const avatarRadius = borderRadius ?? avatarSize / 2;
75
+
76
+ // Generate initials from name
77
+ const getInitials = (name: string): string => {
78
+ return name
79
+ .split(' ')
80
+ .map(word => word.charAt(0))
81
+ .join('')
82
+ .toUpperCase()
83
+ .slice(0, 2);
84
+ };
85
+
86
+ // Default colors
87
+ const defaultBackgroundColor = backgroundColor || tokens.colors.primary;
88
+ const defaultTextColor = textColor || tokens.colors.onPrimary;
89
+ const defaultBorderColor = borderColor || tokens.colors.border;
90
+
91
+ const avatarStyle: ViewStyle = {
92
+ width: avatarSize,
93
+ height: avatarSize,
94
+ borderRadius: avatarRadius,
95
+ backgroundColor: defaultBackgroundColor,
96
+ borderWidth,
97
+ borderColor: defaultBorderColor,
98
+ alignItems: 'center',
99
+ justifyContent: 'center',
100
+ overflow: 'hidden',
101
+ };
102
+
103
+ const imageStyleFinal: ImageStyle = {
104
+ width: avatarSize,
105
+ height: avatarSize,
106
+ borderRadius: avatarRadius,
107
+ };
108
+
109
+ // Font size based on avatar size
110
+ const getFontSize = (size: number): number => {
111
+ if (size <= 32) return 12;
112
+ if (size <= 48) return 16;
113
+ if (size <= 64) return 20;
114
+ return 24;
115
+ };
116
+
117
+ return (
118
+ <View
119
+ style={[avatarStyle, style]}
120
+ testID={testID}
121
+ accessibilityLabel={name ? `Avatar for ${name}` : 'Default avatar'}
122
+ accessibilityRole="image"
123
+ >
124
+ {source ? (
125
+ <Image
126
+ source={source}
127
+ style={StyleSheet.flatten([imageStyleFinal, imageStyle])}
128
+ resizeMode="cover"
129
+ />
130
+ ) : name ? (
131
+ <AtomicText
132
+ type="labelLarge"
133
+ color={defaultTextColor}
134
+ style={{
135
+ fontSize: getFontSize(avatarSize),
136
+ fontWeight: tokens.typography.semibold,
137
+ }}
138
+ >
139
+ {getInitials(name)}
140
+ </AtomicText>
141
+ ) : (
142
+ <AtomicText
143
+ type="labelLarge"
144
+ color={defaultTextColor}
145
+ style={{
146
+ fontSize: getFontSize(avatarSize),
147
+ fontWeight: tokens.typography.semibold,
148
+ }}
149
+ >
150
+ ?
151
+ </AtomicText>
152
+ )}
153
+ </View>
154
+ );
155
+ };
156
+
157
+ // =============================================================================
158
+ // EXPORTS
159
+ // =============================================================================
160
+
161
+ export default AtomicAvatar;
@@ -0,0 +1,241 @@
1
+ import React from 'react';
2
+ import { StyleSheet, StyleProp, ViewStyle, TextStyle, TouchableOpacity, View } from 'react-native';
3
+ import { AtomicText } from './AtomicText';
4
+ import { AtomicIcon } from './AtomicIcon';
5
+ import { useAppDesignTokens } from '../theme';
6
+ import type { IconName } from './AtomicIcon';
7
+
8
+ export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'danger';
9
+ export type ButtonSize = 'sm' | 'md' | 'lg';
10
+
11
+ export interface AtomicButtonProps {
12
+ title?: string;
13
+ children?: React.ReactNode;
14
+ onPress: () => void;
15
+ variant?: ButtonVariant;
16
+ size?: ButtonSize;
17
+ disabled?: boolean;
18
+ icon?: IconName;
19
+ fullWidth?: boolean;
20
+ style?: StyleProp<ViewStyle>;
21
+ textStyle?: StyleProp<TextStyle>;
22
+ activeOpacity?: number;
23
+ testID?: string;
24
+ }
25
+
26
+ export const AtomicButton: React.FC<AtomicButtonProps> = React.memo(({
27
+ title,
28
+ children,
29
+ onPress,
30
+ variant = 'primary',
31
+ size = 'md',
32
+ disabled = false,
33
+ icon,
34
+ fullWidth = false,
35
+ style,
36
+ textStyle,
37
+ activeOpacity = 0.8,
38
+ testID,
39
+ }) => {
40
+ const tokens = useAppDesignTokens();
41
+
42
+ const handlePress = () => {
43
+ if (!disabled) {
44
+ if (__DEV__) {
45
+ console.log('[AtomicButton] Button pressed:', { title, variant, disabled });
46
+ }
47
+ onPress();
48
+ }
49
+ };
50
+
51
+ // Size configurations
52
+ const sizeConfig = {
53
+ sm: {
54
+ paddingVertical: tokens.spacing.xs,
55
+ paddingHorizontal: tokens.spacing.sm,
56
+ fontSize: tokens.typography.bodySmall.fontSize,
57
+ iconSize: 16,
58
+ minHeight: 32,
59
+ },
60
+ md: {
61
+ paddingVertical: tokens.spacing.sm,
62
+ paddingHorizontal: tokens.spacing.md,
63
+ fontSize: tokens.typography.bodyMedium.fontSize,
64
+ iconSize: 20,
65
+ minHeight: 44,
66
+ },
67
+ lg: {
68
+ paddingVertical: tokens.spacing.md,
69
+ paddingHorizontal: tokens.spacing.lg,
70
+ fontSize: tokens.typography.bodyLarge.fontSize,
71
+ iconSize: 24,
72
+ minHeight: 52,
73
+ },
74
+ };
75
+
76
+ const config = sizeConfig[size];
77
+
78
+ // Variant styles
79
+ const getVariantStyles = () => {
80
+ const baseStyle: ViewStyle = {
81
+ backgroundColor: tokens.colors.primary,
82
+ borderWidth: 0,
83
+ };
84
+
85
+ const baseTextStyle: TextStyle = {
86
+ color: tokens.colors.textInverse,
87
+ };
88
+
89
+ switch (variant) {
90
+ case 'primary':
91
+ return {
92
+ container: {
93
+ ...baseStyle,
94
+ backgroundColor: tokens.colors.primary,
95
+ },
96
+ text: {
97
+ ...baseTextStyle,
98
+ color: tokens.colors.textInverse,
99
+ },
100
+ };
101
+
102
+ case 'secondary':
103
+ return {
104
+ container: {
105
+ ...baseStyle,
106
+ backgroundColor: tokens.colors.surfaceSecondary,
107
+ },
108
+ text: {
109
+ ...baseTextStyle,
110
+ color: tokens.colors.textPrimary,
111
+ },
112
+ };
113
+
114
+ case 'outline':
115
+ return {
116
+ container: {
117
+ ...baseStyle,
118
+ backgroundColor: 'transparent',
119
+ borderWidth: 1,
120
+ borderColor: tokens.colors.border,
121
+ },
122
+ text: {
123
+ ...baseTextStyle,
124
+ color: tokens.colors.textPrimary,
125
+ },
126
+ };
127
+
128
+ case 'text':
129
+ return {
130
+ container: {
131
+ ...baseStyle,
132
+ backgroundColor: 'transparent',
133
+ },
134
+ text: {
135
+ ...baseTextStyle,
136
+ color: tokens.colors.primary,
137
+ },
138
+ };
139
+
140
+ case 'danger':
141
+ return {
142
+ container: {
143
+ ...baseStyle,
144
+ backgroundColor: tokens.colors.error,
145
+ },
146
+ text: {
147
+ ...baseTextStyle,
148
+ color: tokens.colors.textInverse,
149
+ },
150
+ };
151
+
152
+ default:
153
+ return {
154
+ container: baseStyle,
155
+ text: baseTextStyle,
156
+ };
157
+ }
158
+ };
159
+
160
+ const variantStyles = getVariantStyles();
161
+
162
+ const containerStyle: StyleProp<ViewStyle> = [
163
+ styles.button,
164
+ {
165
+ paddingVertical: config.paddingVertical,
166
+ paddingHorizontal: config.paddingHorizontal,
167
+ minHeight: config.minHeight,
168
+ borderRadius: tokens.borders.radius.md,
169
+ },
170
+ variantStyles.container,
171
+ fullWidth ? styles.fullWidth : undefined,
172
+ disabled ? styles.disabled : undefined,
173
+ style,
174
+ ];
175
+
176
+ const buttonTextStyle: StyleProp<TextStyle> = [
177
+ {
178
+ fontSize: config.fontSize,
179
+ fontWeight: '600',
180
+ },
181
+ variantStyles.text,
182
+ disabled ? styles.disabledText : undefined,
183
+ textStyle,
184
+ ];
185
+
186
+ const buttonText = title || children;
187
+ const showIcon = icon;
188
+ const iconColor = variantStyles.text.color;
189
+
190
+ return (
191
+ <TouchableOpacity
192
+ style={containerStyle}
193
+ onPress={handlePress}
194
+ activeOpacity={activeOpacity}
195
+ disabled={disabled}
196
+ testID={testID}
197
+ >
198
+ <View style={styles.content}>
199
+ {showIcon ? (
200
+ <AtomicIcon
201
+ name={icon}
202
+ customSize={config.iconSize}
203
+ customColor={iconColor as string | undefined}
204
+ style={styles.icon}
205
+ />
206
+ ) : null}
207
+
208
+ <AtomicText style={buttonTextStyle}>
209
+ {buttonText}
210
+ </AtomicText>
211
+ </View>
212
+ </TouchableOpacity>
213
+ );
214
+ });
215
+
216
+ const styles = StyleSheet.create({
217
+ button: {
218
+ alignItems: 'center',
219
+ justifyContent: 'center',
220
+ flexDirection: 'row',
221
+ },
222
+ content: {
223
+ flexDirection: 'row',
224
+ alignItems: 'center',
225
+ justifyContent: 'center',
226
+ },
227
+ fullWidth: {
228
+ width: '100%',
229
+ },
230
+ disabled: {
231
+ opacity: 0.5,
232
+ },
233
+ disabledText: {
234
+ opacity: 0.7,
235
+ },
236
+ icon: {
237
+ marginRight: 8,
238
+ },
239
+ });
240
+
241
+ export type { AtomicButtonProps as ButtonProps };