z-cal
v0.9.0
Published
A Temporal-native event calendar with a vanilla DOM core and optional React 19 bindings
Maintainers
Readme
z-cal
A Temporal-native event calendar with a vanilla DOM API and React 19 bindings in one package.
Month, week, day, list, and resource views; drag, resize, select, recurring events, and custom event content.
Timed events reclaim unused space, with customizable details on hover or keyboard focus (eventTooltipContent). Click a day header to widen a crowded day while keeping the week visible. Enable scrollToFirstEvent to start at the earliest scheduled time, or swipeNavigation to swipe between periods.
Opt in to keyboardNavigation for arrow-key access to every cell and slot, with Google-style keyboardShortcuts and screen-reader announcements.
Set businessHours to shade closed time, and keep drags, resizes, and selections inside it or off other events with 'businessHours' constraints and eventOverlap.
Docs and live demos · npm · Documentation · Agent guide
Install
npm install z-calFor React apps, also install React 19 if it is not already installed:
npm install react@^19 react-dom@^19Import the stylesheet once. Import z-cal/polyfill before using the calendar unless all your
runtimes already provide Temporal. React is an optional peer dependency: vanilla users do not
need it. The package is ESM; React bindings live at z-cal/react, not a separate npm package.
Solid and Svelte adapters are not yet available.
React quickstart
In a client-rendered React application:
import 'z-cal/polyfill'
import { Calendar, DayGrid, TimeGrid, Interaction, type EventInput } from 'z-cal/react'
import 'z-cal/style.css'
const plugins = [DayGrid, TimeGrid, Interaction]
const events: EventInput[] = [
{ id: 'meeting', title: 'Team sync', start: '2026-09-07T10:00', end: '2026-09-07T11:00' },
]
export default function App() {
return (
<Calendar
plugins={plugins}
date="2026-09-07"
view="timeGridWeek"
timeZone="America/New_York"
height="650px"
responsiveWeek
editable
events={events}
headerToolbar={{
start: 'title',
end: 'today prev,next dayGridMonth,timeGridWeek,timeGridDay',
}}
/>
)
}This renders the sample week with a draggable event. To show today's week, omit date.
To create events from a selection, enable selectable and handle select in your application.
The library emits a range; your application supplies the form and persistence.
Vanilla quickstart
Add <div id="calendar"></div> to your page, then run this module after the element exists:
import 'z-cal/polyfill'
import { createCalendar, DayGrid, TimeGrid, Interaction } from 'z-cal'
import 'z-cal/style.css'
const host = document.querySelector<HTMLElement>('#calendar')
if (!host) throw new Error('Missing #calendar element')
const calendar = createCalendar(host, {
plugins: [DayGrid, TimeGrid, Interaction],
options: {
date: '2026-09-07',
view: 'timeGridWeek',
timeZone: 'America/New_York',
height: '650px',
responsiveWeek: true,
editable: true,
events: [
{ id: 'meeting', title: 'Team sync', start: '2026-09-07T10:00', end: '2026-09-07T11:00' },
],
},
})
// Call when your page/component is removed:
export function dispose() {
calendar.destroy()
}Find the right guide
| Task | Guide | | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | Install, use a CDN, understand runtime requirements | Installation | | Choose views, configure toolbars, sizing, timezone, or resources | Configuration | | Load, create, update, persist, drag, or resize events | Events and interaction | | Use refs, hooks, slots, or server rendering | React | | Change colors, typography, icons, or dark mode | Styling | | Look up methods, options, callbacks, and exports | API reference | | Diagnose missing views, events, styles, or unexpected updates | Troubleshooting | | Integrate with a coding agent | Agent guide | | Develop, test, publish, or deploy this repository | Contributing |
Important behavior
Replacing FullCalendar? Read the migration checklist for duration units, callback differences, and current API gaps.
- Supply the plugin that provides your
view;Interactionenables selection and event editing. keyboardShortcutslistens on the calendar root by default; pass{ target: document }for page-wide keys. They never fire in text fields or with a modifier held.- Dates returned by callbacks are Temporal values. All-day ranges have an exclusive end.
updateEventreplaces an event; supply its complete input, includingstart.Recurrenceexpandsrecurrencerules (RRULE text or an object) into occurrences; each callback event carriesoccurrence, and theeditRecurringEventhelper produces the series inputs for "this", "this and following", and "all".- Replacing
eventsor refetching sources replaces the corresponding loaded data. Persist edits in your application. Keep unchanged React arrays/objects stable across renders. - Drag/resize commits are canceled if the event was replaced during the gesture. A delayed
revert()leaves newer edits intact. See editing and persistence. responsiveWeekadjuststimeGridWeekand its derived views to their container width.- Define
heightto fill a container vertically.height="100%"needs a parent with a defined height.
License
MIT.
