Installation
Section titled “Installation”pnpm dlx shadcn@latest add pxl-ui/registry/schemas/gcalendar
Install the following dependencies:
pnpm add zod
Copy and paste the following code into your project.
1import z from "zod";2
3const CalendarAccessRoleSchema = z4 .union([5 z6 .literal("freeBusyReader")7 .describe("Provides read access to free/busy information."),8 z9 .literal("reader")10 .describe(11 "Provides read access to the calendar. Private events will appear to users with reader access, but event details will be hidden.",12 ),13 z14 .literal("writer")15 .describe(16 "Provides read and write access to the calendar. Private events will appear to users with writer access, and event details will be visible.",17 ),18 z19 .literal("owner")20 .describe(21 "Provides manager access to the calendar. This role has all of the permissions of the writer role with the additional ability to see and modify access levels of other users.",22 ),23 ])24 .describe(25 "The effective access role that the authenticated user has on the calendar. Read-only. Important: the owner role is different from the calendar's data owner. A calendar has a single data owner, but can have multiple users with owner role.",26 );27
28const AttendeeResponseStatusSchema = z29 .union([30 z31 .literal("needsAction")32 .describe(33 "The attendee has not responded to the invitation (recommended for new events)",34 ),35 z.literal("declined").describe("The attendee has declined the invitation."),36 z37 .literal("tentative")38 .describe("The attendee has tentatively accepted the invitation."),39 z40 .literal("accepted")41 .describe(42 "The attendee has accepted the invitation. Warning: If you add an event using the values declined, tentative, or accepted, attendees with the 'Add invitations to my calendar' setting set to 'When I respond to invitation in email' or 'Only if the sender is known' might have their response reset to needsAction and won't see an event in their calendar unless they change their response in the event invitation email. Furthermore, if more than 200 guests are invited to the event, response status is not propagated to the guests.",43 ),44 ])45 .describe("The attendee's response status.");46
47const AttendeeSchema = z48 .object({49 displayName: z50 .string()51 .nullish()52 .describe("The attendee's name, if available. Optional."),53 email: z54 .email()55 .nullish()56 .describe(57 "The attendee's email address, if available. This field must be present when adding an attendee. It must be a valid email address as per RFC5322. * Required when adding an attendee.",58 ),59 id: z60 .string()61 .nullish()62 .describe("The attendee's Profile ID, if available."),63 optional: z64 .boolean()65 .nullish()66 .describe(67 "Whether this is an optional attendee. Optional. The default is False.",68 ),69 organizer: z70 .boolean()71 .nullish()72 .describe(73 "Whether the attendee is the organizer of the event. Read-only. The default is False.",74 ),75 responseStatus: AttendeeResponseStatusSchema.nullish(),76 })77 .describe(78 "The attendees of the event. See the Events with attendees guide for more information on scheduling events with other calendar users. Service accounts need to use domain-wide delegation of authority to populate the attendee list.",79 );80
81const DateTimeSchema = z.object({82 date: z83 .string()84 .nullish()85 .describe(86 "The date, in the format 'yyyy-mm-dd', if this is an all-day event.",87 ),88 dateTime: z89 .string()90 .nullish()91 .describe(92 "The time, as a combined date-time value (formatted according to RFC3339). A time zone offset is required unless a time zone is explicitly specified in timeZone.",93 ),94 timeZone: z95 .string()96 .nullish()97 .describe(98 "The time zone in which the time is specified. (Formatted as an IANA Time Zone Database name, e.g. 'Europe/Zurich'.) For recurring events this field is required and specifies the time zone in which the recurrence is expanded. For single events this field is optional and indicates a custom time zone for the event start/end.",99 ),100});101
102const ReminderSchema = z.object({103 method: z104 .union([105 z.literal("email").describe("Reminders are sent via email."),106 z.literal("popup").describe("Reminders are sent via a UI popup."),107 ])108 .nullish()109 .describe("The method used by this reminder."),110 minutes: z111 .number()112 .nullish()113 .describe(114 "Number of minutes before the start of the event when the reminder should trigger. Valid values are between 0 and 40320 (4 weeks in minutes).",115 ),116});117
118const EventStatusSchema = z.union([119 z120 .literal("confirmed")121 .describe("The event is confirmed. This is the default status."),122 z.literal("tentative").describe("The event is tentatively confirmed."),123 z124 .literal("cancelled")125 .describe(`The event is cancelled (deleted). The list method returns cancelled events only on incremental sync (when syncToken or updatedMin are specified) or if the showDeleted flag is set to true. The get method always returns them.126 A cancelled status represents two different states depending on the event type:127 - Cancelled exceptions of an uncancelled recurring event indicate that this instance should no longer be presented to the user. Clients should store these events for the lifetime of the parent recurring event.128 Cancelled exceptions are only guaranteed to have values for the id, recurringEventId and originalStartTime fields populated. The other fields might be empty.129 - All other cancelled events represent deleted events. Clients should remove their locally synced copies. Such cancelled events will eventually disappear, so do not rely on them being available indefinitely.130 Deleted events are only guaranteed to have the id field populated. On the organizer's calendar, cancelled events continue to expose event details (summary, location, etc.) so that they can be restored (undeleted). Similarly, the events to which the user was invited and that they manually removed continue to provide details. However, incremental sync requests with showDeleted set to false will not return these details.131 If an event changes its organizer (for example via the move operation) and the original organizer is not on the attendee list, it will leave behind a cancelled event where only the id field is guaranteed to be populated.`),132]);133
134const CalendarSchema = z135 .object({136 accessRole: CalendarAccessRoleSchema.nullish(),137 backgroundColor: z138 .string()139 .nullish()140 .describe(141 "The main color of the calendar in the hexadecimal format '#0088aa'. This property supersedes the index-based colorId property. To set or change this property, you need to specify colorRgbFormat=true in the parameters of the insert, update and patch methods. Optional.",142 ),143 colorId: z144 .string()145 .nullish()146 .describe(147 "The color of the calendar. This is an ID referring to an entry in the calendar section of the colors definition (see the colors endpoint). This property is superseded by the backgroundColor and foregroundColor properties and can be ignored when using these properties. Optional.",148 ),149 defaultReminders: z150 .array(ReminderSchema)151 .optional()152 .describe(153 "The default reminders that the authenticated user has for this calendar.",154 ),155 deleted: z156 .boolean()157 .nullish()158 .describe(159 "Whether this calendar list entry has been deleted from the calendar list. Read-only. Optional. The default is False.",160 ),161 description: z162 .string()163 .nullish()164 .describe("Description of the calendar. Optional. Read-only."),165 foregroundColor: z166 .string()167 .nullish()168 .describe(169 "The foreground color of the calendar in the hexadecimal format '#ffffff'. This property supersedes the index-based colorId property. To set or change this property, you need to specify colorRgbFormat=true in the parameters of the insert, update and patch methods. Optional.",170 ),171 hidden: z172 .boolean()173 .nullish()174 .describe(175 "Whether the calendar has been hidden from the list. Optional. The attribute is only returned when the calendar is hidden, in which case the value is true.",176 ),177 id: z.string().nullish().describe("Identifier of the calendar."),178 primary: z179 .boolean()180 .nullish()181 .describe(182 "Whether the calendar is the primary calendar of the authenticated user. Read-only. Optional. The default is False.",183 ),184 selected: z185 .boolean()186 .nullish()187 .describe(188 "Whether the calendar content shows up in the calendar UI. Optional. The default is False.",189 ),190 summary: z.string().nullish().describe("Title of the calendar. Read-only."),191 summaryOverride: z192 .string()193 .nullish()194 .describe(195 "The summary that the authenticated user has set for this calendar. Optional.",196 ),197 })198 .describe("from googleapis calendar_v3.Schema$CalendarListEntry");199
200const EventSchema = z.object({201 attendees: z.array(AttendeeSchema).optional(),202 colorId: z203 .string()204 .nullish()205 .describe(206 "The color of the event. This is an ID referring to an entry in the event section of the colors definition (see the colors endpoint). Optional",207 ),208 description: z209 .string()210 .nullish()211 .describe("Description of the event. Can contain HTML. Optional."),212 end: DateTimeSchema.optional().describe(213 "The (exclusive) end time of the event. For a recurring event, this is the end time of the first instance.",214 ),215 htmlLink: z216 .string()217 .nullish()218 .describe(219 "An absolute link to this event in the Google Calendar Web UI. Read-only.",220 ),221 iCalUID: z222 .string()223 .nullish()224 .describe(225 "Event unique identifier as defined in RFC5545. It is used to uniquely identify events accross calendaring systems and must be supplied when importing events via the import method. * Note that the iCalUID and the id are not identical and only one of them should be supplied at event creation time. One difference in their semantics is that in recurring events, all occurrences of one event have different ids while they all share the same iCalUIDs. To retrieve an event using its iCalUID, call the events.list method using the iCalUID parameter. To retrieve an event using its id, call the events.get method.",226 ),227 id: z228 .string()229 .nullish()230 .describe(`Opaque identifier of the event. When creating new single or recurring events, you can specify their IDs. Provided IDs must follow these rules:231 - characters allowed in the ID are those used in base32hex encoding, i.e. lowercase letters a-v and digits 0-9, see section 3.1.2 in RFC2938232 - the length of the ID must be between 5 and 1024 characters233 - the ID must be unique per calendar Due to the globally distributed nature of the system, we cannot guarantee that ID collisions will be detected at event creation time. To minimize the risk of collisions we recommend using an established UUID algorithm such as one described in RFC4122.234 If you do not specify an ID, it will be automatically generated by the server.235 Note that the icalUID and the id are not identical and only one of them should be supplied at event creation time. One difference in their semantics is that in recurring events, all occurrences of one event have different ids while they all share the same icalUIDs.236 `),237 recurrence: z238 .array(z.string())239 .nullish()240 .describe(241 "List of RRULE, EXRULE, RDATE and EXDATE lines for a recurring event, as specified in RFC5545. Note that DTSTART and DTEND lines are not allowed in this field; event start and end times are specified in the start and end fields. This field is omitted for single events or instances of recurring events.",242 ),243 recurringEventId: z244 .string()245 .nullish()246 .describe(247 "For an instance of a recurring event, this is the id of the recurring event to which this instance belongs. Immutable.",248 ),249 reminders: z250 .object({251 overrides: z.array(ReminderSchema).optional(),252 useDefault: z.boolean().optional(),253 })254 .nullish()255 .describe(256 "Information about the event's reminders for the authenticated user. Note that changing reminders does not also change the updated property of the enclosing event.",257 ),258 start: DateTimeSchema.optional().describe(259 "The (inclusive) start time of the event. For a recurring event, this is the start time of the first instance.",260 ),261 status: EventStatusSchema.nullish(),262 summary: z.string().nullish().describe("Title of the event."),263});264
265const GCalendarSchemas = {266 Attendee: AttendeeSchema,267 AttendeeResponseStatus: AttendeeResponseStatusSchema,268 Calendar: CalendarSchema,269 CalendarAccessRole: CalendarAccessRoleSchema,270 DateTime: DateTimeSchema,271 Event: EventSchema,272 EventStatus: EventStatusSchema,273};274
275type Attendee = z.infer<typeof AttendeeSchema>;276type AttendeeResponseStatus = z.infer<typeof AttendeeResponseStatusSchema>;277type Calendar = z.infer<typeof CalendarSchema>;278type CalendarAccessRole = z.infer<typeof CalendarAccessRoleSchema>;279type DateTime = z.infer<typeof DateTimeSchema>;280type Event = z.infer<typeof EventSchema>;281type EventStatus = z.infer<typeof EventStatusSchema>;282
283declare namespace GCalendar {284 export type {285 Attendee,286 AttendeeResponseStatus,287 Calendar,288 CalendarAccessRole,289 DateTime,290 Event,291 EventStatus,292 };293}294
295export type {296 Attendee,297 AttendeeResponseStatus,298 Calendar,299 CalendarAccessRole,300 DateTime,301 Event,302 EventStatus,303 GCalendar,304};305export {306 AttendeeResponseStatusSchema,307 AttendeeSchema,308 CalendarAccessRoleSchema,309 CalendarSchema,310 DateTimeSchema,311 EventSchema,312 EventStatusSchema,313 GCalendarSchemas,314};315export default GCalendarSchemas;Update the import paths to match your project setup.
import type { GCalendar } from "@/lib/schemas/pxl/gcalendar";const task: GCalendar.Event = { ... }API Reference
Section titled “API Reference”Calendar
Section titled “Calendar”A Google Calendar.
A Google Calendar event.