04core concepts
Events
CalEvent: the discriminated union on allDay, real instants, colors, attendees, and every optional field.
A CalEvent is a discriminated union on allDay. Timed events carry
offset-qualified instants; all-day events carry date-only instants with an
exclusive end — the RFC 5545 conventions, so events round-trip to real
calendars without translation.
The two shapes
The union means the compiler enforces the difference: a timed event cannot
carry date-only strings, and an all-day event cannot carry clock times. end
on an all-day event is exclusive — the same convention RFC 5545 uses for a
date-only DTEND — so a one-day event ends on the next date.
Instants are strings, not Dates, because a Date cannot say which zone it
was authored in. Helpers like instantAt, parseInstant, instantPlus and
toDateOnlyString are exported for building them.
Color is optional on purpose
color is one of five palette keys —
"blue" | "violet" | "emerald" | "amber" | "rose" — and an event with no
color of its own takes its calendar's (resolveEventColor). An event that
names a color keeps it wherever it moves. That absence-means-inherit rule is
how a source calendar's color tints everything nobody colored by hand;
DEFAULT_EVENT_COLOR is what an event with neither is drawn in.
Every optional field
| prop | type · description |
|---|---|
description? | stringFree text, shown in the event panel. |
location? | stringA room, an address, "Zoom". |
meetingUrl? | stringVideo-call link; rendered as a Join affordance. |
attendees? | Attendee[]Invitees in insertion order; |
organizer? | stringRFC 5545 |
reminders? | Reminder[]Alerts as offsets from the start. kloq stores them; delivery is the host's job. |
busy? | booleanFree/busy. Absent means busy — |
readOnly? | booleanThe event can't be edited, moved, resized or deleted from the UI. |
calendarId? | stringThe source calendar the event belongs to. |
rrule? | stringRFC 5545 |
timeZone? | stringThe zone the event was authored in — see the time-zones page. |
Attendees and RSVP
Pass currentUserEmail on <Kloq> and the event panel grows an RSVP control
whenever that address is actually on the invite; conflict detection starts
answering "does this clash for me" instead of "do these two overlap"; and
showDeclinedEvents={false} filters events you have declined out of every
surface — still in the store, still findable in ⌘K search, just not on your
calendar.
CalEvent vs PlacedEvent
Slots never receive a raw CalEvent — they receive a PlacedEvent: the
event projected into the current view's column/minute space, carrying a
branded PlacementId. For a recurring event the two differ (one stored
master, many placed instances); masterIdOf is the bridge back to the store
id. Segment predicates continuesBefore / continuesAfter tell a custom
block to square off the cut edge of a cross-midnight event.