@umituz/react-native-design-system 2.3.13 → 2.3.14

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.3.13",
3
+ "version": "2.3.14",
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",
@@ -54,6 +54,11 @@
54
54
  "@react-native-async-storage/async-storage": ">=2.0.0",
55
55
  "@react-native-community/datetimepicker": ">=8.0.0",
56
56
  "@react-navigation/native": ">=6.0.0",
57
+ "@umituz/react-native-uuid": "latest",
58
+ "expo-application": ">=5.0.0",
59
+ "expo-calendar": ">=13.0.0",
60
+ "expo-crypto": ">=13.0.0",
61
+ "expo-device": ">=5.0.0",
57
62
  "expo-linear-gradient": ">=15.0.0",
58
63
  "react": ">=19.0.0",
59
64
  "react-native": ">=0.81.0",
@@ -61,11 +66,7 @@
61
66
  "react-native-reanimated": ">=3.16.0",
62
67
  "react-native-safe-area-context": ">=5.0.0",
63
68
  "react-native-svg": ">=15.0.0",
64
- "zustand": ">=5.0.0",
65
- "expo-device": ">=5.0.0",
66
- "expo-application": ">=5.0.0",
67
- "@umituz/react-native-uuid": "latest",
68
- "expo-crypto": ">=13.0.0"
69
+ "zustand": ">=5.0.0"
69
70
  },
