@umituz/react-native-design-system 2.6.61 → 2.6.62

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-design-system",
3
- "version": "2.6.61",
3
+ "version": "2.6.62",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -1,258 +1,7 @@
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 { AtomicSpinner } from './AtomicSpinner';
6
- import { useAppDesignTokens } from '../theme';
7
- import type { IconName } from './AtomicIcon';
1
+ /**
2
+ * AtomicButton - Re-export from button module
3
+ * Maintains backward compatibility
4
+ */
8
5
 
9
- export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'danger';
10
- export type ButtonSize = 'sm' | 'md' | 'lg';
11
-
12
- export interface AtomicButtonProps {
13
- title?: string;
14
- children?: React.ReactNode;
15
- onPress: () => void;
16
- variant?: ButtonVariant;
17
- size?: ButtonSize;
18
- disabled?: boolean;
19
- loading?: boolean;
20
- icon?: IconName;
21
- iconPosition?: 'left' | 'right';
22
- fullWidth?: boolean;
23
- style?: StyleProp<ViewStyle>;
24
- textStyle?: StyleProp<TextStyle>;
25
- activeOpacity?: number;
26
- testID?: string;
27
- }
28
-
29
- export const AtomicButton: React.FC<AtomicButtonProps> = React.memo(({
30
- title,
31
- children,
32
- onPress,
33
- variant = 'primary',
34
- size = 'md',
35
- disabled = false,
36
- loading = false,
37
- icon,
38
- iconPosition = 'left',
39
- fullWidth = false,
40
- style,
41
- textStyle,
42
- activeOpacity = 0.8,
43
- testID,
44
- }) => {
45
- const tokens = useAppDesignTokens();
46
-
47
- const handlePress = () => {
48
- if (!disabled && !loading) {
49
- onPress();
50
- }
51
- };
52
-
53
- const isDisabled = disabled || loading;
54
-
55
- // Size configurations
56
- const sizeConfig = {
57
- sm: {
58
- paddingVertical: tokens.spacing.xs,
59
- paddingHorizontal: tokens.spacing.sm,
60
- fontSize: tokens.typography.bodySmall.responsiveFontSize,
61
- iconSize: 16 * tokens.spacingMultiplier,
62
- minHeight: 32 * tokens.spacingMultiplier,
63
- },
64
- md: {
65
- paddingVertical: tokens.spacing.sm,
66
- paddingHorizontal: tokens.spacing.md,
67
- fontSize: tokens.typography.bodyMedium.responsiveFontSize,
68
- iconSize: 20 * tokens.spacingMultiplier,
69
- minHeight: 44 * tokens.spacingMultiplier,
70
- },
71
- lg: {
72
- paddingVertical: tokens.spacing.md,
73
- paddingHorizontal: tokens.spacing.lg,
74
- fontSize: tokens.typography.bodyLarge.responsiveFontSize,
75
- iconSize: 24 * tokens.spacingMultiplier,
76
- minHeight: 52 * tokens.spacingMultiplier,
77
- },
78
- };
79
-
80
- const config = sizeConfig[size];
81
-
82
- // Variant styles
83
- const getVariantStyles = () => {
84
- const baseStyle: ViewStyle = {
85
- backgroundColor: tokens.colors.primary,
86
- borderWidth: 0,
87
- };
88
-
89
- const baseTextStyle: TextStyle = {
90
- color: tokens.colors.textInverse,
91
- };
92
-
93
- switch (variant) {
94
- case 'primary':
95
- return {
96
- container: {
97
- ...baseStyle,
98
- backgroundColor: tokens.colors.primary,
99
- },
100
- text: {
101
- ...baseTextStyle,
102
- color: tokens.colors.textInverse,
103
- },
104
- };
105
-
106
- case 'secondary':
107
- return {
108
- container: {
109
- ...baseStyle,
110
- backgroundColor: tokens.colors.surfaceSecondary,
111
- },
112
- text: {
113
- ...baseTextStyle,
114
- color: tokens.colors.textPrimary,
115
- },
116
- };
117
-
118
- case 'outline':
119
- return {
120
- container: {
121
- ...baseStyle,
122
- backgroundColor: undefined,
123
- borderWidth: 1,
124
- borderColor: tokens.colors.border,
125
- },
126
- text: {
127
- ...baseTextStyle,
128
- color: tokens.colors.textPrimary,
129
- },
130
- };
131
-
132
- case 'text':
133
- return {
134
- container: {
135
- ...baseStyle,
136
- backgroundColor: undefined,
137
- },
138
- text: {
139
- ...baseTextStyle,
140
- color: tokens.colors.primary,
141
- },
142
- };
143
-
144
- case 'danger':
145
- return {
146
- container: {
147
- ...baseStyle,
148
- backgroundColor: tokens.colors.error,
149
- },
150
- text: {
151
- ...baseTextStyle,
152
- color: tokens.colors.textInverse,
153
- },
154
- };
155
-
156
- default:
157
- return {
158
- container: baseStyle,
159
- text: baseTextStyle,
160
- };
161
- }
162
- };
163
-
164
- const variantStyles = getVariantStyles();
165
-
166
- const containerStyle: StyleProp<ViewStyle> = [
167
- styles.button,
168
- {
169
- paddingVertical: config.paddingVertical,
170
- paddingHorizontal: config.paddingHorizontal,
171
- minHeight: config.minHeight,
172
- borderRadius: tokens.borders.radius.md,
173
- },
174
- variantStyles.container,
175
- fullWidth ? styles.fullWidth : undefined,
176
- isDisabled ? styles.disabled : undefined,
177
- style,
178
- ];
179
-
180
- const buttonTextStyle: StyleProp<TextStyle> = [
181
- {
182
- fontSize: config.fontSize,
183
- fontWeight: '600',
184
- },
185
- variantStyles.text,
186
- isDisabled ? styles.disabledText : undefined,
187
- textStyle,
188
- ];
189
-
190
- const buttonText = title || children;
191
- const showIcon = icon;
192
- const iconColor = variantStyles.text.color;
193
-
194
- return (
195
- <TouchableOpacity
196
- style={containerStyle}
197
- onPress={handlePress}
198
- activeOpacity={activeOpacity}
199
- disabled={isDisabled}
200
- testID={testID}
201
- >
202
- <View style={[styles.content, iconPosition === 'right' && styles.rowReverse]}>
203
- {loading ? (
204
- <AtomicSpinner
205
- size="sm"
206
- color={iconColor as string}
207
- style={iconPosition === 'right' ? styles.iconRight : styles.iconLeft}
208
- />
209
- ) : showIcon ? (
210
- <AtomicIcon
211
- name={icon}
212
- customSize={config.iconSize}
213
- customColor={iconColor as string | undefined}
214
- style={iconPosition === 'right' ? styles.iconRight : styles.iconLeft}
215
- />
216
- ) : null}
217
-
218
- <AtomicText style={buttonTextStyle}>
219
- {buttonText}
220
- </AtomicText>
221
- </View>
222
- </TouchableOpacity>
223
- );
224
- });
225
- AtomicButton.displayName = 'AtomicButton';
226
-
227
- const styles = StyleSheet.create({
228
- button: {
229
- alignItems: 'center',
230
- justifyContent: 'center',
231
- flexDirection: 'row',
232
- },
233
- content: {
234
- flexDirection: 'row',
235
- alignItems: 'center',
236
- justifyContent: 'center',
237
- },
238
- rowReverse: {
239
- flexDirection: 'row-reverse',
240
- },
241
- fullWidth: {
242
- width: '100%',
243
- },
244
- disabled: {
245
- opacity: 0.5,
246
- },
247
- disabledText: {
248
- opacity: 0.7,
249
- },
250
- iconLeft: {
251
- marginRight: 8,
252
- },
253
- iconRight: {
254
- marginLeft: 8,
255
- },
256
- });
257
-
258
- export type { AtomicButtonProps as ButtonProps };
6
+ export { AtomicButton } from './button';
7
+ export type { AtomicButtonProps, ButtonVariant, ButtonSize } from './button';
@@ -1,227 +1,7 @@
1
1
  /**
2
- * AtomicChip - Universal Chip/Tag Component
3
- *
4
- * Displays small tags, labels, or status indicators
5
- * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
- *
7
- * Atomic Design Level: ATOM
8
- * Purpose: Tag and label display
9
- *
10
- * Usage:
11
- * - Category tags
12
- * - Status indicators
13
- * - Filter chips
14
- * - Skill labels
15
- * - Badge displays
2
+ * AtomicChip - Re-export from chip module
3
+ * Maintains backward compatibility
16
4
  */
