@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-design-system",
3
- "version": "4.27.2",
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={{ top: 10, bottom: 10, left: 10, right: 10 }}
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?: string): string[] {
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 ?? undefined, { weekday: 'short' }));
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
- onSuccessRef.current = onSuccess;
84
- onErrorRef.current = onError;
85
- onFinallyRef.current = onFinally;
86
- operationRef.current = operation;
87
- errorHandlerRef.current = errorHandler;
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(() => {