@umituz/react-native-design-system 1.15.0 → 2.0.0

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 (87) hide show
  1. package/package.json +26 -19
  2. package/src/atoms/AtomicAvatar.tsx +161 -0
  3. package/src/atoms/AtomicButton.tsx +241 -0
  4. package/src/atoms/AtomicChip.tsx +226 -0
  5. package/src/atoms/AtomicDatePicker.tsx +255 -0
  6. package/src/atoms/AtomicFab.tsx +99 -0
  7. package/src/atoms/AtomicIcon.tsx +149 -0
  8. package/src/atoms/AtomicInput.tsx +308 -0
  9. package/src/atoms/AtomicPicker.tsx +310 -0
  10. package/src/atoms/AtomicProgress.tsx +149 -0
  11. package/src/atoms/AtomicText.tsx +55 -0
  12. package/src/atoms/__tests__/AtomicButton.test.tsx +107 -0
  13. package/src/atoms/__tests__/AtomicIcon.test.tsx +110 -0
  14. package/src/atoms/__tests__/AtomicInput.test.tsx +195 -0
  15. package/src/atoms/datepicker/components/DatePickerButton.tsx +112 -0
  16. package/src/atoms/datepicker/components/DatePickerModal.tsx +143 -0
  17. package/src/atoms/fab/styles/fabStyles.ts +98 -0
  18. package/src/atoms/fab/types/index.ts +88 -0
  19. package/src/atoms/index.ts +70 -0
  20. package/src/atoms/input/hooks/useInputState.ts +63 -0
  21. package/src/atoms/input/styles/inputStylesHelper.ts +120 -0
  22. package/src/atoms/picker/components/PickerChips.tsx +57 -0
  23. package/src/atoms/picker/components/PickerModal.tsx +214 -0
  24. package/src/atoms/picker/styles/pickerStyles.ts +223 -0
  25. package/src/atoms/picker/types/index.ts +42 -0
  26. package/src/index.ts +133 -56
  27. package/src/molecules/ConfirmationModal.tsx +42 -0
  28. package/src/molecules/ConfirmationModalContent.tsx +87 -0
  29. package/src/molecules/ConfirmationModalMain.tsx +91 -0
  30. package/src/molecules/FormField.tsx +155 -0
  31. package/src/molecules/IconContainer.tsx +79 -0
  32. package/src/molecules/ListItem.tsx +35 -0
  33. package/src/molecules/ScreenHeader.tsx +171 -0
  34. package/src/molecules/SearchBar.tsx +198 -0
  35. package/src/molecules/confirmation-modal/components.tsx +94 -0
  36. package/src/molecules/confirmation-modal/index.ts +7 -0
  37. package/src/molecules/confirmation-modal/styles/confirmationModalStyles.ts +133 -0
  38. package/src/molecules/confirmation-modal/types/index.ts +41 -0
  39. package/src/molecules/confirmation-modal/useConfirmationModal.ts +50 -0
  40. package/src/molecules/index.ts +19 -0
  41. package/src/molecules/listitem/index.ts +6 -0
  42. package/src/molecules/listitem/styles/listItemStyles.ts +37 -0
  43. package/src/molecules/listitem/types/index.ts +21 -0
  44. package/src/organisms/AppHeader.tsx +136 -0
  45. package/src/organisms/FormContainer.tsx +169 -0
  46. package/src/organisms/ScreenLayout.tsx +183 -0
  47. package/src/organisms/index.ts +31 -0
  48. package/src/responsive/config.ts +139 -0
  49. package/src/responsive/deviceDetection.ts +155 -0
  50. package/src/responsive/gridUtils.ts +79 -0
  51. package/src/responsive/index.ts +52 -0
  52. package/src/responsive/platformConstants.ts +98 -0
  53. package/src/responsive/responsive.ts +61 -0
  54. package/src/responsive/responsiveLayout.ts +137 -0
  55. package/src/responsive/responsiveSizing.ts +134 -0
  56. package/src/responsive/useResponsive.ts +140 -0
  57. package/src/responsive/validation.ts +158 -0
  58. package/src/theme/core/BaseTokens.ts +42 -0
  59. package/src/theme/core/ColorPalette.ts +29 -0
  60. package/src/theme/core/CustomColors.ts +122 -0
  61. package/src/theme/core/NavigationTheme.ts +72 -0
  62. package/src/theme/core/TokenFactory.ts +103 -0
  63. package/src/theme/core/colors/ColorUtils.ts +53 -0
  64. package/src/theme/core/colors/DarkColors.ts +146 -0
  65. package/src/theme/core/colors/LightColors.ts +146 -0
  66. package/src/theme/core/constants/DesignConstants.ts +31 -0
  67. package/src/theme/core/themes.ts +118 -0
  68. package/src/theme/core/tokens/BaseTokens.ts +144 -0
  69. package/src/theme/core/tokens/Borders.ts +43 -0
  70. package/src/theme/core/tokens/Sizes.ts +51 -0
  71. package/src/theme/core/tokens/Spacing.ts +38 -0
  72. package/src/theme/core/tokens/Typography.ts +143 -0
  73. package/src/theme/hooks/useAppDesignTokens.ts +45 -0
  74. package/src/theme/hooks/useCommonStyles.ts +248 -0
  75. package/src/theme/hooks/useThemedStyles.ts +68 -0
  76. package/src/theme/index.ts +94 -0
  77. package/src/theme/infrastructure/globalThemeStore.ts +69 -0
  78. package/src/theme/infrastructure/storage/ThemeStorage.ts +93 -0
  79. package/src/theme/infrastructure/stores/themeStore.ts +109 -0
  80. package/src/typography/__tests__/colorValidationUtils.test.ts +180 -0
  81. package/src/typography/__tests__/textColorUtils.test.ts +185 -0
  82. package/src/typography/__tests__/textStyleUtils.test.ts +168 -0
  83. package/src/typography/domain/entities/TypographyTypes.ts +88 -0
  84. package/src/typography/index.ts +53 -0
  85. package/src/typography/presentation/utils/colorValidationUtils.ts +133 -0
  86. package/src/typography/presentation/utils/textColorUtils.ts +205 -0
  87. package/src/typography/presentation/utils/textStyleUtils.ts +159 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * AtomicPicker Styles
