@umituz/react-native-design-system 2.5.9 → 2.5.11
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/README.md +1 -1
- package/package.json +3 -1
- package/src/atoms/AtomicButton.tsx +2 -5
- package/src/atoms/AtomicChip.tsx +13 -13
- package/src/atoms/AtomicIcon.tsx +1 -8
- package/src/atoms/AtomicPicker.tsx +6 -5
- package/src/atoms/__tests__/AtomicIcon.test.tsx +0 -6
- package/src/atoms/input/hooks/useInputState.ts +0 -6
- package/src/atoms/picker/components/PickerModal.tsx +15 -6
- package/src/atoms/picker/types/index.ts +17 -4
- package/src/device/detection/deviceDetection.ts +7 -20
- package/src/layouts/ScreenHeader/ScreenHeader.tsx +1 -2
- package/src/molecules/alerts/AlertToast.tsx +1 -1
- package/src/molecules/animation/presentation/hooks/useFireworks.ts +1 -3
- package/src/molecules/animation/presentation/providers/AnimationThemeProvider.tsx +1 -3
- package/src/molecules/avatar/Avatar.tsx +2 -2
- package/src/molecules/bottom-sheet/components/BottomSheetModal.tsx +0 -6
- package/src/molecules/calendar/infrastructure/storage/CalendarStore.ts +243 -245
- package/src/molecules/navigation/StackNavigator.tsx +6 -9
- package/src/molecules/navigation/TabsNavigator.tsx +9 -13
- package/src/molecules/navigation/utils/AppNavigation.ts +0 -2
- package/src/molecules/navigation/utils/LabelProcessor.ts +1 -10
- package/src/molecules/navigation/utils/NavigationCleanup.ts +4 -8
- package/src/molecules/navigation/utils/NavigationValidator.ts +2 -11
- package/src/presentation/utils/variants/compound.ts +0 -4
- package/src/presentation/utils/variants/core.ts +0 -4
- package/src/presentation/utils/variants/helpers.ts +0 -6
- package/src/safe-area/components/SafeAreaProvider.tsx +0 -10
- package/src/safe-area/utils/validation.ts +3 -27
- package/src/theme/core/CustomColors.ts +2 -8
- package/src/theme/core/colors/ColorUtils.ts +0 -6
- package/src/theme/infrastructure/storage/ThemeStorage.ts +2 -16
- package/src/typography/presentation/utils/textColorUtils.ts +0 -3
- package/src/utilities/clipboard/ClipboardUtils.ts +1 -5
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Calendar Store (Zustand)
|
|
2
|
+
* Calendar Store (Zustand via @umituz/react-native-storage)
|
|
3
3
|
*
|
|
4
4
|
* Global state management for calendar functionality.
|
|
5
5
|
* Manages calendar view state, selected date, and events.
|
|
6
6
|
*
|
|
7
7
|
* Design Philosophy:
|
|
8
|
-
* -
|
|
9
|
-
* - AsyncStorage
|
|
8
|
+
* - Uses createStore from @umituz/react-native-storage
|
|
9
|
+
* - AsyncStorage persistence built-in
|
|
10
10
|
* - Generic event handling
|
|
11
11
|
* - Timezone-aware via CalendarService
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
15
|
-
import { persist, createJSONStorage, type PersistOptions } from 'zustand/middleware';
|
|
16
|
-
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
14
|
+
import { createStore, storageRepository } from '@umituz/react-native-storage';
|
|
17
15
|
import type { CalendarEvent, CreateCalendarEventRequest, UpdateCalendarEventRequest } from '../../domain/entities/CalendarEvent.entity';
|
|
18
16
|
import { CalendarService } from '../services/CalendarService';
|
|
19
17
|
|
|
@@ -23,285 +21,285 @@ import { CalendarService } from '../services/CalendarService';
|
|
|
23
21
|
export type CalendarViewMode = 'month' | 'week' | 'day' | 'list';
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
|
-
*
|
|
24
|
+
* Storage key for calendar events
|
|
25
|
+
*/
|
|
26
|
+
const STORAGE_KEY = 'calendar_events';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Generate unique ID for events
|
|
30
|
+
*/
|
|
31
|
+
const generateId = (): string => {
|
|
32
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Calendar state (data only)
|
|
27
37
|
*/
|
|
28
38
|
interface CalendarState {
|
|
29
|
-
// State
|
|
30
39
|
events: CalendarEvent[];
|
|
31
40
|
selectedDate: Date;
|
|
32
41
|
currentMonth: Date;
|
|
33
42
|
viewMode: CalendarViewMode;
|
|
34
43
|
isLoading: boolean;
|
|
35
44
|
error: string | null;
|
|
45
|
+
}
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Calendar actions
|
|
49
|
+
*/
|
|
50
|
+
interface CalendarActions {
|
|
51
|
+
// Event CRUD
|
|
52
|
+
loadEvents: () => Promise<void>;
|
|
53
|
+
addEvent: (request: CreateCalendarEventRequest) => Promise<void>;
|
|
54
|
+
updateEvent: (request: UpdateCalendarEventRequest) => Promise<void>;
|
|
55
|
+
deleteEvent: (id: string) => Promise<void>;
|
|
56
|
+
completeEvent: (id: string) => Promise<void>;
|
|
57
|
+
uncompleteEvent: (id: string) => Promise<void>;
|
|
46
58
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
// Navigation
|
|
60
|
+
setSelectedDate: (date: Date) => void;
|
|
61
|
+
goToToday: () => void;
|
|
62
|
+
navigateMonth: (direction: 'prev' | 'next') => void;
|
|
63
|
+
navigateWeek: (direction: 'prev' | 'next') => void;
|
|
64
|
+
setCurrentMonth: (date: Date) => void;
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
|
|
66
|
+
// View mode
|
|
67
|
+
setViewMode: (mode: CalendarViewMode) => void;
|
|
56
68
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
69
|
+
// Utilities
|
|
70
|
+
getEventsForDate: (date: Date) => CalendarEvent[];
|
|
71
|
+
getEventsForMonth: (year: number, month: number) => CalendarEvent[];
|
|
72
|
+
clearError: () => void;
|
|
73
|
+
clearAllEvents: () => Promise<void>;
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
/**
|
|
66
|
-
*
|
|
67
|
-
*/
|
|
68
|
-
const STORAGE_KEY = 'calendar_events';
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Generate unique ID for events
|
|
77
|
+
* Initial state
|
|
72
78
|
*/
|
|
73
|
-
const
|
|
74
|
-
|
|
79
|
+
const initialState: CalendarState = {
|
|
80
|
+
events: [],
|
|
81
|
+
selectedDate: new Date(),
|
|
82
|
+
currentMonth: new Date(),
|
|
83
|
+
viewMode: 'month',
|
|
84
|
+
isLoading: false,
|
|
85
|
+
error: null,
|
|
75
86
|
};
|
|
76
87
|
|
|
77
88
|
/**
|
|
78
89
|
* Calendar Store
|
|
79
90
|
*/
|
|
80
|
-
export const useCalendarStore =
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
export const useCalendarStore = createStore<CalendarState, CalendarActions>({
|
|
92
|
+
name: 'calendar-storage',
|
|
93
|
+
initialState,
|
|
94
|
+
persist: true,
|
|
95
|
+
partialize: (state) => ({ events: state.events }),
|
|
96
|
+
actions: (set, get) => ({
|
|
97
|
+
/**
|
|
98
|
+
* Load events from storage
|
|
99
|
+
*/
|
|
100
|
+
loadEvents: async () => {
|
|
101
|
+
set({ isLoading: true, error: null });
|
|
102
|
+
try {
|
|
103
|
+
const stored = await storageRepository.getItem<CalendarEvent[]>(STORAGE_KEY);
|
|
104
|
+
if (stored) {
|
|
105
|
+
// Restore Date objects
|
|
106
|
+
const events = stored.map((event) => ({
|
|
107
|
+
...event,
|
|
108
|
+
createdAt: new Date(event.createdAt),
|
|
109
|
+
updatedAt: new Date(event.updatedAt),
|
|
110
|
+
}));
|
|
111
|
+
set({ events, isLoading: false });
|
|
112
|
+
} else {
|
|
113
|
+
set({ isLoading: false });
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
set({
|
|
117
|
+
error: error instanceof Error ? error.message : 'Failed to load events',
|
|
118
|
+
isLoading: false,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
},
|
|
90
122
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
},
|
|
123
|
+
/**
|
|
124
|
+
* Add a new event
|
|
125
|
+
*/
|
|
126
|
+
addEvent: async (request: CreateCalendarEventRequest) => {
|
|
127
|
+
set({ isLoading: true, error: null });
|
|
128
|
+
try {
|
|
129
|
+
const newEvent: CalendarEvent = {
|
|
130
|
+
id: generateId(),
|
|
131
|
+
...request,
|
|
132
|
+
isCompleted: false,
|
|
133
|
+
createdAt: new Date(),
|
|
134
|
+
updatedAt: new Date(),
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const events = [...get().events, newEvent];
|
|
138
|
+
await storageRepository.setItem(STORAGE_KEY, events);
|
|
139
|
+
set({ events, isLoading: false });
|
|
140
|
+
} catch (error) {
|
|
141
|
+
set({
|
|
142
|
+
error: error instanceof Error ? error.message : 'Failed to add event',
|
|
143
|
+
isLoading: false,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
},
|
|
118
147
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Update an existing event
|
|
150
|
+
*/
|
|
151
|
+
updateEvent: async (request: UpdateCalendarEventRequest) => {
|
|
152
|
+
set({ isLoading: true, error: null });
|
|
153
|
+
try {
|
|
154
|
+
const events = get().events.map((event) => {
|
|
155
|
+
if (event.id === request.id) {
|
|
156
|
+
return {
|
|
157
|
+
...event,
|
|
127
158
|
...request,
|
|
128
|
-
isCompleted: false,
|
|
129
|
-
createdAt: new Date(),
|
|
130
159
|
updatedAt: new Date(),
|
|
131
160
|
};
|
|
132
|
-
|
|
133
|
-
const events = [...get().events, newEvent];
|
|
134
|
-
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(events));
|
|
135
|
-
set({ events, isLoading: false });
|
|
136
|
-
} catch (error) {
|
|
137
|
-
set({
|
|
138
|
-
error: error instanceof Error ? error.message : 'Failed to add event',
|
|
139
|
-
isLoading: false
|
|
140
|
-
});
|
|
141
161
|
}
|
|
142
|
-
|
|
162
|
+
return event;
|
|
163
|
+
});
|
|
143
164
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
...event,
|
|
154
|
-
...request,
|
|
155
|
-
updatedAt: new Date(),
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
return event;
|
|
159
|
-
});
|
|
165
|
+
await storageRepository.setItem(STORAGE_KEY, events);
|
|
166
|
+
set({ events, isLoading: false });
|
|
167
|
+
} catch (error) {
|
|
168
|
+
set({
|
|
169
|
+
error: error instanceof Error ? error.message : 'Failed to update event',
|
|
170
|
+
isLoading: false,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
},
|
|
160
174
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
175
|
+
/**
|
|
176
|
+
* Delete an event
|
|
177
|
+
*/
|
|
178
|
+
deleteEvent: async (id: string) => {
|
|
179
|
+
set({ isLoading: true, error: null });
|
|
180
|
+
try {
|
|
181
|
+
const events = get().events.filter((event) => event.id !== id);
|
|
182
|
+
await storageRepository.setItem(STORAGE_KEY, events);
|
|
183
|
+
set({ events, isLoading: false });
|
|
184
|
+
} catch (error) {
|
|
185
|
+
set({
|
|
186
|
+
error: error instanceof Error ? error.message : 'Failed to delete event',
|
|
187
|
+
isLoading: false,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
},
|
|
170
191
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const events = get().events.filter(event => event.id !== id);
|
|
178
|
-
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(events));
|
|
179
|
-
set({ events, isLoading: false });
|
|
180
|
-
} catch (error) {
|
|
181
|
-
set({
|
|
182
|
-
error: error instanceof Error ? error.message : 'Failed to delete event',
|
|
183
|
-
isLoading: false
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Mark event as completed
|
|
190
|
-
*/
|
|
191
|
-
completeEvent: async (id: string) => {
|
|
192
|
-
await get().actions.updateEvent({ id, isCompleted: true });
|
|
193
|
-
},
|
|
192
|
+
/**
|
|
193
|
+
* Mark event as completed
|
|
194
|
+
*/
|
|
195
|
+
completeEvent: async (id: string) => {
|
|
196
|
+
await get().updateEvent({ id, isCompleted: true });
|
|
197
|
+
},
|
|
194
198
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Mark event as incomplete
|
|
201
|
+
*/
|
|
202
|
+
uncompleteEvent: async (id: string) => {
|
|
203
|
+
await get().updateEvent({ id, isCompleted: false });
|
|
204
|
+
},
|
|
201
205
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Set selected date
|
|
208
|
+
*/
|
|
209
|
+
setSelectedDate: (date: Date) => {
|
|
210
|
+
set({ selectedDate: date });
|
|
211
|
+
},
|
|
208
212
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Go to today's date
|
|
215
|
+
*/
|
|
216
|
+
goToToday: () => {
|
|
217
|
+
const today = new Date();
|
|
218
|
+
set({
|
|
219
|
+
selectedDate: today,
|
|
220
|
+
currentMonth: today,
|
|
221
|
+
});
|
|
222
|
+
},
|
|
219
223
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Navigate to previous/next month
|
|
226
|
+
*/
|
|
227
|
+
navigateMonth: (direction: 'prev' | 'next') => {
|
|
228
|
+
const currentMonth = get().currentMonth;
|
|
229
|
+
const newMonth =
|
|
230
|
+
direction === 'prev'
|
|
231
|
+
? CalendarService.getPreviousMonth(currentMonth)
|
|
232
|
+
: CalendarService.getNextMonth(currentMonth);
|
|
228
233
|
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
set({ currentMonth: newMonth });
|
|
235
|
+
},
|
|
231
236
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Navigate to previous/next week
|
|
239
|
+
*/
|
|
240
|
+
navigateWeek: (direction: 'prev' | 'next') => {
|
|
241
|
+
const selectedDate = get().selectedDate;
|
|
242
|
+
const newDate =
|
|
243
|
+
direction === 'prev'
|
|
244
|
+
? CalendarService.getPreviousWeek(selectedDate)
|
|
245
|
+
: CalendarService.getNextWeek(selectedDate);
|
|
240
246
|
|
|
241
|
-
|
|
242
|
-
|
|
247
|
+
set({ selectedDate: newDate });
|
|
248
|
+
},
|
|
243
249
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Set current month directly
|
|
252
|
+
*/
|
|
253
|
+
setCurrentMonth: (date: Date) => {
|
|
254
|
+
set({ currentMonth: date });
|
|
255
|
+
},
|
|
250
256
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Set view mode
|
|
259
|
+
*/
|
|
260
|
+
setViewMode: (mode: CalendarViewMode) => {
|
|
261
|
+
set({ viewMode: mode });
|
|
262
|
+
},
|
|
257
263
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
264
|
+
/**
|
|
265
|
+
* Get events for a specific date
|
|
266
|
+
*/
|
|
267
|
+
getEventsForDate: (date: Date) => {
|
|
268
|
+
const events = get().events;
|
|
269
|
+
return CalendarService.getEventsForDate(date, events);
|
|
270
|
+
},
|
|
265
271
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
/**
|
|
273
|
+
* Get events for a specific month
|
|
274
|
+
*/
|
|
275
|
+
getEventsForMonth: (year: number, month: number) => {
|
|
276
|
+
const events = get().events;
|
|
277
|
+
const firstDay = new Date(year, month, 1);
|
|
278
|
+
const lastDay = new Date(year, month + 1, 0);
|
|
279
|
+
return CalendarService.getEventsInRange(firstDay, lastDay, events);
|
|
280
|
+
},
|
|
275
281
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Clear error state
|
|
284
|
+
*/
|
|
285
|
+
clearError: () => {
|
|
286
|
+
set({ error: null });
|
|
287
|
+
},
|
|
282
288
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
{
|
|
301
|
-
name: 'calendar-storage',
|
|
302
|
-
storage: createJSONStorage(() => AsyncStorage),
|
|
303
|
-
// Only persist events, not UI state
|
|
304
|
-
partialize: (state) => ({ events: state.events }),
|
|
305
|
-
}
|
|
306
|
-
)
|
|
307
|
-
);
|
|
289
|
+
/**
|
|
290
|
+
* Clear all events (for testing/reset)
|
|
291
|
+
*/
|
|
292
|
+
clearAllEvents: async () => {
|
|
293
|
+
set({ isLoading: true, error: null });
|
|
294
|
+
try {
|
|
295
|
+
await storageRepository.removeItem(STORAGE_KEY);
|
|
296
|
+
set({ events: [], isLoading: false });
|
|
297
|
+
} catch (error) {
|
|
298
|
+
set({
|
|
299
|
+
error: error instanceof Error ? error.message : 'Failed to clear events',
|
|
300
|
+
isLoading: false,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
}),
|
|
305
|
+
});
|
|
@@ -22,14 +22,12 @@ export interface StackNavigatorProps<T extends ParamListBase> {
|
|
|
22
22
|
export function StackNavigator<T extends ParamListBase>({ config }: StackNavigatorProps<T>) {
|
|
23
23
|
const tokens = useAppDesignTokens();
|
|
24
24
|
|
|
25
|
-
// Validate configuration
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (__DEV__) console.error('[StackNavigator] Configuration validation failed:', error);
|
|
32
|
-
}
|
|
25
|
+
// Validate configuration silently
|
|
26
|
+
try {
|
|
27
|
+
NavigationValidator.validateScreens(config.screens, "stack");
|
|
28
|
+
NavigationValidator.validateInitialRoute(config.initialRouteName, config.screens);
|
|
29
|
+
} catch {
|
|
30
|
+
// Silent validation failure
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
const { screens } = config;
|
|
@@ -55,7 +53,6 @@ export function StackNavigator<T extends ParamListBase>({ config }: StackNavigat
|
|
|
55
53
|
}), [tokens]);
|
|
56
54
|
|
|
57
55
|
if (screens.length === 0) {
|
|
58
|
-
if (__DEV__) console.warn('[StackNavigator] No screens found');
|
|
59
56
|
return null;
|
|
60
57
|
}
|
|
61
58
|
|
|
@@ -24,18 +24,15 @@ export function TabsNavigator<T extends ParamListBase>({
|
|
|
24
24
|
}: TabsNavigatorProps<T>) {
|
|
25
25
|
const tokens = useAppDesignTokens();
|
|
26
26
|
|
|
27
|
-
// Validate configuration
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (__DEV__)
|
|
37
|
-
console.error("[TabsNavigator] Configuration validation failed:", error);
|
|
38
|
-
}
|
|
27
|
+
// Validate configuration silently
|
|
28
|
+
try {
|
|
29
|
+
NavigationValidator.validateScreens(config.screens, "tab");
|
|
30
|
+
NavigationValidator.validateInitialRoute(
|
|
31
|
+
config.initialRouteName,
|
|
32
|
+
config.screens
|
|
33
|
+
);
|
|
34
|
+
} catch {
|
|
35
|
+
// Silent validation failure
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
// Memoize filtered screens
|
|
@@ -74,7 +71,6 @@ export function TabsNavigator<T extends ParamListBase>({
|
|
|
74
71
|
);
|
|
75
72
|
|
|
76
73
|
if (visibleScreens.length === 0) {
|
|
77
|
-
if (__DEV__) console.warn("[TabsNavigator] No visible screens found");
|
|
78
74
|
return null;
|
|
79
75
|
}
|
|
80
76
|
|
|
@@ -31,8 +31,6 @@ export class AppNavigation {
|
|
|
31
31
|
static navigate(name: string, params?: object): void {
|
|
32
32
|
if (this.navigationRef?.isReady()) {
|
|
33
33
|
this.navigationRef.navigate(name, params);
|
|
34
|
-
} else if (__DEV__) {
|
|
35
|
-
console.warn('[AppNavigation] Navigation ref is not ready. Call setRef() first.');
|
|
36
34
|
}
|
|
37
35
|
}
|
|
38
36
|
|
|
@@ -28,10 +28,7 @@ export class LabelProcessor {
|
|
|
28
28
|
try {
|
|
29
29
|
const processedLabel = getLabel(label);
|
|
30
30
|
result = typeof processedLabel === "string" ? processedLabel : label;
|
|
31
|
-
} catch
|
|
32
|
-
if (__DEV__) {
|
|
33
|
-
console.error(`[LabelProcessor] Error processing label: ${label}`, error);
|
|
34
|
-
}
|
|
31
|
+
} catch {
|
|
35
32
|
result = label;
|
|
36
33
|
}
|
|
37
34
|
}
|
|
@@ -45,12 +42,6 @@ export class LabelProcessor {
|
|
|
45
42
|
}
|
|
46
43
|
this.labelCache.set(cacheKey, result);
|
|
47
44
|
|
|
48
|
-
// Log cache performance in development
|
|
49
|
-
if (__DEV__ && (this.cacheHits + this.cacheMisses) % 100 === 0) {
|
|
50
|
-
const hitRate = (this.cacheHits / (this.cacheHits + this.cacheMisses)) * 100;
|
|
51
|
-
console.log(`[LabelProcessor] Cache hit rate: ${hitRate.toFixed(1)}%`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
45
|
return result;
|
|
55
46
|
}
|
|
56
47
|
|