@umituz/react-native-design-system 1.14.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 +148 -79
  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,91 @@
1
+ /**
2
+ * ConfirmationModal Main Component
3
+ *
4
+ * Main confirmation modal component
5
+ */
6
+
7
+ import React from 'react';
8
+ import { View, Modal, TouchableOpacity } from 'react-native';
9
+ import { useAppDesignTokens } from '../theme';
10
+ import { ConfirmationModalProps } from './confirmation-modal/types/';
11
+ import {
12
+ getModalOverlayStyle,
13
+ getBackdropStyle,
14
+ } from './confirmation-modal/styles/confirmationModalStyles';
15
+ import { ConfirmationModalContent } from './ConfirmationModalContent';
16
+
17
+ const useBackdropHandler = (backdropDismissible: boolean, onCancel: () => void) => {
18
+ return React.useCallback(() => {
19
+ if (backdropDismissible) {
20
+ onCancel();
21
+ }
22
+ }, [backdropDismissible, onCancel]);
23
+ };
24
+
25
+ const ConfirmationModalBackdrop: React.FC<{
26
+ showBackdrop: boolean;
27
+ onBackdropPress: () => void;
28
+ testID: string;
29
+ }> = ({ showBackdrop, onBackdropPress, testID }) => {
30
+ if (!showBackdrop) return null;
31
+
32
+ return (
33
+ <TouchableOpacity
34
+ style={getBackdropStyle()}
35
+ activeOpacity={1}
36
+ onPress={onBackdropPress}
37
+ testID={`${testID}-backdrop`}
38
+ />
39
+ );
40
+ };
41
+
42
+ export const ConfirmationModal: React.FC<ConfirmationModalProps> = ({
43
+ visible,
44
+ title,
45
+ message,
46
+ variant = 'default',
47
+ confirmText = 'Confirm',
48
+ cancelText = 'Cancel',
49
+ icon,
50
+ onConfirm,
51
+ onCancel,
52
+ showBackdrop = true,
53
+ backdropDismissible = true,
54
+ style,
55
+ testID = 'atomic-confirmation-modal',
56
+ }) => {
57
+ const tokens = useAppDesignTokens();
58
+ const handleBackdropPress = useBackdropHandler(backdropDismissible, onCancel);
59
+
60
+ return (
61
+ <Modal
62
+ visible={visible}
63
+ transparent
64
+ onRequestClose={onCancel}
65
+ statusBarTranslucent
66
+ testID={testID}
67
+ >
68
+ <View style={getModalOverlayStyle(tokens)}>
69
+ <ConfirmationModalBackdrop
70
+ showBackdrop={showBackdrop}
71
+ onBackdropPress={handleBackdropPress}
72
+ testID={testID}
73
+ />
74
+
75
+ <ConfirmationModalContent
76
+ tokens={tokens}
77
+ variant={variant}
78
+ title={title}
79
+ message={message}
80
+ confirmText={confirmText}
81
+ cancelText={cancelText}
82
+ icon={icon}
83
+ onConfirm={onConfirm}
84
+ onCancel={onCancel}
85
+ style={style}
86
+ testID={testID}
87
+ />
88
+ </View>
89
+ </Modal>
90
+ );
91
+ };
@@ -0,0 +1,155 @@
1
+ /**
2
+ * FormField Molecule - Complete Form Input with Label and Error
3
+ *
4
+ * Combines AtomicText (label/error) + AtomicInput (field)
5
+ *
6
+ * Atomic Design Level: MOLECULE
7
+ * Composition: AtomicText + AtomicInput
8
+ */
9
+
10
+ import React from 'react';
11
+ import { View, ViewStyle } from 'react-native';
12
+ import { useAppDesignTokens } from '../theme';
13
+ import { AtomicText, AtomicInput, type AtomicInputProps } from '../atoms';
14
+
15
+ // =============================================================================
16
+ // TYPE DEFINITIONS
17
+ // =============================================================================
18
+
19
+ export interface FormFieldProps extends Omit<AtomicInputProps, 'state' | 'label'> {
20
+ label?: string;
21
+ error?: string;
22
+ helperText?: string;
23
+ required?: boolean;
24
+ containerStyle?: ViewStyle;
25
+ style?: ViewStyle; // Alias for containerStyle (for convenience)
26
+ requiredIndicator?: string;
27
+ }
28
+
29
+ // =============================================================================
30
+ // COMPONENT IMPLEMENTATION
31
+ // =============================================================================
32
+
33
+ const FormFieldLabel: React.FC<{
34
+ label?: string;
35
+ required?: boolean;
36
+ requiredIndicator?: string;
37
+ styles: ReturnType<typeof getStyles>;
38
+ }> = ({ label, required, requiredIndicator, styles }) => {
39
+ if (!label) return null;
40
+
41
+ return (
42
+ <View style={styles.labelContainer}>
43
+ <AtomicText type="labelMedium" color="primary" style={styles.label}>
44
+ {label}
45
+ </AtomicText>
46
+ {required && (
47
+ <AtomicText type="labelMedium" color="error">
48
+ {requiredIndicator}
49
+ </AtomicText>
50
+ )}
51
+ </View>
52
+ );
53
+ };
54
+
55
+ const FormFieldMessage: React.FC<{
56
+ error?: string;
57
+ helperText?: string;
58
+ styles: ReturnType<typeof getStyles>;
59
+ }> = ({ error, helperText, styles }) => {
60
+ if (error) {
61
+ return (
62
+ <AtomicText
63
+ type="bodySmall"
64
+ color="error"
65
+ style={styles.errorText}
66
+ >
67
+ {error}
68
+ </AtomicText>
69
+ );
70
+ }
71
+
72
+ if (helperText) {
73
+ return (
74
+ <AtomicText
75
+ type="bodySmall"
76
+ color="secondary"
77
+ style={styles.helperText}
78
+ >
79
+ {helperText}
80
+ </AtomicText>
81
+ );
82
+ }
83
+
84
+ return null;
85
+ };
86
+
87
+ export const FormField: React.FC<FormFieldProps> = ({
88
+ label,
89
+ error,
90
+ helperText,
91
+ required = false,
92
+ containerStyle,
93
+ style,
94
+ requiredIndicator = ' *',
95
+ ...inputProps
96
+ }) => {
97
+ const tokens = useAppDesignTokens();
98
+ const inputState = error ? 'error' : 'default';
99
+ const styles = getStyles(tokens);
100
+
101
+ return (
102
+ <View style={[styles.container, containerStyle || style]}>
103
+ <FormFieldLabel
104
+ label={label}
105
+ required={required}
106
+ requiredIndicator={requiredIndicator}
107
+ styles={styles}
108
+ />
109
+
110
+ <AtomicInput
111
+ {...inputProps}
112
+ label={label || ''}
113
+ state={inputState}
114
+ />
115
+
116
+ <FormFieldMessage
117
+ error={error}
118
+ helperText={helperText}
119
+ styles={styles}
120
+ />
121
+ </View>
122
+ );
123
+ };
124
+
125
+ // =============================================================================
126
+ // STYLES
127
+ // =============================================================================
128
+
129
+ const getStyles = (tokens: ReturnType<typeof useAppDesignTokens>) => ({
130
+ container: {
131
+ marginBottom: tokens.spacing.md,
132
+ } as ViewStyle,
133
+ labelContainer: {
134
+ flexDirection: 'row',
135
+ marginBottom: tokens.spacing.sm,
136
+ } as ViewStyle,
137
+ label: {
138
+ fontWeight: tokens.typography.labelMedium.fontWeight,
139
+ color: tokens.colors.textPrimary,
140
+ } as ViewStyle,
141
+ inputError: {
142
+ borderColor: tokens.colors.error,
143
+ } as ViewStyle,
144
+ errorText: {
145
+ marginTop: tokens.spacing.xs,
146
+ } as ViewStyle,
147
+ helperText: {
148
+ marginTop: tokens.spacing.xs,
149
+ } as ViewStyle,
150
+ });
151
+
152
+ // =============================================================================
153
+ // EXPORTS
154
+ // =============================================================================
155
+
@@ -0,0 +1,79 @@
1
+ /**
2
+ * IconContainer Molecule Component
3
+ *
4
+ * Standardized icon container with consistent sizing and styling.
5
+ * Used throughout app for icon displays in lists, cards, and settings.
6
+ *
7
+ * Features:
8
+ * - Consistent sizing system
9
+ * - Optional background circle
10
+ * - Optional gradient background
11
+ * - Theme-aware colors
12
+ * - Accessibility support
13
+ *
14
+ * Atomic Design: Molecule (View + Icon)
15
+ */
16
+
17
+ import React from 'react';
18
+ import { View, StyleSheet } from 'react-native';
19
+ import { useAppDesignTokens } from '../theme';
20
+
21
+ interface IconContainerProps {
22
+ icon: React.ReactNode;
23
+ size?: 'sm' | 'md' | 'lg' | 'xl';
24
+ backgroundColor?: string;
25
+ withBorder?: boolean;
26
+ borderColor?: string;
27
+ style?: object;
28
+ testID?: string;
29
+ }
30
+
31
+ const getSizeMap = (tokens: ReturnType<typeof useAppDesignTokens>) => ({
32
+ sm: tokens.iconSizes.sm,
33
+ md: tokens.iconSizes.md,
34
+ lg: tokens.iconSizes.lg,
35
+ xl: tokens.iconSizes.xl,
36
+ });
37
+
38
+ export const IconContainer: React.FC<IconContainerProps> = ({
39
+ icon,
40
+ size = 'md',
41
+ backgroundColor,
42
+ withBorder = false,
43
+ borderColor,
44
+ style,
45
+ testID,
46
+ }) => {
47
+ const tokens = useAppDesignTokens();
48
+ const sizeMap = getSizeMap(tokens);
49
+ const containerSize = sizeMap[size];
50
+ const borderRadius = containerSize / 2;
51
+
52
+ const containerStyle = [
53
+ styles.container,
54
+ {
55
+ width: containerSize,
56
+ height: containerSize,
57
+ borderRadius,
58
+ backgroundColor: backgroundColor || tokens.colors.surfaceVariant,
59
+ },
60
+ withBorder && {
61
+ borderWidth: 1,
62
+ borderColor: borderColor || tokens.colors.border,
63
+ },
64
+ style,
65
+ ];
66
+
67
+ return (
68
+ <View style={containerStyle} testID={testID}>
69
+ {icon}
70
+ </View>
71
+ );
72
+ };
73
+
74
+ const styles = StyleSheet.create({
75
+ container: {
76
+ alignItems: 'center',
77
+ justifyContent: 'center',
78
+ },
79
+ });
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { TouchableOpacity, View } from 'react-native';
3
+ import { useAppDesignTokens } from '../theme';
4
+ import { AtomicText, AtomicIcon } from '../atoms';
5
+ import { ListItemProps } from './listitem/types';
6
+ import { getListItemStyles } from './listitem/styles/listItemStyles';
7
+
8
+ export type { ListItemProps };
9
+
10
+ export const ListItem: React.FC<ListItemProps> = ({
11
+ title, subtitle, leftIcon, rightIcon, onPress, disabled = false, style,
12
+ }) => {
13
+ const tokens = useAppDesignTokens();
14
+ const listItemStyles = getListItemStyles(tokens);
15
+ const Component = onPress ? TouchableOpacity : View;
16
+
17
+ return (
18
+ <Component style={[listItemStyles.container, disabled ? listItemStyles.disabled : undefined, style]} onPress={onPress} disabled={disabled} activeOpacity={0.7}>
19
+ {leftIcon && (
20
+ <View style={listItemStyles.iconContainer}>
21
+ <AtomicIcon name={leftIcon} color={disabled ? 'surfaceVariant' : 'primary'} />
22
+ </View>
23
+ )}
24
+ <View style={listItemStyles.content}>
25
+ <AtomicText type="bodyLarge" color={disabled ? 'surfaceVariant' : 'onSurface'} numberOfLines={1}>{title}</AtomicText>
26
+ {subtitle && <AtomicText type="bodySmall" color="surfaceVariant" numberOfLines={2} style={listItemStyles.subtitle}>{subtitle}</AtomicText>}
27
+ </View>
28
+ {rightIcon && onPress && (
29
+ <View style={listItemStyles.iconContainer}>
30
+ <AtomicIcon name={rightIcon} color="surfaceVariant" />
31
+ </View>
32
+ )}
33
+ </Component>
34
+ );
35
+ };
@@ -0,0 +1,171 @@
1
+ /**
2
+ * ScreenHeader Component
3
+ *
4
+ * Reusable screen header with consistent back button placement
5
+ *
6
+ * Features:
7
+ * - Top-left back button (configurable icon)
8
+ * - Centered title text
9
+ * - Optional right action button
10
+ * - Consistent spacing and layout
11
+ * - Theme-aware styling
12
+ * - Fully configurable for general purpose use
13
+ */
14
+
15
+ import React from 'react';
16
+ import { View, TouchableOpacity, ViewStyle } from 'react-native';
17
+ import { AtomicIcon, AtomicText } from '../atoms';
18
+ import { useAppDesignTokens } from '../theme';
19
+
20
+ export interface ScreenHeaderProps {
21
+ /** Screen title (centered) */
22
+ title: string;
23
+
24
+ /** Optional right action button */
25
+ rightAction?: React.ReactNode;
26
+
27
+ /** Custom back button action (required if back button is visible) */
28
+ onBackPress?: () => void;
29
+
30
+ /** Hide back button (rare cases only) */
31
+ hideBackButton?: boolean;
32
+
33
+ /** Additional header style */
34
+ style?: ViewStyle;
35
+
36
+ /** Test ID for E2E testing */
37
+ testID?: string;
38
+
39
+ /** Custom back button icon name */
40
+ backIconName?: string;
41
+
42
+ /** Custom back button icon color */
43
+ backIconColor: 'primary' | 'secondary' | 'error' | 'warning' | 'success' | 'surfaceVariant';
44
+ }
45
+
46
+ /**
47
+ * ScreenHeader Component
48
+ *
49
+ * @example
50
+ * // Basic usage (most common)
51
+ * <ScreenHeader title="Settings" />
52
+ *
53
+ * @example
54
+ * // With right action
55
+ * <ScreenHeader
56
+ * title="Edit Profile"
57
+ * rightAction={<TouchableOpacity onPress={handleSave}><Text>Save</Text></TouchableOpacity>}
58
+ * />
59
+ *
60
+ * @example
61
+ * // Custom back action
62
+ * <ScreenHeader
63
+ * title="Unsaved Changes"
64
+ * onBackPress={handleUnsavedChanges}
65
+ * />
66
+ */
67
+ const ScreenHeaderBackButton: React.FC<{
68
+ hideBackButton?: boolean;
69
+ onBackPress?: () => void;
70
+ backIconName?: string;
71
+ backIconColor?: 'primary' | 'secondary' | 'error' | 'warning' | 'success' | 'surfaceVariant';
72
+ testID?: string;
73
+ }> = ({ hideBackButton, onBackPress, backIconName, backIconColor, testID }) => {
74
+ const handleBackPress = React.useCallback(() => {
75
+ if (onBackPress) {
76
+ onBackPress();
77
+ } else {
78
+ __DEV__ && console.warn('ScreenHeader: onBackPress is required when back button is visible');
79
+ }
80
+ }, [onBackPress]);
81
+
82
+ if (hideBackButton) return null;
83
+
84
+ return (
85
+ <View style={{ width: 40, alignItems: 'flex-start' }}>
86
+ <TouchableOpacity
87
+ onPress={handleBackPress}
88
+ hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
89
+ testID={`${testID}-back-button`}
90
+ >
91
+ <AtomicIcon name={backIconName || 'ArrowLeft'} color={backIconColor} />
92
+ </TouchableOpacity>
93
+ </View>
94
+ );
95
+ };
96
+
97
+ const ScreenHeaderTitle: React.FC<{
98
+ title: string;
99
+ tokens: ReturnType<typeof useAppDesignTokens>;
100
+ testID?: string;
101
+ }> = ({ title, tokens, testID }) => (
102
+ <View style={{ flex: 1, alignItems: 'center', paddingHorizontal: tokens.spacing.sm }}>
103
+ <AtomicText
104
+ type="headlineMedium"
105
+ style={[
106
+ {
107
+ fontWeight: tokens.typography.bold,
108
+ textAlign: 'center',
109
+ color: tokens.colors.textPrimary,
110
+ }
111
+ ]}
112
+ numberOfLines={1}
113
+ testID={`${testID}-title`}
114
+ >
115
+ {title}
116
+ </AtomicText>
117
+ </View>
118
+ );
119
+
120
+ const ScreenHeaderRightAction: React.FC<{
121
+ rightAction?: React.ReactNode;
122
+ }> = ({ rightAction }) => (
123
+ <View style={{ width: 40, alignItems: 'flex-start' }}>
124
+ {rightAction || <View style={{ width: 40 }} />}
125
+ </View>
126
+ );
127
+
128
+ export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
129
+ title,
130
+ rightAction,
131
+ onBackPress,
132
+ hideBackButton = false,
133
+ style,
134
+ testID = 'screen-header',
135
+ backIconName = 'ArrowLeft',
136
+ backIconColor = 'primary',
137
+ }) => {
138
+ const tokens = useAppDesignTokens();
139
+
140
+ const headerStyle = React.useMemo(() => [
141
+ {
142
+ flexDirection: 'row' as const,
143
+ alignItems: 'center' as const,
144
+ justifyContent: 'space-between' as const,
145
+ paddingHorizontal: tokens.spacing.screenPadding,
146
+ paddingVertical: tokens.spacing.md,
147
+ borderBottomWidth: 0.5,
148
+ backgroundColor: tokens.colors.backgroundPrimary,
149
+ borderBottomColor: tokens.colors.border,
150
+ },
151
+ style
152
+ ], [tokens, style]);
153
+
154
+ return (
155
+ <View style={headerStyle} testID={testID}>
156
+ <ScreenHeaderBackButton
157
+ hideBackButton={hideBackButton}
158
+ onBackPress={onBackPress}
159
+ backIconName={backIconName}
160
+ backIconColor={backIconColor}
161
+ testID={testID}
162
+ />
163
+
164
+ <ScreenHeaderTitle title={title} tokens={tokens} testID={testID} />
165
+
166
+ <ScreenHeaderRightAction rightAction={rightAction} />
167
+ </View>
168
+ );
169
+ };
170
+
171
+ export default ScreenHeader;