3
+ */
4
+ import type { ViewStyle, TextStyle } from 'react-native';
5
+ import type { DesignTokens } from '../../../theme';
6
+
7
+ export type PickerSize = 'sm' | 'md' | 'lg';
8
+
9
+ export interface PickerContainerStyles {
10
+ base: ViewStyle;
11
+ size: Record<PickerSize, ViewStyle>;
12
+ state: {
13
+ error: ViewStyle;
14
+ disabled: ViewStyle;
15
+ };
16
+ }
17
+
18
+ export interface PickerLabelStyles {
19
+ base: TextStyle;
20
+ size: Record<PickerSize, TextStyle>;
21
+ }
22
+
23
+ export interface PickerValueStyles {
24
+ base: TextStyle;
25
+ size: Record<PickerSize, TextStyle>;
26
+ }
27
+
28
+ export interface PickerPlaceholderStyles {
29
+ base: TextStyle;
30
+ size: Record<PickerSize, TextStyle>;
31
+ }
32
+
33
+ export const getPickerContainerStyles = (tokens: DesignTokens): PickerContainerStyles => ({
34
+ base: {
35
+ flexDirection: 'row',
36
+ alignItems: 'center',
37
+ justifyContent: 'space-between',
38
+ borderWidth: 1,
39
+ borderColor: tokens.colors.outline,
40
+ backgroundColor: tokens.colors.surface,
41
+ borderRadius: tokens.borders.radius.md,
42
+ },
43
+ size: {
44
+ sm: {
45
+ paddingHorizontal: tokens.spacing.sm,
46
+ paddingVertical: tokens.spacing.xs,
47
+ minHeight: 36,
48
+ },
49
+ md: {
50
+ paddingHorizontal: tokens.spacing.md,
51
+ paddingVertical: tokens.spacing.sm,
52
+ minHeight: 48,
53
+ },
54
+ lg: {
55
+ paddingHorizontal: tokens.spacing.lg,
56
+ paddingVertical: tokens.spacing.md,
57
+ minHeight: 56,
58
+ },
59
+ },
60
+ state: {
61
+ error: {
62
+ borderColor: tokens.colors.error,
63
+ },
64
+ disabled: {
65
+ opacity: tokens.opacity.disabled,
66
+ },
67
+ },
68
+ });
69
+
70
+ export const getPickerLabelStyles = (tokens: DesignTokens): PickerLabelStyles => ({
71
+ base: {
72
+ color: tokens.colors.textPrimary,
73
+ marginBottom: tokens.spacing.xs,
74
+ },
75
+ size: {
76
+ sm: { fontSize: tokens.typography.bodySmall.fontSize },
77
+ md: { fontSize: tokens.typography.bodyMedium.fontSize },
78
+ lg: { fontSize: tokens.typography.bodyLarge.fontSize },
79
+ },
80
+ });
81
+
82
+ export const getPickerValueStyles = (tokens: DesignTokens): PickerValueStyles => ({
83
+ base: {
84
+ color: tokens.colors.textPrimary,
85
+ flex: 1,
86
+ },
87
+ size: {
88
+ sm: { fontSize: tokens.typography.bodySmall.fontSize },
89
+ md: { fontSize: tokens.typography.bodyMedium.fontSize },
90
+ lg: { fontSize: tokens.typography.bodyLarge.fontSize },
91
+ },
92
+ });
93
+
94
+ export const getPickerPlaceholderStyles = (tokens: DesignTokens): PickerPlaceholderStyles => ({
95
+ base: {
96
+ color: tokens.colors.textTertiary,
97
+ flex: 1,
98
+ },
99
+ size: {
100
+ sm: { fontSize: tokens.typography.bodySmall.fontSize },
101
+ md: { fontSize: tokens.typography.bodyMedium.fontSize },
102
+ lg: { fontSize: tokens.typography.bodyLarge.fontSize },
103
+ },
104
+ });
105
+
106
+ export const getPickerErrorStyles = (tokens: DesignTokens): TextStyle => ({
107
+ color: tokens.colors.error,
108
+ fontSize: tokens.typography.bodySmall.fontSize,
109
+ marginTop: tokens.spacing.xs,
110
+ });
111
+
112
+ // Modal styles
113
+ export const getModalOverlayStyles = (tokens: DesignTokens): ViewStyle => ({
114
+ flex: 1,
115
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
116
+ justifyContent: 'flex-end',
117
+ });
118
+
119
+ export const getModalContainerStyles = (tokens: DesignTokens, bottomInset: number): ViewStyle => ({
120
+ backgroundColor: tokens.colors.surface,
121
+ borderTopLeftRadius: tokens.borders.radius.lg,
122
+ borderTopRightRadius: tokens.borders.radius.lg,
123
+ maxHeight: '80%',
124
+ paddingBottom: bottomInset,
125
+ });
126
+
127
+ export const getModalHeaderStyles = (tokens: DesignTokens): ViewStyle => ({
128
+ flexDirection: 'row',
129
+ justifyContent: 'space-between',
130
+ alignItems: 'center',
131
+ paddingHorizontal: tokens.spacing.md,
132
+ paddingVertical: tokens.spacing.md,
133
+ borderBottomWidth: 1,
134
+ borderBottomColor: tokens.colors.outline,
135
+ });
136
+
137
+ export const getModalTitleStyles = (tokens: DesignTokens): TextStyle => ({
138
+ fontSize: tokens.typography.titleLarge.fontSize,
139
+ fontWeight: '600',
140
+ color: tokens.colors.onSurface,
141
+ });
142
+
143
+ export const getSearchContainerStyles = (tokens: DesignTokens): ViewStyle => ({
144
+ flexDirection: 'row',
145
+ alignItems: 'center',
146
+ backgroundColor: tokens.colors.surfaceVariant,
147
+ borderRadius: tokens.borders.radius.md,
148
+ marginHorizontal: tokens.spacing.md,
149
+ marginVertical: tokens.spacing.sm,
150
+ paddingHorizontal: tokens.spacing.md,
151
+ paddingVertical: tokens.spacing.sm,
152
+ gap: tokens.spacing.sm,
153
+ });
154
+
155
+ export const getSearchInputStyles = (tokens: DesignTokens): TextStyle => ({
156
+ flex: 1,
157
+ fontSize: tokens.typography.bodyMedium.fontSize,
158
+ color: tokens.colors.onSurface,
159
+ paddingVertical: 0,
160
+ });
161
+
162
+ export const getOptionContainerStyles = (
163
+ tokens: DesignTokens,
164
+ selected: boolean,
165
+ disabled: boolean
166
+ ): ViewStyle => ({
167
+ flexDirection: 'row',
168
+ alignItems: 'center',
169
+ paddingHorizontal: tokens.spacing.md,
170
+ paddingVertical: tokens.spacing.md,
171
+ gap: tokens.spacing.md,
172
+ backgroundColor: selected ? tokens.colors.surfaceVariant : 'transparent',
173
+ opacity: disabled ? tokens.opacity.disabled : 1,
174
+ });
175
+
176
+ export const getOptionTextStyles = (tokens: DesignTokens, selected: boolean): TextStyle => ({
177
+ fontSize: tokens.typography.bodyLarge.fontSize,
178
+ color: selected ? tokens.colors.primary : tokens.colors.onSurface,
179
+ fontWeight: selected ? '600' : '400',
180
+ });
181
+
182
+ export const getOptionDescriptionStyles = (tokens: DesignTokens): TextStyle => ({
183
+ fontSize: tokens.typography.bodySmall.fontSize,
184
+ color: tokens.colors.textSecondary,
185
+ marginTop: tokens.spacing.xs,
186
+ });
187
+
188
+ export const getEmptyStateStyles = (tokens: DesignTokens): ViewStyle => ({
189
+ flex: 1,
190
+ justifyContent: 'center',
191
+ alignItems: 'center',
192
+ paddingVertical: tokens.spacing.xl,
193
+ gap: tokens.spacing.md,
194
+ });
195
+
196
+ export const getEmptyStateTextStyles = (tokens: DesignTokens): TextStyle => ({
197
+ fontSize: tokens.typography.bodyMedium.fontSize,
198
+ color: tokens.colors.textSecondary,
199
+ textAlign: 'center',
200
+ });
201
+
202
+ // Chip styles
203
+ export const getChipContainerStyles = (tokens: DesignTokens): ViewStyle => ({
204
+ flexDirection: 'row',
205
+ flexWrap: 'wrap',
206
+ gap: tokens.spacing.xs,
207
+ marginTop: tokens.spacing.sm,
208
+ });
209
+
210
+ export const getChipStyles = (tokens: DesignTokens): ViewStyle => ({
211
+ flexDirection: 'row',
212
+ alignItems: 'center',
213
+ backgroundColor: tokens.colors.surfaceVariant,
214
+ borderRadius: tokens.borders.radius.full,
215
+ paddingHorizontal: tokens.spacing.sm,
216
+ paddingVertical: tokens.spacing.xs,
217
+ gap: tokens.spacing.xs,
218
+ });
219
+
220
+ export const getChipTextStyles = (tokens: DesignTokens): TextStyle => ({
221
+ fontSize: tokens.typography.bodySmall.fontSize,
222
+ color: tokens.colors.onSurface,
223
+ });
@@ -0,0 +1,42 @@
1
+ import { ViewStyle, TextStyle } from 'react-native';
2
+ import { IconColor } 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?: IconColor;
34
+ size?: PickerSize;
35
+ modalTitle?: string;
36
+ emptyMessage?: string;
37
+ clearAccessibilityLabel?: string;
38
+ closeAccessibilityLabel?: string;
39
+ style?: ViewStyle | ViewStyle[];
40
+ labelStyle?: TextStyle | TextStyle[];
41
+ testID?: string;
42
+ }
package/src/index.ts CHANGED
@@ -1,36 +1,121 @@
1
1
  /**
2
2
  * @umituz/react-native-design-system
3
3
  * Universal design system for React Native apps
4
+ *
5
+ * Consolidated package including:
6
+ * - Atoms (primitive UI components)
7
+ * - Molecules (composite components)
8
+ * - Organisms (complex UI patterns)
9
+ * - Theme (design tokens, colors)
10
+ * - Typography (text styles)
11
+ * - Responsive (screen utilities)
4
12
  */
