@umituz/react-native-design-system 1.5.32 → 1.5.34

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 (67) hide show
  1. package/package.json +4 -1
  2. package/src/presentation/atoms/AtomicDatePicker.tsx +3 -2
  3. package/src/presentation/atoms/AtomicInput.tsx +19 -12
  4. package/src/index.js +0 -100
  5. package/src/presentation/atoms/AtomicAvatar.js +0 -84
  6. package/src/presentation/atoms/AtomicAvatarGroup.js +0 -82
  7. package/src/presentation/atoms/AtomicBadge.js +0 -167
  8. package/src/presentation/atoms/AtomicButton.js +0 -171
  9. package/src/presentation/atoms/AtomicCard.js +0 -69
  10. package/src/presentation/atoms/AtomicChip.js +0 -130
  11. package/src/presentation/atoms/AtomicDatePicker.js +0 -245
  12. package/src/presentation/atoms/AtomicDivider.js +0 -57
  13. package/src/presentation/atoms/AtomicFab.js +0 -67
  14. package/src/presentation/atoms/AtomicFilter.js +0 -103
  15. package/src/presentation/atoms/AtomicFormError.js +0 -63
  16. package/src/presentation/atoms/AtomicIcon.js +0 -29
  17. package/src/presentation/atoms/AtomicImage.js +0 -91
  18. package/src/presentation/atoms/AtomicInput.js +0 -201
  19. package/src/presentation/atoms/AtomicNumberInput.js +0 -124
  20. package/src/presentation/atoms/AtomicPicker.js +0 -298
  21. package/src/presentation/atoms/AtomicProgress.js +0 -79
  22. package/src/presentation/atoms/AtomicSearchBar.js +0 -45
  23. package/src/presentation/atoms/AtomicSort.js +0 -76
  24. package/src/presentation/atoms/AtomicSwitch.js +0 -103
  25. package/src/presentation/atoms/AtomicText.js +0 -22
  26. package/src/presentation/atoms/AtomicTextArea.js +0 -195
  27. package/src/presentation/atoms/AtomicTouchable.js +0 -137
  28. package/src/presentation/atoms/fab/styles/fabStyles.js +0 -62
  29. package/src/presentation/atoms/fab/types/index.js +0 -1
  30. package/src/presentation/atoms/filter/styles/filterStyles.js +0 -28
  31. package/src/presentation/atoms/filter/types/index.js +0 -1
  32. package/src/presentation/atoms/index.js +0 -145
  33. package/src/presentation/atoms/input/hooks/useInputState.js +0 -12
  34. package/src/presentation/atoms/input/styles/inputStyles.js +0 -58
  35. package/src/presentation/atoms/input/types/index.js +0 -1
  36. package/src/presentation/atoms/picker/styles/pickerStyles.js +0 -176
  37. package/src/presentation/atoms/picker/types/index.js +0 -1
  38. package/src/presentation/atoms/touchable/styles/touchableStyles.js +0 -53
  39. package/src/presentation/atoms/touchable/types/index.js +0 -1
  40. package/src/presentation/hooks/useResponsive.js +0 -81
  41. package/src/presentation/molecules/AtomicConfirmationModal.js +0 -153
  42. package/src/presentation/molecules/EmptyState.js +0 -67
  43. package/src/presentation/molecules/FormField.js +0 -75
  44. package/src/presentation/molecules/GridContainer.js +0 -76
  45. package/src/presentation/molecules/IconContainer.js +0 -59
  46. package/src/presentation/molecules/ListItem.js +0 -23
  47. package/src/presentation/molecules/ScreenHeader.js +0 -93
  48. package/src/presentation/molecules/SearchBar.js +0 -46
  49. package/src/presentation/molecules/SectionCard.js +0 -46
  50. package/src/presentation/molecules/SectionContainer.js +0 -63
  51. package/src/presentation/molecules/SectionHeader.js +0 -72
  52. package/src/presentation/molecules/confirmation-modal/styles/confirmationModalStyles.js +0 -114
  53. package/src/presentation/molecules/confirmation-modal/types/index.js +0 -6
  54. package/src/presentation/molecules/index.js +0 -16
  55. package/src/presentation/molecules/listitem/styles/listItemStyles.js +0 -14
  56. package/src/presentation/molecules/listitem/types/index.js +0 -1
  57. package/src/presentation/organisms/AppHeader.js +0 -77
  58. package/src/presentation/organisms/FormContainer.js +0 -126
  59. package/src/presentation/organisms/ScreenLayout.js +0 -68
  60. package/src/presentation/organisms/index.js +0 -13
  61. package/src/presentation/tokens/commonStyles.js +0 -219
  62. package/src/presentation/utils/platformConstants.js +0 -113
  63. package/src/presentation/utils/responsive.js +0 -451
  64. package/src/presentation/utils/variants/compound.js +0 -15
  65. package/src/presentation/utils/variants/core.js +0 -22
  66. package/src/presentation/utils/variants/helpers.js +0 -9
  67. package/src/presentation/utils/variants.js +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "1.5.32",
