Working with Events
Events are the core data structure in Day Flow. Learn how to create, update, delete, and manage calendar events.
Event Interface
The library uses the Temporal API for all date/time handling. Events support three Temporal types:
- PlainDate: For all-day events (no time)
- PlainDateTime: For local events (date + time, no timezone) ✨ Recommended for most use cases
- ZonedDateTime: For timezone-aware events (international meetings, flights, etc.)
import { Temporal } from 'temporal-polyfill';
import { Event } from '@dayflow/core';| Property | Type | Description | Required |
|---|---|---|---|
id | string | Unique identifier for the event | ✅ Yes |
title | string | Event title displayed in the calendar | ✅ Yes |
start | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime | Event start date/time. Use PlainDate for all-day, PlainDateTime for local, ZonedDateTime for timezone-aware | ✅ Yes |
end | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime | Event end date/time | ✅ Yes |
description | string | Optional event description or notes | ❌ No |
allDay | boolean | Whether this is an all-day event (default: false) | ❌ No |
calendarId | string | Calendar type reference for multi-calendar support | ❌ No |
meta | Record<string, any> | Additional custom metadata (location, attendees, custom fields, etc.) | ❌ No |
day | number | Internal field: week day index (0-6), auto-calculated by the system | ❌ No |
Creating Events
Simple Event Creation (Recommended)
Use the createEvent() helper for most use cases:
import {
createEvent,
createAllDayEvent,
createTimedEvent,
} from '@dayflow/core';
import '@dayflow/core/dist/styles.css';
// Local timed event (no timezone complexity)
const meeting = createEvent({
id: '1',
title: 'Team Meeting',
start: new Date(2024, 9, 15, 10, 0), // October 15, 2024, 10:00 AM
end: new Date(2024, 9, 15, 11, 0), // October 15, 2024, 11:00 AM
});
// All-day event
const holiday = createAllDayEvent('2', 'Conference', new Date(2024, 9, 20));
// Quick timed event
const lunch = createTimedEvent(
'3',
'Lunch Break',
new Date(2024, 9, 15, 12, 0), // 12:00 PM
new Date(2024, 9, 15, 13, 0) // 1:00 PM
);Advanced: Using Temporal API Directly
For more control, use Temporal API directly:
import { Temporal } from 'temporal-polyfill';
import { Event } from '@dayflow/core';
// Local event with PlainDateTime (recommended)
const localEvent: Event = {
id: '1',
title: 'Team Meeting',
start: Temporal.PlainDateTime.from({
year: 2024,
month: 10,
day: 15,
hour: 10,
minute: 0,
}),
end: Temporal.PlainDateTime.from({
year: 2024,
month: 10,
day: 15,
hour: 11,
minute: 0,
}),
};
// All-day event with PlainDate
const allDayEvent: Event = {
id: '2',
title: 'Conference',
start: Temporal.PlainDate.from('2024-10-20'),
end: Temporal.PlainDate.from('2024-10-22'),
allDay: true,
};
// Timezone-aware event with ZonedDateTime
const timezoneEvent: Event = {
id: '3',
title: 'International Call',
start: Temporal.ZonedDateTime.from('2024-10-16T14:00:00[America/New_York]'),
end: Temporal.ZonedDateTime.from('2024-10-16T15:00:00[America/New_York]'),
};Event with Metadata
import { createEvent } from '@dayflow/core';
const event = createEvent({
id: '3',
title: 'Client Call',
description: 'Discuss Q4 roadmap',
start: new Date(2024, 9, 16, 14, 0),
end: new Date(2024, 9, 16, 15, 0),
meta: {
location: 'Zoom',
attendees: ['john@example.com', 'jane@example.com'],
recurring: false,
},
});Managing Events
Adding Events
// Add a single event
calendar.addEvent(event);
// Add multiple events during initialization
const calendar = useCalendarApp({
views: [createMonthView()],
events: [event1, event2, event3],
});Updating Events
// Update an event
calendar.updateEvent('event-id', {
title: 'Updated Meeting Title',
start: new Date(2024, 9, 15, 11, 0),
end: new Date(2024, 9, 15, 12, 0),
});
// Update with pending state (for resize operations)
calendar.updateEvent('event-id', updatedEvent, true);Deleting Events
// Delete an event by ID
calendar.deleteEvent('event-id');Getting Events
// Get all events
const events = calendar.getEvents();
// Get current events from state
const { events } = calendar;Event Callbacks
Day Flow provides callbacks to handle event lifecycle:
import { useCalendarApp, createMonthView, Event } from '@dayflow/core';
const calendar = useCalendarApp({
views: [createMonthView()],
events: initialEvents,
callbacks: {
onEventCreate: (event: Event) => {
console.log('New event created:', event);
// Sync with backend
api.createEvent(event);
},
onEventUpdate: (event: Event) => {
console.log('Event updated:', event);
// Sync with backend
api.updateEvent(event);
},
onEventDelete: (eventId: string) => {
console.log('Event deleted:', eventId);
// Sync with backend
api.deleteEvent(eventId);
},
},
});Event State Management
Using React State
import { useState } from 'react';
import {
useCalendarApp,
DayFlowCalendar,
createMonthView,
Event,
} from '@dayflow/core';
function MyCalendar() {
const [events, setEvents] = useState<Event[]>([]);
const calendar = useCalendarApp({
views: [createMonthView()],
events,
callbacks: {
onEventCreate: (event: Event) => {
setEvents(prev => [...prev, event]);
},
onEventUpdate: (event: Event) => {
setEvents(prev => prev.map(e => (e.id === event.id ? event : e)));
},
onEventDelete: (eventId: string) => {
setEvents(prev => prev.filter(e => e.id !== eventId));
},
},
});
return <DayFlowCalendar calendar={calendar} />;
}Syncing with Backend
import { useCalendarApp, createMonthView, Event } from '@dayflow/core';
const calendar = useCalendarApp({
views: [createMonthView()],
events,
callbacks: {
onEventCreate: async (event: Event) => {
try {
// Create event in backend
const savedEvent = await api.createEvent(event);
// Update local state with backend response
setEvents(prev => [...prev, savedEvent]);
} catch (error) {
console.error('Failed to create event:', error);
// Optionally remove the optimistic update
}
},
onEventUpdate: async (event: Event) => {
try {
await api.updateEvent(event);
setEvents(prev => prev.map(e => (e.id === event.id ? event : e)));
} catch (error) {
console.error('Failed to update event:', error);
}
},
onEventDelete: async (eventId: string) => {
try {
await api.deleteEvent(eventId);
setEvents(prev => prev.filter(e => e.id !== eventId));
} catch (error) {
console.error('Failed to delete event:', error);
}
},
},
});Event Styling with Calendar Types
Customize event appearance by assigning events to different calendar types using calendarId. Each calendar type can have its own color scheme and styling:
import { createEvent } from '@dayflow/core';
// Work event
const workEvent = createEvent({
id: '1',
title: 'Design Review',
start: new Date(2024, 9, 15, 14, 0),
end: new Date(2024, 9, 15, 15, 0),
calendarId: 'work', // Links to work calendar styling
});
// Personal event
const personalEvent = createEvent({
id: '2',
title: 'Dentist Appointment',
start: new Date(2024, 9, 16, 10, 0),
end: new Date(2024, 9, 16, 11, 0),
calendarId: 'personal', // Links to personal calendar styling
});
// Configure calendar types with colors
const calendars = [
{
id: 'work',
name: 'Work',
colors: {
eventColor: '#3b82f6',
eventSelectedColor: '#2563eb',
lineColor: '#3b82f6',
textColor: '#ffffff',
},
isVisible: true,
},
{
id: 'personal',
name: 'Personal',
colors: {
eventColor: '#10b981',
eventSelectedColor: '#059669',
lineColor: '#10b981',
textColor: '#ffffff',
},
isVisible: true,
},
];
const calendar = useCalendarApp({
views: [createMonthView()],
events: [workEvent, personalEvent],
calendars,
});Multi-Day Events
Events can span multiple days:
import { Temporal } from 'temporal-polyfill';
import { Event } from '@dayflow/core';
// Conference spanning 3 days (all-day event)
const multiDayEvent: Event = {
id: '1',
title: 'Tech Conference 2024',
start: Temporal.PlainDate.from('2024-10-20'),
end: Temporal.PlainDate.from('2024-10-22'),
allDay: true,
calendarId: 'conferences',
};
// Meeting spanning across midnight (timed event)
const crossMidnightEvent: Event = {
id: '2',
title: 'Night Shift',
start: Temporal.ZonedDateTime.from('2024-10-15T22:00:00[America/New_York]'), // 10 PM
end: Temporal.ZonedDateTime.from('2024-10-16T06:00:00[America/New_York]'), // 6 AM next day
calendarId: 'shifts',
};Event Metadata
Store additional information in the meta field:
import { Temporal } from 'temporal-polyfill';
import { Event } from '@dayflow/core';
const event: Event = {
id: '1',
title: 'Project Kickoff',
start: Temporal.ZonedDateTime.from('2024-10-15T10:00:00[America/New_York]'),
end: Temporal.ZonedDateTime.from('2024-10-15T11:00:00[America/New_York]'),
meta: {
// Meeting details
location: 'Conference Room A',
meetingUrl: 'https://zoom.us/j/123456',
// Attendees
organizer: 'john@example.com',
attendees: ['jane@example.com', 'bob@example.com'],
// Custom fields
project: 'Project X',
priority: 'high',
tags: ['planning', 'kickoff'],
// Recurring info
recurring: true,
recurrenceRule: 'FREQ=WEEKLY;BYDAY=MO',
// Any other data
customField: 'custom value',
},
};Best Practices
- Always provide unique IDs - Use UUID or database IDs (string format)
- Use helper functions - Prefer
createEvent()over manual Temporal construction (90% of use cases) - Choose the right type:
- Use
PlainDatefor all-day events (birthdays, holidays) - Use
PlainDateTimefor local events (meetings, appointments) ✨ Recommended default - Use
ZonedDateTimeonly for timezone-aware events (international calls, flights)
- Use
- Validate time values - The helper functions validate hour (0-23) and minute (0-59) automatically
- Use calendar types for styling - Assign
calendarIdto categorize and style events consistently - Leverage the
metafield - Store custom data without modifying the Event interface - Validate event data - Ensure start < end for timed events
- Optimize event updates - Batch updates when possible
- Handle errors gracefully - Provide user feedback on failures
Type Reference
For detailed information about date/time handling, see:
- Event interface:
/src/types/event.ts
Related Documentation
- Views - Understanding calendar views
- Plugins - Event management with plugins
- Getting Started - Basic usage examples
Last updated on