70
71
  "peerDependenciesMeta": {
71
72
  "expo-linear-gradient": {
@@ -95,10 +96,16 @@
95
96
  "@types/react": "~19.1.10",
96
97
  "@typescript-eslint/eslint-plugin": "^8.50.1",
97
98
  "@typescript-eslint/parser": "^8.50.1",
99
+ "@umituz/react-native-uuid": "latest",
98
100
  "eslint": "^9.39.2",
99
101
  "eslint-plugin-react": "^7.37.5",
100
102
  "eslint-plugin-react-hooks": "^7.0.1",
101
103
  "eslint-plugin-react-native": "^5.0.0",
104
+ "expo-application": "~5.9.1",
105
+ "expo-calendar": "~14.0.0",
106
+ "expo-crypto": "~14.0.0",
107
+ "expo-device": "~7.0.2",
108
+ "expo-localization": "~16.0.1",
102
109
  "react": "19.1.0",
103
110
  "react-native": "0.81.5",
104
111
  "react-native-gesture-handler": "^2.20.0",
@@ -106,12 +113,7 @@
106
113
  "react-native-safe-area-context": "^5.6.0",
107
114
  "react-native-svg": "15.12.1",
108
115
  "typescript": "~5.9.2",
109
- "zustand": "^5.0.2",
110
- "expo-device": "~7.0.2",
111
- "expo-application": "~5.9.1",
112
- "expo-localization": "~16.0.1",
113
- "@umituz/react-native-uuid": "latest",
114
- "expo-crypto": "~14.0.0"
116
+ "zustand": "^5.0.2"
115
117
  },
116
118
  "publishConfig": {
117
119
  "access": "public"
package/src/index.ts CHANGED
@@ -301,6 +301,31 @@ export {
301
301
  type Alert,
302
302
  type AlertAction,
303
303
  type AlertOptions,
304
+ // Calendar
305
+ AtomicCalendar,
306
+ useCalendar,
307
+ useCalendarNavigation,
308
+ useCalendarEvents,
309
+ useSystemCalendar,
310
+ CalendarService,
311
+ CalendarPermissions,
312
+ CalendarEvents,
313
+ CalendarGeneration,
314
+ CalendarSync,
315
+ DateUtilities,
316
+ useCalendarStore,
317
+ type AtomicCalendarProps,
318
+ type UseCalendarReturn,
319
+ type CalendarEvent,
320
+ type CreateCalendarEventRequest,
321
+ type UpdateCalendarEventRequest,
322
+ type SystemCalendar,
323
+ type CalendarPermissionResult,
324
+ type CalendarDay,
325
+ type CalendarMonth,
326
+ type CalendarWeek,
327
+ type ICalendarRepository,
328
+ type CalendarViewMode,
304
329
  } from './molecules';
305
330
 
306
331
  // =============================================================================
@@ -0,0 +1,115 @@
1
+ /**
2
+ * CalendarDay Entity
3
+ *
4
+ * Represents a single day in a calendar view with its properties and associated events.
5
+ *
6
+ * Design Philosophy:
7
+ * - Timezone-aware (uses timezone domain for date calculations)
8
+ * - Event-agnostic (works with any CalendarEvent type)
9
+ * - View-ready (contains all display state)
10
+ * - Immutable (never mutate, create new instances)
11
+ */
12
+
13
+ import type { CalendarEvent } from './CalendarEvent.entity';
14
+
15
+ export interface CalendarDay {
16
+ /**
17
+ * The date this calendar day represents
18
+ */
19
+ date: Date;
20
+
21
+ /**
22
+ * Whether this day belongs to the currently displayed month
23
+ * Used to gray out days from prev/next months in calendar grid
24
+ */
25
+ isCurrentMonth: boolean;
26
+
27
+ /**
28
+ * Whether this day is today (timezone-aware via timezone domain)
29
+ */
30
+ isToday: boolean;
31
+
32
+ /**
33
+ * Whether this day is currently selected by the user
34
+ */
35
+ isSelected: boolean;
36
+
37
+ /**
38
+ * Events scheduled for this day
39
+ * @default []
40
+ */
41
+ events: CalendarEvent[];
42
+
43
+ /**
44
+ * Whether this day is disabled/non-selectable
45
+ * @example Past dates, dates outside valid range
46
+ * @default false
47
+ */
48
+ isDisabled?: boolean;
49
+
50
+ /**
51
+ * Whether this day is a weekend (Saturday or Sunday)
52
+ * Useful for styling weekend days differently
53
+ */
54
+ isWeekend?: boolean;
55
+ }
56
+
57
+ /**
58
+ * Calendar Month Configuration
59
+ *
60
+ * Represents a full month view with all necessary display information
61
+ */
62
+ export interface CalendarMonth {
63
+ /**
64
+ * Year of the month
65
+ */
66
+ year: number;
67
+
68
+ /**
69
+ * Month (0-indexed: 0 = January, 11 = December)
70
+ */
71
+ month: number;
72
+
73
+ /**
74
+ * All days to display in the calendar grid (usually 42 days = 6 weeks)
75
+ * Includes days from previous and next months to fill the grid
76
+ */
77
+ days: CalendarDay[];
78
+
79
+ /**
80
+ * First day of the month
81
+ */
82
+ firstDay: Date;
83
+
84
+ /**
85
+ * Last day of the month
86
+ */
87
+ lastDay: Date;
88
+
89
+ /**
90
+ * Total number of days in this month
91
+ */
92
+ daysInMonth: number;
93
+ }
94
+
95
+ /**
96
+ * Week View Configuration
97
+ *
98
+ * Represents a week view with 7 days
99
+ */
100
+ export interface CalendarWeek {
101
+ /**
102
+ * Start date of the week (usually Sunday)
103
+ */
104
+ startDate: Date;
105
+
106
+ /**
107
+ * End date of the week (usually Saturday)
108
+ */
109
+ endDate: Date;
110
+
111
+ /**
112
+ * All 7 days in the week
113
+ */
114
+ days: CalendarDay[];
115
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * CalendarEvent Entity
3
+ *
4
+ * Generic calendar event that can represent:
5
+ * - Workouts (fitness apps)
6
+ * - Habits (habit tracking apps)
7
+ * - Tasks (productivity apps)
8
+ * - Appointments (scheduling apps)
9
+ * - Any other time-based event
10
+ *
11
+ * Design Philosophy:
12
+ * - Generic and reusable across all app types
13
+ * - Extensible via metadata field
14
+ * - Simple core properties
15
+ * - App-specific data in metadata
16
+ */
17
+
18
+ export interface CalendarEvent {
19
+ /**
20
+ * Unique identifier for the event
21
+ */
22
+ id: string;
23
+
24
+ /**
25
+ * Event title/name
26
+ * @example "Morning Workout", "Team Meeting", "Water plants"
27
+ */
28
+ title: string;
29
+
30
+ /**
31
+ * Event date in YYYY-MM-DD format (timezone-aware via timezone domain)
32
+ * @example "2024-10-30"
33
+ */
34
+ date: string;
35
+
36
+ /**
37
+ * Optional event time in HH:mm format
38
+ * @example "09:30", "14:00"
39
+ */
40
+ time?: string;
41
+
42
+ /**
43
+ * Optional event color for visual distinction
44
+ * Uses design token color names or hex values
45
+ * @example "primary", "success", "#FF5733"
46
+ */
47
+ color?: string;
48
+
49
+ /**
50
+ * Whether the event has been completed/checked off
51
+ * @default false
52
+ */
53
+ isCompleted?: boolean;
54
+
55
+ /**
56
+ * Optional duration in minutes
57
+ * @example 30, 60, 90
58
+ */
59
+ duration?: number;
60
+
61
+ /**
62
+ * Optional event description/notes
63
+ */
64
+ description?: string;
65
+
66
+ /**
67
+ * Optional location for the event
68
+ */
69
+ location?: string;
70
+
71
+ /**
72
+ * Reminders/alarms (minutes before event)
73
+ * @example [15, 30] → 15 mins and 30 mins before
74
+ */
75
+ reminders?: number[];
76
+
77
+ /**
78
+ * System calendar sync (expo-calendar integration)
79
+ */
80
+ systemCalendar?: {
81
+ /**
82
+ * System calendar ID where event is synced
83
+ */
84
+ calendarId: string;
85
+
86
+ /**
87
+ * System event ID from device calendar
88
+ */
89
+ eventId: string;
90
+
91
+ /**
92
+ * Last sync timestamp
93
+ */
94
+ lastSyncedAt: Date;
95
+ };
96
+
97
+ /**
98
+ * App-specific metadata
99
+ * Use this for domain-specific properties
100
+ * @example
101
+ * // Workout app:
102
+ * metadata: { workoutTemplateId: "abc123", exercises: [...] }
103
+ *
104
+ * // Habit app:
105
+ * metadata: { habitId: "xyz789", streak: 5 }
106
+ */
107
+ metadata?: unknown;
108
+
109
+ /**
110
+ * Recurring event configuration
111
+ */
112
+ recurring?: {
113
+ /**
114
+ * Recurrence pattern
115
+ */
116
+ pattern: 'daily' | 'weekly' | 'monthly' | 'custom';
117
+
118
+ /**
119
+ * Interval for recurrence
120
+ * @example pattern: 'weekly', interval: 2 → every 2 weeks
121
+ */
122
+ interval?: number;
123
+
124
+ /**
125
+ * Days of week for weekly recurrence (0 = Sunday, 6 = Saturday)
126
+ * @example [1, 3, 5] → Monday, Wednesday, Friday
127
+ */
128
+ daysOfWeek?: number[];
129
+
130
+ /**
131
+ * End date for recurrence (YYYY-MM-DD)
132
+ */
133
+ endDate?: string;
134
+ };
135
+
136
+ /**
137
+ * Creation timestamp
138
+ */
139
+ createdAt: Date;
140
+
141
+ /**
142
+ * Last update timestamp
143
+ */
144
+ updatedAt: Date;
145
+ }
146
+
147
+ /**
148
+ * Request object for creating a new calendar event
149
+ */
150
+ export interface CreateCalendarEventRequest {
151
+ title: string;
152
+ date: string;
153
+ time?: string;
154
+ color?: string;
155
+ duration?: number;
156
+ description?: string;
157
+ location?: string;
158
+ reminders?: number[];
159
+ metadata?: unknown;
160
+ recurring?: CalendarEvent['recurring'];
161
+ syncToSystemCalendar?: boolean; // Auto-sync to device calendar
162
+ }
163
+
164
+ /**
165
+ * Request object for updating an existing calendar event
166
+ */
167
+ export interface UpdateCalendarEventRequest {
168
+ id: string;
169
+ title?: string;
170
+ date?: string;
171
+ time?: string;
172
+ color?: string;
173
+ isCompleted?: boolean;
174
+ duration?: number;
175
+ description?: string;
176
+ location?: string;
177
+ reminders?: number[];
178
+ metadata?: unknown;
179
+ recurring?: CalendarEvent['recurring'];
180
+ systemCalendar?: CalendarEvent['systemCalendar'];
181
+ }
182
+
183
+ /**
184
+ * System calendar list item
185
+ */
186
+ export interface SystemCalendar {
187
+ id: string;
188
+ title: string;
189
+ color: string;
190
+ source: string;
191
+ isPrimary: boolean;
192
+ allowsModifications: boolean;
193
+ }
194
+
195
+ /**
196
+ * Calendar permission result
197
+ */
198
+ export interface CalendarPermissionResult {
199
+ granted: boolean;
200
+ canAskAgain: boolean;
201
+ status: string;
202
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * ICalendarRepository Interface
3
+ *
4
+ * Port (interface) for calendar data access operations.
5
+ * Implementations can use any storage mechanism (AsyncStorage, SQLite, etc.)
6
+ *
7
+ * Design Philosophy:
8
+ * - Repository pattern (DDD)
9
+ * - Storage-agnostic
10
+ * - CRUD operations for calendar events
11
+ * - Query methods for finding events
12
+ */
13
+
14
+ import type {
15
+ CalendarEvent,
16
+ CreateCalendarEventRequest,
17
+ UpdateCalendarEventRequest,
18
+ } from '../entities/CalendarEvent.entity';
19
+
20
+ export interface ICalendarRepository {
21
+ /**
22
+ * Get all calendar events
23
+ * @returns Promise resolving to array of all events
24
+ */
25
+ getAllEvents(): Promise<CalendarEvent[]>;
26
+
27
+ /**
28
+ * Get a calendar event by ID
29
+ * @param id - Event ID
30
+ * @returns Promise resolving to event or null if not found
31
+ */
32
+ getEventById(id: string): Promise<CalendarEvent | null>;
33
+
34
+ /**
35
+ * Get events for a specific date
36
+ * @param date - Date string in YYYY-MM-DD format
37
+ * @returns Promise resolving to array of events for that date
38
+ */
39
+ getEventsByDate(date: string): Promise<CalendarEvent[]>;
40
+
41
+ /**
42
+ * Get events within a date range
43
+ * @param startDate - Start date (YYYY-MM-DD)
44
+ * @param endDate - End date (YYYY-MM-DD)
45
+ * @returns Promise resolving to array of events in range
46
+ */
47
+ getEventsByDateRange(startDate: string, endDate: string): Promise<CalendarEvent[]>;
48
+
49
+ /**
50
+ * Get events for a specific month
51
+ * @param year - Year (e.g., 2024)
52
+ * @param month - Month (0-indexed: 0 = January, 11 = December)
53
+ * @returns Promise resolving to array of events in that month
54
+ */
55
+ getEventsByMonth(year: number, month: number): Promise<CalendarEvent[]>;
56
+
57
+ /**
58
+ * Create a new calendar event
59
+ * @param request - Event creation data
60
+ * @returns Promise resolving to created event
61
+ */
62
+ createEvent(request: CreateCalendarEventRequest): Promise<CalendarEvent>;
63
+
64
+ /**
65
+ * Update an existing calendar event
66
+ * @param request - Event update data (must include id)
67
+ * @returns Promise resolving to updated event
68
+ */
69
+ updateEvent(request: UpdateCalendarEventRequest): Promise<CalendarEvent>;
70
+
71
+ /**
72
+ * Delete a calendar event
73
+ * @param id - Event ID to delete
74
+ * @returns Promise resolving to void
75
+ */
76
+ deleteEvent(id: string): Promise<void>;
77
+
78
+ /**
79
+ * Delete all events for a specific date
80
+ * @param date - Date string in YYYY-MM-DD format
81
+ * @returns Promise resolving to number of deleted events
82
+ */
83
+ deleteEventsByDate(date: string): Promise<number>;
84
+
85
+ /**
86
+ * Mark an event as completed
87
+ * @param id - Event ID
88
+ * @returns Promise resolving to updated event
89
+ */
90
+ completeEvent(id: string): Promise<CalendarEvent>;
91
+
92
+ /**
93
+ * Mark an event as incomplete
94
+ * @param id - Event ID
95
+ * @returns Promise resolving to updated event
96
+ */
97
+ uncompleteEvent(id: string): Promise<CalendarEvent>;
98
+
99
+ /**
100
+ * Search events by title
101
+ * @param query - Search query string
102
+ * @returns Promise resolving to array of matching events
103
+ */
104
+ searchEvents(query: string): Promise<CalendarEvent[]>;
105
+
106
+ /**
107
+ * Get upcoming events (from today onwards)
108
+ * @param limit - Maximum number of events to return
109
+ * @returns Promise resolving to array of upcoming events
110
+ */
111
+ getUpcomingEvents(limit?: number): Promise<CalendarEvent[]>;
112
+
113
+ /**
114
+ * Get completed events count for a date range
115
+ * @param startDate - Start date (YYYY-MM-DD)
116
+ * @param endDate - End date (YYYY-MM-DD)
117
+ * @returns Promise resolving to count of completed events
118
+ */
119
+ getCompletedEventsCount(startDate: string, endDate: string): Promise<number>;
120
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Calendar Domain - Barrel Export
3
+ *
4
+ * Public API for the calendar domain.
5
+ * Provides generic, reusable calendar functionality for all factory-generated apps.
6
+ *
7
+ * Features:
8
+ * - Timezone-aware calendar generation (built-in DateUtilities)
9
+ * - Generic event system (workouts, habits, tasks, etc.)
10
+ * - Month/Week/Day views
11
+ * - Event CRUD operations with persistence
12
+ * - Completion tracking
13
+ * - Recurring events support
14
+ * - **NEW:** System calendar sync (expo-calendar) - iOS/Android only
15
+ *
16
+ * Usage:
17
+ * ```tsx
18
+ * import { useCalendar, AtomicCalendar, useSystemCalendar } from '@umituz/react-native-calendar';
19
+ *
20
+ * const MyScreen = () => {
21
+ * const { days, selectedDate, actions } = useCalendar();
22
+ * const {
23
+ * systemCalendars,
24
+ * permission,
25
+ * requestPermission,
26
+ * syncEventToCalendar,
27
+ * } = useSystemCalendar();
28
+ *
29
+ * // Request permission to access device calendar
30
+ * useEffect(() => {
31
+ * requestPermission();
32
+ * }, []);
33
+ *
34
+ * // Sync event to device calendar
35
+ * const handleCreateEvent = async (eventData) => {
36
+ * const event = await actions.addEvent(eventData);
37
+ * await syncEventToCalendar(event); // Sync to iOS/Android calendar
38
+ * };
39
+ *
40
+ * return (
41
+ * <AtomicCalendar
42
+ * days={days}
43
+ * selectedDate={selectedDate}
44
+ * onDateSelect={actions.setSelectedDate}
45
+ * />
46
+ * );
47
+ * };
48
+ * ```
49
+ */
50
+
51
+ // Domain Entities
52
+ export type {
53
+ CalendarEvent,
54
+ CreateCalendarEventRequest,
55
+ UpdateCalendarEventRequest,
56
+ SystemCalendar,
57
+ CalendarPermissionResult,
58
+ } from './domain/entities/CalendarEvent.entity';
59
+
60
+ export type {
61
+ CalendarDay,
62
+ CalendarMonth,
63
+ CalendarWeek,
64
+ } from './domain/entities/CalendarDay.entity';
65
+
66
+ // Domain Repositories
67
+ export type { ICalendarRepository } from './domain/repositories/ICalendarRepository';
68
+
69
+ // Infrastructure Services
70
+ export { CalendarService } from './infrastructure/services/CalendarService';
71
+ export { CalendarPermissions } from './infrastructure/services/CalendarPermissions';
72
+ export { CalendarEvents } from './infrastructure/services/CalendarEvents';
73
+ export { CalendarGeneration } from './infrastructure/services/CalendarGeneration';
74
+ export { CalendarSync } from './infrastructure/services/CalendarSync';
75
+
76
+ // Infrastructure Utils
77
+ export { DateUtilities } from './infrastructure/utils/DateUtilities';
78
+
79
+ // Infrastructure Storage
80
+ export {
81
+ useCalendarStore,
82
+ type CalendarViewMode,
83
+ } from './infrastructure/storage/CalendarStore';
84
+
85
+ // Presentation Hooks
86
+ export {
87
+ useCalendar,
88
+ useCalendarNavigation,
89
+ useCalendarEvents,
90
+ useSystemCalendar,
91
+ type UseCalendarReturn,
92
+ } from './presentation/hooks/useCalendar';
93
+
94
+ // Presentation Components
95
+ export {
96
+ AtomicCalendar,
97
+ type AtomicCalendarProps,
98
+ } from './presentation/components/AtomicCalendar';