From 1a26d9aac3fa0d0305d5d97c5d4c503035696464 Mon Sep 17 00:00:00 2001 From: Nathan Panchout Date: Sun, 25 Jan 2026 20:33:36 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F(front)=20add=20DAV=20serv?= =?UTF-8?q?ice=20type=20definitions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add TypeScript type definitions for CalDAV service including calendar, event, addressbook and options types. Add global type declarations for tsdav and ical.js libraries. Co-Authored-By: Claude Opus 4.5 --- .../services/dav/types/addressbook.ts | 30 ++ .../services/dav/types/caldav-service.ts | 280 +++++++++++ .../calendar/services/dav/types/calendar.ts | 39 ++ .../services/dav/types/event-calendar.ts | 434 ++++++++++++++++++ .../calendar/services/dav/types/options.ts | 161 +++++++ src/frontend/apps/calendars/types.d.ts | 45 ++ 6 files changed, 989 insertions(+) create mode 100644 src/frontend/apps/calendars/src/features/calendar/services/dav/types/addressbook.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/services/dav/types/caldav-service.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/services/dav/types/calendar.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/services/dav/types/event-calendar.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/services/dav/types/options.ts create mode 100644 src/frontend/apps/calendars/types.d.ts diff --git a/src/frontend/apps/calendars/src/features/calendar/services/dav/types/addressbook.ts b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/addressbook.ts new file mode 100644 index 0000000..d98f79c --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/addressbook.ts @@ -0,0 +1,30 @@ +import type { DAVAddressBook } from 'tsdav' +import ICAL from 'ical.js' + +export type AddressBook = DAVAddressBook & { + headers?: Record + uid?: unknown +} + +export type AddressBookObject = { + data: ICAL.Component + etag?: string + url: string + addressBookUrl: string +} + +export type VCard = { + name: string + email: string | null +} + +export type AddressBookVCard = { + // INFO - 2025-07-24 - addressBookUrl is undefined when the contact is from a VCardProvider + addressBookUrl?: string + vCard: VCard +} + +export type Contact = { + name?: string + email: string +} diff --git a/src/frontend/apps/calendars/src/features/calendar/services/dav/types/caldav-service.ts b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/caldav-service.ts new file mode 100644 index 0000000..e0a7c09 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/caldav-service.ts @@ -0,0 +1,280 @@ +/** + * Types for CalDavService - Pure CalDAV operations + * + * Reuses types from tsdav and ts-ics where possible to avoid duplication. + */ + +import type { DAVCalendar, DAVCalendarObject } from 'tsdav' +import type { + IcsCalendar, + IcsEvent, + IcsAttendee, + IcsOrganizer, + IcsAttendeePartStatusType, + FreeBusyType as IcsFreeBusyType, +} from 'ts-ics' + +// ============================================================================ +// Re-exports from libraries (avoid duplication) +// ============================================================================ + +/** Attendee type from ts-ics */ +export type CalDavAttendee = IcsAttendee + +/** Organizer type from ts-ics */ +export type CalDavOrganizer = IcsOrganizer + +/** Attendee participation status from ts-ics */ +export type AttendeeStatus = IcsAttendeePartStatusType + +/** FreeBusy type from ts-ics */ +export type FreeBusyType = IcsFreeBusyType + +// ============================================================================ +// Connection & Authentication +// ============================================================================ + +export type CalDavCredentials = { + serverUrl: string + username?: string + password?: string + headers?: Record + fetchOptions?: RequestInit +} + +export type CalDavAccount = { + serverUrl: string + rootUrl?: string + principalUrl?: string + homeUrl?: string + headers?: Record + fetchOptions?: RequestInit +} + +// ============================================================================ +// Calendar Types (extends tsdav types) +// ============================================================================ + +/** Calendar type extending DAVCalendar with additional properties */ +export type CalDavCalendar = Pick & { + displayName: string + description?: string + color?: string + resourcetype?: string[] + headers?: Record + fetchOptions?: RequestInit +} + +export type CalDavCalendarCreate = { + displayName: string + description?: string + color?: string + timezone?: string + components?: ('VEVENT' | 'VTODO' | 'VJOURNAL')[] +} + +export type CalDavCalendarUpdate = { + displayName?: string + description?: string + color?: string + timezone?: string +} + +// ============================================================================ +// Event Types (extends tsdav types) +// ============================================================================ + +/** Event type extending DAVCalendarObject with parsed ICS data */ +export type CalDavEvent = Pick & { + calendarUrl: string + data: IcsCalendar +} + +export type CalDavEventCreate = { + calendarUrl: string + event: IcsEvent +} + +export type CalDavEventUpdate = { + eventUrl: string + event: IcsEvent + etag?: string +} + +// ============================================================================ +// Time Range & Filters +// ============================================================================ + +export type TimeRange = { + start: string | Date + end: string | Date +} + +export type EventFilter = { + timeRange?: TimeRange + expand?: boolean + componentType?: 'VEVENT' | 'VTODO' | 'VJOURNAL' +} + +// ============================================================================ +// Sharing Types (CalDAV Scheduling & ACL) +// ============================================================================ + +export type SharePrivilege = 'read' | 'read-write' | 'read-write-noacl' | 'admin' + +export type ShareStatus = 'pending' | 'accepted' | 'declined' + +export type CalDavSharee = { + href: string // mailto:email or principal URL + displayName?: string + privilege: SharePrivilege + status?: ShareStatus +} + +export type CalDavShareInvite = { + calendarUrl: string + sharees: CalDavSharee[] + summary?: string + comment?: string +} + +export type CalDavShareResponse = { + success: boolean + sharees: CalDavSharee[] + errors?: { href: string; error: string }[] +} + +export type CalDavInvitation = { + uid: string + calendarUrl: string + ownerHref: string + ownerDisplayName?: string + summary?: string + privilege: SharePrivilege + status: ShareStatus +} + +// ============================================================================ +// Scheduling (iTIP) Types +// ============================================================================ + +export type SchedulingMethod = 'REQUEST' | 'REPLY' | 'CANCEL' | 'ADD' | 'REFRESH' | 'COUNTER' | 'DECLINECOUNTER' + +export type SchedulingRequest = { + method: SchedulingMethod + organizer: CalDavOrganizer + attendees: CalDavAttendee[] + event: IcsEvent +} + +export type SchedulingResponse = { + success: boolean + responses: { + recipient: string + status: 'delivered' | 'failed' | 'pending' + error?: string + }[] +} + +// ============================================================================ +// FreeBusy Types +// ============================================================================ + +export type FreeBusyPeriod = { + start: Date + end: Date + type: FreeBusyType +} + +export type FreeBusyRequest = { + attendees: string[] // email addresses + timeRange: TimeRange + organizer?: CalDavOrganizer +} + +export type FreeBusyResponse = { + attendee: string + periods: FreeBusyPeriod[] +} + +// ============================================================================ +// ACL Types +// ============================================================================ + +export type AclPrivilege = + | 'all' + | 'read' + | 'write' + | 'write-properties' + | 'write-content' + | 'unlock' + | 'bind' + | 'unbind' + | 'read-acl' + | 'write-acl' + | 'read-current-user-privilege-set' + +export type AclPrincipal = { + href?: string + all?: boolean + authenticated?: boolean + unauthenticated?: boolean + self?: boolean +} + +export type AclEntry = { + principal: AclPrincipal + privileges: AclPrivilege[] + grant: boolean + protected?: boolean + inherited?: string +} + +export type CalendarAcl = { + calendarUrl: string + entries: AclEntry[] + ownerHref?: string +} + +// ============================================================================ +// Sync Types +// ============================================================================ + +export type SyncReport = { + syncToken: string + changed: CalDavEvent[] + deleted: string[] // URLs of deleted events +} + +export type SyncOptions = { + syncToken?: string + syncLevel?: 1 | 'infinite' +} + +// ============================================================================ +// Principal Types +// ============================================================================ + +export type CalDavPrincipal = { + url: string + displayName?: string + email?: string + calendarHomeSet?: string + addressBookHomeSet?: string +} + +// ============================================================================ +// Response Types +// ============================================================================ + +export type CalDavResponse = { + success: boolean + data?: T + error?: string + status?: number +} + +export type CalDavMultiResponse = { + success: boolean + results: { url: string; data?: T; error?: string }[] +} diff --git a/src/frontend/apps/calendars/src/features/calendar/services/dav/types/calendar.ts b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/calendar.ts new file mode 100644 index 0000000..dfecdb9 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/calendar.ts @@ -0,0 +1,39 @@ +import type { IcsCalendar, IcsEvent, IcsRecurrenceId } from 'ts-ics' +import type { DAVCalendar } from 'tsdav' + +// TODO - CJ - 2025-07-03 - add generic +// TODO - CJ - 2025-07-03 - add options to support IcsEvent custom props +export type Calendar = DAVCalendar & { + // INFO - CJ - 2025-07-03 - Useful fields from 'DAVCalendar' + // ctag?: string + // description?: string; + // displayName?: string | Record; + // calendarColor?: string + // url: string + // fetchOptions?: RequestInit + headers?: Record + uid?: unknown +} + +export type CalendarObject = { + data: IcsCalendar + etag?: string + url: string + calendarUrl: string +} + +export type CalendarEvent = { + calendarUrl: string + event: IcsEvent +} + +export type EventUid = { + uid: string + recurrenceId?: IcsRecurrenceId +} + +export type DisplayedCalendarEvent = { + calendarUrl: string + event: IcsEvent + recurringEvent?: IcsEvent +} diff --git a/src/frontend/apps/calendars/src/features/calendar/services/dav/types/event-calendar.ts b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/event-calendar.ts new file mode 100644 index 0000000..5ea6380 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/event-calendar.ts @@ -0,0 +1,434 @@ +/** + * Types for EventCalendar adapter (vkurko/calendar) + * + * Based on: https://github.com/vkurko/calendar + * These types represent the EventCalendar library format + */ + +// ============================================================================ +// Duration Types +// ============================================================================ + +export type EventCalendarDuration = { + years?: number + months?: number + weeks?: number + days?: number + hours?: number + minutes?: number + seconds?: number +} + +export type EventCalendarDurationInput = + | EventCalendarDuration + | string // 'hh:mm:ss' or 'hh:mm' + | number // total seconds + +// ============================================================================ +// Event Types +// ============================================================================ + +export type EventCalendarEvent = { + id: string | number + resourceId?: string | number + resourceIds?: (string | number)[] + allDay?: boolean + start: Date | string + end?: Date | string + title?: EventCalendarContent + editable?: boolean + startEditable?: boolean + durationEditable?: boolean + display?: 'auto' | 'background' | 'ghost' | 'preview' | 'pointer' + backgroundColor?: string + textColor?: string + color?: string + classNames?: string | string[] + styles?: string | string[] + extendedProps?: Record +} + +export type EventCalendarEventInput = Omit & { + id?: string | number +} + +// ============================================================================ +// Resource Types +// ============================================================================ + +export type EventCalendarResource = { + id: string | number + title?: EventCalendarContent + eventBackgroundColor?: string + eventTextColor?: string + extendedProps?: Record + children?: EventCalendarResource[] +} + +// ============================================================================ +// View Types +// ============================================================================ + +export type EventCalendarView = + | 'dayGridMonth' + | 'dayGridWeek' + | 'dayGridDay' + | 'timeGridWeek' + | 'timeGridDay' + | 'listDay' + | 'listWeek' + | 'listMonth' + | 'listYear' + | 'resourceTimeGridDay' + | 'resourceTimeGridWeek' + | 'resourceTimelineDay' + | 'resourceTimelineWeek' + | 'resourceTimelineMonth' + +export type EventCalendarViewInfo = { + type: EventCalendarView + title: string + currentStart: Date + currentEnd: Date + activeStart: Date + activeEnd: Date +} + +// ============================================================================ +// Content Types +// ============================================================================ + +export type EventCalendarContent = + | string + | { html: string } + | { domNodes: Node[] } + +// ============================================================================ +// Callback/Handler Types +// ============================================================================ + +// Note: jsEvent uses Event (not MouseEvent) for compatibility with @event-calendar/core DomEvent type +export type EventCalendarEventClickInfo = { + el: HTMLElement + event: EventCalendarEvent + jsEvent: Event + view: EventCalendarViewInfo +} + +export type EventCalendarDateClickInfo = { + date: Date + dateStr: string + allDay: boolean + dayEl: HTMLElement + jsEvent: Event + view: EventCalendarViewInfo + resource?: EventCalendarResource +} + +export type EventCalendarEventDropInfo = { + event: EventCalendarEvent + oldEvent: EventCalendarEvent + oldResource?: EventCalendarResource + newResource?: EventCalendarResource + delta: EventCalendarDuration + revert: () => void + jsEvent: Event + view: EventCalendarViewInfo +} + +export type EventCalendarEventResizeInfo = { + event: EventCalendarEvent + oldEvent: EventCalendarEvent + startDelta: EventCalendarDuration + endDelta: EventCalendarDuration + revert: () => void + jsEvent: Event + view: EventCalendarViewInfo +} + +export type EventCalendarSelectInfo = { + start: Date + end: Date + startStr: string + endStr: string + allDay: boolean + jsEvent: Event + view: EventCalendarViewInfo + resource?: EventCalendarResource +} + +export type EventCalendarDatesSetInfo = { + start: Date + end: Date + startStr: string + endStr: string + view: EventCalendarViewInfo +} + +export type EventCalendarEventMountInfo = { + el: HTMLElement + event: EventCalendarEvent + view: EventCalendarViewInfo + timeText: string +} + +export type EventCalendarEventContentInfo = { + event: EventCalendarEvent + view: EventCalendarViewInfo + timeText: string +} + +// ============================================================================ +// Options Types +// ============================================================================ + +export type EventCalendarOptions = { + // View configuration + view?: EventCalendarView + views?: Record + headerToolbar?: EventCalendarToolbar + footerToolbar?: EventCalendarToolbar + + // Date configuration + date?: Date | string + firstDay?: 0 | 1 | 2 | 3 | 4 | 5 | 6 + hiddenDays?: number[] + + // Time configuration + slotMinTime?: EventCalendarDurationInput + slotMaxTime?: EventCalendarDurationInput + slotDuration?: EventCalendarDurationInput + slotLabelInterval?: EventCalendarDurationInput + slotHeight?: number + scrollTime?: EventCalendarDurationInput + + // Display configuration + allDaySlot?: boolean + allDayContent?: EventCalendarContent + dayMaxEvents?: boolean | number + nowIndicator?: boolean + locale?: string + + // Event configuration + events?: EventCalendarEvent[] | EventCalendarEventFetcher + eventSources?: EventCalendarEventSource[] + eventColor?: string + eventBackgroundColor?: string + eventTextColor?: string + eventClassNames?: string | string[] | ((info: EventCalendarEventMountInfo) => string | string[]) + eventContent?: EventCalendarContent | ((info: EventCalendarEventContentInfo) => EventCalendarContent) + displayEventEnd?: boolean + + // Resource configuration + resources?: EventCalendarResource[] | EventCalendarResourceFetcher + datesAboveResources?: boolean + filterResourcesWithEvents?: boolean + + // Interaction configuration + editable?: boolean + selectable?: boolean + dragScroll?: boolean + eventStartEditable?: boolean + eventDurationEditable?: boolean + eventDragMinDistance?: number + longPressDelay?: number + + // Callbacks + dateClick?: (info: EventCalendarDateClickInfo) => void + eventClick?: (info: EventCalendarEventClickInfo) => void + eventDrop?: (info: EventCalendarEventDropInfo) => void + eventResize?: (info: EventCalendarEventResizeInfo) => void + select?: (info: EventCalendarSelectInfo) => void + datesSet?: (info: EventCalendarDatesSetInfo) => void + eventDidMount?: (info: EventCalendarEventMountInfo) => void + + // Button text + buttonText?: { + today?: string + dayGridMonth?: string + dayGridWeek?: string + dayGridDay?: string + listDay?: string + listWeek?: string + listMonth?: string + listYear?: string + resourceTimeGridDay?: string + resourceTimeGridWeek?: string + resourceTimelineDay?: string + resourceTimelineWeek?: string + resourceTimelineMonth?: string + timeGridDay?: string + timeGridWeek?: string + } + + // Theme + theme?: EventCalendarTheme +} + +export type EventCalendarViewOptions = Partial & { + titleFormat?: ((start: Date, end: Date) => string) | Intl.DateTimeFormatOptions + duration?: EventCalendarDurationInput + dayHeaderFormat?: Intl.DateTimeFormatOptions + slotLabelFormat?: Intl.DateTimeFormatOptions +} + +export type EventCalendarToolbar = { + start?: string + center?: string + end?: string +} + +export type EventCalendarTheme = { + allDay?: string + active?: string + bgEvent?: string + bgEvents?: string + body?: string + button?: string + buttonGroup?: string + calendar?: string + compact?: string + content?: string + day?: string + dayFoot?: string + dayHead?: string + daySide?: string + days?: string + draggable?: string + dragging?: string + event?: string + eventBody?: string + eventTag?: string + eventTime?: string + eventTitle?: string + events?: string + extra?: string + ghost?: string + handle?: string + header?: string + hiddenScroll?: string + hiddenTimes?: string + highlight?: string + icon?: string + line?: string + lines?: string + list?: string + month?: string + noEvents?: string + nowIndicator?: string + otherMonth?: string + pointer?: string + popup?: string + preview?: string + resizer?: string + resource?: string + resourceTitle?: string + sidebar?: string + today?: string + time?: string + title?: string + toolbar?: string + view?: string + week?: string + withScroll?: string +} + +// ============================================================================ +// Event Source Types +// ============================================================================ + +export type EventCalendarEventSource = { + events?: EventCalendarEvent[] | EventCalendarEventFetcher + url?: string + method?: string + extraParams?: Record | (() => Record) + eventDataTransform?: (event: unknown) => EventCalendarEventInput + backgroundColor?: string + textColor?: string + color?: string + classNames?: string | string[] + editable?: boolean +} + +export type EventCalendarFetchInfo = { + start: Date + end: Date + startStr: string + endStr: string +} + +export type EventCalendarEventFetcher = ( + fetchInfo: EventCalendarFetchInfo, + successCallback: (events: EventCalendarEventInput[]) => void, + failureCallback: (error: Error) => void +) => void | Promise + +export type EventCalendarResourceFetcher = ( + fetchInfo: EventCalendarFetchInfo, + successCallback: (resources: EventCalendarResource[]) => void, + failureCallback: (error: Error) => void +) => void | Promise + +// ============================================================================ +// Calendar Instance Types +// ============================================================================ + +export type EventCalendarInstance = { + // Navigation + getDate(): Date + setOption(name: string, value: unknown): void + getOption(name: string): unknown + getView(): EventCalendarViewInfo + prev(): void + next(): void + today(): void + gotoDate(date: Date | string): void + + // Events + getEvents(): EventCalendarEvent[] + getEventById(id: string | number): EventCalendarEvent | null + addEvent(event: EventCalendarEventInput): EventCalendarEvent + updateEvent(event: EventCalendarEvent): void + removeEventById(id: string | number): void + refetchEvents(): void + + // Resources + getResources(): EventCalendarResource[] + getResourceById(id: string | number): EventCalendarResource | null + addResource(resource: EventCalendarResource): void + refetchResources(): void + + // Rendering + unselect(): void + destroy(): void +} + +// ============================================================================ +// Conversion Options +// ============================================================================ + +export type CalDavToEventCalendarOptions = { + /** Default color for events without a color */ + defaultEventColor?: string + /** Default text color for events */ + defaultTextColor?: string + /** Whether to include recurring event instances */ + includeRecurringInstances?: boolean + /** Custom ID generator for events */ + eventIdGenerator?: (event: unknown, calendarUrl: string) => string | number + /** Custom extended props extractor */ + extendedPropsExtractor?: (event: unknown) => Record + /** Map calendar URLs to colors */ + calendarColors?: Map +} + +export type EventCalendarToCalDavOptions = { + /** Default calendar URL for new events */ + defaultCalendarUrl?: string + /** Default timezone for events */ + defaultTimezone?: string + /** Custom UID generator */ + uidGenerator?: () => string + /** Preserve extended props in ICS custom properties */ + preserveExtendedProps?: boolean +} diff --git a/src/frontend/apps/calendars/src/features/calendar/services/dav/types/options.ts b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/options.ts new file mode 100644 index 0000000..2449fb5 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/services/dav/types/options.ts @@ -0,0 +1,161 @@ +import type { IcsEvent } from 'ts-ics' +import type { Calendar, CalendarEvent } from './calendar' +import type { AddressBookVCard, Contact, VCard } from './addressbook' +import { attendeeRoleTypes, availableViews } from '../constants' + + +export type RecursivePartial = { + [P in keyof T]?: RecursivePartial +} + +export type DomEvent = GlobalEventHandlersEventMap[keyof GlobalEventHandlersEventMap] + +export type ServerSource = { + serverUrl: string + headers?: Record + fetchOptions?: RequestInit +} + +export type CalendarSource = { + calendarUrl: string + calendarUid?: unknown + headers?: Record + fetchOptions?: RequestInit +} + +export type AddressBookSource = { + addressBookUrl: string + addressBookUid?: unknown + headers?: Record + fetchOptions?: RequestInit +} + +export type VCardProvider = { + fetchContacts: () => Promise +} + +export type View = typeof availableViews[number] +export type IcsAttendeeRoleType = typeof attendeeRoleTypes[number] + + +export type SelectedCalendar = { + url: string + selected: boolean +} + +export type SelectCalendarCallback = (calendar: SelectedCalendar) => void +export type SelectCalendarsClickInfo = { + jsEvent: DomEvent + calendars: Calendar[] + selectedCalendars: Set + handleSelect: SelectCalendarCallback +} +export type SelectCalendarHandlers = { + onClickSelectCalendars: (info: SelectCalendarsClickInfo) => void, +} + + +export type EventBodyInfo = { + calendar: Calendar + vCards: AddressBookVCard[] + event: IcsEvent + view: View + userContact?: Contact +} +export type BodyHandlers = { + getEventBody: (info: EventBodyInfo) => Node[] +} + +export type EventEditCallback = (event: CalendarEvent) => Promise +export type EventEditCreateInfo = { + jsEvent: DomEvent + userContact?: Contact, + event: IcsEvent + calendars: Calendar[] + vCards: AddressBookVCard[] + handleCreate: EventEditCallback +} +export type EventEditSelectInfo = { + jsEvent: DomEvent + userContact?: Contact, + calendarUrl: string + event: IcsEvent + recurringEvent?: IcsEvent + calendars: Calendar[] + vCards: AddressBookVCard[] + handleUpdate: EventEditCallback + handleDelete: EventEditCallback +} +export type EventEditMoveResizeInfo = { + jsEvent: DomEvent + calendarUrl: string + userContact?: Contact, + event: IcsEvent + recurringEvent?: IcsEvent, + start: Date, + end: Date, + handleUpdate: EventEditCallback +} +export type EventEditDeleteInfo = { + jsEvent: DomEvent + userContact?: Contact, + calendarUrl: string + event: IcsEvent + recurringEvent?: IcsEvent + handleDelete: EventEditCallback +} +export type EventEditHandlers = { + onCreateEvent: (info: EventEditCreateInfo) => void, + onSelectEvent: (info: EventEditSelectInfo) => void, + onMoveResizeEvent: (info: EventEditMoveResizeInfo) => void, + onDeleteEvent: (info: EventEditDeleteInfo) => void, +} + +export type EventChangeInfo = { + calendarUrl: string + event: IcsEvent + ical: string +} + +export type EventChangeHandlers = { + onEventCreated?: (info: EventChangeInfo) => void + onEventUpdated?: (info: EventChangeInfo) => void + onEventDeleted?: (info: EventChangeInfo) => void +} + +export type CalendarElementOptions = { + view?: View + views?: View[] + locale?: string + date?: Date + editable?: boolean +} + +export type CalendarClientOptions = { + userContact?: Contact +} + +export type DefaultComponentsOptions = { + hideVCardEmails?: boolean +} + +export type CalendarOptions = + // NOTE - CJ - 2025-07-03 + // May define individual options or not + CalendarElementOptions + // May define individual options or not + & CalendarClientOptions + // Must define all handlers or none + & (SelectCalendarHandlers | Record) + // Must define all handlers or none + & (EventEditHandlers | Record) + // May define individual handlers or not + & EventChangeHandlers + // May define handlers or not, but they will be assigned a default value if they are not + & Partial + & DefaultComponentsOptions + +export type CalendarResponse = { + response: Response + ical: string +} diff --git a/src/frontend/apps/calendars/types.d.ts b/src/frontend/apps/calendars/types.d.ts new file mode 100644 index 0000000..7135b60 --- /dev/null +++ b/src/frontend/apps/calendars/types.d.ts @@ -0,0 +1,45 @@ +declare module "mustache" { + const Mustache: { + render: (template: string, view: unknown) => string; + }; + export default Mustache; +} + +declare module "email-addresses" { + interface ParsedAddress { + type: "mailbox" | "group"; + name?: string; + address?: string; + local?: string; + domain?: string; + } + export function parseOneAddress(input: string): ParsedAddress | null; +} + +declare module "@event-calendar/core" { + export interface Calendar { + setOption: (name: string, value: unknown) => void; + getOption: (name: string) => unknown; + refetchEvents: () => void; + addEvent: (event: unknown) => void; + updateEvent: (event: unknown) => void; + removeEventById: (id: string) => void; + unselect: () => void; + $destroy?: () => void; + } + + export function createCalendar( + el: HTMLElement, + plugins: unknown[], + options: Record + ): Calendar; + + export const TimeGrid: unknown; + export const DayGrid: unknown; + export const List: unknown; + export const Interaction: unknown; + export const ResourceTimeGrid: unknown; + export const ResourceTimeline: unknown; +} + +declare module "@event-calendar/core/index.css";