kalendly 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +317 -681
- package/dist/core/index.js +3 -3
- package/dist/index.d.mts +48 -602
- package/dist/index.d.ts +48 -602
- package/dist/index.js +753 -2359
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +727 -2348
- package/dist/index.mjs.map +1 -1
- package/dist/{vanilla/index.umd.js → index.umd.js} +218 -218
- package/dist/index.umd.js.map +1 -0
- package/package.json +41 -91
- package/dist/react/index.d.mts +0 -251
- package/dist/react/index.d.ts +0 -251
- package/dist/react/index.js +0 -969
- package/dist/react/index.js.map +0 -1
- package/dist/react/index.mjs +0 -924
- package/dist/react/index.mjs.map +0 -1
- package/dist/react-native/index.d.mts +0 -642
- package/dist/react-native/index.d.ts +0 -642
- package/dist/react-native/index.js +0 -1649
- package/dist/react-native/index.js.map +0 -1
- package/dist/react-native/index.mjs +0 -1615
- package/dist/react-native/index.mjs.map +0 -1
- package/dist/vanilla/index.d.mts +0 -271
- package/dist/vanilla/index.d.ts +0 -271
- package/dist/vanilla/index.js +0 -1064
- package/dist/vanilla/index.js.map +0 -1
- package/dist/vanilla/index.mjs +0 -1013
- package/dist/vanilla/index.mjs.map +0 -1
- package/dist/vanilla/index.umd.js.map +0 -1
- package/dist/vue/components/Calendar.vue.d.ts +0 -43
- package/dist/vue/components/Calendar.vue.d.ts.map +0 -1
- package/dist/vue/index.d.ts +0 -134
- package/dist/vue/index.d.ts.map +0 -1
- package/dist/vue/index.js +0 -1
- package/dist/vue/index.mjs +0 -717
- package/dist/vue/types.d.ts +0 -21
- package/dist/vue/types.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web-components/CalendarElement.ts","../src/core/utils.ts","../src/core/calendar-engine.ts"],"sourcesContent":["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\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 ];\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 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 }\n\n set renderNoEvents(val: () => string) {\n this._renderNoEvents = val;\n if (this.engine) this.render();\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 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\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 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 ‹\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\">▾</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 >‹</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 >›</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 ›\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 ${viewModel.calendarDates\n .map(\n week => `\n <tr>\n ${week\n .map((calendarDate, dayIndex) => {\n const classes = getCellClasses(calendarDate);\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 </tbody>\n </table>\n\n ${\n 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 viewModel.tasks.length > 0\n ? viewModel.tasks.map(event => renderEvent(event)).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 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 this.actions!.previous();\n this.dispatchMonthChange();\n break;\n\n case 'next':\n this.actions!.next();\n this.dispatchMonthChange();\n break;\n\n case 'today':\n this.actions!.goToToday();\n this.pickerOpen = false;\n this.dispatchMonthChange();\n break;\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.actions!.jump(newYear, vm.currentMonth);\n this.dispatchMonthChange();\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.actions!.jump(newYear, vm.currentMonth);\n this.dispatchMonthChange();\n }\n break;\n }\n\n case 'select-month': {\n const month = parseInt(actionEl.dataset.month || '0', 10);\n this.actions!.jump(this.engine!.getViewModel().currentYear, month);\n this.pickerOpen = false;\n this.dispatchMonthChange();\n break;\n }\n\n case 'close-popup':\n this.engine!.clearSelection();\n break;\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.actions!.jump(year, vm.currentMonth);\n this.dispatchMonthChange();\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(): 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: { year: vm.currentYear, month: vm.currentMonth },\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 this.actions?.jump(date.getFullYear(), date.getMonth());\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","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"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kalendly",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A universal calendar web component — works in React, Vue, Angular, svelte, and plain HTML with no framework dependency",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"build": "
|
|
7
|
-
"build:tsup": "tsup",
|
|
8
|
-
"build:vue": "vite build",
|
|
9
|
-
"build:examples": "npm run build && vite build --config vite.examples.config.ts",
|
|
6
|
+
"build": "tsup && npm run copy:styles && npm run copy:dist",
|
|
10
7
|
"copy:styles": "mkdir -p dist/styles && cp src/styles/calendar.css dist/styles/",
|
|
8
|
+
"copy:dist": "rm -rf docs/dist && cp -r dist docs/dist",
|
|
11
9
|
"dev": "tsup --watch",
|
|
12
|
-
"dev:examples": "
|
|
10
|
+
"dev:examples": "npm run build && npx serve docs -p 5173",
|
|
13
11
|
"test": "vitest",
|
|
14
12
|
"test:ui": "vitest --ui",
|
|
15
13
|
"test:run": "vitest run",
|
|
@@ -19,28 +17,16 @@
|
|
|
19
17
|
"test:manual": "echo 'Open tests/manual/*.html in browser' && npx serve . -p 8080",
|
|
20
18
|
"lint": "eslint src tests",
|
|
21
19
|
"lint:fix": "eslint src tests --fix",
|
|
22
|
-
"format": "prettier --write \"src/**/*.{ts,tsx,
|
|
23
|
-
"format:check": "prettier --check \"src/**/*.{ts,tsx,
|
|
20
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
|
21
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
|
24
22
|
"type-check": "tsc --noEmit",
|
|
25
23
|
"prepare": "husky",
|
|
26
24
|
"prepublishOnly": "npm run test && npm run build",
|
|
27
25
|
"prepack": "npm run test:package"
|
|
28
26
|
},
|
|
29
|
-
"author": "Callis Ezenwaka <callisezenwaka@outlook.com>",
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"keywords": [
|
|
32
|
-
"calendar",
|
|
33
|
-
"scheduler",
|
|
34
|
-
"react",
|
|
35
|
-
"vue",
|
|
36
|
-
"react-native",
|
|
37
|
-
"typescript",
|
|
38
|
-
"events",
|
|
39
|
-
"datepicker"
|
|
40
|
-
],
|
|
41
27
|
"repository": {
|
|
42
28
|
"type": "git",
|
|
43
|
-
"url": "https://github.com/callezenwaka/kalendly.git"
|
|
29
|
+
"url": "git+https://github.com/callezenwaka/kalendly.git"
|
|
44
30
|
},
|
|
45
31
|
"bugs": {
|
|
46
32
|
"url": "https://github.com/callezenwaka/kalendly/issues"
|
|
@@ -64,24 +50,9 @@
|
|
|
64
50
|
"require": "./dist/core/index.cjs"
|
|
65
51
|
},
|
|
66
52
|
"./react": {
|
|
67
|
-
"types": "./dist/
|
|
68
|
-
"import": "./dist/
|
|
69
|
-
"require": "./dist/
|
|
70
|
-
},
|
|
71
|
-
"./vue": {
|
|
72
|
-
"types": "./dist/vue/index.d.ts",
|
|
73
|
-
"import": "./dist/vue/index.mjs",
|
|
74
|
-
"require": "./dist/vue/index.cjs"
|
|
75
|
-
},
|
|
76
|
-
"./react-native": {
|
|
77
|
-
"types": "./dist/react-native/index.d.ts",
|
|
78
|
-
"import": "./dist/react-native/index.mjs",
|
|
79
|
-
"require": "./dist/react-native/index.cjs"
|
|
80
|
-
},
|
|
81
|
-
"./vanilla": {
|
|
82
|
-
"types": "./dist/vanilla/index.d.ts",
|
|
83
|
-
"import": "./dist/vanilla/index.mjs",
|
|
84
|
-
"require": "./dist/vanilla/index.cjs"
|
|
53
|
+
"types": "./dist/index.d.ts",
|
|
54
|
+
"import": "./dist/index.mjs",
|
|
55
|
+
"require": "./dist/index.cjs"
|
|
85
56
|
},
|
|
86
57
|
"./styles": {
|
|
87
58
|
"types": "./styles.d.ts",
|
|
@@ -94,24 +65,9 @@
|
|
|
94
65
|
"README.md",
|
|
95
66
|
"LICENSE"
|
|
96
67
|
],
|
|
97
|
-
"peerDependencies": {
|
|
98
|
-
"react": ">=16.8.0",
|
|
99
|
-
"react-dom": ">=16.8.0",
|
|
100
|
-
"react-native": "^0.76.0",
|
|
101
|
-
"vue": ">=3.0.0"
|
|
102
|
-
},
|
|
103
68
|
"peerDependenciesMeta": {
|
|
104
69
|
"react": {
|
|
105
70
|
"optional": true
|
|
106
|
-
},
|
|
107
|
-
"react-dom": {
|
|
108
|
-
"optional": true
|
|
109
|
-
},
|
|
110
|
-
"vue": {
|
|
111
|
-
"optional": true
|
|
112
|
-
},
|
|
113
|
-
"react-native": {
|
|
114
|
-
"optional": true
|
|
115
71
|
}
|
|
116
72
|
},
|
|
117
73
|
"lint-staged": {
|
|
@@ -122,51 +78,45 @@
|
|
|
122
78
|
"*.{ts,tsx,vue,js,jsx,json,css,md}": [
|
|
123
79
|
"prettier --write"
|
|
124
80
|
],
|
|
125
|
-
"*.{ts,tsx
|
|
81
|
+
"*.{ts,tsx}": [
|
|
126
82
|
"eslint --fix",
|
|
127
83
|
"vitest related --run",
|
|
128
84
|
"bash -c 'tsc --noEmit'"
|
|
129
85
|
]
|
|
130
86
|
},
|
|
131
87
|
"devDependencies": {
|
|
132
|
-
"@eslint/js": "^
|
|
88
|
+
"@eslint/js": "^10.0.1",
|
|
133
89
|
"@testing-library/dom": "^10.4.0",
|
|
134
90
|
"@testing-library/jest-dom": "^6.9.1",
|
|
135
|
-
"@testing-library/react": "^16.3.1",
|
|
136
|
-
"@testing-library/react-native": "^13.3.3",
|
|
137
91
|
"@testing-library/user-event": "^14.6.1",
|
|
138
|
-
"@
|
|
139
|
-
"@
|
|
140
|
-
"@
|
|
141
|
-
"@
|
|
142
|
-
"@
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"@vitest/coverage-v8": "^4.0.16",
|
|
147
|
-
"@vitest/ui": "^4.0.16",
|
|
148
|
-
"@vue/compiler-sfc": "^3.5.25",
|
|
149
|
-
"@vue/eslint-config-typescript": "^14.1.3",
|
|
150
|
-
"esbuild-plugin-vue-next": "^0.1.4",
|
|
151
|
-
"eslint": "^9.18.0",
|
|
152
|
-
"eslint-config-prettier": "^9.1.0",
|
|
153
|
-
"eslint-plugin-react": "^7.37.2",
|
|
154
|
-
"eslint-plugin-react-hooks": "^5.1.0",
|
|
155
|
-
"eslint-plugin-vue": "^9.17.0",
|
|
156
|
-
"globals": "^15.14.0",
|
|
92
|
+
"@types/node": "^25.6.0",
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "^8.58.1",
|
|
94
|
+
"@typescript-eslint/parser": "^8.58.1",
|
|
95
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
96
|
+
"@vitest/ui": "^4.1.4",
|
|
97
|
+
"eslint": "^10.2.0",
|
|
98
|
+
"eslint-config-prettier": "^10.1.8",
|
|
99
|
+
"globals": "^17.4.0",
|
|
157
100
|
"husky": "^9.1.7",
|
|
158
|
-
"jsdom": "^
|
|
159
|
-
"lint-staged": "^16.
|
|
160
|
-
"prettier": "^3.
|
|
161
|
-
"react": "^18.3.1",
|
|
162
|
-
"react-dom": "^18.3.1",
|
|
163
|
-
"react-native": "^0.76.0",
|
|
164
|
-
"react-test-renderer": "^18.3.1",
|
|
101
|
+
"jsdom": "^29.0.2",
|
|
102
|
+
"lint-staged": "^16.4.0",
|
|
103
|
+
"prettier": "^3.8.2",
|
|
165
104
|
"tsup": "^8.5.1",
|
|
166
|
-
"typescript": "^5.
|
|
167
|
-
"
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
"
|
|
171
|
-
|
|
105
|
+
"typescript": "^5.9.3",
|
|
106
|
+
"vitest": "^4.1.4"
|
|
107
|
+
},
|
|
108
|
+
"keywords": [
|
|
109
|
+
"calendar",
|
|
110
|
+
"scheduler",
|
|
111
|
+
"web-components",
|
|
112
|
+
"custom-elements",
|
|
113
|
+
"typescript",
|
|
114
|
+
"react",
|
|
115
|
+
"vue",
|
|
116
|
+
"angular",
|
|
117
|
+
"events",
|
|
118
|
+
"datepicker"
|
|
119
|
+
],
|
|
120
|
+
"author": "Callis Ezenwaka <callisezenwaka@outlook.com>",
|
|
121
|
+
"license": "MIT"
|
|
172
122
|
}
|
package/dist/react/index.d.mts
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import React, { CSSProperties, ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
interface CalendarEvent {
|
|
4
|
-
id: string | number;
|
|
5
|
-
name: string;
|
|
6
|
-
date: string | Date;
|
|
7
|
-
startTime?: string;
|
|
8
|
-
endTime?: string;
|
|
9
|
-
allDay?: boolean;
|
|
10
|
-
description?: string;
|
|
11
|
-
color?: string;
|
|
12
|
-
category?: 'work' | 'personal' | 'meeting' | 'deadline' | 'appointment' | 'other';
|
|
13
|
-
location?: string;
|
|
14
|
-
url?: string;
|
|
15
|
-
status?: 'scheduled' | 'completed' | 'cancelled' | 'tentative';
|
|
16
|
-
priority?: 'low' | 'medium' | 'high';
|
|
17
|
-
attendees?: string[];
|
|
18
|
-
organizer?: string;
|
|
19
|
-
reminders?: number[];
|
|
20
|
-
recurring?: {
|
|
21
|
-
frequency: 'daily' | 'weekly' | 'monthly' | 'yearly';
|
|
22
|
-
interval?: number;
|
|
23
|
-
endDate?: string | Date;
|
|
24
|
-
daysOfWeek?: number[];
|
|
25
|
-
};
|
|
26
|
-
notes?: string;
|
|
27
|
-
tags?: string[];
|
|
28
|
-
createdAt?: string | Date;
|
|
29
|
-
updatedAt?: string | Date;
|
|
30
|
-
[key: string]: unknown;
|
|
31
|
-
}
|
|
32
|
-
interface CalendarDate {
|
|
33
|
-
date: Date;
|
|
34
|
-
isCurrentMonth: boolean;
|
|
35
|
-
isToday: boolean;
|
|
36
|
-
hasEvents: boolean;
|
|
37
|
-
events: CalendarEvent[];
|
|
38
|
-
}
|
|
39
|
-
interface CalendarState {
|
|
40
|
-
currentYear: number;
|
|
41
|
-
currentMonth: number;
|
|
42
|
-
currentDate: number;
|
|
43
|
-
selectedDate: Date | null;
|
|
44
|
-
selectedDayIndex: number | null;
|
|
45
|
-
tasks: CalendarEvent[];
|
|
46
|
-
}
|
|
47
|
-
interface CategoryColorMap {
|
|
48
|
-
[category: string]: string;
|
|
49
|
-
}
|
|
50
|
-
interface CalendarConfig {
|
|
51
|
-
events: CalendarEvent[];
|
|
52
|
-
initialDate?: Date;
|
|
53
|
-
minYear?: number;
|
|
54
|
-
maxYear?: number;
|
|
55
|
-
weekStartsOn?: 0 | 1;
|
|
56
|
-
categoryColors?: CategoryColorMap;
|
|
57
|
-
}
|
|
58
|
-
interface CalendarActions {
|
|
59
|
-
next: () => void;
|
|
60
|
-
previous: () => void;
|
|
61
|
-
jump: (year: number, month: number) => void;
|
|
62
|
-
goToToday: () => void;
|
|
63
|
-
isCurrentMonth: () => boolean;
|
|
64
|
-
selectDate: (date: Date) => void;
|
|
65
|
-
updateTasks: () => void;
|
|
66
|
-
}
|
|
67
|
-
interface PopupPosition {
|
|
68
|
-
class: 'popup-left' | 'popup-right' | 'popup-center-top' | 'popup-center-bottom';
|
|
69
|
-
style?: Record<string, string | number>;
|
|
70
|
-
}
|
|
71
|
-
interface CalendarViewModel extends CalendarState {
|
|
72
|
-
months: string[];
|
|
73
|
-
days: string[];
|
|
74
|
-
years: number[];
|
|
75
|
-
monthAndYearText: string;
|
|
76
|
-
scheduleDay: string;
|
|
77
|
-
calendarDates: CalendarDate[][];
|
|
78
|
-
popupPositionClass: string;
|
|
79
|
-
}
|
|
80
|
-
type CalendarEventHandler = (event: CalendarEvent) => void;
|
|
81
|
-
interface CalendarProps {
|
|
82
|
-
events: CalendarEvent[];
|
|
83
|
-
initialDate?: Date;
|
|
84
|
-
minYear?: number;
|
|
85
|
-
maxYear?: number;
|
|
86
|
-
weekStartsOn?: 0 | 1;
|
|
87
|
-
useShortMonthNames?: boolean;
|
|
88
|
-
onDateSelect?: (date: Date) => void;
|
|
89
|
-
onEventClick?: CalendarEventHandler;
|
|
90
|
-
onMonthChange?: (year: number, month: number) => void;
|
|
91
|
-
}
|
|
92
|
-
interface CalendarTheme {
|
|
93
|
-
primary?: string;
|
|
94
|
-
secondary?: string;
|
|
95
|
-
tertiary?: string;
|
|
96
|
-
textColor?: string;
|
|
97
|
-
textLight?: string;
|
|
98
|
-
background?: string;
|
|
99
|
-
cellHover?: string;
|
|
100
|
-
borderColor?: string;
|
|
101
|
-
todayOutline?: string;
|
|
102
|
-
selectedBg?: string;
|
|
103
|
-
eventIndicator?: string;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
declare const MONTHS: string[];
|
|
107
|
-
declare const MONTHS_FULL: string[];
|
|
108
|
-
declare const DAYS: string[];
|
|
109
|
-
declare function normalizeDate(date: Date): Date;
|
|
110
|
-
declare function isSameDay(date1: Date, date2: Date): boolean;
|
|
111
|
-
declare function isToday(date: Date): boolean;
|
|
112
|
-
declare function generateYears(minYear?: number, maxYear?: number): number[];
|
|
113
|
-
declare function getEventsForDate(events: CalendarEvent[], date: Date): CalendarEvent[];
|
|
114
|
-
declare function hasEvents(events: CalendarEvent[], date: Date): boolean;
|
|
115
|
-
declare function generateCalendarDates(year: number, month: number, events?: CalendarEvent[], weekStartsOn?: 0 | 1): CalendarDate[][];
|
|
116
|
-
declare function getPopupPositionClass(selectedDayIndex: number | null): string;
|
|
117
|
-
declare function getCellClasses(calendarDate: CalendarDate): string[];
|
|
118
|
-
declare function formatDateForDisplay(date: Date): string;
|
|
119
|
-
declare function getMonthYearText(year: number, month: number): string;
|
|
120
|
-
declare function formatTimeRange(event: CalendarEvent): string;
|
|
121
|
-
declare function formatAttendees(attendees?: string[]): string;
|
|
122
|
-
declare function sortEventsByTime(events: CalendarEvent[]): CalendarEvent[];
|
|
123
|
-
declare const DEFAULT_CATEGORY_COLORS: CategoryColorMap;
|
|
124
|
-
declare function getDefaultEventColor(category?: string, customColors?: CategoryColorMap): string;
|
|
125
|
-
declare function mergeCategoryColors(customColors?: CategoryColorMap): CategoryColorMap;
|
|
126
|
-
declare function isValidHexColor(color: string): boolean;
|
|
127
|
-
declare function getCategoryColor(category: string, customColors?: CategoryColorMap): string;
|
|
128
|
-
|
|
129
|
-
declare class CalendarEngine {
|
|
130
|
-
private state;
|
|
131
|
-
private config;
|
|
132
|
-
private listeners;
|
|
133
|
-
private categoryColors;
|
|
134
|
-
constructor(config: CalendarConfig);
|
|
135
|
-
/**
|
|
136
|
-
* Subscribe to state changes
|
|
137
|
-
*/
|
|
138
|
-
subscribe(listener: () => void): () => void;
|
|
139
|
-
/**
|
|
140
|
-
* Notify all listeners of state changes
|
|
141
|
-
*/
|
|
142
|
-
private notify;
|
|
143
|
-
/**
|
|
144
|
-
* Get current state
|
|
145
|
-
*/
|
|
146
|
-
getState(): CalendarState;
|
|
147
|
-
/**
|
|
148
|
-
* Get view model with computed properties
|
|
149
|
-
*/
|
|
150
|
-
getViewModel(): CalendarViewModel;
|
|
151
|
-
/**
|
|
152
|
-
* Get actions object
|
|
153
|
-
*/
|
|
154
|
-
getActions(): CalendarActions;
|
|
155
|
-
/**
|
|
156
|
-
* Navigate to next month
|
|
157
|
-
*/
|
|
158
|
-
private next;
|
|
159
|
-
/**
|
|
160
|
-
* Navigate to previous month
|
|
161
|
-
*/
|
|
162
|
-
private previous;
|
|
163
|
-
/**
|
|
164
|
-
* Jump to specific month and year
|
|
165
|
-
*/
|
|
166
|
-
private jump;
|
|
167
|
-
/**
|
|
168
|
-
* Navigate to current month (today)
|
|
169
|
-
*/
|
|
170
|
-
private goToToday;
|
|
171
|
-
/**
|
|
172
|
-
* Check if currently viewing today's month
|
|
173
|
-
*/
|
|
174
|
-
private isCurrentMonth;
|
|
175
|
-
/**
|
|
176
|
-
* Select a specific date
|
|
177
|
-
*/
|
|
178
|
-
private selectDate;
|
|
179
|
-
/**
|
|
180
|
-
* Update tasks for the currently selected date
|
|
181
|
-
*/
|
|
182
|
-
private updateTasks;
|
|
183
|
-
/**
|
|
184
|
-
* Update events configuration
|
|
185
|
-
*/
|
|
186
|
-
updateEvents(events: CalendarEvent[]): void;
|
|
187
|
-
/**
|
|
188
|
-
* Handle date cell click
|
|
189
|
-
*/
|
|
190
|
-
handleDateClick(date: Date, dayIndex?: number): void;
|
|
191
|
-
/**
|
|
192
|
-
* Check if date has events
|
|
193
|
-
*/
|
|
194
|
-
hasEventsForDate(date: Date): boolean;
|
|
195
|
-
/**
|
|
196
|
-
* Get events for a specific date
|
|
197
|
-
*/
|
|
198
|
-
getEventsForDate(date: Date): CalendarEvent[];
|
|
199
|
-
/**
|
|
200
|
-
* Clear selected date
|
|
201
|
-
*/
|
|
202
|
-
clearSelection(): void;
|
|
203
|
-
/**
|
|
204
|
-
* Get category color (with custom colors support)
|
|
205
|
-
*/
|
|
206
|
-
getCategoryColor(category?: string): string;
|
|
207
|
-
/**
|
|
208
|
-
* Update category colors dynamically
|
|
209
|
-
*/
|
|
210
|
-
updateCategoryColors(colors: CategoryColorMap): void;
|
|
211
|
-
/**
|
|
212
|
-
* Get all category colors
|
|
213
|
-
*/
|
|
214
|
-
getCategoryColors(): CategoryColorMap;
|
|
215
|
-
/**
|
|
216
|
-
* Register a new category with color
|
|
217
|
-
*/
|
|
218
|
-
registerCategory(name: string, color: string): void;
|
|
219
|
-
/**
|
|
220
|
-
* Destroy the engine and cleanup listeners
|
|
221
|
-
*/
|
|
222
|
-
destroy(): void;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
interface ReactCalendarProps extends CalendarProps {
|
|
226
|
-
className?: string;
|
|
227
|
-
style?: CSSProperties;
|
|
228
|
-
children?: ReactNode;
|
|
229
|
-
renderEvent?: (event: CalendarEvent) => ReactNode;
|
|
230
|
-
renderNoEvents?: () => ReactNode;
|
|
231
|
-
title?: string;
|
|
232
|
-
theme?: CalendarTheme;
|
|
233
|
-
}
|
|
234
|
-
type CalendarComponentProps = ReactCalendarProps;
|
|
235
|
-
interface DatePopupProps {
|
|
236
|
-
isVisible: boolean;
|
|
237
|
-
selectedDate: Date | null;
|
|
238
|
-
events: CalendarEvent[];
|
|
239
|
-
scheduleDay: string;
|
|
240
|
-
popupPositionClass: string;
|
|
241
|
-
onClose?: () => void;
|
|
242
|
-
onEventClick?: (event: CalendarEvent) => void;
|
|
243
|
-
renderEvent?: (event: CalendarEvent) => ReactNode;
|
|
244
|
-
renderNoEvents?: () => ReactNode;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
declare const Calendar: React.FC<CalendarComponentProps>;
|
|
248
|
-
|
|
249
|
-
declare const DatePopup: React.FC<DatePopupProps>;
|
|
250
|
-
|
|
251
|
-
export { Calendar, type CalendarActions, type CalendarComponentProps, type CalendarConfig, type CalendarDate, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, DatePopup, type DatePopupProps, MONTHS, MONTHS_FULL, type PopupPosition, type ReactCalendarProps, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, getPopupPositionClass, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, sortEventsByTime };
|