17
5
 
18
- import React from 'react';
19
- import { View, ViewStyle, TouchableOpacity } from 'react-native';
20
- import { AtomicText } from './AtomicText';
21
- import { AtomicIcon } from './AtomicIcon';
22
- import { useAppDesignTokens } from '../theme';
23
-
24
- // =============================================================================
25
- // TYPE DEFINITIONS
26
- // =============================================================================
27
-
28
- export interface AtomicChipProps {
29
- /** Text content of the chip */
30
- children: React.ReactNode;
31
- /** Chip variant */
32
- variant?: 'filled' | 'outlined' | 'soft';
33
- /** Chip size */
34
- size?: 'sm' | 'md' | 'lg';
35
- /** Chip color theme */
36
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info';
37
- /** Custom background color */
38
- backgroundColor?: string;
39
- /** Custom text color */
40
- textColor?: string;
41
- /** Custom border color */
42
- borderColor?: string;
43
- /** Leading icon */
44
- leadingIcon?: string;
45
- /** Trailing icon */
46
- trailingIcon?: string;
47
- /** Whether the chip is clickable */
48
- clickable?: boolean;
49
- /** Click handler */
50
- onPress?: () => void;
51
- /** Whether the chip is selected */
52
- selected?: boolean;
53
- /** Whether the chip is disabled */
54
- disabled?: boolean;
55
- /** Style overrides */
56
- style?: ViewStyle;
57
- /** Test ID for testing */
58
- testID?: string;
59
- /** Active opacity for touch feedback */
60
- activeOpacity?: number;
61
- }
62
-
63
- // =============================================================================
64
- // COMPONENT IMPLEMENTATION
65
- // =============================================================================
66
-
67
- export const AtomicChip: React.FC<AtomicChipProps> = React.memo(({
68
- children,
69
- variant = 'filled',
70
- size = 'md',
71
- color = 'primary',
72
- backgroundColor,
73
- textColor,
74
- borderColor,
75
- leadingIcon,
76
- trailingIcon,
77
- clickable = false,
78
- onPress,
79
- selected = false,
80
- disabled = false,
81
- style,
82
- testID,
83
- activeOpacity = 0.7,
84
- }) => {
85
- const tokens = useAppDesignTokens();
86
-
87
- // Size mapping
88
- const sizeMap = {
89
- sm: {
90
- paddingHorizontal: tokens.spacing.sm,
91
- paddingVertical: tokens.spacing.xs,
92
- fontSize: tokens.typography.bodySmall.responsiveFontSize,
93
- iconSize: 'xs' as const
94
- },
95
- md: {
96
- paddingHorizontal: tokens.spacing.md,
97
- paddingVertical: tokens.spacing.sm,
98
- fontSize: tokens.typography.bodyMedium.responsiveFontSize,
99
- iconSize: 'sm' as const
100
- },
101
- lg: {
102
- paddingHorizontal: tokens.spacing.md,
103
- paddingVertical: tokens.spacing.sm,
104
- fontSize: tokens.typography.bodyLarge.responsiveFontSize,
105
- iconSize: 'sm' as const
106
- },
107
- };
108
-
109
- const sizeConfig = sizeMap[size];
110
-
111
- // Color mapping - using undefined for transparent backgrounds
112
- const colorMap = {
113
- primary: {
114
- filled: { bg: tokens.colors.primary, text: tokens.colors.onPrimary, border: tokens.colors.primary },
115
- outlined: { bg: undefined, text: tokens.colors.primary, border: tokens.colors.primary },
116
- soft: { bg: tokens.colors.primaryContainer, text: tokens.colors.onPrimaryContainer, border: undefined },
117
- },
118
- secondary: {
119
- filled: { bg: tokens.colors.secondary, text: tokens.colors.onSecondary, border: tokens.colors.secondary },
120
- outlined: { bg: undefined, text: tokens.colors.secondary, border: tokens.colors.secondary },
121
- soft: { bg: tokens.colors.secondaryContainer, text: tokens.colors.onSecondaryContainer, border: undefined },
122
- },
123
- success: {
124
- filled: { bg: tokens.colors.success, text: tokens.colors.onSuccess, border: tokens.colors.success },
125
- outlined: { bg: undefined, text: tokens.colors.success, border: tokens.colors.success },
126
- soft: { bg: tokens.colors.successContainer, text: tokens.colors.onSuccessContainer, border: undefined },
127
- },
128
- warning: {
129
- filled: { bg: tokens.colors.warning, text: tokens.colors.onWarning, border: tokens.colors.warning },
130
- outlined: { bg: undefined, text: tokens.colors.warning, border: tokens.colors.warning },
131
- soft: { bg: tokens.colors.warningContainer, text: tokens.colors.onWarningContainer, border: undefined },
132
- },
133
- error: {
134
- filled: { bg: tokens.colors.error, text: tokens.colors.onError, border: tokens.colors.error },
135
- outlined: { bg: undefined, text: tokens.colors.error, border: tokens.colors.error },
136
- soft: { bg: tokens.colors.errorContainer, text: tokens.colors.onErrorContainer, border: undefined },
137
- },
138
- info: {
139
- filled: { bg: tokens.colors.info, text: tokens.colors.onInfo, border: tokens.colors.info },
140
- outlined: { bg: undefined, text: tokens.colors.info, border: tokens.colors.info },
141
- soft: { bg: tokens.colors.infoContainer, text: tokens.colors.onInfoContainer, border: undefined },
142
- },
143
- };
144
-
145
- const colorConfig = colorMap[color][variant];
146
-
147
- // Apply custom colors if provided
148
- const finalBackgroundColor = backgroundColor || colorConfig.bg;
149
- const finalTextColor = textColor || colorConfig.text;
150
- const finalBorderColor = borderColor || colorConfig.border;
151
-
152
- // Handle disabled state
153
- const isDisabled = disabled || (!clickable && !onPress);
154
- const opacity = isDisabled ? 0.5 : 1;
155
-
156
- // Handle selected state
157
- const selectedStyle = selected ? {
158
- borderWidth: tokens.borders.width.medium,
159
- borderColor: tokens.colors.primary,
160
- } : {};
161
-
162
- const chipStyle: ViewStyle = {
163
- flexDirection: 'row',
164
- alignItems: 'center',
165
- justifyContent: 'center',
166
- paddingHorizontal: sizeConfig.paddingHorizontal,
167
- paddingVertical: sizeConfig.paddingVertical,
168
- backgroundColor: finalBackgroundColor,
169
- borderRadius: tokens.borders.radius.xl,
170
- borderWidth: variant === 'outlined' ? 1 : 0,
171
- borderColor: finalBorderColor,
172
- opacity,
173
- ...selectedStyle,
174
- };
175
-
176
- const textStyle = {
177
- fontSize: sizeConfig.fontSize,
178
- fontWeight: tokens.typography.medium,
179
- };
180
-
181
- const iconColor = finalTextColor;
182
-
183
- const content = (
184
- <View style={[chipStyle, style]} testID={testID}>
185
- {leadingIcon && (
186
- <AtomicIcon
187
- name={leadingIcon}
188
- size={sizeConfig.iconSize}
189
- customColor={iconColor}
190
- style={{ marginRight: tokens.spacing.xs }}
191
- />
192
- )}
193
- <AtomicText
194
- type="labelMedium"
195
- color={finalTextColor}
196
- style={textStyle}
197
- >
198
- {children}
199
- </AtomicText>
200
- {trailingIcon && (
201
- <AtomicIcon
202
- name={trailingIcon}
203
- size={sizeConfig.iconSize}
204
- customColor={iconColor}
205
- style={{ marginLeft: tokens.spacing.xs }}
206
- />
207
- )}
208
- </View>
209
- );
210
-
211
- if (clickable && onPress && !disabled) {
212
- return (
213
- <TouchableOpacity onPress={onPress} activeOpacity={activeOpacity}>
214
- {content}
215
- </TouchableOpacity>
216
- );
217
- }
218
-
219
- return content;
220
- });
221
- AtomicChip.displayName = 'AtomicChip';
222
-
223
- // =============================================================================
224
- // EXPORTS
225
- // =============================================================================
226
-
227
- export default AtomicChip;
6
+ export { AtomicChip } from './chip';
7
+ export type { AtomicChipProps } from './chip';
@@ -0,0 +1,108 @@
1
+ /**
2
+ * AtomicButton Component
3
+ * Refactored: Extracted configs, styles, and types
4
+ */
5
+
6
+ import React from 'react';
7
+ import { StyleProp, ViewStyle, TextStyle, TouchableOpacity, View } from 'react-native';
8
+ import { AtomicText } from '../AtomicText';
9
+ import { AtomicIcon } from '../AtomicIcon';
10
+ import { AtomicSpinner } from '../AtomicSpinner';
11
+ import { useAppDesignTokens } from '../../theme';
12
+ import { getButtonSizeConfig } from './configs/buttonSizeConfig';
13
+ import { getVariantStyles } from './styles/buttonVariantStyles';
14
+ import { buttonStyles } from './styles/buttonStyles';
15
+ import type { AtomicButtonProps } from './types';
16
+
17
+ export const AtomicButton: React.FC<AtomicButtonProps> = React.memo(({
18
+ title,
19
+ children,
20
+ onPress,
21
+ variant = 'primary',
22
+ size = 'md',
23
+ disabled = false,
24
+ loading = false,
25
+ icon,
26
+ iconPosition = 'left',
27
+ fullWidth = false,
28
+ style,
29
+ textStyle,
30
+ activeOpacity = 0.8,
31
+ testID,
32
+ }) => {
33
+ const tokens = useAppDesignTokens();
34
+
35
+ const handlePress = () => {
36
+ if (!disabled && !loading) {
37
+ onPress();
38
+ }
39
+ };
40
+
41
+ const isDisabled = disabled || loading;
42
+ const config = getButtonSizeConfig(size, tokens);
43
+ const variantStyles = getVariantStyles(variant, tokens);
44
+ const iconColor = variantStyles.text.color;
45
+
46
+ const containerStyle: StyleProp<ViewStyle> = [
47
+ buttonStyles.button,
48
+ {
49
+ paddingVertical: config.paddingVertical,
50
+ paddingHorizontal: config.paddingHorizontal,
51
+ minHeight: config.minHeight,
52
+ borderRadius: tokens.borders.radius.md,
53
+ },
54
+ variantStyles.container,
55
+ fullWidth ? buttonStyles.fullWidth : undefined,
56
+ isDisabled ? buttonStyles.disabled : undefined,
57
+ style,
58
+ ];
59
+
60
+ const buttonTextStyle: StyleProp<TextStyle> = [
61
+ {
62
+ fontSize: config.fontSize,
63
+ fontWeight: '600',
64
+ },
65
+ variantStyles.text,
66
+ isDisabled ? buttonStyles.disabledText : undefined,
67
+ textStyle,
68
+ ];
69
+
70
+ const buttonText = title || children;
71
+ const showIcon = icon;
72
+
73
+ return (
74
+ <TouchableOpacity
75
+ style={containerStyle}
76
+ onPress={handlePress}
77
+ activeOpacity={activeOpacity}
78
+ disabled={isDisabled}
79
+ testID={testID}
80
+ >
81
+ <View style={[buttonStyles.content, iconPosition === 'right' && buttonStyles.rowReverse]}>
82
+ {loading ? (
83
+ <AtomicSpinner
84
+ size="sm"
85
+ color={iconColor as string}
86
+ style={iconPosition === 'right' ? buttonStyles.iconRight : buttonStyles.iconLeft}
87
+ />
88
+ ) : showIcon ? (
89
+ <AtomicIcon
90
+ name={icon}
91
+ customSize={config.iconSize}
92
+ customColor={iconColor as string | undefined}
93
+ style={iconPosition === 'right' ? buttonStyles.iconRight : buttonStyles.iconLeft}
94
+ />
95
+ ) : null}
96
+
97
+ <AtomicText style={buttonTextStyle}>
98
+ {buttonText}
99
+ </AtomicText>
100
+ </View>
101
+ </TouchableOpacity>
102
+ );
103
+ });
104
+
105
+ AtomicButton.displayName = 'AtomicButton';
106
+
107
+ // Re-export types for convenience
108
+ export type { AtomicButtonProps, ButtonVariant, ButtonSize } from './types';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Button Size Configuration
3
+ */
4
+
5
+ import type { DesignTokens } from '../../../theme';
6
+ import type { ButtonSize, ButtonSizeConfig } from '../types';
7
+
8
+ export const getButtonSizeConfig = (
9
+ size: ButtonSize,
10
+ tokens: DesignTokens,
11
+ ): ButtonSizeConfig => {
12
+ const sizeConfigs: Record<ButtonSize, ButtonSizeConfig> = {
13
+ sm: {
14
+ paddingVertical: tokens.spacing.xs,
15
+ paddingHorizontal: tokens.spacing.sm,
16
+ fontSize: tokens.typography.bodySmall.responsiveFontSize,
17
+ iconSize: 16 * tokens.spacingMultiplier,
18
+ minHeight: 32 * tokens.spacingMultiplier,
19
+ },
20
+ md: {
21
+ paddingVertical: tokens.spacing.sm,
22
+ paddingHorizontal: tokens.spacing.md,
23
+ fontSize: tokens.typography.bodyMedium.responsiveFontSize,
24
+ iconSize: 20 * tokens.spacingMultiplier,
25
+ minHeight: 44 * tokens.spacingMultiplier,
26
+ },
27
+ lg: {
28
+ paddingVertical: tokens.spacing.md,
29
+ paddingHorizontal: tokens.spacing.lg,
30
+ fontSize: tokens.typography.bodyLarge.responsiveFontSize,
31
+ iconSize: 24 * tokens.spacingMultiplier,
32
+ minHeight: 52 * tokens.spacingMultiplier,
33
+ },
34
+ };
35
+
36
+ return sizeConfigs[size];
37
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * AtomicButton Barrel Export
3
+ */
4
+
5
+ export { AtomicButton } from './AtomicButton';
6
+ export type { AtomicButtonProps, ButtonVariant, ButtonSize } from './types';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Button Base Styles
3
+ */
4
+
5
+ import { StyleSheet } from 'react-native';
6
+
7
+ export const buttonStyles = StyleSheet.create({
8
+ button: {
9
+ alignItems: 'center',
10
+ justifyContent: 'center',
11
+ flexDirection: 'row',
12
+ },
13
+ content: {
14
+ flexDirection: 'row',
15
+ alignItems: 'center',
16
+ justifyContent: 'center',
17
+ },
18
+ rowReverse: {
19
+ flexDirection: 'row-reverse',
20
+ },
21
+ fullWidth: {
22
+ width: '100%',
23
+ },
24
+ disabled: {
25
+ opacity: 0.5,
26
+ },
27
+ disabledText: {
28
+ opacity: 0.7,
29
+ },
30
+ iconLeft: {
31
+ marginRight: 8,
32
+ },
33
+ iconRight: {
34
+ marginLeft: 8,
35
+ },
36
+ });