@umituz/react-native-design-system 2.5.7 → 2.5.9

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": "2.5.7",
3
+ "version": "2.5.9",
4
4
  "description": "Universal design system for React Native apps - Consolidated package with atoms, molecules, organisms, theme, typography, responsive and safe area utilities",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -110,9 +110,10 @@ export const AtomicIcon: React.FC<AtomicIconProps> = React.memo(({
110
110
 
111
111
  // Calculate size
112
112
  const baseSize = customSize ?? size;
113
- const sizeInPixels = typeof baseSize === 'number'
113
+ const iconSizesMap = tokens.iconSizes as Record<string, number>;
114
+ const sizeInPixels: number = typeof baseSize === 'number'
114
115
  ? baseSize * tokens.spacingMultiplier
115
- : (tokens.iconSizes as Record<string, number>)[baseSize] || (tokens.iconSizes as Record<string, number>).md;
116
+ : iconSizesMap[baseSize] ?? iconSizesMap['md'] ?? 24;
116
117
 
117
118
  // Calculate color
118
119
  const iconColor = customColor
@@ -88,7 +88,7 @@ const ScreenHeaderBackButton: React.FC<{
88
88
  hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
89
89
  testID={`${testID}-back-button`}
90
90
  >
91
- <AtomicIcon name={backIconName || 'ArrowLeft'} color={backIconColor} />
91
+ <AtomicIcon name={backIconName || 'arrow-back'} color={backIconColor} />
92
92
  </TouchableOpacity>
93
93
  </View>
94
94
  );
@@ -132,7 +132,7 @@ export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
132
132
  hideBackButton = false,
133
133
  style,
134
134
  testID = 'screen-header',
135
- backIconName = 'ArrowLeft',
135
+ backIconName = 'arrow-back',
136
136
  backIconColor = 'primary',
137
137
  }) => {
138
138
  const tokens = useAppDesignTokens();
@@ -2,7 +2,7 @@
2
2
  * Alert Store
3
3
  */
4
4
 
5
- import { create, type StoreApi } from 'zustand';
5
+ import { createStore } from '@umituz/react-native-storage';
6
6
  import { Alert } from './AlertTypes';
7
7
 
8
8
  interface AlertState {
@@ -15,14 +15,17 @@ interface AlertActions {
15
15
  clearAlerts: () => void;
16
16
  }
17
17
 
18
- type AlertStore = AlertState & AlertActions;
19
- type SetState = StoreApi<AlertStore>['setState'];
20
-
21
- export const useAlertStore = create<AlertStore>((set: SetState) => ({
22
- alerts: [],
23
- addAlert: (alert: Alert) => set((state: AlertStore) => ({ alerts: [...state.alerts, alert] })),
24
- dismissAlert: (id: string) => set((state: AlertStore) => ({
25
- alerts: state.alerts.filter((a: Alert) => a.id !== id)
26
- })),
27
- clearAlerts: () => set({ alerts: [] }),
28
- }));
18
+ export const useAlertStore = createStore<AlertState, AlertActions>({
19
+ name: 'alert-store',
20
+ initialState: {
21
+ alerts: [],
22
+ },
23
+ persist: false,
24
+ actions: (set, get) => ({
25
+ addAlert: (alert: Alert) => set({ alerts: [...get().alerts, alert] }),
26
+ dismissAlert: (id: string) => set({
27
+ alerts: get().alerts.filter((a: Alert) => a.id !== id)
28
+ }),
29
+ clearAlerts: () => set({ alerts: [] }),
30
+ }),
31
+ });
@@ -104,7 +104,8 @@ export const useFireworks = (config: FireworksConfig) => {
104
104
 
105
105
  const newParticles: ParticleConfig[] = [];
106
106
  for (let i = 0; i < particleCount; i++) {
107
- const color = colors[Math.floor(Math.random() * colors.length)];
107
+ const colorIndex = Math.floor(Math.random() * colors.length);
108
+ const color = colors[colorIndex] ?? colors[0] ?? '#FFFFFF';
108
109
  newParticles.push(createParticle(centerX, centerY, color));
109
110
  }
110
111
 
@@ -165,9 +165,11 @@ export class AvatarUtils {
165
165
 
166
166
  if (words.length >= 2) {
167
167
  // Full name: First letter of first + first letter of last
168
- const first = words[0][0];
169
- const last = words[words.length - 1][0];
170
- return (first + last).toLocaleUpperCase('tr-TR');
168
+ const firstWord = words[0] ?? '';
169
+ const lastWord = words[words.length - 1] ?? '';
170
+ const first = firstWord[0] ?? '';
171
+ const last = lastWord[0] ?? '';
172
+ return (first + last).toLocaleUpperCase('tr-TR') || '?';
171
173
  } else {
172
174
  // Single word: First 2 letters
173
175
  return trimmed.slice(0, 2).toLocaleUpperCase('tr-TR');
@@ -11,8 +11,8 @@
11
11
  * - Timezone-aware via CalendarService
12
12
  */
13
13
 
14
- import { create } from 'zustand';
15
- import { persist, createJSONStorage } from 'zustand/middleware';
14
+ import { create, type StateCreator } from 'zustand';
15
+ import { persist, createJSONStorage, type PersistOptions } from 'zustand/middleware';
16
16
  import AsyncStorage from '@react-native-async-storage/async-storage';
17
17
  import type { CalendarEvent, CreateCalendarEventRequest, UpdateCalendarEventRequest } from '../../domain/entities/CalendarEvent.entity';
18
18
  import { CalendarService } from '../services/CalendarService';
@@ -14,7 +14,8 @@ export class DateUtilities {
14
14
  * Format date to string (YYYY-MM-DD)
15
15
  */
16
16
  static formatDateToString(date: Date): string {
17
- return date.toISOString().split('T')[0];
17
+ const parts = date.toISOString().split('T');
18
+ return parts[0] ?? '';
18
19
  }
19
20
 
20
21
  /**
@@ -91,7 +92,10 @@ export class DateUtilities {
91
92
  * Parse date from string (YYYY-MM-DD)
92
93
  */
93
94
  static parseDate(dateString: string): Date {
94
- const [year, month, day] = dateString.split('-').map(Number);
95
+ const parts = dateString.split('-').map(Number);
96
+ const year = parts[0] ?? 0;
97
+ const month = parts[1] ?? 1;
98
+ const day = parts[2] ?? 1;
95
99
  return new Date(year, month - 1, day);
96
100
  }
97
101
 
@@ -84,7 +84,7 @@ export const useCalendar = (): UseCalendarReturn => {
84
84
  isLoading,
85
85
  error,
86
86
  actions,
87
- } = useCalendarStore((state) => state);
87
+ } = useCalendarStore((state: ReturnType<typeof useCalendarStore.getState>) => state);
88
88
 
89
89
  // Load events on mount
90
90
  useEffect(() => {
@@ -133,7 +133,7 @@ export const useCalendarNavigation = () => {
133
133
  selectedDate,
134
134
  currentMonth,
135
135
  actions: { setSelectedDate, navigateMonth, goToToday, setCurrentMonth },
136
- } = useCalendarStore((state) => state);
136
+ } = useCalendarStore((state: ReturnType<typeof useCalendarStore.getState>) => state);
137
137
 
138
138
  return {
139
139
  selectedDate,
@@ -163,7 +163,7 @@ export const useCalendarEvents = () => {
163
163
  uncompleteEvent,
164
164
  clearError,
165
165
  },
166
- } = useCalendarStore((state) => state);
166
+ } = useCalendarStore((state: ReturnType<typeof useCalendarStore.getState>) => state);
167
167
 
168
168
  return {
169
169
  events,
@@ -25,20 +25,20 @@
25
25
  * ```
26
26
  */
27
27
 
28
- import { create } from 'zustand';
28
+ import { createStore } from '@umituz/react-native-storage';
29
29
  import type { ThemeMode } from '../core/ColorPalette';
30
30
  import type { CustomThemeColors } from '../core/CustomColors';
31
31
 
32
- interface GlobalThemeStore {
32
+ interface GlobalThemeState {
33
33
  /** Current theme mode */
34
34
  themeMode: ThemeMode;
35
-
36
35
  /** Custom theme colors override */
37
36
  customColors?: CustomThemeColors;
37
+ }
38
38
 
39
+ interface GlobalThemeActions {
39
40
  /** Update theme mode (called by app when theme changes) */
40
41
  setThemeMode: (mode: ThemeMode) => void;
41
-
42
42
  /** Set custom theme colors (called by app when custom colors change) */
43
43
  setCustomColors: (colors?: CustomThemeColors) => void;
44
44
  }
@@ -49,20 +49,26 @@ interface GlobalThemeStore {
49
49
  * This is a MINIMAL store - app has the real theme logic.
50
50
  * Design system just mirrors the current theme for its components.
51
51
  */
52
- export const useDesignSystemTheme = create<GlobalThemeStore>()((set: any, get: any) => ({
53
- themeMode: 'dark',
54
- customColors: undefined,
55
- setThemeMode: (mode: ThemeMode) => {
56
- // Only update if mode actually changed to prevent unnecessary re-renders
57
- const currentMode = get().themeMode;
58
- if (currentMode !== mode) {
59
- set({ themeMode: mode });
60
- }
61
- },
62
- setCustomColors: (colors?: CustomThemeColors) => {
63
- set({ customColors: colors });
52
+ export const useDesignSystemTheme = createStore<GlobalThemeState, GlobalThemeActions>({
53
+ name: 'design-system-theme',
54
+ initialState: {
55
+ themeMode: 'dark',
56
+ customColors: undefined,
64
57
  },
65
- }));
58
+ persist: false,
59
+ actions: (set, get) => ({
60
+ setThemeMode: (mode: ThemeMode) => {
61
+ // Only update if mode actually changed to prevent unnecessary re-renders
62
+ const currentMode = get().themeMode;
63
+ if (currentMode !== mode) {
64
+ set({ themeMode: mode });
65
+ }
66
+ },
67
+ setCustomColors: (colors?: CustomThemeColors) => {
68
+ set({ customColors: colors });
69
+ },
70
+ }),
71
+ });
66
72
 
67
73
  // Re-export ThemeMode for backward compatibility
68
74
  export type { ThemeMode };
@@ -10,7 +10,7 @@
10
10
  * - Syncs with design system global theme store
11
11
  */
12
12
 
13
- import { create } from 'zustand';
13
+ import { createStore } from '@umituz/react-native-storage';
14
14
  import { lightTheme, darkTheme, type Theme } from '../../core/themes';
15
15
  import { ThemeStorage } from '../storage/ThemeStorage';
16
16
  import { useDesignSystemTheme } from '../globalThemeStore';
@@ -21,6 +21,9 @@ interface ThemeState {
21
21
  themeMode: ThemeMode;
22
22
  isDark: boolean;
23
23
  isInitialized: boolean;
24
+ }
25
+
26
+ interface ThemeActions {
24
27
  setThemeMode: (mode: ThemeMode) => Promise<void>;
25
28
  toggleTheme: () => Promise<void>;
26
29
  initialize: () => Promise<void>;
@@ -39,66 +42,70 @@ interface ThemeState {
39
42
  * };
40
43
  * ```
41
44
  */
42
- export const useTheme = create<ThemeState>()((set: any, get: any) => ({
43
- theme: darkTheme,
44
- themeMode: 'dark',
45
- isDark: true,
46
- isInitialized: false,
47
-
48
- initialize: async () => {
49
- try {
50
- const savedMode = await ThemeStorage.getThemeMode();
51
- if (savedMode) {
52
- const theme = savedMode === 'light' ? lightTheme : darkTheme;
53
- set({
54
- themeMode: savedMode,
55
- theme,
56
- isDark: savedMode === 'dark',
57
- isInitialized: true,
58
- });
59
-
60
- // Sync with design system global theme
61
- useDesignSystemTheme.getState().setThemeMode(savedMode);
62
- } else {
63
- // No saved mode - use default 'dark' and sync to design system store
45
+ export const useTheme = createStore<ThemeState, ThemeActions>({
46
+ name: 'theme-store',
47
+ initialState: {
48
+ theme: darkTheme,
49
+ themeMode: 'dark',
50
+ isDark: true,
51
+ isInitialized: false,
52
+ },
53
+ persist: false,
54
+ actions: (set, get) => ({
55
+ initialize: async () => {
56
+ try {
57
+ const savedMode = await ThemeStorage.getThemeMode();
58
+ if (savedMode) {
59
+ const theme = savedMode === 'light' ? lightTheme : darkTheme;
60
+ set({
61
+ themeMode: savedMode,
62
+ theme,
63
+ isDark: savedMode === 'dark',
64
+ isInitialized: true,
65
+ });
66
+
67
+ // Sync with design system global theme
68
+ useDesignSystemTheme.getState().setThemeMode(savedMode);
69
+ } else {
70
+ // No saved mode - use default 'dark' and sync to design system store
71
+ set({ isInitialized: true });
72
+ // Ensure design system store is synced even if no saved mode exists
73
+ useDesignSystemTheme.getState().setThemeMode('dark');
74
+ }
75
+ } catch {
76
+ // Silent failure - still mark as initialized to prevent blocking
64
77
  set({ isInitialized: true });
65
- // Ensure design system store is synced even if no saved mode exists
78
+ // Ensure design system store is synced even on error
66
79
  useDesignSystemTheme.getState().setThemeMode('dark');
67
80
  }
68
- } catch (error) {
69
- if (__DEV__) console.error('[ThemeStore] Initialization error:', error);
70
- // Silent failure - still mark as initialized to prevent blocking
71
- set({ isInitialized: true });
72
- // Ensure design system store is synced even on error
73
- useDesignSystemTheme.getState().setThemeMode('dark');
74
- }
75
- },
81
+ },
76
82
 
77
- setThemeMode: async (mode: ThemeMode) => {
78
- try {
79
- const theme = mode === 'light' ? lightTheme : darkTheme;
83
+ setThemeMode: async (mode: ThemeMode) => {
84
+ try {
85
+ const theme = mode === 'light' ? lightTheme : darkTheme;
80
86
 
81
- set({
82
- themeMode: mode,
83
- theme,
84
- isDark: mode === 'dark',
85
- });
86
-
87
- await ThemeStorage.setThemeMode(mode);
87
+ set({
88
+ themeMode: mode,
89
+ theme,
90
+ isDark: mode === 'dark',
91
+ });
88
92
 
89
- // Sync with design system global theme
90
- useDesignSystemTheme.getState().setThemeMode(mode);
91
- } catch (error) {
92
- if (__DEV__) console.error('[ThemeStore] Error setting theme mode:', error);
93
- }
94
- },
93
+ await ThemeStorage.setThemeMode(mode);
95
94
 
96
- toggleTheme: async () => {
97
- const { themeMode, setThemeMode } = get();
98
- const newMode: ThemeMode = themeMode === 'light' ? 'dark' : 'light';
99
- await setThemeMode(newMode);
100
- },
101
- }));
95
+ // Sync with design system global theme
96
+ useDesignSystemTheme.getState().setThemeMode(mode);
97
+ } catch {
98
+ // Silent failure
99
+ }
100
+ },
101
+
102
+ toggleTheme: async () => {
103
+ const { themeMode, setThemeMode } = get();
104
+ const newMode: ThemeMode = themeMode === 'light' ? 'dark' : 'light';
105
+ await setThemeMode(newMode);
106
+ },
107
+ }),
108
+ });
102
109
 
103
110
 
104
111