kalendly 0.1.7 → 0.2.0

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 (38) hide show
  1. package/README.md +317 -681
  2. package/dist/core/index.js +3 -3
  3. package/dist/index.d.mts +48 -602
  4. package/dist/index.d.ts +48 -602
  5. package/dist/index.js +753 -2359
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +727 -2348
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/{vanilla/index.umd.js → index.umd.js} +218 -218
  10. package/dist/index.umd.js.map +1 -0
  11. package/package.json +41 -91
  12. package/dist/react/index.d.mts +0 -251
  13. package/dist/react/index.d.ts +0 -251
  14. package/dist/react/index.js +0 -969
  15. package/dist/react/index.js.map +0 -1
  16. package/dist/react/index.mjs +0 -924
  17. package/dist/react/index.mjs.map +0 -1
  18. package/dist/react-native/index.d.mts +0 -642
  19. package/dist/react-native/index.d.ts +0 -642
  20. package/dist/react-native/index.js +0 -1649
  21. package/dist/react-native/index.js.map +0 -1
  22. package/dist/react-native/index.mjs +0 -1615
  23. package/dist/react-native/index.mjs.map +0 -1
  24. package/dist/vanilla/index.d.mts +0 -271
  25. package/dist/vanilla/index.d.ts +0 -271
  26. package/dist/vanilla/index.js +0 -1064
  27. package/dist/vanilla/index.js.map +0 -1
  28. package/dist/vanilla/index.mjs +0 -1013
  29. package/dist/vanilla/index.mjs.map +0 -1
  30. package/dist/vanilla/index.umd.js.map +0 -1
  31. package/dist/vue/components/Calendar.vue.d.ts +0 -43
  32. package/dist/vue/components/Calendar.vue.d.ts.map +0 -1
  33. package/dist/vue/index.d.ts +0 -134
  34. package/dist/vue/index.d.ts.map +0 -1
  35. package/dist/vue/index.js +0 -1
  36. package/dist/vue/index.mjs +0 -717
  37. package/dist/vue/types.d.ts +0 -21
  38. package/dist/vue/types.d.ts.map +0 -1
