@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.
Files changed (62) hide show
  1. package/README.md +2 -2
  2. package/package.json +7 -5
  3. package/src/index.ts +29 -221
  4. package/src/presentation/organisms/AppHeader.tsx +3 -5
  5. package/src/presentation/tokens/commonStyles.ts +1 -1
  6. package/src/presentation/atoms/AtomicAvatar.tsx +0 -157
  7. package/src/presentation/atoms/AtomicAvatarGroup.tsx +0 -169
  8. package/src/presentation/atoms/AtomicBadge.tsx +0 -232
  9. package/src/presentation/atoms/AtomicButton.tsx +0 -236
  10. package/src/presentation/atoms/AtomicCard.tsx +0 -107
  11. package/src/presentation/atoms/AtomicChip.tsx +0 -223
  12. package/src/presentation/atoms/AtomicDatePicker.tsx +0 -347
  13. package/src/presentation/atoms/AtomicDivider.tsx +0 -114
  14. package/src/presentation/atoms/AtomicFab.tsx +0 -98
  15. package/src/presentation/atoms/AtomicFilter.tsx +0 -154
  16. package/src/presentation/atoms/AtomicFormError.tsx +0 -105
  17. package/src/presentation/atoms/AtomicIcon.tsx +0 -40
  18. package/src/presentation/atoms/AtomicImage.tsx +0 -149
  19. package/src/presentation/atoms/AtomicInput.tsx +0 -363
  20. package/src/presentation/atoms/AtomicNumberInput.tsx +0 -182
  21. package/src/presentation/atoms/AtomicPicker.tsx +0 -458
  22. package/src/presentation/atoms/AtomicProgress.tsx +0 -139
  23. package/src/presentation/atoms/AtomicSearchBar.tsx +0 -114
  24. package/src/presentation/atoms/AtomicSort.tsx +0 -145
  25. package/src/presentation/atoms/AtomicSwitch.tsx +0 -166
  26. package/src/presentation/atoms/AtomicText.tsx +0 -55
  27. package/src/presentation/atoms/AtomicTextArea.tsx +0 -313
  28. package/src/presentation/atoms/AtomicTouchable.tsx +0 -209
  29. package/src/presentation/atoms/fab/styles/fabStyles.ts +0 -69
  30. package/src/presentation/atoms/fab/types/index.ts +0 -82
  31. package/src/presentation/atoms/filter/styles/filterStyles.ts +0 -32
  32. package/src/presentation/atoms/filter/types/index.ts +0 -89
  33. package/src/presentation/atoms/index.ts +0 -366
  34. package/src/presentation/atoms/input/hooks/useInputState.ts +0 -15
  35. package/src/presentation/atoms/input/styles/inputStyles.ts +0 -66
  36. package/src/presentation/atoms/input/types/index.ts +0 -25
  37. package/src/presentation/atoms/picker/styles/pickerStyles.ts +0 -207
  38. package/src/presentation/atoms/picker/types/index.ts +0 -40
  39. package/src/presentation/atoms/touchable/styles/touchableStyles.ts +0 -62
  40. package/src/presentation/atoms/touchable/types/index.ts +0 -155
  41. package/src/presentation/hooks/useResponsive.ts +0 -180
  42. package/src/presentation/molecules/AtomicConfirmationModal.tsx +0 -243
  43. package/src/presentation/molecules/EmptyState.tsx +0 -130
  44. package/src/presentation/molecules/FormField.tsx +0 -128
  45. package/src/presentation/molecules/GridContainer.tsx +0 -124
  46. package/src/presentation/molecules/IconContainer.tsx +0 -94
  47. package/src/presentation/molecules/ListItem.tsx +0 -36
  48. package/src/presentation/molecules/ScreenHeader.tsx +0 -140
  49. package/src/presentation/molecules/SearchBar.tsx +0 -85
  50. package/src/presentation/molecules/SectionCard.tsx +0 -74
  51. package/src/presentation/molecules/SectionContainer.tsx +0 -106
  52. package/src/presentation/molecules/SectionHeader.tsx +0 -125
  53. package/src/presentation/molecules/confirmation-modal/styles/confirmationModalStyles.ts +0 -133
  54. package/src/presentation/molecules/confirmation-modal/types/index.ts +0 -105
  55. package/src/presentation/molecules/index.ts +0 -41
  56. package/src/presentation/molecules/listitem/styles/listItemStyles.ts +0 -19
  57. package/src/presentation/molecules/listitem/types/index.ts +0 -17
  58. package/src/presentation/organisms/FormContainer.tsx +0 -180
  59. package/src/presentation/organisms/ScreenLayout.tsx +0 -171
  60. package/src/presentation/organisms/index.ts +0 -25
  61. package/src/presentation/utils/platformConstants.ts +0 -124
  62. 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;