@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,40 +0,0 @@
|
|
|
1
|
-
import { ViewStyle, TextStyle } from 'react-native';
|
|
2
|
-
import { AtomicIconColor } from '../../AtomicIcon';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Picker option item
|
|
6
|
-
*
|
|
7
|
-
* icon: Any MaterialIcons name
|
|
8
|
-
* @see https://fonts.google.com/icons
|
|
9
|
-
*/
|
|
10
|
-
export interface PickerOption {
|
|
11
|
-
label: string;
|
|
12
|
-
value: string;
|
|
13
|
-
icon?: string; // MaterialIcons name
|
|
14
|
-
disabled?: boolean;
|
|
15
|
-
description?: string;
|
|
16
|
-
testID?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export type PickerSize = 'sm' | 'md' | 'lg';
|
|
20
|
-
|
|
21
|
-
export interface AtomicPickerProps {
|
|
22
|
-
value: string | string[];
|
|
23
|
-
onChange: (value: string | string[]) => void;
|
|
24
|
-
options: PickerOption[];
|
|
25
|
-
label?: string;
|
|
26
|
-
placeholder?: string;
|
|
27
|
-
error?: string;
|
|
28
|
-
disabled?: boolean;
|
|
29
|
-
multiple?: boolean;
|
|
30
|
-
searchable?: boolean;
|
|
31
|
-
clearable?: boolean;
|
|
32
|
-
autoClose?: boolean;
|
|
33
|
-
color?: AtomicIconColor;
|
|
34
|
-
size?: PickerSize;
|
|
35
|
-
modalTitle?: string;
|
|
36
|
-
emptyMessage?: string;
|
|
37
|
-
style?: ViewStyle | ViewStyle[];
|
|
38
|
-
labelStyle?: TextStyle | TextStyle[];
|
|
39
|
-
testID?: string;
|
|
40
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { ViewStyle } from 'react-native';
|
|
2
|
-
import { FeedbackStrength } from '../types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Get opacity value based on feedback strength
|
|
6
|
-
*/
|
|
7
|
-
export const getOpacityValue = (strength: FeedbackStrength): number => {
|
|
8
|
-
switch (strength) {
|
|
9
|
-
case 'subtle':
|
|
10
|
-
return 0.8;
|
|
11
|
-
case 'normal':
|
|
12
|
-
return 0.6;
|
|
13
|
-
case 'strong':
|
|
14
|
-
return 0.4;
|
|
15
|
-
default:
|
|
16
|
-
return 0.6;
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Get base touchable container style
|
|
22
|
-
* Ensures minimum touch target size (iOS HIG: 48x48)
|
|
23
|
-
*/
|
|
24
|
-
export const getTouchableContainerStyle = (): ViewStyle => ({
|
|
25
|
-
minWidth: 48,
|
|
26
|
-
minHeight: 48,
|
|
27
|
-
justifyContent: 'center',
|
|
28
|
-
alignItems: 'center',
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Get disabled touchable style
|
|
33
|
-
*/
|
|
34
|
-
export const getDisabledStyle = (): ViewStyle => ({
|
|
35
|
-
opacity: 0.5,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Convert number to HitSlop object
|
|
40
|
-
* If hitSlop is a number, apply it to all sides
|
|
41
|
-
*/
|
|
42
|
-
export const normalizeHitSlop = (
|
|
43
|
-
hitSlop: number | { top?: number; bottom?: number; left?: number; right?: number } | undefined
|
|
44
|
-
): { top: number; bottom: number; left: number; right: number } | undefined => {
|
|
45
|
-
if (hitSlop === undefined) return undefined;
|
|
46
|
-
|
|
47
|
-
if (typeof hitSlop === 'number') {
|
|
48
|
-
return {
|
|
49
|
-
top: hitSlop,
|
|
50
|
-
bottom: hitSlop,
|
|
51
|
-
left: hitSlop,
|
|
52
|
-
right: hitSlop,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
top: hitSlop.top || 0,
|
|
58
|
-
bottom: hitSlop.bottom || 0,
|
|
59
|
-
left: hitSlop.left || 0,
|
|
60
|
-
right: hitSlop.right || 0,
|
|
61
|
-
};
|
|
62
|
-
};
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { StyleProp, ViewStyle, GestureResponderEvent } from 'react-native';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Touchable feedback variant
|
|
5
|
-
* - opacity: iOS-style opacity feedback (default)
|
|
6
|
-
* - highlight: Android-style highlight feedback
|
|
7
|
-
* - ripple: Material Design ripple effect (Android only)
|
|
8
|
-
* - none: No visual feedback
|
|
9
|
-
*/
|
|
10
|
-
export type TouchableFeedback = 'opacity' | 'highlight' | 'ripple' | 'none';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Feedback strength for visual feedback
|
|
14
|
-
* - subtle: Light feedback (0.8 opacity)
|
|
15
|
-
* - normal: Standard feedback (0.6 opacity)
|
|
16
|
-
* - strong: Strong feedback (0.4 opacity)
|
|
17
|
-
*/
|
|
18
|
-
export type FeedbackStrength = 'subtle' | 'normal' | 'strong';
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Hit slop configuration
|
|
22
|
-
* Extends the touchable area beyond the component's bounds
|
|
23
|
-
*/
|
|
24
|
-
export interface HitSlop {
|
|
25
|
-
top?: number;
|
|
26
|
-
bottom?: number;
|
|
27
|
-
left?: number;
|
|
28
|
-
right?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* AtomicTouchable component props
|
|
33
|
-
*
|
|
34
|
-
* A unified touchable wrapper with consistent behavior across platforms.
|
|
35
|
-
* Uses React Native's Pressable API for modern, accessible touch handling.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```tsx
|
|
39
|
-
* <AtomicTouchable
|
|
40
|
-
* onPress={handlePress}
|
|
41
|
-
* feedback="opacity"
|
|
42
|
-
* strength="normal"
|
|
43
|
-
* disabled={isDisabled}
|
|
44
|
-
* hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
45
|
-
* style={styles.touchable}
|
|
46
|
-
* >
|
|
47
|
-
* <AtomicText>Press Me</AtomicText>
|
|
48
|
-
* </AtomicTouchable>
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export interface AtomicTouchableProps {
|
|
52
|
-
/**
|
|
53
|
-
* Content to render inside the touchable
|
|
54
|
-
*/
|
|
55
|
-
children: React.ReactNode;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Callback fired when the touchable is pressed
|
|
59
|
-
*/
|
|
60
|
-
onPress?: (event: GestureResponderEvent) => void;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Callback fired when press starts (finger down)
|
|
64
|
-
*/
|
|
65
|
-
onPressIn?: (event: GestureResponderEvent) => void;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Callback fired when press ends (finger up)
|
|
69
|
-
*/
|
|
70
|
-
onPressOut?: (event: GestureResponderEvent) => void;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Callback fired on long press (500ms default)
|
|
74
|
-
*/
|
|
75
|
-
onLongPress?: (event: GestureResponderEvent) => void;
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Feedback variant
|
|
79
|
-
* @default 'opacity'
|
|
80
|
-
*/
|
|
81
|
-
feedback?: TouchableFeedback;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Feedback strength
|
|
85
|
-
* @default 'normal'
|
|
86
|
-
*/
|
|
87
|
-
strength?: FeedbackStrength;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Disable the touchable
|
|
91
|
-
* @default false
|
|
92
|
-
*/
|
|
93
|
-
disabled?: boolean;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Hit slop - extends touchable area
|
|
97
|
-
* Useful for small touch targets
|
|
98
|
-
* @default undefined
|
|
99
|
-
*/
|
|
100
|
-
hitSlop?: HitSlop | number;
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Custom style for the touchable container
|
|
104
|
-
*/
|
|
105
|
-
style?: StyleProp<ViewStyle>;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Style applied when pressed
|
|
109
|
-
*/
|
|
110
|
-
pressedStyle?: StyleProp<ViewStyle>;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Style applied when disabled
|
|
114
|
-
*/
|
|
115
|
-
disabledStyle?: StyleProp<ViewStyle>;
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Accessibility label for screen readers
|
|
119
|
-
*/
|
|
120
|
-
accessibilityLabel?: string;
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Accessibility hint for screen readers
|
|
124
|
-
*/
|
|
125
|
-
accessibilityHint?: string;
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Accessibility role
|
|
129
|
-
* @default 'button'
|
|
130
|
-
*/
|
|
131
|
-
accessibilityRole?: 'button' | 'link' | 'none';
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Test ID for E2E testing
|
|
135
|
-
*/
|
|
136
|
-
testID?: string;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Delay before onLongPress is triggered (ms)
|
|
140
|
-
* @default 500
|
|
141
|
-
*/
|
|
142
|
-
delayLongPress?: number;
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Ripple color (Android only, for 'ripple' feedback)
|
|
146
|
-
* @default theme primary color with alpha
|
|
147
|
-
*/
|
|
148
|
-
rippleColor?: string;
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Border radius for ripple effect (Android only)
|
|
152
|
-
* @default 0
|
|
153
|
-
*/
|
|
154
|
-
rippleRadius?: number;
|
|
155
|
-
}
|
|
@@ -1,180 +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
|
-
|
|
13
|
-
import { useWindowDimensions } from 'react-native';
|
|
14
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
15
|
-
import {
|
|
16
|
-
getResponsiveLogoSize,
|
|
17
|
-
getResponsiveInputHeight,
|
|
18
|
-
getResponsiveHorizontalPadding,
|
|
19
|
-
getResponsiveBottomPosition,
|
|
20
|
-
getResponsiveFABPosition,
|
|
21
|
-
getResponsiveModalMaxHeight,
|
|
22
|
-
getResponsiveMinModalHeight,
|
|
23
|
-
getResponsiveIconContainerSize,
|
|
24
|
-
getResponsiveGridColumns,
|
|
25
|
-
getResponsiveMaxWidth,
|
|
26
|
-
getResponsiveFontSize,
|
|
27
|
-
isSmallPhone,
|
|
28
|
-
isTablet,
|
|
29
|
-
isLandscape,
|
|
30
|
-
getDeviceType,
|
|
31
|
-
getMinTouchTargetSize,
|
|
32
|
-
getSpacingMultiplier,
|
|
33
|
-
getOnboardingIconMarginTop,
|
|
34
|
-
getOnboardingIconMarginBottom,
|
|
35
|
-
getOnboardingTitleMarginBottom,
|
|
36
|
-
getOnboardingTextPadding,
|
|
37
|
-
getOnboardingDescriptionMarginTop,
|
|
38
|
-
getOnboardingIconSize,
|
|
39
|
-
getFormBottomPadding,
|
|
40
|
-
getInputIconSize,
|
|
41
|
-
getFormContentWidth,
|
|
42
|
-
getFormElementSpacing,
|
|
43
|
-
DeviceType,
|
|
44
|
-
} from '../utils/responsive';
|
|
45
|
-
|
|
46
|
-
export interface UseResponsiveReturn {
|
|
47
|
-
// Device info
|
|
48
|
-
width: number;
|
|
49
|
-
height: number;
|
|
50
|
-
isSmallDevice: boolean;
|
|
51
|
-
isTabletDevice: boolean;
|
|
52
|
-
isLandscapeMode: boolean;
|
|
53
|
-
deviceType: DeviceType;
|
|
54
|
-
|
|
55
|
-
// Safe area insets
|
|
56
|
-
insets: {
|
|
57
|
-
top: number;
|
|
58
|
-
bottom: number;
|
|
59
|
-
left: number;
|
|
60
|
-
right: number;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Responsive sizes
|
|
64
|
-
logoSize: number;
|
|
65
|
-
inputHeight: number;
|
|
66
|
-
iconContainerSize: number;
|
|
67
|
-
maxContentWidth: number;
|
|
68
|
-
minTouchTarget: number;
|
|
69
|
-
|
|
70
|
-
// Responsive positioning
|
|
71
|
-
horizontalPadding: number;
|
|
72
|
-
bottomPosition: number;
|
|
73
|
-
fabPosition: { bottom: number; right: number };
|
|
74
|
-
|
|
75
|
-
// Responsive layout
|
|
76
|
-
modalMaxHeight: string;
|
|
77
|
-
modalMinHeight: number;
|
|
78
|
-
gridColumns: number;
|
|
79
|
-
spacingMultiplier: number;
|
|
80
|
-
|
|
81
|
-
// Onboarding-specific spacing (pre-calculated, device-aware)
|
|
82
|
-
onboardingIconMarginTop: number;
|
|
83
|
-
onboardingIconMarginBottom: number;
|
|
84
|
-
onboardingIconSize: number;
|
|
85
|
-
onboardingTitleMarginBottom: number;
|
|
86
|
-
onboardingTextPadding: number;
|
|
87
|
-
onboardingDescriptionMarginTop: number;
|
|
88
|
-
|
|
89
|
-
// Form-specific spacing (pre-calculated, universal)
|
|
90
|
-
formBottomPadding: number;
|
|
91
|
-
inputIconSize: number;
|
|
92
|
-
formContentWidth: number | undefined;
|
|
93
|
-
formElementSpacing: number;
|
|
94
|
-
|
|
95
|
-
// Utility functions
|
|
96
|
-
getLogoSize: (baseSize?: number) => number;
|
|
97
|
-
getInputHeight: (baseHeight?: number) => number;
|
|
98
|
-
getIconSize: (baseSize?: number) => number;
|
|
99
|
-
getMaxWidth: (baseWidth?: number) => number;
|
|
100
|
-
getFontSize: (baseFontSize: number) => number;
|
|
101
|
-
getGridCols: (mobile?: number, tablet?: number) => number;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Hook for responsive design utilities
|
|
106
|
-
* Automatically updates when screen dimensions or orientation changes
|
|
107
|
-
*/
|
|
108
|
-
export const useResponsive = (): UseResponsiveReturn => {
|
|
109
|
-
const { width, height } = useWindowDimensions();
|
|
110
|
-
const insets = useSafeAreaInsets();
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
// Device info
|
|
114
|
-
width,
|
|
115
|
-
height,
|
|
116
|
-
isSmallDevice: isSmallPhone(),
|
|
117
|
-
isTabletDevice: isTablet(),
|
|
118
|
-
isLandscapeMode: isLandscape(),
|
|
119
|
-
deviceType: getDeviceType(),
|
|
120
|
-
|
|
121
|
-
// Safe area insets
|
|
122
|
-
insets,
|
|
123
|
-
|
|
124
|
-
// Responsive sizes (with default values)
|
|
125
|
-
logoSize: getResponsiveLogoSize(),
|
|
126
|
-
inputHeight: getResponsiveInputHeight(),
|
|
127
|
-
iconContainerSize: getResponsiveIconContainerSize(),
|
|
128
|
-
maxContentWidth: getResponsiveMaxWidth(),
|
|
129
|
-
minTouchTarget: getMinTouchTargetSize(),
|
|
130
|
-
|
|
131
|
-
// Responsive positioning
|
|
132
|
-
horizontalPadding: getResponsiveHorizontalPadding(16, insets),
|
|
133
|
-
bottomPosition: getResponsiveBottomPosition(32, insets),
|
|
134
|
-
fabPosition: getResponsiveFABPosition(insets),
|
|
135
|
-
|
|
136
|
-
// Responsive layout
|
|
137
|
-
modalMaxHeight: getResponsiveModalMaxHeight(),
|
|
138
|
-
modalMinHeight: getResponsiveMinModalHeight(),
|
|
139
|
-
gridColumns: getResponsiveGridColumns(),
|
|
140
|
-
spacingMultiplier: getSpacingMultiplier(),
|
|
141
|
-
|
|
142
|
-
// Onboarding-specific spacing (pre-calculated, no component calculations)
|
|
143
|
-
onboardingIconMarginTop: getOnboardingIconMarginTop(),
|
|
144
|
-
onboardingIconMarginBottom: getOnboardingIconMarginBottom(),
|
|
145
|
-
onboardingIconSize: getOnboardingIconSize(),
|
|
146
|
-
onboardingTitleMarginBottom: getOnboardingTitleMarginBottom(),
|
|
147
|
-
onboardingTextPadding: getOnboardingTextPadding(),
|
|
148
|
-
onboardingDescriptionMarginTop: getOnboardingDescriptionMarginTop(),
|
|
149
|
-
|
|
150
|
-
// Form-specific spacing (pre-calculated, universal)
|
|
151
|
-
formBottomPadding: getFormBottomPadding(insets.bottom),
|
|
152
|
-
inputIconSize: getInputIconSize(),
|
|
153
|
-
formContentWidth: getFormContentWidth(),
|
|
154
|
-
formElementSpacing: getFormElementSpacing(),
|
|
155
|
-
|
|
156
|
-
// Utility functions (allow custom base values)
|
|
157
|
-
getLogoSize: (baseSize) => getResponsiveLogoSize(baseSize),
|
|
158
|
-
getInputHeight: (baseHeight) => getResponsiveInputHeight(baseHeight),
|
|
159
|
-
getIconSize: (baseSize) => getResponsiveIconContainerSize(baseSize),
|
|
160
|
-
getMaxWidth: (baseWidth) => getResponsiveMaxWidth(baseWidth),
|
|
161
|
-
getFontSize: (baseFontSize) => getResponsiveFontSize(baseFontSize),
|
|
162
|
-
getGridCols: (mobile, tablet) => getResponsiveGridColumns(mobile, tablet),
|
|
163
|
-
};
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Shorthand hook for just responsive sizes
|
|
168
|
-
*/
|
|
169
|
-
export const useResponsiveSizes = () => {
|
|
170
|
-
const { logoSize, inputHeight, iconContainerSize, maxContentWidth } = useResponsive();
|
|
171
|
-
return { logoSize, inputHeight, iconContainerSize, maxContentWidth };
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Shorthand hook for just device type checks
|
|
176
|
-
*/
|
|
177
|
-
export const useDeviceType = () => {
|
|
178
|
-
const { isSmallDevice, isTabletDevice, deviceType } = useResponsive();
|
|
179
|
-
return { isSmallDevice, isTabletDevice, deviceType };
|
|
180
|
-
};
|
|
@@ -1,243 +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
|
-
|
|
40
|
-
import React from 'react';
|
|
41
|
-
import { View, Modal, TouchableOpacity } from 'react-native';
|
|
42
|
-
import { useAppDesignTokens } from '@umituz/react-native-theme';
|
|
43
|
-
import { AtomicText } from '../atoms/AtomicText';
|
|
44
|
-
import { AtomicButton } from '../atoms/AtomicButton';
|
|
45
|
-
import { AtomicIcon } from '../atoms/AtomicIcon';
|
|
46
|
-
import {
|
|
47
|
-
AtomicConfirmationModalProps,
|
|
48
|
-
ConfirmationModalVariant,
|
|
49
|
-
} from './confirmation-modal/types';
|
|
50
|
-
import {
|
|
51
|
-
getVariantConfig,
|
|
52
|
-
getModalOverlayStyle,
|
|
53
|
-
getBackdropStyle,
|
|
54
|
-
getModalContainerStyle,
|
|
55
|
-
getIconContainerStyle,
|
|
56
|
-
getTitleContainerStyle,
|
|
57
|
-
getMessageContainerStyle,
|
|
58
|
-
getButtonContainerStyle,
|
|
59
|
-
getButtonStyle,
|
|
60
|
-
} from './confirmation-modal/styles/confirmationModalStyles';
|
|
61
|
-
|
|
62
|
-
export type { AtomicConfirmationModalProps };
|
|
63
|
-
export type { ConfirmationModalVariant };
|
|
64
|
-
|
|
65
|
-
export const AtomicConfirmationModal: React.FC<AtomicConfirmationModalProps> = ({
|
|
66
|
-
visible,
|
|
67
|
-
title,
|
|
68
|
-
message,
|
|
69
|
-
variant = 'default',
|
|
70
|
-
confirmText,
|
|
71
|
-
cancelText,
|
|
72
|
-
icon,
|
|
73
|
-
onConfirm,
|
|
74
|
-
onCancel,
|
|
75
|
-
showBackdrop = true,
|
|
76
|
-
backdropDismissible = true,
|
|
77
|
-
style,
|
|
78
|
-
testID = 'atomic-confirmation-modal',
|
|
79
|
-
}) => {
|
|
80
|
-
const tokens = useAppDesignTokens();
|
|
81
|
-
|
|
82
|
-
// Get variant-specific configuration (icon and color only)
|
|
83
|
-
const variantConfig = getVariantConfig(variant as 'default' | 'destructive' | 'warning' | 'success', tokens);
|
|
84
|
-
|
|
85
|
-
// Determine final icon
|
|
86
|
-
const finalIcon = icon || variantConfig.icon;
|
|
87
|
-
|
|
88
|
-
// Handle backdrop press
|
|
89
|
-
const handleBackdropPress = () => {
|
|
90
|
-
if (backdropDismissible) {
|
|
91
|
-
onCancel();
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<Modal
|
|
97
|
-
visible={visible}
|
|
98
|
-
transparent
|
|
99
|
-
animationType="fade"
|
|
100
|
-
onRequestClose={onCancel}
|
|
101
|
-
statusBarTranslucent
|
|
102
|
-
testID={testID}
|
|
103
|
-
>
|
|
104
|
-
<View style={getModalOverlayStyle(tokens)}>
|
|
105
|
-
{/* Backdrop - Tap to dismiss if enabled */}
|
|
106
|
-
{showBackdrop && (
|
|
107
|
-
<TouchableOpacity
|
|
108
|
-
style={getBackdropStyle()}
|
|
109
|
-
activeOpacity={1}
|
|
110
|
-
onPress={handleBackdropPress}
|
|
111
|
-
testID={`${testID}-backdrop`}
|
|
112
|
-
/>
|
|
113
|
-
)}
|
|
114
|
-
|
|
115
|
-
{/* Modal Container */}
|
|
116
|
-
<View style={[getModalContainerStyle(tokens), style]}>
|
|
117
|
-
{/* Icon */}
|
|
118
|
-
<View style={getIconContainerStyle(tokens)}>
|
|
119
|
-
<AtomicIcon
|
|
120
|
-
name={finalIcon}
|
|
121
|
-
size="xl"
|
|
122
|
-
color={variantConfig.iconColor}
|
|
123
|
-
testID={`${testID}-icon`}
|
|
124
|
-
/>
|
|
125
|
-
</View>
|
|
126
|
-
|
|
127
|
-
{/* Title */}
|
|
128
|
-
<View style={getTitleContainerStyle(tokens)}>
|
|
129
|
-
<AtomicText
|
|
130
|
-
type="titleLarge"
|
|
131
|
-
style={{
|
|
132
|
-
color: tokens.colors.textPrimary,
|
|
133
|
-
textAlign: 'center',
|
|
134
|
-
fontWeight: tokens.typography.bold,
|
|
135
|
-
}}
|
|
136
|
-
testID={`${testID}-title`}
|
|
137
|
-
>
|
|
138
|
-
{title}
|
|
139
|
-
</AtomicText>
|
|
140
|
-
</View>
|
|
141
|
-
|
|
142
|
-
{/* Message */}
|
|
143
|
-
<View style={getMessageContainerStyle(tokens)}>
|
|
144
|
-
<AtomicText
|
|
145
|
-
type="bodyMedium"
|
|
146
|
-
style={{
|
|
147
|
-
color: tokens.colors.textSecondary,
|
|
148
|
-
textAlign: 'center',
|
|
149
|
-
lineHeight: tokens.typography.bodyMedium.lineHeight,
|
|
150
|
-
}}
|
|
151
|
-
testID={`${testID}-message`}
|
|
152
|
-
>
|
|
153
|
-
{message}
|
|
154
|
-
</AtomicText>
|
|
155
|
-
</View>
|
|
156
|
-
|
|
157
|
-
{/* Action Buttons */}
|
|
158
|
-
<View style={getButtonContainerStyle(tokens)}>
|
|
159
|
-
{/* Cancel Button */}
|
|
160
|
-
<AtomicButton
|
|
161
|
-
variant="outline"
|
|
162
|
-
size="md"
|
|
163
|
-
onPress={onCancel}
|
|
164
|
-
style={getButtonStyle()}
|
|
165
|
-
testID={`${testID}-cancel-button`}
|
|
166
|
-
>
|
|
167
|
-
{cancelText}
|
|
168
|
-
</AtomicButton>
|
|
169
|
-
|
|
170
|
-
{/* Confirm Button */}
|
|
171
|
-
<AtomicButton
|
|
172
|
-
variant={variant === 'destructive' ? 'primary' : 'primary'}
|
|
173
|
-
size="md"
|
|
174
|
-
onPress={onConfirm}
|
|
175
|
-
style={[
|
|
176
|
-
getButtonStyle(),
|
|
177
|
-
...(variant === 'destructive' ? [{ backgroundColor: tokens.colors.error }] : []),
|
|
178
|
-
...(variant === 'warning' ? [{ backgroundColor: tokens.colors.warning }] : []),
|
|
179
|
-
...(variant === 'success' ? [{ backgroundColor: tokens.colors.success }] : []),
|
|
180
|
-
]}
|
|
181
|
-
testID={`${testID}-confirm-button`}
|
|
182
|
-
>
|
|
183
|
-
{confirmText}
|
|
184
|
-
</AtomicButton>
|
|
185
|
-
</View>
|
|
186
|
-
</View>
|
|
187
|
-
</View>
|
|
188
|
-
</Modal>
|
|
189
|
-
);
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Hook for managing confirmation modal state
|
|
194
|
-
*
|
|
195
|
-
* @example
|
|
196
|
-
* ```tsx
|
|
197
|
-
* const { showConfirmation, confirmationProps } = useConfirmationModal({
|
|
198
|
-
* title: 'Delete Item?',
|
|
199
|
-
* message: 'This cannot be undone',
|
|
200
|
-
* variant: 'destructive',
|
|
201
|
-
* onConfirm: handleDelete,
|
|
202
|
-
* });
|
|
203
|
-
*
|
|
204
|
-
* // In JSX
|
|
205
|
-
* <AtomicConfirmationModal {...confirmationProps} />
|
|
206
|
-
* <Button onPress={showConfirmation}>Delete</Button>
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
export const useConfirmationModal = (config: {
|
|
210
|
-
title: string;
|
|
211
|
-
message: string;
|
|
212
|
-
variant?: ConfirmationModalVariant;
|
|
213
|
-
confirmText: string;
|
|
214
|
-
cancelText: string;
|
|
215
|
-
onConfirm: () => void;
|
|
216
|
-
}) => {
|
|
217
|
-
const [visible, setVisible] = React.useState(false);
|
|
218
|
-
|
|
219
|
-
const showConfirmation = () => setVisible(true);
|
|
220
|
-
const hideConfirmation = () => setVisible(false);
|
|
221
|
-
|
|
222
|
-
const handleConfirm = () => {
|
|
223
|
-
config.onConfirm();
|
|
224
|
-
hideConfirmation();
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const confirmationProps: AtomicConfirmationModalProps = {
|
|
228
|
-
visible,
|
|
229
|
-
title: config.title,
|
|
230
|
-
message: config.message,
|
|
231
|
-
variant: config.variant || 'default',
|
|
232
|
-
confirmText: config.confirmText,
|
|
233
|
-
cancelText: config.cancelText,
|
|
234
|
-
onConfirm: handleConfirm,
|
|
235
|
-
onCancel: hideConfirmation,
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
return {
|
|
239
|
-
showConfirmation,
|
|
240
|
-
hideConfirmation,
|
|
241
|
-
confirmationProps,
|
|
242
|
-
};
|
|
243
|
-
};
|