@@ -1,969 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/react/index.tsx
21
- var index_exports = {};
22
- __export(index_exports, {
23
- Calendar: () => Calendar,
24
- CalendarEngine: () => CalendarEngine,
25
- DAYS: () => DAYS,
26
- DEFAULT_CATEGORY_COLORS: () => DEFAULT_CATEGORY_COLORS,
27
- DatePopup: () => DatePopup,
28
- MONTHS: () => MONTHS,
29
- MONTHS_FULL: () => MONTHS_FULL,
30
- formatAttendees: () => formatAttendees,
31
- formatDateForDisplay: () => formatDateForDisplay,
32
- formatTimeRange: () => formatTimeRange,
33
- generateCalendarDates: () => generateCalendarDates,
34
- generateYears: () => generateYears,
35
- getCategoryColor: () => getCategoryColor,
36
- getCellClasses: () => getCellClasses,
37
- getDefaultEventColor: () => getDefaultEventColor,
38
- getEventsForDate: () => getEventsForDate,
39
- getMonthYearText: () => getMonthYearText,
40
- getPopupPositionClass: () => getPopupPositionClass,
41
- hasEvents: () => hasEvents,
42
- isSameDay: () => isSameDay,
43
- isToday: () => isToday,
44
- isValidHexColor: () => isValidHexColor,
45
- mergeCategoryColors: () => mergeCategoryColors,
46
- normalizeDate: () => normalizeDate,
47
- sortEventsByTime: () => sortEventsByTime
48
- });
49
- module.exports = __toCommonJS(index_exports);
50
-
51
- // src/react/components/Calendar.tsx
52
- var import_react = require("react");
53
-
54
- // src/core/utils.ts
55
- var MONTHS = [
56
- "Jan",
57
- "Feb",
58
- "Mar",
59
- "Apr",
60
- "May",
61
- "Jun",
62
- "Jul",
63
- "Aug",
64
- "Sep",
65
- "Oct",
66
- "Nov",
67
- "Dec"
68
- ];
69
- var MONTHS_FULL = [
70
- "January",
71
- "February",
72
- "March",
73
- "April",
74
- "May",
75
- "June",
76
- "July",
77
- "August",
78
- "September",
79
- "October",
80
- "November",
81
- "December"
82
- ];
83
- var DAYS = [
84
- "Sunday",
85
- "Monday",
86
- "Tuesday",
87
- "Wednesday",
88
- "Thursday",
89
- "Friday",
90
- "Saturday"
91
- ];
92
- function normalizeDate(date) {
93
- return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
94
- }
95
- function isSameDay(date1, date2) {
96
- return normalizeDate(date1).getTime() === normalizeDate(date2).getTime();
97
- }
98
- function isToday(date) {
99
- return isSameDay(date, /* @__PURE__ */ new Date());
100
- }
101
- function generateYears(minYear, maxYear) {
102
- const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
103
- const min = minYear ?? currentYear - 30;
104
- const max = maxYear ?? currentYear + 10;
105
- return Array.from({ length: max - min + 1 }, (_, i) => min + i);
106
- }
107
- function getEventsForDate(events, date) {
108
- const normalizedTargetDate = normalizeDate(date);
109
- return events.filter((event) => {
110
- const eventDate = normalizeDate(new Date(event.date));
111
- return eventDate.getTime() === normalizedTargetDate.getTime();
112
- });
113
- }
114
- function hasEvents(events, date) {
115
- return getEventsForDate(events, date).length > 0;
116
- }
117
- function generateCalendarDates(year, month, events = [], weekStartsOn = 0) {
118
- const firstDay = new Date(year, month, 1);
119
- const lastDay = new Date(year, month + 1, 0);
120
- const daysInMonth = lastDay.getDate();
121
- const prevMonthLastDay = new Date(year, month, 0).getDate();
122
- let firstDayOfWeek = firstDay.getDay();
123
- if (weekStartsOn === 1) {
124
- firstDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1;
125
- }
126
- const dates = [];
127
- let day = 1;
128
- let nextMonthDay = 1;
129
- for (let week = 0; week < 6; week++) {
130
- const weekDates = [];
131
- for (let dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {
132
- if (week === 0 && dayOfWeek < firstDayOfWeek) {
133
- const prevDay = prevMonthLastDay - firstDayOfWeek + dayOfWeek + 1;
134
- const prevDate = new Date(year, month - 1, prevDay);
135
- const dateEvents = getEventsForDate(events, prevDate);
136
- weekDates.push({
137
- date: prevDate,
138
- isCurrentMonth: false,
139
- isToday: isToday(prevDate),
140
- hasEvents: dateEvents.length > 0,
141
- events: dateEvents
142
- });
143
- } else if (day > daysInMonth) {
144
- const nextDate = new Date(year, month + 1, nextMonthDay);
145
- const dateEvents = getEventsForDate(events, nextDate);
146
- weekDates.push({
147
- date: nextDate,
148
- isCurrentMonth: false,
149
- isToday: isToday(nextDate),
150
- hasEvents: dateEvents.length > 0,
151
- events: dateEvents
152
- });
153
- nextMonthDay++;
154
- } else {
155
- const currentDate = new Date(year, month, day);
156
- const dateEvents = getEventsForDate(events, currentDate);
157
- weekDates.push({
158
- date: currentDate,
159
- isCurrentMonth: true,
160
- isToday: isToday(currentDate),
161
- hasEvents: dateEvents.length > 0,
162
- events: dateEvents
163
- });
164
- day++;
165
- }
166
- }
167
- dates.push(weekDates);
168
- }
169
- return dates;
170
- }
171
- function getPopupPositionClass(selectedDayIndex) {
172
- if (selectedDayIndex === null) return "popup-center-bottom";
173
- if (selectedDayIndex < 3) {
174
- return "popup-right";
175
- } else if (selectedDayIndex > 4) {
176
- return "popup-left";
177
- } else {
178
- return "popup-center-bottom";
179
- }
180
- }
181
- function getCellClasses(calendarDate) {
182
- const classes = [];
183
- if (!calendarDate.isCurrentMonth) {
184
- classes.push("other-month");
185
- }
186
- if (calendarDate.isToday) {
187
- classes.push("schedule--current--exam");
188
- }
189
- if (calendarDate.hasEvents) {
190
- classes.push("has--event");
191
- }
192
- return classes;
193
- }
194
- function formatDateForDisplay(date) {
195
- return `${DAYS[date.getDay()]} ${date.getDate()}`;
196
- }
197
- function getMonthYearText(year, month) {
198
- return `${MONTHS_FULL[month]} ${year}`;
199
- }
200
- function formatTimeRange(event) {
201
- if (event.allDay || !event.startTime && !event.endTime) {
202
- return "All day";
203
- }
204
- if (event.startTime && event.endTime) {
205
- return `${event.startTime} - ${event.endTime}`;
206
- }
207
- if (event.startTime) {
208
- return `${event.startTime}`;
209
- }
210
- return "";
211
- }
212
- function formatAttendees(attendees) {
213
- if (!attendees || attendees.length === 0) return "";
214
- if (attendees.length === 1) return attendees[0];
215
- if (attendees.length === 2) return attendees.join(" and ");
216
- return `${attendees.slice(0, -1).join(", ")}, and ${attendees[attendees.length - 1]}`;
217
- }
218
- function sortEventsByTime(events) {
219
- return [...events].sort((a, b) => {
220
- const aAllDay = a.allDay || !a.startTime && !a.endTime;
221
- const bAllDay = b.allDay || !b.startTime && !b.endTime;
222
- if (aAllDay && !bAllDay) return -1;
223
- if (!aAllDay && bAllDay) return 1;
224
- if (!a.startTime || !b.startTime) return 0;
225
- return a.startTime.localeCompare(b.startTime);
226
- });
227
- }
228
- var DEFAULT_CATEGORY_COLORS = {
229
- work: "#3b82f6",
230
- personal: "#8b5cf6",
231
- meeting: "#10b981",
232
- deadline: "#ef4444",
233
- appointment: "#f59e0b",
234
- other: "#6b7280"
235
- };
236
- function getDefaultEventColor(category, customColors) {
237
- const colorMap = customColors || DEFAULT_CATEGORY_COLORS;
238
- if (category && colorMap[category]) {
239
- return colorMap[category];
240
- }
241
- return "#fc8917";
242
- }
243
- function mergeCategoryColors(customColors) {
244
- return {
245
- ...DEFAULT_CATEGORY_COLORS,
246
- ...customColors
247
- };
248
- }
249
- function isValidHexColor(color) {
250
- return /^#([0-9A-F]{3}){1,2}$/i.test(color);
251
- }
252
- function getCategoryColor(category, customColors) {
253
- const colorMap = mergeCategoryColors(customColors);
254
- const color = colorMap[category] || colorMap.other || "#fc8917";
255
- return isValidHexColor(color) ? color : "#fc8917";
256
- }
257
-
258
- // src/core/calendar-engine.ts
259
- var CalendarEngine = class {
260
- constructor(config) {
261
- this.listeners = /* @__PURE__ */ new Set();
262
- this.config = config;
263
- this.categoryColors = mergeCategoryColors(config.categoryColors);
264
- const initialDate = config.initialDate || /* @__PURE__ */ new Date();
265
- this.state = {
266
- currentYear: initialDate.getFullYear(),
267
- currentMonth: initialDate.getMonth(),
268
- currentDate: initialDate.getDate(),
269
- selectedDate: null,
270
- selectedDayIndex: null,
271
- tasks: []
272
- };
273
- }
274
- /**
275
- * Subscribe to state changes
276
- */
277
- subscribe(listener) {
278
- this.listeners.add(listener);
279
- return () => this.listeners.delete(listener);
280
- }
281
- /**
282
- * Notify all listeners of state changes
283
- */
284
- notify() {
285
- this.listeners.forEach((listener) => listener());
286
- }
287
- /**
288
- * Get current state
289
- */
290
- getState() {
291
- return { ...this.state };
292
- }
293
- /**
294
- * Get view model with computed properties
295
- */
296
- getViewModel() {
297
- const calendarDates = generateCalendarDates(
298
- this.state.currentYear,
299
- this.state.currentMonth,
300
- this.config.events,
301
- this.config.weekStartsOn
302
- );
303
- return {
304
- ...this.state,
305
- months: MONTHS,
306
- days: DAYS,
307
- years: generateYears(this.config.minYear, this.config.maxYear),
308
- monthAndYearText: getMonthYearText(
309
- this.state.currentYear,
310
- this.state.currentMonth
311
- ),
312
- scheduleDay: this.state.selectedDate ? formatDateForDisplay(this.state.selectedDate) : "",
313
- calendarDates,
314
- popupPositionClass: getPopupPositionClass(this.state.selectedDayIndex)
315
- };
316
- }
317
- /**
318
- * Get actions object
319
- */
320
- getActions() {
321
- return {
322
- next: this.next.bind(this),
323
- previous: this.previous.bind(this),
324
- jump: this.jump.bind(this),
325
- goToToday: this.goToToday.bind(this),
326
- isCurrentMonth: this.isCurrentMonth.bind(this),
327
- selectDate: this.selectDate.bind(this),
328
- updateTasks: this.updateTasks.bind(this)
329
- };
330
- }
331
- /**
332
- * Navigate to next month
333
- */
334
- next() {
335
- if (this.state.currentMonth === 11) {
336
- this.state.currentMonth = 0;
337
- this.state.currentYear++;
338
- } else {
339
- this.state.currentMonth++;
340
- }
341
- this.state.selectedDate = null;
342
- this.state.selectedDayIndex = null;
343
- this.updateTasks();
344
- this.notify();
345
- }
346
- /**
347
- * Navigate to previous month
348
- */
349
- previous() {
350
- if (this.state.currentMonth === 0) {
351
- this.state.currentMonth = 11;
352
- this.state.currentYear--;
353
- } else {
354
- this.state.currentMonth--;
355
- }
356
- this.state.selectedDate = null;
357
- this.state.selectedDayIndex = null;
358
- this.updateTasks();
359
- this.notify();
360
- }
361
- /**
362
- * Jump to specific month and year
363
- */
364
- jump(year, month) {
365
- this.state.currentYear = year;
366
- this.state.currentMonth = month;
367
- this.state.selectedDate = null;
368
- this.state.selectedDayIndex = null;
369
- this.updateTasks();
370
- this.notify();
371
- }
372
- /**
373
- * Navigate to current month (today)
374
- */
375
- goToToday() {
376
- const today = /* @__PURE__ */ new Date();
377
- this.state.currentYear = today.getFullYear();
378
- this.state.currentMonth = today.getMonth();
379
- this.state.selectedDate = null;
380
- this.state.selectedDayIndex = null;
381
- this.updateTasks();
382
- this.notify();
383
- }
384
- /**
385
- * Check if currently viewing today's month
386
- */
387
- isCurrentMonth() {
388
- const today = /* @__PURE__ */ new Date();
389
- return this.state.currentYear === today.getFullYear() && this.state.currentMonth === today.getMonth();
390
- }
391
- /**
392
- * Select a specific date
393
- */
394
- selectDate(date, dayIndex) {
395
- this.state.selectedDate = date;
396
- this.state.selectedDayIndex = dayIndex ?? null;
397
- this.state.currentDate = date.getDate();
398
- this.state.currentMonth = date.getMonth();
399
- this.state.currentYear = date.getFullYear();
400
- this.updateTasks();
401
- this.notify();
402
- }
403
- /**
404
- * Update tasks for the currently selected date
405
- */
406
- updateTasks() {
407
- if (!this.state.selectedDate) {
408
- this.state.tasks = [];
409
- return;
410
- }
411
- this.state.tasks = getEventsForDate(
412
- this.config.events,
413
- this.state.selectedDate
414
- );
415
- }
416
- /**
417
- * Update events configuration
418
- */
419
- updateEvents(events) {
420
- this.config.events = events;
421
- this.updateTasks();
422
- this.notify();
423
- }
424
- /**
425
- * Handle date cell click
426
- */
427
- handleDateClick(date, dayIndex) {
428
- this.selectDate(date, dayIndex);
429
- }
430
- /**
431
- * Check if date has events
432
- */
433
- hasEventsForDate(date) {
434
- return getEventsForDate(this.config.events, date).length > 0;
435
- }
436
- /**
437
- * Get events for a specific date
438
- */
439
- getEventsForDate(date) {
440
- return getEventsForDate(this.config.events, date);
441
- }
442
- /**
443
- * Clear selected date
444
- */
445
- clearSelection() {
446
- this.state.selectedDate = null;
447
- this.state.selectedDayIndex = null;
448
- this.state.tasks = [];
449
- this.notify();
450
- }
451
- /**
452
- * Get category color (with custom colors support)
453
- */
454
- getCategoryColor(category) {
455
- if (!category) return "#fc8917";
456
- return getCategoryColor(category, this.categoryColors);
457
- }
458
- /**
459
- * Update category colors dynamically
460
- */
461
- updateCategoryColors(colors) {
462
- this.categoryColors = mergeCategoryColors(colors);
463
- this.notify();
464
- }
465
- /**
466
- * Get all category colors
467
- */
468
- getCategoryColors() {
469
- return { ...this.categoryColors };
470
- }
471
- /**
472
- * Register a new category with color
473
- */
474
- registerCategory(name, color) {
475
- this.categoryColors[name] = color;
476
- this.notify();
477
- }
478
- /**
479
- * Destroy the engine and cleanup listeners
480
- */
481
- destroy() {
482
- this.listeners.clear();
483
- }
484
- };
485
-
486
- // src/react/components/DatePopup.tsx
487
- var import_jsx_runtime = require("react/jsx-runtime");
488
- var PriorityBadge = ({ priority }) => {
489
- if (!priority) return null;
490
- const priorityConfig = {
491
- high: { label: "HIGH", className: "badge priority-high" },
492
- medium: { label: "MEDIUM", className: "badge priority-medium" },
493
- low: { label: "LOW", className: "badge priority-low" }
494
- };
495
- const config = priorityConfig[priority];
496
- if (!config) return null;
497
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: config.className, children: config.label });
498
- };
499
- var StatusBadge = ({ status }) => {
500
- if (!status || status === "scheduled") return null;
501
- const statusConfig = {
502
- completed: { label: "COMPLETED", className: "badge status-completed" },
503
- cancelled: { label: "CANCELLED", className: "badge status-cancelled" },
504
- tentative: { label: "TENTATIVE", className: "badge status-tentative" }
505
- };
506
- const config = statusConfig[status];
507
- if (!config) return null;
508
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: config.className, children: config.label });
509
- };
510
- var CategoryBadge = ({ category }) => {
511
- if (!category) return null;
512
- const categoryConfig = {
513
- work: { label: "WORK", className: "badge category-work" },
514
- personal: { label: "PERSONAL", className: "badge category-personal" },
515
- meeting: { label: "MEETING", className: "badge category-meeting" },
516
- deadline: { label: "DEADLINE", className: "badge category-deadline" },
517
- appointment: {
518
- label: "APPOINTMENT",
519
- className: "badge category-appointment"
520
- },
521
- other: { label: "OTHER", className: "badge category-other" }
522
- };
523
- const config = categoryConfig[category];
524
- if (!config) return null;
525
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: config.className, children: config.label });
526
- };
527
- var DatePopup = ({
528
- isVisible,
529
- selectedDate,
530
- events,
531
- scheduleDay,
532
- popupPositionClass,
533
- onEventClick,
534
- onClose,
535
- renderEvent,
536
- renderNoEvents
537
- }) => {
538
- if (!isVisible || !selectedDate) return null;
539
- const handleEventClick = (event) => {
540
- onEventClick?.(event);
541
- };
542
- const showScrollHint = events.length > 3;
543
- const defaultRenderEvent = (event) => {
544
- const timeRange = formatTimeRange(event);
545
- const attendeesList = formatAttendees(event.attendees);
546
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
547
- "div",
548
- {
549
- className: `event-card${onEventClick ? " clickable" : ""}`,
550
- onClick: () => handleEventClick(event),
551
- style: {
552
- borderLeftColor: event.color || void 0
553
- },
554
- children: [
555
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-header", children: [
556
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "event-title", children: event.name }),
557
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-badges", children: [
558
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CategoryBadge, { category: event.category }),
559
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PriorityBadge, { priority: event.priority }),
560
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusBadge, { status: event.status })
561
- ] })
562
- ] }),
563
- timeRange && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-time", children: [
564
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-label", children: "Time:" }),
565
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-value", children: timeRange })
566
- ] }),
567
- event.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "event-description", children: event.description }),
568
- event.location && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-time", children: [
569
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-label", children: "Location:" }),
570
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-value", children: event.location })
571
- ] }),
572
- attendeesList && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-time", children: [
573
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-label", children: "Attendees:" }),
574
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-value", children: attendeesList })
575
- ] }),
576
- event.organizer && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-time", children: [
577
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-label", children: "Organizer:" }),
578
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-value", children: event.organizer })
579
- ] }),
580
- event.notes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "event-time", children: [
581
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-label", children: "Notes:" }),
582
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-time-value", children: event.notes })
583
- ] }),
584
- event.url && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "event-time", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
585
- "a",
586
- {
587
- href: event.url,
588
- target: "_blank",
589
- rel: "noopener noreferrer",
590
- className: "event-link",
591
- onClick: (e) => e.stopPropagation(),
592
- children: "View Details \u2192"
593
- }
594
- ) }),
595
- event.tags && event.tags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "event-tags", children: event.tags.map((tag, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "event-tag", children: tag }, idx)) })
596
- ]
597
- },
598
- event.id || event.name
599
- );
600
- };
601
- const defaultRenderNoEvents = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "no-events-message", children: "No events scheduled for this day." });
602
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `date-popup ${popupPositionClass}`, children: [
603
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "popup-header", children: [
604
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: scheduleDay }),
605
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
606
- "button",
607
- {
608
- type: "button",
609
- className: "popup-close",
610
- onClick: onClose,
611
- "aria-label": "Close",
612
- children: "\u2715"
613
- }
614
- )
615
- ] }),
616
- showScrollHint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "scroll-hint", children: "\u2193 Scroll to see more events \u2193" }),
617
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "events-container", children: events.length > 0 ? events.map(
618
- (event) => renderEvent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
619
- "div",
620
- {
621
- className: `event-card${onEventClick ? " clickable" : ""}`,
622
- onClick: () => handleEventClick(event),
623
- children: renderEvent(event)
624
- },
625
- event.id || event.name
626
- ) : defaultRenderEvent(event)
627
- ) : renderNoEvents ? renderNoEvents() : defaultRenderNoEvents() })
628
- ] });
629
- };
630
-
631
- // src/react/components/Calendar.tsx
632
- var import_jsx_runtime2 = require("react/jsx-runtime");
633
- var Calendar = ({
634
- events,
635
- initialDate,
636
- minYear,
637
- maxYear,
638
- weekStartsOn = 0,
639
- useShortMonthNames = false,
640
- onDateSelect,
641
- onEventClick,
642
- onMonthChange,
643
- className = "",
644
- style,
645
- renderEvent,
646
- renderNoEvents,
647
- title,
648
- theme
649
- }) => {
650
- const engine = (0, import_react.useMemo)(
651
- () => new CalendarEngine({
652
- events,
653
- initialDate,
654
- minYear,
655
- maxYear,
656
- weekStartsOn
657
- }),
658
- [events, initialDate, minYear, maxYear, weekStartsOn]
659
- );
660
- const [, forceUpdate] = (0, import_react.useState)({});
661
- const rerender = (0, import_react.useCallback)(() => forceUpdate({}), []);
662
- const [pickerOpen, setPickerOpen] = (0, import_react.useState)(false);
663
- const [yearInput, setYearInput] = (0, import_react.useState)("");
664
- const [yearInputValid, setYearInputValid] = (0, import_react.useState)(true);
665
- const pickerRef = (0, import_react.useRef)(null);
666
- (0, import_react.useEffect)(() => {
667
- const unsubscribe = engine.subscribe(rerender);
668
- return unsubscribe;
669
- }, [engine, rerender]);
670
- (0, import_react.useEffect)(() => {
671
- engine.updateEvents(events);
672
- }, [engine, events]);
673
- (0, import_react.useEffect)(() => {
674
- return () => {
675
- engine.destroy();
676
- };
677
- }, [engine]);
678
- (0, import_react.useEffect)(() => {
679
- if (theme) {
680
- const root = document.documentElement;
681
- if (theme.primary)
682
- root.style.setProperty("--calendar-primary-color", theme.primary);
683
- if (theme.secondary)
684
- root.style.setProperty("--calendar-secondary-color", theme.secondary);
685
- if (theme.tertiary)
686
- root.style.setProperty("--calendar-tertiary-color", theme.tertiary);
687
- if (theme.textColor)
688
- root.style.setProperty("--calendar-text-color", theme.textColor);
689
- if (theme.textLight)
690
- root.style.setProperty("--calendar-text-light", theme.textLight);
691
- if (theme.background)
692
- root.style.setProperty("--calendar-background", theme.background);
693
- if (theme.cellHover)
694
- root.style.setProperty("--calendar-cell-hover", theme.cellHover);
695
- if (theme.borderColor)
696
- root.style.setProperty("--calendar-border-color", theme.borderColor);
697
- if (theme.todayOutline)
698
- root.style.setProperty("--calendar-today-outline", theme.todayOutline);
699
- if (theme.selectedBg)
700
- root.style.setProperty("--calendar-selected-bg", theme.selectedBg);
701
- if (theme.eventIndicator)
702
- root.style.setProperty(
703
- "--calendar-event-indicator",
704
- theme.eventIndicator
705
- );
706
- }
707
- }, [theme]);
708
- const viewModel = engine.getViewModel();
709
- const actions = engine.getActions();
710
- const { selectedDate, tasks } = viewModel;
711
- const handleDateClick = (event) => {
712
- const td = event.target.closest("td");
713
- if (!td) return;
714
- const tr = td.parentElement;
715
- if (!tr) return;
716
- const weekIndex = tr.rowIndex - 1;
717
- const dayIndex = Array.from(tr.children).indexOf(td);
718
- const calendarDate = viewModel.calendarDates[weekIndex]?.[dayIndex];
719
- if (!calendarDate) return;
720
- engine.handleDateClick(calendarDate.date, dayIndex);
721
- onDateSelect?.(calendarDate.date);
722
- };
723
- const handleMonthChange = (0, import_react.useCallback)(() => {
724
- onMonthChange?.(viewModel.currentYear, viewModel.currentMonth);
725
- }, [onMonthChange, viewModel.currentYear, viewModel.currentMonth]);
726
- const handleNext = () => {
727
- actions.next();
728
- handleMonthChange();
729
- };
730
- const handlePrevious = () => {
731
- actions.previous();
732
- handleMonthChange();
733
- };
734
- const handleGoToToday = () => {
735
- actions.goToToday();
736
- setPickerOpen(false);
737
- const today2 = /* @__PURE__ */ new Date();
738
- onMonthChange?.(today2.getFullYear(), today2.getMonth());
739
- };
740
- const togglePicker = () => {
741
- const newOpen = !pickerOpen;
742
- setPickerOpen(newOpen);
743
- if (newOpen) {
744
- setYearInput(String(viewModel.currentYear));
745
- setYearInputValid(true);
746
- }
747
- };
748
- const today = /* @__PURE__ */ new Date();
749
- const computedMinYear = minYear ?? today.getFullYear() - 30;
750
- const computedMaxYear = maxYear ?? today.getFullYear() + 10;
751
- const handleYearInputChange = (e) => {
752
- const value = e.target.value;
753
- if (value === "" || /^\d+$/.test(value)) {
754
- setYearInput(value);
755
- const year = parseInt(value, 10);
756
- setYearInputValid(
757
- value === "" || year >= computedMinYear && year <= computedMaxYear
758
- );
759
- }
760
- };
761
- const handleYearInputBlur = () => {
762
- const year = parseInt(yearInput, 10);
763
- if (isNaN(year) || year < computedMinYear || year > computedMaxYear) {
764
- setYearInput(String(viewModel.currentYear));
765
- setYearInputValid(true);
766
- } else {
767
- actions.jump(year, viewModel.currentMonth);
768
- handleMonthChange();
769
- }
770
- };
771
- const handleYearPrev = () => {
772
- const newYear = viewModel.currentYear - 1;
773
- if (newYear >= computedMinYear) {
774
- actions.jump(newYear, viewModel.currentMonth);
775
- setYearInput(String(newYear));
776
- handleMonthChange();
777
- }
778
- };
779
- const handleYearNext = () => {
780
- const newYear = viewModel.currentYear + 1;
781
- if (newYear <= computedMaxYear) {
782
- actions.jump(newYear, viewModel.currentMonth);
783
- setYearInput(String(newYear));
784
- handleMonthChange();
785
- }
786
- };
787
- const handleMonthSelect = (month) => {
788
- actions.jump(viewModel.currentYear, month);
789
- setPickerOpen(false);
790
- handleMonthChange();
791
- };
792
- (0, import_react.useEffect)(() => {
793
- const handleClickOutside = (event) => {
794
- if (pickerRef.current && !pickerRef.current.contains(event.target)) {
795
- setPickerOpen(false);
796
- }
797
- };
798
- if (pickerOpen) {
799
- document.addEventListener("mousedown", handleClickOutside);
800
- }
801
- return () => document.removeEventListener("mousedown", handleClickOutside);
802
- }, [pickerOpen]);
803
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `kalendly-calendar ${className}`, style, children: [
804
- title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "page--title", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { children: title }) }),
805
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "calendar--content", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "calendar--card", children: [
806
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "calendar--nav-header", children: [
807
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
808
- "button",
809
- {
810
- type: "button",
811
- className: "calendar--nav-arrow",
812
- onClick: handlePrevious,
813
- "aria-label": "Previous month",
814
- children: "\u2039"
815
- }
816
- ),
817
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "calendar--picker-container", ref: pickerRef, children: [
818
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
819
- "button",
820
- {
821
- type: "button",
822
- className: "calendar--picker-btn",
823
- onClick: togglePicker,
824
- ...{ "aria-expanded": pickerOpen },
825
- "aria-haspopup": "true",
826
- children: [
827
- useShortMonthNames ? `${MONTHS[viewModel.currentMonth]} ${viewModel.currentYear}` : viewModel.monthAndYearText,
828
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "calendar--picker-chevron", children: "\u25BE" })
829
- ]
830
- }
831
- ),
832
- pickerOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "calendar--picker-dropdown", children: [
833
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "calendar--picker-year-row", children: [
834
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
835
- "button",
836
- {
837
- type: "button",
838
- className: "calendar--picker-year-arrow",
839
- onClick: handleYearPrev,
840
- disabled: viewModel.currentYear <= computedMinYear,
841
- "aria-label": "Previous year",
842
- children: "\u2039"
843
- }
844
- ),
845
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
846
- "input",
847
- {
848
- type: "text",
849
- className: `calendar--picker-year-input${!yearInputValid ? " invalid" : ""}`,
850
- value: yearInput,
851
- onChange: handleYearInputChange,
852
- onBlur: handleYearInputBlur,
853
- onKeyDown: (e) => {
854
- if (e.key === "Enter") handleYearInputBlur();
855
- },
856
- "aria-label": "Year"
857
- }
858
- ),
859
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
860
- "button",
861
- {
862
- type: "button",
863
- className: "calendar--picker-year-arrow",
864
- onClick: handleYearNext,
865
- disabled: viewModel.currentYear >= computedMaxYear,
866
- "aria-label": "Next year",
867
- children: "\u203A"
868
- }
869
- )
870
- ] }),
871
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "calendar--picker-months", children: (useShortMonthNames ? MONTHS : MONTHS_FULL).map(
872
- (month, index) => {
873
- const isSelected = index === viewModel.currentMonth;
874
- const isCurrentMonth = index === today.getMonth() && viewModel.currentYear === today.getFullYear();
875
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
876
- "button",
877
- {
878
- type: "button",
879
- className: `calendar--picker-month${isSelected ? " selected" : ""}${isCurrentMonth ? " current-month" : ""}`,
880
- onClick: () => handleMonthSelect(index),
881
- children: month
882
- },
883
- month
884
- );
885
- }
886
- ) })
887
- ] })
888
- ] }),
889
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
890
- "button",
891
- {
892
- type: "button",
893
- className: "calendar--today-btn",
894
- onClick: handleGoToToday,
895
- disabled: actions.isCurrentMonth(),
896
- children: "Today"
897
- }
898
- ),
899
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
900
- "button",
901
- {
902
- type: "button",
903
- className: "calendar--nav-arrow",
904
- onClick: handleNext,
905
- "aria-label": "Next month",
906
- children: "\u203A"
907
- }
908
- )
909
- ] }),
910
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { className: "calendar--table calendar--table--bordered", children: [
911
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: viewModel.days.map((day) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: day.slice(0, 3) }, day)) }) }),
912
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { onClick: handleDateClick, children: viewModel.calendarDates.map((week, weekIndex) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: week.map((calendarDate, dayIndex) => {
913
- const cellClasses = getCellClasses(calendarDate);
914
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
915
- "td",
916
- {
917
- className: cellClasses.join(" "),
918
- children: calendarDate.date.getDate()
919
- },
920
- `${weekIndex}-${dayIndex}`
921
- );
922
- }) }, weekIndex)) })
923
- ] }),
924
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
925
- DatePopup,
926
- {
927
- isVisible: !!selectedDate,
928
- selectedDate,
929
- events: tasks,
930
- scheduleDay: viewModel.scheduleDay,
931
- popupPositionClass: viewModel.popupPositionClass,
932
- onClose: () => engine.clearSelection(),
933
- onEventClick,
934
- renderEvent,
935
- renderNoEvents
936
- }
937
- )
938
- ] }) })
939
- ] });
940
- };
941
- // Annotate the CommonJS export names for ESM import in node:
942
- 0 && (module.exports = {
943
- Calendar,
944
- CalendarEngine,
945
- DAYS,
946
- DEFAULT_CATEGORY_COLORS,
947
- DatePopup,
948
- MONTHS,
949
- MONTHS_FULL,
950
- formatAttendees,
951
- formatDateForDisplay,
952
- formatTimeRange,
953
- generateCalendarDates,
954
- generateYears,
955
- getCategoryColor,
956
- getCellClasses,
957
- getDefaultEventColor,
958
- getEventsForDate,
959
- getMonthYearText,
960
- getPopupPositionClass,
961
- hasEvents,
962
- isSameDay,
963
- isToday,
964
- isValidHexColor,
965
- mergeCategoryColors,
966
- normalizeDate,
967
- sortEventsByTime
968
- });
969
- //# sourceMappingURL=index.js.map