5
13
 
14
+ // =============================================================================
15
+ // THEME EXPORTS
16
+ // =============================================================================
17
+
6
18
  export {
19
+ useAppDesignTokens,
7
20
  useCommonStyles,
8
- } from '@umituz/react-native-design-system-theme';
21
+ useDesignSystemTheme,
22
+ useTheme,
23
+ useThemedStyles,
24
+ useThemedStyleSheet,
25
+ lightColors,
26
+ darkColors,
27
+ getColorPalette,
28
+ withAlpha,
29
+ BASE_TOKENS,
30
+ BASE_TOKENS as STATIC_TOKENS,
31
+ spacing,
32
+ typography,
33
+ borders,
34
+ createDesignTokens,
35
+ lightTheme,
36
+ darkTheme,
37
+ createResponsiveValue,
38
+ ThemeStorage,
39
+ createNavigationTheme,
40
+ applyCustomColors,
41
+ type ColorPalette,
42
+ type ThemeMode,
43
+ type CustomThemeColors,
44
+ type Spacing,
45
+ type Typography,
46
+ type Borders,
47
+ type BaseTokens,
48
+ type IconSizes,
49
+ type Opacity,
50
+ type AvatarSizes,
51
+ type ComponentSizes,
52
+ type DesignTokens,
53
+ type Theme,
54
+ type ExtendedColorPalette,
55
+ type NavigationTheme,
56
+ } from './theme';
9
57
 
