kalendly 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -145,7 +145,55 @@ function App() {
145
145
 
146
146
  ### Vue 3
147
147
 
148
- Vue 3 supports custom elements natively — bind props with `:` and listen to events with `@`:
148
+ Vue 3 supports custom elements natively — bind props with `:` and listen to events with `@`.
149
+
150
+ > **Vue-specific:** Vue's template compiler warns on unknown tags. React, Solid.js, and Svelte treat hyphenated tags as DOM elements natively — no config needed. Angular uses `CUSTOM_ELEMENTS_SCHEMA` (see the Angular section below).
151
+
152
+ Tell Vue's compiler that `<kal-*>` tags are native custom elements. The config location depends on your build tool:
153
+
154
+ **Vite** (`vite.config.ts`):
155
+
156
+ ```ts
157
+ vue({
158
+ template: {
159
+ compilerOptions: {
160
+ isCustomElement: tag => tag.startsWith('kal-'),
161
+ },
162
+ },
163
+ });
164
+ ```
165
+
166
+ **Nuxt 3** (`nuxt.config.ts`):
167
+
168
+ ```ts
169
+ export default defineNuxtConfig({
170
+ vue: {
171
+ compilerOptions: {
172
+ isCustomElement: tag => tag.startsWith('kal-'),
173
+ },
174
+ },
175
+ });
176
+ ```
177
+
178
+ **webpack / Vue CLI** (`vue.config.js`):
179
+
180
+ ```js
181
+ module.exports = {
182
+ chainWebpack: config => {
183
+ config.module
184
+ .rule('vue')
185
+ .use('vue-loader')
186
+ .tap(options => ({
187
+ ...options,
188
+ compilerOptions: {
189
+ isCustomElement: tag => tag.startsWith('kal-'),
190
+ },
191
+ }));
192
+ },
193
+ };
194
+ ```
195
+
196
+ Without this the component still renders correctly — Vue falls back to a native DOM element. This only suppresses the console warning.
149
197
 
150
198
  ```vue
151
199
  <template>
@@ -337,9 +385,14 @@ Hides all event details from the end user — only booked/free state is shown. D
337
385
  <kal-calendar availability-mode="day"></kal-calendar>
338
386
  ```
339
387
 
340
- Days with events get a red tint (booked); days without get a green tint (free). Clicking a day opens no popup.
388
+ Days with events are tinted red (booked); days without events are tinted green (free). Only cells in the current month are colour-coded — other-month cells remain grayed out. Clicking a day fires no popup and reveals no event details.
341
389
 
342
- Pass the minimal event shape — no names, no descriptions:
390
+ <div align="center">
391
+ <img src="./docs/images/day.png" alt="Availability day view — month grid with red booked cells and green free cells"/>
392
+ <p><em>Day view: the month grid shows only booked/free state per day — event names, times, and attendees are never revealed</em></p>
393
+ </div>
394
+
395
+ Pass the minimal event shape — only `id` and `date` are required; `startTime`/`endTime` are optional and mark the whole day as booked regardless:
343
396
 
344
397
  ```js
345
398
  cal.events = [
@@ -355,7 +408,12 @@ cal.events = [
355
408
  <kal-calendar availability-mode="time"></kal-calendar>
356
409
  ```
357
410
 
358
- Clicking a day opens a time-grid popup showing which hours are booked (red) and free (green). No event name or organiser is ever rendered.
411
+ Clicking a day opens a popup with a 24-slot hourly grid (00:00 23:00). Each slot shows only "Booked" or "Available" — no event name or organiser is ever rendered. A slot is booked if any event's time window overlaps that hour; the rest are free.
412
+
413
+ <div align="center">
414
+ <img src="./docs/images/time.png" alt="Availability time view — day popup showing 24 hourly slots coloured red (booked) or green (available)"/>
415
+ <p><em>Time view: clicking a day opens an hourly grid — booked slots in red, available slots in green; no event details exposed</em></p>
416
+ </div>
359
417
 
360
418
  ### Selectable range
361
419
 
@@ -98,6 +98,8 @@ interface CalendarTheme {
98
98
  borderColor?: string;
99
99
  todayOutline?: string;
100
100
  selectedBg?: string;
101
+ headerBg?: string;
102
+ popupBg?: string;
101
103
  eventIndicator?: string;
102
104
  }
103
105
 
@@ -98,6 +98,8 @@ interface CalendarTheme {
98
98
  borderColor?: string;
99
99
  todayOutline?: string;
100
100
  selectedBg?: string;
101
+ headerBg?: string;
102
+ popupBg?: string;
101
103
  eventIndicator?: string;
102
104
  }
103
105
 
package/dist/index.d.mts CHANGED
@@ -98,6 +98,8 @@ interface CalendarTheme {
98
98
  borderColor?: string;
99
99
  todayOutline?: string;
100
100
  selectedBg?: string;
101
+ headerBg?: string;
102
+ popupBg?: string;
101
103
  eventIndicator?: string;
102
104
  }
103
105
 
package/dist/index.d.ts CHANGED
@@ -98,6 +98,8 @@ interface CalendarTheme {
98
98
  borderColor?: string;
99
99
  todayOutline?: string;
100
100
  selectedBg?: string;
101
+ headerBg?: string;
102
+ popupBg?: string;
101
103
  eventIndicator?: string;
102
104
  }
103
105
 
package/dist/index.js CHANGED
@@ -678,6 +678,8 @@ var init_CalendarElement = __esm({
678
678
  root.style.setProperty("--calendar-today-outline", t.todayOutline);
679
679
  if (t.selectedBg)
680
680
  root.style.setProperty("--calendar-selected-bg", t.selectedBg);
681
+ if (t.headerBg) root.style.setProperty("--calendar-header-bg", t.headerBg);
682
+ if (t.popupBg) root.style.setProperty("--calendar-popup-bg", t.popupBg);
681
683
  if (t.eventIndicator)
682
684
  root.style.setProperty("--calendar-event-indicator", t.eventIndicator);
683
685
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/types.ts","../src/core/utils.ts","../src/core/calendar-engine.ts","../src/core/index.ts","../src/web-components/CalendarElement.ts","../src/web-components/index.ts"],"sourcesContent":["export interface CalendarEvent {\n id: string | number;\n name: string;\n date: string | Date;\n\n // Time fields\n startTime?: string;\n endTime?: string;\n allDay?: boolean;\n\n // Display & categorization\n description?: string;\n color?: string;\n category?:\n | 'work'\n | 'personal'\n | 'meeting'\n | 'deadline'\n | 'appointment'\n | 'other';\n location?: string;\n url?: string;\n\n // Status & priority\n status?: 'scheduled' | 'completed' | 'cancelled' | 'tentative';\n priority?: 'low' | 'medium' | 'high';\n\n // Collaboration\n attendees?: string[];\n organizer?: string;\n\n // Reminders & recurrence\n reminders?: number[];\n recurring?: {\n frequency: 'daily' | 'weekly' | 'monthly' | 'yearly';\n interval?: number;\n endDate?: string | Date;\n daysOfWeek?: number[];\n };\n\n // Metadata\n notes?: string;\n tags?: string[];\n createdAt?: string | Date;\n updatedAt?: string | Date;\n\n // Flexibility for custom fields\n [key: string]: unknown;\n}\n\nexport interface CalendarDate {\n date: Date;\n isCurrentMonth: boolean;\n isToday: boolean;\n hasEvents: boolean;\n events: CalendarEvent[];\n}\n\nexport interface CalendarState {\n currentYear: number;\n currentMonth: number;\n currentDate: number;\n selectedDate: Date | null;\n selectedDayIndex: number | null;\n tasks: CalendarEvent[];\n}\n\nexport interface CategoryColorMap {\n [category: string]: string;\n}\n\nexport interface CalendarConfig {\n events: CalendarEvent[];\n initialDate?: Date;\n minYear?: number;\n maxYear?: number;\n weekStartsOn?: 0 | 1;\n categoryColors?: CategoryColorMap;\n}\n\nexport interface CalendarActions {\n next: () => void;\n previous: () => void;\n jump: (year: number, month: number) => void;\n goToToday: () => void;\n isCurrentMonth: () => boolean;\n selectDate: (date: Date) => void;\n updateTasks: () => void;\n}\n\nexport interface PopupPosition {\n class:\n | 'popup-left'\n | 'popup-right'\n | 'popup-center-top'\n | 'popup-center-bottom';\n style?: Record<string, string | number>;\n}\n\nexport interface CalendarViewModel extends CalendarState {\n months: string[];\n days: string[];\n years: number[];\n monthAndYearText: string;\n scheduleDay: string;\n calendarDates: CalendarDate[][];\n popupPositionClass: string;\n}\n\nexport type CalendarEventHandler = (event: CalendarEvent) => void;\n\nexport interface CalendarProps {\n events: CalendarEvent[];\n initialDate?: Date;\n minYear?: number;\n maxYear?: number;\n weekStartsOn?: 0 | 1;\n useShortMonthNames?: boolean;\n onDateSelect?: (date: Date) => void;\n onEventClick?: CalendarEventHandler;\n onMonthChange?: (year: number, month: number) => void;\n}\n\nexport interface CalendarTheme {\n primary?: string;\n secondary?: string;\n tertiary?: string;\n textColor?: string;\n textLight?: string;\n background?: string;\n cellHover?: string;\n borderColor?: string;\n todayOutline?: string;\n selectedBg?: string;\n eventIndicator?: string;\n}\n","import { CalendarEvent, CalendarDate, CategoryColorMap } from './types';\n\nexport const MONTHS = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec',\n];\n\nexport const MONTHS_FULL = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n];\n\nexport const DAYS = [\n 'Sunday',\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday',\n];\n\nexport function normalizeDate(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);\n}\n\nexport function isSameDay(date1: Date, date2: Date): boolean {\n return normalizeDate(date1).getTime() === normalizeDate(date2).getTime();\n}\n\nexport function isToday(date: Date): boolean {\n return isSameDay(date, new Date());\n}\n\nexport function generateYears(minYear?: number, maxYear?: number): number[] {\n const currentYear = new Date().getFullYear();\n const min = minYear ?? currentYear - 30;\n const max = maxYear ?? currentYear + 10;\n\n return Array.from({ length: max - min + 1 }, (_, i) => min + i);\n}\n\nexport function getEventsForDate(\n events: CalendarEvent[],\n date: Date\n): CalendarEvent[] {\n const normalizedTargetDate = normalizeDate(date);\n\n return events.filter(event => {\n const eventDate = normalizeDate(new Date(event.date));\n return eventDate.getTime() === normalizedTargetDate.getTime();\n });\n}\n\nexport function hasEvents(events: CalendarEvent[], date: Date): boolean {\n return getEventsForDate(events, date).length > 0;\n}\n\nexport function generateCalendarDates(\n year: number,\n month: number,\n events: CalendarEvent[] = [],\n weekStartsOn: 0 | 1 = 0\n): CalendarDate[][] {\n const firstDay = new Date(year, month, 1);\n const lastDay = new Date(year, month + 1, 0);\n const daysInMonth = lastDay.getDate();\n const prevMonthLastDay = new Date(year, month, 0).getDate();\n\n let firstDayOfWeek = firstDay.getDay();\n if (weekStartsOn === 1) {\n firstDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1;\n }\n\n const dates: CalendarDate[][] = [];\n let day = 1;\n let nextMonthDay = 1;\n\n for (let week = 0; week < 6; week++) {\n const weekDates: CalendarDate[] = [];\n\n for (let dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {\n if (week === 0 && dayOfWeek < firstDayOfWeek) {\n // Previous month days\n const prevDay = prevMonthLastDay - firstDayOfWeek + dayOfWeek + 1;\n const prevDate = new Date(year, month - 1, prevDay);\n const dateEvents = getEventsForDate(events, prevDate);\n weekDates.push({\n date: prevDate,\n isCurrentMonth: false,\n isToday: isToday(prevDate),\n hasEvents: dateEvents.length > 0,\n events: dateEvents,\n });\n } else if (day > daysInMonth) {\n // Next month days\n const nextDate = new Date(year, month + 1, nextMonthDay);\n const dateEvents = getEventsForDate(events, nextDate);\n weekDates.push({\n date: nextDate,\n isCurrentMonth: false,\n isToday: isToday(nextDate),\n hasEvents: dateEvents.length > 0,\n events: dateEvents,\n });\n nextMonthDay++;\n } else {\n // Current month days\n const currentDate = new Date(year, month, day);\n const dateEvents = getEventsForDate(events, currentDate);\n weekDates.push({\n date: currentDate,\n isCurrentMonth: true,\n isToday: isToday(currentDate),\n hasEvents: dateEvents.length > 0,\n events: dateEvents,\n });\n day++;\n }\n }\n\n dates.push(weekDates);\n }\n\n return dates;\n}\n\nexport function getPopupPositionClass(selectedDayIndex: number | null): string {\n if (selectedDayIndex === null) return 'popup-center-bottom';\n\n if (selectedDayIndex < 3) {\n return 'popup-right';\n } else if (selectedDayIndex > 4) {\n return 'popup-left';\n } else {\n return 'popup-center-bottom';\n }\n}\n\nexport function getCellClasses(calendarDate: CalendarDate): string[] {\n const classes: string[] = [];\n\n if (!calendarDate.isCurrentMonth) {\n classes.push('other-month');\n }\n\n if (calendarDate.isToday) {\n classes.push('schedule--current--exam');\n }\n\n if (calendarDate.hasEvents) {\n classes.push('has--event');\n }\n\n return classes;\n}\n\nexport function formatDateForDisplay(date: Date): string {\n return `${DAYS[date.getDay()]} ${date.getDate()}`;\n}\n\nexport function getMonthYearText(year: number, month: number): string {\n return `${MONTHS_FULL[month]} ${year}`;\n}\n\nexport function formatTimeRange(event: CalendarEvent): string {\n if (event.allDay || (!event.startTime && !event.endTime)) {\n return 'All day';\n }\n\n if (event.startTime && event.endTime) {\n return `${event.startTime} - ${event.endTime}`;\n }\n\n if (event.startTime) {\n return `${event.startTime}`;\n }\n\n return '';\n}\n\nexport function formatAttendees(attendees?: string[]): string {\n if (!attendees || attendees.length === 0) return '';\n\n if (attendees.length === 1) return attendees[0];\n if (attendees.length === 2) return attendees.join(' and ');\n\n return `${attendees.slice(0, -1).join(', ')}, and ${attendees[attendees.length - 1]}`;\n}\n\nexport function sortEventsByTime(events: CalendarEvent[]): CalendarEvent[] {\n return [...events].sort((a, b) => {\n const aAllDay = a.allDay || (!a.startTime && !a.endTime);\n const bAllDay = b.allDay || (!b.startTime && !b.endTime);\n\n if (aAllDay && !bAllDay) return -1;\n if (!aAllDay && bAllDay) return 1;\n\n if (!a.startTime || !b.startTime) return 0;\n return a.startTime.localeCompare(b.startTime);\n });\n}\n\nexport const DEFAULT_CATEGORY_COLORS: CategoryColorMap = {\n work: '#3b82f6',\n personal: '#8b5cf6',\n meeting: '#10b981',\n deadline: '#ef4444',\n appointment: '#f59e0b',\n other: '#6b7280',\n};\n\n// Dynamic function that accepts custom colors\nexport function getDefaultEventColor(\n category?: string,\n customColors?: CategoryColorMap\n): string {\n const colorMap = customColors || DEFAULT_CATEGORY_COLORS;\n\n if (category && colorMap[category]) {\n return colorMap[category];\n }\n\n // Default fallback color\n return '#fc8917';\n}\n\n// Helper to merge custom colors with defaults\nexport function mergeCategoryColors(\n customColors?: CategoryColorMap\n): CategoryColorMap {\n return {\n ...DEFAULT_CATEGORY_COLORS,\n ...customColors,\n };\n}\n\n// Validate if a color is a valid hex color\nexport function isValidHexColor(color: string): boolean {\n return /^#([0-9A-F]{3}){1,2}$/i.test(color);\n}\n\n// Get color for a category with validation\nexport function getCategoryColor(\n category: string,\n customColors?: CategoryColorMap\n): string {\n const colorMap = mergeCategoryColors(customColors);\n const color = colorMap[category] || colorMap.other || '#fc8917';\n\n return isValidHexColor(color) ? color : '#fc8917';\n}\n","import {\n CalendarEvent,\n CalendarState,\n CalendarConfig,\n CalendarActions,\n CalendarViewModel,\n CategoryColorMap,\n} from './types';\nimport {\n generateCalendarDates,\n getEventsForDate,\n generateYears,\n getPopupPositionClass,\n getMonthYearText,\n formatDateForDisplay,\n mergeCategoryColors,\n getCategoryColor,\n MONTHS,\n DAYS,\n} from './utils';\n\nexport class CalendarEngine {\n private state: CalendarState;\n private config: CalendarConfig;\n private listeners: Set<() => void> = new Set();\n private categoryColors: CategoryColorMap;\n\n constructor(config: CalendarConfig) {\n this.config = config;\n this.categoryColors = mergeCategoryColors(config.categoryColors);\n\n const initialDate = config.initialDate || new Date();\n this.state = {\n currentYear: initialDate.getFullYear(),\n currentMonth: initialDate.getMonth(),\n currentDate: initialDate.getDate(),\n selectedDate: null,\n selectedDayIndex: null,\n tasks: [],\n };\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Notify all listeners of state changes\n */\n private notify(): void {\n this.listeners.forEach(listener => listener());\n }\n\n /**\n * Get current state\n */\n getState(): CalendarState {\n return { ...this.state };\n }\n\n /**\n * Get view model with computed properties\n */\n getViewModel(): CalendarViewModel {\n const calendarDates = generateCalendarDates(\n this.state.currentYear,\n this.state.currentMonth,\n this.config.events,\n this.config.weekStartsOn\n );\n\n return {\n ...this.state,\n months: MONTHS,\n days: DAYS,\n years: generateYears(this.config.minYear, this.config.maxYear),\n monthAndYearText: getMonthYearText(\n this.state.currentYear,\n this.state.currentMonth\n ),\n scheduleDay: this.state.selectedDate\n ? formatDateForDisplay(this.state.selectedDate)\n : '',\n calendarDates,\n popupPositionClass: getPopupPositionClass(this.state.selectedDayIndex),\n };\n }\n\n /**\n * Get actions object\n */\n getActions(): CalendarActions {\n return {\n next: this.next.bind(this),\n previous: this.previous.bind(this),\n jump: this.jump.bind(this),\n goToToday: this.goToToday.bind(this),\n isCurrentMonth: this.isCurrentMonth.bind(this),\n selectDate: this.selectDate.bind(this),\n updateTasks: this.updateTasks.bind(this),\n };\n }\n\n /**\n * Navigate to next month\n */\n private next(): void {\n if (this.state.currentMonth === 11) {\n this.state.currentMonth = 0;\n this.state.currentYear++;\n } else {\n this.state.currentMonth++;\n }\n\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Navigate to previous month\n */\n private previous(): void {\n if (this.state.currentMonth === 0) {\n this.state.currentMonth = 11;\n this.state.currentYear--;\n } else {\n this.state.currentMonth--;\n }\n\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Jump to specific month and year\n */\n private jump(year: number, month: number): void {\n this.state.currentYear = year;\n this.state.currentMonth = month;\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Navigate to current month (today)\n */\n private goToToday(): void {\n const today = new Date();\n this.state.currentYear = today.getFullYear();\n this.state.currentMonth = today.getMonth();\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Check if currently viewing today's month\n */\n private isCurrentMonth(): boolean {\n const today = new Date();\n return (\n this.state.currentYear === today.getFullYear() &&\n this.state.currentMonth === today.getMonth()\n );\n }\n\n /**\n * Select a specific date\n */\n private selectDate(date: Date, dayIndex?: number): void {\n this.state.selectedDate = date;\n this.state.selectedDayIndex = dayIndex ?? null;\n this.state.currentDate = date.getDate();\n this.state.currentMonth = date.getMonth();\n this.state.currentYear = date.getFullYear();\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Update tasks for the currently selected date\n */\n private updateTasks(): void {\n if (!this.state.selectedDate) {\n this.state.tasks = [];\n return;\n }\n\n this.state.tasks = getEventsForDate(\n this.config.events,\n this.state.selectedDate\n );\n }\n\n /**\n * Update events configuration\n */\n updateEvents(events: CalendarEvent[]): void {\n this.config.events = events;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Handle date cell click\n */\n handleDateClick(date: Date, dayIndex?: number): void {\n this.selectDate(date, dayIndex);\n }\n\n /**\n * Check if date has events\n */\n hasEventsForDate(date: Date): boolean {\n return getEventsForDate(this.config.events, date).length > 0;\n }\n\n /**\n * Get events for a specific date\n */\n getEventsForDate(date: Date): CalendarEvent[] {\n return getEventsForDate(this.config.events, date);\n }\n\n /**\n * Clear selected date\n */\n clearSelection(): void {\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.state.tasks = [];\n this.notify();\n }\n\n /**\n * Get category color (with custom colors support)\n */\n getCategoryColor(category?: string): string {\n if (!category) return '#fc8917';\n return getCategoryColor(category, this.categoryColors);\n }\n\n /**\n * Update category colors dynamically\n */\n updateCategoryColors(colors: CategoryColorMap): void {\n this.categoryColors = mergeCategoryColors(colors);\n this.notify();\n }\n\n /**\n * Get all category colors\n */\n getCategoryColors(): CategoryColorMap {\n return { ...this.categoryColors };\n }\n\n /**\n * Register a new category with color\n */\n registerCategory(name: string, color: string): void {\n this.categoryColors[name] = color;\n this.notify();\n }\n\n /**\n * Destroy the engine and cleanup listeners\n */\n destroy(): void {\n this.listeners.clear();\n }\n}\n","export * from './types';\nexport * from './utils';\nexport { CalendarEngine } from './calendar-engine';\n\n// Re-export commonly used utilities\nexport {\n MONTHS,\n MONTHS_FULL,\n DAYS,\n normalizeDate,\n isSameDay,\n isToday,\n generateYears,\n getEventsForDate,\n hasEvents,\n generateCalendarDates,\n getPopupPositionClass,\n getCellClasses,\n formatDateForDisplay,\n getMonthYearText,\n} from './utils';\n","import {\n CalendarEngine,\n getCellClasses,\n formatTimeRange,\n formatAttendees,\n MONTHS_FULL,\n MONTHS,\n} from '../core';\nimport type { CalendarEvent, CalendarTheme, CategoryColorMap } from '../core';\n\nconst isSameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\nexport class CalendarElement extends HTMLElement {\n static observedAttributes = [\n 'initial-date',\n 'min-year',\n 'max-year',\n 'week-starts-on',\n 'title',\n 'use-short-month-names',\n 'availability-mode',\n 'selectable',\n 'loading',\n ];\n\n private engine: CalendarEngine | null = null;\n private unsubscribe: (() => void) | null = null;\n private actions: ReturnType<CalendarEngine['getActions']> | null = null;\n private pickerOpen = false;\n private yearInput = '';\n private yearInputValid = true;\n private listenersAttached = false;\n\n private clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private delegatedClickHandler: ((e: MouseEvent) => void) | null = null;\n private delegatedInputHandler: ((e: Event) => void) | null = null;\n private delegatedBlurHandler: ((e: FocusEvent) => void) | null = null;\n private delegatedKeydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\n // Rich property backing fields\n private _events: CalendarEvent[] = [];\n private _theme: CalendarTheme | null = null;\n private _categoryColors: CategoryColorMap | null = null;\n private _renderEvent: ((e: CalendarEvent) => string) | null = null;\n private _renderNoEvents: (() => string) | null = null;\n\n // Selection state (availability mode — range)\n private _rangeStart: Date | null = null;\n private _rangeEnd: Date | null = null;\n private _timeRangeDate: Date | null = null;\n private _timeRangeStart: string | null = null;\n private _timeRangeEnd: string | null = null;\n private _timeRangeComplete = false;\n\n get events(): CalendarEvent[] {\n return this._events;\n }\n\n set events(val: CalendarEvent[]) {\n this._events = val;\n if (this.engine) {\n this.engine.updateEvents(val);\n }\n }\n\n set theme(val: CalendarTheme) {\n this._theme = val;\n this.applyTheme();\n }\n\n set categoryColors(val: CategoryColorMap) {\n this._categoryColors = val;\n if (this.engine) {\n this.engine.updateCategoryColors(val);\n }\n }\n\n set renderEvent(val: (e: CalendarEvent) => string) {\n this._renderEvent = val;\n if (this.engine) this.render();\n // ignored when availability-mode attribute is set\n }\n\n set renderNoEvents(val: () => string) {\n this._renderNoEvents = val;\n if (this.engine) this.render();\n // ignored when availability-mode attribute is set\n }\n\n get loading(): boolean {\n return this.hasAttribute('loading');\n }\n\n set loading(val: boolean) {\n if (val) this.setAttribute('loading', '');\n else this.removeAttribute('loading');\n }\n\n connectedCallback(): void {\n this.classList.add('kalendly-calendar');\n this.initEngine();\n this.render();\n }\n\n disconnectedCallback(): void {\n this.cleanup();\n this.classList.remove('kalendly-calendar');\n this.innerHTML = '';\n }\n\n attributeChangedCallback(\n name: string,\n oldVal: string | null,\n newVal: string | null\n ): void {\n if (oldVal === newVal) return;\n if (name === 'loading') {\n this.render();\n return;\n }\n if (name === 'selectable' && newVal === null) {\n this._rangeStart = null;\n this._rangeEnd = null;\n this._timeRangeDate = null;\n this._timeRangeStart = null;\n this._timeRangeEnd = null;\n this._timeRangeComplete = false;\n }\n this.reinit();\n }\n\n private get minYear(): number {\n const val = this.getAttribute('min-year');\n return val ? parseInt(val, 10) : new Date().getFullYear() - 30;\n }\n\n private get maxYear(): number {\n const val = this.getAttribute('max-year');\n return val ? parseInt(val, 10) : new Date().getFullYear() + 10;\n }\n\n private initEngine(): void {\n const initialDateAttr = this.getAttribute('initial-date');\n const initialDate = initialDateAttr ? new Date(initialDateAttr) : undefined;\n const weekStartsOnAttr = this.getAttribute('week-starts-on');\n const weekStartsOn: 0 | 1 = weekStartsOnAttr === '1' ? 1 : 0;\n\n this.engine = new CalendarEngine({\n events: this._events,\n initialDate,\n minYear: this.minYear,\n maxYear: this.maxYear,\n weekStartsOn,\n categoryColors: this._categoryColors ?? undefined,\n });\n\n this.actions = this.engine.getActions();\n this.applyTheme();\n\n this.unsubscribe = this.engine.subscribe(() => {\n this.render();\n });\n }\n\n private reinit(): void {\n if (!this.engine) return;\n this.cleanup();\n this.initEngine();\n this.render();\n }\n\n private cleanup(): void {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n\n if (this.delegatedClickHandler) {\n this.removeEventListener('click', this.delegatedClickHandler);\n this.delegatedClickHandler = null;\n }\n if (this.delegatedInputHandler) {\n this.removeEventListener('input', this.delegatedInputHandler);\n this.delegatedInputHandler = null;\n }\n if (this.delegatedBlurHandler) {\n this.removeEventListener('blur', this.delegatedBlurHandler, true);\n this.delegatedBlurHandler = null;\n }\n if (this.delegatedKeydownHandler) {\n this.removeEventListener('keydown', this.delegatedKeydownHandler);\n this.delegatedKeydownHandler = null;\n }\n if (this.clickOutsideHandler) {\n document.removeEventListener('click', this.clickOutsideHandler);\n this.clickOutsideHandler = null;\n }\n\n this.listenersAttached = false;\n\n if (this.engine) {\n this.engine.destroy();\n this.engine = null;\n }\n\n this.actions = null;\n }\n\n private applyTheme(): void {\n if (!this._theme) return;\n const root = document.documentElement;\n const t = this._theme;\n if (t.primary)\n root.style.setProperty('--calendar-primary-color', t.primary);\n if (t.secondary)\n root.style.setProperty('--calendar-secondary-color', t.secondary);\n if (t.tertiary)\n root.style.setProperty('--calendar-tertiary-color', t.tertiary);\n if (t.textColor)\n root.style.setProperty('--calendar-text-color', t.textColor);\n if (t.textLight)\n root.style.setProperty('--calendar-text-light', t.textLight);\n if (t.background)\n root.style.setProperty('--calendar-background', t.background);\n if (t.cellHover)\n root.style.setProperty('--calendar-cell-hover', t.cellHover);\n if (t.borderColor)\n root.style.setProperty('--calendar-border-color', t.borderColor);\n if (t.todayOutline)\n root.style.setProperty('--calendar-today-outline', t.todayOutline);\n if (t.selectedBg)\n root.style.setProperty('--calendar-selected-bg', t.selectedBg);\n if (t.eventIndicator)\n root.style.setProperty('--calendar-event-indicator', t.eventIndicator);\n }\n\n private render(): void {\n if (!this.engine) return;\n\n const viewModel = this.engine.getViewModel();\n const useShortMonths = this.hasAttribute('use-short-month-names');\n const title = this.getAttribute('title');\n const minYear = this.minYear;\n const maxYear = this.maxYear;\n const availabilityMode = this.getAttribute('availability-mode');\n const selectable = this.hasAttribute('selectable');\n const isLoading = this.loading;\n\n const today = new Date();\n const todayMonth = today.getMonth();\n const todayYear = today.getFullYear();\n const isCurrentMonth =\n viewModel.currentYear === todayYear &&\n viewModel.currentMonth === todayMonth;\n\n const showScrollHint = viewModel.tasks.length > 3;\n\n const defaultRenderEvent = (event: CalendarEvent) => {\n const timeRange = formatTimeRange(event);\n const attendeesList = formatAttendees(event.attendees);\n\n let borderColor = event.color || '#3b82f6';\n if (event.category) {\n borderColor = this.engine!.getCategoryColor(event.category);\n }\n\n const getCategoryLabel = (category?: string) => {\n const labels: Record<string, string> = {\n work: 'WORK',\n personal: 'PERSONAL',\n meeting: 'MEETING',\n deadline: 'DEADLINE',\n appointment: 'APPOINTMENT',\n other: 'OTHER',\n };\n return category ? labels[category] || category.toUpperCase() : '';\n };\n\n const getPriorityLabel = (priority?: string) => {\n const labels: Record<string, string> = {\n high: 'HIGH',\n medium: 'MEDIUM',\n low: 'LOW',\n };\n return priority ? labels[priority] || priority.toUpperCase() : '';\n };\n\n const getStatusLabel = (status?: string) => {\n const labels: Record<string, string> = {\n completed: 'COMPLETED',\n cancelled: 'CANCELLED',\n tentative: 'TENTATIVE',\n scheduled: 'SCHEDULED',\n };\n return status ? labels[status] || status.toUpperCase() : '';\n };\n\n return `\n <div class=\"event-card\" style=\"border-left-color: ${borderColor}\">\n <div class=\"event-header\">\n <div class=\"event-title\">${event.name}</div>\n <div class=\"event-badges\">\n ${event.category ? `<span class=\"badge category-${event.category}\">${getCategoryLabel(event.category)}</span>` : ''}\n ${event.priority ? `<span class=\"badge priority-${event.priority}\">${getPriorityLabel(event.priority)}</span>` : ''}\n ${event.status && event.status !== 'scheduled' ? `<span class=\"badge status-${event.status}\">${getStatusLabel(event.status)}</span>` : ''}\n </div>\n </div>\n\n ${\n timeRange\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Time:</span>\n <span class=\"event-time-value\">${timeRange}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.description\n ? `\n <div class=\"event-description\">${event.description}</div>\n `\n : ''\n }\n\n ${\n event.location\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Location:</span>\n <span class=\"event-time-value\">${event.location}</span>\n </div>\n `\n : ''\n }\n\n ${\n attendeesList\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Attendees:</span>\n <span class=\"event-time-value\">${attendeesList}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.organizer\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Organizer:</span>\n <span class=\"event-time-value\">${event.organizer}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.notes\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Notes:</span>\n <span class=\"event-time-value\">${event.notes}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.url\n ? `\n <div class=\"event-time\">\n <a href=\"${event.url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"event-link\">\n View Details →\n </a>\n </div>\n `\n : ''\n }\n\n ${\n event.tags && event.tags.length > 0\n ? `\n <div class=\"event-tags\">\n ${event.tags.map((tag: string) => `<span class=\"event-tag\">${tag}</span>`).join('')}\n </div>\n `\n : ''\n }\n </div>\n `;\n };\n\n const defaultRenderNoEvents = () =>\n '<div class=\"no-events-message\">No events scheduled for this day.</div>';\n\n const renderEvent = this._renderEvent || defaultRenderEvent;\n const renderNoEvents = this._renderNoEvents || defaultRenderNoEvents;\n\n const renderTimeGrid = (events: CalendarEvent[], date: Date): string => {\n const isHourBooked = (hour: number): boolean =>\n events.some(event => {\n if (!event.startTime || !event.endTime) return true;\n const [startH] = (event.startTime as string).split(':').map(Number);\n const [endH] = (event.endTime as string).split(':').map(Number);\n return hour >= startH && hour < endH;\n });\n\n const slots = Array.from({ length: 24 }, (_, hour) => {\n const startTime = `${String(hour).padStart(2, '0')}:00`;\n const endTime = `${String(hour + 1).padStart(2, '0')}:00`;\n const booked = isHourBooked(hour);\n\n const inTimeRange =\n !booked &&\n selectable &&\n this._timeRangeStart !== null &&\n this._timeRangeEnd !== null &&\n isSameDay(this._timeRangeDate!, date) &&\n startTime >= this._timeRangeStart &&\n endTime <= this._timeRangeEnd;\n\n const isRangeStart = inTimeRange && startTime === this._timeRangeStart;\n const isRangeEnd = inTimeRange && endTime === this._timeRangeEnd;\n const isInRange = inTimeRange && !isRangeStart && !isRangeEnd;\n\n const slotClasses = [\n 'time-grid__slot',\n booked ? 'time-grid__slot--booked' : 'time-grid__slot--free',\n isRangeStart ? 'time-grid__slot--range-start' : '',\n isRangeEnd ? 'time-grid__slot--range-end' : '',\n isInRange ? 'time-grid__slot--in-range' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n const slotAttrs =\n !booked && selectable\n ? `data-action=\"select-slot\" data-start-time=\"${startTime}\" data-end-time=\"${endTime}\" data-date=\"${date.toISOString()}\"`\n : '';\n\n return `\n <div class=\"${slotClasses}\" ${slotAttrs}>\n <span class=\"time-grid__label\">${startTime}</span>\n <span class=\"time-grid__status\">${booked ? 'Booked' : 'Available'}</span>\n </div>`;\n });\n\n return `<div class=\"time-grid\">${slots.join('')}</div>`;\n };\n\n const html = `\n ${\n title\n ? `\n <div class=\"page--title\">\n <h1>${title}</h1>\n </div>\n `\n : ''\n }\n\n <div class=\"calendar--content\">\n <div class=\"calendar--card\">\n <div class=\"calendar--nav-header\">\n <button type=\"button\" class=\"calendar--nav-arrow\" data-action=\"previous\" aria-label=\"Previous month\">\n &#8249;\n </button>\n\n <div class=\"calendar--picker-container\" data-picker-container>\n <button\n type=\"button\"\n class=\"calendar--picker-btn\"\n data-action=\"toggle-picker\"\n aria-expanded=\"${this.pickerOpen ? 'true' : 'false'}\"\n aria-haspopup=\"true\"\n >\n ${\n useShortMonths\n ? `${MONTHS[viewModel.currentMonth]} ${viewModel.currentYear}`\n : viewModel.monthAndYearText\n }\n <span class=\"calendar--picker-chevron\">&#9662;</span>\n </button>\n\n ${\n this.pickerOpen\n ? `\n <div class=\"calendar--picker-dropdown\">\n <div class=\"calendar--picker-year-row\">\n <button\n type=\"button\"\n class=\"calendar--picker-year-arrow\"\n data-action=\"year-prev\"\n ${viewModel.currentYear <= minYear ? 'disabled' : ''}\n aria-label=\"Previous year\"\n >&#8249;</button>\n <input\n type=\"text\"\n class=\"calendar--picker-year-input${!this.yearInputValid ? ' invalid' : ''}\"\n value=\"${this.yearInput || viewModel.currentYear}\"\n data-year-input\n aria-label=\"Year\"\n />\n <button\n type=\"button\"\n class=\"calendar--picker-year-arrow\"\n data-action=\"year-next\"\n ${viewModel.currentYear >= maxYear ? 'disabled' : ''}\n aria-label=\"Next year\"\n >&#8250;</button>\n </div>\n\n <div class=\"calendar--picker-months\">\n ${(useShortMonths ? MONTHS : MONTHS_FULL)\n .map((month, index) => {\n const isSelected = index === viewModel.currentMonth;\n const isCurrent =\n index === todayMonth &&\n viewModel.currentYear === todayYear;\n return `\n <button\n type=\"button\"\n class=\"calendar--picker-month${isSelected ? ' selected' : ''}${isCurrent ? ' current-month' : ''}\"\n data-action=\"select-month\"\n data-month=\"${index}\"\n >${month}</button>\n `;\n })\n .join('')}\n </div>\n </div>\n `\n : ''\n }\n </div>\n\n <button\n type=\"button\"\n class=\"calendar--today-btn\"\n data-action=\"today\"\n ${isCurrentMonth ? 'disabled' : ''}\n >Today</button>\n\n <button type=\"button\" class=\"calendar--nav-arrow\" data-action=\"next\" aria-label=\"Next month\">\n &#8250;\n </button>\n </div>\n\n <table class=\"calendar--table calendar--table--bordered\">\n <thead>\n <tr>\n ${viewModel.days.map(day => `<th>${day.slice(0, 3)}</th>`).join('')}\n </tr>\n </thead>\n <tbody data-calendar-body>\n ${\n isLoading\n ? Array.from(\n { length: 6 },\n () =>\n `<tr>${Array.from(\n { length: 7 },\n () =>\n `<td class=\"calendar--skeleton\" aria-hidden=\"true\"></td>`\n ).join('')}</tr>`\n ).join('')\n : viewModel.calendarDates\n .map(\n week => `\n <tr>\n ${week\n .map((calendarDate, dayIndex) => {\n const classes = getCellClasses(calendarDate);\n if (availabilityMode && calendarDate.isCurrentMonth) {\n classes.push(\n calendarDate.hasEvents\n ? 'availability--booked'\n : 'availability--free'\n );\n }\n if (\n availabilityMode === 'day' &&\n selectable &&\n calendarDate.isCurrentMonth\n ) {\n const d = calendarDate.date;\n if (\n this._rangeStart &&\n isSameDay(d, this._rangeStart)\n )\n classes.push('availability--range-start');\n if (this._rangeEnd && isSameDay(d, this._rangeEnd))\n classes.push('availability--range-end');\n if (this._rangeStart && this._rangeEnd) {\n if (d > this._rangeStart && d < this._rangeEnd)\n classes.push('availability--in-range');\n }\n }\n const dateString = calendarDate.date.toISOString();\n return `\n <td\n class=\"${classes.join(' ')}\"\n data-date=\"${dateString}\"\n data-day-index=\"${dayIndex}\"\n data-clickable=\"true\"\n >\n ${calendarDate.date.getDate()}\n </td>\n `;\n })\n .join('')}\n </tr>\n `\n )\n .join('')\n }\n </tbody>\n </table>\n\n ${\n !isLoading && availabilityMode !== 'day' && viewModel.selectedDate\n ? `\n <div class=\"date-popup ${viewModel.popupPositionClass}\">\n <div class=\"popup-header\">\n <h2>${viewModel.scheduleDay}</h2>\n <button type=\"button\" class=\"popup-close\" data-action=\"close-popup\" aria-label=\"Close\">✕</button>\n </div>\n\n ${\n showScrollHint\n ? `\n <div class=\"scroll-hint\">\n ↓ Scroll to see more events ↓\n </div>\n `\n : ''\n }\n\n <div class=\"events-container\">\n ${\n availabilityMode === 'time'\n ? renderTimeGrid(viewModel.tasks, viewModel.selectedDate!)\n : viewModel.tasks.length > 0\n ? viewModel.tasks\n .map(event => renderEvent(event))\n .join('')\n : renderNoEvents()\n }\n </div>\n </div>\n `\n : ''\n }\n </div>\n </div>\n `;\n\n this.innerHTML = html;\n this.attachEventListeners();\n }\n\n private attachEventListeners(): void {\n if (this.listenersAttached) return;\n this.listenersAttached = true;\n\n const minYear = this.minYear;\n const maxYear = this.maxYear;\n\n this.delegatedClickHandler = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n const cell = target.closest('td[data-clickable=\"true\"]') as HTMLElement;\n if (cell && cell.dataset.date) {\n e.stopPropagation();\n const date = new Date(cell.dataset.date);\n const dayIndex = parseInt(cell.dataset.dayIndex || '0');\n const availMode = this.getAttribute('availability-mode');\n const isSelectable = this.hasAttribute('selectable');\n\n if (availMode === 'day' && isSelectable) {\n const isBooked = cell.classList.contains('availability--booked');\n if (!isBooked) {\n let startDate: Date;\n let endDate: Date;\n if (this._rangeEnd !== null) {\n // State 2 (complete) → reset, start fresh\n this._rangeStart = date;\n this._rangeEnd = null;\n startDate = date;\n endDate = date;\n } else if (this._rangeStart === null) {\n // State 0 → first click\n this._rangeStart = date;\n startDate = date;\n endDate = date;\n } else {\n // State 1 → second click, complete the range if no booked day inside\n const [s, e] =\n this._rangeStart <= date\n ? [this._rangeStart, date]\n : [date, this._rangeStart];\n const cursor = new Date(s);\n cursor.setDate(cursor.getDate() + 1);\n let blocked = false;\n while (cursor < e) {\n if (this.engine!.getEventsForDate(cursor).length > 0) {\n blocked = true;\n break;\n }\n cursor.setDate(cursor.getDate() + 1);\n }\n if (blocked) {\n // Booked day inside range — reset, start fresh from this click\n this._rangeStart = date;\n this._rangeEnd = null;\n } else {\n this._rangeStart = s;\n this._rangeEnd = e;\n }\n startDate = this._rangeStart;\n endDate = this._rangeEnd ?? this._rangeStart;\n }\n this.dispatchEvent(\n new CustomEvent('cal-availability-select', {\n bubbles: true,\n composed: true,\n detail: { startDate, endDate },\n })\n );\n }\n }\n\n if (availMode === 'time') {\n // Reset time range when a new day is opened\n this._timeRangeDate = null;\n this._timeRangeStart = null;\n this._timeRangeEnd = null;\n this._timeRangeComplete = false;\n }\n\n this.engine!.handleDateClick(date, dayIndex);\n this.dispatchEvent(\n new CustomEvent('cal-date-select', {\n bubbles: true,\n composed: true,\n detail: { date, events: this.engine!.getEventsForDate(date) },\n })\n );\n return;\n }\n\n const actionEl = target.closest('[data-action]') as HTMLElement;\n if (!actionEl) return;\n\n const action = actionEl.dataset.action;\n e.stopPropagation();\n\n switch (action) {\n case 'previous': {\n const vm = this.engine!.getViewModel();\n const tMonth = vm.currentMonth === 0 ? 11 : vm.currentMonth - 1;\n const tYear =\n vm.currentMonth === 0 ? vm.currentYear - 1 : vm.currentYear;\n this.dispatchMonthChange(tYear, tMonth);\n this.actions!.previous();\n break;\n }\n\n case 'next': {\n const vm = this.engine!.getViewModel();\n const tMonth = vm.currentMonth === 11 ? 0 : vm.currentMonth + 1;\n const tYear =\n vm.currentMonth === 11 ? vm.currentYear + 1 : vm.currentYear;\n this.dispatchMonthChange(tYear, tMonth);\n this.actions!.next();\n break;\n }\n\n case 'today': {\n const t = new Date();\n this.dispatchMonthChange(t.getFullYear(), t.getMonth());\n this.actions!.goToToday();\n this.pickerOpen = false;\n break;\n }\n\n case 'toggle-picker':\n this.pickerOpen = !this.pickerOpen;\n if (this.pickerOpen) {\n this.yearInput = String(this.engine!.getViewModel().currentYear);\n this.yearInputValid = true;\n }\n this.render();\n break;\n\n case 'year-prev': {\n const vm = this.engine!.getViewModel();\n if (vm.currentYear > minYear) {\n const newYear = vm.currentYear - 1;\n this.yearInput = String(newYear);\n this.updatePickerYear(newYear);\n this.dispatchMonthChange(newYear, vm.currentMonth);\n this.actions!.jump(newYear, vm.currentMonth);\n }\n break;\n }\n\n case 'year-next': {\n const vm = this.engine!.getViewModel();\n if (vm.currentYear < maxYear) {\n const newYear = vm.currentYear + 1;\n this.yearInput = String(newYear);\n this.updatePickerYear(newYear);\n this.dispatchMonthChange(newYear, vm.currentMonth);\n this.actions!.jump(newYear, vm.currentMonth);\n }\n break;\n }\n\n case 'select-month': {\n const month = parseInt(actionEl.dataset.month || '0', 10);\n const year = this.engine!.getViewModel().currentYear;\n this.dispatchMonthChange(year, month);\n this.actions!.jump(year, month);\n this.pickerOpen = false;\n break;\n }\n\n case 'close-popup':\n this._timeRangeDate = null;\n this._timeRangeStart = null;\n this._timeRangeEnd = null;\n this._timeRangeComplete = false;\n this.engine!.clearSelection();\n break;\n\n case 'select-slot': {\n const slotStart = actionEl.dataset.startTime!;\n const slotEnd = actionEl.dataset.endTime!;\n const slotDate = new Date(actionEl.dataset.date!);\n if (this._timeRangeComplete) {\n // State 2 → reset, start fresh\n this._timeRangeDate = slotDate;\n this._timeRangeStart = slotStart;\n this._timeRangeEnd = slotEnd;\n this._timeRangeComplete = false;\n } else if (this._timeRangeStart === null) {\n // State 0 → first click\n this._timeRangeDate = slotDate;\n this._timeRangeStart = slotStart;\n this._timeRangeEnd = slotEnd;\n } else {\n // State 1 → second click, extend range\n const newStart =\n slotStart < this._timeRangeStart\n ? slotStart\n : this._timeRangeStart;\n const newEnd =\n slotEnd > this._timeRangeEnd! ? slotEnd : this._timeRangeEnd!;\n this._timeRangeStart = newStart;\n this._timeRangeEnd = newEnd;\n this._timeRangeComplete = true;\n }\n this.render();\n this.dispatchEvent(\n new CustomEvent('cal-availability-select', {\n bubbles: true,\n composed: true,\n detail: {\n date: this._timeRangeDate,\n startTime: this._timeRangeStart,\n endTime: this._timeRangeEnd,\n },\n })\n );\n break;\n }\n }\n };\n\n this.delegatedInputHandler = (e: Event) => {\n const target = e.target as HTMLInputElement;\n if (!target.matches('[data-year-input]')) return;\n\n const value = target.value;\n if (value === '' || /^\\d+$/.test(value)) {\n this.yearInput = value;\n const year = parseInt(value, 10);\n this.yearInputValid =\n value === '' || (year >= minYear && year <= maxYear);\n target.classList.toggle('invalid', !this.yearInputValid);\n }\n };\n\n this.delegatedBlurHandler = (e: FocusEvent) => {\n const target = e.target as HTMLInputElement;\n if (!target.matches('[data-year-input]')) return;\n\n const year = parseInt(this.yearInput, 10);\n const vm = this.engine!.getViewModel();\n if (isNaN(year) || year < minYear || year > maxYear) {\n this.yearInput = String(vm.currentYear);\n this.yearInputValid = true;\n target.value = this.yearInput;\n target.classList.remove('invalid');\n } else if (year !== vm.currentYear) {\n this.dispatchMonthChange(year, vm.currentMonth);\n this.actions!.jump(year, vm.currentMonth);\n }\n };\n\n this.delegatedKeydownHandler = (e: KeyboardEvent) => {\n const target = e.target as HTMLInputElement;\n if (!target.matches('[data-year-input]')) return;\n if (e.key === 'Enter') target.blur();\n };\n\n this.addEventListener('click', this.delegatedClickHandler);\n this.addEventListener('input', this.delegatedInputHandler);\n this.addEventListener('blur', this.delegatedBlurHandler, true);\n this.addEventListener('keydown', this.delegatedKeydownHandler);\n\n this.clickOutsideHandler = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (this.contains(target)) return;\n\n if (this.pickerOpen) {\n this.pickerOpen = false;\n this.render();\n return;\n }\n\n const popup = this.querySelector('.date-popup');\n if (popup) {\n this.engine!.clearSelection();\n }\n };\n\n document.addEventListener('click', this.clickOutsideHandler);\n }\n\n private updatePickerYear(year: number): void {\n const input = this.querySelector('[data-year-input]') as HTMLInputElement;\n if (input) input.value = String(year);\n\n const prevBtn = this.querySelector(\n '[data-action=\"year-prev\"]'\n ) as HTMLButtonElement;\n const nextBtn = this.querySelector(\n '[data-action=\"year-next\"]'\n ) as HTMLButtonElement;\n if (prevBtn) prevBtn.disabled = year <= this.minYear;\n if (nextBtn) nextBtn.disabled = year >= this.maxYear;\n }\n\n private dispatchMonthChange(year?: number, month?: number): void {\n if (!this.engine) return;\n const vm = this.engine.getViewModel();\n this.dispatchEvent(\n new CustomEvent('cal-month-change', {\n bubbles: true,\n composed: true,\n detail: {\n year: year ?? vm.currentYear,\n month: month ?? vm.currentMonth,\n },\n })\n );\n }\n\n // Public API\n updateEvents(events: CalendarEvent[]): void {\n this.events = events;\n }\n\n updateTheme(theme: CalendarTheme): void {\n this.theme = theme;\n }\n\n getCurrentDate(): Date | null {\n return this.engine?.getViewModel().selectedDate ?? null;\n }\n\n goToDate(date: Date): void {\n const year = date.getFullYear();\n const month = date.getMonth();\n this.dispatchMonthChange(year, month);\n this.actions?.jump(year, month);\n }\n\n getEngine(): CalendarEngine {\n if (!this.engine)\n throw new Error('CalendarElement is not connected to the DOM');\n return this.engine;\n }\n}\n\nexport function defineCalendarElement(tagName = 'kal-calendar'): void {\n if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {\n customElements.define(tagName, CalendarElement);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kal-calendar': CalendarElement;\n }\n}\n","export { CalendarElement, defineCalendarElement } from './CalendarElement';\nexport type { CalendarElementProps, CalendarElementInstance } from './types';\nexport * from '../core';\n\n// Auto-register the custom element (guarded — safe to import multiple times)\nif (\n typeof customElements !== 'undefined' &&\n !customElements.get('kal-calendar')\n) {\n // Dynamic import keeps this out of the synchronous module evaluation path,\n // which prevents crashes in SSR environments where customElements is undefined\n // but window/document may not be fully available.\n import('./CalendarElement.js').then(({ CalendarElement }) => {\n if (!customElements.get('kal-calendar')) {\n customElements.define('kal-calendar', CalendarElement);\n }\n });\n}\n"],"mappings":"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","names":["isSameDay","e","CalendarElement"]}
1
+ {"version":3,"sources":["../src/core/types.ts","../src/core/utils.ts","../src/core/calendar-engine.ts","../src/core/index.ts","../src/web-components/CalendarElement.ts","../src/web-components/index.ts"],"sourcesContent":["export interface CalendarEvent {\n id: string | number;\n name: string;\n date: string | Date;\n\n // Time fields\n startTime?: string;\n endTime?: string;\n allDay?: boolean;\n\n // Display & categorization\n description?: string;\n color?: string;\n category?:\n | 'work'\n | 'personal'\n | 'meeting'\n | 'deadline'\n | 'appointment'\n | 'other';\n location?: string;\n url?: string;\n\n // Status & priority\n status?: 'scheduled' | 'completed' | 'cancelled' | 'tentative';\n priority?: 'low' | 'medium' | 'high';\n\n // Collaboration\n attendees?: string[];\n organizer?: string;\n\n // Reminders & recurrence\n reminders?: number[];\n recurring?: {\n frequency: 'daily' | 'weekly' | 'monthly' | 'yearly';\n interval?: number;\n endDate?: string | Date;\n daysOfWeek?: number[];\n };\n\n // Metadata\n notes?: string;\n tags?: string[];\n createdAt?: string | Date;\n updatedAt?: string | Date;\n\n // Flexibility for custom fields\n [key: string]: unknown;\n}\n\nexport interface CalendarDate {\n date: Date;\n isCurrentMonth: boolean;\n isToday: boolean;\n hasEvents: boolean;\n events: CalendarEvent[];\n}\n\nexport interface CalendarState {\n currentYear: number;\n currentMonth: number;\n currentDate: number;\n selectedDate: Date | null;\n selectedDayIndex: number | null;\n tasks: CalendarEvent[];\n}\n\nexport interface CategoryColorMap {\n [category: string]: string;\n}\n\nexport interface CalendarConfig {\n events: CalendarEvent[];\n initialDate?: Date;\n minYear?: number;\n maxYear?: number;\n weekStartsOn?: 0 | 1;\n categoryColors?: CategoryColorMap;\n}\n\nexport interface CalendarActions {\n next: () => void;\n previous: () => void;\n jump: (year: number, month: number) => void;\n goToToday: () => void;\n isCurrentMonth: () => boolean;\n selectDate: (date: Date) => void;\n updateTasks: () => void;\n}\n\nexport interface PopupPosition {\n class:\n | 'popup-left'\n | 'popup-right'\n | 'popup-center-top'\n | 'popup-center-bottom';\n style?: Record<string, string | number>;\n}\n\nexport interface CalendarViewModel extends CalendarState {\n months: string[];\n days: string[];\n years: number[];\n monthAndYearText: string;\n scheduleDay: string;\n calendarDates: CalendarDate[][];\n popupPositionClass: string;\n}\n\nexport type CalendarEventHandler = (event: CalendarEvent) => void;\n\nexport interface CalendarProps {\n events: CalendarEvent[];\n initialDate?: Date;\n minYear?: number;\n maxYear?: number;\n weekStartsOn?: 0 | 1;\n useShortMonthNames?: boolean;\n onDateSelect?: (date: Date) => void;\n onEventClick?: CalendarEventHandler;\n onMonthChange?: (year: number, month: number) => void;\n}\n\nexport interface CalendarTheme {\n primary?: string;\n secondary?: string;\n tertiary?: string;\n textColor?: string;\n textLight?: string;\n background?: string;\n cellHover?: string;\n borderColor?: string;\n todayOutline?: string;\n selectedBg?: string;\n headerBg?: string;\n popupBg?: string;\n eventIndicator?: string;\n}\n","import { CalendarEvent, CalendarDate, CategoryColorMap } from './types';\n\nexport const MONTHS = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec',\n];\n\nexport const MONTHS_FULL = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n];\n\nexport const DAYS = [\n 'Sunday',\n 'Monday',\n 'Tuesday',\n 'Wednesday',\n 'Thursday',\n 'Friday',\n 'Saturday',\n];\n\nexport function normalizeDate(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);\n}\n\nexport function isSameDay(date1: Date, date2: Date): boolean {\n return normalizeDate(date1).getTime() === normalizeDate(date2).getTime();\n}\n\nexport function isToday(date: Date): boolean {\n return isSameDay(date, new Date());\n}\n\nexport function generateYears(minYear?: number, maxYear?: number): number[] {\n const currentYear = new Date().getFullYear();\n const min = minYear ?? currentYear - 30;\n const max = maxYear ?? currentYear + 10;\n\n return Array.from({ length: max - min + 1 }, (_, i) => min + i);\n}\n\nexport function getEventsForDate(\n events: CalendarEvent[],\n date: Date\n): CalendarEvent[] {\n const normalizedTargetDate = normalizeDate(date);\n\n return events.filter(event => {\n const eventDate = normalizeDate(new Date(event.date));\n return eventDate.getTime() === normalizedTargetDate.getTime();\n });\n}\n\nexport function hasEvents(events: CalendarEvent[], date: Date): boolean {\n return getEventsForDate(events, date).length > 0;\n}\n\nexport function generateCalendarDates(\n year: number,\n month: number,\n events: CalendarEvent[] = [],\n weekStartsOn: 0 | 1 = 0\n): CalendarDate[][] {\n const firstDay = new Date(year, month, 1);\n const lastDay = new Date(year, month + 1, 0);\n const daysInMonth = lastDay.getDate();\n const prevMonthLastDay = new Date(year, month, 0).getDate();\n\n let firstDayOfWeek = firstDay.getDay();\n if (weekStartsOn === 1) {\n firstDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1;\n }\n\n const dates: CalendarDate[][] = [];\n let day = 1;\n let nextMonthDay = 1;\n\n for (let week = 0; week < 6; week++) {\n const weekDates: CalendarDate[] = [];\n\n for (let dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) {\n if (week === 0 && dayOfWeek < firstDayOfWeek) {\n // Previous month days\n const prevDay = prevMonthLastDay - firstDayOfWeek + dayOfWeek + 1;\n const prevDate = new Date(year, month - 1, prevDay);\n const dateEvents = getEventsForDate(events, prevDate);\n weekDates.push({\n date: prevDate,\n isCurrentMonth: false,\n isToday: isToday(prevDate),\n hasEvents: dateEvents.length > 0,\n events: dateEvents,\n });\n } else if (day > daysInMonth) {\n // Next month days\n const nextDate = new Date(year, month + 1, nextMonthDay);\n const dateEvents = getEventsForDate(events, nextDate);\n weekDates.push({\n date: nextDate,\n isCurrentMonth: false,\n isToday: isToday(nextDate),\n hasEvents: dateEvents.length > 0,\n events: dateEvents,\n });\n nextMonthDay++;\n } else {\n // Current month days\n const currentDate = new Date(year, month, day);\n const dateEvents = getEventsForDate(events, currentDate);\n weekDates.push({\n date: currentDate,\n isCurrentMonth: true,\n isToday: isToday(currentDate),\n hasEvents: dateEvents.length > 0,\n events: dateEvents,\n });\n day++;\n }\n }\n\n dates.push(weekDates);\n }\n\n return dates;\n}\n\nexport function getPopupPositionClass(selectedDayIndex: number | null): string {\n if (selectedDayIndex === null) return 'popup-center-bottom';\n\n if (selectedDayIndex < 3) {\n return 'popup-right';\n } else if (selectedDayIndex > 4) {\n return 'popup-left';\n } else {\n return 'popup-center-bottom';\n }\n}\n\nexport function getCellClasses(calendarDate: CalendarDate): string[] {\n const classes: string[] = [];\n\n if (!calendarDate.isCurrentMonth) {\n classes.push('other-month');\n }\n\n if (calendarDate.isToday) {\n classes.push('schedule--current--exam');\n }\n\n if (calendarDate.hasEvents) {\n classes.push('has--event');\n }\n\n return classes;\n}\n\nexport function formatDateForDisplay(date: Date): string {\n return `${DAYS[date.getDay()]} ${date.getDate()}`;\n}\n\nexport function getMonthYearText(year: number, month: number): string {\n return `${MONTHS_FULL[month]} ${year}`;\n}\n\nexport function formatTimeRange(event: CalendarEvent): string {\n if (event.allDay || (!event.startTime && !event.endTime)) {\n return 'All day';\n }\n\n if (event.startTime && event.endTime) {\n return `${event.startTime} - ${event.endTime}`;\n }\n\n if (event.startTime) {\n return `${event.startTime}`;\n }\n\n return '';\n}\n\nexport function formatAttendees(attendees?: string[]): string {\n if (!attendees || attendees.length === 0) return '';\n\n if (attendees.length === 1) return attendees[0];\n if (attendees.length === 2) return attendees.join(' and ');\n\n return `${attendees.slice(0, -1).join(', ')}, and ${attendees[attendees.length - 1]}`;\n}\n\nexport function sortEventsByTime(events: CalendarEvent[]): CalendarEvent[] {\n return [...events].sort((a, b) => {\n const aAllDay = a.allDay || (!a.startTime && !a.endTime);\n const bAllDay = b.allDay || (!b.startTime && !b.endTime);\n\n if (aAllDay && !bAllDay) return -1;\n if (!aAllDay && bAllDay) return 1;\n\n if (!a.startTime || !b.startTime) return 0;\n return a.startTime.localeCompare(b.startTime);\n });\n}\n\nexport const DEFAULT_CATEGORY_COLORS: CategoryColorMap = {\n work: '#3b82f6',\n personal: '#8b5cf6',\n meeting: '#10b981',\n deadline: '#ef4444',\n appointment: '#f59e0b',\n other: '#6b7280',\n};\n\n// Dynamic function that accepts custom colors\nexport function getDefaultEventColor(\n category?: string,\n customColors?: CategoryColorMap\n): string {\n const colorMap = customColors || DEFAULT_CATEGORY_COLORS;\n\n if (category && colorMap[category]) {\n return colorMap[category];\n }\n\n // Default fallback color\n return '#fc8917';\n}\n\n// Helper to merge custom colors with defaults\nexport function mergeCategoryColors(\n customColors?: CategoryColorMap\n): CategoryColorMap {\n return {\n ...DEFAULT_CATEGORY_COLORS,\n ...customColors,\n };\n}\n\n// Validate if a color is a valid hex color\nexport function isValidHexColor(color: string): boolean {\n return /^#([0-9A-F]{3}){1,2}$/i.test(color);\n}\n\n// Get color for a category with validation\nexport function getCategoryColor(\n category: string,\n customColors?: CategoryColorMap\n): string {\n const colorMap = mergeCategoryColors(customColors);\n const color = colorMap[category] || colorMap.other || '#fc8917';\n\n return isValidHexColor(color) ? color : '#fc8917';\n}\n","import {\n CalendarEvent,\n CalendarState,\n CalendarConfig,\n CalendarActions,\n CalendarViewModel,\n CategoryColorMap,\n} from './types';\nimport {\n generateCalendarDates,\n getEventsForDate,\n generateYears,\n getPopupPositionClass,\n getMonthYearText,\n formatDateForDisplay,\n mergeCategoryColors,\n getCategoryColor,\n MONTHS,\n DAYS,\n} from './utils';\n\nexport class CalendarEngine {\n private state: CalendarState;\n private config: CalendarConfig;\n private listeners: Set<() => void> = new Set();\n private categoryColors: CategoryColorMap;\n\n constructor(config: CalendarConfig) {\n this.config = config;\n this.categoryColors = mergeCategoryColors(config.categoryColors);\n\n const initialDate = config.initialDate || new Date();\n this.state = {\n currentYear: initialDate.getFullYear(),\n currentMonth: initialDate.getMonth(),\n currentDate: initialDate.getDate(),\n selectedDate: null,\n selectedDayIndex: null,\n tasks: [],\n };\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Notify all listeners of state changes\n */\n private notify(): void {\n this.listeners.forEach(listener => listener());\n }\n\n /**\n * Get current state\n */\n getState(): CalendarState {\n return { ...this.state };\n }\n\n /**\n * Get view model with computed properties\n */\n getViewModel(): CalendarViewModel {\n const calendarDates = generateCalendarDates(\n this.state.currentYear,\n this.state.currentMonth,\n this.config.events,\n this.config.weekStartsOn\n );\n\n return {\n ...this.state,\n months: MONTHS,\n days: DAYS,\n years: generateYears(this.config.minYear, this.config.maxYear),\n monthAndYearText: getMonthYearText(\n this.state.currentYear,\n this.state.currentMonth\n ),\n scheduleDay: this.state.selectedDate\n ? formatDateForDisplay(this.state.selectedDate)\n : '',\n calendarDates,\n popupPositionClass: getPopupPositionClass(this.state.selectedDayIndex),\n };\n }\n\n /**\n * Get actions object\n */\n getActions(): CalendarActions {\n return {\n next: this.next.bind(this),\n previous: this.previous.bind(this),\n jump: this.jump.bind(this),\n goToToday: this.goToToday.bind(this),\n isCurrentMonth: this.isCurrentMonth.bind(this),\n selectDate: this.selectDate.bind(this),\n updateTasks: this.updateTasks.bind(this),\n };\n }\n\n /**\n * Navigate to next month\n */\n private next(): void {\n if (this.state.currentMonth === 11) {\n this.state.currentMonth = 0;\n this.state.currentYear++;\n } else {\n this.state.currentMonth++;\n }\n\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Navigate to previous month\n */\n private previous(): void {\n if (this.state.currentMonth === 0) {\n this.state.currentMonth = 11;\n this.state.currentYear--;\n } else {\n this.state.currentMonth--;\n }\n\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Jump to specific month and year\n */\n private jump(year: number, month: number): void {\n this.state.currentYear = year;\n this.state.currentMonth = month;\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Navigate to current month (today)\n */\n private goToToday(): void {\n const today = new Date();\n this.state.currentYear = today.getFullYear();\n this.state.currentMonth = today.getMonth();\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Check if currently viewing today's month\n */\n private isCurrentMonth(): boolean {\n const today = new Date();\n return (\n this.state.currentYear === today.getFullYear() &&\n this.state.currentMonth === today.getMonth()\n );\n }\n\n /**\n * Select a specific date\n */\n private selectDate(date: Date, dayIndex?: number): void {\n this.state.selectedDate = date;\n this.state.selectedDayIndex = dayIndex ?? null;\n this.state.currentDate = date.getDate();\n this.state.currentMonth = date.getMonth();\n this.state.currentYear = date.getFullYear();\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Update tasks for the currently selected date\n */\n private updateTasks(): void {\n if (!this.state.selectedDate) {\n this.state.tasks = [];\n return;\n }\n\n this.state.tasks = getEventsForDate(\n this.config.events,\n this.state.selectedDate\n );\n }\n\n /**\n * Update events configuration\n */\n updateEvents(events: CalendarEvent[]): void {\n this.config.events = events;\n this.updateTasks();\n this.notify();\n }\n\n /**\n * Handle date cell click\n */\n handleDateClick(date: Date, dayIndex?: number): void {\n this.selectDate(date, dayIndex);\n }\n\n /**\n * Check if date has events\n */\n hasEventsForDate(date: Date): boolean {\n return getEventsForDate(this.config.events, date).length > 0;\n }\n\n /**\n * Get events for a specific date\n */\n getEventsForDate(date: Date): CalendarEvent[] {\n return getEventsForDate(this.config.events, date);\n }\n\n /**\n * Clear selected date\n */\n clearSelection(): void {\n this.state.selectedDate = null;\n this.state.selectedDayIndex = null;\n this.state.tasks = [];\n this.notify();\n }\n\n /**\n * Get category color (with custom colors support)\n */\n getCategoryColor(category?: string): string {\n if (!category) return '#fc8917';\n return getCategoryColor(category, this.categoryColors);\n }\n\n /**\n * Update category colors dynamically\n */\n updateCategoryColors(colors: CategoryColorMap): void {\n this.categoryColors = mergeCategoryColors(colors);\n this.notify();\n }\n\n /**\n * Get all category colors\n */\n getCategoryColors(): CategoryColorMap {\n return { ...this.categoryColors };\n }\n\n /**\n * Register a new category with color\n */\n registerCategory(name: string, color: string): void {\n this.categoryColors[name] = color;\n this.notify();\n }\n\n /**\n * Destroy the engine and cleanup listeners\n */\n destroy(): void {\n this.listeners.clear();\n }\n}\n","export * from './types';\nexport * from './utils';\nexport { CalendarEngine } from './calendar-engine';\n\n// Re-export commonly used utilities\nexport {\n MONTHS,\n MONTHS_FULL,\n DAYS,\n normalizeDate,\n isSameDay,\n isToday,\n generateYears,\n getEventsForDate,\n hasEvents,\n generateCalendarDates,\n getPopupPositionClass,\n getCellClasses,\n formatDateForDisplay,\n getMonthYearText,\n} from './utils';\n","import {\n CalendarEngine,\n getCellClasses,\n formatTimeRange,\n formatAttendees,\n MONTHS_FULL,\n MONTHS,\n} from '../core';\nimport type { CalendarEvent, CalendarTheme, CategoryColorMap } from '../core';\n\nconst isSameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\nexport class CalendarElement extends HTMLElement {\n static observedAttributes = [\n 'initial-date',\n 'min-year',\n 'max-year',\n 'week-starts-on',\n 'title',\n 'use-short-month-names',\n 'availability-mode',\n 'selectable',\n 'loading',\n ];\n\n private engine: CalendarEngine | null = null;\n private unsubscribe: (() => void) | null = null;\n private actions: ReturnType<CalendarEngine['getActions']> | null = null;\n private pickerOpen = false;\n private yearInput = '';\n private yearInputValid = true;\n private listenersAttached = false;\n\n private clickOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private delegatedClickHandler: ((e: MouseEvent) => void) | null = null;\n private delegatedInputHandler: ((e: Event) => void) | null = null;\n private delegatedBlurHandler: ((e: FocusEvent) => void) | null = null;\n private delegatedKeydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\n // Rich property backing fields\n private _events: CalendarEvent[] = [];\n private _theme: CalendarTheme | null = null;\n private _categoryColors: CategoryColorMap | null = null;\n private _renderEvent: ((e: CalendarEvent) => string) | null = null;\n private _renderNoEvents: (() => string) | null = null;\n\n // Selection state (availability mode — range)\n private _rangeStart: Date | null = null;\n private _rangeEnd: Date | null = null;\n private _timeRangeDate: Date | null = null;\n private _timeRangeStart: string | null = null;\n private _timeRangeEnd: string | null = null;\n private _timeRangeComplete = false;\n\n get events(): CalendarEvent[] {\n return this._events;\n }\n\n set events(val: CalendarEvent[]) {\n this._events = val;\n if (this.engine) {\n this.engine.updateEvents(val);\n }\n }\n\n set theme(val: CalendarTheme) {\n this._theme = val;\n this.applyTheme();\n }\n\n set categoryColors(val: CategoryColorMap) {\n this._categoryColors = val;\n if (this.engine) {\n this.engine.updateCategoryColors(val);\n }\n }\n\n set renderEvent(val: (e: CalendarEvent) => string) {\n this._renderEvent = val;\n if (this.engine) this.render();\n // ignored when availability-mode attribute is set\n }\n\n set renderNoEvents(val: () => string) {\n this._renderNoEvents = val;\n if (this.engine) this.render();\n // ignored when availability-mode attribute is set\n }\n\n get loading(): boolean {\n return this.hasAttribute('loading');\n }\n\n set loading(val: boolean) {\n if (val) this.setAttribute('loading', '');\n else this.removeAttribute('loading');\n }\n\n connectedCallback(): void {\n this.classList.add('kalendly-calendar');\n this.initEngine();\n this.render();\n }\n\n disconnectedCallback(): void {\n this.cleanup();\n this.classList.remove('kalendly-calendar');\n this.innerHTML = '';\n }\n\n attributeChangedCallback(\n name: string,\n oldVal: string | null,\n newVal: string | null\n ): void {\n if (oldVal === newVal) return;\n if (name === 'loading') {\n this.render();\n return;\n }\n if (name === 'selectable' && newVal === null) {\n this._rangeStart = null;\n this._rangeEnd = null;\n this._timeRangeDate = null;\n this._timeRangeStart = null;\n this._timeRangeEnd = null;\n this._timeRangeComplete = false;\n }\n this.reinit();\n }\n\n private get minYear(): number {\n const val = this.getAttribute('min-year');\n return val ? parseInt(val, 10) : new Date().getFullYear() - 30;\n }\n\n private get maxYear(): number {\n const val = this.getAttribute('max-year');\n return val ? parseInt(val, 10) : new Date().getFullYear() + 10;\n }\n\n private initEngine(): void {\n const initialDateAttr = this.getAttribute('initial-date');\n const initialDate = initialDateAttr ? new Date(initialDateAttr) : undefined;\n const weekStartsOnAttr = this.getAttribute('week-starts-on');\n const weekStartsOn: 0 | 1 = weekStartsOnAttr === '1' ? 1 : 0;\n\n this.engine = new CalendarEngine({\n events: this._events,\n initialDate,\n minYear: this.minYear,\n maxYear: this.maxYear,\n weekStartsOn,\n categoryColors: this._categoryColors ?? undefined,\n });\n\n this.actions = this.engine.getActions();\n this.applyTheme();\n\n this.unsubscribe = this.engine.subscribe(() => {\n this.render();\n });\n }\n\n private reinit(): void {\n if (!this.engine) return;\n this.cleanup();\n this.initEngine();\n this.render();\n }\n\n private cleanup(): void {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n\n if (this.delegatedClickHandler) {\n this.removeEventListener('click', this.delegatedClickHandler);\n this.delegatedClickHandler = null;\n }\n if (this.delegatedInputHandler) {\n this.removeEventListener('input', this.delegatedInputHandler);\n this.delegatedInputHandler = null;\n }\n if (this.delegatedBlurHandler) {\n this.removeEventListener('blur', this.delegatedBlurHandler, true);\n this.delegatedBlurHandler = null;\n }\n if (this.delegatedKeydownHandler) {\n this.removeEventListener('keydown', this.delegatedKeydownHandler);\n this.delegatedKeydownHandler = null;\n }\n if (this.clickOutsideHandler) {\n document.removeEventListener('click', this.clickOutsideHandler);\n this.clickOutsideHandler = null;\n }\n\n this.listenersAttached = false;\n\n if (this.engine) {\n this.engine.destroy();\n this.engine = null;\n }\n\n this.actions = null;\n }\n\n private applyTheme(): void {\n if (!this._theme) return;\n const root = document.documentElement;\n const t = this._theme;\n if (t.primary)\n root.style.setProperty('--calendar-primary-color', t.primary);\n if (t.secondary)\n root.style.setProperty('--calendar-secondary-color', t.secondary);\n if (t.tertiary)\n root.style.setProperty('--calendar-tertiary-color', t.tertiary);\n if (t.textColor)\n root.style.setProperty('--calendar-text-color', t.textColor);\n if (t.textLight)\n root.style.setProperty('--calendar-text-light', t.textLight);\n if (t.background)\n root.style.setProperty('--calendar-background', t.background);\n if (t.cellHover)\n root.style.setProperty('--calendar-cell-hover', t.cellHover);\n if (t.borderColor)\n root.style.setProperty('--calendar-border-color', t.borderColor);\n if (t.todayOutline)\n root.style.setProperty('--calendar-today-outline', t.todayOutline);\n if (t.selectedBg)\n root.style.setProperty('--calendar-selected-bg', t.selectedBg);\n if (t.headerBg) root.style.setProperty('--calendar-header-bg', t.headerBg);\n if (t.popupBg) root.style.setProperty('--calendar-popup-bg', t.popupBg);\n if (t.eventIndicator)\n root.style.setProperty('--calendar-event-indicator', t.eventIndicator);\n }\n\n private render(): void {\n if (!this.engine) return;\n\n const viewModel = this.engine.getViewModel();\n const useShortMonths = this.hasAttribute('use-short-month-names');\n const title = this.getAttribute('title');\n const minYear = this.minYear;\n const maxYear = this.maxYear;\n const availabilityMode = this.getAttribute('availability-mode');\n const selectable = this.hasAttribute('selectable');\n const isLoading = this.loading;\n\n const today = new Date();\n const todayMonth = today.getMonth();\n const todayYear = today.getFullYear();\n const isCurrentMonth =\n viewModel.currentYear === todayYear &&\n viewModel.currentMonth === todayMonth;\n\n const showScrollHint = viewModel.tasks.length > 3;\n\n const defaultRenderEvent = (event: CalendarEvent) => {\n const timeRange = formatTimeRange(event);\n const attendeesList = formatAttendees(event.attendees);\n\n let borderColor = event.color || '#3b82f6';\n if (event.category) {\n borderColor = this.engine!.getCategoryColor(event.category);\n }\n\n const getCategoryLabel = (category?: string) => {\n const labels: Record<string, string> = {\n work: 'WORK',\n personal: 'PERSONAL',\n meeting: 'MEETING',\n deadline: 'DEADLINE',\n appointment: 'APPOINTMENT',\n other: 'OTHER',\n };\n return category ? labels[category] || category.toUpperCase() : '';\n };\n\n const getPriorityLabel = (priority?: string) => {\n const labels: Record<string, string> = {\n high: 'HIGH',\n medium: 'MEDIUM',\n low: 'LOW',\n };\n return priority ? labels[priority] || priority.toUpperCase() : '';\n };\n\n const getStatusLabel = (status?: string) => {\n const labels: Record<string, string> = {\n completed: 'COMPLETED',\n cancelled: 'CANCELLED',\n tentative: 'TENTATIVE',\n scheduled: 'SCHEDULED',\n };\n return status ? labels[status] || status.toUpperCase() : '';\n };\n\n return `\n <div class=\"event-card\" style=\"border-left-color: ${borderColor}\">\n <div class=\"event-header\">\n <div class=\"event-title\">${event.name}</div>\n <div class=\"event-badges\">\n ${event.category ? `<span class=\"badge category-${event.category}\">${getCategoryLabel(event.category)}</span>` : ''}\n ${event.priority ? `<span class=\"badge priority-${event.priority}\">${getPriorityLabel(event.priority)}</span>` : ''}\n ${event.status && event.status !== 'scheduled' ? `<span class=\"badge status-${event.status}\">${getStatusLabel(event.status)}</span>` : ''}\n </div>\n </div>\n\n ${\n timeRange\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Time:</span>\n <span class=\"event-time-value\">${timeRange}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.description\n ? `\n <div class=\"event-description\">${event.description}</div>\n `\n : ''\n }\n\n ${\n event.location\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Location:</span>\n <span class=\"event-time-value\">${event.location}</span>\n </div>\n `\n : ''\n }\n\n ${\n attendeesList\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Attendees:</span>\n <span class=\"event-time-value\">${attendeesList}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.organizer\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Organizer:</span>\n <span class=\"event-time-value\">${event.organizer}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.notes\n ? `\n <div class=\"event-time\">\n <span class=\"event-time-label\">Notes:</span>\n <span class=\"event-time-value\">${event.notes}</span>\n </div>\n `\n : ''\n }\n\n ${\n event.url\n ? `\n <div class=\"event-time\">\n <a href=\"${event.url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"event-link\">\n View Details →\n </a>\n </div>\n `\n : ''\n }\n\n ${\n event.tags && event.tags.length > 0\n ? `\n <div class=\"event-tags\">\n ${event.tags.map((tag: string) => `<span class=\"event-tag\">${tag}</span>`).join('')}\n </div>\n `\n : ''\n }\n </div>\n `;\n };\n\n const defaultRenderNoEvents = () =>\n '<div class=\"no-events-message\">No events scheduled for this day.</div>';\n\n const renderEvent = this._renderEvent || defaultRenderEvent;\n const renderNoEvents = this._renderNoEvents || defaultRenderNoEvents;\n\n const renderTimeGrid = (events: CalendarEvent[], date: Date): string => {\n const isHourBooked = (hour: number): boolean =>\n events.some(event => {\n if (!event.startTime || !event.endTime) return true;\n const [startH] = (event.startTime as string).split(':').map(Number);\n const [endH] = (event.endTime as string).split(':').map(Number);\n return hour >= startH && hour < endH;\n });\n\n const slots = Array.from({ length: 24 }, (_, hour) => {\n const startTime = `${String(hour).padStart(2, '0')}:00`;\n const endTime = `${String(hour + 1).padStart(2, '0')}:00`;\n const booked = isHourBooked(hour);\n\n const inTimeRange =\n !booked &&\n selectable &&\n this._timeRangeStart !== null &&\n this._timeRangeEnd !== null &&\n isSameDay(this._timeRangeDate!, date) &&\n startTime >= this._timeRangeStart &&\n endTime <= this._timeRangeEnd;\n\n const isRangeStart = inTimeRange && startTime === this._timeRangeStart;\n const isRangeEnd = inTimeRange && endTime === this._timeRangeEnd;\n const isInRange = inTimeRange && !isRangeStart && !isRangeEnd;\n\n const slotClasses = [\n 'time-grid__slot',\n booked ? 'time-grid__slot--booked' : 'time-grid__slot--free',\n isRangeStart ? 'time-grid__slot--range-start' : '',\n isRangeEnd ? 'time-grid__slot--range-end' : '',\n isInRange ? 'time-grid__slot--in-range' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n const slotAttrs =\n !booked && selectable\n ? `data-action=\"select-slot\" data-start-time=\"${startTime}\" data-end-time=\"${endTime}\" data-date=\"${date.toISOString()}\"`\n : '';\n\n return `\n <div class=\"${slotClasses}\" ${slotAttrs}>\n <span class=\"time-grid__label\">${startTime}</span>\n <span class=\"time-grid__status\">${booked ? 'Booked' : 'Available'}</span>\n </div>`;\n });\n\n return `<div class=\"time-grid\">${slots.join('')}</div>`;\n };\n\n const html = `\n ${\n title\n ? `\n <div class=\"page--title\">\n <h1>${title}</h1>\n </div>\n `\n : ''\n }\n\n <div class=\"calendar--content\">\n <div class=\"calendar--card\">\n <div class=\"calendar--nav-header\">\n <button type=\"button\" class=\"calendar--nav-arrow\" data-action=\"previous\" aria-label=\"Previous month\">\n &#8249;\n </button>\n\n <div class=\"calendar--picker-container\" data-picker-container>\n <button\n type=\"button\"\n class=\"calendar--picker-btn\"\n data-action=\"toggle-picker\"\n aria-expanded=\"${this.pickerOpen ? 'true' : 'false'}\"\n aria-haspopup=\"true\"\n >\n ${\n useShortMonths\n ? `${MONTHS[viewModel.currentMonth]} ${viewModel.currentYear}`\n : viewModel.monthAndYearText\n }\n <span class=\"calendar--picker-chevron\">&#9662;</span>\n </button>\n\n ${\n this.pickerOpen\n ? `\n <div class=\"calendar--picker-dropdown\">\n <div class=\"calendar--picker-year-row\">\n <button\n type=\"button\"\n class=\"calendar--picker-year-arrow\"\n data-action=\"year-prev\"\n ${viewModel.currentYear <= minYear ? 'disabled' : ''}\n aria-label=\"Previous year\"\n >&#8249;</button>\n <input\n type=\"text\"\n class=\"calendar--picker-year-input${!this.yearInputValid ? ' invalid' : ''}\"\n value=\"${this.yearInput || viewModel.currentYear}\"\n data-year-input\n aria-label=\"Year\"\n />\n <button\n type=\"button\"\n class=\"calendar--picker-year-arrow\"\n data-action=\"year-next\"\n ${viewModel.currentYear >= maxYear ? 'disabled' : ''}\n aria-label=\"Next year\"\n >&#8250;</button>\n </div>\n\n <div class=\"calendar--picker-months\">\n ${(useShortMonths ? MONTHS : MONTHS_FULL)\n .map((month, index) => {\n const isSelected = index === viewModel.currentMonth;\n const isCurrent =\n index === todayMonth &&\n viewModel.currentYear === todayYear;\n return `\n <button\n type=\"button\"\n class=\"calendar--picker-month${isSelected ? ' selected' : ''}${isCurrent ? ' current-month' : ''}\"\n data-action=\"select-month\"\n data-month=\"${index}\"\n >${month}</button>\n `;\n })\n .join('')}\n </div>\n </div>\n `\n : ''\n }\n </div>\n\n <button\n type=\"button\"\n class=\"calendar--today-btn\"\n data-action=\"today\"\n ${isCurrentMonth ? 'disabled' : ''}\n >Today</button>\n\n <button type=\"button\" class=\"calendar--nav-arrow\" data-action=\"next\" aria-label=\"Next month\">\n &#8250;\n </button>\n </div>\n\n <table class=\"calendar--table calendar--table--bordered\">\n <thead>\n <tr>\n ${viewModel.days.map(day => `<th>${day.slice(0, 3)}</th>`).join('')}\n </tr>\n </thead>\n <tbody data-calendar-body>\n ${\n isLoading\n ? Array.from(\n { length: 6 },\n () =>\n `<tr>${Array.from(\n { length: 7 },\n () =>\n `<td class=\"calendar--skeleton\" aria-hidden=\"true\"></td>`\n ).join('')}</tr>`\n ).join('')\n : viewModel.calendarDates\n .map(\n week => `\n <tr>\n ${week\n .map((calendarDate, dayIndex) => {\n const classes = getCellClasses(calendarDate);\n if (availabilityMode && calendarDate.isCurrentMonth) {\n classes.push(\n calendarDate.hasEvents\n ? 'availability--booked'\n : 'availability--free'\n );\n }\n if (\n availabilityMode === 'day' &&\n selectable &&\n calendarDate.isCurrentMonth\n ) {\n const d = calendarDate.date;\n if (\n this._rangeStart &&\n isSameDay(d, this._rangeStart)\n )\n classes.push('availability--range-start');\n if (this._rangeEnd && isSameDay(d, this._rangeEnd))\n classes.push('availability--range-end');\n if (this._rangeStart && this._rangeEnd) {\n if (d > this._rangeStart && d < this._rangeEnd)\n classes.push('availability--in-range');\n }\n }\n const dateString = calendarDate.date.toISOString();\n return `\n <td\n class=\"${classes.join(' ')}\"\n data-date=\"${dateString}\"\n data-day-index=\"${dayIndex}\"\n data-clickable=\"true\"\n >\n ${calendarDate.date.getDate()}\n </td>\n `;\n })\n .join('')}\n </tr>\n `\n )\n .join('')\n }\n </tbody>\n </table>\n\n ${\n !isLoading && availabilityMode !== 'day' && viewModel.selectedDate\n ? `\n <div class=\"date-popup ${viewModel.popupPositionClass}\">\n <div class=\"popup-header\">\n <h2>${viewModel.scheduleDay}</h2>\n <button type=\"button\" class=\"popup-close\" data-action=\"close-popup\" aria-label=\"Close\">✕</button>\n </div>\n\n ${\n showScrollHint\n ? `\n <div class=\"scroll-hint\">\n ↓ Scroll to see more events ↓\n </div>\n `\n : ''\n }\n\n <div class=\"events-container\">\n ${\n availabilityMode === 'time'\n ? renderTimeGrid(viewModel.tasks, viewModel.selectedDate!)\n : viewModel.tasks.length > 0\n ? viewModel.tasks\n .map(event => renderEvent(event))\n .join('')\n : renderNoEvents()\n }\n </div>\n </div>\n `\n : ''\n }\n </div>\n </div>\n `;\n\n this.innerHTML = html;\n this.attachEventListeners();\n }\n\n private attachEventListeners(): void {\n if (this.listenersAttached) return;\n this.listenersAttached = true;\n\n const minYear = this.minYear;\n const maxYear = this.maxYear;\n\n this.delegatedClickHandler = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n const cell = target.closest('td[data-clickable=\"true\"]') as HTMLElement;\n if (cell && cell.dataset.date) {\n e.stopPropagation();\n const date = new Date(cell.dataset.date);\n const dayIndex = parseInt(cell.dataset.dayIndex || '0');\n const availMode = this.getAttribute('availability-mode');\n const isSelectable = this.hasAttribute('selectable');\n\n if (availMode === 'day' && isSelectable) {\n const isBooked = cell.classList.contains('availability--booked');\n if (!isBooked) {\n let startDate: Date;\n let endDate: Date;\n if (this._rangeEnd !== null) {\n // State 2 (complete) → reset, start fresh\n this._rangeStart = date;\n this._rangeEnd = null;\n startDate = date;\n endDate = date;\n } else if (this._rangeStart === null) {\n // State 0 → first click\n this._rangeStart = date;\n startDate = date;\n endDate = date;\n } else {\n // State 1 → second click, complete the range if no booked day inside\n const [s, e] =\n this._rangeStart <= date\n ? [this._rangeStart, date]\n : [date, this._rangeStart];\n const cursor = new Date(s);\n cursor.setDate(cursor.getDate() + 1);\n let blocked = false;\n while (cursor < e) {\n if (this.engine!.getEventsForDate(cursor).length > 0) {\n blocked = true;\n break;\n }\n cursor.setDate(cursor.getDate() + 1);\n }\n if (blocked) {\n // Booked day inside range — reset, start fresh from this click\n this._rangeStart = date;\n this._rangeEnd = null;\n } else {\n this._rangeStart = s;\n this._rangeEnd = e;\n }\n startDate = this._rangeStart;\n endDate = this._rangeEnd ?? this._rangeStart;\n }\n this.dispatchEvent(\n new CustomEvent('cal-availability-select', {\n bubbles: true,\n composed: true,\n detail: { startDate, endDate },\n })\n );\n }\n }\n\n if (availMode === 'time') {\n // Reset time range when a new day is opened\n this._timeRangeDate = null;\n this._timeRangeStart = null;\n this._timeRangeEnd = null;\n this._timeRangeComplete = false;\n }\n\n this.engine!.handleDateClick(date, dayIndex);\n this.dispatchEvent(\n new CustomEvent('cal-date-select', {\n bubbles: true,\n composed: true,\n detail: { date, events: this.engine!.getEventsForDate(date) },\n })\n );\n return;\n }\n\n const actionEl = target.closest('[data-action]') as HTMLElement;\n if (!actionEl) return;\n\n const action = actionEl.dataset.action;\n e.stopPropagation();\n\n switch (action) {\n case 'previous': {\n const vm = this.engine!.getViewModel();\n const tMonth = vm.currentMonth === 0 ? 11 : vm.currentMonth - 1;\n const tYear =\n vm.currentMonth === 0 ? vm.currentYear - 1 : vm.currentYear;\n this.dispatchMonthChange(tYear, tMonth);\n this.actions!.previous();\n break;\n }\n\n case 'next': {\n const vm = this.engine!.getViewModel();\n const tMonth = vm.currentMonth === 11 ? 0 : vm.currentMonth + 1;\n const tYear =\n vm.currentMonth === 11 ? vm.currentYear + 1 : vm.currentYear;\n this.dispatchMonthChange(tYear, tMonth);\n this.actions!.next();\n break;\n }\n\n case 'today': {\n const t = new Date();\n this.dispatchMonthChange(t.getFullYear(), t.getMonth());\n this.actions!.goToToday();\n this.pickerOpen = false;\n break;\n }\n\n case 'toggle-picker':\n this.pickerOpen = !this.pickerOpen;\n if (this.pickerOpen) {\n this.yearInput = String(this.engine!.getViewModel().currentYear);\n this.yearInputValid = true;\n }\n this.render();\n break;\n\n case 'year-prev': {\n const vm = this.engine!.getViewModel();\n if (vm.currentYear > minYear) {\n const newYear = vm.currentYear - 1;\n this.yearInput = String(newYear);\n this.updatePickerYear(newYear);\n this.dispatchMonthChange(newYear, vm.currentMonth);\n this.actions!.jump(newYear, vm.currentMonth);\n }\n break;\n }\n\n case 'year-next': {\n const vm = this.engine!.getViewModel();\n if (vm.currentYear < maxYear) {\n const newYear = vm.currentYear + 1;\n this.yearInput = String(newYear);\n this.updatePickerYear(newYear);\n this.dispatchMonthChange(newYear, vm.currentMonth);\n this.actions!.jump(newYear, vm.currentMonth);\n }\n break;\n }\n\n case 'select-month': {\n const month = parseInt(actionEl.dataset.month || '0', 10);\n const year = this.engine!.getViewModel().currentYear;\n this.dispatchMonthChange(year, month);\n this.actions!.jump(year, month);\n this.pickerOpen = false;\n break;\n }\n\n case 'close-popup':\n this._timeRangeDate = null;\n this._timeRangeStart = null;\n this._timeRangeEnd = null;\n this._timeRangeComplete = false;\n this.engine!.clearSelection();\n break;\n\n case 'select-slot': {\n const slotStart = actionEl.dataset.startTime!;\n const slotEnd = actionEl.dataset.endTime!;\n const slotDate = new Date(actionEl.dataset.date!);\n if (this._timeRangeComplete) {\n // State 2 → reset, start fresh\n this._timeRangeDate = slotDate;\n this._timeRangeStart = slotStart;\n this._timeRangeEnd = slotEnd;\n this._timeRangeComplete = false;\n } else if (this._timeRangeStart === null) {\n // State 0 → first click\n this._timeRangeDate = slotDate;\n this._timeRangeStart = slotStart;\n this._timeRangeEnd = slotEnd;\n } else {\n // State 1 → second click, extend range\n const newStart =\n slotStart < this._timeRangeStart\n ? slotStart\n : this._timeRangeStart;\n const newEnd =\n slotEnd > this._timeRangeEnd! ? slotEnd : this._timeRangeEnd!;\n this._timeRangeStart = newStart;\n this._timeRangeEnd = newEnd;\n this._timeRangeComplete = true;\n }\n this.render();\n this.dispatchEvent(\n new CustomEvent('cal-availability-select', {\n bubbles: true,\n composed: true,\n detail: {\n date: this._timeRangeDate,\n startTime: this._timeRangeStart,\n endTime: this._timeRangeEnd,\n },\n })\n );\n break;\n }\n }\n };\n\n this.delegatedInputHandler = (e: Event) => {\n const target = e.target as HTMLInputElement;\n if (!target.matches('[data-year-input]')) return;\n\n const value = target.value;\n if (value === '' || /^\\d+$/.test(value)) {\n this.yearInput = value;\n const year = parseInt(value, 10);\n this.yearInputValid =\n value === '' || (year >= minYear && year <= maxYear);\n target.classList.toggle('invalid', !this.yearInputValid);\n }\n };\n\n this.delegatedBlurHandler = (e: FocusEvent) => {\n const target = e.target as HTMLInputElement;\n if (!target.matches('[data-year-input]')) return;\n\n const year = parseInt(this.yearInput, 10);\n const vm = this.engine!.getViewModel();\n if (isNaN(year) || year < minYear || year > maxYear) {\n this.yearInput = String(vm.currentYear);\n this.yearInputValid = true;\n target.value = this.yearInput;\n target.classList.remove('invalid');\n } else if (year !== vm.currentYear) {\n this.dispatchMonthChange(year, vm.currentMonth);\n this.actions!.jump(year, vm.currentMonth);\n }\n };\n\n this.delegatedKeydownHandler = (e: KeyboardEvent) => {\n const target = e.target as HTMLInputElement;\n if (!target.matches('[data-year-input]')) return;\n if (e.key === 'Enter') target.blur();\n };\n\n this.addEventListener('click', this.delegatedClickHandler);\n this.addEventListener('input', this.delegatedInputHandler);\n this.addEventListener('blur', this.delegatedBlurHandler, true);\n this.addEventListener('keydown', this.delegatedKeydownHandler);\n\n this.clickOutsideHandler = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (this.contains(target)) return;\n\n if (this.pickerOpen) {\n this.pickerOpen = false;\n this.render();\n return;\n }\n\n const popup = this.querySelector('.date-popup');\n if (popup) {\n this.engine!.clearSelection();\n }\n };\n\n document.addEventListener('click', this.clickOutsideHandler);\n }\n\n private updatePickerYear(year: number): void {\n const input = this.querySelector('[data-year-input]') as HTMLInputElement;\n if (input) input.value = String(year);\n\n const prevBtn = this.querySelector(\n '[data-action=\"year-prev\"]'\n ) as HTMLButtonElement;\n const nextBtn = this.querySelector(\n '[data-action=\"year-next\"]'\n ) as HTMLButtonElement;\n if (prevBtn) prevBtn.disabled = year <= this.minYear;\n if (nextBtn) nextBtn.disabled = year >= this.maxYear;\n }\n\n private dispatchMonthChange(year?: number, month?: number): void {\n if (!this.engine) return;\n const vm = this.engine.getViewModel();\n this.dispatchEvent(\n new CustomEvent('cal-month-change', {\n bubbles: true,\n composed: true,\n detail: {\n year: year ?? vm.currentYear,\n month: month ?? vm.currentMonth,\n },\n })\n );\n }\n\n // Public API\n updateEvents(events: CalendarEvent[]): void {\n this.events = events;\n }\n\n updateTheme(theme: CalendarTheme): void {\n this.theme = theme;\n }\n\n getCurrentDate(): Date | null {\n return this.engine?.getViewModel().selectedDate ?? null;\n }\n\n goToDate(date: Date): void {\n const year = date.getFullYear();\n const month = date.getMonth();\n this.dispatchMonthChange(year, month);\n this.actions?.jump(year, month);\n }\n\n getEngine(): CalendarEngine {\n if (!this.engine)\n throw new Error('CalendarElement is not connected to the DOM');\n return this.engine;\n }\n}\n\nexport function defineCalendarElement(tagName = 'kal-calendar'): void {\n if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {\n customElements.define(tagName, CalendarElement);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'kal-calendar': CalendarElement;\n }\n}\n","export { CalendarElement, defineCalendarElement } from './CalendarElement';\nexport type { CalendarElementProps, CalendarElementInstance } from './types';\nexport * from '../core';\n\n// Auto-register the custom element (guarded — safe to import multiple times)\nif (\n typeof customElements !== 'undefined' &&\n !customElements.get('kal-calendar')\n) {\n // Dynamic import keeps this out of the synchronous module evaluation path,\n // which prevents crashes in SSR environments where customElements is undefined\n // but window/document may not be fully available.\n import('./CalendarElement.js').then(({ CalendarElement }) => {\n if (!customElements.get('kal-calendar')) {\n customElements.define('kal-calendar', CalendarElement);\n }\n });\n}\n"],"mappings":"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","names":["isSameDay","e","CalendarElement"]}
package/dist/index.mjs CHANGED
@@ -666,6 +666,8 @@ var init_CalendarElement = __esm({
666
666
  root.style.setProperty("--calendar-today-outline", t.todayOutline);
667
667
  if (t.selectedBg)
668
668
  root.style.setProperty("--calendar-selected-bg", t.selectedBg);
669
+ if (t.headerBg) root.style.setProperty("--calendar-header-bg", t.headerBg);
670
+ if (t.popupBg) root.style.setProperty("--calendar-popup-bg", t.popupBg);
669
671
  if (t.eventIndicator)
670
672
  root.style.setProperty("--calendar-event-indicator", t.eventIndicator);
671
673
  }