useCalendarApp Reference
useCalendarApp(config: CalendarAppConfig) is the hook that connects the DayFlow core to your application. Pass a single configuration object to register views, feed initial events, toggle optional UI, and connect lifecycle callbacks. This guide breaks down every available option.
Quick Start
import {
useCalendarApp,
DayFlowCalendar,
createMonthView,
createWeekView,
ViewType,
} from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular'
import '@dayflow/core/dist/styles.css';
export function TeamCalendar() {
const calendar = useCalendarApp({
views: [createMonthView(), createWeekView()],
defaultView: ViewType.MONTH,
initialDate: new Date(),
events: [],
});
return <DayFlowCalendar calendar={calendar} />;
}Configuration Overview
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
views | CalendarView[] | Required | — | Registers the view definitions (e.g., createMonthView()). At least one view is required. |
plugins | CalendarPlugin[] | Optional | [] | Installs optional plugins (drag helpers, shortcuts, etc.). Each plugin receives the app instance during install. |
events | Event[] | Optional | [] | Initial event payload. Use addEvent/updateEvent afterward to mutate state. |
callbacks | CalendarCallbacks | Optional | {} | Lifecycle hooks that fire when views, dates, or events change—perfect for syncing with APIs. |
defaultView | ViewType | Optional | ViewType.WEEK | View that loads first; must exist in views. |
initialDate | Date | Optional | new Date() | Starting focus date (also seeds visible month calculations). |
timeZone | string | Optional | User's system timezone | Global display and editing timezone for all views. |
switcherMode | 'buttons' | 'select' | Optional | 'buttons' | Controls how the built-in view switcher renders in headers. |
calendars | CalendarType[] | Optional | [] | Registers calendar categories (Work, Personal, etc.) with colors and visibility. |
defaultCalendar | string | Optional | First visible calendar | ID used when new events are created. |
theme | ThemeConfig | Optional | { mode: 'light' } | Sets global theme mode and optional token overrides. |
locale | string | Locale | Optional | 'en-US' | Sets the locale for internationalization (i18n). Supports language codes (e.g., 'ja') or Locale objects. |
useEventDetailDialog | boolean | Optional | false | Enables the default modal detail dialog instead of inline panels. |
useCalendarHeader | boolean | Optional | true | Enables the default header (true) or hides it (false). For a custom header, use the calendarHeader slot on DayFlowCalendar. |
readOnly | boolean | ReadOnlyConfig | Optional | false | Disables built-in mutation UI. Can be a boolean or a config for fine-grained control (drag/view). Programmatic event APIs still work. |
customMobileEventRenderer | MobileEventRenderer | Optional | — | Custom component to replace the default mobile event drawer/dialog. |
allDaySortComparator | AllDaySortComparator | Optional | Calendar-group order with multi-day all-day events first | Custom comparator controlling the row order of all-day events across all views. When provided, it fully overrides the default order. |
Key Options
Views (required)
- Each view is a
CalendarViewobject{ type, component, config }. - DayFlow ships with factories (
createDayView,createWeekView, etc.) that return ready-made definitions. defaultViewmust match one of the registered view types; otherwise the app throws during initialization.
Events
- The provided array becomes the in-memory
CalendarApp.state.eventslist. useCalendarAppwatches app mutations, so callingcalendar.addEvent()orcalendar.updateEvent()automatically syncs application state.- Make sure events adhere to the
Eventinterface (start/endacceptPlainDate,PlainDateTime, orZonedDateTime).
Plugins
- A plugin has
{ name, install(app), config }and is executed once during construction. - Use plugins to register drag handlers, keyboard shortcuts, analytics observers, or expose custom APIs via
app.getPlugin(name).
Callbacks
callbacks keep state in sync with your backend or analytics layer:
onViewChange(view)fires after a successful view switch.onDateChange(date)fires whenever the focused date changes (navigation or selection).onVisibleRangeChange(start, end, reason)fires whenever visible date-range shifts. Helps in more precise fetches without additional calculations.onEventCreate(event),onEventUpdate(event),onEventDelete(id)mirror CRUD operations—ideal for syncing APIs.onEventDoubleClick(event, e)fires when an event is double-clicked. Usee.currentTargetas an anchor for external popovers, and returnfalseto suppress DayFlow's default detail panel/dialog.onMoreEventsClick(date)fires when the "+ X more" link is clicked in Month view.onCalendarCreate(calendar),onCalendarUpdate(calendar),onCalendarDelete(id)mirror calendar CRUD operations.onCalendarMerge(sourceId, targetId)fires when merging two calendars (e.g., merging "Work" into "Personal").onRender()executes when the calendar finishes a render pass (useful for instrumentation).
defaultView & initialDate
defaultViewsets the initialstate.currentView. If omitted, DayFlow falls back toViewType.WEEK, so explicitly set it for single-view calendars.initialDateseeds bothstate.currentDateand the internalvisibleMonth. Override it if you pull the date from routing or user settings.
timeZone
timeZonedefines the primary display and editing timezone for Day, Week, Month, and Year views.- If omitted, DayFlow resolves it from the user's system timezone.
- Changing
timeZonereprojects the UI, but does not itself mutate event data. - Edit callbacks still return canonical event data after the change is applied. DayFlow does not persist the temporary UI projection timezone as the stored event shape.
- Day/Week
secondaryTimeZoneremains a display-only reference axis and does not replace the primary app timezone.
switcherMode
'buttons': renders a horizontal button group, great for desktop.'select': renders a dropdown, perfect when space is limited or you expose many view types.
calendars & defaultCalendar
calendarsdefines each calendar type (id,name,colors, visibility). The Calendar Registry automatically picks light/dark colors based ontheme.mode('light' | 'dark' | 'auto').defaultCalendardetermines which calendar new events inherit; if omitted, the first visible calendar wins.
CalendarType properties:
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier (e.g., 'work', 'personal'). |
name | string | Yes | Display name shown in the UI. |
colors | CalendarColors | Yes | Light mode color set (see below). |
darkColors | CalendarColors | No | Dark mode color set; falls back to colors if omitted. |
description | string | No | Optional human-readable description. |
icon | string | No | Emoji or icon name displayed alongside the calendar name. |
isVisible | boolean | No | Whether events of this calendar are shown. Defaults to true. |
isDefault | boolean | No | Marks this as a system default calendar. |
readOnly | boolean | No | Disables drag, resize, and edit UI for events in this calendar. |
source | string | No | Origin label (e.g., 'Google Calendar', 'iCloud'). |
subscription | { url, status, meta? } | No | Subscription metadata for ICS/remote calendars. |
CalendarColors properties:
| Property | Type | Description |
|---|---|---|
eventColor | string | Event background color (usually translucent). |
eventSelectedColor | string | Event background when selected. |
lineColor | string | Accent / border color. |
textColor | string | Event text color. |
theme
The theme configuration controls the visual appearance of the entire calendar:
const calendar = useCalendarApp({
theme: {
mode: 'dark', // 'light' | 'dark' | 'auto'
},
});Theme Modes:
'light': Light mode with light backgrounds and dark text (default)'dark': Dark mode with dark backgrounds and light text'auto': Automatically follows system theme preference
Programmatic Theme Changes:
// Get current theme
const currentTheme = calendar.app.getTheme();
// Set theme
calendar.app.setTheme('dark');
// Subscribe to theme changes
calendar.app.subscribeThemeChange(theme => {
console.log('Theme changed to:', theme);
});Custom Dark Mode Colors:
Define different colors for light and dark modes for each calendar type:
const calendars = [
{
id: 'work',
name: 'Work',
colors: {
// Light mode colors
lineColor: '#0066cc',
eventColor: '#e6f2ff',
eventSelectedColor: '#cce4ff',
textColor: '#003d7a',
},
darkColors: {
// Dark mode colors
lineColor: '#4da6ff',
eventColor: '#1a3d5c',
eventSelectedColor: '#2a5a8a',
textColor: '#b3d9ff',
},
},
];See Dark Mode for comprehensive theming documentation.
locale
The locale option sets the language and regional settings for the calendar.
- String: Use a language code like
'en-US','ja','zh','de','fr','es','ko'. - Locale Object: Pass an imported
Localeobject for type safety or a custom object for unsupported languages.
// String code
const calendar = useCalendarApp({
locale: 'ja',
});
// Built-in Locale object
import { ja } from '@dayflow/core';
const calendar = useCalendarApp({
locale: ja,
});
// Custom Locale object
const customLocale = {
code: 'it',
messages: { today: 'Oggi', ... }
};
const calendar = useCalendarApp({
locale: customLocale,
});useEventDetailDialog
trueturns on the default modal dialog (DefaultEventDetailDialog).- Combine with
customDetailPanelContentorcustomEventDetailDialogonDayFlowCalendarto swap the UI while keeping the core state machine.
useCalendarHeader
true(default): Renders the built-in calendar header.false: Hides the header entirely.
To render a custom header, use the calendarHeader slot on DayFlowCalendar. See Calendar Header for details.
readOnly
true: Disables built-in mutation UI (dragging, creating, editing).ReadOnlyConfig: Fine-grained control.draggable: Whether dragging is allowed.viewable: Whether opening event details is allowed.
- Programmatic APIs such as
calendar.addEvent(),calendar.updateEvent(),calendar.deleteEvent(), andcalendar.applyEventsChanges()still work in read-only mode. - Use
calendar.canMutateFromUI()in custom UI to decide whether create/edit/delete controls should be shown. - See Read-only Mode for details.
customMobileEventRenderer
- Allows replacing the default bottom-drawer for mobile event editing with your own component.
- See Sidebar Plugin for more on specific features.
allDaySortComparator
Controls the row order of all-day events in every view (day, week, month, year).
By default, DayFlow:
- groups all-day events by
calendarIdin first-seen order - keeps multi-day all-day events above single-day all-day events
- keeps same-calendar all-day events visually grouped together
Pass allDaySortComparator only when you want to take full control of the final order. Once provided, the comparator result is used directly.
Pass a comparator to take full control — it receives two Event objects and works like JavaScript's Array.sort:
const calendar = useCalendarApp({
allDaySortComparator: (a, b) => a.title.localeCompare(b.title),
});Available exported helper from @dayflow/core:
| Helper | Behavior |
|---|---|
sortAllDayByTitle | Sorts all-day events alphabetically by title and fully overrides the default grouping flow |
import { sortAllDayByTitle } from '@dayflow/core';
const calendar = useCalendarApp({
allDaySortComparator: sortAllDayByTitle,
});Use updateConfig to change the sort at runtime:
calendar.app.updateConfig({ allDaySortComparator: sortAllDayByTitle });
// Restore the default calendar-grouped ordering
calendar.app.updateConfig({ allDaySortComparator: undefined });Advanced Configuration Example
import {
useCalendarApp,
DayFlowCalendar,
createMonthView,
createWeekView,
ViewType,
} from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular'
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';
import '@dayflow/core/dist/styles.css';
const calendars = [
{
id: 'work',
name: 'Work',
colors: {
eventColor: '#2563eb',
eventSelectedColor: '#1d4ed8',
lineColor: '#1e40af',
textColor: '#ffffff',
},
},
{
id: 'personal',
name: 'Personal',
colors: {
eventColor: '#f97316',
eventSelectedColor: '#ea580c',
lineColor: '#c2410c',
textColor: '#ffffff',
},
},
];
export function AdvancedCalendar() {
const calendar = useCalendarApp({
views: [createMonthView(), createWeekView()],
defaultView: ViewType.WEEK,
initialDate: new Date('2024-10-01'),
events: [],
calendars,
defaultCalendar: 'work',
switcherMode: 'select',
callbacks: {
onEventUpdate: event => api.events.update(event),
onVisibleRangeChange: (start, end, reason) =>
preloadVisibleRange(start, end, reason),
},
plugins: [
createSidebarPlugin({
width: 280,
initialCollapsed: false,
}),
],
useEventDetailDialog: true,
});
return <DayFlowCalendar calendar={calendar} />;
}Tip: The object returned by
useCalendarAppexposes both state (currentView,currentDate,events) and actions. Share the same instance withDayFlowCalendar, your own toolbar, and side panels to keep everything synchronized.