@umituz/react-native-design-system 1.5.33 → 1.5.35

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 +7 -3
  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
@@ -1,176 +0,0 @@
1
- import { IOS_HIG, getMinTouchTarget } from '../../../utils/platformConstants';
2
- /**
3
- * Picker container styles with iOS HIG compliance
4
- *
5
- * All picker sizes meet Apple's minimum touch target requirement of 44pt.
6
- * @see https://developer.apple.com/design/human-interface-guidelines/layout
7
- */
8
- export const getPickerContainerStyles = (tokens) => ({
9
- base: {
10
- flexDirection: 'row',
11
- alignItems: 'center',
12
- justifyContent: 'space-between',
13
- borderWidth: tokens.borders.width.thin,
14
- borderColor: tokens.colors.border,
15
- backgroundColor: tokens.colors.surface,
16
- },
17
- size: {
18
- // ✅ iOS HIG Compliant: All sizes >= 44pt minimum touch target
19
- sm: {
20
- height: IOS_HIG.MIN_TOUCH_TARGET, // 44pt - iOS minimum
21
- paddingHorizontal: tokens.spacing.sm,
22
- borderRadius: tokens.borders.radius.sm,
23
- },
24
- md: {
25
- height: getMinTouchTarget('input'), // 48pt - Recommended
26
- paddingHorizontal: tokens.spacing.md,
27
- borderRadius: tokens.borders.radius.md,
28
- },
29
- lg: {
30
- height: 56, // 56pt - Large touch target
31
- paddingHorizontal: tokens.spacing.lg,
32
- borderRadius: tokens.borders.radius.md,
33
- },
34
- },
35
- state: {
36
- error: {
37
- borderColor: tokens.colors.error,
38
- borderWidth: tokens.borders.width.medium,
39
- },
40
- disabled: {
41
- backgroundColor: tokens.colors.surfaceDisabled,
42
- opacity: 0.6,
43
- },
44
- },
45
- });
46
- export const getPickerLabelStyles = (tokens) => ({
47
- base: {
48
- marginBottom: tokens.spacing.xs,
49
- color: tokens.colors.textPrimary,
50
- fontWeight: '600',
51
- },
52
- size: {
53
- sm: tokens.typography.bodySmall,
54
- md: tokens.typography.bodyMedium,
55
- lg: tokens.typography.bodyLarge,
56
- },
57
- });
58
- export const getPickerPlaceholderStyles = (tokens) => ({
59
- base: {
60
- color: tokens.colors.textSecondary,
61
- },
62
- size: {
63
- sm: tokens.typography.bodySmall,
64
- md: tokens.typography.bodyMedium,
65
- lg: tokens.typography.bodyLarge,
66
- },
67
- });
68
- export const getPickerValueStyles = (tokens) => ({
69
- base: {
70
- flex: 1,
71
- color: tokens.colors.textPrimary,
72
- },
73
- size: {
74
- sm: tokens.typography.bodySmall,
75
- md: tokens.typography.bodyMedium,
76
- lg: tokens.typography.bodyLarge,
77
- },
78
- });
79
- export const getPickerErrorStyles = (tokens) => ({
80
- marginTop: tokens.spacing.xs,
81
- color: tokens.colors.error,
82
- ...tokens.typography.bodySmall,
83
- });
84
- export const getModalOverlayStyles = (tokens) => ({
85
- flex: 1,
86
- backgroundColor: tokens.colors.overlayMedium,
87
- justifyContent: 'flex-end',
88
- });
89
- export const getModalContainerStyles = (tokens, maxHeight) => ({
90
- backgroundColor: tokens.colors.backgroundPrimary,
91
- borderTopLeftRadius: tokens.borders.radius.lg,
92
- borderTopRightRadius: tokens.borders.radius.lg,
93
- maxHeight: maxHeight,
94
- paddingBottom: tokens.spacing.lg,
95
- });
96
- export const getModalHeaderStyles = (tokens) => ({
97
- flexDirection: 'row',
98
- alignItems: 'center',
99
- justifyContent: 'space-between',
100
- paddingHorizontal: tokens.spacing.lg,
101
- paddingVertical: tokens.spacing.md,
102
- borderBottomWidth: tokens.borders.width.thin,
103
- borderBottomColor: tokens.colors.border,
104
- });
105
- export const getModalTitleStyles = (tokens) => ({
106
- ...tokens.typography.titleLarge,
107
- color: tokens.colors.textPrimary,
108
- fontWeight: '600',
109
- });
110
- export const getSearchContainerStyles = (tokens) => ({
111
- flexDirection: 'row',
112
- alignItems: 'center',
113
- backgroundColor: tokens.colors.surfaceVariant,
114
- paddingHorizontal: tokens.spacing.md,
115
- paddingVertical: tokens.spacing.sm,
116
- marginHorizontal: tokens.spacing.lg,
117
- marginTop: tokens.spacing.md,
118
- borderRadius: tokens.borders.radius.md,
119
- });
120
- export const getSearchInputStyles = (tokens) => ({
121
- flex: 1,
122
- marginLeft: tokens.spacing.sm,
123
- ...tokens.typography.bodyMedium,
124
- color: tokens.colors.textPrimary,
125
- });
126
- export const getOptionContainerStyles = (tokens, isSelected, isDisabled) => ({
127
- flexDirection: 'row',
128
- alignItems: 'center',
129
- paddingHorizontal: tokens.spacing.lg,
130
- paddingVertical: tokens.spacing.md,
131
- backgroundColor: isSelected ? tokens.colors.primaryContainer : 'transparent',
132
- opacity: isDisabled ? 0.5 : 1,
133
- });
134
- export const getOptionTextStyles = (tokens, isSelected) => ({
135
- flex: 1,
136
- marginLeft: tokens.spacing.sm,
137
- ...tokens.typography.bodyLarge,
138
- color: isSelected ? tokens.colors.primary : tokens.colors.textPrimary,
139
- fontWeight: isSelected ? '600' : '400',
140
- });
141
- export const getOptionDescriptionStyles = (tokens) => ({
142
- ...tokens.typography.bodySmall,
143
- color: tokens.colors.textSecondary,
144
- marginLeft: tokens.spacing.sm,
145
- marginTop: tokens.spacing.xs,
146
- });
147
- export const getEmptyStateStyles = (tokens) => ({
148
- alignItems: 'center',
149
- justifyContent: 'center',
150
- paddingVertical: tokens.spacing.xxl,
151
- });
152
- export const getEmptyStateTextStyles = (tokens) => ({
153
- ...tokens.typography.bodyLarge,
154
- color: tokens.colors.textSecondary,
155
- textAlign: 'center',
156
- marginTop: tokens.spacing.md,
157
- });
158
- export const getChipContainerStyles = (tokens) => ({
159
- flexDirection: 'row',
160
- flexWrap: 'wrap',
161
- gap: tokens.spacing.xs,
162
- marginTop: tokens.spacing.xs,
163
- });
164
- export const getChipStyles = (tokens) => ({
165
- flexDirection: 'row',
166
- alignItems: 'center',
167
- backgroundColor: tokens.colors.primaryContainer,
168
- paddingHorizontal: tokens.spacing.sm,
169
- paddingVertical: tokens.spacing.xs,
170
- borderRadius: tokens.borders.radius.sm,
171
- });
172
- export const getChipTextStyles = (tokens) => ({
173
- ...tokens.typography.bodySmall,
174
- color: tokens.colors.primary,
175
- marginRight: tokens.spacing.xs,
176
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,53 +0,0 @@
1
- /**
2
- * Get opacity value based on feedback strength
3
- */
4
- export const getOpacityValue = (strength) => {
5
- switch (strength) {
6
- case 'subtle':
7
- return 0.8;
8
- case 'normal':
9
- return 0.6;
10
- case 'strong':
11
- return 0.4;
12
- default:
13
- return 0.6;
14
- }
15
- };
16
- /**
17
- * Get base touchable container style
18
- * Ensures minimum touch target size (iOS HIG: 48x48)
19
- */
20
- export const getTouchableContainerStyle = () => ({
21
- minWidth: 48,
22
- minHeight: 48,
23
- justifyContent: 'center',
24
- alignItems: 'center',
25
- });
26
- /**
27
- * Get disabled touchable style
28
- */
29
- export const getDisabledStyle = () => ({
30
- opacity: 0.5,
31
- });
32
- /**
33
- * Convert number to HitSlop object
34
- * If hitSlop is a number, apply it to all sides
35
- */
36
- export const normalizeHitSlop = (hitSlop) => {
37
- if (hitSlop === undefined)
38
- return undefined;
39
- if (typeof hitSlop === 'number') {
40
- return {
41
- top: hitSlop,
42
- bottom: hitSlop,
43
- left: hitSlop,
44
- right: hitSlop,
45
- };
46
- }
47
- return {
48
- top: hitSlop.top || 0,
49
- bottom: hitSlop.bottom || 0,
50
- left: hitSlop.left || 0,
51
- right: hitSlop.right || 0,
52
- };
53
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,81 +0,0 @@
1
- /**
2
- * useResponsive Hook
3
- *
4
- * React Hook for accessing responsive utilities with real-time dimension updates
5
- * and safe area insets integration.
6
- *
7
- * Usage:
8
- * ```tsx
9
- * const { logoSize, inputHeight, fabPosition, isSmallDevice } = useResponsive();
10
- * ```
11
- */
12
- import { useWindowDimensions } from 'react-native';
13
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
14
- import { getResponsiveLogoSize, getResponsiveInputHeight, getResponsiveHorizontalPadding, getResponsiveBottomPosition, getResponsiveFABPosition, getResponsiveModalMaxHeight, getResponsiveMinModalHeight, getResponsiveIconContainerSize, getResponsiveGridColumns, getResponsiveMaxWidth, getResponsiveFontSize, isSmallPhone, isTablet, isLandscape, getDeviceType, getMinTouchTargetSize, getSpacingMultiplier, getOnboardingIconMarginTop, getOnboardingIconMarginBottom, getOnboardingTitleMarginBottom, getOnboardingTextPadding, getOnboardingDescriptionMarginTop, getOnboardingIconSize, getFormBottomPadding, getInputIconSize, getFormContentWidth, getFormElementSpacing, } from '../utils/responsive';
15
- /**
16
- * Hook for responsive design utilities
17
- * Automatically updates when screen dimensions or orientation changes
18
- */
19
- export const useResponsive = () => {
20
- const { width, height } = useWindowDimensions();
21
- const insets = useSafeAreaInsets();
22
- return {
23
- // Device info
24
- width,
25
- height,
26
- isSmallDevice: isSmallPhone(),
27
- isTabletDevice: isTablet(),
28
- isLandscapeMode: isLandscape(),
29
- deviceType: getDeviceType(),
30
- // Safe area insets
31
- insets,
32
- // Responsive sizes (with default values)
33
- logoSize: getResponsiveLogoSize(),
34
- inputHeight: getResponsiveInputHeight(),
35
- iconContainerSize: getResponsiveIconContainerSize(),
36
- maxContentWidth: getResponsiveMaxWidth(),
37
- minTouchTarget: getMinTouchTargetSize(),
38
- // Responsive positioning
39
- horizontalPadding: getResponsiveHorizontalPadding(16, insets),
40
- bottomPosition: getResponsiveBottomPosition(32, insets),
41
- fabPosition: getResponsiveFABPosition(insets),
42
- // Responsive layout
43
- modalMaxHeight: getResponsiveModalMaxHeight(),
44
- modalMinHeight: getResponsiveMinModalHeight(),
45
- gridColumns: getResponsiveGridColumns(),
46
- spacingMultiplier: getSpacingMultiplier(),
47
- // Onboarding-specific spacing (pre-calculated, no component calculations)
48
- onboardingIconMarginTop: getOnboardingIconMarginTop(),
49
- onboardingIconMarginBottom: getOnboardingIconMarginBottom(),
50
- onboardingIconSize: getOnboardingIconSize(),
51
- onboardingTitleMarginBottom: getOnboardingTitleMarginBottom(),
52
- onboardingTextPadding: getOnboardingTextPadding(),
53
- onboardingDescriptionMarginTop: getOnboardingDescriptionMarginTop(),
54
- // Form-specific spacing (pre-calculated, universal)
55
- formBottomPadding: getFormBottomPadding(insets.bottom),
56
- inputIconSize: getInputIconSize(),
57
- formContentWidth: getFormContentWidth(),
58
- formElementSpacing: getFormElementSpacing(),
59
- // Utility functions (allow custom base values)
60
- getLogoSize: (baseSize) => getResponsiveLogoSize(baseSize),
61
- getInputHeight: (baseHeight) => getResponsiveInputHeight(baseHeight),
62
- getIconSize: (baseSize) => getResponsiveIconContainerSize(baseSize),
63
- getMaxWidth: (baseWidth) => getResponsiveMaxWidth(baseWidth),
64
- getFontSize: (baseFontSize) => getResponsiveFontSize(baseFontSize),
65
- getGridCols: (mobile, tablet) => getResponsiveGridColumns(mobile, tablet),
66
- };
67
- };
68
- /**
69
- * Shorthand hook for just responsive sizes
70
- */
71
- export const useResponsiveSizes = () => {
72
- const { logoSize, inputHeight, iconContainerSize, maxContentWidth } = useResponsive();
73
- return { logoSize, inputHeight, iconContainerSize, maxContentWidth };
74
- };
75
- /**
76
- * Shorthand hook for just device type checks
77
- */
78
- export const useDeviceType = () => {
79
- const { isSmallDevice, isTabletDevice, deviceType } = useResponsive();
80
- return { isSmallDevice, isTabletDevice, deviceType };
81
- };
@@ -1,153 +0,0 @@
1
- /**
2
- * AtomicConfirmationModal - Universal Confirmation Dialog
3
- *
4
- * A reusable confirmation modal for destructive and important actions.
5
- * Follows Material Design 3 dialog patterns and accessibility guidelines.
6
- *
7
- * Features:
8
- * - Multiple variants (default, destructive, warning, success)
9
- * - Configurable text and icons
10
- * - Backdrop dismissal
11
- * - Full keyboard and screen reader support
12
- * - Theme-aware styling
13
- *
14
- * @example
15
- * ```tsx
16
- * // Destructive confirmation (delete)
17
- * <AtomicConfirmationModal
18
- * visible={showDeleteModal}
19
- * variant="destructive"
20
- * title="Delete Item?"
21
- * message="This action cannot be undone. All data will be permanently deleted."
22
- * confirmText="Delete"
23
- * cancelText="Cancel"
24
- * onConfirm={handleDelete}
25
- * onCancel={() => setShowDeleteModal(false)}
26
- * />
27
- *
28
- * // Generic confirmation
29
- * <AtomicConfirmationModal
30
- * visible={showConfirmModal}
31
- * variant="default"
32
- * title="Confirm Action"
33
- * message="Are you sure you want to proceed?"
34
- * onConfirm={handleConfirm}
35
- * onCancel={() => setShowConfirmModal(false)}
36
- * />
37
- * ```
38
- */
39
- import React from 'react';
40
- import { View, Modal, TouchableOpacity } from 'react-native';
41
- import { useAppDesignTokens } from '@umituz/react-native-theme';
42
- import { AtomicText } from '../atoms/AtomicText';
43
- import { AtomicButton } from '../atoms/AtomicButton';
44
- import { AtomicIcon } from '../atoms/AtomicIcon';
45
- import { getVariantConfig, getModalOverlayStyle, getBackdropStyle, getModalContainerStyle, getIconContainerStyle, getTitleContainerStyle, getMessageContainerStyle, getButtonContainerStyle, getButtonStyle, } from './confirmation-modal/styles/confirmationModalStyles';
46
- export const AtomicConfirmationModal = ({ visible, title, message, variant = 'default', confirmText, cancelText, icon, onConfirm, onCancel, showBackdrop = true, backdropDismissible = true, style, testID = 'atomic-confirmation-modal', }) => {
47
- const tokens = useAppDesignTokens();
48
- // Get variant-specific configuration (icon and color only)
49
- const variantConfig = getVariantConfig(variant, tokens);
50
- // Determine final icon
51
- const finalIcon = icon || variantConfig.icon;
52
- // Handle backdrop press
53
- const handleBackdropPress = () => {
54
- if (backdropDismissible) {
55
- onCancel();
56
- }
57
- };
58
- return (<Modal visible={visible} transparent animationType="fade" onRequestClose={onCancel} statusBarTranslucent testID={testID}>
59
- <View style={getModalOverlayStyle(tokens)}>
60
- {/* Backdrop - Tap to dismiss if enabled */}
61
- {showBackdrop && (<TouchableOpacity style={getBackdropStyle()} activeOpacity={1} onPress={handleBackdropPress} testID={`${testID}-backdrop`}/>)}
62
-
63
- {/* Modal Container */}
64
- <View style={[getModalContainerStyle(tokens), style]}>
65
- {/* Icon */}
66
- <View style={getIconContainerStyle(tokens)}>
67
- <AtomicIcon name={finalIcon} size="xl" color={variantConfig.iconColor} testID={`${testID}-icon`}/>
68
- </View>
69
-
70
- {/* Title */}
71
- <View style={getTitleContainerStyle(tokens)}>
72
- <AtomicText type="titleLarge" style={{
73
- color: tokens.colors.textPrimary,
74
- textAlign: 'center',
75
- fontWeight: tokens.typography.bold,
76
- }} testID={`${testID}-title`}>
77
- {title}
78
- </AtomicText>
79
- </View>
80
-
81
- {/* Message */}
82
- <View style={getMessageContainerStyle(tokens)}>
83
- <AtomicText type="bodyMedium" style={{
84
- color: tokens.colors.textSecondary,
85
- textAlign: 'center',
86
- lineHeight: tokens.typography.bodyMedium.lineHeight,
87
- }} testID={`${testID}-message`}>
88
- {message}
89
- </AtomicText>
90
- </View>
91
-
92
- {/* Action Buttons */}
93
- <View style={getButtonContainerStyle(tokens)}>
94
- {/* Cancel Button */}
95
- <AtomicButton variant="outline" size="md" onPress={onCancel} style={getButtonStyle()} testID={`${testID}-cancel-button`}>
96
- {cancelText}
97
- </AtomicButton>
98
-
99
- {/* Confirm Button */}
100
- <AtomicButton variant={variant === 'destructive' ? 'primary' : 'primary'} size="md" onPress={onConfirm} style={[
101
- getButtonStyle(),
102
- ...(variant === 'destructive' ? [{ backgroundColor: tokens.colors.error }] : []),
103
- ...(variant === 'warning' ? [{ backgroundColor: tokens.colors.warning }] : []),
104
- ...(variant === 'success' ? [{ backgroundColor: tokens.colors.success }] : []),
105
- ]} testID={`${testID}-confirm-button`}>
106
- {confirmText}
107
- </AtomicButton>
108
- </View>
109
- </View>
110
- </View>
111
- </Modal>);
112
- };
113
- /**
114
- * Hook for managing confirmation modal state
115
- *
116
- * @example
117
- * ```tsx
118
- * const { showConfirmation, confirmationProps } = useConfirmationModal({
119
- * title: 'Delete Item?',
120
- * message: 'This cannot be undone',
121
- * variant: 'destructive',
122
- * onConfirm: handleDelete,
123
- * });
124
- *
125
- * // In JSX
126
- * <AtomicConfirmationModal {...confirmationProps} />
127
- * <Button onPress={showConfirmation}>Delete</Button>
128
- * ```
129
- */
130
- export const useConfirmationModal = (config) => {
131
- const [visible, setVisible] = React.useState(false);
132
- const showConfirmation = () => setVisible(true);
133
- const hideConfirmation = () => setVisible(false);
134
- const handleConfirm = () => {
135
- config.onConfirm();
136
- hideConfirmation();
137
- };
138
- const confirmationProps = {
139
- visible,
140
- title: config.title,
141
- message: config.message,
142
- variant: config.variant || 'default',
143
- confirmText: config.confirmText,
144
- cancelText: config.cancelText,
145
- onConfirm: handleConfirm,
146
- onCancel: hideConfirmation,
147
- };
148
- return {
149
- showConfirmation,
150
- hideConfirmation,
151
- confirmationProps,
152
- };
153
- };
@@ -1,67 +0,0 @@
1
- /**
2
- * EmptyState Molecule - Universal Empty State Display
3
- *
4
- * Displays icon, title, and subtitle for empty data scenarios
5
- * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
- *
7
- * Atomic Design Level: MOLECULE
8
- * Composition: Icon + AtomicText + Layout
9
- *
10
- * Usage:
11
- * - Empty lists
12
- * - Empty grids
13
- * - No search results
14
- * - No data states
15
- */
16
- import React from 'react';
17
- import { View, StyleSheet } from 'react-native';
18
- import { AtomicText, AtomicIcon } from '../atoms';
19
- import { useAppDesignTokens } from '@umituz/react-native-theme';
20
- // =============================================================================
21
- // COMPONENT IMPLEMENTATION
22
- // =============================================================================
23
- export const EmptyState = ({ icon, iconSize = 'xl', title, subtitle, iconColor, titleColor, subtitleColor, style, titleStyle, subtitleStyle, }) => {
24
- const tokens = useAppDesignTokens();
25
- const styles = getStyles(tokens);
26
- return (<View style={[styles.container, style]}>
27
- <AtomicIcon name={icon} size={iconSize} customColor={iconColor || tokens.colors.textSecondary}/>
28
- <AtomicText type="headlineMedium" color={titleColor || tokens.colors.textPrimary} style={StyleSheet.flatten([
29
- styles.title,
30
- titleStyle,
31
- ])}>
32
- {title}
33
- </AtomicText>
34
- {subtitle && (<AtomicText type="bodyMedium" color={subtitleColor || tokens.colors.textSecondary} style={StyleSheet.flatten([
35
- styles.subtitle,
36
- subtitleStyle,
37
- ])}>
38
- {subtitle}
39
- </AtomicText>)}
40
- </View>);
41
- };
42
- // =============================================================================
43
- // STYLES
44
- // =============================================================================
45
- const getStyles = (tokens) => StyleSheet.create({
46
- container: {
47
- flex: 1,
48
- justifyContent: 'center',
49
- alignItems: 'center',
50
- paddingVertical: tokens.spacing.xl,
51
- paddingHorizontal: tokens.spacing.lg,
52
- },
53
- title: {
54
- fontSize: tokens.typography.headingMedium.fontSize,
55
- fontWeight: tokens.typography.headingMedium.fontWeight,
56
- marginTop: tokens.spacing.md,
57
- textAlign: 'center',
58
- },
59
- subtitle: {
60
- fontSize: tokens.typography.bodySmall.fontSize,
61
- marginTop: tokens.spacing.xs,
62
- textAlign: 'center',
63
- },
64
- });
65
- // =============================================================================
66
- // EXPORTS
67
- // =============================================================================
@@ -1,75 +0,0 @@
1
- /**
2
- * FormField Molecule - Complete Form Input with Label and Error
3
- *
4
- * Combines AtomicText (label/error) + AtomicInput (field)
5
- * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
- *
7
- * Atomic Design Level: MOLECULE
8
- * Composition: AtomicText + AtomicInput
9
- */
10
- import React from 'react';
11
- import { View } from 'react-native';
12
- import { useAppDesignTokens } from '@umituz/react-native-theme';
13
- import { AtomicText } from '../atoms/AtomicText';
14
- import { AtomicInput } from '../atoms/AtomicInput';
15
- // =============================================================================
16
- // COMPONENT IMPLEMENTATION
17
- // =============================================================================
18
- export const FormField = ({ label, error, helperText, required = false, containerStyle, style, // Accept both style and containerStyle
19
- ...inputProps }) => {
20
- const tokens = useAppDesignTokens();
21
- const inputState = error ? 'error' : 'default';
22
- const styles = getStyles(tokens);
23
- return (<View style={[styles.container, containerStyle || style]}>
24
- {/* Label */}
25
- {label && (<View style={styles.labelContainer}>
26
- <AtomicText type="labelMedium" color="primary" style={styles.label}>
27
- {label}
28
- </AtomicText>
29
- {required && (<AtomicText type="labelMedium" color="error">
30
- {' *'}
31
- </AtomicText>)}
32
- </View>)}
33
-
34
- {/* Input Field */}
35
- <AtomicInput {...inputProps} label={label || ''} state={inputState}/>
36
-
37
- {/* Error Message */}
38
- {error && (<AtomicText type="bodySmall" color="error" style={styles.errorText}>
39
- {error}
40
- </AtomicText>)}
41
-
42
- {/* Helper Text */}
43
- {!error && helperText && (<AtomicText type="bodySmall" color="secondary" style={styles.helperText}>
44
- {helperText}
45
- </AtomicText>)}
46
- </View>);
47
- };
48
- // =============================================================================
49
- // STYLES
50
- // =============================================================================
51
- const getStyles = (tokens) => ({
52
- container: {
53
- marginBottom: tokens.spacing.md,
54
- },
55
- labelContainer: {
56
- flexDirection: 'row',
57
- marginBottom: tokens.spacing.sm,
58
- },
59
- label: {
60
- fontWeight: tokens.typography.labelMedium.fontWeight,
61
- color: tokens.colors.textPrimary,
62
- },
63
- inputError: {
64
- borderColor: tokens.colors.error,
65
- },
66
- errorText: {
67
- marginTop: tokens.spacing.xs,
68
- },
69
- helperText: {
70
- marginTop: tokens.spacing.xs,
71
- },
72
- });
73
- // =============================================================================
74
- // EXPORTS
75
- // =============================================================================
@@ -1,76 +0,0 @@
1
- /**
2
- * GridContainer Molecule - Responsive Grid Layout
3
- *
4
- * Provides flexible grid layout with configurable columns and gap
5
- * Theme: {{THEME_NAME}} ({{CATEGORY}} category)
6
- *
7
- * Atomic Design Level: MOLECULE
8
- * Composition: View + Responsive Layout
9
- *
10
- * Usage:
11
- * - Stats grids (2 columns)
12
- * - Action grids (2 columns)
13
- * - Product grids (2-3 columns)
14
- * - Gallery grids (3-4 columns)
15
- */
16
- import React from 'react';
17
- import { View, StyleSheet } from 'react-native';
18
- // =============================================================================
19
- // COMPONENT IMPLEMENTATION
20
- // =============================================================================
21
- const GridContainerComponent = ({ columns = 2, gap = 8, style, children, }) => {
22
- const styles = getStyles(gap);
23
- return (<View style={[styles.container, style]}>
24
- {React.Children.map(children, (child) => {
25
- if (React.isValidElement(child)) {
26
- const childStyle = child.props.style;
27
- const itemStyle = getItemStyle(columns, gap);
28
- return React.cloneElement(child, {
29
- style: StyleSheet.flatten([itemStyle, childStyle]),
30
- });
31
- }
32
- return child;
33
- })}
34
- </View>);
35
- };
36
- // =============================================================================
37
- // GRID ITEM COMPONENT
38
- // =============================================================================
39
- export const GridItem = ({ children, style }) => {
40
- return <View style={style}>{children}</View>;
41
- };
42
- // Export GridContainer with Item property
43
- export const GridContainer = GridContainerComponent;
44
- // Attach GridItem to GridContainer for convenient usage
45
- GridContainer.Item = GridItem;
46
- // =============================================================================
47
- // HELPERS
48
- // =============================================================================
49
- const getItemStyle = (columns, gap) => {
50
- // Calculate width: (100% - total gap space) / columns
51
- // For 2 columns with 8px gap: (100% - 8px) / 2 = ~48%
52
- // For 3 columns with 8px gap: (100% - 16px) / 3 = ~31.33%
53
- const widthMap = {
54
- 2: '48%',
55
- 3: '31.33%',
56
- 4: '23%',
57
- };
58
- return {
59
- width: widthMap[columns] || '48%',
60
- marginHorizontal: gap / 2,
61
- marginBottom: gap * 1.5,
62
- };
63
- };
64
- // =============================================================================
65
- // STYLES
66
- // =============================================================================
67
- const getStyles = (gap) => StyleSheet.create({
68
- container: {
69
- flexDirection: 'row',
70
- flexWrap: 'wrap',
71
- marginHorizontal: -(gap / 2),
72
- },
73
- });
74
- // =============================================================================
75
- // EXPORTS
76
- // =============================================================================