@umituz/react-native-design-system 1.5.36 → 1.5.38
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 +2 -2
- package/package.json +7 -5
- package/src/index.ts +29 -221
- package/src/presentation/organisms/AppHeader.tsx +3 -5
- package/src/presentation/tokens/commonStyles.ts +1 -1
- package/src/presentation/atoms/AtomicAvatar.tsx +0 -157
- package/src/presentation/atoms/AtomicAvatarGroup.tsx +0 -169
- package/src/presentation/atoms/AtomicBadge.tsx +0 -232
- package/src/presentation/atoms/AtomicButton.tsx +0 -236
- package/src/presentation/atoms/AtomicCard.tsx +0 -107
- package/src/presentation/atoms/AtomicChip.tsx +0 -223
- package/src/presentation/atoms/AtomicDatePicker.tsx +0 -347
- package/src/presentation/atoms/AtomicDivider.tsx +0 -114
- package/src/presentation/atoms/AtomicFab.tsx +0 -98
- package/src/presentation/atoms/AtomicFilter.tsx +0 -154
- package/src/presentation/atoms/AtomicFormError.tsx +0 -105
- package/src/presentation/atoms/AtomicIcon.tsx +0 -40
- package/src/presentation/atoms/AtomicImage.tsx +0 -149
- package/src/presentation/atoms/AtomicInput.tsx +0 -363
- package/src/presentation/atoms/AtomicNumberInput.tsx +0 -182
- package/src/presentation/atoms/AtomicPicker.tsx +0 -458
- package/src/presentation/atoms/AtomicProgress.tsx +0 -139
- package/src/presentation/atoms/AtomicSearchBar.tsx +0 -114
- package/src/presentation/atoms/AtomicSort.tsx +0 -145
- package/src/presentation/atoms/AtomicSwitch.tsx +0 -166
- package/src/presentation/atoms/AtomicText.tsx +0 -55
- package/src/presentation/atoms/AtomicTextArea.tsx +0 -313
- package/src/presentation/atoms/AtomicTouchable.tsx +0 -209
- package/src/presentation/atoms/fab/styles/fabStyles.ts +0 -69
- package/src/presentation/atoms/fab/types/index.ts +0 -82
- package/src/presentation/atoms/filter/styles/filterStyles.ts +0 -32
- package/src/presentation/atoms/filter/types/index.ts +0 -89
- package/src/presentation/atoms/index.ts +0 -366
- package/src/presentation/atoms/input/hooks/useInputState.ts +0 -15
- package/src/presentation/atoms/input/styles/inputStyles.ts +0 -66
- package/src/presentation/atoms/input/types/index.ts +0 -25
- package/src/presentation/atoms/picker/styles/pickerStyles.ts +0 -207
- package/src/presentation/atoms/picker/types/index.ts +0 -40
- package/src/presentation/atoms/touchable/styles/touchableStyles.ts +0 -62
- package/src/presentation/atoms/touchable/types/index.ts +0 -155
- package/src/presentation/hooks/useResponsive.ts +0 -180
- package/src/presentation/molecules/AtomicConfirmationModal.tsx +0 -243
- package/src/presentation/molecules/EmptyState.tsx +0 -130
- package/src/presentation/molecules/FormField.tsx +0 -128
- package/src/presentation/molecules/GridContainer.tsx +0 -124
- package/src/presentation/molecules/IconContainer.tsx +0 -94
- package/src/presentation/molecules/ListItem.tsx +0 -36
- package/src/presentation/molecules/ScreenHeader.tsx +0 -140
- package/src/presentation/molecules/SearchBar.tsx +0 -85
- package/src/presentation/molecules/SectionCard.tsx +0 -74
- package/src/presentation/molecules/SectionContainer.tsx +0 -106
- package/src/presentation/molecules/SectionHeader.tsx +0 -125
- package/src/presentation/molecules/confirmation-modal/styles/confirmationModalStyles.ts +0 -133
- package/src/presentation/molecules/confirmation-modal/types/index.ts +0 -105
- package/src/presentation/molecules/index.ts +0 -41
- package/src/presentation/molecules/listitem/styles/listItemStyles.ts +0 -19
- package/src/presentation/molecules/listitem/types/index.ts +0 -17
- package/src/presentation/organisms/FormContainer.tsx +0 -180
- package/src/presentation/organisms/ScreenLayout.tsx +0 -171
- package/src/presentation/organisms/index.ts +0 -25
- package/src/presentation/utils/platformConstants.ts +0 -124
- package/src/presentation/utils/responsive.ts +0 -516
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AtomicDivider - Universal Divider Component
|
|
3
|
-
*
|
|
4
|
-
* Displays horizontal or vertical dividers for content separation
|
|
5
|
-
* Theme: {{THEME_NAME}} ({{CATEGORY}} category)
|
|
6
|
-
*
|
|
7
|
-
* Atomic Design Level: ATOM
|
|
8
|
-
* Purpose: Content separation and visual hierarchy
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* - Section separators
|
|
12
|
-
* - List item dividers
|
|
13
|
-
* - Card separators
|
|
14
|
-
* - Menu dividers
|
|
15
|
-
* - Form field separators
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import React from 'react';
|
|
19
|
-
import { View, StyleSheet, ViewStyle } from 'react-native';
|
|
20
|
-
import { useAppDesignTokens } from '@umituz/react-native-theme';
|
|
21
|
-
|
|
22
|
-
// =============================================================================
|
|
23
|
-
// TYPE DEFINITIONS
|
|
24
|
-
// =============================================================================
|
|
25
|
-
|
|
26
|
-
export interface AtomicDividerProps {
|
|
27
|
-
/** Divider orientation */
|
|
28
|
-
orientation?: 'horizontal' | 'vertical';
|
|
29
|
-
/** Divider thickness */
|
|
30
|
-
thickness?: 'thin' | 'medium' | 'thick';
|
|
31
|
-
/** Divider color */
|
|
32
|
-
color?: string;
|
|
33
|
-
/** Divider length (for horizontal: width, for vertical: height) */
|
|
34
|
-
length?: number | string;
|
|
35
|
-
/** Margin around the divider */
|
|
36
|
-
margin?: number;
|
|
37
|
-
/** Margin top */
|
|
38
|
-
marginTop?: number;
|
|
39
|
-
/** Margin bottom */
|
|
40
|
-
marginBottom?: number;
|
|
41
|
-
/** Margin left */
|
|
42
|
-
marginLeft?: number;
|
|
43
|
-
/** Margin right */
|
|
44
|
-
marginRight?: number;
|
|
45
|
-
/** Style overrides */
|
|
46
|
-
style?: ViewStyle;
|
|
47
|
-
/** Test ID for testing */
|
|
48
|
-
testID?: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// =============================================================================
|
|
52
|
-
// COMPONENT IMPLEMENTATION
|
|
53
|
-
// =============================================================================
|
|
54
|
-
|
|
55
|
-
export const AtomicDivider: React.FC<AtomicDividerProps> = ({
|
|
56
|
-
orientation = 'horizontal',
|
|
57
|
-
thickness = 'thin',
|
|
58
|
-
color,
|
|
59
|
-
length,
|
|
60
|
-
margin,
|
|
61
|
-
marginTop,
|
|
62
|
-
marginBottom,
|
|
63
|
-
marginLeft,
|
|
64
|
-
marginRight,
|
|
65
|
-
style,
|
|
66
|
-
testID,
|
|
67
|
-
}) => {
|
|
68
|
-
const tokens = useAppDesignTokens();
|
|
69
|
-
|
|
70
|
-
// Thickness mapping
|
|
71
|
-
const thicknessMap = {
|
|
72
|
-
thin: 1,
|
|
73
|
-
medium: 2,
|
|
74
|
-
thick: 4,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const dividerThickness = thicknessMap[thickness];
|
|
78
|
-
const dividerColor = color || tokens.colors.border;
|
|
79
|
-
|
|
80
|
-
// Compute final length values with proper type handling
|
|
81
|
-
const finalLength = length !== undefined ? length : (orientation === 'horizontal' ? '100%' : 20);
|
|
82
|
-
|
|
83
|
-
// Base styles for all dividers
|
|
84
|
-
const baseStyle: ViewStyle = {
|
|
85
|
-
backgroundColor: dividerColor,
|
|
86
|
-
margin: margin,
|
|
87
|
-
marginTop: marginTop,
|
|
88
|
-
marginBottom: marginBottom,
|
|
89
|
-
marginLeft: marginLeft,
|
|
90
|
-
marginRight: marginRight,
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// Orientation-specific styles with explicit type casting
|
|
94
|
-
const orientationStyle: ViewStyle = (orientation === 'horizontal' ? {
|
|
95
|
-
width: finalLength as ViewStyle['width'],
|
|
96
|
-
height: dividerThickness,
|
|
97
|
-
} : {
|
|
98
|
-
width: dividerThickness,
|
|
99
|
-
height: finalLength as ViewStyle['height'],
|
|
100
|
-
}) as ViewStyle;
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<View
|
|
104
|
-
style={[baseStyle, orientationStyle, style]}
|
|
105
|
-
testID={testID}
|
|
106
|
-
/>
|
|
107
|
-
);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
// =============================================================================
|
|
111
|
-
// EXPORTS
|
|
112
|
-
// =============================================================================
|
|
113
|
-
|
|
114
|
-
export default AtomicDivider;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
-
import { useAppDesignTokens } from '@umituz/react-native-theme';
|
|
4
|
-
import { useResponsive } from '../hooks/useResponsive';
|
|
5
|
-
import { AtomicIcon } from './AtomicIcon';
|
|
6
|
-
import { AtomicFabProps } from './fab/types';
|
|
7
|
-
import {
|
|
8
|
-
FAB_SIZES,
|
|
9
|
-
getFabVariants,
|
|
10
|
-
getFabIconSize,
|
|
11
|
-
getFabBorder,
|
|
12
|
-
} from './fab/styles/fabStyles';
|
|
13
|
-
|
|
14
|
-
export type { FabSize, FabVariant, FabVariantConfig, FabSizeConfig, AtomicFabProps } from './fab/types';
|
|
15
|
-
export { FAB_SIZES, getFabVariants, getFabIconSize, getFabBorder };
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* AtomicFab - Floating Action Button Component
|
|
19
|
-
*
|
|
20
|
-
* A Material Design 3 compliant FAB component for primary actions.
|
|
21
|
-
* Follows CLAUDE.md standards for responsive positioning.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```tsx
|
|
25
|
-
* // IMPORTANT: FAB must be used at screen level, NOT inside ScrollView
|
|
26
|
-
* <ScreenLayout>
|
|
27
|
-
* <ScrollView>
|
|
28
|
-
* {/* Your content *\/}
|
|
29
|
-
* </ScrollView>
|
|
30
|
-
* <AtomicFab
|
|
31
|
-
* icon="add"
|
|
32
|
-
* onPress={handleAddItem}
|
|
33
|
-
* variant="primary"
|
|
34
|
-
* size="md"
|
|
35
|
-
* />
|
|
36
|
-
* </ScreenLayout>
|
|
37
|
-
* ```
|
|
38
|
-
*
|
|
39
|
-
* Features:
|
|
40
|
-
* - Material Design 3 sizes (sm: 40px, md: 56px, lg: 72px)
|
|
41
|
-
* - Three variants: primary, secondary, surface
|
|
42
|
-
* - Responsive positioning (above tab bar, safe area aware)
|
|
43
|
-
* - Disabled state with opacity
|
|
44
|
-
* - Theme-aware colors from design tokens
|
|
45
|
-
* - Border for depth (no shadows per CLAUDE.md)
|
|
46
|
-
*/
|
|
47
|
-
export const AtomicFab: React.FC<AtomicFabProps> = ({
|
|
48
|
-
icon,
|
|
49
|
-
onPress,
|
|
50
|
-
variant = 'primary',
|
|
51
|
-
size = 'md',
|
|
52
|
-
disabled = false,
|
|
53
|
-
style,
|
|
54
|
-
testID,
|
|
55
|
-
accessibilityLabel,
|
|
56
|
-
}) => {
|
|
57
|
-
const tokens = useAppDesignTokens();
|
|
58
|
-
const responsive = useResponsive();
|
|
59
|
-
const isDisabled = disabled;
|
|
60
|
-
|
|
61
|
-
// Get configurations
|
|
62
|
-
const sizeConfig = FAB_SIZES[size as 'sm' | 'md' | 'lg'];
|
|
63
|
-
const variants = getFabVariants(tokens);
|
|
64
|
-
const variantConfig = variants[variant as 'primary' | 'secondary' | 'surface'];
|
|
65
|
-
const iconSize = getFabIconSize(size as 'sm' | 'md' | 'lg');
|
|
66
|
-
|
|
67
|
-
// Combine styles
|
|
68
|
-
const fabStyle = StyleSheet.flatten([
|
|
69
|
-
{
|
|
70
|
-
position: 'absolute' as const,
|
|
71
|
-
bottom: responsive.fabPosition.bottom,
|
|
72
|
-
right: responsive.fabPosition.right,
|
|
73
|
-
width: sizeConfig.width,
|
|
74
|
-
height: sizeConfig.height,
|
|
75
|
-
borderRadius: sizeConfig.borderRadius,
|
|
76
|
-
backgroundColor: variantConfig.backgroundColor,
|
|
77
|
-
alignItems: 'center' as const,
|
|
78
|
-
justifyContent: 'center' as const,
|
|
79
|
-
},
|
|
80
|
-
getFabBorder(tokens),
|
|
81
|
-
isDisabled ? { opacity: tokens.opacity.disabled } : undefined,
|
|
82
|
-
style, // Custom style override
|
|
83
|
-
]);
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<TouchableOpacity
|
|
87
|
-
style={fabStyle}
|
|
88
|
-
onPress={onPress}
|
|
89
|
-
disabled={isDisabled}
|
|
90
|
-
activeOpacity={0.7}
|
|
91
|
-
testID={testID}
|
|
92
|
-
accessibilityLabel={accessibilityLabel || `${icon} button`}
|
|
93
|
-
accessibilityRole="button"
|
|
94
|
-
>
|
|
95
|
-
<AtomicIcon name={icon} size={iconSize} customColor={variantConfig.iconColor} />
|
|
96
|
-
</TouchableOpacity>
|
|
97
|
-
);
|
|
98
|
-
};
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ScrollView, View, TouchableOpacity, ViewStyle } from 'react-native';
|
|
3
|
-
import { useAppDesignTokens } from '@umituz/react-native-theme';
|
|
4
|
-
import { AtomicChip } from './AtomicChip';
|
|
5
|
-
import { AtomicText } from './AtomicText';
|
|
6
|
-
import { AtomicIcon } from './AtomicIcon';
|
|
7
|
-
import { AtomicFilterProps, FilterOption } from './filter/types';
|
|
8
|
-
import {
|
|
9
|
-
getFilterContainerStyle,
|
|
10
|
-
getClearAllContainerStyle,
|
|
11
|
-
getScrollContentContainerStyle,
|
|
12
|
-
} from './filter/styles/filterStyles';
|
|
13
|
-
|
|
14
|
-
export type { FilterOption, AtomicFilterProps } from './filter/types';
|
|
15
|
-
export {
|
|
16
|
-
getFilterContainerStyle,
|
|
17
|
-
getClearAllContainerStyle,
|
|
18
|
-
getScrollContentContainerStyle,
|
|
19
|
-
} from './filter/styles/filterStyles';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* AtomicFilter - Horizontal Filter Chip Component
|
|
23
|
-
*
|
|
24
|
-
* A Material Design 3 compliant filter component using chip selection.
|
|
25
|
-
* Supports single and multi-select modes with "Clear All" functionality.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```tsx
|
|
29
|
-
* const [selectedFilters, setSelectedFilters] = useState<string[]>([]);
|
|
30
|
-
*
|
|
31
|
-
* <AtomicFilter
|
|
32
|
-
* options={[
|
|
33
|
-
* { id: 'active', label: 'Active', icon: 'check-circle' },
|
|
34
|
-
* { id: 'completed', label: 'Completed', icon: 'check' },
|
|
35
|
-
* { id: 'pending', label: 'Pending', icon: 'clock' },
|
|
36
|
-
* ]}
|
|
37
|
-
* selectedIds={selectedFilters}
|
|
38
|
-
* onSelectionChange={setSelectedFilters}
|
|
39
|
-
* multiSelect={true}
|
|
40
|
-
* showClearAll={true}
|
|
41
|
-
* />
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* Features:
|
|
45
|
-
* - Horizontal scrollable filter chips
|
|
46
|
-
* - Single/Multi-select modes
|
|
47
|
-
* - Clear all button (when filters active)
|
|
48
|
-
* - Theme-aware colors from design tokens
|
|
49
|
-
* - Icon support per filter option
|
|
50
|
-
* - Fully controlled component
|
|
51
|
-
*/
|
|
52
|
-
export const AtomicFilter: React.FC<AtomicFilterProps> = ({
|
|
53
|
-
options,
|
|
54
|
-
selectedIds,
|
|
55
|
-
onSelectionChange,
|
|
56
|
-
multiSelect = true,
|
|
57
|
-
showClearAll = true,
|
|
58
|
-
variant = 'outlined',
|
|
59
|
-
color = 'primary',
|
|
60
|
-
size = 'md',
|
|
61
|
-
style,
|
|
62
|
-
testID,
|
|
63
|
-
}) => {
|
|
64
|
-
const tokens = useAppDesignTokens();
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Handle filter chip press
|
|
68
|
-
*/
|
|
69
|
-
const handleFilterPress = (optionId: string) => {
|
|
70
|
-
if (multiSelect) {
|
|
71
|
-
// Multi-select mode: Toggle selection
|
|
72
|
-
if (selectedIds.includes(optionId)) {
|
|
73
|
-
// Deselect
|
|
74
|
-
onSelectionChange(selectedIds.filter(id => id !== optionId));
|
|
75
|
-
} else {
|
|
76
|
-
// Select
|
|
77
|
-
onSelectionChange([...selectedIds, optionId]);
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
// Single-select mode: Replace selection
|
|
81
|
-
if (selectedIds.includes(optionId)) {
|
|
82
|
-
// Deselect (clear selection)
|
|
83
|
-
onSelectionChange([]);
|
|
84
|
-
} else {
|
|
85
|
-
// Select (only this one)
|
|
86
|
-
onSelectionChange([optionId]);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Handle clear all button press
|
|
93
|
-
*/
|
|
94
|
-
const handleClearAll = () => {
|
|
95
|
-
onSelectionChange([]);
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const hasActiveFilters = selectedIds.length > 0;
|
|
99
|
-
|
|
100
|
-
return (
|
|
101
|
-
<ScrollView
|
|
102
|
-
horizontal
|
|
103
|
-
showsHorizontalScrollIndicator={false}
|
|
104
|
-
contentContainerStyle={getScrollContentContainerStyle()}
|
|
105
|
-
style={[style]}
|
|
106
|
-
testID={testID}
|
|
107
|
-
>
|
|
108
|
-
<View style={getFilterContainerStyle()}>
|
|
109
|
-
{options.map((option) => {
|
|
110
|
-
const isSelected = selectedIds.includes(option.id);
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<AtomicChip
|
|
114
|
-
key={option.id}
|
|
115
|
-
variant={isSelected ? 'filled' : variant}
|
|
116
|
-
color={color}
|
|
117
|
-
size={size}
|
|
118
|
-
leadingIcon={option.icon}
|
|
119
|
-
selected={isSelected}
|
|
120
|
-
clickable={true}
|
|
121
|
-
onPress={() => handleFilterPress(option.id)}
|
|
122
|
-
testID={`filter-chip-${option.id}`}
|
|
123
|
-
>
|
|
124
|
-
{option.label}
|
|
125
|
-
</AtomicChip>
|
|
126
|
-
);
|
|
127
|
-
})}
|
|
128
|
-
|
|
129
|
-
{/* Clear All Button */}
|
|
130
|
-
{showClearAll && hasActiveFilters && (
|
|
131
|
-
<TouchableOpacity
|
|
132
|
-
onPress={handleClearAll}
|
|
133
|
-
style={[
|
|
134
|
-
getClearAllContainerStyle(),
|
|
135
|
-
{
|
|
136
|
-
backgroundColor: tokens.colors.surfaceVariant,
|
|
137
|
-
borderWidth: 1,
|
|
138
|
-
borderColor: tokens.colors.outline,
|
|
139
|
-
}
|
|
140
|
-
]}
|
|
141
|
-
testID="clear-all-button"
|
|
142
|
-
>
|
|
143
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', gap: tokens.spacing.xs }}>
|
|
144
|
-
<AtomicIcon name="X" size="xs" color="surfaceVariant" />
|
|
145
|
-
<AtomicText type="labelSmall" style={{ color: tokens.colors.textSecondary }}>
|
|
146
|
-
Clear All
|
|
147
|
-
</AtomicText>
|
|
148
|
-
</View>
|
|
149
|
-
</TouchableOpacity>
|
|
150
|
-
)}
|
|
151
|
-
</View>
|
|
152
|
-
</ScrollView>
|
|
153
|
-
);
|
|
154
|
-
};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AtomicFormError - Universal Form Error Component
|
|
3
|
-
*
|
|
4
|
-
* Provides consistent error message display for forms
|
|
5
|
-
* Theme: {{THEME_NAME}} ({{CATEGORY}} category)
|
|
6
|
-
*
|
|
7
|
-
* Atomic Design Level: ATOM
|
|
8
|
-
* Purpose: Display validation error messages
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* - Form field validation errors
|
|
12
|
-
* - Global form error messages
|
|
13
|
-
* - API error display
|
|
14
|
-
* - Input validation feedback
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import React from 'react';
|
|
18
|
-
import { View, StyleSheet, StyleProp, ViewStyle, TextStyle } from 'react-native';
|
|
19
|
-
import { AtomicText } from './AtomicText';
|
|
20
|
-
import { useAppDesignTokens } from '@umituz/react-native-theme';
|
|
21
|
-
import { withAlpha } from '@umituz/react-native-theme';
|
|
22
|
-
|
|
23
|
-
// =============================================================================
|
|
24
|
-
// TYPE DEFINITIONS
|
|
25
|
-
// =============================================================================
|
|
26
|
-
|
|
27
|
-
export interface AtomicFormErrorProps {
|
|
28
|
-
/** Error message to display */
|
|
29
|
-
message: string | null | undefined;
|
|
30
|
-
/** Error display variant */
|
|
31
|
-
variant?: 'global' | 'field';
|
|
32
|
-
/** Custom container style */
|
|
33
|
-
style?: StyleProp<ViewStyle>;
|
|
34
|
-
/** Custom text style */
|
|
35
|
-
textStyle?: StyleProp<TextStyle>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// =============================================================================
|
|
39
|
-
// COMPONENT IMPLEMENTATION
|
|
40
|
-
// =============================================================================
|
|
41
|
-
|
|
42
|
-
export const AtomicFormError: React.FC<AtomicFormErrorProps> = ({
|
|
43
|
-
message,
|
|
44
|
-
variant = 'field',
|
|
45
|
-
style,
|
|
46
|
-
textStyle,
|
|
47
|
-
}) => {
|
|
48
|
-
const tokens = useAppDesignTokens();
|
|
49
|
-
|
|
50
|
-
if (!message) {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (variant === 'global') {
|
|
55
|
-
return (
|
|
56
|
-
<View
|
|
57
|
-
style={[
|
|
58
|
-
{
|
|
59
|
-
padding: tokens.spacing.md,
|
|
60
|
-
borderRadius: tokens.borders.radius.md,
|
|
61
|
-
marginBottom: tokens.spacing.sm,
|
|
62
|
-
backgroundColor: withAlpha(tokens.colors.error, 0.15),
|
|
63
|
-
},
|
|
64
|
-
style,
|
|
65
|
-
]}
|
|
66
|
-
>
|
|
67
|
-
<AtomicText
|
|
68
|
-
type="bodySmall"
|
|
69
|
-
color="error"
|
|
70
|
-
style={StyleSheet.flatten([
|
|
71
|
-
{
|
|
72
|
-
textAlign: 'center',
|
|
73
|
-
fontWeight: tokens.typography.medium,
|
|
74
|
-
},
|
|
75
|
-
textStyle,
|
|
76
|
-
])}
|
|
77
|
-
>
|
|
78
|
-
{message}
|
|
79
|
-
</AtomicText>
|
|
80
|
-
</View>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<AtomicText
|
|
86
|
-
type="bodySmall"
|
|
87
|
-
color="error"
|
|
88
|
-
style={StyleSheet.flatten([
|
|
89
|
-
{
|
|
90
|
-
marginTop: tokens.spacing.xs,
|
|
91
|
-
marginLeft: tokens.spacing.xs,
|
|
92
|
-
},
|
|
93
|
-
textStyle,
|
|
94
|
-
])}
|
|
95
|
-
>
|
|
96
|
-
{message}
|
|
97
|
-
</AtomicText>
|
|
98
|
-
);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// =============================================================================
|
|
102
|
-
// EXPORTS
|
|
103
|
-
// =============================================================================
|
|
104
|
-
|
|
105
|
-
export default AtomicFormError;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AtomicIcon - Atomic Design System Icon Component
|
|
3
|
-
*
|
|
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.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import React from 'react';
|
|
10
|
-
import { Icon } from '@umituz/react-native-icon';
|
|
11
|
-
import type { IconProps, IconSize, IconColor, IconName } from '@umituz/react-native-icon';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* AtomicIcon Component
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```tsx
|
|
18
|
-
* import { AtomicIcon } from '@umituz/react-native-design-system';
|
|
19
|
-
*
|
|
20
|
-
* // Basic usage
|
|
21
|
-
* <AtomicIcon name="Settings" size="md" color="primary" />
|
|
22
|
-
*
|
|
23
|
-
* // Custom size and color
|
|
24
|
-
* <AtomicIcon name="Heart" customSize={32} customColor="#FF0000" />
|
|
25
|
-
*
|
|
26
|
-
* // With background
|
|
27
|
-
* <AtomicIcon name="Info" size="lg" withBackground backgroundColor="#667eea" />
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
export const AtomicIcon: React.FC<IconProps> = (props) => {
|
|
31
|
-
return <Icon {...props} />;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Re-export types with Atomic naming convention
|
|
36
|
-
*/
|
|
37
|
-
export type AtomicIconProps = IconProps;
|
|
38
|
-
export type AtomicIconSize = IconSize;
|
|
39
|
-
export type AtomicIconColor = IconColor;
|
|
40
|
-
export type AtomicIconName = IconName;
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AtomicImage - Universal Image Component
|
|
3
|
-
*
|
|
4
|
-
* Provides consistent image handling across the app with theme integration
|
|
5
|
-
* Theme: {{THEME_NAME}} ({{CATEGORY}} category)
|
|
6
|
-
*
|
|
7
|
-
* Atomic Design Level: ATOM
|
|
8
|
-
* Purpose: Basic image display with consistent styling
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* - Profile pictures
|
|
12
|
-
* - Product images
|
|
13
|
-
* - Icons and illustrations
|
|
14
|
-
* - Background images
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import React from 'react';
|
|
18
|
-
import { Image, ImageProps, StyleSheet, ViewStyle } from 'react-native';
|
|
19
|
-
import { useAppDesignTokens } from '@umituz/react-native-theme';
|
|
20
|
-
|
|
21
|
-
// =============================================================================
|
|
22
|
-
// TYPE DEFINITIONS
|
|
23
|
-
// =============================================================================
|
|
24
|
-
|
|
25
|
-
export interface AtomicImageProps extends Omit<ImageProps, 'style'> {
|
|
26
|
-
/** Image source */
|
|
27
|
-
source: ImageProps['source'];
|
|
28
|
-
/** Size variant */
|
|
29
|
-
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
|
30
|
-
/** Shape variant */
|
|
31
|
-
shape?: 'square' | 'circle' | 'rounded';
|
|
32
|
-
/** Border radius override */
|
|
33
|
-
borderRadius?: number;
|
|
34
|
-
/** Container style override */
|
|
35
|
-
style?: ViewStyle | ViewStyle[];
|
|
36
|
-
/** Image style override */
|
|
37
|
-
imageStyle?: ImageProps['style'];
|
|
38
|
-
/** Background color */
|
|
39
|
-
backgroundColor?: string;
|
|
40
|
-
/** Border color */
|
|
41
|
-
borderColor?: string;
|
|
42
|
-
/** Border width */
|
|
43
|
-
borderWidth?: number;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// =============================================================================
|
|
47
|
-
// SIZE CONFIGURATION
|
|
48
|
-
// =============================================================================
|
|
49
|
-
|
|
50
|
-
const SIZE_CONFIG = {
|
|
51
|
-
xs: 24,
|
|
52
|
-
sm: 32,
|
|
53
|
-
md: 48,
|
|
54
|
-
lg: 64,
|
|
55
|
-
xl: 96,
|
|
56
|
-
xxl: 128,
|
|
57
|
-
} as const;
|
|
58
|
-
|
|
59
|
-
// =============================================================================
|
|
60
|
-
// COMPONENT IMPLEMENTATION
|
|
61
|
-
// =============================================================================
|
|
62
|
-
|
|
63
|
-
export const AtomicImage: React.FC<AtomicImageProps> = ({
|
|
64
|
-
source,
|
|
65
|
-
size = 'md',
|
|
66
|
-
shape = 'rounded',
|
|
67
|
-
borderRadius,
|
|
68
|
-
style,
|
|
69
|
-
imageStyle,
|
|
70
|
-
backgroundColor,
|
|
71
|
-
borderColor,
|
|
72
|
-
borderWidth = 0,
|
|
73
|
-
...props
|
|
74
|
-
}) => {
|
|
75
|
-
const tokens = useAppDesignTokens();
|
|
76
|
-
const styles = getStyles(tokens);
|
|
77
|
-
|
|
78
|
-
const imageSize = SIZE_CONFIG[size as 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'];
|
|
79
|
-
const calculatedBorderRadius = borderRadius ?? getBorderRadius(shape as 'square' | 'circle' | 'rounded', imageSize, tokens);
|
|
80
|
-
|
|
81
|
-
const containerStyle = [
|
|
82
|
-
styles.container,
|
|
83
|
-
{
|
|
84
|
-
width: imageSize,
|
|
85
|
-
height: imageSize,
|
|
86
|
-
borderRadius: calculatedBorderRadius,
|
|
87
|
-
backgroundColor: backgroundColor || tokens.colors.surface,
|
|
88
|
-
borderColor: borderColor || tokens.colors.border,
|
|
89
|
-
borderWidth,
|
|
90
|
-
},
|
|
91
|
-
style,
|
|
92
|
-
];
|
|
93
|
-
|
|
94
|
-
const finalImageStyle = [
|
|
95
|
-
styles.image,
|
|
96
|
-
{
|
|
97
|
-
borderRadius: calculatedBorderRadius,
|
|
98
|
-
},
|
|
99
|
-
imageStyle,
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<Image
|
|
104
|
-
source={source}
|
|
105
|
-
style={finalImageStyle}
|
|
106
|
-
{...props}
|
|
107
|
-
/>
|
|
108
|
-
);
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// =============================================================================
|
|
112
|
-
// HELPER FUNCTIONS
|
|
113
|
-
// =============================================================================
|
|
114
|
-
|
|
115
|
-
const getBorderRadius = (shape: AtomicImageProps['shape'], size: number, tokens: ReturnType<typeof useAppDesignTokens>): number => {
|
|
116
|
-
switch (shape) {
|
|
117
|
-
case 'circle':
|
|
118
|
-
return size / 2;
|
|
119
|
-
case 'square':
|
|
120
|
-
return 0;
|
|
121
|
-
case 'rounded':
|
|
122
|
-
default:
|
|
123
|
-
return tokens.borders.radius.md;
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
// =============================================================================
|
|
128
|
-
// STYLES
|
|
129
|
-
// =============================================================================
|
|
130
|
-
|
|
131
|
-
const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>) =>
|
|
132
|
-
StyleSheet.create({
|
|
133
|
-
container: {
|
|
134
|
-
overflow: 'hidden',
|
|
135
|
-
justifyContent: 'center',
|
|
136
|
-
alignItems: 'center',
|
|
137
|
-
},
|
|
138
|
-
image: {
|
|
139
|
-
width: '100%',
|
|
140
|
-
height: '100%',
|
|
141
|
-
resizeMode: 'cover',
|
|
142
|
-
},
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// =============================================================================
|
|
146
|
-
// EXPORTS
|
|
147
|
-
// =============================================================================
|
|
148
|
-
|
|
149
|
-
export default AtomicImage;
|