@umituz/react-native-design-system 2.3.13 → 2.3.15
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 +32 -13
- package/src/index.ts +116 -0
- package/src/layouts/ScreenLayout/ScreenLayout.example.tsx +2 -2
- package/src/layouts/ScreenLayout/ScreenLayout.tsx +1 -1
- package/src/molecules/animation/core/AnimationCore.ts +29 -0
- package/src/molecules/animation/domain/entities/Animation.ts +81 -0
- package/src/molecules/animation/domain/entities/Fireworks.ts +44 -0
- package/src/molecules/animation/domain/entities/Theme.ts +76 -0
- package/src/molecules/animation/index.ts +146 -0
- package/src/molecules/animation/infrastructure/services/AnimationConfigService.ts +35 -0
- package/src/molecules/animation/infrastructure/services/SpringAnimationConfigService.ts +67 -0
- package/src/molecules/animation/infrastructure/services/TimingAnimationConfigService.ts +57 -0
- package/src/molecules/animation/infrastructure/services/__tests__/SpringAnimationConfigService.test.ts +114 -0
- package/src/molecules/animation/infrastructure/services/__tests__/TimingAnimationConfigService.test.ts +105 -0
- package/src/molecules/animation/presentation/components/Fireworks.tsx +126 -0
- package/src/molecules/animation/presentation/components/__tests__/Fireworks.test.tsx +189 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useAnimation.integration.test.ts +216 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useFireworks.test.ts +242 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useGesture.test.ts +111 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useSpringAnimation.test.ts +131 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useTimingAnimation.test.ts +175 -0
- package/src/molecules/animation/presentation/hooks/__tests__/useTransformAnimation.test.ts +137 -0
- package/src/molecules/animation/presentation/hooks/useAnimation.ts +77 -0
- package/src/molecules/animation/presentation/hooks/useFireworks.ts +141 -0
- package/src/molecules/animation/presentation/hooks/useGesture.ts +61 -0
- package/src/molecules/animation/presentation/hooks/useGestureCreators.ts +163 -0
- package/src/molecules/animation/presentation/hooks/useGestureState.ts +53 -0
- package/src/molecules/animation/presentation/hooks/useIconAnimations.ts +119 -0
- package/src/molecules/animation/presentation/hooks/useModalAnimations.ts +124 -0
- package/src/molecules/animation/presentation/hooks/useReanimatedReady.ts +60 -0
- package/src/molecules/animation/presentation/hooks/useSpringAnimation.ts +69 -0
- package/src/molecules/animation/presentation/hooks/useTimingAnimation.ts +111 -0
- package/src/molecules/animation/presentation/hooks/useTransformAnimation.ts +57 -0
- package/src/molecules/animation/presentation/providers/AnimationThemeProvider.tsx +62 -0
- package/src/molecules/animation/presentation/providers/__tests__/AnimationThemeProvider.test.tsx +165 -0
- package/src/molecules/animation/types/global.d.ts +97 -0
- package/src/molecules/calendar/domain/entities/CalendarDay.entity.ts +115 -0
- package/src/molecules/calendar/domain/entities/CalendarEvent.entity.ts +202 -0
- package/src/molecules/calendar/domain/repositories/ICalendarRepository.ts +120 -0
- package/src/molecules/calendar/index.ts +98 -0
- package/src/molecules/calendar/infrastructure/services/CalendarEvents.ts +196 -0
- package/src/molecules/calendar/infrastructure/services/CalendarGeneration.ts +172 -0
- package/src/molecules/calendar/infrastructure/services/CalendarPermissions.ts +92 -0
- package/src/molecules/calendar/infrastructure/services/CalendarService.ts +161 -0
- package/src/molecules/calendar/infrastructure/services/CalendarSync.ts +205 -0
- package/src/molecules/calendar/infrastructure/storage/CalendarStore.ts +307 -0
- package/src/molecules/calendar/infrastructure/utils/DateUtilities.ts +128 -0
- package/src/molecules/calendar/presentation/components/AtomicCalendar.tsx +279 -0
- package/src/molecules/calendar/presentation/hooks/useCalendar.ts +356 -0
- package/src/molecules/celebration/domain/entities/CelebrationConfig.ts +17 -0
- package/src/molecules/celebration/domain/entities/FireworksConfig.ts +32 -0
- package/src/molecules/celebration/index.ts +93 -0
- package/src/molecules/celebration/infrastructure/services/FireworksConfigService.ts +49 -0
- package/src/molecules/celebration/presentation/components/CelebrationFireworksOverlay.tsx +33 -0
- package/src/molecules/celebration/presentation/components/CelebrationModal.tsx +78 -0
- package/src/molecules/celebration/presentation/components/CelebrationModalContent.tsx +90 -0
- package/src/molecules/celebration/presentation/hooks/useCelebrationModalAnimation.ts +49 -0
- package/src/molecules/celebration/presentation/hooks/useCelebrationState.ts +45 -0
- package/src/molecules/celebration/presentation/styles/CelebrationModalStyles.ts +65 -0
- package/src/molecules/countdown/components/Countdown.tsx +128 -0
- package/src/molecules/countdown/components/CountdownHeader.tsx +84 -0
- package/src/molecules/countdown/components/TimeUnit.tsx +73 -0
- package/src/molecules/countdown/hooks/useCountdown.ts +107 -0
- package/src/molecules/countdown/index.ts +25 -0
- package/src/molecules/countdown/types/CountdownTypes.ts +31 -0
- package/src/molecules/countdown/utils/TimeCalculator.ts +46 -0
- package/src/molecules/emoji/domain/entities/Emoji.ts +129 -0
- package/src/molecules/emoji/index.ts +177 -0
- package/src/molecules/emoji/presentation/components/EmojiPicker.tsx +102 -0
- package/src/molecules/emoji/presentation/hooks/useEmojiPicker.ts +171 -0
- package/src/molecules/index.ts +24 -0
- package/src/molecules/long-press-menu/domain/entities/MenuAction.ts +37 -0
- package/src/molecules/long-press-menu/index.ts +16 -0
- package/src/molecules/navigation/StackNavigator.tsx +75 -0
- package/src/molecules/navigation/TabsNavigator.tsx +94 -0
- package/src/molecules/navigation/components/FabButton.tsx +45 -0
- package/src/molecules/navigation/components/TabLabel.tsx +47 -0
- package/src/molecules/navigation/createStackNavigator.ts +20 -0
- package/src/molecules/navigation/createTabNavigator.ts +20 -0
- package/src/molecules/navigation/hooks/useTabBarStyles.ts +54 -0
- package/src/molecules/navigation/index.ts +37 -0
- package/src/molecules/navigation/types.ts +118 -0
- package/src/molecules/navigation/utils/AppNavigation.ts +101 -0
- package/src/molecules/navigation/utils/IconRenderer.ts +50 -0
- package/src/molecules/navigation/utils/LabelProcessor.ts +70 -0
- package/src/molecules/navigation/utils/NavigationCleanup.ts +62 -0
- package/src/molecules/navigation/utils/NavigationTheme.ts +21 -0
- package/src/molecules/navigation/utils/NavigationValidator.ts +61 -0
- package/src/molecules/navigation/utils/ScreenFactory.ts +115 -0
- package/src/molecules/navigation/utils/__tests__/IconRenderer.getIconName.test.ts +109 -0
- package/src/molecules/navigation/utils/__tests__/IconRenderer.renderIcon.test.ts +116 -0
- package/src/molecules/navigation/utils/__tests__/LabelProcessor.processLabel.test.ts +116 -0
- package/src/molecules/navigation/utils/__tests__/LabelProcessor.processTitle.test.ts +59 -0
- package/src/molecules/navigation/utils/__tests__/NavigationCleanup.test.ts +271 -0
- package/src/molecules/navigation/utils/__tests__/NavigationValidator.test.ts +252 -0
- package/src/molecules/swipe-actions/domain/entities/SwipeAction.ts +194 -0
- package/src/molecules/swipe-actions/index.ts +6 -0
- package/src/molecules/swipe-actions/presentation/components/SwipeActionButton.tsx +131 -0
- package/src/theme/hooks/useResponsiveDesignTokens.ts +1 -1
- package/src/utilities/clipboard/ClipboardUtils.ts +71 -0
- package/src/utilities/clipboard/index.ts +5 -0
- package/src/utilities/index.ts +6 -0
- package/src/utilities/sharing/domain/entities/Share.ts +210 -0
- package/src/utilities/sharing/index.ts +205 -0
- package/src/utilities/sharing/infrastructure/services/SharingService.ts +165 -0
- package/src/utilities/sharing/presentation/hooks/useSharing.ts +154 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useCalendar Hook
|
|
3
|
+
*
|
|
4
|
+
* Main hook for calendar functionality.
|
|
5
|
+
* Provides calendar state, events, and actions.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const {
|
|
10
|
+
* days,
|
|
11
|
+
* events,
|
|
12
|
+
* selectedDate,
|
|
13
|
+
* viewMode,
|
|
14
|
+
* actions
|
|
15
|
+
* } = useCalendar();
|
|
16
|
+
*
|
|
17
|
+
* // Navigate calendar
|
|
18
|
+
* actions.navigateMonth('next');
|
|
19
|
+
*
|
|
20
|
+
* // Add event
|
|
21
|
+
* actions.addEvent({
|
|
22
|
+
* title: 'Team Meeting',
|
|
23
|
+
* date: '2024-10-30',
|
|
24
|
+
* time: '14:00',
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { useMemo, useEffect, useState, useCallback } from 'react';
|
|
30
|
+
import { useCalendarStore, type CalendarViewMode } from '../../infrastructure/storage/CalendarStore';
|
|
31
|
+
import { CalendarService } from '../../infrastructure/services/CalendarService';
|
|
32
|
+
import type { CalendarDay } from '../../domain/entities/CalendarDay.entity';
|
|
33
|
+
import type {
|
|
34
|
+
CalendarEvent,
|
|
35
|
+
SystemCalendar,
|
|
36
|
+
CalendarPermissionResult,
|
|
37
|
+
} from '../../domain/entities/CalendarEvent.entity';
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Calendar hook return type
|
|
41
|
+
*/
|
|
42
|
+
export interface UseCalendarReturn {
|
|
43
|
+
// Calendar data
|
|
44
|
+
days: CalendarDay[];
|
|
45
|
+
events: CalendarEvent[];
|
|
46
|
+
selectedDate: Date;
|
|
47
|
+
currentMonth: Date;
|
|
48
|
+
viewMode: CalendarViewMode;
|
|
49
|
+
|
|
50
|
+
// Computed data
|
|
51
|
+
selectedDateEvents: CalendarEvent[];
|
|
52
|
+
currentMonthEvents: CalendarEvent[];
|
|
53
|
+
|
|
54
|
+
// State
|
|
55
|
+
isLoading: boolean;
|
|
56
|
+
error: string | null;
|
|
57
|
+
|
|
58
|
+
// Actions
|
|
59
|
+
actions: {
|
|
60
|
+
loadEvents: () => Promise<void>;
|
|
61
|
+
addEvent: (request: any) => Promise<void>;
|
|
62
|
+
updateEvent: (request: any) => Promise<void>;
|
|
63
|
+
deleteEvent: (id: string) => Promise<void>;
|
|
64
|
+
completeEvent: (id: string) => Promise<void>;
|
|
65
|
+
uncompleteEvent: (id: string) => Promise<void>;
|
|
66
|
+
setSelectedDate: (date: Date) => void;
|
|
67
|
+
goToToday: () => void;
|
|
68
|
+
navigateMonth: (direction: 'prev' | 'next') => void;
|
|
69
|
+
navigateWeek: (direction: 'prev' | 'next') => void;
|
|
70
|
+
setCurrentMonth: (date: Date) => void;
|
|
71
|
+
setViewMode: (mode: CalendarViewMode) => void;
|
|
72
|
+
getEventsForDate: (date: Date) => CalendarEvent[];
|
|
73
|
+
getEventsForMonth: (year: number, month: number) => CalendarEvent[];
|
|
74
|
+
clearError: () => void;
|
|
75
|
+
clearAllEvents: () => Promise<void>;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Main calendar hook
|
|
81
|
+
*/
|
|
82
|
+
export const useCalendar = (): UseCalendarReturn => {
|
|
83
|
+
const {
|
|
84
|
+
events,
|
|
85
|
+
selectedDate,
|
|
86
|
+
currentMonth,
|
|
87
|
+
viewMode,
|
|
88
|
+
isLoading,
|
|
89
|
+
error,
|
|
90
|
+
actions,
|
|
91
|
+
} = useCalendarStore((state) => state);
|
|
92
|
+
|
|
93
|
+
// Load events on mount
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
actions.loadEvents();
|
|
96
|
+
}, []);
|
|
97
|
+
|
|
98
|
+
// Generate calendar days for current month
|
|
99
|
+
const days = useMemo(() => {
|
|
100
|
+
const year = currentMonth.getFullYear();
|
|
101
|
+
const month = currentMonth.getMonth();
|
|
102
|
+
return CalendarService.getMonthDays(year, month, events);
|
|
103
|
+
}, [currentMonth, events]);
|
|
104
|
+
|
|
105
|
+
// Get events for selected date
|
|
106
|
+
const selectedDateEvents = useMemo(() => {
|
|
107
|
+
return actions.getEventsForDate(selectedDate);
|
|
108
|
+
}, [selectedDate, events]);
|
|
109
|
+
|
|
110
|
+
// Get events for current month
|
|
111
|
+
const currentMonthEvents = useMemo(() => {
|
|
112
|
+
const year = currentMonth.getFullYear();
|
|
113
|
+
const month = currentMonth.getMonth();
|
|
114
|
+
return actions.getEventsForMonth(year, month);
|
|
115
|
+
}, [currentMonth, events]);
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
days,
|
|
119
|
+
events,
|
|
120
|
+
selectedDate,
|
|
121
|
+
currentMonth,
|
|
122
|
+
viewMode,
|
|
123
|
+
selectedDateEvents,
|
|
124
|
+
currentMonthEvents,
|
|
125
|
+
isLoading,
|
|
126
|
+
error,
|
|
127
|
+
actions,
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Hook for calendar navigation
|
|
133
|
+
* Lightweight hook for just navigation actions
|
|
134
|
+
*/
|
|
135
|
+
export const useCalendarNavigation = () => {
|
|
136
|
+
const {
|
|
137
|
+
selectedDate,
|
|
138
|
+
currentMonth,
|
|
139
|
+
actions: { setSelectedDate, navigateMonth, goToToday, setCurrentMonth },
|
|
140
|
+
} = useCalendarStore((state) => state);
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
selectedDate,
|
|
144
|
+
currentMonth,
|
|
145
|
+
setSelectedDate,
|
|
146
|
+
navigateMonth,
|
|
147
|
+
goToToday,
|
|
148
|
+
setCurrentMonth,
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Hook for calendar events only
|
|
154
|
+
* Lightweight hook for just event operations
|
|
155
|
+
*/
|
|
156
|
+
export const useCalendarEvents = () => {
|
|
157
|
+
const {
|
|
158
|
+
events,
|
|
159
|
+
isLoading,
|
|
160
|
+
error,
|
|
161
|
+
actions: {
|
|
162
|
+
loadEvents,
|
|
163
|
+
addEvent,
|
|
164
|
+
updateEvent,
|
|
165
|
+
deleteEvent,
|
|
166
|
+
completeEvent,
|
|
167
|
+
uncompleteEvent,
|
|
168
|
+
clearError,
|
|
169
|
+
},
|
|
170
|
+
} = useCalendarStore((state) => state);
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
events,
|
|
174
|
+
isLoading,
|
|
175
|
+
error,
|
|
176
|
+
loadEvents,
|
|
177
|
+
addEvent,
|
|
178
|
+
updateEvent,
|
|
179
|
+
deleteEvent,
|
|
180
|
+
completeEvent,
|
|
181
|
+
uncompleteEvent,
|
|
182
|
+
clearError,
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Hook for system calendar integration (expo-calendar)
|
|
188
|
+
*
|
|
189
|
+
* USAGE:
|
|
190
|
+
* ```tsx
|
|
191
|
+
* const {
|
|
192
|
+
* systemCalendars,
|
|
193
|
+
* permission,
|
|
194
|
+
* requestPermission,
|
|
195
|
+
* syncEventToCalendar,
|
|
196
|
+
* updateSyncedEvent,
|
|
197
|
+
* deleteSyncedEvent,
|
|
198
|
+
* } = useSystemCalendar();
|
|
199
|
+
*
|
|
200
|
+
* // Request permission
|
|
201
|
+
* const granted = await requestPermission();
|
|
202
|
+
*
|
|
203
|
+
* // Sync event to device calendar
|
|
204
|
+
* await syncEventToCalendar(event);
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export const useSystemCalendar = () => {
|
|
208
|
+
const [systemCalendars, setSystemCalendars] = useState<SystemCalendar[]>([]);
|
|
209
|
+
const [permission, setPermission] = useState<CalendarPermissionResult | null>(null);
|
|
210
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
211
|
+
|
|
212
|
+
const { actions } = useCalendarStore((state) => state);
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Request calendar permissions
|
|
216
|
+
*/
|
|
217
|
+
const requestPermission = useCallback(async (): Promise<boolean> => {
|
|
218
|
+
setIsLoading(true);
|
|
219
|
+
try {
|
|
220
|
+
const result = await CalendarService.requestPermissions();
|
|
221
|
+
setPermission(result);
|
|
222
|
+
return result.granted;
|
|
223
|
+
} catch {
|
|
224
|
+
return false;
|
|
225
|
+
} finally {
|
|
226
|
+
setIsLoading(false);
|
|
227
|
+
}
|
|
228
|
+
}, []);
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Load system calendars
|
|
232
|
+
*/
|
|
233
|
+
const loadSystemCalendars = useCallback(async () => {
|
|
234
|
+
setIsLoading(true);
|
|
235
|
+
try {
|
|
236
|
+
const calendars = await CalendarService.getSystemCalendars();
|
|
237
|
+
setSystemCalendars(calendars);
|
|
238
|
+
} catch {
|
|
239
|
+
setSystemCalendars([]);
|
|
240
|
+
} finally {
|
|
241
|
+
setIsLoading(false);
|
|
242
|
+
}
|
|
243
|
+
}, []);
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Sync event to system calendar
|
|
247
|
+
*/
|
|
248
|
+
const syncEventToCalendar = useCallback(
|
|
249
|
+
async (event: CalendarEvent): Promise<boolean> => {
|
|
250
|
+
setIsLoading(true);
|
|
251
|
+
try {
|
|
252
|
+
const result = await CalendarService.syncToSystemCalendar(event);
|
|
253
|
+
|
|
254
|
+
if (result.success && result.eventId && result.calendarId) {
|
|
255
|
+
// Update event with system calendar info
|
|
256
|
+
await actions.updateEvent({
|
|
257
|
+
id: event.id,
|
|
258
|
+
systemCalendar: {
|
|
259
|
+
eventId: result.eventId,
|
|
260
|
+
calendarId: result.calendarId,
|
|
261
|
+
lastSyncedAt: new Date(),
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return false;
|
|
268
|
+
} catch {
|
|
269
|
+
return false;
|
|
270
|
+
} finally {
|
|
271
|
+
setIsLoading(false);
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
[actions]
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Update synced event in system calendar
|
|
279
|
+
*/
|
|
280
|
+
const updateSyncedEvent = useCallback(async (event: CalendarEvent): Promise<boolean> => {
|
|
281
|
+
if (!event.systemCalendar) return false;
|
|
282
|
+
|
|
283
|
+
setIsLoading(true);
|
|
284
|
+
try {
|
|
285
|
+
const result = await CalendarService.updateSystemCalendarEvent(event);
|
|
286
|
+
|
|
287
|
+
if (result.success) {
|
|
288
|
+
// Update last synced timestamp
|
|
289
|
+
await actions.updateEvent({
|
|
290
|
+
id: event.id,
|
|
291
|
+
systemCalendar: {
|
|
292
|
+
...event.systemCalendar,
|
|
293
|
+
lastSyncedAt: new Date(),
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return false;
|
|
300
|
+
} catch {
|
|
301
|
+
return false;
|
|
302
|
+
} finally {
|
|
303
|
+
setIsLoading(false);
|
|
304
|
+
}
|
|
305
|
+
}, [actions]);
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Delete synced event from system calendar
|
|
309
|
+
*/
|
|
310
|
+
const deleteSyncedEvent = useCallback(
|
|
311
|
+
async (event: CalendarEvent): Promise<boolean> => {
|
|
312
|
+
if (!event.systemCalendar) return false;
|
|
313
|
+
|
|
314
|
+
setIsLoading(true);
|
|
315
|
+
try {
|
|
316
|
+
const result = await CalendarService.removeFromSystemCalendar(
|
|
317
|
+
event.systemCalendar.eventId
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
if (result.success) {
|
|
321
|
+
// Remove system calendar info from event
|
|
322
|
+
await actions.updateEvent({
|
|
323
|
+
id: event.id,
|
|
324
|
+
systemCalendar: undefined,
|
|
325
|
+
});
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return false;
|
|
330
|
+
} catch {
|
|
331
|
+
return false;
|
|
332
|
+
} finally {
|
|
333
|
+
setIsLoading(false);
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
[actions]
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
// Load calendars when permission is granted
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
if (permission?.granted) {
|
|
342
|
+
loadSystemCalendars();
|
|
343
|
+
}
|
|
344
|
+
}, [permission, loadSystemCalendars]);
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
systemCalendars,
|
|
348
|
+
permission,
|
|
349
|
+
isLoading,
|
|
350
|
+
requestPermission,
|
|
351
|
+
loadSystemCalendars,
|
|
352
|
+
syncEventToCalendar,
|
|
353
|
+
updateSyncedEvent,
|
|
354
|
+
deleteSyncedEvent,
|
|
355
|
+
};
|
|
356
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Celebration Config Entity
|
|
3
|
+
* Single Responsibility: Define celebration configuration types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface CelebrationAction {
|
|
7
|
+
label: string;
|
|
8
|
+
onPress: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CelebrationConfig {
|
|
12
|
+
title: string;
|
|
13
|
+
message: string;
|
|
14
|
+
primaryAction?: CelebrationAction;
|
|
15
|
+
secondaryAction?: CelebrationAction;
|
|
16
|
+
}
|
|
17
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fireworks Config Entity
|
|
3
|
+
* Single Responsibility: Define fireworks configuration types and constants
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FireworksConfig as AnimationFireworksConfig } from "../../../animation";
|
|
7
|
+
|
|
8
|
+
export interface ThemeColors {
|
|
9
|
+
primary?: string;
|
|
10
|
+
success?: string;
|
|
11
|
+
warning?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CelebrationFireworksConfig extends Omit<AnimationFireworksConfig, 'colors'> {
|
|
15
|
+
colors: string[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_FIREWORKS_COLORS = [
|
|
19
|
+
"#FF6B6B",
|
|
20
|
+
"#4ECDC4",
|
|
21
|
+
"#FFE66D",
|
|
22
|
+
"#A8E6CF",
|
|
23
|
+
"#95E1D3",
|
|
24
|
+
"#F38181",
|
|
25
|
+
"#AA96DA",
|
|
26
|
+
] as const;
|
|
27
|
+
|
|
28
|
+
export const DEFAULT_FIREWORKS_CONFIG: Required<Pick<CelebrationFireworksConfig, "particleCount" | "duration">> = {
|
|
29
|
+
particleCount: 80,
|
|
30
|
+
duration: 2000,
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @umituz/react-native-celebration - Public API
|
|
3
|
+
*
|
|
4
|
+
* Celebration animations and effects for React Native applications.
|
|
5
|
+
* Built on top of ../../../animation for consistent animations.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Celebration modals with fireworks
|
|
9
|
+
* - Configurable animations
|
|
10
|
+
* - Theme integration
|
|
11
|
+
* - State management
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { useCelebrationState, CelebrationModal, Animated } from '@umituz/react-native-celebration';
|
|
16
|
+
*
|
|
17
|
+
* const MyCelebration = () => {
|
|
18
|
+
* const { visible, show, hide, config } = useCelebrationState();
|
|
19
|
+
*
|
|
20
|
+
* return (
|
|
21
|
+
* <CelebrationModal
|
|
22
|
+
* visible={visible}
|
|
23
|
+
* config={config!}
|
|
24
|
+
* onClose={hide}
|
|
25
|
+
* themeColors={{ primary: '#007AFF', success: '#34C759' }}
|
|
26
|
+
* />
|
|
27
|
+
* );
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// DOMAIN LAYER - Entities
|
|
36
|
+
// =============================================================================
|
|
37
|
+
|
|
38
|
+
export type {
|
|
39
|
+
CelebrationConfig,
|
|
40
|
+
CelebrationAction,
|
|
41
|
+
} from "./domain/entities/CelebrationConfig";
|
|
42
|
+
|
|
43
|
+
export type {
|
|
44
|
+
ThemeColors,
|
|
45
|
+
CelebrationFireworksConfig,
|
|
46
|
+
} from "./domain/entities/FireworksConfig";
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
DEFAULT_FIREWORKS_COLORS,
|
|
50
|
+
DEFAULT_FIREWORKS_CONFIG,
|
|
51
|
+
} from "./domain/entities/FireworksConfig";
|
|
52
|
+
|
|
53
|
+
// =============================================================================
|
|
54
|
+
// INFRASTRUCTURE LAYER - Services
|
|
55
|
+
// =============================================================================
|
|
56
|
+
|
|
57
|
+
export { FireworksConfigService } from "./infrastructure/services/FireworksConfigService";
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// PRESENTATION LAYER - Hooks
|
|
63
|
+
// =============================================================================
|
|
64
|
+
|
|
65
|
+
export { useCelebrationState } from "./presentation/hooks/useCelebrationState";
|
|
66
|
+
export type { UseCelebrationStateReturn } from "./presentation/hooks/useCelebrationState";
|
|
67
|
+
|
|
68
|
+
export { useCelebrationModalAnimation } from "./presentation/hooks/useCelebrationModalAnimation";
|
|
69
|
+
export type { UseCelebrationModalAnimationReturn } from "./presentation/hooks/useCelebrationModalAnimation";
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
// =============================================================================
|
|
74
|
+
// PRESENTATION LAYER - Components
|
|
75
|
+
// =============================================================================
|
|
76
|
+
|
|
77
|
+
export { CelebrationModal } from "./presentation/components/CelebrationModal";
|
|
78
|
+
export type { CelebrationModalProps } from "./presentation/components/CelebrationModal";
|
|
79
|
+
|
|
80
|
+
export { CelebrationModalContent } from "./presentation/components/CelebrationModalContent";
|
|
81
|
+
export type { CelebrationModalContentProps } from "./presentation/components/CelebrationModalContent";
|
|
82
|
+
|
|
83
|
+
export { CelebrationFireworksOverlay } from "./presentation/components/CelebrationFireworksOverlay";
|
|
84
|
+
export type { CelebrationFireworksOverlayProps } from "./presentation/components/CelebrationFireworksOverlay";
|
|
85
|
+
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// PRESENTATION LAYER - Styles
|
|
88
|
+
// =============================================================================
|
|
89
|
+
|
|
90
|
+
export { createCelebrationModalStyles } from "./presentation/styles/CelebrationModalStyles";
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fireworks Config Service
|
|
3
|
+
* Single Responsibility: Build fireworks configuration from theme colors
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
ThemeColors,
|
|
8
|
+
CelebrationFireworksConfig,
|
|
9
|
+
} from "../../domain/entities/FireworksConfig";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_FIREWORKS_COLORS,
|
|
12
|
+
DEFAULT_FIREWORKS_CONFIG,
|
|
13
|
+
} from "../../domain/entities/FireworksConfig";
|
|
14
|
+
|
|
15
|
+
export class FireworksConfigService {
|
|
16
|
+
/**
|
|
17
|
+
* Build fireworks configuration with theme colors
|
|
18
|
+
* Gracefully handles missing theme colors
|
|
19
|
+
*/
|
|
20
|
+
static build(
|
|
21
|
+
themeColors?: ThemeColors,
|
|
22
|
+
customConfig?: Partial<CelebrationFireworksConfig>,
|
|
23
|
+
): CelebrationFireworksConfig {
|
|
24
|
+
const colors: string[] = [];
|
|
25
|
+
|
|
26
|
+
// Add theme colors if available
|
|
27
|
+
if (themeColors?.primary) {
|
|
28
|
+
colors.push(themeColors.primary);
|
|
29
|
+
}
|
|
30
|
+
if (themeColors?.success) {
|
|
31
|
+
colors.push(themeColors.success);
|
|
32
|
+
}
|
|
33
|
+
if (themeColors?.warning) {
|
|
34
|
+
colors.push(themeColors.warning);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Add default colors
|
|
38
|
+
colors.push(...DEFAULT_FIREWORKS_COLORS);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
particleCount: customConfig?.particleCount ?? DEFAULT_FIREWORKS_CONFIG.particleCount,
|
|
42
|
+
duration: customConfig?.duration ?? DEFAULT_FIREWORKS_CONFIG.duration,
|
|
43
|
+
colors: customConfig?.colors ?? colors,
|
|
44
|
+
particleSize: customConfig?.particleSize,
|
|
45
|
+
spread: customConfig?.spread,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Celebration Fireworks Overlay
|
|
3
|
+
* Renders fireworks effect as an overlay
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, StyleSheet } from "react-native";
|
|
8
|
+
import { Fireworks } from "../../../animation";
|
|
9
|
+
import type { FireworksConfig } from "../../../animation";
|
|
10
|
+
|
|
11
|
+
export interface CelebrationFireworksOverlayProps {
|
|
12
|
+
visible: boolean;
|
|
13
|
+
config: FireworksConfig;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const CelebrationFireworksOverlay: React.FC<CelebrationFireworksOverlayProps> = ({
|
|
17
|
+
visible,
|
|
18
|
+
config,
|
|
19
|
+
}) => {
|
|
20
|
+
if (!visible) return null;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View style={StyleSheet.absoluteFill} pointerEvents="none">
|
|
24
|
+
<Fireworks
|
|
25
|
+
autoTrigger
|
|
26
|
+
triggerX={0.5}
|
|
27
|
+
triggerY={0.5}
|
|
28
|
+
{...config}
|
|
29
|
+
style={StyleSheet.absoluteFill}
|
|
30
|
+
/>
|
|
31
|
+
</View>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Celebration Modal Component
|
|
3
|
+
* Displays celebration modal with animations using BaseModal
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { Animated } from "../../../animation";
|
|
8
|
+
import { BaseModal } from "../../../BaseModal";
|
|
9
|
+
import { useCelebrationModalAnimation } from "../hooks/useCelebrationModalAnimation";
|
|
10
|
+
import { FireworksConfigService } from "../../infrastructure/services/FireworksConfigService";
|
|
11
|
+
import { CelebrationModalContent } from "./CelebrationModalContent";
|
|
12
|
+
import { CelebrationFireworksOverlay } from "./CelebrationFireworksOverlay";
|
|
13
|
+
import type { CelebrationConfig } from "../../domain/entities/CelebrationConfig";
|
|
14
|
+
import type { ThemeColors } from "../../domain/entities/FireworksConfig";
|
|
15
|
+
import type {
|
|
16
|
+
ModalAnimationConfig,
|
|
17
|
+
IconAnimationConfig,
|
|
18
|
+
} from "../../../animation";
|
|
19
|
+
|
|
20
|
+
export interface CelebrationModalProps {
|
|
21
|
+
visible: boolean;
|
|
22
|
+
config: CelebrationConfig;
|
|
23
|
+
onClose: () => void;
|
|
24
|
+
themeColors?: ThemeColors;
|
|
25
|
+
fireworksConfig?: Partial<import("../../../animation").FireworksConfig>;
|
|
26
|
+
animationConfig?: {
|
|
27
|
+
modal?: ModalAnimationConfig;
|
|
28
|
+
icon?: IconAnimationConfig;
|
|
29
|
+
};
|
|
30
|
+
renderContent?: (props: {
|
|
31
|
+
config: CelebrationConfig;
|
|
32
|
+
onClose: () => void;
|
|
33
|
+
iconStyle: ReturnType<typeof useCelebrationModalAnimation>["iconStyle"];
|
|
34
|
+
modalStyle: ReturnType<typeof useCelebrationModalAnimation>["modalStyle"];
|
|
35
|
+
}) => React.ReactNode;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const CelebrationModal: React.FC<CelebrationModalProps> = ({
|
|
39
|
+
visible,
|
|
40
|
+
config,
|
|
41
|
+
onClose,
|
|
42
|
+
themeColors,
|
|
43
|
+
fireworksConfig,
|
|
44
|
+
animationConfig,
|
|
45
|
+
renderContent,
|
|
46
|
+
}) => {
|
|
47
|
+
const { isReady, iconStyle, modalStyle } =
|
|
48
|
+
useCelebrationModalAnimation(visible, animationConfig);
|
|
49
|
+
|
|
50
|
+
const fireworks = FireworksConfigService.build(themeColors, fireworksConfig);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<CelebrationFireworksOverlay visible={visible} config={fireworks} />
|
|
55
|
+
|
|
56
|
+
<BaseModal
|
|
57
|
+
visible={visible && isReady}
|
|
58
|
+
onClose={onClose}
|
|
59
|
+
dismissOnBackdrop={true}
|
|
60
|
+
testID="celebration-modal"
|
|
61
|
+
>
|
|
62
|
+
<Animated.View style={modalStyle}>
|
|
63
|
+
{renderContent ? (
|
|
64
|
+
renderContent({ config, onClose, iconStyle, modalStyle })
|
|
65
|
+
) : themeColors ? (
|
|
66
|
+
<CelebrationModalContent
|
|
67
|
+
config={config}
|
|
68
|
+
onClose={onClose}
|
|
69
|
+
themeColors={themeColors}
|
|
70
|
+
iconStyle={iconStyle}
|
|
71
|
+
modalStyle={modalStyle}
|
|
72
|
+
/>
|
|
73
|
+
) : null}
|
|
74
|
+
</Animated.View>
|
|
75
|
+
</BaseModal>
|
|
76
|
+
</>
|
|
77
|
+
);
|
|
78
|
+
};
|