3
+ "version": "1.5.34",
4
4
  "description": "Universal design system for React Native apps - Domain-Driven Design architecture with Material Design 3 components",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./dist/index.d.ts",
@@ -65,12 +65,14 @@
65
65
  "devDependencies": {
66
66
  "@eslint/js": "^9.0.0",
67
67
  "@expo/vector-icons": ">=14.0.0",
68
+ "@gorhom/bottom-sheet": "^5.0.0",
68
69
  "@react-native-community/datetimepicker": "^8.5.0",
69
70
  "@react-navigation/native": "^6.0.0",
70
71
  "@types/react": "^18.2.45",
71
72
  "@types/react-native": "^0.73.0",
72
73
  "@typescript-eslint/eslint-plugin": "^7.0.0",
73
74
  "@typescript-eslint/parser": "^7.0.0",
75
+ "@umituz/react-native-bottom-sheet": "*",
74
76
  "@umituz/react-native-icon": "^1.0.1",
75
77
  "eslint": "^9.0.0",
76
78
  "eslint-plugin-react": "^7.33.0",
@@ -79,6 +81,7 @@
79
81
  "lucide-react-native": ">=0.468.0",
80
82
  "react": ">=18.2.0 || ^19.0.0",
81
83
  "react-native": ">=0.74.0",
84
+ "react-native-gesture-handler": "^2.16.0",
82
85
  "react-native-reanimated": "~3.10.1",
83
86
  "react-native-safe-area-context": "^5.6.2",
84
87
  "react-native-svg": "^15.0.0",
@@ -49,6 +49,7 @@ import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/dat
49
49
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
50
50
  import { useAppDesignTokens } from '@umituz/react-native-theme';
51
51
  import { AtomicIcon, type AtomicIconColor } from './AtomicIcon';
52
+ // @ts-ignore - Peer dependency, types may not be available during typecheck
52
53
  import { BottomSheetModal, useBottomSheetModal } from '@umituz/react-native-bottom-sheet';
53
54
  import { AtomicButton } from './AtomicButton';
54
55
 
@@ -205,7 +206,7 @@ export const AtomicDatePicker: React.FC<AtomicDatePickerProps> = ({
205
206
  accessibilityState={{ disabled }}
206
207
  >
207
208
  <AtomicIcon
208
- name="calendar"
209
+ name="Calendar"
209
210
  color={getIconColor()}
210
211
  size="md"
211
212
  />
@@ -250,7 +251,7 @@ export const AtomicDatePicker: React.FC<AtomicDatePickerProps> = ({
250
251
  />
251
252
  <View style={styles.buttonContainer}>
252
253
  <AtomicButton
253
- label="Done"
254
+ title="Done"
254
255
  onPress={handleDone}
255
256
  variant="primary"
256
257
  style={styles.doneButton}
@@ -131,7 +131,14 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
131
131
  },
132
132
  };
133
133
 
134
- const config = sizeConfig[size];
134
+ const config = sizeConfig[size] ?? sizeConfig.md;
135
+
136
+ // Ensure config is always defined with safe fallbacks
137
+ const fontSize = config?.fontSize ?? tokens.typography.bodyMedium?.fontSize ?? 16;
138
+ const iconSize = config?.iconSize ?? 20;
139
+ const paddingVertical = config?.paddingVertical ?? tokens.spacing?.sm ?? 8;
140
+ const paddingHorizontal = config?.paddingHorizontal ?? tokens.spacing?.md ?? 12;
141
+ const minHeight = config?.minHeight ?? 48;
135
142
 
136
143
  // Get variant styles
137
144
  const getVariantStyle = (): ViewStyle => {
@@ -192,10 +199,10 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
192
199
  styles.container,
193
200
  getVariantStyle(),
194
201
  {
195
- paddingTop: config.paddingVertical,
196
- paddingBottom: config.paddingVertical,
197
- paddingHorizontal: config.paddingHorizontal,
198
- minHeight: config.minHeight,
202
+ paddingTop: paddingVertical,
203
+ paddingBottom: paddingVertical,
204
+ paddingHorizontal: paddingHorizontal,
205
+ minHeight: minHeight,
199
206
  justifyContent: 'center',
200
207
  opacity: isDisabled ? 0.5 : 1,
201
208
  },
@@ -205,13 +212,13 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
205
212
  const textInputStyle: StyleProp<TextStyle> = [
206
213
  styles.input,
207
214
  {
208
- fontSize: config.fontSize,
209
- lineHeight: config.fontSize * 1.2, // Tighter lineHeight to prevent text clipping
215
+ fontSize: fontSize,
216
+ lineHeight: fontSize * 1.2, // Tighter lineHeight to prevent text clipping
210
217
  color: getTextColor(),
211
218
  paddingVertical: 0, // Remove vertical padding to prevent clipping
212
219
  },
213
- leadingIcon ? { paddingLeft: config.iconSize + 8 } : undefined,
214
- (trailingIcon || showPasswordToggle) ? { paddingRight: config.iconSize + 8 } : undefined,
220
+ leadingIcon ? { paddingLeft: iconSize + 8 } : undefined,
221
+ (trailingIcon || showPasswordToggle) ? { paddingRight: iconSize + 8 } : undefined,
215
222
  inputStyle,
216
223
  ];
217
224
 
@@ -232,7 +239,7 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
232
239
  <View style={styles.leadingIcon}>
233
240
  <AtomicIcon
234
241
  name={leadingIcon}
235
- customSize={config.iconSize}
242
+ customSize={iconSize}
236
243
  customColor={iconColor}
237
244
  />
238
245
  </View>
@@ -268,7 +275,7 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
268
275
  >
269
276
  <AtomicIcon
270
277
  name={isPasswordVisible ? "EyeOff" : "Eye"}
271
- customSize={config.iconSize}
278
+ customSize={iconSize}
272
279
  customColor={iconColor}
273
280
  />
274
281
  </Pressable>
@@ -282,7 +289,7 @@ export const AtomicInput: React.FC<AtomicInputProps> = ({
282
289
  >
283
290
  <AtomicIcon
284
291
  name={trailingIcon}
285
- customSize={config.iconSize}
292
+ customSize={iconSize}
286
293
  customColor={iconColor}
287
294
  />
288
295
  </Pressable>
package/src/index.js DELETED
@@ -1,100 +0,0 @@
1
- /**
2
- * @umituz/react-native-design-system - Public API
3
- *
4
- * Universal UI component library for React Native apps
5
- * Domain-Driven Design (DDD) Architecture
6
- *
7
- * This is the SINGLE SOURCE OF TRUTH for all UI components.
8
- * ALL imports from the design system MUST go through this file.
9
- *
10
- * Architecture:
11
- * - presentation/atoms: Primitive UI components (AtomicButton, AtomicText, etc.)
12
- * - presentation/molecules: Composite components (SearchBar, ListItem, etc.)
13
- * - presentation/organisms: Complex patterns (ScreenLayout, AppHeader, FormContainer)
14
- * - presentation/tokens: Design tokens (colors, typography, spacing, etc.)
15
- * - presentation/utils: Utility functions and helpers
16
- *
17
- * Usage:
18
- * import { AtomicButton, AtomicFilter, AtomicTouchable, SearchBar, STATIC_TOKENS } from '@umituz/react-native-design-system';
19
- */
20
- // =============================================================================
21
- // ATOMS - Primitive UI Components
22
- // =============================================================================
23
- export { AtomicButton, } from './presentation/atoms/AtomicButton';
24
- export { AtomicText, } from './presentation/atoms/AtomicText';
25
- export { AtomicCard, } from './presentation/atoms/AtomicCard';
26
- export { AtomicInput, } from './presentation/atoms/AtomicInput';
27
- export { AtomicNumberInput, } from './presentation/atoms/AtomicNumberInput';
28
- export { AtomicSwitch, } from './presentation/atoms/AtomicSwitch';
29
- export { AtomicIcon, } from './presentation/atoms/AtomicIcon';
30
- export { AtomicFormError, } from './presentation/atoms/AtomicFormError';
31
- export { AtomicDatePicker, } from './presentation/atoms/AtomicDatePicker';
32
- export { AtomicPicker, } from './presentation/atoms/AtomicPicker';
33
- export { AtomicTextArea, } from './presentation/atoms/AtomicTextArea';
34
- export { AtomicBadge, } from './presentation/atoms/AtomicBadge';
35
- export { AtomicProgress, } from './presentation/atoms/AtomicProgress';
36
- export { AtomicDivider, } from './presentation/atoms/AtomicDivider';
37
- export { AtomicFab, getFabVariants, } from './presentation/atoms/AtomicFab';
38
- export { AtomicFilter, getFilterContainerStyle, getClearAllContainerStyle, getScrollContentContainerStyle, } from './presentation/atoms/AtomicFilter';
39
- export { AtomicTouchable, TouchablePresets, getOpacityValue, normalizeHitSlop, } from './presentation/atoms/AtomicTouchable';
40
- export { AtomicSearchBar, } from './presentation/atoms/AtomicSearchBar';
41
- export { AtomicSort, } from './presentation/atoms/AtomicSort';
42
- // =============================================================================
43
- // MOLECULES - Composite Components
44
- // =============================================================================
45
- export { FormField, } from './presentation/molecules/FormField';
46
- export { ListItem, } from './presentation/molecules/ListItem';
47
- export { SearchBar, } from './presentation/molecules/SearchBar';
48
- // SettingItem moved to @domains/settings/presentation/components/SettingItem
49
- // LanguageSwitcher moved to @umituz/react-native-localization
50
- // Import directly: import { SettingItem } from '@domains/settings/presentation/components/SettingItem';
51
- export { SectionCard, } from './presentation/molecules/SectionCard';
52
- export { IconContainer, } from './presentation/molecules/IconContainer';
53
- export { SectionHeader, } from './presentation/molecules/SectionHeader';
54
- export { EmptyState, } from './presentation/molecules/EmptyState';
55
- export { GridContainer, } from './presentation/molecules/GridContainer';
56
- export { SectionContainer, } from './presentation/molecules/SectionContainer';
57
- export { ScreenHeader, } from './presentation/molecules/ScreenHeader';
58
- export { AtomicConfirmationModal, useConfirmationModal, } from './presentation/molecules/AtomicConfirmationModal';
59
- // =============================================================================
60
- // ORGANISMS - Complex Patterns
61
- // =============================================================================
62
- export { ScreenLayout, } from './presentation/organisms/ScreenLayout';
63
- export { AppHeader, } from './presentation/organisms/AppHeader';
64
- export { FormContainer, } from './presentation/organisms/FormContainer';
65
- // Note: FeedbackModal moved to @domains/feedback
66
- // Import from feedback domain: import { FeedbackModal } from '@domains/feedback';
67
- // =============================================================================
68
- // THEME-RELATED EXPORTS - Re-exported from @umituz/react-native-theme
69
- // =============================================================================
70
- // All tokens, colors, and theme utilities come from @umituz/react-native-theme
71
- // Design system does NOT define any tokens - it only uses them from theme package
72
- export {
73
- // Token factory
74
- createDesignTokens, STATIC_DESIGN_TOKENS, BASE_TOKENS, STATIC_TOKENS,
75
- // Color utilities
76
- withAlpha, lightColors, darkColors, getColorPalette, } from '@umituz/react-native-theme';
77
- // Hook for dynamic theme-aware tokens (re-exported from theme package)
78
- export { useAppDesignTokens } from '@umituz/react-native-theme';
79
- export { useCommonStyles, } from './presentation/tokens/commonStyles';
80
- // =============================================================================
81
- // UTILITIES - Helper Functions
82
- // =============================================================================
83
- export { IOS_HIG, ANDROID_MATERIAL, PLATFORM_CONSTANTS, isValidTouchTarget, getMinTouchTarget, } from './presentation/utils/platformConstants';
84
- // =============================================================================
85
- // RESPONSIVE UTILITIES - Centralized Responsive Management
86
- // =============================================================================
87
- export { useResponsive, useResponsiveSizes, useDeviceType, } from './presentation/hooks/useResponsive';
88
- export { getScreenDimensions, isSmallPhone, isTablet, getResponsiveLogoSize, getResponsiveInputHeight, getResponsiveHorizontalPadding, getResponsiveBottomPosition, getResponsiveFABPosition, getResponsiveModalMaxHeight, getResponsiveMinModalHeight, getResponsiveIconContainerSize, getResponsiveGridColumns, getResponsiveMaxWidth, getResponsiveFontSize, isLandscape, getKeyboardBehavior, getDeviceType, getMinTouchTargetSize, getSpacingMultiplier, getOnboardingIconMarginTop, getOnboardingIconMarginBottom, getOnboardingTitleMarginBottom, getOnboardingTextPadding, getOnboardingDescriptionMarginTop, DeviceType, } from './presentation/utils/responsive';
89
- // =============================================================================
90
- // THEME MANAGEMENT - Global Theme Store
91
- // =============================================================================
92
- // Theme management moved to @umituz/react-native-theme
93
- export { useDesignSystemTheme, } from '@umituz/react-native-theme';
94
- // =============================================================================
95
- // ICONS DOMAIN - Universal Icon System
96
- // =============================================================================
97
- // Icon components have been moved to @umituz/react-native-icon package.
98
- // Import directly: import { Icon, IconName, IconSize, IconColor } from '@umituz/react-native-icon';
99
- // Re-export for backward compatibility (deprecated - use @umituz/react-native-icon directly)
100
- export { Icon, } from '@umituz/react-native-icon';
@@ -1,84 +0,0 @@
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
- import React from 'react';
17
- import { View, StyleSheet } from 'react-native';
18
- import { AtomicImage } from './AtomicImage';
19
- import { AtomicText } from './AtomicText';
20
- import { useAppDesignTokens } from '@umituz/react-native-theme';
21
- // =============================================================================
22
- // COMPONENT IMPLEMENTATION
23
- // =============================================================================
24
- export const AtomicAvatar = ({ source, name, size = 'md', customSize, backgroundColor, textColor, borderRadius, borderWidth = 0, borderColor, style, imageStyle, testID, }) => {
25
- const tokens = useAppDesignTokens();
26
- const avatarSize = customSize || tokens.avatarSizes[size];
27
- const avatarRadius = borderRadius ?? avatarSize / 2;
28
- // Generate initials from name
29
- const getInitials = (name) => {
30
- return name
31
- .split(' ')
32
- .map(word => word.charAt(0))
33
- .join('')
34
- .toUpperCase()
35
- .slice(0, 2);
36
- };
37
- // Default colors
38
- const defaultBackgroundColor = backgroundColor || tokens.colors.primary;
39
- const defaultTextColor = textColor || tokens.colors.onPrimary;
40
- const defaultBorderColor = borderColor || tokens.colors.border;
41
- const avatarStyle = {
42
- width: avatarSize,
43
- height: avatarSize,
44
- borderRadius: avatarRadius,
45
- backgroundColor: defaultBackgroundColor,
46
- borderWidth,
47
- borderColor: defaultBorderColor,
48
- alignItems: 'center',
49
- justifyContent: 'center',
50
- overflow: 'hidden',
51
- };
52
- const imageStyleFinal = {
53
- width: avatarSize,
54
- height: avatarSize,
55
- borderRadius: avatarRadius,
56
- };
57
- // Font size based on avatar size
58
- const getFontSize = (size) => {
59
- if (size <= 32)
60
- return 12;
61
- if (size <= 48)
62
- return 16;
63
- if (size <= 64)
64
- return 20;
65
- return 24;
66
- };
67
- return (<View style={[avatarStyle, style]} testID={testID}>
68
- {source ? (<AtomicImage source={source} style={StyleSheet.flatten([imageStyleFinal, imageStyle])} resizeMode="cover"/>) : name ? (<AtomicText type="labelLarge" color={defaultTextColor} style={{
69
- fontSize: getFontSize(avatarSize),
70
- fontWeight: tokens.typography.semibold,
71
- }}>
72
- {getInitials(name)}
73
- </AtomicText>) : (<AtomicText type="labelLarge" color={defaultTextColor} style={{
74
- fontSize: getFontSize(avatarSize),
75
- fontWeight: tokens.typography.semibold,
76
- }}>
77
- ?
78
- </AtomicText>)}
79
- </View>);
80
- };
81
- // =============================================================================
82
- // EXPORTS
83
- // =============================================================================
84
- export default AtomicAvatar;
@@ -1,82 +0,0 @@
1
- /**
2
- * AtomicAvatarGroup - Universal Avatar Group Component
3
- *
4
- * Displays multiple avatars in a group with overlap and overflow handling
5
- * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
- *
7
- * Atomic Design Level: ATOM
8
- * Purpose: Multiple avatar display with group behavior
9
- *
10
- * Usage:
11
- * - Team member avatars
12
- * - Group chat participants
13
- * - Project collaborators
14
- * - Event attendees
15
- * - Social connections
16
- */
17
- import React from 'react';
18
- import { View } from 'react-native';
19
- import { AtomicAvatar } from './AtomicAvatar';
20
- import { AtomicText } from './AtomicText';
21
- import { useAppDesignTokens } from '@umituz/react-native-theme';
22
- // =============================================================================
23
- // COMPONENT IMPLEMENTATION
24
- // =============================================================================
25
- export const AtomicAvatarGroup = ({ avatars, maxVisible = 3, size = 'md', customSize, spacing = -8, showOverflow = true, overflowBackgroundColor, overflowTextColor, borderWidth = 2, borderColor, style, testID, }) => {
26
- const tokens = useAppDesignTokens();
27
- // Calculate visible avatars and overflow count
28
- const visibleAvatars = avatars.slice(0, maxVisible);
29
- const overflowCount = avatars.length - maxVisible;
30
- // Size mapping for overflow text
31
- const sizeMap = {
32
- xs: 10,
33
- sm: 12,
34
- md: 14,
35
- lg: 16,
36
- xl: 18,
37
- xxl: 20,
38
- };
39
- const textSize = sizeMap[size];
40
- // Default colors for overflow
41
- const defaultOverflowBackground = overflowBackgroundColor || tokens.colors.surfaceVariant;
42
- const defaultOverflowText = overflowTextColor || tokens.colors.textPrimary;
43
- const containerStyle = {
44
- flexDirection: 'row',
45
- alignItems: 'center',
46
- };
47
- const avatarStyle = {
48
- marginLeft: spacing,
49
- borderWidth,
50
- borderColor: borderColor || tokens.colors.surface,
51
- };
52
- return (<View style={[containerStyle, style]} testID={testID}>
53
- {visibleAvatars.map((avatar, index) => (<AtomicAvatar key={avatar.id} source={avatar.source} name={avatar.name} size={size} customSize={customSize} backgroundColor={avatar.backgroundColor} textColor={avatar.textColor} borderWidth={borderWidth} borderColor={borderColor} style={[
54
- avatarStyle,
55
- ...(index === 0 ? [{ marginLeft: 0 }] : []), // First avatar has no left margin
56
- ]}/>))}
57
- {showOverflow && overflowCount > 0 && (<View style={[
58
- {
59
- alignItems: 'center',
60
- justifyContent: 'center',
61
- width: customSize || 40,
62
- height: customSize || 40,
63
- borderRadius: (customSize || 40) / 2,
64
- backgroundColor: defaultOverflowBackground,
65
- borderWidth,
66
- borderColor: borderColor || tokens.colors.surface,
67
- marginLeft: spacing,
68
- },
69
- ]}>
70
- <AtomicText type="labelMedium" color={defaultOverflowText} style={{
71
- fontWeight: tokens.typography.semibold,
72
- fontSize: textSize,
73
- }}>
74
- +{overflowCount}
75
- </AtomicText>
76
- </View>)}
77
- </View>);
78
- };
79
- // =============================================================================
80
- // EXPORTS
81
- // =============================================================================
82
- export default AtomicAvatarGroup;
@@ -1,167 +0,0 @@
1
- /**
2
- * AtomicBadge - Universal Badge Component
3
- *
4
- * Provides consistent badge/notification count display
5
- * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
- *
7
- * Atomic Design Level: ATOM
8
- * Purpose: Display counts, notifications, status indicators
9
- *
10
- * Usage:
11
- * - Notification counts
12
- * - Cart item counts
13
- * - Status indicators
14
- * - Achievement badges
15
- */
16
- import React from 'react';
17
- import { View, StyleSheet } from 'react-native';
18
- import { AtomicText } from './AtomicText';
19
- import { useAppDesignTokens } from '@umituz/react-native-theme';
20
- // =============================================================================
21
- // SIZE CONFIGURATION
22
- // =============================================================================
23
- const getSizeConfig = (tokens) => ({
24
- xs: {
25
- minHeight: tokens.spacing.sm,
26
- paddingHorizontal: tokens.spacing.xs,
27
- fontSize: tokens.typography.labelSmall.fontSize,
28
- borderRadius: tokens.borders.radius.sm,
29
- },
30
- sm: {
31
- minHeight: tokens.spacing.md,
32
- paddingHorizontal: tokens.spacing.sm,
33
- fontSize: tokens.typography.bodySmall.fontSize,
34
- borderRadius: tokens.borders.radius.md,
35
- },
36
- md: {
37
- minHeight: tokens.spacing.lg,
38
- paddingHorizontal: tokens.spacing.sm,
39
- fontSize: tokens.typography.bodyMedium.fontSize,
40
- borderRadius: tokens.borders.radius.md,
41
- },
42
- lg: {
43
- minHeight: tokens.spacing.xl,
44
- paddingHorizontal: tokens.spacing.md,
45
- fontSize: tokens.typography.bodyLarge.fontSize,
46
- borderRadius: tokens.borders.radius.lg,
47
- },
48
- });
49
- // =============================================================================
50
- // COMPONENT IMPLEMENTATION
51
- // =============================================================================
52
- export const AtomicBadge = ({ children, size = 'md', variant = 'primary', shape = 'circle', max, showZero = false, style, textStyle, minWidth, maxWidth, }) => {
53
- const tokens = useAppDesignTokens();
54
- const styles = getStyles(tokens);
55
- const sizeConfig = getSizeConfig(tokens)[size];
56
- const colors = getVariantColors(tokens, variant);
57
- const borderRadius = getBorderRadius(shape, sizeConfig.borderRadius, tokens);
58
- // Handle max value display
59
- const displayValue = React.useMemo(() => {
60
- if (typeof children === 'number') {
61
- if (max && children > max) {
62
- return `${max}+`;
63
- }
64
- return children.toString();
65
- }
66
- return children;
67
- }, [children, max]);
68
- // Don't render if count is 0 and showZero is false
69
- if (typeof children === 'number' && children === 0 && !showZero) {
70
- return null;
71
- }
72
- const containerStyle = [
73
- styles.container,
74
- {
75
- minHeight: sizeConfig.minHeight,
76
- paddingHorizontal: sizeConfig.paddingHorizontal,
77
- borderRadius,
78
- backgroundColor: colors.background,
79
- minWidth: minWidth || sizeConfig.minHeight,
80
- maxWidth,
81
- },
82
- style,
83
- ];
84
- const textStyleFinal = StyleSheet.flatten([
85
- styles.text,
86
- {
87
- fontSize: sizeConfig.fontSize,
88
- },
89
- textStyle,
90
- ]);
91
- return (<View style={containerStyle}>
92
- <AtomicText type="bodySmall" color={colors.text} style={textStyleFinal} numberOfLines={1}>
93
- {displayValue}
94
- </AtomicText>
95
- </View>);
96
- };
97
- // =============================================================================
98
- // HELPER FUNCTIONS
99
- // =============================================================================
100
- const getVariantColors = (tokens, variant) => {
101
- switch (variant) {
102
- case 'primary':
103
- return {
104
- background: tokens.colors.primary,
105
- text: tokens.colors.textInverse,
106
- };
107
- case 'secondary':
108
- return {
109
- background: tokens.colors.secondary,
110
- text: tokens.colors.textInverse,
111
- };
112
- case 'success':
113
- return {
114
- background: tokens.colors.success,
115
- text: tokens.colors.textInverse,
116
- };
117
- case 'warning':
118
- return {
119
- background: tokens.colors.warning,
120
- text: tokens.colors.textInverse,
121
- };
122
- case 'error':
123
- return {
124
- background: tokens.colors.error,
125
- text: tokens.colors.textInverse,
126
- };
127
- case 'info':
128
- return {
129
- background: tokens.colors.info,
130
- text: tokens.colors.textInverse,
131
- };
132
- default:
133
- return {
134
- background: tokens.colors.primary,
135
- text: tokens.colors.textInverse,
136
- };
137
- }
138
- };
139
- const getBorderRadius = (shape, defaultRadius, tokens) => {
140
- switch (shape) {
141
- case 'circle':
142
- return tokens.borders.radius.full; // Very large radius for circle
143
- case 'square':
144
- return tokens.borders.radius.sm;
145
- case 'rounded':
146
- default:
147
- return defaultRadius;
148
- }
149
- };
150
- // =============================================================================
151
- // STYLES
152
- // =============================================================================
153
- const getStyles = (tokens) => StyleSheet.create({
154
- container: {
155
- justifyContent: 'center',
156
- alignItems: 'center',
157
- alignSelf: 'flex-start',
158
- },
159
- text: {
160
- fontWeight: tokens.typography.semibold,
161
- textAlign: 'center',
162
- },
163
- });
164
- // =============================================================================
165
- // EXPORTS
166
- // =============================================================================
167
- export default AtomicBadge;