@umituz/react-native-design-system 4.27.2 → 4.27.3
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/card/AtomicCard.tsx +2 -2
- package/src/molecules/SearchBar/SearchBar.tsx +5 -2
- package/src/molecules/calendar/infrastructure/services/CalendarService.ts +15 -2
- package/src/tanstack/infrastructure/monitoring/DevMonitor.ts +10 -0
- package/src/utils/hooks/useAsyncOperation.ts +8 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-design-system",
|
|
3
|
-
"version": "4.27.
|
|
3
|
+
"version": "4.27.3",
|
|
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 - TanStack persistence and expo-image-manipulator now lazy loaded",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -182,13 +182,13 @@ const AtomicCardComponent: React.FC<AtomicCardProps> = ({
|
|
|
182
182
|
|
|
183
183
|
const paddingValue = getCardPadding(padding, tokens);
|
|
184
184
|
|
|
185
|
-
const containerStyle = [
|
|
185
|
+
const containerStyle = useMemo(() => [
|
|
186
186
|
cardStyles.container,
|
|
187
187
|
{ borderRadius: tokens.borders.radius.lg },
|
|
188
188
|
variantStyles.container,
|
|
189
189
|
selected && { borderColor: tokens.colors.primary, borderWidth: 2 },
|
|
190
190
|
style,
|
|
191
|
-
];
|
|
191
|
+
], [tokens.borders.radius.lg, variantStyles.container, selected, tokens.colors.primary, style]);
|
|
192
192
|
|
|
193
193
|
const handlePress = (event: GestureResponderEvent) => {
|
|
194
194
|
if (!disabled && onPress) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback } from 'react';
|
|
1
|
+
import React, { useCallback, useMemo } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
TextInput,
|
|
@@ -28,6 +28,9 @@ export const SearchBar: React.FC<SearchBarProps> = ({
|
|
|
28
28
|
const searchIcon = useIconName('search');
|
|
29
29
|
const closeCircleIcon = useIconName('closeCircle');
|
|
30
30
|
|
|
31
|
+
// Memoize hitSlop to prevent object creation on every render
|
|
32
|
+
const hitSlop = useMemo(() => ({ top: 10, bottom: 10, left: 10, right: 10 }), []);
|
|
33
|
+
|
|
31
34
|
const handleClear = useCallback(() => {
|
|
32
35
|
onChangeText('');
|
|
33
36
|
onClear?.();
|
|
@@ -94,7 +97,7 @@ export const SearchBar: React.FC<SearchBarProps> = ({
|
|
|
94
97
|
<TouchableOpacity
|
|
95
98
|
onPress={handleClear}
|
|
96
99
|
style={styles.clearButton}
|
|
97
|
-
hitSlop={
|
|
100
|
+
hitSlop={hitSlop}
|
|
98
101
|
accessibilityRole="button"
|
|
99
102
|
accessibilityLabel="Clear search"
|
|
100
103
|
>
|
|
@@ -21,6 +21,9 @@ import { DateUtilities } from '../utils/DateUtilities';
|
|
|
21
21
|
* Follows SOLID principles with composition over inheritance.
|
|
22
22
|
*/
|
|
23
23
|
export class CalendarService {
|
|
24
|
+
// Cache for weekday names to prevent recalculation
|
|
25
|
+
private static weekdayNamesCache = new Map<string, string[]>();
|
|
26
|
+
|
|
24
27
|
/**
|
|
25
28
|
* Generate calendar days for a specific month
|
|
26
29
|
*/
|
|
@@ -96,13 +99,23 @@ export class CalendarService {
|
|
|
96
99
|
/**
|
|
97
100
|
* Get weekday names
|
|
98
101
|
*/
|
|
99
|
-
static getWeekdayNames(locale
|
|
102
|
+
static getWeekdayNames(locale: string = 'en-US'): string[] {
|
|
103
|
+
const cacheKey = locale;
|
|
104
|
+
|
|
105
|
+
// Return cached result if available
|
|
106
|
+
if (this.weekdayNamesCache.has(cacheKey)) {
|
|
107
|
+
return this.weekdayNamesCache.get(cacheKey)!;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Calculate and cache
|
|
100
111
|
const weekdays: string[] = [];
|
|
101
112
|
for (let i = 0; i < 7; i++) {
|
|
102
113
|
const date = new Date();
|
|
103
114
|
date.setDate(date.getDate() - date.getDay() + i);
|
|
104
|
-
weekdays.push(date.toLocaleDateString(locale
|
|
115
|
+
weekdays.push(date.toLocaleDateString(locale, { weekday: 'short' }));
|
|
105
116
|
}
|
|
117
|
+
|
|
118
|
+
this.weekdayNamesCache.set(cacheKey, weekdays);
|
|
106
119
|
return weekdays;
|
|
107
120
|
}
|
|
108
121
|
|
|
@@ -18,6 +18,7 @@ class DevMonitorClass {
|
|
|
18
18
|
private statsInterval: ReturnType<typeof setInterval> | null = null;
|
|
19
19
|
private cacheSubscription: (() => void) | null = null;
|
|
20
20
|
private isEnabled: boolean;
|
|
21
|
+
private maxMetrics: number = 1000; // Prevent unbounded growth
|
|
21
22
|
|
|
22
23
|
constructor(options: DevMonitorOptions = {}) {
|
|
23
24
|
this.isEnabled = __DEV__ ?? false;
|
|
@@ -53,6 +54,14 @@ class DevMonitorClass {
|
|
|
53
54
|
|
|
54
55
|
this.metrics.set(queryKeyString, updatedMetrics);
|
|
55
56
|
|
|
57
|
+
// Prevent unbounded growth - remove oldest metric if limit exceeded
|
|
58
|
+
if (this.metrics.size > this.maxMetrics) {
|
|
59
|
+
const oldestKey = this.metrics.keys().next().value;
|
|
60
|
+
if (oldestKey) {
|
|
61
|
+
this.metrics.delete(oldestKey);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
56
65
|
if (this.options.enableLogging && updatedMetrics.slowFetchCount > 0) {
|
|
57
66
|
const fetchTime = MetricsCalculator.calculateFetchTime(query);
|
|
58
67
|
if (MetricsCalculator.isSlowQuery(fetchTime, this.options.slowQueryThreshold)) {
|
|
@@ -177,6 +186,7 @@ class DevMonitorClass {
|
|
|
177
186
|
clear(): void {
|
|
178
187
|
if (!this.isEnabled) return;
|
|
179
188
|
this.metrics.clear();
|
|
189
|
+
this.stopStatsLogging();
|
|
180
190
|
if (this.options.enableLogging) {
|
|
181
191
|
DevMonitorLogger.logMethodsCleared();
|
|
182
192
|
}
|
|
@@ -79,12 +79,14 @@ export function useAsyncOperation<T, E = Error>(
|
|
|
79
79
|
const operationRef = useRef(operation);
|
|
80
80
|
const errorHandlerRef = useRef(errorHandler);
|
|
81
81
|
|
|
82
|
-
// Keep all callback refs in sync with latest values
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
// Keep all callback refs in sync with latest values - use useEffect to prevent updates on every render
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
onSuccessRef.current = onSuccess;
|
|
85
|
+
onErrorRef.current = onError;
|
|
86
|
+
onFinallyRef.current = onFinally;
|
|
87
|
+
operationRef.current = operation;
|
|
88
|
+
errorHandlerRef.current = errorHandler;
|
|
89
|
+
}, [onSuccess, onError, onFinally, operation, errorHandler]);
|
|
88
90
|
|
|
89
91
|
// Cleanup on unmount
|
|
90
92
|
useEffect(() => {
|