kalendly 0.1.7 → 0.2.1

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 (39) hide show
  1. package/README.md +377 -662
  2. package/dist/core/index.js +3 -3
  3. package/dist/index.d.mts +61 -602
  4. package/dist/index.d.ts +61 -602
  5. package/dist/index.js +963 -2375
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +937 -2364
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/{vanilla/index.umd.js → index.umd.js} +438 -244
  10. package/dist/index.umd.js.map +1 -0
  11. package/dist/styles/calendar.css +96 -0
  12. package/package.json +54 -118
  13. package/dist/react/index.d.mts +0 -251
  14. package/dist/react/index.d.ts +0 -251
  15. package/dist/react/index.js +0 -969
  16. package/dist/react/index.js.map +0 -1
  17. package/dist/react/index.mjs +0 -924
  18. package/dist/react/index.mjs.map +0 -1
  19. package/dist/react-native/index.d.mts +0 -642
  20. package/dist/react-native/index.d.ts +0 -642
  21. package/dist/react-native/index.js +0 -1649
  22. package/dist/react-native/index.js.map +0 -1
  23. package/dist/react-native/index.mjs +0 -1615
  24. package/dist/react-native/index.mjs.map +0 -1
  25. package/dist/vanilla/index.d.mts +0 -271
  26. package/dist/vanilla/index.d.ts +0 -271
  27. package/dist/vanilla/index.js +0 -1064
  28. package/dist/vanilla/index.js.map +0 -1
  29. package/dist/vanilla/index.mjs +0 -1013
  30. package/dist/vanilla/index.mjs.map +0 -1
  31. package/dist/vanilla/index.umd.js.map +0 -1
  32. package/dist/vue/components/Calendar.vue.d.ts +0 -43
  33. package/dist/vue/components/Calendar.vue.d.ts.map +0 -1
  34. package/dist/vue/index.d.ts +0 -134
  35. package/dist/vue/index.d.ts.map +0 -1
  36. package/dist/vue/index.js +0 -1
  37. package/dist/vue/index.mjs +0 -717
  38. package/dist/vue/types.d.ts +0 -21
  39. package/dist/vue/types.d.ts.map +0 -1
