kalendly 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -19
- package/dist/core/index.d.mts +10 -1
- package/dist/core/index.d.ts +10 -1
- package/dist/core/index.js +99 -5
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +91 -5
- package/dist/core/index.mjs.map +1 -1
- package/dist/index.d.mts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +165 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +157 -29
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +148 -28
- package/dist/index.umd.js.map +1 -1
- package/dist/styles/calendar.css +16 -1
- package/package.json +1 -1
package/dist/core/index.mjs
CHANGED
|
@@ -51,12 +51,28 @@ function generateYears(minYear, maxYear) {
|
|
|
51
51
|
const max = maxYear ?? currentYear + 10;
|
|
52
52
|
return Array.from({ length: max - min + 1 }, (_, i) => min + i);
|
|
53
53
|
}
|
|
54
|
+
function eventCoversDate(event, date) {
|
|
55
|
+
const start = normalizeDate(new Date(event.date)).getTime();
|
|
56
|
+
const target = normalizeDate(date).getTime();
|
|
57
|
+
if (Number.isNaN(start)) return false;
|
|
58
|
+
if (event.endDate === void 0 || event.endDate === null) {
|
|
59
|
+
return start === target;
|
|
60
|
+
}
|
|
61
|
+
const end = normalizeDate(new Date(event.endDate)).getTime();
|
|
62
|
+
if (Number.isNaN(end)) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`<kal-calendar> event ${event.id} has an unreadable endDate: ${String(event.endDate)}.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (end < start) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`<kal-calendar> event ${event.id} has an endDate before its date: ${String(event.endDate)} < ${String(event.date)}.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return target >= start && target <= end;
|
|
73
|
+
}
|
|
54
74
|
function getEventsForDate(events, date) {
|
|
55
|
-
|
|
56
|
-
return events.filter((event) => {
|
|
57
|
-
const eventDate = normalizeDate(new Date(event.date));
|
|
58
|
-
return eventDate.getTime() === normalizedTargetDate.getTime();
|
|
59
|
-
});
|
|
75
|
+
return events.filter((event) => eventCoversDate(event, date));
|
|
60
76
|
}
|
|
61
77
|
function hasEvents(events, date) {
|
|
62
78
|
return getEventsForDate(events, date).length > 0;
|
|
@@ -215,6 +231,68 @@ function safeColor(value) {
|
|
|
215
231
|
const trimmed = String(value).trim();
|
|
216
232
|
return isValidHexColor(trimmed) || /^[a-z]+$/i.test(trimmed) ? trimmed : "#3b82f6";
|
|
217
233
|
}
|
|
234
|
+
var MINUTES_PER_DAY = 1440;
|
|
235
|
+
var DEFAULT_SLOT_DURATION = 60;
|
|
236
|
+
function parseTimeToMinutes(time) {
|
|
237
|
+
if (typeof time !== "string") return null;
|
|
238
|
+
const match = /^(\d{1,2}):(\d{2})$/.exec(time.trim());
|
|
239
|
+
if (!match) return null;
|
|
240
|
+
const hours = Number(match[1]);
|
|
241
|
+
const mins = Number(match[2]);
|
|
242
|
+
if (hours > 24 || mins > 59 || hours === 24 && mins > 0) return null;
|
|
243
|
+
return hours * 60 + mins;
|
|
244
|
+
}
|
|
245
|
+
function formatMinutes(total) {
|
|
246
|
+
const hours = Math.floor(total / 60);
|
|
247
|
+
const mins = total % 60;
|
|
248
|
+
return `${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
|
|
249
|
+
}
|
|
250
|
+
function eventInterval(event, slotDuration, onDay) {
|
|
251
|
+
const day = normalizeDate(onDay).getTime();
|
|
252
|
+
if (Number.isNaN(day)) return null;
|
|
253
|
+
const base = day / 6e4;
|
|
254
|
+
const wholeDay = [base, base + MINUTES_PER_DAY];
|
|
255
|
+
if (event.allDay || !event.startTime) return wholeDay;
|
|
256
|
+
const from = parseTimeToMinutes(event.startTime);
|
|
257
|
+
if (from === null) return wholeDay;
|
|
258
|
+
if (event.endTime === void 0 || event.endTime === null) {
|
|
259
|
+
return [base + from, base + from + slotDuration];
|
|
260
|
+
}
|
|
261
|
+
const to = parseTimeToMinutes(event.endTime);
|
|
262
|
+
if (to === null) return wholeDay;
|
|
263
|
+
return [base + from, base + (to <= from ? to + MINUTES_PER_DAY : to)];
|
|
264
|
+
}
|
|
265
|
+
function mergeIntervals(intervals) {
|
|
266
|
+
const sorted = [...intervals].sort((a, b) => a[0] - b[0]);
|
|
267
|
+
return sorted.reduce((merged, [start, end]) => {
|
|
268
|
+
const last = merged[merged.length - 1];
|
|
269
|
+
if (last && start <= last[1]) last[1] = Math.max(last[1], end);
|
|
270
|
+
else merged.push([start, end]);
|
|
271
|
+
return merged;
|
|
272
|
+
}, []);
|
|
273
|
+
}
|
|
274
|
+
function bookedSlots(events, date, slotDuration = DEFAULT_SLOT_DURATION) {
|
|
275
|
+
const base = normalizeDate(date).getTime() / 6e4;
|
|
276
|
+
const previousDay = new Date(date);
|
|
277
|
+
previousDay.setDate(previousDay.getDate() - 1);
|
|
278
|
+
const intervals = [];
|
|
279
|
+
for (const event of new Set(events)) {
|
|
280
|
+
for (const day of [previousDay, date]) {
|
|
281
|
+
if (!eventCoversDate(event, day)) continue;
|
|
282
|
+
const interval = eventInterval(event, slotDuration, day);
|
|
283
|
+
if (interval) intervals.push(interval);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const merged = mergeIntervals(intervals);
|
|
287
|
+
return Array.from(
|
|
288
|
+
{ length: Math.floor(MINUTES_PER_DAY / slotDuration) },
|
|
289
|
+
(_, index) => {
|
|
290
|
+
const start = base + index * slotDuration;
|
|
291
|
+
const end = start + slotDuration;
|
|
292
|
+
return merged.some(([from, to]) => start < to && end > from);
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
}
|
|
218
296
|
|
|
219
297
|
// src/core/calendar-engine.ts
|
|
220
298
|
var CalendarEngine = class {
|
|
@@ -461,11 +539,17 @@ export {
|
|
|
461
539
|
CalendarEngine,
|
|
462
540
|
DAYS,
|
|
463
541
|
DEFAULT_CATEGORY_COLORS,
|
|
542
|
+
DEFAULT_SLOT_DURATION,
|
|
543
|
+
MINUTES_PER_DAY,
|
|
464
544
|
MONTHS,
|
|
465
545
|
MONTHS_FULL,
|
|
546
|
+
bookedSlots,
|
|
466
547
|
escapeHtml,
|
|
548
|
+
eventCoversDate,
|
|
549
|
+
eventInterval,
|
|
467
550
|
formatAttendees,
|
|
468
551
|
formatDateForDisplay,
|
|
552
|
+
formatMinutes,
|
|
469
553
|
formatTimeRange,
|
|
470
554
|
generateCalendarDates,
|
|
471
555
|
generateYears,
|
|
@@ -479,7 +563,9 @@ export {
|
|
|
479
563
|
isToday,
|
|
480
564
|
isValidHexColor,
|
|
481
565
|
mergeCategoryColors,
|
|
566
|
+
mergeIntervals,
|
|
482
567
|
normalizeDate,
|
|
568
|
+
parseTimeToMinutes,
|
|
483
569
|
safeColor,
|
|
484
570
|
safeUrl,
|
|
485
571
|
slugifyToken,
|
package/dist/core/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/utils.ts","../../src/core/calendar-engine.ts"],"sourcesContent":["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 getCellClasses(calendarDate: CalendarDate): string[] {\n const classes: string[] = [];\n\n if (!calendarDate.isCurrentMonth) {\n classes.push('calendar-cell-other-month');\n }\n\n if (calendarDate.isToday) {\n classes.push('calendar-cell-today');\n }\n\n if (calendarDate.hasEvents) {\n classes.push('calendar-cell-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\nconst HTML_ESCAPES: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\n// Escape a value for interpolation into HTML text or a quoted attribute\nexport function escapeHtml(value: unknown): string {\n if (value === null || value === undefined) return '';\n\n return String(value).replace(/[&<>\"']/g, char => HTML_ESCAPES[char]);\n}\n\n// Reduce a caller-supplied value to a single safe CSS class token\nexport function slugifyToken(value: string): string {\n return String(value)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n// Allow http(s), mailto and relative URLs; anything else (javascript:, data:,\n// vbscript:) collapses to a harmless anchor\nexport function safeUrl(value: string): string {\n // Browsers ignore control characters when resolving a scheme, so\n // `java\\0script:` and `java\\tscript:` both navigate. Strip them before\n // testing rather than after.\n const normalized = String(value)\n .split('')\n .filter(char => char.charCodeAt(0) > 0x20)\n .join('');\n\n if (/^(?:https?:|mailto:)/i.test(normalized)) return normalized;\n\n // Relative URLs have no scheme at all — a colon before the first slash,\n // question mark or hash means someone is naming one\n const schemeless = !/^[^/?#]*:/.test(normalized);\n\n return schemeless ? normalized : '#';\n}\n\n// Accept hex colors and bare CSS color keywords; reject anything that could\n// terminate the declaration or escape the style attribute\nexport function safeColor(value: string): string {\n const trimmed = String(value).trim();\n\n return isValidHexColor(trimmed) || /^[a-z]+$/i.test(trimmed)\n ? trimmed\n : '#3b82f6';\n}\n","import {\n CalendarEvent,\n CalendarState,\n CalendarConfig,\n CalendarActions,\n CalendarViewModel,\n CalendarPane,\n CategoryColorMap,\n} from './types';\nimport {\n generateCalendarDates,\n getEventsForDate,\n generateYears,\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 panes: CalendarPane[] = Array.from(\n { length: Math.max(1, this.config.monthCount ?? 1) },\n (_, offset) => {\n const anchor = new Date(\n this.state.currentYear,\n this.state.currentMonth + offset,\n 1\n );\n const year = anchor.getFullYear();\n const month = anchor.getMonth();\n\n return {\n year,\n month,\n monthAndYearText: getMonthYearText(year, month),\n calendarDates: generateCalendarDates(\n year,\n month,\n this.config.events,\n this.config.weekStartsOn\n ),\n };\n }\n );\n\n return {\n ...this.state,\n months: MONTHS,\n days: DAYS,\n years: generateYears(this.config.minYear, this.config.maxYear),\n monthAndYearText: panes[0].monthAndYearText,\n scheduleDay: this.state.selectedDate\n ? formatDateForDisplay(this.state.selectedDate)\n : '',\n panes,\n calendarDates: panes[0].calendarDates,\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":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/utils.ts","../../src/core/calendar-engine.ts"],"sourcesContent":["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\n// endDate is inclusive, matching the endDate cal-availability-select emits, so\n// a selection can be handed straight back as one event.\nexport function eventCoversDate(event: CalendarEvent, date: Date): boolean {\n const start = normalizeDate(new Date(event.date)).getTime();\n const target = normalizeDate(date).getTime();\n if (Number.isNaN(start)) return false;\n\n if (event.endDate === undefined || event.endDate === null) {\n return start === target;\n }\n\n const end = normalizeDate(new Date(event.endDate)).getTime();\n if (Number.isNaN(end)) {\n throw new Error(\n `<kal-calendar> event ${event.id} has an unreadable endDate: ` +\n `${String(event.endDate)}.`\n );\n }\n if (end < start) {\n throw new Error(\n `<kal-calendar> event ${event.id} has an endDate before its date: ` +\n `${String(event.endDate)} < ${String(event.date)}.`\n );\n }\n\n return target >= start && target <= end;\n}\n\nexport function getEventsForDate(\n events: CalendarEvent[],\n date: Date\n): CalendarEvent[] {\n return events.filter(event => eventCoversDate(event, date));\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 getCellClasses(calendarDate: CalendarDate): string[] {\n const classes: string[] = [];\n\n if (!calendarDate.isCurrentMonth) {\n classes.push('calendar-cell-other-month');\n }\n\n if (calendarDate.isToday) {\n classes.push('calendar-cell-today');\n }\n\n if (calendarDate.hasEvents) {\n classes.push('calendar-cell-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\nconst HTML_ESCAPES: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\n// Escape a value for interpolation into HTML text or a quoted attribute\nexport function escapeHtml(value: unknown): string {\n if (value === null || value === undefined) return '';\n\n return String(value).replace(/[&<>\"']/g, char => HTML_ESCAPES[char]);\n}\n\n// Reduce a caller-supplied value to a single safe CSS class token\nexport function slugifyToken(value: string): string {\n return String(value)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n// Allow http(s), mailto and relative URLs; anything else (javascript:, data:,\n// vbscript:) collapses to a harmless anchor\nexport function safeUrl(value: string): string {\n // Browsers ignore control characters when resolving a scheme, so\n // `java\\0script:` and `java\\tscript:` both navigate. Strip them before\n // testing rather than after.\n const normalized = String(value)\n .split('')\n .filter(char => char.charCodeAt(0) > 0x20)\n .join('');\n\n if (/^(?:https?:|mailto:)/i.test(normalized)) return normalized;\n\n // Relative URLs have no scheme at all — a colon before the first slash,\n // question mark or hash means someone is naming one\n const schemeless = !/^[^/?#]*:/.test(normalized);\n\n return schemeless ? normalized : '#';\n}\n\n// Accept hex colors and bare CSS color keywords; reject anything that could\n// terminate the declaration or escape the style attribute\nexport function safeColor(value: string): string {\n const trimmed = String(value).trim();\n\n return isValidHexColor(trimmed) || /^[a-z]+$/i.test(trimmed)\n ? trimmed\n : '#3b82f6';\n}\n\nexport const MINUTES_PER_DAY = 1440;\nexport const DEFAULT_SLOT_DURATION = 60;\n\nexport function parseTimeToMinutes(time: unknown): number | null {\n if (typeof time !== 'string') return null;\n\n const match = /^(\\d{1,2}):(\\d{2})$/.exec(time.trim());\n if (!match) return null;\n\n const hours = Number(match[1]);\n const mins = Number(match[2]);\n if (hours > 24 || mins > 59 || (hours === 24 && mins > 0)) return null;\n\n return hours * 60 + mins;\n}\n\nexport function formatMinutes(total: number): string {\n const hours = Math.floor(total / 60);\n const mins = total % 60;\n return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;\n}\n\n// Absolute [start, end) in minutes. An end at or before the start is on the\n// following day, so a booking that crosses midnight is one interval rather than\n// two half-days. An unreadable time occupies the whole day — a booking surface\n// that cannot parse a time must not offer the slot.\nexport function eventInterval(\n event: CalendarEvent,\n slotDuration: number,\n onDay: Date\n): [number, number] | null {\n const day = normalizeDate(onDay).getTime();\n if (Number.isNaN(day)) return null;\n\n const base = day / 60000;\n const wholeDay: [number, number] = [base, base + MINUTES_PER_DAY];\n\n if (event.allDay || !event.startTime) return wholeDay;\n\n const from = parseTimeToMinutes(event.startTime);\n if (from === null) return wholeDay;\n\n if (event.endTime === undefined || event.endTime === null) {\n return [base + from, base + from + slotDuration];\n }\n\n const to = parseTimeToMinutes(event.endTime);\n if (to === null) return wholeDay;\n\n return [base + from, base + (to <= from ? to + MINUTES_PER_DAY : to)];\n}\n\nexport function mergeIntervals(\n intervals: Array<[number, number]>\n): Array<[number, number]> {\n const sorted = [...intervals].sort((a, b) => a[0] - b[0]);\n\n return sorted.reduce<Array<[number, number]>>((merged, [start, end]) => {\n const last = merged[merged.length - 1];\n if (last && start <= last[1]) last[1] = Math.max(last[1], end);\n else merged.push([start, end]);\n return merged;\n }, []);\n}\n\n// Which of the day's slots any booking overlaps. Events from the previous day\n// belong in `events` so a booking crossing midnight marks the morning it runs into.\nexport function bookedSlots(\n events: CalendarEvent[],\n date: Date,\n slotDuration: number = DEFAULT_SLOT_DURATION\n): boolean[] {\n const base = normalizeDate(date).getTime() / 60000;\n\n const previousDay = new Date(date);\n previousDay.setDate(previousDay.getDate() - 1);\n\n // A span's times repeat on each day it covers, so the window is anchored to\n // the day being drawn rather than the day the span began\n const intervals: Array<[number, number]> = [];\n for (const event of new Set(events)) {\n for (const day of [previousDay, date]) {\n if (!eventCoversDate(event, day)) continue;\n const interval = eventInterval(event, slotDuration, day);\n if (interval) intervals.push(interval);\n }\n }\n\n const merged = mergeIntervals(intervals);\n\n return Array.from(\n { length: Math.floor(MINUTES_PER_DAY / slotDuration) },\n (_, index) => {\n const start = base + index * slotDuration;\n const end = start + slotDuration;\n return merged.some(([from, to]) => start < to && end > from);\n }\n );\n}\n","import {\n CalendarEvent,\n CalendarState,\n CalendarConfig,\n CalendarActions,\n CalendarViewModel,\n CalendarPane,\n CategoryColorMap,\n} from './types';\nimport {\n generateCalendarDates,\n getEventsForDate,\n generateYears,\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 panes: CalendarPane[] = Array.from(\n { length: Math.max(1, this.config.monthCount ?? 1) },\n (_, offset) => {\n const anchor = new Date(\n this.state.currentYear,\n this.state.currentMonth + offset,\n 1\n );\n const year = anchor.getFullYear();\n const month = anchor.getMonth();\n\n return {\n year,\n month,\n monthAndYearText: getMonthYearText(year, month),\n calendarDates: generateCalendarDates(\n year,\n month,\n this.config.events,\n this.config.weekStartsOn\n ),\n };\n }\n );\n\n return {\n ...this.state,\n months: MONTHS,\n days: DAYS,\n years: generateYears(this.config.minYear, this.config.maxYear),\n monthAndYearText: panes[0].monthAndYearText,\n scheduleDay: this.state.selectedDate\n ? formatDateForDisplay(this.state.selectedDate)\n : '',\n panes,\n calendarDates: panes[0].calendarDates,\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/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,7 @@ interface CalendarEvent {
|
|
|
3
3
|
id: string | number;
|
|
4
4
|
name: string;
|
|
5
5
|
date: string | Date;
|
|
6
|
+
endDate?: string | Date;
|
|
6
7
|
startTime?: string;
|
|
7
8
|
endTime?: string;
|
|
8
9
|
allDay?: boolean;
|
|
@@ -145,6 +146,7 @@ declare function normalizeDate(date: Date): Date;
|
|
|
145
146
|
declare function isSameDay(date1: Date, date2: Date): boolean;
|
|
146
147
|
declare function isToday(date: Date): boolean;
|
|
147
148
|
declare function generateYears(minYear?: number, maxYear?: number): number[];
|
|
149
|
+
declare function eventCoversDate(event: CalendarEvent, date: Date): boolean;
|
|
148
150
|
declare function getEventsForDate(events: CalendarEvent[], date: Date): CalendarEvent[];
|
|
149
151
|
declare function hasEvents(events: CalendarEvent[], date: Date): boolean;
|
|
150
152
|
declare function generateCalendarDates(year: number, month: number, events?: CalendarEvent[], weekStartsOn?: 0 | 1): CalendarDate[][];
|
|
@@ -163,6 +165,13 @@ declare function escapeHtml(value: unknown): string;
|
|
|
163
165
|
declare function slugifyToken(value: string): string;
|
|
164
166
|
declare function safeUrl(value: string): string;
|
|
165
167
|
declare function safeColor(value: string): string;
|
|
168
|
+
declare const MINUTES_PER_DAY = 1440;
|
|
169
|
+
declare const DEFAULT_SLOT_DURATION = 60;
|
|
170
|
+
declare function parseTimeToMinutes(time: unknown): number | null;
|
|
171
|
+
declare function formatMinutes(total: number): string;
|
|
172
|
+
declare function eventInterval(event: CalendarEvent, slotDuration: number, onDay: Date): [number, number] | null;
|
|
173
|
+
declare function mergeIntervals(intervals: Array<[number, number]>): Array<[number, number]>;
|
|
174
|
+
declare function bookedSlots(events: CalendarEvent[], date: Date, slotDuration?: number): boolean[];
|
|
166
175
|
|
|
167
176
|
declare class CalendarEngine {
|
|
168
177
|
private state;
|
|
@@ -307,6 +316,9 @@ declare class CalendarElement extends HTMLElement {
|
|
|
307
316
|
disconnectedCallback(): void;
|
|
308
317
|
attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
|
|
309
318
|
private get headingText();
|
|
319
|
+
private static warnedMissingEnd;
|
|
320
|
+
private get slotDuration();
|
|
321
|
+
private warnMissingEndTime;
|
|
310
322
|
private get monthCount();
|
|
311
323
|
private get minYear();
|
|
312
324
|
private get maxYear();
|
|
@@ -371,4 +383,4 @@ interface CalendarElementInstance {
|
|
|
371
383
|
getEngine: () => CalendarEngine;
|
|
372
384
|
}
|
|
373
385
|
|
|
374
|
-
export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarElement, type CalendarElementInstance, type CalendarElementProps, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarPane, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, MONTHS, MONTHS_FULL, defineCalendarElement, escapeHtml, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, safeColor, safeUrl, slugifyToken, sortEventsByTime };
|
|
386
|
+
export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarElement, type CalendarElementInstance, type CalendarElementProps, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarPane, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, DEFAULT_SLOT_DURATION, MINUTES_PER_DAY, MONTHS, MONTHS_FULL, bookedSlots, defineCalendarElement, escapeHtml, eventCoversDate, eventInterval, formatAttendees, formatDateForDisplay, formatMinutes, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, mergeIntervals, normalizeDate, parseTimeToMinutes, safeColor, safeUrl, slugifyToken, sortEventsByTime };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ interface CalendarEvent {
|
|
|
3
3
|
id: string | number;
|
|
4
4
|
name: string;
|
|
5
5
|
date: string | Date;
|
|
6
|
+
endDate?: string | Date;
|
|
6
7
|
startTime?: string;
|
|
7
8
|
endTime?: string;
|
|
8
9
|
allDay?: boolean;
|
|
@@ -145,6 +146,7 @@ declare function normalizeDate(date: Date): Date;
|
|
|
145
146
|
declare function isSameDay(date1: Date, date2: Date): boolean;
|
|
146
147
|
declare function isToday(date: Date): boolean;
|
|
147
148
|
declare function generateYears(minYear?: number, maxYear?: number): number[];
|
|
149
|
+
declare function eventCoversDate(event: CalendarEvent, date: Date): boolean;
|
|
148
150
|
declare function getEventsForDate(events: CalendarEvent[], date: Date): CalendarEvent[];
|
|
149
151
|
declare function hasEvents(events: CalendarEvent[], date: Date): boolean;
|
|
150
152
|
declare function generateCalendarDates(year: number, month: number, events?: CalendarEvent[], weekStartsOn?: 0 | 1): CalendarDate[][];
|
|
@@ -163,6 +165,13 @@ declare function escapeHtml(value: unknown): string;
|
|
|
163
165
|
declare function slugifyToken(value: string): string;
|
|
164
166
|
declare function safeUrl(value: string): string;
|
|
165
167
|
declare function safeColor(value: string): string;
|
|
168
|
+
declare const MINUTES_PER_DAY = 1440;
|
|
169
|
+
declare const DEFAULT_SLOT_DURATION = 60;
|
|
170
|
+
declare function parseTimeToMinutes(time: unknown): number | null;
|
|
171
|
+
declare function formatMinutes(total: number): string;
|
|
172
|
+
declare function eventInterval(event: CalendarEvent, slotDuration: number, onDay: Date): [number, number] | null;
|
|
173
|
+
declare function mergeIntervals(intervals: Array<[number, number]>): Array<[number, number]>;
|
|
174
|
+
declare function bookedSlots(events: CalendarEvent[], date: Date, slotDuration?: number): boolean[];
|
|
166
175
|
|
|
167
176
|
declare class CalendarEngine {
|
|
168
177
|
private state;
|
|
@@ -307,6 +316,9 @@ declare class CalendarElement extends HTMLElement {
|
|
|
307
316
|
disconnectedCallback(): void;
|
|
308
317
|
attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null): void;
|
|
309
318
|
private get headingText();
|
|
319
|
+
private static warnedMissingEnd;
|
|
320
|
+
private get slotDuration();
|
|
321
|
+
private warnMissingEndTime;
|
|
310
322
|
private get monthCount();
|
|
311
323
|
private get minYear();
|
|
312
324
|
private get maxYear();
|
|
@@ -371,4 +383,4 @@ interface CalendarElementInstance {
|
|
|
371
383
|
getEngine: () => CalendarEngine;
|
|
372
384
|
}
|
|
373
385
|
|
|
374
|
-
export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarElement, type CalendarElementInstance, type CalendarElementProps, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarPane, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, MONTHS, MONTHS_FULL, defineCalendarElement, escapeHtml, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, safeColor, safeUrl, slugifyToken, sortEventsByTime };
|
|
386
|
+
export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarElement, type CalendarElementInstance, type CalendarElementProps, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarPane, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, DEFAULT_SLOT_DURATION, MINUTES_PER_DAY, MONTHS, MONTHS_FULL, bookedSlots, defineCalendarElement, escapeHtml, eventCoversDate, eventInterval, formatAttendees, formatDateForDisplay, formatMinutes, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, mergeIntervals, normalizeDate, parseTimeToMinutes, safeColor, safeUrl, slugifyToken, sortEventsByTime };
|