10
- export {
11
- createVariants,
12
- type VariantConfig,
13
- type VariantProps,
14
- } from './presentation/utils/variants/core';
58
+ // =============================================================================
59
+ // TYPOGRAPHY EXPORTS
60
+ // =============================================================================
15
61
 
16
62
  export {
17
- createAdvancedVariants,
18
- type AdvancedVariantConfig,
19
- type CompoundVariant,
20
- } from './presentation/utils/variants/compound';
63
+ getTextColor,
64
+ getTextStyle,
65
+ isTextStyleVariant,
66
+ getAllTextStyleVariants,
67
+ clearTypographyCache,
68
+ clearColorCache,
69
+ isValidHexColor,
70
+ isValidRgbColor,
71
+ isValidHslColor,
72
+ isValidNamedColor,
73
+ isValidColor,
74
+ getColorFormat,
75
+ normalizeColor,
76
+ type TextStyleVariant,
77
+ type ColorVariant,
78
+ } from './typography';
79
+
80
+ // =============================================================================
81
+ // RESPONSIVE EXPORTS
82
+ // =============================================================================
21
83
 
22
84
  export {
23
- conditionalStyle,
24
- responsiveStyle,
25
- combineStyles,
26
- } from './presentation/utils/variants/helpers';
85
+ useResponsive,
86
+ getScreenDimensions,
87
+ isSmallPhone,
88
+ isTablet,
89
+ getResponsiveLogoSize,
90
+ getResponsiveInputHeight,
91
+ getResponsiveHorizontalPadding,
92
+ getResponsiveBottomPosition,
93
+ getResponsiveFABPosition,
94
+ getResponsiveModalMaxHeight,
95
+ getResponsiveMinModalHeight,
96
+ getResponsiveIconContainerSize,
97
+ getResponsiveGridColumns,
98
+ getResponsiveMaxWidth,
99
+ getResponsiveFontSize,
100
+ isLandscape,
101
+ getDeviceType,
102
+ getMinTouchTarget,
103
+ getSpacingMultiplier,
104
+ IOS_HIG,
105
+ PLATFORM_CONSTANTS,
106
+ isValidTouchTarget,
107
+ DeviceType,
108
+ } from './responsive';
109
+
110
+ // =============================================================================
111
+ // ATOMS EXPORTS
112
+ // =============================================================================
27
113
 
