@campxdev/react-blueprint 2.2.3 → 2.2.4

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.
Files changed (26) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/types/src/components/Navigation/Calendar/Calendar.d.ts +3 -0
  3. package/dist/cjs/types/src/components/Navigation/Calendar/index.d.ts +3 -0
  4. package/dist/cjs/types/src/components/Navigation/Calendar/styles.d.ts +9 -0
  5. package/dist/cjs/types/src/components/Navigation/Calendar/types.d.ts +90 -0
  6. package/dist/cjs/types/src/components/Navigation/Calendar/utils.d.ts +55 -0
  7. package/dist/cjs/types/src/components/Navigation/export.d.ts +2 -0
  8. package/dist/cjs/types/src/stories/Navigation/Calendar.stories.d.ts +10 -0
  9. package/dist/esm/index.js +2 -2
  10. package/dist/esm/types/src/components/Navigation/Calendar/Calendar.d.ts +3 -0
  11. package/dist/esm/types/src/components/Navigation/Calendar/index.d.ts +3 -0
  12. package/dist/esm/types/src/components/Navigation/Calendar/styles.d.ts +9 -0
  13. package/dist/esm/types/src/components/Navigation/Calendar/types.d.ts +90 -0
  14. package/dist/esm/types/src/components/Navigation/Calendar/utils.d.ts +55 -0
  15. package/dist/esm/types/src/components/Navigation/export.d.ts +2 -0
  16. package/dist/esm/types/src/stories/Navigation/Calendar.stories.d.ts +10 -0
  17. package/dist/index.d.ts +151 -4
  18. package/package.json +6 -1
  19. package/src/components/Navigation/Calendar/Calendar.tsx +243 -0
  20. package/src/components/Navigation/Calendar/README.md +308 -0
  21. package/src/components/Navigation/Calendar/index.ts +3 -0
  22. package/src/components/Navigation/Calendar/styles.tsx +222 -0
  23. package/src/components/Navigation/Calendar/types.ts +120 -0
  24. package/src/components/Navigation/Calendar/utils.ts +265 -0
  25. package/src/components/Navigation/export.ts +2 -0
  26. package/src/stories/Navigation/Calendar.stories.tsx +475 -0
