@umituz/react-native-design-system 4.23.66 → 4.23.68
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/package.json +1 -1
- package/src/atoms/icon/AtomicIcon.tsx +41 -112
- package/src/atoms/icon/components/iconRenderer.tsx +118 -0
- package/src/atoms/icon/utils/iconUtils.ts +94 -0
- package/src/exception/presentation/components/ErrorBoundary.tsx +2 -2
- package/src/molecules/alerts/AlertToast.tsx +163 -192
- package/src/molecules/alerts/utils/alertToastHelpers.ts +70 -0
- package/src/services/api/ApiClient.ts +242 -0
- package/src/services/api/index.ts +9 -0
- package/src/services/api/types/ApiTypes.ts +50 -0
- package/src/services/api/utils/requestBuilder.ts +92 -0
- package/src/services/api/utils/responseHandler.ts +130 -0
- package/src/tanstack/domain/repositories/BaseRepository.ts +16 -72
- package/src/tanstack/domain/repositories/helpers/repositoryHelpers.ts +58 -0
- package/src/tanstack/domain/repositories/mixins/repositoryInvalidationMethods.ts +101 -0
- package/src/tanstack/domain/repositories/mixins/repositoryQueryMethods.ts +102 -0
- package/src/tanstack/presentation/hooks/types/prefetchTypes.ts +33 -0
- package/src/tanstack/presentation/hooks/usePrefetch.ts +8 -28
- package/src/tanstack/presentation/hooks/utils/prefetchLogger.ts +27 -0
- package/src/utils/colorMapper.ts +193 -0
- package/src/utils/formatHelper.ts +16 -0
- package/src/utils/formatters/dateFormatter.ts +64 -0
- package/src/utils/formatters/numberFormatter.ts +130 -0
- package/src/utils/formatters/stringFormatter.ts +190 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/styleComposer.ts +94 -0
- package/src/utils/validationHelper.ts +16 -0
- package/src/utils/validators/dataValidators.ts +111 -0
- package/src/utils/validators/numericValidators.ts +106 -0
- package/src/utils/validators/stringValidators.ts +85 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.68",
|
|
4
4
|
"description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive, safe area, exception, infinite scroll, UUID, image, timezone, offline, onboarding, and loading utilities",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -20,19 +20,27 @@
|
|
|
20
20
|
* <AtomicIcon name="favorite" size="md" color="primary" />
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import React from
|
|
24
|
-
import {
|
|
25
|
-
import
|
|
26
|
-
import {
|
|
27
|
-
import { useIconRenderer, type IconRenderProps } from "./iconStore";
|
|
23
|
+
import React from 'react';
|
|
24
|
+
import { StyleProp, ViewStyle } from 'react-native';
|
|
25
|
+
import { useAppDesignTokens } from '../../theme';
|
|
26
|
+
import { useIconRenderer } from './iconStore';
|
|
28
27
|
import {
|
|
29
28
|
type IconSize as BaseIconSize,
|
|
30
29
|
type IconColor,
|
|
31
|
-
} from
|
|
30
|
+
} from './AtomicIcon.types';
|
|
31
|
+
import {
|
|
32
|
+
calculateIconSize,
|
|
33
|
+
calculateIconColor,
|
|
34
|
+
} from './utils/iconUtils';
|
|
35
|
+
import {
|
|
36
|
+
renderSvgIcon,
|
|
37
|
+
renderWithBackground,
|
|
38
|
+
buildIconRenderProps,
|
|
39
|
+
} from './components/iconRenderer';
|
|
32
40
|
|
|
33
41
|
export type IconSize = BaseIconSize;
|
|
34
42
|
export type IconName = string;
|
|
35
|
-
export type { IconColor
|
|
43
|
+
export type { IconColor };
|
|
36
44
|
|
|
37
45
|
export interface AtomicIconProps {
|
|
38
46
|
/** Icon name - interpreted by the app's icon renderer */
|
|
@@ -61,44 +69,20 @@ export interface AtomicIconProps {
|
|
|
61
69
|
style?: StyleProp<ViewStyle>;
|
|
62
70
|
}
|
|
63
71
|
|
|
64
|
-
const getSemanticColor = (
|
|
65
|
-
color: IconColor,
|
|
66
|
-
tokens: ReturnType<typeof useAppDesignTokens>
|
|
67
|
-
): string => {
|
|
68
|
-
const colorMap: Record<IconColor, string> = {
|
|
69
|
-
primary: tokens.colors.primary,
|
|
70
|
-
secondary: tokens.colors.secondary,
|
|
71
|
-
success: tokens.colors.success,
|
|
72
|
-
warning: tokens.colors.warning,
|
|
73
|
-
error: tokens.colors.error,
|
|
74
|
-
info: tokens.colors.info,
|
|
75
|
-
onSurface: tokens.colors.onSurface,
|
|
76
|
-
surfaceVariant: tokens.colors.surfaceVariant,
|
|
77
|
-
onPrimary: tokens.colors.onPrimary,
|
|
78
|
-
onSecondary: tokens.colors.onSecondary,
|
|
79
|
-
textInverse: tokens.colors.textInverse,
|
|
80
|
-
textPrimary: tokens.colors.textPrimary,
|
|
81
|
-
textSecondary: tokens.colors.textSecondary,
|
|
82
|
-
textTertiary: tokens.colors.textTertiary,
|
|
83
|
-
onSurfaceVariant: tokens.colors.onSurfaceVariant,
|
|
84
|
-
};
|
|
85
|
-
return colorMap[color];
|
|
86
|
-
};
|
|
87
|
-
|
|
88
72
|
/**
|
|
89
73
|
* Agnostic icon component - requires iconRenderer in DesignSystemProvider
|
|
90
74
|
*/
|
|
91
75
|
export const AtomicIcon: React.FC<AtomicIconProps> = React.memo(
|
|
92
76
|
({
|
|
93
77
|
name,
|
|
94
|
-
size =
|
|
78
|
+
size = 'md',
|
|
95
79
|
customSize,
|
|
96
80
|
color,
|
|
97
81
|
customColor,
|
|
98
82
|
withBackground = false,
|
|
99
83
|
backgroundColor,
|
|
100
84
|
svgPath,
|
|
101
|
-
svgViewBox =
|
|
85
|
+
svgViewBox = '0 0 24 24',
|
|
102
86
|
accessibilityLabel,
|
|
103
87
|
testID,
|
|
104
88
|
style,
|
|
@@ -106,34 +90,19 @@ export const AtomicIcon: React.FC<AtomicIconProps> = React.memo(
|
|
|
106
90
|
const tokens = useAppDesignTokens();
|
|
107
91
|
const iconRenderer = useIconRenderer();
|
|
108
92
|
|
|
109
|
-
// Calculate size
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
const sizeInPixels: number =
|
|
113
|
-
typeof baseSize === "number"
|
|
114
|
-
? baseSize * tokens.spacingMultiplier
|
|
115
|
-
: iconSizesMap[baseSize] ?? iconSizesMap["md"] ?? 24;
|
|
116
|
-
|
|
117
|
-
// Calculate color
|
|
118
|
-
const iconColor = customColor
|
|
119
|
-
? customColor
|
|
120
|
-
: color
|
|
121
|
-
? getSemanticColor(color, tokens)
|
|
122
|
-
: tokens.colors.textPrimary;
|
|
93
|
+
// Calculate size and color using utility functions
|
|
94
|
+
const sizeInPixels = calculateIconSize(size, customSize, tokens);
|
|
95
|
+
const iconColor = calculateIconColor(customColor, color, tokens);
|
|
123
96
|
|
|
124
97
|
// SVG path rendering (built-in, no external dependency)
|
|
125
98
|
if (svgPath) {
|
|
126
|
-
const svgElement = (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
accessibilityLabel={accessibilityLabel}
|
|
134
|
-
>
|
|
135
|
-
<Path d={svgPath} fill={iconColor} />
|
|
136
|
-
</Svg>
|
|
99
|
+
const svgElement = renderSvgIcon(
|
|
100
|
+
svgPath,
|
|
101
|
+
svgViewBox,
|
|
102
|
+
sizeInPixels,
|
|
103
|
+
iconColor,
|
|
104
|
+
testID,
|
|
105
|
+
accessibilityLabel
|
|
137
106
|
);
|
|
138
107
|
|
|
139
108
|
if (withBackground) {
|
|
@@ -154,27 +123,27 @@ export const AtomicIcon: React.FC<AtomicIconProps> = React.memo(
|
|
|
154
123
|
if (!iconRenderer) {
|
|
155
124
|
if (__DEV__) {
|
|
156
125
|
console.warn(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
126
|
+
'[DesignSystem] AtomicIcon requires an iconRenderer in DesignSystemProvider.\n' +
|
|
127
|
+
'Example:\n' +
|
|
128
|
+
'<DesignSystemProvider\n' +
|
|
160
129
|
' iconRenderer={({ name, size, color }) => (\n' +
|
|
161
130
|
' <YourIconLibrary name={name} size={size} color={color} />\n' +
|
|
162
|
-
|
|
163
|
-
|
|
131
|
+
' )}\n' +
|
|
132
|
+
'>'
|
|
164
133
|
);
|
|
165
134
|
}
|
|
166
135
|
return null;
|
|
167
136
|
}
|
|
168
137
|
|
|
169
|
-
// Build render props
|
|
170
|
-
const renderProps
|
|
171
|
-
name
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
style
|
|
138
|
+
// Build render props and render icon
|
|
139
|
+
const renderProps = buildIconRenderProps(
|
|
140
|
+
name || '',
|
|
141
|
+
sizeInPixels,
|
|
142
|
+
iconColor,
|
|
143
|
+
style,
|
|
175
144
|
testID,
|
|
176
|
-
accessibilityLabel
|
|
177
|
-
|
|
145
|
+
accessibilityLabel
|
|
146
|
+
);
|
|
178
147
|
|
|
179
148
|
const iconElement = iconRenderer(renderProps);
|
|
180
149
|
|
|
@@ -193,44 +162,4 @@ export const AtomicIcon: React.FC<AtomicIconProps> = React.memo(
|
|
|
193
162
|
}
|
|
194
163
|
);
|
|
195
164
|
|
|
196
|
-
AtomicIcon.displayName =
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Helper to render icon with circular background
|
|
200
|
-
*/
|
|
201
|
-
function renderWithBackground(
|
|
202
|
-
iconElement: React.ReactNode,
|
|
203
|
-
sizeInPixels: number,
|
|
204
|
-
bgColor: string,
|
|
205
|
-
style: StyleProp<ViewStyle> | undefined,
|
|
206
|
-
testID: string | undefined,
|
|
207
|
-
accessibilityLabel: string | undefined
|
|
208
|
-
): React.ReactElement {
|
|
209
|
-
const containerSize = sizeInPixels + 16;
|
|
210
|
-
|
|
211
|
-
return (
|
|
212
|
-
<View
|
|
213
|
-
style={[
|
|
214
|
-
styles.backgroundContainer,
|
|
215
|
-
{
|
|
216
|
-
width: containerSize,
|
|
217
|
-
height: containerSize,
|
|
218
|
-
borderRadius: containerSize / 2,
|
|
219
|
-
backgroundColor: bgColor,
|
|
220
|
-
},
|
|
221
|
-
style,
|
|
222
|
-
]}
|
|
223
|
-
testID={testID}
|
|
224
|
-
accessibilityLabel={accessibilityLabel}
|
|
225
|
-
>
|
|
226
|
-
{iconElement}
|
|
227
|
-
</View>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const styles = StyleSheet.create({
|
|
232
|
-
backgroundContainer: {
|
|
233
|
-
justifyContent: "center",
|
|
234
|
-
alignItems: "center",
|
|
235
|
-
},
|
|
236
|
-
});
|
|
165
|
+
AtomicIcon.displayName = 'AtomicIcon';
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon Renderer Components
|
|
3
|
+
* SVG rendering and background rendering logic
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
|
8
|
+
import Svg, { Path } from 'react-native-svg';
|
|
9
|
+
import type { IconRenderProps } from '../iconStore';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Renders an SVG icon from path data
|
|
13
|
+
*
|
|
14
|
+
* @param svgPath - SVG path string
|
|
15
|
+
* @param svgViewBox - SVG viewBox attribute
|
|
16
|
+
* @param size - Icon size in pixels
|
|
17
|
+
* @param color - Icon color
|
|
18
|
+
* @param testID - Test ID for testing
|
|
19
|
+
* @param accessibilityLabel - Accessibility label
|
|
20
|
+
* @returns SVG element
|
|
21
|
+
*/
|
|
22
|
+
export function renderSvgIcon(
|
|
23
|
+
svgPath: string,
|
|
24
|
+
svgViewBox: string,
|
|
25
|
+
size: number,
|
|
26
|
+
color: string,
|
|
27
|
+
testID?: string,
|
|
28
|
+
accessibilityLabel?: string
|
|
29
|
+
): React.ReactElement {
|
|
30
|
+
return (
|
|
31
|
+
<Svg
|
|
32
|
+
viewBox={svgViewBox}
|
|
33
|
+
width={size}
|
|
34
|
+
height={size}
|
|
35
|
+
testID={testID}
|
|
36
|
+
accessibilityLabel={accessibilityLabel}
|
|
37
|
+
>
|
|
38
|
+
<Path d={svgPath} fill={color} />
|
|
39
|
+
</Svg>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Renders an icon with a circular background
|
|
45
|
+
*
|
|
46
|
+
* @param iconElement - Icon element to wrap
|
|
47
|
+
* @param size - Icon size in pixels
|
|
48
|
+
* @param backgroundColor - Background color
|
|
49
|
+
* @param style - Additional styles
|
|
50
|
+
* @param testID - Test ID for testing
|
|
51
|
+
* @param accessibilityLabel - Accessibility label
|
|
52
|
+
* @returns Wrapped icon with background
|
|
53
|
+
*/
|
|
54
|
+
export function renderWithBackground(
|
|
55
|
+
iconElement: React.ReactNode,
|
|
56
|
+
size: number,
|
|
57
|
+
backgroundColor: string,
|
|
58
|
+
style?: StyleProp<ViewStyle>,
|
|
59
|
+
testID?: string,
|
|
60
|
+
accessibilityLabel?: string
|
|
61
|
+
): React.ReactElement {
|
|
62
|
+
const containerSize = size + 16;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<View
|
|
66
|
+
style={[
|
|
67
|
+
styles.backgroundContainer,
|
|
68
|
+
{
|
|
69
|
+
width: containerSize,
|
|
70
|
+
height: containerSize,
|
|
71
|
+
borderRadius: containerSize / 2,
|
|
72
|
+
backgroundColor,
|
|
73
|
+
},
|
|
74
|
+
style,
|
|
75
|
+
]}
|
|
76
|
+
testID={testID}
|
|
77
|
+
accessibilityLabel={accessibilityLabel}
|
|
78
|
+
>
|
|
79
|
+
{iconElement}
|
|
80
|
+
</View>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Builds render props for custom icon renderer
|
|
86
|
+
*
|
|
87
|
+
* @param name - Icon name
|
|
88
|
+
* @param size - Icon size in pixels
|
|
89
|
+
* @param color - Icon color
|
|
90
|
+
* @param style - Additional styles
|
|
91
|
+
* @param testID - Test ID
|
|
92
|
+
* @param accessibilityLabel - Accessibility label
|
|
93
|
+
* @returns Icon render props
|
|
94
|
+
*/
|
|
95
|
+
export function buildIconRenderProps(
|
|
96
|
+
name: string,
|
|
97
|
+
size: number,
|
|
98
|
+
color: string,
|
|
99
|
+
style?: StyleProp<ViewStyle>,
|
|
100
|
+
testID?: string,
|
|
101
|
+
accessibilityLabel?: string
|
|
102
|
+
): IconRenderProps {
|
|
103
|
+
return {
|
|
104
|
+
name,
|
|
105
|
+
size,
|
|
106
|
+
color,
|
|
107
|
+
style: style as StyleProp<ViewStyle>,
|
|
108
|
+
testID,
|
|
109
|
+
accessibilityLabel,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const styles = StyleSheet.create({
|
|
114
|
+
backgroundContainer: {
|
|
115
|
+
justifyContent: 'center',
|
|
116
|
+
alignItems: 'center',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon Utility Functions
|
|
3
|
+
* Helper functions for icon color and size calculations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { IconColor } from '../AtomicIcon.types';
|
|
7
|
+
import type { DesignTokens } from '../../../theme';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Maps semantic color names to actual color values from tokens
|
|
11
|
+
*
|
|
12
|
+
* @param color - Semantic color name
|
|
13
|
+
* @param tokens - Design tokens
|
|
14
|
+
* @returns Hex color string
|
|
15
|
+
*/
|
|
16
|
+
export function getSemanticColor(
|
|
17
|
+
color: IconColor,
|
|
18
|
+
tokens: DesignTokens
|
|
19
|
+
): string {
|
|
20
|
+
const colorMap: Record<IconColor, string> = {
|
|
21
|
+
primary: tokens.colors.primary,
|
|
22
|
+
secondary: tokens.colors.secondary,
|
|
23
|
+
success: tokens.colors.success,
|
|
24
|
+
warning: tokens.colors.warning,
|
|
25
|
+
error: tokens.colors.error,
|
|
26
|
+
info: tokens.colors.info,
|
|
27
|
+
onSurface: tokens.colors.onSurface,
|
|
28
|
+
surfaceVariant: tokens.colors.surfaceVariant,
|
|
29
|
+
onPrimary: tokens.colors.onPrimary,
|
|
30
|
+
onSecondary: tokens.colors.onSecondary,
|
|
31
|
+
textInverse: tokens.colors.textInverse,
|
|
32
|
+
textPrimary: tokens.colors.textPrimary,
|
|
33
|
+
textSecondary: tokens.colors.textSecondary,
|
|
34
|
+
textTertiary: tokens.colors.textTertiary,
|
|
35
|
+
onSurfaceVariant: tokens.colors.onSurfaceVariant,
|
|
36
|
+
};
|
|
37
|
+
return colorMap[color];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Calculates icon size in pixels
|
|
42
|
+
*
|
|
43
|
+
* @param size - Size preset or custom size value
|
|
44
|
+
* @param customSize - Custom size in pixels (overrides size)
|
|
45
|
+
* @param tokens - Design tokens
|
|
46
|
+
* @returns Size in pixels
|
|
47
|
+
*/
|
|
48
|
+
export function calculateIconSize(
|
|
49
|
+
size: string | number,
|
|
50
|
+
customSize: number | undefined,
|
|
51
|
+
tokens: DesignTokens
|
|
52
|
+
): number {
|
|
53
|
+
const baseSize = customSize ?? size;
|
|
54
|
+
const iconSizesMap = tokens.iconSizes as Record<string, number>;
|
|
55
|
+
|
|
56
|
+
return typeof baseSize === 'number'
|
|
57
|
+
? baseSize * tokens.spacingMultiplier
|
|
58
|
+
: iconSizesMap[baseSize] ?? iconSizesMap['md'] ?? 24;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Calculates icon color
|
|
63
|
+
*
|
|
64
|
+
* @param customColor - Custom color override
|
|
65
|
+
* @param semanticColor - Semantic color from theme
|
|
66
|
+
* @param tokens - Design tokens
|
|
67
|
+
* @returns Hex color string
|
|
68
|
+
*/
|
|
69
|
+
export function calculateIconColor(
|
|
70
|
+
customColor: string | undefined,
|
|
71
|
+
semanticColor: IconColor | undefined,
|
|
72
|
+
tokens: DesignTokens
|
|
73
|
+
): string {
|
|
74
|
+
if (customColor) {
|
|
75
|
+
return customColor;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (semanticColor) {
|
|
79
|
+
return getSemanticColor(semanticColor, tokens);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return tokens.colors.textPrimary;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Calculates container size for icon with background
|
|
87
|
+
*
|
|
88
|
+
* @param iconSize - Icon size in pixels
|
|
89
|
+
* @param padding - Padding around icon (default: 16)
|
|
90
|
+
* @returns Container size
|
|
91
|
+
*/
|
|
92
|
+
export function calculateContainerSize(iconSize: number, padding: number = 16): number {
|
|
93
|
+
return iconSize + padding;
|
|
94
|
+
}
|
|
@@ -36,7 +36,7 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
|
|
40
40
|
// Log error to exception service
|
|
41
41
|
exceptionService.handleFatalError(error, {
|
|
42
42
|
componentStack: errorInfo.componentStack ?? undefined,
|
|
@@ -56,7 +56,7 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
56
56
|
});
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
render(): ReactNode {
|
|
60
60
|
if (this.state.hasError) {
|
|
61
61
|
if (this.props.fallback) {
|
|
62
62
|
return this.props.fallback;
|