28
114
  export {
29
115
  AtomicText,
30
116
  AtomicIcon,
31
117
  AtomicButton,
32
118
  AtomicInput,
33
- AtomicCard,
34
119
  AtomicFab,
35
120
  AtomicAvatar,
36
121
  AtomicChip,
@@ -49,9 +134,6 @@ export {
49
134
  type AtomicInputVariant,
50
135
  type AtomicInputState,
51
136
  type AtomicInputSize,
52
- type AtomicCardProps,
53
- type AtomicCardVariant,
54
- type AtomicCardPadding,
55
137
  type AtomicFabProps,
56
138
  type FabSize,
57
139
  type FabVariant,
@@ -62,55 +144,50 @@ export {
62
144
  type PickerOption,
63
145
  type PickerSize,
64
146
  type AtomicDatePickerProps,
65
- } from '@umituz/react-native-design-system-atoms';
147
+ } from './atoms';
66
148
 
67
- export {
68
- ScreenLayout,
69
- } from '@umituz/react-native-design-system-organisms';
149
+ // =============================================================================
150
+ // MOLECULES EXPORTS
151
+ // =============================================================================
70
152
 
71
153
  export {
72
154
  FormField,
73
155
  ListItem,
74
156
  SearchBar,
75
- SectionCard,
76
157
  IconContainer,
77
158
  ScreenHeader,
78
- SectionHeader,
79
- SectionContainer,
80
- GridContainer,
81
159
  ConfirmationModal,
82
160
  useConfirmationModal,
83
- } from '@umituz/react-native-design-system-molecules';
161
+ } from './molecules';
162
+
163
+ // =============================================================================
164
+ // ORGANISMS EXPORTS
165
+ // =============================================================================
84
166
 
