@umituz/react-native-design-system 1.1.3 → 1.3.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.
- package/README.md +16 -11
- package/package.json +1 -2
- package/src/domains/icons/domain/config/IconLibraryConfig.ts +93 -0
- package/src/domains/icons/domain/entities/Icon.ts +143 -0
- package/src/domains/icons/domain/interfaces/IIconAdapter.ts +144 -0
- package/src/domains/icons/index.ts +109 -0
- package/src/domains/icons/infrastructure/adapters/LucideAdapter.ts +100 -0
- package/src/domains/icons/infrastructure/registries/ExpoIconRegistry.ts +191 -0
- package/src/domains/icons/presentation/components/Icon.tsx +132 -0
- package/src/domains/icons/presentation/hooks/useIconLibrary.ts +141 -0
- package/src/index.ts +12 -0
- package/src/presentation/atoms/AtomicButton.tsx +188 -40
- package/src/presentation/atoms/AtomicCard.tsx +52 -29
- package/src/presentation/atoms/AtomicIcon.tsx +26 -117
- package/src/presentation/atoms/AtomicInput.tsx +217 -99
- package/src/presentation/atoms/AtomicText.tsx +38 -6
- package/src/presentation/atoms/AtomicTextArea.tsx +173 -58
- package/src/presentation/organisms/FormContainer.tsx +16 -16
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { StyleSheet, StyleProp, ViewStyle, TextStyle } from 'react-native';
|
|
2
|
+
import { StyleSheet, StyleProp, ViewStyle, TextStyle, TouchableOpacity, ActivityIndicator, View } from 'react-native';
|
|
4
3
|
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
|
|
5
|
-
import {
|
|
4
|
+
import { AtomicText } from './AtomicText';
|
|
5
|
+
import { Icon } from '../../domains/icons/presentation/components/Icon';
|
|
6
|
+
import { useAppDesignTokens } from '../hooks/useAppDesignTokens';
|
|
7
|
+
import type { IconName } from '../../domains/icons/domain/interfaces/IIconAdapter';
|
|
6
8
|
|
|
7
9
|
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'text' | 'danger';
|
|
8
10
|
export type ButtonSize = 'sm' | 'md' | 'lg';
|
|
@@ -15,14 +17,14 @@ export interface AtomicButtonProps {
|
|
|
15
17
|
size?: ButtonSize;
|
|
16
18
|
disabled?: boolean;
|
|
17
19
|
loading?: boolean;
|
|
18
|
-
icon?:
|
|
20
|
+
icon?: IconName;
|
|
19
21
|
fullWidth?: boolean;
|
|
20
22
|
style?: StyleProp<ViewStyle>;
|
|
21
23
|
textStyle?: StyleProp<TextStyle>;
|
|
22
24
|
testID?: string;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
const
|
|
27
|
+
const AnimatedTouchable = Animated.createAnimatedComponent(TouchableOpacity);
|
|
26
28
|
|
|
27
29
|
export const AtomicButton: React.FC<AtomicButtonProps> = ({
|
|
28
30
|
title,
|
|
@@ -35,8 +37,11 @@ export const AtomicButton: React.FC<AtomicButtonProps> = ({
|
|
|
35
37
|
icon,
|
|
36
38
|
fullWidth = false,
|
|
37
39
|
style,
|
|
40
|
+
textStyle,
|
|
38
41
|
testID,
|
|
39
42
|
}) => {
|
|
43
|
+
const tokens = useAppDesignTokens();
|
|
44
|
+
|
|
40
45
|
// Animation
|
|
41
46
|
const scale = useSharedValue(1);
|
|
42
47
|
|
|
@@ -63,62 +68,205 @@ export const AtomicButton: React.FC<AtomicButtonProps> = ({
|
|
|
63
68
|
}
|
|
64
69
|
};
|
|
65
70
|
|
|
66
|
-
//
|
|
67
|
-
const
|
|
71
|
+
// Size configurations
|
|
72
|
+
const sizeConfig = {
|
|
73
|
+
sm: {
|
|
74
|
+
paddingVertical: tokens.spacing.xs,
|
|
75
|
+
paddingHorizontal: tokens.spacing.sm,
|
|
76
|
+
fontSize: tokens.typography.bodySmall.fontSize,
|
|
77
|
+
iconSize: 16,
|
|
78
|
+
minHeight: 32,
|
|
79
|
+
},
|
|
80
|
+
md: {
|
|
81
|
+
paddingVertical: tokens.spacing.sm,
|
|
82
|
+
paddingHorizontal: tokens.spacing.md,
|
|
83
|
+
fontSize: tokens.typography.bodyMedium.fontSize,
|
|
84
|
+
iconSize: 20,
|
|
85
|
+
minHeight: 44,
|
|
86
|
+
},
|
|
87
|
+
lg: {
|
|
88
|
+
paddingVertical: tokens.spacing.md,
|
|
89
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
90
|
+
fontSize: tokens.typography.bodyLarge.fontSize,
|
|
91
|
+
iconSize: 24,
|
|
92
|
+
minHeight: 52,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const config = sizeConfig[size];
|
|
97
|
+
|
|
98
|
+
// Variant styles
|
|
99
|
+
const getVariantStyles = () => {
|
|
100
|
+
const baseStyle: ViewStyle = {
|
|
101
|
+
backgroundColor: tokens.colors.primary,
|
|
102
|
+
borderWidth: 0,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const baseTextStyle: TextStyle = {
|
|
106
|
+
color: tokens.colors.textInverse,
|
|
107
|
+
};
|
|
108
|
+
|
|
68
109
|
switch (variant) {
|
|
69
110
|
case 'primary':
|
|
70
|
-
return
|
|
111
|
+
return {
|
|
112
|
+
container: {
|
|
113
|
+
...baseStyle,
|
|
114
|
+
backgroundColor: tokens.colors.primary,
|
|
115
|
+
},
|
|
116
|
+
text: {
|
|
117
|
+
...baseTextStyle,
|
|
118
|
+
color: tokens.colors.textInverse,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
71
122
|
case 'secondary':
|
|
72
|
-
return
|
|
123
|
+
return {
|
|
124
|
+
container: {
|
|
125
|
+
...baseStyle,
|
|
126
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
127
|
+
},
|
|
128
|
+
text: {
|
|
129
|
+
...baseTextStyle,
|
|
130
|
+
color: tokens.colors.textPrimary,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
73
134
|
case 'outline':
|
|
74
|
-
return
|
|
135
|
+
return {
|
|
136
|
+
container: {
|
|
137
|
+
...baseStyle,
|
|
138
|
+
backgroundColor: 'transparent',
|
|
139
|
+
borderWidth: 1,
|
|
140
|
+
borderColor: tokens.colors.border,
|
|
141
|
+
},
|
|
142
|
+
text: {
|
|
143
|
+
...baseTextStyle,
|
|
144
|
+
color: tokens.colors.textPrimary,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
75
148
|
case 'text':
|
|
76
|
-
return
|
|
149
|
+
return {
|
|
150
|
+
container: {
|
|
151
|
+
...baseStyle,
|
|
152
|
+
backgroundColor: 'transparent',
|
|
153
|
+
},
|
|
154
|
+
text: {
|
|
155
|
+
...baseTextStyle,
|
|
156
|
+
color: tokens.colors.primary,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
77
160
|
case 'danger':
|
|
78
|
-
return
|
|
161
|
+
return {
|
|
162
|
+
container: {
|
|
163
|
+
...baseStyle,
|
|
164
|
+
backgroundColor: tokens.colors.error,
|
|
165
|
+
},
|
|
166
|
+
text: {
|
|
167
|
+
...baseTextStyle,
|
|
168
|
+
color: tokens.colors.textInverse,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
|
|
79
172
|
default:
|
|
80
|
-
return
|
|
173
|
+
return {
|
|
174
|
+
container: baseStyle,
|
|
175
|
+
text: baseTextStyle,
|
|
176
|
+
};
|
|
81
177
|
}
|
|
82
178
|
};
|
|
83
179
|
|
|
84
|
-
|
|
85
|
-
const getContentStyle = () => {
|
|
86
|
-
const paddingMap = {
|
|
87
|
-
sm: { paddingVertical: 4, paddingHorizontal: 12 },
|
|
88
|
-
md: { paddingVertical: 8, paddingHorizontal: 16 },
|
|
89
|
-
lg: { paddingVertical: 12, paddingHorizontal: 20 },
|
|
90
|
-
};
|
|
91
|
-
return paddingMap[size];
|
|
92
|
-
};
|
|
180
|
+
const variantStyles = getVariantStyles();
|
|
93
181
|
|
|
94
|
-
const
|
|
95
|
-
|
|
182
|
+
const containerStyle: StyleProp<ViewStyle> = [
|
|
183
|
+
styles.button,
|
|
184
|
+
{
|
|
185
|
+
paddingVertical: config.paddingVertical,
|
|
186
|
+
paddingHorizontal: config.paddingHorizontal,
|
|
187
|
+
minHeight: config.minHeight,
|
|
188
|
+
borderRadius: tokens.borders.radius.md,
|
|
189
|
+
},
|
|
190
|
+
variantStyles.container,
|
|
191
|
+
fullWidth ? styles.fullWidth : undefined,
|
|
192
|
+
disabled ? styles.disabled : undefined,
|
|
96
193
|
style,
|
|
97
|
-
]
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const buttonTextStyle: StyleProp<TextStyle> = [
|
|
197
|
+
{
|
|
198
|
+
fontSize: config.fontSize,
|
|
199
|
+
fontWeight: '600',
|
|
200
|
+
},
|
|
201
|
+
variantStyles.text,
|
|
202
|
+
disabled ? styles.disabledText : undefined,
|
|
203
|
+
textStyle,
|
|
204
|
+
];
|
|
98
205
|
|
|
99
206
|
const buttonText = title || children;
|
|
207
|
+
const showIcon = icon && !loading;
|
|
208
|
+
const iconColor = variantStyles.text.color;
|
|
100
209
|
|
|
101
210
|
return (
|
|
102
|
-
<
|
|
103
|
-
style={animatedStyle}
|
|
211
|
+
<AnimatedTouchable
|
|
212
|
+
style={[animatedStyle, containerStyle]}
|
|
104
213
|
onPressIn={handlePressIn}
|
|
105
214
|
onPressOut={handlePressOut}
|
|
106
215
|
onPress={handlePress}
|
|
216
|
+
activeOpacity={0.8}
|
|
217
|
+
disabled={disabled || loading}
|
|
218
|
+
testID={testID}
|
|
107
219
|
>
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
220
|
+
<View style={styles.content}>
|
|
221
|
+
{loading ? (
|
|
222
|
+
<ActivityIndicator
|
|
223
|
+
size="small"
|
|
224
|
+
color={variantStyles.text.color}
|
|
225
|
+
style={styles.loader}
|
|
226
|
+
/>
|
|
227
|
+
) : showIcon ? (
|
|
228
|
+
<Icon
|
|
229
|
+
name={icon}
|
|
230
|
+
customSize={config.iconSize}
|
|
231
|
+
customColor={iconColor}
|
|
232
|
+
style={styles.icon}
|
|
233
|
+
/>
|
|
234
|
+
) : null}
|
|
235
|
+
|
|
236
|
+
<AtomicText style={buttonTextStyle}>
|
|
237
|
+
{buttonText}
|
|
238
|
+
</AtomicText>
|
|
239
|
+
</View>
|
|
240
|
+
</AnimatedTouchable>
|
|
121
241
|
);
|
|
122
242
|
};
|
|
123
243
|
|
|
244
|
+
const styles = StyleSheet.create({
|
|
245
|
+
button: {
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
justifyContent: 'center',
|
|
248
|
+
flexDirection: 'row',
|
|
249
|
+
},
|
|
250
|
+
content: {
|
|
251
|
+
flexDirection: 'row',
|
|
252
|
+
alignItems: 'center',
|
|
253
|
+
justifyContent: 'center',
|
|
254
|
+
},
|
|
255
|
+
fullWidth: {
|
|
256
|
+
width: '100%',
|
|
257
|
+
},
|
|
258
|
+
disabled: {
|
|
259
|
+
opacity: 0.5,
|
|
260
|
+
},
|
|
261
|
+
disabledText: {
|
|
262
|
+
opacity: 0.7,
|
|
263
|
+
},
|
|
264
|
+
icon: {
|
|
265
|
+
marginRight: 8,
|
|
266
|
+
},
|
|
267
|
+
loader: {
|
|
268
|
+
marginRight: 8,
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
|
|
124
272
|
export type { AtomicButtonProps as ButtonProps };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import { View, StyleProp, ViewStyle } from 'react-native';
|
|
4
3
|
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated';
|
|
5
4
|
import { Pressable } from 'react-native';
|
|
5
|
+
import { useAppDesignTokens } from '../hooks/useAppDesignTokens';
|
|
6
6
|
|
|
7
7
|
export type AtomicCardVariant = 'flat' | 'elevated' | 'outlined';
|
|
8
8
|
export type AtomicCardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl';
|
|
@@ -28,6 +28,8 @@ export const AtomicCard: React.FC<AtomicCardProps> = ({
|
|
|
28
28
|
children,
|
|
29
29
|
testID,
|
|
30
30
|
}) => {
|
|
31
|
+
const tokens = useAppDesignTokens();
|
|
32
|
+
|
|
31
33
|
// Animation for tap feedback
|
|
32
34
|
const scale = useSharedValue(1);
|
|
33
35
|
|
|
@@ -54,43 +56,64 @@ export const AtomicCard: React.FC<AtomicCardProps> = ({
|
|
|
54
56
|
}
|
|
55
57
|
};
|
|
56
58
|
|
|
57
|
-
// Map
|
|
58
|
-
const
|
|
59
|
+
// Map padding to token values
|
|
60
|
+
const getPaddingValue = (): number => {
|
|
61
|
+
const paddingMap = {
|
|
62
|
+
none: 0,
|
|
63
|
+
sm: tokens.spacing.sm,
|
|
64
|
+
md: tokens.spacing.md,
|
|
65
|
+
lg: tokens.spacing.lg,
|
|
66
|
+
xl: tokens.spacing.xl,
|
|
67
|
+
};
|
|
68
|
+
return paddingMap[padding];
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Get variant styles
|
|
72
|
+
const getVariantStyle = (): ViewStyle => {
|
|
73
|
+
const baseStyle: ViewStyle = {
|
|
74
|
+
backgroundColor: tokens.colors.surface,
|
|
75
|
+
borderRadius: tokens.borders.radius.md,
|
|
76
|
+
};
|
|
77
|
+
|
|
59
78
|
switch (variant) {
|
|
60
79
|
case 'elevated':
|
|
61
|
-
return
|
|
80
|
+
return {
|
|
81
|
+
...baseStyle,
|
|
82
|
+
borderWidth: 1,
|
|
83
|
+
borderColor: tokens.colors.border,
|
|
84
|
+
};
|
|
85
|
+
|
|
62
86
|
case 'outlined':
|
|
63
|
-
return
|
|
87
|
+
return {
|
|
88
|
+
...baseStyle,
|
|
89
|
+
borderWidth: 1,
|
|
90
|
+
borderColor: tokens.colors.border,
|
|
91
|
+
};
|
|
92
|
+
|
|
64
93
|
case 'flat':
|
|
65
|
-
return
|
|
94
|
+
return {
|
|
95
|
+
...baseStyle,
|
|
96
|
+
borderWidth: 0,
|
|
97
|
+
};
|
|
98
|
+
|
|
66
99
|
default:
|
|
67
|
-
return
|
|
100
|
+
return baseStyle;
|
|
68
101
|
}
|
|
69
102
|
};
|
|
70
103
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
const paddingValue = paddingMap[padding];
|
|
81
|
-
return { padding: paddingValue };
|
|
82
|
-
};
|
|
104
|
+
const cardStyle: StyleProp<ViewStyle> = [
|
|
105
|
+
getVariantStyle(),
|
|
106
|
+
{
|
|
107
|
+
padding: getPaddingValue(),
|
|
108
|
+
opacity: disabled ? 0.5 : 1,
|
|
109
|
+
},
|
|
110
|
+
style,
|
|
111
|
+
];
|
|
83
112
|
|
|
84
113
|
const cardContent = (
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
testID={testID}
|
|
89
|
-
>
|
|
90
|
-
<PaperCard.Content style={getContentStyle()}>
|
|
91
|
-
{children}
|
|
92
|
-
</PaperCard.Content>
|
|
93
|
-
</PaperCard>
|
|
114
|
+
<View style={cardStyle} testID={testID}>
|
|
115
|
+
{children}
|
|
116
|
+
</View>
|
|
94
117
|
);
|
|
95
118
|
|
|
96
119
|
// If onPress provided, wrap with animated pressable
|
|
@@ -1,132 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AtomicIcon - Design System Icon Component
|
|
2
|
+
* AtomicIcon - Atomic Design System Icon Component
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Provides
|
|
4
|
+
* Wrapper for the universal Icon component from @domains/icons
|
|
5
|
+
* Provides backward compatibility with AtomicIcon naming convention
|
|
6
|
+
* while leveraging the full power of the icons domain architecture.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import React from 'react';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Icon size presets
|
|
15
|
-
*/
|
|
16
|
-
export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Semantic color tokens
|
|
20
|
-
*/
|
|
21
|
-
export type IconColor =
|
|
22
|
-
| 'primary'
|
|
23
|
-
| 'secondary'
|
|
24
|
-
| 'error'
|
|
25
|
-
| 'warning'
|
|
26
|
-
| 'success'
|
|
27
|
-
| 'info'
|
|
28
|
-
| 'onPrimary'
|
|
29
|
-
| 'onSurface'
|
|
30
|
-
| 'textPrimary'
|
|
31
|
-
| 'textSecondary'
|
|
32
|
-
| 'textDisabled';
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Icon component props
|
|
36
|
-
*/
|
|
37
|
-
export interface IconProps {
|
|
38
|
-
/** Icon name from Lucide icon set (PascalCase) */
|
|
39
|
-
name: string;
|
|
40
|
-
/** Semantic color token */
|
|
41
|
-
color?: IconColor;
|
|
42
|
-
/** Size preset */
|
|
43
|
-
size?: IconSize;
|
|
44
|
-
/** Custom size override (pixels) */
|
|
45
|
-
customSize?: number;
|
|
46
|
-
/** Custom color override (hex) */
|
|
47
|
-
customColor?: string;
|
|
48
|
-
/** Optional style */
|
|
49
|
-
style?: ViewStyle;
|
|
50
|
-
/** Optional test ID */
|
|
51
|
-
testID?: string;
|
|
52
|
-
/** Legacy prop support: icon (alias for name) */
|
|
53
|
-
icon?: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Icon name type (all Lucide icon names as string)
|
|
58
|
-
*/
|
|
59
|
-
export type IconName = string;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Size mapping (pixels)
|
|
63
|
-
*/
|
|
64
|
-
const sizeMap: Record<IconSize, number> = {
|
|
65
|
-
xs: 16,
|
|
66
|
-
sm: 20,
|
|
67
|
-
md: 24,
|
|
68
|
-
lg: 28,
|
|
69
|
-
xl: 32,
|
|
70
|
-
xxl: 48,
|
|
71
|
-
};
|
|
10
|
+
import { Icon } from '../../domains/icons/presentation/components/Icon';
|
|
11
|
+
import type { IconProps, IconSize, IconColor } from '../../domains/icons/domain/interfaces/IIconAdapter';
|
|
12
|
+
import type { LucideIconName } from '../../domains/icons/infrastructure/adapters/LucideAdapter';
|
|
72
13
|
|
|
73
14
|
/**
|
|
74
15
|
* AtomicIcon Component
|
|
75
16
|
*
|
|
76
|
-
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import { AtomicIcon } from '@umituz/react-native-design-system';
|
|
20
|
+
*
|
|
21
|
+
* // Basic usage
|
|
22
|
+
* <AtomicIcon name="Settings" size="md" color="primary" />
|
|
23
|
+
*
|
|
24
|
+
* // Custom size and color
|
|
25
|
+
* <AtomicIcon name="Heart" customSize={32} customColor="#FF0000" />
|
|
26
|
+
*
|
|
27
|
+
* // With background
|
|
28
|
+
* <AtomicIcon name="Info" size="lg" withBackground backgroundColor="#667eea" />
|
|
29
|
+
* ```
|
|
77
30
|
*/
|
|
78
|
-
export const AtomicIcon: React.FC<IconProps> = ({
|
|
79
|
-
|
|
80
|
-
icon, // Legacy support
|
|
81
|
-
color = 'textPrimary',
|
|
82
|
-
size = 'md',
|
|
83
|
-
customSize,
|
|
84
|
-
customColor,
|
|
85
|
-
style,
|
|
86
|
-
testID,
|
|
87
|
-
}) => {
|
|
88
|
-
const tokens = useAppDesignTokens();
|
|
89
|
-
|
|
90
|
-
// Support legacy 'icon' prop (fallback to 'name')
|
|
91
|
-
const iconName = name || icon || '';
|
|
92
|
-
|
|
93
|
-
// Get icon component from Lucide
|
|
94
|
-
const IconComponent = (LucideIcons as any)[iconName];
|
|
95
|
-
|
|
96
|
-
if (!IconComponent) {
|
|
97
|
-
console.warn(`Icon "${iconName}" not found in Lucide icon set`);
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Resolve color from semantic token
|
|
102
|
-
const resolveColor = (): string => {
|
|
103
|
-
if (customColor) return customColor;
|
|
104
|
-
|
|
105
|
-
const colorMap: Record<IconColor, string> = {
|
|
106
|
-
primary: tokens.colors.primary,
|
|
107
|
-
secondary: tokens.colors.secondary,
|
|
108
|
-
error: tokens.colors.error,
|
|
109
|
-
warning: tokens.colors.warning,
|
|
110
|
-
success: tokens.colors.success,
|
|
111
|
-
info: tokens.colors.info,
|
|
112
|
-
onPrimary: tokens.colors.onPrimary,
|
|
113
|
-
onSurface: tokens.colors.onSurface,
|
|
114
|
-
textPrimary: tokens.colors.textPrimary,
|
|
115
|
-
textSecondary: tokens.colors.textSecondary,
|
|
116
|
-
textDisabled: tokens.colors.textDisabled,
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
return colorMap[color];
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
// Resolve size
|
|
123
|
-
const iconSize = customSize || sizeMap[size];
|
|
124
|
-
|
|
125
|
-
return <IconComponent color={resolveColor()} size={iconSize} style={style} testID={testID} />;
|
|
31
|
+
export const AtomicIcon: React.FC<IconProps> = (props) => {
|
|
32
|
+
return <Icon {...props} />;
|
|
126
33
|
};
|
|
127
34
|
|
|
128
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Re-export types with Atomic naming convention
|
|
37
|
+
*/
|
|
129
38
|
export type AtomicIconProps = IconProps;
|
|
130
39
|
export type AtomicIconSize = IconSize;
|
|
131
40
|
export type AtomicIconColor = IconColor;
|
|
132
|
-
export type AtomicIconName =
|
|
41
|
+
export type AtomicIconName = LucideIconName;
|