@@ -0,0 +1,265 @@
1
+ import {
2
+ addDays,
3
+ eachDayOfInterval,
4
+ endOfWeek,
5
+ format,
6
+ startOfWeek,
7
+ } from 'date-fns';
8
+ import { CalendarEvent } from './types';
9
+
10
+ /**
11
+ * Generate recurring events based on a pattern
12
+ */
13
+ export interface RecurringEventConfig {
14
+ title: string;
15
+ startTime: string; // HH:mm format
16
+ endTime: string; // HH:mm format
17
+ startDate: Date;
18
+ endDate?: Date;
19
+ daysOfWeek?: number[]; // 0 = Sunday, 1 = Monday, etc.
20
+ interval?: number; // For weekly/monthly recurring
21
+ backgroundColor?: string;
22
+ extendedProps?: { [key: string]: any };
23
+ }
24
+
25
+ export const generateRecurringEvents = (
26
+ config: RecurringEventConfig,
27
+ maxEvents: number = 50,
28
+ ): CalendarEvent[] => {
29
+ const events: CalendarEvent[] = [];
30
+ const {
31
+ title,
32
+ startTime,
33
+ endTime,
34
+ startDate,
35
+ endDate = addDays(startDate, 365), // Default to 1 year
36
+ daysOfWeek = [1, 2, 3, 4, 5], // Default to weekdays
37
+ backgroundColor,
38
+ extendedProps,
39
+ } = config;
40
+
41
+ let currentDate = new Date(startDate);
42
+ let eventCount = 0;
43
+
44
+ while (currentDate <= endDate && eventCount < maxEvents) {
45
+ if (daysOfWeek.includes(currentDate.getDay())) {
46
+ const eventId = `recurring-${title
47
+ .toLowerCase()
48
+ .replace(/\s+/g, '-')}-${eventCount}`;
49
+ const startDateTime = format(currentDate, `yyyy-MM-dd'T'${startTime}:00`);
50
+ const endDateTime = format(currentDate, `yyyy-MM-dd'T'${endTime}:00`);
51
+
52
+ events.push({
53
+ id: eventId,
54
+ title,
55
+ start: startDateTime,
56
+ end: endDateTime,
57
+ backgroundColor,
58
+ extendedProps,
59
+ });
60
+
61
+ eventCount++;
62
+ }
63
+ currentDate = addDays(currentDate, 1);
64
+ }
65
+
66
+ return events;
67
+ };
68
+
69
+ /**
70
+ * Generate sample business events for demonstration
71
+ */
72
+ export const generateBusinessEvents = (
73
+ startDate: Date = new Date(),
74
+ ): CalendarEvent[] => {
75
+ const weekStart = startOfWeek(startDate);
76
+ const weekEnd = endOfWeek(startDate);
77
+ const weekDays = eachDayOfInterval({ start: weekStart, end: weekEnd });
78
+
79
+ const eventTemplates = [
80
+ { title: 'Daily Standup', time: '09:00-09:30', color: '#1976d2' },
81
+ { title: 'Team Meeting', time: '14:00-15:00', color: '#388e3c' },
82
+ { title: 'Code Review', time: '10:30-11:30', color: '#f57c00' },
83
+ { title: 'Sprint Planning', time: '13:00-16:00', color: '#d32f2f' },
84
+ { title: 'Client Call', time: '11:00-12:00', color: '#7b1fa2' },
85
+ ];
86
+
87
+ const events: CalendarEvent[] = [];
88
+
89
+ weekDays.forEach((day, dayIndex) => {
90
+ // Skip weekends for business events
91
+ if (day.getDay() === 0 || day.getDay() === 6) return;
92
+
93
+ // Add 1-2 random events per day
94
+ const numEvents = Math.floor(Math.random() * 2) + 1;
95
+ const shuffledTemplates = [...eventTemplates].sort(
96
+ () => Math.random() - 0.5,
97
+ );
98
+
99
+ for (let i = 0; i < numEvents && i < shuffledTemplates.length; i++) {
100
+ const template = shuffledTemplates[i];
101
+ const [startTime, endTime] = template.time.split('-');
102
+
103
+ events.push({
104
+ id: `business-${dayIndex}-${i}`,
105
+ title: template.title,
106
+ start: format(day, `yyyy-MM-dd'T'${startTime}:00`),
107
+ end: format(day, `yyyy-MM-dd'T'${endTime}:00`),
108
+ backgroundColor: template.color,
109
+ extendedProps: {
110
+ type: 'business',
111
+ department: ['Engineering', 'Sales', 'Marketing'][
112
+ Math.floor(Math.random() * 3)
113
+ ],
114
+ },
115
+ });
116
+ }
117
+ });
118
+
119
+ return events;
120
+ };
121
+
122
+ /**
123
+ * Filter events by date range
124
+ */
125
+ export const filterEventsByDateRange = (
126
+ events: CalendarEvent[],
127
+ startDate: Date,
128
+ endDate: Date,
129
+ ): CalendarEvent[] => {
130
+ return events.filter((event) => {
131
+ const eventStart = new Date(event.start);
132
+ return eventStart >= startDate && eventStart <= endDate;
133
+ });
134
+ };
135
+
136
+ /**
137
+ * Group events by date
138
+ */
139
+ export const groupEventsByDate = (
140
+ events: CalendarEvent[],
141
+ ): { [date: string]: CalendarEvent[] } => {
142
+ return events.reduce((groups: { [date: string]: CalendarEvent[] }, event) => {
143
+ const date = format(new Date(event.start), 'yyyy-MM-dd');
144
+ if (!groups[date]) {
145
+ groups[date] = [];
146
+ }
147
+ groups[date].push(event);
148
+ return groups;
149
+ }, {});
150
+ };
151
+
152
+ /**
153
+ * Calculate event statistics
154
+ */
155
+ export interface EventStats {
156
+ totalEvents: number;
157
+ eventsThisWeek: number;
158
+ eventsThisMonth: number;
159
+ averageEventsPerDay: number;
160
+ mostBusyDay: string;
161
+ leastBusyDay: string;
162
+ }
163
+
164
+ export const calculateEventStats = (events: CalendarEvent[]): EventStats => {
165
+ const now = new Date();
166
+ const weekStart = startOfWeek(now);
167
+ const weekEnd = endOfWeek(now);
168
+ const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
169
+ const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0);
170
+
171
+ const eventsThisWeek = filterEventsByDateRange(events, weekStart, weekEnd);
172
+ const eventsThisMonth = filterEventsByDateRange(events, monthStart, monthEnd);
173
+ const eventsByDate = groupEventsByDate(events);
174
+
175
+ const dailyCounts = Object.values(eventsByDate).map(
176
+ (dayEvents) => dayEvents.length,
177
+ );
178
+ const averageEventsPerDay =
179
+ dailyCounts.length > 0
180
+ ? dailyCounts.reduce((sum, count) => sum + count, 0) / dailyCounts.length
181
+ : 0;
182
+
183
+ const sortedDates = Object.keys(eventsByDate).sort();
184
+ const mostBusyDate = sortedDates.reduce(
185
+ (max, date) =>
186
+ eventsByDate[date].length > eventsByDate[max]?.length ? date : max,
187
+ sortedDates[0],
188
+ );
189
+ const leastBusyDate = sortedDates.reduce(
190
+ (min, date) =>
191
+ eventsByDate[date].length < eventsByDate[min]?.length ? date : min,
192
+ sortedDates[0],
193
+ );
194
+
195
+ return {
196
+ totalEvents: events.length,
197
+ eventsThisWeek: eventsThisWeek.length,
198
+ eventsThisMonth: eventsThisMonth.length,
199
+ averageEventsPerDay: Math.round(averageEventsPerDay * 100) / 100,
200
+ mostBusyDay: mostBusyDate
201
+ ? format(new Date(mostBusyDate), 'EEEE, MMMM do')
202
+ : 'N/A',
203
+ leastBusyDay: leastBusyDate
204
+ ? format(new Date(leastBusyDate), 'EEEE, MMMM do')
205
+ : 'N/A',
206
+ };
207
+ };
208
+
209
+ /**
210
+ * Convert events to different formats
211
+ */
212
+ export const exportEventsToCSV = (events: CalendarEvent[]): string => {
213
+ const headers = [
214
+ 'Title',
215
+ 'Start Date',
216
+ 'Start Time',
217
+ 'End Date',
218
+ 'End Time',
219
+ 'All Day',
220
+ ];
221
+ const rows = events.map((event) => [
222
+ event.title,
223
+ format(new Date(event.start), 'yyyy-MM-dd'),
224
+ event.allDay ? '' : format(new Date(event.start), 'HH:mm'),
225
+ event.end ? format(new Date(event.end), 'yyyy-MM-dd') : '',
226
+ event.end && !event.allDay ? format(new Date(event.end), 'HH:mm') : '',
227
+ event.allDay ? 'Yes' : 'No',
228
+ ]);
229
+
230
+ return [headers, ...rows].map((row) => row.join(',')).join('\n');
231
+ };
232
+
233
+ /**
234
+ * Validate event data
235
+ */
236
+ export const validateEvent = (
237
+ event: Partial<CalendarEvent>,
238
+ ): { isValid: boolean; errors: string[] } => {
239
+ const errors: string[] = [];
240
+
241
+ if (!event.title || event.title.trim() === '') {
242
+ errors.push('Event title is required');
243
+ }
244
+
245
+ if (!event.start) {
246
+ errors.push('Event start date is required');
247
+ }
248
+
249
+ if (event.start && event.end) {
250
+ const start = new Date(event.start);
251
+ const end = new Date(event.end);
252
+ if (start >= end) {
253
+ errors.push('Event end time must be after start time');
254
+ }
255
+ }
256
+
257
+ if (event.title && event.title.length > 100) {
258
+ errors.push('Event title must be less than 100 characters');
259
+ }
260
+
261
+ return {
262
+ isValid: errors.length === 0,
263
+ errors,
264
+ };
265
+ };
@@ -1,5 +1,7 @@
1
1
  export * from '../Layout/PageHeader/components/TableColumnsSelector/TableColumnsSelector';
2
2
  export * from './Breadcrumbs/Breadcrumbs';
3
+ export * from './Calendar';
4
+ export * from './Calendar/Calendar';
3
5
  export * from './ConfirmDialog/ConfirmDialog';
4
6
  export * from './Dialog/Dialog';
5
7
  export * from './DialogButton/DialogButton';