85
167
  export {
86
- useResponsive,
87
- getScreenDimensions,
88
- isSmallPhone,
89
- isTablet,
90
- getResponsiveLogoSize,
91
- getResponsiveInputHeight,
92
- getResponsiveHorizontalPadding,
93
- getResponsiveBottomPosition,
94
- getResponsiveFABPosition,
95
- getResponsiveModalMaxHeight,
96
- getResponsiveMinModalHeight,
97
- getResponsiveIconContainerSize,
98
- getResponsiveGridColumns,
99
- getResponsiveMaxWidth,
100
- getResponsiveFontSize,
101
- isLandscape,
102
- getDeviceType,
103
- getMinTouchTarget,
104
- getSpacingMultiplier,
105
- IOS_HIG,
106
- PLATFORM_CONSTANTS,
107
- isValidTouchTarget,
108
- DeviceType,
109
- } from '@umituz/react-native-design-system-responsive';
168
+ ScreenLayout,
169
+ AppHeader,
170
+ FormContainer,
171
+ } from './organisms';
172
+
173
+ // =============================================================================
174
+ // VARIANT UTILITIES
175
+ // =============================================================================
110
176
 
111
177
  export {
112
- useAppDesignTokens,
113
- STATIC_TOKENS,
114
- type DesignTokens,
115
- withAlpha,
116
- } from '@umituz/react-native-design-system-theme';
178
+ createVariants,
179
+ type VariantConfig,
180
+ type VariantProps,
181
+ } from './presentation/utils/variants/core';
182
+
183
+ export {
184
+ createAdvancedVariants,
185
+ type AdvancedVariantConfig,
186
+ type CompoundVariant,
187
+ } from './presentation/utils/variants/compound';
188
+
189
+ export {
190
+ conditionalStyle,
191
+ responsiveStyle,
192
+ combineStyles,
193
+ } from './presentation/utils/variants/helpers';
@@ -0,0 +1,42 @@
1
+ /**
2
+ * ConfirmationModal - 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
+ * <ConfirmationModal
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
+ * <ConfirmationModal
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
+ export { ConfirmationModal } from './ConfirmationModalMain';
41
+ export { useConfirmationModal } from './confirmation-modal/useConfirmationModal';
42
+ export type { ConfirmationModalProps, ConfirmationModalVariant } from './confirmation-modal/types';
@@ -0,0 +1,87 @@
1
+ /**
2
+ * ConfirmationModal Content Component
3
+ *
4
+ * Content component for confirmation modal
5
+ */
6
+
7
+ import React from 'react';
8
+ import { View, ViewStyle, StyleProp } from 'react-native';
9
+ import { useAppDesignTokens } from '../theme';
10
+ import { ConfirmationModalVariant } from './confirmation-modal/types/';
11
+ import {
12
+ getVariantConfig,
13
+ getModalContainerStyle,
14
+ getIconContainerStyle,
15
+ getTitleContainerStyle,
16
+ getMessageContainerStyle,
17
+ getButtonStyle,
18
+ } from './confirmation-modal/styles/confirmationModalStyles';
19
+ import {
20
+ ConfirmationModalIcon,
21
+ ConfirmationModalTitle,
22
+ ConfirmationModalMessage,
23
+ ConfirmationModalButtons,
24
+ } from './confirmation-modal/components';
25
+
26
+ const useConfirmButtonStyle = (
27
+ variant: ConfirmationModalVariant,
28
+ tokens: ReturnType<typeof useAppDesignTokens>
29
+ ) => {
30
+ return React.useCallback(() => {
31
+ const baseStyle = getButtonStyle();
32
+ const variantStyles = [];
33
+
34
+ if (variant === 'destructive') variantStyles.push({ backgroundColor: tokens.colors.error });
35
+ if (variant === 'warning') variantStyles.push({ backgroundColor: tokens.colors.warning });
36
+ if (variant === 'success') variantStyles.push({ backgroundColor: tokens.colors.success });
37
+
38
+ return [baseStyle, ...variantStyles];
39
+ }, [variant, tokens.colors]);
40
+ };
41
+
42
+ export const ConfirmationModalContent: React.FC<{
43
+ tokens: ReturnType<typeof useAppDesignTokens>;
44
+ variant: ConfirmationModalVariant;
45
+ title: string;
46
+ message: string;
47
+ confirmText: string;
48
+ cancelText: string;
49
+ icon?: string;
50
+ onConfirm: () => void;
51
+ onCancel: () => void;
52
+ style?: StyleProp<ViewStyle>;
53
+ testID: string;
54
+ }> = ({ tokens, variant, title, message, confirmText, cancelText, icon, onConfirm, onCancel, style, testID }) => {
55
+ const variantConfig = getVariantConfig(variant as 'default' | 'destructive' | 'warning' | 'success', tokens);
56
+ const finalIcon = icon || variantConfig.icon;
57
+ const getConfirmButtonStyle = useConfirmButtonStyle(variant, tokens);
58
+
59
+ return (
60
+ <View style={[getModalContainerStyle(tokens), style]}>
61
+ <View style={getIconContainerStyle(tokens)}>
62
+ <ConfirmationModalIcon
63
+ icon={finalIcon}
64
+ iconColor={variantConfig.iconColor}
65
+ testID={testID}
66
+ />
67
+ </View>
68
+
69
+ <View style={getTitleContainerStyle(tokens)}>
70
+ <ConfirmationModalTitle title={title} tokens={tokens} testID={testID} />
71
+ </View>
72
+
73
+ <View style={getMessageContainerStyle(tokens)}>
74
+ <ConfirmationModalMessage message={message} tokens={tokens} testID={testID} />
75
+ </View>
76
+
77
+ <ConfirmationModalButtons
78
+ confirmText={confirmText}
79
+ cancelText={cancelText}
80
+ onConfirm={onConfirm}
81
+ onCancel={onCancel}
82
+ confirmButtonStyle={getConfirmButtonStyle()}
83
+ testID={testID}
84
+ />
85
+ </View>
86
+ );
87
+ };