Calendar state
Keep the event collection and persistence in the caller while applying view requests explicitly.
Pure calculations and React view
@ghost-ui/core/calendar-core provides pure data operations and date calculations; changeCalendarEvent returns a new event proposal. It does not mutate an event collection or persist anything. The React Calendar receives events, date, and timeZone as inputs. Its callbacks report requested changes; the caller updates those inputs when a change should take effect.
Apply an edit proposal
For a direct edit flow, calculate the proposed event, then replace the matching item in caller state. Persist it separately and keep the prior event if persistence fails. A view's onEventChange(next, { previous, action }) follows the same boundary: next is a proposal, not proof of a saved change.
editable and onEventChange are both required for view drag or keyboard edits; an individual event with editable: false cannot be changed. snapDuration defaults to 15 minutes and bounds resize duration. changeCalendarEvent throws for non-finite deltas, non-positive snapping, disabled edits, point-event resizing, a duration shorter than the snap interval, or a timed resize outside its original local day unless date resizing is enabled. The view ignores invalid gesture proposals rather than sending them to onEventChange.
During a pointer edit, the original stays visible and a candidate shows the proposed position and duration. Escape, pointer cancellation, leaving the Calendar, or changing its inputs cancels the proposal. A valid release emits one change. Touch scrolling on the event body does not move it; use the event’s Edit action and a caller-owned date/time form. Points and very short events use this explicit editor rather than overlapping resize handles.
Callbacks and caller ownership
Selection callbacks identify an event or slot. onDateChange, onViewChange, and onTimeZoneChange report navigation requests; update the corresponding controlled prop in response. onEventResponse, onEventAction, and onSchedulingResponse report decisions about event metadata. They do not execute a server action, authorize it, or update a backend. Keep pending, failed, and conflict status in the caller's event data and present truthful feedback.
Creator, organizer, invitation response, proposed changes and execution status are separate fields. Answering an invitation should not discard a pending time proposal. Accepting a proposal should update only the fields it changes. Keep stable IDs and reject stale asynchronous results when a newer decision supersedes them.
A selected timed slot includes offset timestamps and has slotDuration minutes (default 30); pointer and keyboard selection snap by snapDuration (default 15). A slot can be shorter than the requested duration only when the local day has fewer remaining minutes. Resource schedule slots carry resourceId; unassigned slots omit it.
Timezone and DST
Changing the view timezone changes how instants map to local dates and clock labels; it does not change the stored instant. A local-day interval can be 23 or 25 hours. When moving a timed event by local days, the core preserves its start wall-clock time and elapsed duration only when that target start is unique. It throws when DST makes the requested start nonexistent or ambiguous. The ending wall-clock label can change across a transition. Choose and validate a product-specific resolution before applying that proposal.
View and inspection ownership
Calendar owns layout, overflow disclosure and inspection of the supplied events. Those view decisions do not change event identity, semantic intervals or the caller's collection. The application owns the editing form and persistence feedback. Use renderEvent to customize event content or onEventEdit to open an application editor; use the Calendar component documentation for density, sizing, inspection and responsive behavior. Core getCalendarDates returns 42 dates for Month; the React view renders five or six weeks as needed.
No recurrence or server scheduler
The current core models individual events and intervals. It does not expand recurrence rules, reserve availability, detect domain conflicts, or schedule events on a server. The application owns those policies and any persistence or retry behavior. See Calendar API for operation signatures and Calendar component for the view behavior.