🏷️(front) add DAV service type definitions
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 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
import type { DAVAddressBook } from 'tsdav'
|
||||||
|
import ICAL from 'ical.js'
|
||||||
|
|
||||||
|
export type AddressBook = DAVAddressBook & {
|
||||||
|
headers?: Record<string, string>
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -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<string, string>
|
||||||
|
fetchOptions?: RequestInit
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CalDavAccount = {
|
||||||
|
serverUrl: string
|
||||||
|
rootUrl?: string
|
||||||
|
principalUrl?: string
|
||||||
|
homeUrl?: string
|
||||||
|
headers?: Record<string, string>
|
||||||
|
fetchOptions?: RequestInit
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Calendar Types (extends tsdav types)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/** Calendar type extending DAVCalendar with additional properties */
|
||||||
|
export type CalDavCalendar = Pick<DAVCalendar, 'url' | 'ctag' | 'syncToken' | 'components' | 'timezone'> & {
|
||||||
|
displayName: string
|
||||||
|
description?: string
|
||||||
|
color?: string
|
||||||
|
resourcetype?: string[]
|
||||||
|
headers?: Record<string, string>
|
||||||
|
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<DAVCalendarObject, 'url' | 'etag'> & {
|
||||||
|
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<T = void> = {
|
||||||
|
success: boolean
|
||||||
|
data?: T
|
||||||
|
error?: string
|
||||||
|
status?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CalDavMultiResponse<T> = {
|
||||||
|
success: boolean
|
||||||
|
results: { url: string; data?: T; error?: string }[]
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import type { IcsCalendar, IcsEvent, IcsRecurrenceId } from 'ts-ics'
|
||||||
|
import type { DAVCalendar } from 'tsdav'
|
||||||
|
|
||||||
|
// TODO - CJ - 2025-07-03 - add <TCalendarUid = any> 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<string, unknown>;
|
||||||
|
// calendarColor?: string
|
||||||
|
// url: string
|
||||||
|
// fetchOptions?: RequestInit
|
||||||
|
headers?: Record<string, string>
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -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<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type EventCalendarEventInput = Omit<EventCalendarEvent, 'id'> & {
|
||||||
|
id?: string | number
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Resource Types
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export type EventCalendarResource = {
|
||||||
|
id: string | number
|
||||||
|
title?: EventCalendarContent
|
||||||
|
eventBackgroundColor?: string
|
||||||
|
eventTextColor?: string
|
||||||
|
extendedProps?: Record<string, unknown>
|
||||||
|
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<string, EventCalendarViewOptions>
|
||||||
|
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<EventCalendarOptions> & {
|
||||||
|
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<string, unknown> | (() => Record<string, unknown>)
|
||||||
|
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<EventCalendarEventInput[]>
|
||||||
|
|
||||||
|
export type EventCalendarResourceFetcher = (
|
||||||
|
fetchInfo: EventCalendarFetchInfo,
|
||||||
|
successCallback: (resources: EventCalendarResource[]) => void,
|
||||||
|
failureCallback: (error: Error) => void
|
||||||
|
) => void | Promise<EventCalendarResource[]>
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 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<string, unknown>
|
||||||
|
/** Map calendar URLs to colors */
|
||||||
|
calendarColors?: Map<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -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<T> = {
|
||||||
|
[P in keyof T]?: RecursivePartial<T[P]>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DomEvent = GlobalEventHandlersEventMap[keyof GlobalEventHandlersEventMap]
|
||||||
|
|
||||||
|
export type ServerSource = {
|
||||||
|
serverUrl: string
|
||||||
|
headers?: Record<string, string>
|
||||||
|
fetchOptions?: RequestInit
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CalendarSource = {
|
||||||
|
calendarUrl: string
|
||||||
|
calendarUid?: unknown
|
||||||
|
headers?: Record<string, string>
|
||||||
|
fetchOptions?: RequestInit
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AddressBookSource = {
|
||||||
|
addressBookUrl: string
|
||||||
|
addressBookUid?: unknown
|
||||||
|
headers?: Record<string, string>
|
||||||
|
fetchOptions?: RequestInit
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VCardProvider = {
|
||||||
|
fetchContacts: () => Promise<VCard[]>
|
||||||
|
}
|
||||||
|
|
||||||
|
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<string>
|
||||||
|
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<Response>
|
||||||
|
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<never, never>)
|
||||||
|
// Must define all handlers or none
|
||||||
|
& (EventEditHandlers | Record<never, never>)
|
||||||
|
// 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<BodyHandlers>
|
||||||
|
& DefaultComponentsOptions
|
||||||
|
|
||||||
|
export type CalendarResponse = {
|
||||||
|
response: Response
|
||||||
|
ical: string
|
||||||
|
}
|
||||||
45
src/frontend/apps/calendars/types.d.ts
vendored
Normal file
45
src/frontend/apps/calendars/types.d.ts
vendored
Normal file
@@ -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<string, unknown>
|
||||||
|
): 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";
|
||||||
Reference in New Issue
Block a user