@@ -1,1615 +0,0 @@
1
- // src/react-native/components/Calendar.tsx
2
- import { useEffect, useState, useCallback, useMemo } from "react";
3
- import {
4
- View as View2,
5
- Text as Text2,
6
- TouchableOpacity as TouchableOpacity2,
7
- ScrollView as ScrollView2,
8
- TextInput,
9
- Modal as Modal2,
10
- Pressable,
11
- Dimensions,
12
- StyleSheet as StyleSheet2
13
- } from "react-native";
14
-
15
- // src/core/utils.ts
16
- var MONTHS = [
17
- "Jan",
18
- "Feb",
19
- "Mar",
20
- "Apr",
21
- "May",
22
- "Jun",
23
- "Jul",
24
- "Aug",
25
- "Sep",
26
- "Oct",
27
- "Nov",
28
- "Dec"
29
- ];
30
- var MONTHS_FULL = [
31
- "January",
32
- "February",
33
- "March",
34
- "April",
35
- "May",
36
- "June",
37
- "July",
38
- "August",
39
- "September",
40
- "October",
41
- "November",
42
- "December"
43
- ];
44
- var DAYS = [
45
- "Sunday",
46
- "Monday",
47
- "Tuesday",
48
- "Wednesday",
49
- "Thursday",
50
- "Friday",
51
- "Saturday"
52
- ];
53
- function normalizeDate(date) {
54
- return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
55
- }
56
- function isSameDay(date1, date2) {
57
- return normalizeDate(date1).getTime() === normalizeDate(date2).getTime();
58
- }
59
- function isToday(date) {
60
- return isSameDay(date, /* @__PURE__ */ new Date());
61
- }
62
- function generateYears(minYear, maxYear) {
63
- const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
64
- const min = minYear ?? currentYear - 30;
65
- const max = maxYear ?? currentYear + 10;
66
- return Array.from({ length: max - min + 1 }, (_, i) => min + i);
67
- }
68
- function getEventsForDate(events, date) {
69
- const normalizedTargetDate = normalizeDate(date);
70
- return events.filter((event) => {
71
- const eventDate = normalizeDate(new Date(event.date));
72
- return eventDate.getTime() === normalizedTargetDate.getTime();
73
- });
74
- }
75
- function hasEvents(events, date) {
76
- return getEventsForDate(events, date).length > 0;
77
- }
78
- function generateCalendarDates(year, month, events = [], weekStartsOn = 0) {
79
- const firstDay = new Date(year, month, 1);
80
- const lastDay = new Date(year, month + 1, 0);
81
- const daysInMonth = lastDay.getDate();
82
- const prevMonthLastDay = new Date(year, month, 0).getDate();
83
- let firstDayOfWeek = firstDay.getDay();
84
- if (weekStartsOn === 1) {
85
- firstDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1;
86
- }
87
- const dates = [];
88
- let day = 1;
89
- let nextMonthDay = 1;
90
- for (let week = 0; week < 6; week++) {
91
- const weekDates = [];
92
- for (let dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {
93
- if (week === 0 && dayOfWeek < firstDayOfWeek) {
94
- const prevDay = prevMonthLastDay - firstDayOfWeek + dayOfWeek + 1;
95
- const prevDate = new Date(year, month - 1, prevDay);
96
- const dateEvents = getEventsForDate(events, prevDate);
97
- weekDates.push({
98
- date: prevDate,
99
- isCurrentMonth: false,
100
- isToday: isToday(prevDate),
101
- hasEvents: dateEvents.length > 0,
102
- events: dateEvents
103
- });
104
- } else if (day > daysInMonth) {
105
- const nextDate = new Date(year, month + 1, nextMonthDay);
106
- const dateEvents = getEventsForDate(events, nextDate);
107
- weekDates.push({
108
- date: nextDate,
109
- isCurrentMonth: false,
110
- isToday: isToday(nextDate),
111
- hasEvents: dateEvents.length > 0,
112
- events: dateEvents
113
- });
114
- nextMonthDay++;
115
- } else {
116
- const currentDate = new Date(year, month, day);
117
- const dateEvents = getEventsForDate(events, currentDate);
118
- weekDates.push({
119
- date: currentDate,
120
- isCurrentMonth: true,
121
- isToday: isToday(currentDate),
122
- hasEvents: dateEvents.length > 0,
123
- events: dateEvents
124
- });
125
- day++;
126
- }
127
- }
128
- dates.push(weekDates);
129
- }
130
- return dates;
131
- }
132
- function getPopupPositionClass(selectedDayIndex) {
133
- if (selectedDayIndex === null) return "popup-center-bottom";
134
- if (selectedDayIndex < 3) {
135
- return "popup-right";
136
- } else if (selectedDayIndex > 4) {
137
- return "popup-left";
138
- } else {
139
- return "popup-center-bottom";
140
- }
141
- }
142
- function getCellClasses(calendarDate) {
143
- const classes = [];
144
- if (!calendarDate.isCurrentMonth) {
145
- classes.push("other-month");
146
- }
147
- if (calendarDate.isToday) {
148
- classes.push("schedule--current--exam");
149
- }
150
- if (calendarDate.hasEvents) {
151
- classes.push("has--event");
152
- }
153
- return classes;
154
- }
155
- function formatDateForDisplay(date) {
156
- return `${DAYS[date.getDay()]} ${date.getDate()}`;
157
- }
158
- function getMonthYearText(year, month) {
159
- return `${MONTHS_FULL[month]} ${year}`;
160
- }
161
- function formatTimeRange(event) {
162
- if (event.allDay || !event.startTime && !event.endTime) {
163
- return "All day";
164
- }
165
- if (event.startTime && event.endTime) {
166
- return `${event.startTime} - ${event.endTime}`;
167
- }
168
- if (event.startTime) {
169
- return `${event.startTime}`;
170
- }
171
- return "";
172
- }
173
- function formatAttendees(attendees) {
174
- if (!attendees || attendees.length === 0) return "";
175
- if (attendees.length === 1) return attendees[0];
176
- if (attendees.length === 2) return attendees.join(" and ");
177
- return `${attendees.slice(0, -1).join(", ")}, and ${attendees[attendees.length - 1]}`;
178
- }
179
- function sortEventsByTime(events) {
180
- return [...events].sort((a, b) => {
181
- const aAllDay = a.allDay || !a.startTime && !a.endTime;
182
- const bAllDay = b.allDay || !b.startTime && !b.endTime;
183
- if (aAllDay && !bAllDay) return -1;
184
- if (!aAllDay && bAllDay) return 1;
185
- if (!a.startTime || !b.startTime) return 0;
186
- return a.startTime.localeCompare(b.startTime);
187
- });
188
- }
189
- var DEFAULT_CATEGORY_COLORS = {
190
- work: "#3b82f6",
191
- personal: "#8b5cf6",
192
- meeting: "#10b981",
193
- deadline: "#ef4444",
194
- appointment: "#f59e0b",
195
- other: "#6b7280"
196
- };
197
- function getDefaultEventColor(category, customColors) {
198
- const colorMap = customColors || DEFAULT_CATEGORY_COLORS;
199
- if (category && colorMap[category]) {
200
- return colorMap[category];
201
- }
202
- return "#fc8917";
203
- }
204
- function mergeCategoryColors(customColors) {
205
- return {
206
- ...DEFAULT_CATEGORY_COLORS,
207
- ...customColors
208
- };
209
- }
210
- function isValidHexColor(color) {
211
- return /^#([0-9A-F]{3}){1,2}$/i.test(color);
212
- }
213
- function getCategoryColor(category, customColors) {
214
- const colorMap = mergeCategoryColors(customColors);
215
- const color = colorMap[category] || colorMap.other || "#fc8917";
216
- return isValidHexColor(color) ? color : "#fc8917";
217
- }
218
-
219
- // src/core/calendar-engine.ts
220
- var CalendarEngine = class {
221
- constructor(config) {
222
- this.listeners = /* @__PURE__ */ new Set();
223
- this.config = config;
224
- this.categoryColors = mergeCategoryColors(config.categoryColors);
225
- const initialDate = config.initialDate || /* @__PURE__ */ new Date();
226
- this.state = {
227
- currentYear: initialDate.getFullYear(),
228
- currentMonth: initialDate.getMonth(),
229
- currentDate: initialDate.getDate(),
230
- selectedDate: null,
231
- selectedDayIndex: null,
232
- tasks: []
233
- };
234
- }
235
- /**
236
- * Subscribe to state changes
237
- */
238
- subscribe(listener) {
239
- this.listeners.add(listener);
240
- return () => this.listeners.delete(listener);
241
- }
242
- /**
243
- * Notify all listeners of state changes
244
- */
245
- notify() {
246
- this.listeners.forEach((listener) => listener());
247
- }
248
- /**
249
- * Get current state
250
- */
251
- getState() {
252
- return { ...this.state };
253
- }
254
- /**
255
- * Get view model with computed properties
256
- */
257
- getViewModel() {
258
- const calendarDates = generateCalendarDates(
259
- this.state.currentYear,
260
- this.state.currentMonth,
261
- this.config.events,
262
- this.config.weekStartsOn
263
- );
264
- return {
265
- ...this.state,
266
- months: MONTHS,
267
- days: DAYS,
268
- years: generateYears(this.config.minYear, this.config.maxYear),
269
- monthAndYearText: getMonthYearText(
270
- this.state.currentYear,
271
- this.state.currentMonth
272
- ),
273
- scheduleDay: this.state.selectedDate ? formatDateForDisplay(this.state.selectedDate) : "",
274
- calendarDates,
275
- popupPositionClass: getPopupPositionClass(this.state.selectedDayIndex)
276
- };
277
- }
278
- /**
279
- * Get actions object
280
- */
281
- getActions() {
282
- return {
283
- next: this.next.bind(this),
284
- previous: this.previous.bind(this),
285
- jump: this.jump.bind(this),
286
- goToToday: this.goToToday.bind(this),
287
- isCurrentMonth: this.isCurrentMonth.bind(this),
288
- selectDate: this.selectDate.bind(this),
289
- updateTasks: this.updateTasks.bind(this)
290
- };
291
- }
292
- /**
293
- * Navigate to next month
294
- */
295
- next() {
296
- if (this.state.currentMonth === 11) {
297
- this.state.currentMonth = 0;
298
- this.state.currentYear++;
299
- } else {
300
- this.state.currentMonth++;
301
- }
302
- this.state.selectedDate = null;
303
- this.state.selectedDayIndex = null;
304
- this.updateTasks();
305
- this.notify();
306
- }
307
- /**
308
- * Navigate to previous month
309
- */
310
- previous() {
311
- if (this.state.currentMonth === 0) {
312
- this.state.currentMonth = 11;
313
- this.state.currentYear--;
314
- } else {
315
- this.state.currentMonth--;
316
- }
317
- this.state.selectedDate = null;
318
- this.state.selectedDayIndex = null;
319
- this.updateTasks();
320
- this.notify();
321
- }
322
- /**
323
- * Jump to specific month and year
324
- */
325
- jump(year, month) {
326
- this.state.currentYear = year;
327
- this.state.currentMonth = month;
328
- this.state.selectedDate = null;
329
- this.state.selectedDayIndex = null;
330
- this.updateTasks();
331
- this.notify();
332
- }
333
- /**
334
- * Navigate to current month (today)
335
- */
336
- goToToday() {
337
- const today = /* @__PURE__ */ new Date();
338
- this.state.currentYear = today.getFullYear();
339
- this.state.currentMonth = today.getMonth();
340
- this.state.selectedDate = null;
341
- this.state.selectedDayIndex = null;
342
- this.updateTasks();
343
- this.notify();
344
- }
345
- /**
346
- * Check if currently viewing today's month
347
- */
348
- isCurrentMonth() {
349
- const today = /* @__PURE__ */ new Date();
350
- return this.state.currentYear === today.getFullYear() && this.state.currentMonth === today.getMonth();
351
- }
352
- /**
353
- * Select a specific date
354
- */
355
- selectDate(date, dayIndex) {
356
- this.state.selectedDate = date;
357
- this.state.selectedDayIndex = dayIndex ?? null;
358
- this.state.currentDate = date.getDate();
359
- this.state.currentMonth = date.getMonth();
360
- this.state.currentYear = date.getFullYear();
361
- this.updateTasks();
362
- this.notify();
363
- }
364
- /**
365
- * Update tasks for the currently selected date
366
- */
367
- updateTasks() {
368
- if (!this.state.selectedDate) {
369
- this.state.tasks = [];
370
- return;
371
- }
372
- this.state.tasks = getEventsForDate(
373
- this.config.events,
374
- this.state.selectedDate
375
- );
376
- }
377
- /**
378
- * Update events configuration
379
- */
380
- updateEvents(events) {
381
- this.config.events = events;
382
- this.updateTasks();
383
- this.notify();
384
- }
385
- /**
386
- * Handle date cell click
387
- */
388
- handleDateClick(date, dayIndex) {
389
- this.selectDate(date, dayIndex);
390
- }
391
- /**
392
- * Check if date has events
393
- */
394
- hasEventsForDate(date) {
395
- return getEventsForDate(this.config.events, date).length > 0;
396
- }
397
- /**
398
- * Get events for a specific date
399
- */
400
- getEventsForDate(date) {
401
- return getEventsForDate(this.config.events, date);
402
- }
403
- /**
404
- * Clear selected date
405
- */
406
- clearSelection() {
407
- this.state.selectedDate = null;
408
- this.state.selectedDayIndex = null;
409
- this.state.tasks = [];
410
- this.notify();
411
- }
412
- /**
413
- * Get category color (with custom colors support)
414
- */
415
- getCategoryColor(category) {
416
- if (!category) return "#fc8917";
417
- return getCategoryColor(category, this.categoryColors);
418
- }
419
- /**
420
- * Update category colors dynamically
421
- */
422
- updateCategoryColors(colors) {
423
- this.categoryColors = mergeCategoryColors(colors);
424
- this.notify();
425
- }
426
- /**
427
- * Get all category colors
428
- */
429
- getCategoryColors() {
430
- return { ...this.categoryColors };
431
- }
432
- /**
433
- * Register a new category with color
434
- */
435
- registerCategory(name, color) {
436
- this.categoryColors[name] = color;
437
- this.notify();
438
- }
439
- /**
440
- * Destroy the engine and cleanup listeners
441
- */
442
- destroy() {
443
- this.listeners.clear();
444
- }
445
- };
446
-
447
- // src/react-native/components/DatePopup.tsx
448
- import {
449
- Modal,
450
- View,
451
- Text,
452
- TouchableOpacity,
453
- ScrollView,
454
- Linking,
455
- useWindowDimensions
456
- } from "react-native";
457
-
458
- // src/styles/react-native-styles.ts
459
- import { StyleSheet } from "react-native";
460
- var defaultColors = {
461
- primary: "#fc8917",
462
- secondary: "#fca045",
463
- tertiary: "#fdb873",
464
- text: "#2c3e50",
465
- border: "#dee2e6",
466
- todayOutline: "#f7db04",
467
- eventIndicator: "#1890ff",
468
- background: "#fff",
469
- white: "#ffffff",
470
- scrollHint: "#fff3e0",
471
- scrollHintText: "#f59e0b"
472
- };
473
- var getResponsiveStyles = (width, height, customColors) => {
474
- const colors = { ...defaultColors, ...customColors };
475
- const isTablet = width >= 768;
476
- const isSmallPhone = width < 375;
477
- const isPhone = width < 768;
478
- const cellSize = (width - 60) / 7;
479
- const popupWidth = isTablet ? 500 : isPhone ? width * 0.95 : width * 0.9;
480
- const popupMaxWidth = isTablet ? 500 : isPhone ? width : 400;
481
- const popupMaxHeight = isTablet ? height * 0.8 : height * 0.85;
482
- const headerFontSize = isTablet ? 18 : isSmallPhone ? 15 : 16;
483
- const eventTitleSize = isTablet ? 16 : isSmallPhone ? 14 : 15;
484
- const eventDetailSize = isTablet ? 13 : isSmallPhone ? 11 : 12;
485
- const badgeFontSize = isTablet ? 10 : isSmallPhone ? 9 : 9;
486
- const eventCardPadding = isTablet ? 14 : isSmallPhone ? 10 : 12;
487
- const containerPadding = isTablet ? 15 : isSmallPhone ? 10 : 12;
488
- return StyleSheet.create({
489
- container: {
490
- flex: 1,
491
- backgroundColor: colors.background
492
- },
493
- titleContainer: {
494
- paddingVertical: 20,
495
- alignItems: "center"
496
- },
497
- title: {
498
- fontSize: 24,
499
- fontWeight: "600",
500
- color: colors.text
501
- },
502
- contentContainer: {
503
- marginHorizontal: 20,
504
- marginTop: 20
505
- },
506
- card: {
507
- backgroundColor: colors.background,
508
- borderRadius: 8,
509
- shadowColor: "#000",
510
- shadowOffset: {
511
- width: 0,
512
- height: 2
513
- },
514
- shadowOpacity: 0.1,
515
- shadowRadius: 3.84,
516
- elevation: 5,
517
- overflow: "hidden"
518
- },
519
- cardHeader: {
520
- backgroundColor: colors.tertiary,
521
- paddingVertical: 15,
522
- paddingHorizontal: 20,
523
- borderBottomWidth: 1,
524
- borderBottomColor: colors.border
525
- },
526
- cardHeaderText: {
527
- fontSize: 18,
528
- fontWeight: "500",
529
- color: colors.text,
530
- textAlign: "center"
531
- },
532
- table: {
533
- backgroundColor: colors.background
534
- },
535
- tableHeader: {
536
- flexDirection: "row",
537
- backgroundColor: "rgba(252, 137, 23, 0.1)",
538
- borderBottomWidth: 2,
539
- borderBottomColor: colors.border
540
- },
541
- tableHeaderCell: {
542
- flex: 1,
543
- paddingVertical: 12,
544
- borderRightWidth: 1,
545
- borderRightColor: colors.border,
546
- alignItems: "center",
547
- justifyContent: "center"
548
- },
549
- tableHeaderText: {
550
- fontSize: 14,
551
- fontWeight: "600",
552
- color: colors.text
553
- },
554
- tableRow: {
555
- flexDirection: "row",
556
- borderBottomWidth: 1,
557
- borderBottomColor: colors.border
558
- },
559
- tableCell: {
560
- flex: 1,
561
- height: cellSize,
562
- borderRightWidth: 1,
563
- borderRightColor: colors.border,
564
- alignItems: "center",
565
- justifyContent: "center",
566
- position: "relative"
567
- },
568
- tableCellText: {
569
- fontSize: 16,
570
- color: colors.text
571
- },
572
- cellToday: {
573
- borderWidth: 2,
574
- borderColor: colors.todayOutline
575
- },
576
- cellTodayText: {
577
- fontWeight: "bold"
578
- },
579
- cellWithEvents: {
580
- backgroundColor: "rgba(252, 160, 69, 0.3)"
581
- },
582
- eventIndicator: {
583
- position: "absolute",
584
- bottom: 2,
585
- width: 4,
586
- height: 4,
587
- backgroundColor: colors.eventIndicator,
588
- borderRadius: 2
589
- },
590
- navigationContainer: {
591
- flexDirection: "row",
592
- justifyContent: "space-between",
593
- paddingHorizontal: 20,
594
- paddingVertical: 20,
595
- gap: 15
596
- },
597
- navigationButton: {
598
- flex: 1,
599
- backgroundColor: "transparent",
600
- borderWidth: 1,
601
- borderColor: colors.primary,
602
- borderRadius: 6,
603
- paddingVertical: 12,
604
- paddingHorizontal: 16,
605
- alignItems: "center",
606
- justifyContent: "center"
607
- },
608
- navigationButtonText: {
609
- color: colors.primary,
610
- fontSize: 16,
611
- fontWeight: "500"
612
- },
613
- navigationButtonPressed: {
614
- backgroundColor: colors.primary
615
- },
616
- navigationButtonTextPressed: {
617
- color: colors.white
618
- },
619
- jumpForm: {
620
- flexDirection: "row",
621
- alignItems: "center",
622
- justifyContent: "center",
623
- paddingHorizontal: 20,
624
- paddingBottom: 20,
625
- gap: 10
626
- },
627
- jumpLabel: {
628
- fontSize: 18,
629
- fontWeight: "300",
630
- color: colors.text
631
- },
632
- jumpSelect: {
633
- borderWidth: 1,
634
- borderColor: colors.border,
635
- borderRadius: 6,
636
- paddingHorizontal: 12,
637
- paddingVertical: 8,
638
- backgroundColor: colors.background,
639
- minWidth: 80
640
- },
641
- jumpSelectText: {
642
- fontSize: 16,
643
- color: colors.text,
644
- textAlign: "center"
645
- },
646
- // RESPONSIVE POPUP STYLES
647
- popupOverlay: {
648
- position: "absolute",
649
- top: 0,
650
- left: 0,
651
- right: 0,
652
- bottom: 0,
653
- backgroundColor: "rgba(0, 0, 0, 0.5)",
654
- justifyContent: "center",
655
- alignItems: "center",
656
- zIndex: 1e3
657
- },
658
- popup: {
659
- backgroundColor: colors.white,
660
- borderRadius: 8,
661
- width: popupWidth,
662
- maxWidth: popupMaxWidth,
663
- maxHeight: popupMaxHeight,
664
- shadowColor: "#000",
665
- shadowOffset: {
666
- width: 0,
667
- height: 4
668
- },
669
- shadowOpacity: 0.3,
670
- shadowRadius: 6,
671
- elevation: 8,
672
- overflow: "hidden"
673
- },
674
- popupHeader: {
675
- backgroundColor: colors.primary,
676
- paddingVertical: isTablet ? 15 : 12,
677
- paddingHorizontal: isTablet ? 20 : 15,
678
- flexDirection: "row",
679
- justifyContent: "space-between",
680
- alignItems: "center"
681
- },
682
- popupHeaderText: {
683
- fontSize: headerFontSize,
684
- fontWeight: "600",
685
- color: colors.white,
686
- flex: 1
687
- },
688
- popupCloseButton: {
689
- width: isTablet ? 32 : isSmallPhone ? 26 : 28,
690
- height: isTablet ? 32 : isSmallPhone ? 26 : 28,
691
- backgroundColor: "rgba(255, 255, 255, 0.2)",
692
- borderRadius: 16,
693
- alignItems: "center",
694
- justifyContent: "center"
695
- },
696
- popupCloseText: {
697
- color: colors.white,
698
- fontSize: isTablet ? 20 : isSmallPhone ? 16 : 18,
699
- fontWeight: "bold"
700
- },
701
- scrollHint: {
702
- backgroundColor: colors.scrollHint,
703
- paddingVertical: isTablet ? 10 : 8,
704
- paddingHorizontal: containerPadding,
705
- alignItems: "center"
706
- },
707
- scrollHintText: {
708
- color: colors.scrollHintText,
709
- fontSize: isTablet ? 13 : isSmallPhone ? 11 : 12,
710
- fontWeight: "500"
711
- },
712
- eventsContainer: {
713
- maxHeight: popupMaxHeight - 150
714
- },
715
- eventsList: {
716
- padding: containerPadding,
717
- gap: isTablet ? 12 : 10
718
- },
719
- eventCard: {
720
- backgroundColor: colors.white,
721
- borderRadius: 6,
722
- padding: eventCardPadding,
723
- borderLeftWidth: 4,
724
- borderLeftColor: colors.primary,
725
- borderWidth: 1,
726
- borderColor: "#e5e7eb",
727
- shadowColor: "#000",
728
- shadowOffset: {
729
- width: 0,
730
- height: 1
731
- },
732
- shadowOpacity: 0.05,
733
- shadowRadius: 2,
734
- elevation: 1
735
- },
736
- eventHeader: {
737
- marginBottom: 10
738
- },
739
- eventTitle: {
740
- fontSize: eventTitleSize,
741
- color: "#1f2937",
742
- fontWeight: "600",
743
- marginBottom: 8
744
- },
745
- eventBadges: {
746
- flexDirection: "row",
747
- gap: 6,
748
- flexWrap: "wrap"
749
- },
750
- badge: {
751
- paddingHorizontal: isTablet ? 8 : 6,
752
- paddingVertical: isTablet ? 3 : 2,
753
- borderRadius: 10
754
- },
755
- badgeText: {
756
- fontSize: badgeFontSize,
757
- fontWeight: "600",
758
- textTransform: "uppercase",
759
- letterSpacing: 0.3
760
- },
761
- priorityBadgeHigh: {
762
- backgroundColor: "#fee2e2"
763
- },
764
- priorityBadgeMedium: {
765
- backgroundColor: "#fef3c7"
766
- },
767
- priorityBadgeLow: {
768
- backgroundColor: "#dcfce7"
769
- },
770
- statusBadgeCompleted: {
771
- backgroundColor: "#d1fae5"
772
- },
773
- statusBadgeCancelled: {
774
- backgroundColor: "#fee2e2"
775
- },
776
- statusBadgeTentative: {
777
- backgroundColor: "#e0e7ff"
778
- },
779
- categoryBadgeWork: {
780
- backgroundColor: "#dbeafe"
781
- },
782
- categoryBadgePersonal: {
783
- backgroundColor: "#fef3c7"
784
- },
785
- categoryBadgeMeeting: {
786
- backgroundColor: "#d1fae5"
787
- },
788
- categoryBadgeDeadline: {
789
- backgroundColor: "#fee2e2"
790
- },
791
- categoryBadgeAppointment: {
792
- backgroundColor: "#fef3c7"
793
- },
794
- categoryBadgeOther: {
795
- backgroundColor: "#f3f4f6"
796
- },
797
- eventTime: {
798
- flexDirection: isSmallPhone ? "column" : "row",
799
- gap: isSmallPhone ? 2 : 8,
800
- marginBottom: 6
801
- },
802
- eventTimeLabel: {
803
- fontSize: eventDetailSize,
804
- fontWeight: "600",
805
- color: "#6b7280",
806
- minWidth: isSmallPhone ? void 0 : isTablet ? 80 : 70,
807
- textAlign: "left"
808
- },
809
- eventTimeValue: {
810
- fontSize: eventDetailSize,
811
- color: "#374151",
812
- flex: 1
813
- },
814
- eventDescription: {
815
- color: "#4b5563",
816
- fontSize: eventDetailSize,
817
- lineHeight: isTablet ? 20 : 18,
818
- marginTop: 10,
819
- marginBottom: 10,
820
- paddingVertical: 8,
821
- paddingHorizontal: 12,
822
- backgroundColor: "#f9fafb",
823
- borderLeftWidth: 2,
824
- borderLeftColor: "#e5e7eb",
825
- borderRadius: 4,
826
- textAlign: "left"
827
- },
828
- eventUrlContainer: {
829
- marginTop: 8
830
- },
831
- eventLink: {
832
- color: "#2563eb",
833
- fontSize: eventDetailSize,
834
- fontWeight: "500"
835
- },
836
- eventTags: {
837
- flexDirection: "row",
838
- flexWrap: "wrap",
839
- gap: 6,
840
- marginTop: 8
841
- },
842
- eventTag: {
843
- paddingHorizontal: isTablet ? 10 : 8,
844
- paddingVertical: isTablet ? 3 : 2,
845
- backgroundColor: "#e0f2fe",
846
- borderRadius: 12
847
- },
848
- eventTagText: {
849
- fontSize: isTablet ? 11 : 10,
850
- color: "#0369a1",
851
- fontWeight: "500"
852
- },
853
- noEventsMessage: {
854
- padding: containerPadding,
855
- paddingVertical: isTablet ? 30 : 20,
856
- alignItems: "center"
857
- },
858
- noEventsText: {
859
- fontSize: isTablet ? 14 : 13,
860
- color: "#6b7280",
861
- textAlign: "center"
862
- }
863
- });
864
- };
865
- var calendarStyles = getResponsiveStyles(375, 667);
866
-
867
- // src/react-native/components/DatePopup.tsx
868
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
869
- var PriorityBadge = ({
870
- priority,
871
- styles
872
- }) => {
873
- if (!priority) return null;
874
- const priorityConfig = {
875
- high: { label: "HIGH", style: styles.priorityBadgeHigh },
876
- medium: { label: "MEDIUM", style: styles.priorityBadgeMedium },
877
- low: { label: "LOW", style: styles.priorityBadgeLow }
878
- };
879
- const config = priorityConfig[priority];
880
- if (!config) return null;
881
- return /* @__PURE__ */ jsx(View, { style: [styles.badge, config.style], children: /* @__PURE__ */ jsx(Text, { style: styles.badgeText, children: config.label }) });
882
- };
883
- var StatusBadge = ({
884
- status,
885
- styles
886
- }) => {
887
- if (!status || status === "scheduled") return null;
888
- const statusConfig = {
889
- completed: { label: "COMPLETED", style: styles.statusBadgeCompleted },
890
- cancelled: { label: "CANCELLED", style: styles.statusBadgeCancelled },
891
- tentative: { label: "TENTATIVE", style: styles.statusBadgeTentative }
892
- };
893
- const config = statusConfig[status];
894
- if (!config) return null;
895
- return /* @__PURE__ */ jsx(View, { style: [styles.badge, config.style], children: /* @__PURE__ */ jsx(Text, { style: styles.badgeText, children: config.label }) });
896
- };
897
- var CategoryBadge = ({
898
- category,
899
- styles
900
- }) => {
901
- if (!category) return null;
902
- const categoryConfig = {
903
- work: { label: "WORK", style: styles.categoryBadgeWork },
904
- personal: { label: "PERSONAL", style: styles.categoryBadgePersonal },
905
- meeting: { label: "MEETING", style: styles.categoryBadgeMeeting },
906
- deadline: { label: "DEADLINE", style: styles.categoryBadgeDeadline },
907
- appointment: {
908
- label: "APPOINTMENT",
909
- style: styles.categoryBadgeAppointment
910
- },
911
- other: { label: "OTHER", style: styles.categoryBadgeOther }
912
- };
913
- const config = categoryConfig[category];
914
- if (!config) return null;
915
- return /* @__PURE__ */ jsx(View, { style: [styles.badge, config.style], children: /* @__PURE__ */ jsx(Text, { style: styles.badgeText, children: config.label }) });
916
- };
917
- var DatePopup = ({
918
- visible,
919
- selectedDate,
920
- events,
921
- scheduleDay,
922
- onClose,
923
- onEventClick,
924
- renderEvent,
925
- renderNoEvents,
926
- showCloseButton = true
927
- }) => {
928
- const { width, height } = useWindowDimensions();
929
- const calendarStyles2 = getResponsiveStyles(width, height);
930
- if (!selectedDate) return null;
931
- const showScrollHint = events.length > 3;
932
- const handleEventClick = (event) => {
933
- onEventClick?.(event);
934
- };
935
- const defaultRenderEvent = (event) => {
936
- const timeRange = formatTimeRange(event);
937
- const attendeesList = formatAttendees(event.attendees);
938
- const handleUrlPress = () => {
939
- if (event.url) {
940
- Linking.openURL(event.url).catch(
941
- (err) => console.error("Failed to open URL:", err)
942
- );
943
- }
944
- };
945
- const eventContent = /* @__PURE__ */ jsxs(Fragment, { children: [
946
- /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventHeader, children: [
947
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTitle, children: event.name }),
948
- /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventBadges, children: [
949
- /* @__PURE__ */ jsx(CategoryBadge, { category: event.category, styles: calendarStyles2 }),
950
- /* @__PURE__ */ jsx(PriorityBadge, { priority: event.priority, styles: calendarStyles2 }),
951
- /* @__PURE__ */ jsx(StatusBadge, { status: event.status, styles: calendarStyles2 })
952
- ] })
953
- ] }),
954
- timeRange && /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventTime, children: [
955
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeLabel, children: "Time:" }),
956
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeValue, children: timeRange })
957
- ] }),
958
- event.description && /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventDescription, children: event.description }),
959
- event.location && /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventTime, children: [
960
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeLabel, children: "Location:" }),
961
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeValue, children: event.location })
962
- ] }),
963
- attendeesList && /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventTime, children: [
964
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeLabel, children: "Attendees:" }),
965
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeValue, children: attendeesList })
966
- ] }),
967
- event.organizer && /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventTime, children: [
968
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeLabel, children: "Organizer:" }),
969
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeValue, children: event.organizer })
970
- ] }),
971
- event.notes && /* @__PURE__ */ jsxs(View, { style: calendarStyles2.eventTime, children: [
972
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeLabel, children: "Notes:" }),
973
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTimeValue, children: event.notes })
974
- ] }),
975
- event.url && /* @__PURE__ */ jsx(
976
- TouchableOpacity,
977
- {
978
- onPress: handleUrlPress,
979
- style: calendarStyles2.eventUrlContainer,
980
- children: /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventLink, children: "View Details \u2192" })
981
- }
982
- ),
983
- event.tags && event.tags.length > 0 && /* @__PURE__ */ jsx(View, { style: calendarStyles2.eventTags, children: event.tags.map((tag, idx) => /* @__PURE__ */ jsx(View, { style: calendarStyles2.eventTag, children: /* @__PURE__ */ jsx(Text, { style: calendarStyles2.eventTagText, children: tag }) }, idx)) })
984
- ] });
985
- if (onEventClick) {
986
- return /* @__PURE__ */ jsx(
987
- TouchableOpacity,
988
- {
989
- style: [
990
- calendarStyles2.eventCard,
991
- event.color && { borderLeftColor: event.color }
992
- ],
993
- onPress: () => handleEventClick(event),
994
- activeOpacity: 0.7,
995
- children: eventContent
996
- },
997
- event.id || event.name
998
- );
999
- }
1000
- return /* @__PURE__ */ jsx(
1001
- View,
1002
- {
1003
- style: [
1004
- calendarStyles2.eventCard,
1005
- event.color && { borderLeftColor: event.color }
1006
- ],
1007
- children: eventContent
1008
- },
1009
- event.id || event.name
1010
- );
1011
- };
1012
- const defaultRenderNoEvents = () => /* @__PURE__ */ jsx(View, { style: calendarStyles2.noEventsMessage, children: /* @__PURE__ */ jsx(Text, { style: calendarStyles2.noEventsText, children: "No events scheduled for this day." }) });
1013
- return /* @__PURE__ */ jsx(
1014
- Modal,
1015
- {
1016
- visible,
1017
- transparent: true,
1018
- animationType: "fade",
1019
- onRequestClose: onClose,
1020
- children: /* @__PURE__ */ jsx(
1021
- TouchableOpacity,
1022
- {
1023
- style: calendarStyles2.popupOverlay,
1024
- activeOpacity: 1,
1025
- onPress: onClose,
1026
- children: /* @__PURE__ */ jsxs(
1027
- TouchableOpacity,
1028
- {
1029
- style: calendarStyles2.popup,
1030
- activeOpacity: 1,
1031
- onPress: (e) => e.stopPropagation(),
1032
- children: [
1033
- /* @__PURE__ */ jsxs(View, { style: calendarStyles2.popupHeader, children: [
1034
- /* @__PURE__ */ jsx(Text, { style: calendarStyles2.popupHeaderText, children: scheduleDay }),
1035
- showCloseButton && /* @__PURE__ */ jsx(
1036
- TouchableOpacity,
1037
- {
1038
- style: calendarStyles2.popupCloseButton,
1039
- onPress: onClose,
1040
- accessibilityLabel: "Close",
1041
- children: /* @__PURE__ */ jsx(Text, { style: calendarStyles2.popupCloseText, children: "\u2715" })
1042
- }
1043
- )
1044
- ] }),
1045
- showScrollHint && /* @__PURE__ */ jsx(View, { style: calendarStyles2.scrollHint, children: /* @__PURE__ */ jsx(Text, { style: calendarStyles2.scrollHintText, children: "\u2193 Scroll to see more events \u2193" }) }),
1046
- /* @__PURE__ */ jsx(
1047
- ScrollView,
1048
- {
1049
- style: calendarStyles2.eventsContainer,
1050
- showsVerticalScrollIndicator: true,
1051
- children: events.length > 0 ? /* @__PURE__ */ jsx(View, { style: calendarStyles2.eventsList, children: events.map(
1052
- (event) => renderEvent ? renderEvent(event) : defaultRenderEvent(event)
1053
- ) }) : renderNoEvents ? renderNoEvents() : defaultRenderNoEvents()
1054
- }
1055
- )
1056
- ]
1057
- }
1058
- )
1059
- }
1060
- )
1061
- }
1062
- );
1063
- };
1064
-
1065
- // src/react-native/components/Calendar.tsx
1066
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1067
- var Calendar = ({
1068
- events,
1069
- initialDate,
1070
- minYear,
1071
- maxYear,
1072
- weekStartsOn = 0,
1073
- useShortMonthNames = false,
1074
- onDateSelect,
1075
- onEventClick,
1076
- onMonthChange,
1077
- style,
1078
- containerStyle,
1079
- headerStyle,
1080
- headerTextStyle,
1081
- cellStyle,
1082
- cellTextStyle,
1083
- renderEvent,
1084
- renderNoEvents,
1085
- title,
1086
- showCloseButton = true,
1087
- theme
1088
- }) => {
1089
- const engine = useMemo(
1090
- () => new CalendarEngine({
1091
- events,
1092
- initialDate,
1093
- minYear,
1094
- maxYear,
1095
- weekStartsOn
1096
- }),
1097
- [events, initialDate, minYear, maxYear, weekStartsOn]
1098
- );
1099
- const themeColors = useMemo(() => {
1100
- if (!theme) return void 0;
1101
- return {
1102
- primary: theme.primary,
1103
- secondary: theme.secondary,
1104
- tertiary: theme.tertiary,
1105
- text: theme.textColor,
1106
- border: theme.borderColor,
1107
- todayOutline: theme.todayOutline,
1108
- eventIndicator: theme.eventIndicator,
1109
- background: theme.background
1110
- };
1111
- }, [theme]);
1112
- const calendarStyles2 = useMemo(() => {
1113
- const { width, height } = Dimensions.get("window");
1114
- return getResponsiveStyles(width, height, themeColors);
1115
- }, [themeColors]);
1116
- const [, forceUpdate] = useState({});
1117
- const rerender = useCallback(() => forceUpdate({}), []);
1118
- const [pickerOpen, setPickerOpen] = useState(false);
1119
- const [yearInput, setYearInput] = useState("");
1120
- const [yearInputValid, setYearInputValid] = useState(true);
1121
- const today = /* @__PURE__ */ new Date();
1122
- const todayMonth = today.getMonth();
1123
- const todayYear = today.getFullYear();
1124
- const computedMinYear = minYear ?? todayYear - 30;
1125
- const computedMaxYear = maxYear ?? todayYear + 10;
1126
- useEffect(() => {
1127
- const unsubscribe = engine.subscribe(rerender);
1128
- return unsubscribe;
1129
- }, [engine, rerender]);
1130
- useEffect(() => {
1131
- engine.updateEvents(events);
1132
- }, [engine, events]);
1133
- useEffect(() => {
1134
- return () => {
1135
- engine.destroy();
1136
- };
1137
- }, [engine]);
1138
- const viewModel = engine.getViewModel();
1139
- const actions = engine.getActions();
1140
- const { selectedDate, tasks } = viewModel;
1141
- const isCurrentMonth = viewModel.currentYear === todayYear && viewModel.currentMonth === todayMonth;
1142
- const handleDatePress = (date, dayIndex) => {
1143
- engine.handleDateClick(date, dayIndex);
1144
- onDateSelect?.(date);
1145
- };
1146
- const handleNext = () => {
1147
- actions.next();
1148
- onMonthChange?.(viewModel.currentYear, viewModel.currentMonth);
1149
- };
1150
- const handlePrevious = () => {
1151
- actions.previous();
1152
- onMonthChange?.(viewModel.currentYear, viewModel.currentMonth);
1153
- };
1154
- const handleGoToToday = () => {
1155
- actions.goToToday();
1156
- setPickerOpen(false);
1157
- onMonthChange?.(todayYear, todayMonth);
1158
- };
1159
- const togglePicker = () => {
1160
- const newOpen = !pickerOpen;
1161
- setPickerOpen(newOpen);
1162
- if (newOpen) {
1163
- setYearInput(String(viewModel.currentYear));
1164
- setYearInputValid(true);
1165
- }
1166
- };
1167
- const handleYearInputChange = (value) => {
1168
- if (value === "" || /^\d+$/.test(value)) {
1169
- setYearInput(value);
1170
- const year = parseInt(value, 10);
1171
- setYearInputValid(
1172
- value === "" || year >= computedMinYear && year <= computedMaxYear
1173
- );
1174
- }
1175
- };
1176
- const handleYearInputSubmit = () => {
1177
- const year = parseInt(yearInput, 10);
1178
- if (isNaN(year) || year < computedMinYear || year > computedMaxYear) {
1179
- setYearInput(String(viewModel.currentYear));
1180
- setYearInputValid(true);
1181
- } else {
1182
- actions.jump(year, viewModel.currentMonth);
1183
- onMonthChange?.(year, viewModel.currentMonth);
1184
- }
1185
- };
1186
- const handleYearPrev = () => {
1187
- const newYear = viewModel.currentYear - 1;
1188
- if (newYear >= computedMinYear) {
1189
- actions.jump(newYear, viewModel.currentMonth);
1190
- setYearInput(String(newYear));
1191
- onMonthChange?.(newYear, viewModel.currentMonth);
1192
- }
1193
- };
1194
- const handleYearNext = () => {
1195
- const newYear = viewModel.currentYear + 1;
1196
- if (newYear <= computedMaxYear) {
1197
- actions.jump(newYear, viewModel.currentMonth);
1198
- setYearInput(String(newYear));
1199
- onMonthChange?.(newYear, viewModel.currentMonth);
1200
- }
1201
- };
1202
- const handleMonthSelect = (month) => {
1203
- actions.jump(viewModel.currentYear, month);
1204
- setPickerOpen(false);
1205
- onMonthChange?.(viewModel.currentYear, month);
1206
- };
1207
- const closePopup = () => {
1208
- engine.clearSelection();
1209
- };
1210
- return /* @__PURE__ */ jsxs2(ScrollView2, { style: [calendarStyles2.container, containerStyle], children: [
1211
- title && /* @__PURE__ */ jsx2(View2, { style: calendarStyles2.titleContainer, children: /* @__PURE__ */ jsx2(Text2, { style: calendarStyles2.title, children: title }) }),
1212
- /* @__PURE__ */ jsx2(View2, { style: [calendarStyles2.contentContainer, style], children: /* @__PURE__ */ jsxs2(View2, { style: calendarStyles2.card, children: [
1213
- /* @__PURE__ */ jsxs2(View2, { style: [pickerStyles.navHeader, headerStyle], children: [
1214
- /* @__PURE__ */ jsx2(
1215
- TouchableOpacity2,
1216
- {
1217
- style: pickerStyles.navArrow,
1218
- onPress: handlePrevious,
1219
- children: /* @__PURE__ */ jsx2(Text2, { style: pickerStyles.navArrowText, children: "\u2039" })
1220
- }
1221
- ),
1222
- /* @__PURE__ */ jsxs2(
1223
- TouchableOpacity2,
1224
- {
1225
- style: pickerStyles.pickerBtn,
1226
- onPress: togglePicker,
1227
- children: [
1228
- /* @__PURE__ */ jsx2(Text2, { style: [pickerStyles.pickerBtnText, headerTextStyle], children: useShortMonthNames ? `${MONTHS[viewModel.currentMonth]} ${viewModel.currentYear}` : viewModel.monthAndYearText }),
1229
- /* @__PURE__ */ jsx2(Text2, { style: pickerStyles.chevron, children: "\u25BC" })
1230
- ]
1231
- }
1232
- ),
1233
- /* @__PURE__ */ jsx2(
1234
- TouchableOpacity2,
1235
- {
1236
- style: [
1237
- pickerStyles.todayBtn,
1238
- isCurrentMonth && pickerStyles.todayBtnDisabled
1239
- ],
1240
- onPress: handleGoToToday,
1241
- disabled: isCurrentMonth,
1242
- children: /* @__PURE__ */ jsx2(
1243
- Text2,
1244
- {
1245
- style: [
1246
- pickerStyles.todayBtnText,
1247
- isCurrentMonth && pickerStyles.todayBtnTextDisabled
1248
- ],
1249
- children: "Today"
1250
- }
1251
- )
1252
- }
1253
- ),
1254
- /* @__PURE__ */ jsx2(
1255
- TouchableOpacity2,
1256
- {
1257
- style: pickerStyles.navArrow,
1258
- onPress: handleNext,
1259
- children: /* @__PURE__ */ jsx2(Text2, { style: pickerStyles.navArrowText, children: "\u203A" })
1260
- }
1261
- )
1262
- ] }),
1263
- /* @__PURE__ */ jsx2(
1264
- Modal2,
1265
- {
1266
- visible: pickerOpen,
1267
- transparent: true,
1268
- animationType: "fade",
1269
- onRequestClose: () => setPickerOpen(false),
1270
- children: /* @__PURE__ */ jsx2(
1271
- Pressable,
1272
- {
1273
- style: pickerStyles.modalOverlay,
1274
- onPress: () => setPickerOpen(false),
1275
- children: /* @__PURE__ */ jsxs2(
1276
- Pressable,
1277
- {
1278
- style: pickerStyles.pickerDropdown,
1279
- onPress: (e) => e.stopPropagation(),
1280
- children: [
1281
- /* @__PURE__ */ jsxs2(View2, { style: pickerStyles.yearRow, children: [
1282
- /* @__PURE__ */ jsx2(
1283
- TouchableOpacity2,
1284
- {
1285
- style: pickerStyles.yearArrow,
1286
- onPress: handleYearPrev,
1287
- disabled: viewModel.currentYear <= computedMinYear,
1288
- children: /* @__PURE__ */ jsx2(
1289
- Text2,
1290
- {
1291
- style: [
1292
- pickerStyles.yearArrowText,
1293
- viewModel.currentYear <= computedMinYear && pickerStyles.yearArrowDisabled
1294
- ],
1295
- children: "\u2039"
1296
- }
1297
- )
1298
- }
1299
- ),
1300
- /* @__PURE__ */ jsx2(
1301
- TextInput,
1302
- {
1303
- style: [
1304
- pickerStyles.yearInput,
1305
- !yearInputValid && pickerStyles.yearInputInvalid
1306
- ],
1307
- value: yearInput,
1308
- onChangeText: handleYearInputChange,
1309
- onSubmitEditing: handleYearInputSubmit,
1310
- onBlur: handleYearInputSubmit,
1311
- keyboardType: "number-pad",
1312
- maxLength: 4
1313
- }
1314
- ),
1315
- /* @__PURE__ */ jsx2(
1316
- TouchableOpacity2,
1317
- {
1318
- style: pickerStyles.yearArrow,
1319
- onPress: handleYearNext,
1320
- disabled: viewModel.currentYear >= computedMaxYear,
1321
- children: /* @__PURE__ */ jsx2(
1322
- Text2,
1323
- {
1324
- style: [
1325
- pickerStyles.yearArrowText,
1326
- viewModel.currentYear >= computedMaxYear && pickerStyles.yearArrowDisabled
1327
- ],
1328
- children: "\u203A"
1329
- }
1330
- )
1331
- }
1332
- )
1333
- ] }),
1334
- /* @__PURE__ */ jsx2(View2, { style: pickerStyles.monthGrid, children: (useShortMonthNames ? MONTHS : MONTHS_FULL).map(
1335
- (month, index) => {
1336
- const isSelected = index === viewModel.currentMonth;
1337
- const isCurrent = index === todayMonth && viewModel.currentYear === todayYear;
1338
- return /* @__PURE__ */ jsx2(
1339
- TouchableOpacity2,
1340
- {
1341
- style: [
1342
- pickerStyles.monthBtn,
1343
- isSelected && pickerStyles.monthBtnSelected,
1344
- isCurrent && pickerStyles.monthBtnCurrent
1345
- ],
1346
- onPress: () => handleMonthSelect(index),
1347
- children: /* @__PURE__ */ jsx2(
1348
- Text2,
1349
- {
1350
- style: [
1351
- pickerStyles.monthBtnText,
1352
- isSelected && pickerStyles.monthBtnTextSelected
1353
- ],
1354
- children: month
1355
- }
1356
- )
1357
- },
1358
- month
1359
- );
1360
- }
1361
- ) })
1362
- ]
1363
- }
1364
- )
1365
- }
1366
- )
1367
- }
1368
- ),
1369
- /* @__PURE__ */ jsxs2(View2, { style: calendarStyles2.table, children: [
1370
- /* @__PURE__ */ jsx2(View2, { style: calendarStyles2.tableHeader, children: viewModel.days.map((day) => /* @__PURE__ */ jsx2(View2, { style: calendarStyles2.tableHeaderCell, children: /* @__PURE__ */ jsx2(Text2, { style: calendarStyles2.tableHeaderText, children: day.slice(0, 3) }) }, day)) }),
1371
- viewModel.calendarDates.map((week, weekIndex) => /* @__PURE__ */ jsx2(View2, { style: calendarStyles2.tableRow, children: week.map((calendarDate, dayIndex) => {
1372
- const cellClasses = getCellClasses(calendarDate);
1373
- const isToday2 = cellClasses.includes(
1374
- "schedule--current--exam"
1375
- );
1376
- const hasEvents2 = cellClasses.includes("has--event");
1377
- const isOtherMonth = cellClasses.includes("other-month");
1378
- return /* @__PURE__ */ jsxs2(
1379
- TouchableOpacity2,
1380
- {
1381
- style: [
1382
- calendarStyles2.tableCell,
1383
- cellStyle,
1384
- isToday2 && calendarStyles2.cellToday,
1385
- hasEvents2 && calendarStyles2.cellWithEvents,
1386
- isOtherMonth && pickerStyles.cellOtherMonth
1387
- ],
1388
- onPress: () => {
1389
- handleDatePress(calendarDate.date, dayIndex);
1390
- },
1391
- children: [
1392
- /* @__PURE__ */ jsx2(
1393
- Text2,
1394
- {
1395
- style: [
1396
- calendarStyles2.tableCellText,
1397
- cellTextStyle,
1398
- isToday2 && calendarStyles2.cellTodayText,
1399
- isOtherMonth && pickerStyles.cellOtherMonthText
1400
- ],
1401
- children: calendarDate.date.getDate()
1402
- }
1403
- ),
1404
- hasEvents2 && /* @__PURE__ */ jsx2(View2, { style: calendarStyles2.eventIndicator })
1405
- ]
1406
- },
1407
- `${weekIndex}-${dayIndex}`
1408
- );
1409
- }) }, weekIndex))
1410
- ] })
1411
- ] }) }),
1412
- /* @__PURE__ */ jsx2(
1413
- DatePopup,
1414
- {
1415
- visible: !!selectedDate,
1416
- selectedDate,
1417
- events: tasks,
1418
- scheduleDay: viewModel.scheduleDay,
1419
- onClose: closePopup,
1420
- onEventClick,
1421
- renderEvent,
1422
- renderNoEvents,
1423
- showCloseButton
1424
- }
1425
- )
1426
- ] });
1427
- };
1428
- var pickerStyles = StyleSheet2.create({
1429
- navHeader: {
1430
- flexDirection: "row",
1431
- alignItems: "center",
1432
- justifyContent: "center",
1433
- paddingVertical: 12,
1434
- paddingHorizontal: 8,
1435
- backgroundColor: "#f8f9fa",
1436
- borderBottomWidth: 2,
1437
- borderBottomColor: "#dee2e6",
1438
- gap: 8
1439
- },
1440
- navArrow: {
1441
- width: 36,
1442
- height: 36,
1443
- borderRadius: 6,
1444
- borderWidth: 1,
1445
- borderColor: "#dee2e6",
1446
- backgroundColor: "#fff",
1447
- alignItems: "center",
1448
- justifyContent: "center"
1449
- },
1450
- navArrowText: {
1451
- fontSize: 20,
1452
- color: "#2c3e50"
1453
- },
1454
- pickerBtn: {
1455
- flexDirection: "row",
1456
- alignItems: "center",
1457
- paddingHorizontal: 16,
1458
- paddingVertical: 8,
1459
- borderRadius: 6,
1460
- borderWidth: 1,
1461
- borderColor: "#dee2e6",
1462
- backgroundColor: "#fff",
1463
- gap: 8
1464
- },
1465
- pickerBtnText: {
1466
- fontSize: 16,
1467
- fontWeight: "600",
1468
- color: "#2c3e50"
1469
- },
1470
- chevron: {
1471
- fontSize: 10,
1472
- color: "#2c3e50"
1473
- },
1474
- todayBtn: {
1475
- paddingHorizontal: 16,
1476
- paddingVertical: 8,
1477
- borderRadius: 6,
1478
- borderWidth: 1,
1479
- borderColor: "#dee2e6",
1480
- backgroundColor: "#fff"
1481
- },
1482
- todayBtnDisabled: {
1483
- opacity: 0.5
1484
- },
1485
- todayBtnText: {
1486
- fontSize: 14,
1487
- fontWeight: "500",
1488
- color: "#2c3e50"
1489
- },
1490
- todayBtnTextDisabled: {
1491
- color: "#9ca3af"
1492
- },
1493
- modalOverlay: {
1494
- flex: 1,
1495
- backgroundColor: "rgba(0, 0, 0, 0.3)",
1496
- justifyContent: "center",
1497
- alignItems: "center"
1498
- },
1499
- pickerDropdown: {
1500
- backgroundColor: "#fff",
1501
- borderRadius: 12,
1502
- padding: 16,
1503
- minWidth: 280,
1504
- shadowColor: "#000",
1505
- shadowOffset: { width: 0, height: 4 },
1506
- shadowOpacity: 0.15,
1507
- shadowRadius: 20,
1508
- elevation: 10
1509
- },
1510
- yearRow: {
1511
- flexDirection: "row",
1512
- alignItems: "center",
1513
- justifyContent: "center",
1514
- gap: 12,
1515
- marginBottom: 16,
1516
- paddingBottom: 12,
1517
- borderBottomWidth: 1,
1518
- borderBottomColor: "#dee2e6"
1519
- },
1520
- yearArrow: {
1521
- width: 32,
1522
- height: 32,
1523
- borderRadius: 6,
1524
- backgroundColor: "#f3f4f6",
1525
- alignItems: "center",
1526
- justifyContent: "center"
1527
- },
1528
- yearArrowText: {
1529
- fontSize: 18,
1530
- fontWeight: "600",
1531
- color: "#2c3e50"
1532
- },
1533
- yearArrowDisabled: {
1534
- opacity: 0.3
1535
- },
1536
- yearInput: {
1537
- width: 80,
1538
- paddingVertical: 6,
1539
- paddingHorizontal: 8,
1540
- borderRadius: 6,
1541
- borderWidth: 1,
1542
- borderColor: "#dee2e6",
1543
- textAlign: "center",
1544
- fontSize: 18,
1545
- fontWeight: "600",
1546
- color: "#2c3e50"
1547
- },
1548
- yearInputInvalid: {
1549
- borderColor: "#ef4444",
1550
- backgroundColor: "#fef2f2"
1551
- },
1552
- monthGrid: {
1553
- flexDirection: "row",
1554
- flexWrap: "wrap",
1555
- gap: 8
1556
- },
1557
- monthBtn: {
1558
- width: "30%",
1559
- paddingVertical: 10,
1560
- borderRadius: 6,
1561
- backgroundColor: "#f9fafb",
1562
- alignItems: "center"
1563
- },
1564
- monthBtnSelected: {
1565
- backgroundColor: "#fc8917"
1566
- },
1567
- monthBtnCurrent: {
1568
- borderWidth: 1,
1569
- borderColor: "#fc8917"
1570
- },
1571
- monthBtnText: {
1572
- fontSize: 14,
1573
- fontWeight: "500",
1574
- color: "#2c3e50"
1575
- },
1576
- monthBtnTextSelected: {
1577
- color: "#fff",
1578
- fontWeight: "600"
1579
- },
1580
- cellOtherMonth: {
1581
- backgroundColor: "#f9fafb"
1582
- },
1583
- cellOtherMonthText: {
1584
- color: "#9ca3af"
1585
- }
1586
- });
1587
- export {
1588
- Calendar,
1589
- CalendarEngine,
1590
- DAYS,
1591
- DEFAULT_CATEGORY_COLORS,
1592
- DatePopup,
1593
- MONTHS,
1594
- MONTHS_FULL,
1595
- calendarStyles,
1596
- formatAttendees,
1597
- formatDateForDisplay,
1598
- formatTimeRange,
1599
- generateCalendarDates,
1600
- generateYears,
1601
- getCategoryColor,
1602
- getCellClasses,
1603
- getDefaultEventColor,
1604
- getEventsForDate,
1605
- getMonthYearText,
1606
- getPopupPositionClass,
1607
- hasEvents,
1608
- isSameDay,
1609
- isToday,
1610
- isValidHexColor,
1611
- mergeCategoryColors,
1612
- normalizeDate,
1613
- sortEventsByTime
1614
- };
1615
- //# sourceMappingURL=index.mjs.map