Skip to content
MoltenshipPublic

About

A headless React calendar built on the Temporal API. Week, day, month, year, agenda and resource views you own as shadcn/ui source, with exact time zones and DST.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

207 Commits

Folders and files

Repository files navigation

A React 19 calendar built on the Temporal API, with views you copy into your app and own.

npm version CI status MIT license

Documentation · Quick start · Live demo · Releases

The live demo's week view, with overlapping events, an all-day row and the current-time line

Time handles dates, time zones, navigation, calendar state, fast event lookups, and saving changes. Your events stay in the shape your app already uses, and Time reads them through a small adapter. The screenshot is the live demo, a Google Calendar-style app built from the same views. Its source is in apps/demo.

Note

The packages are on npm as a release candidate for 1.0.0. The API can still change before 1.0.0 if the release candidate turns up problems.

Features

  • Temporal, not Date. Timed events use Temporal.Instant, all-day events use Temporal.PlainDate, and floating events use Temporal.PlainDateTime.
  • Time zones and daylight saving time. Time lays out days that are 23 or 25 hours long, and hours that a clock change skips or repeats.
  • Your event shape. An adapter tells Time how to read an ID, a title and a time range from your records. TypeScript keeps your record and ID types.
  • Views you own. Week, day, month, year, agenda, resource columns and resource timeline are shadcn/ui source files. The shadcn CLI copies them into your app, in Tailwind CSS or StyleX.
  • Editing. People drag, resize and create events with a mouse, a pen or touch. Each edit arrives as a change for you to save. It shows as pending while it saves and rolls back if saving fails.
  • Controlled or uncontrolled state. The calendar or your app can own the visible date, the view, the time zone, the selection and the focus.
  • Server rendering. During server rendering, Time doesn't read the clock, the host time zone or window, so the server and the browser render the same markup from the same props.
  • Recurrence and iCalendar. Separate packages expand RRULE series inside the visible range and parse ICS feeds.

Comparison sets Time beside FullCalendar and react-big-calendar, including where they're ahead.

Install

pnpm add @moltenship/calendar react react-dom

Time needs:

  • React 19.
  • A runtime with Temporal. Node.js 26 and later include it. In a browser without it, load a polyfill before the calendar. Time never bundles one.
  • TypeScript 6 or later with "lib": ["DOM", "DOM.Iterable", "ESNext"].

Installation covers the polyfill and the TypeScript setup.

Quick start

The smallest calendar, with a hand-written view:

import {
  createCalendar,
  defineCalendarView,
  defineEventAdapter,
  plainDateInterval,
} from "@moltenship/calendar";

interface Meeting {
  id: string;
  title: string;
  start: Temporal.Instant;
  end: Temporal.Instant;
}

const eventAdapter = defineEventAdapter<Meeting>()({
  getId: (meeting) => meeting.id,
  getTitle: (meeting) => meeting.title,
  getInterval: (meeting) => ({ kind: "timed", start: meeting.start, end: meeting.end }),
  getResourceIds: () => [],
});

// A minimal view: the meetings on the visible day.
const dayView = defineCalendarView({
  name: "day",
  strategy: {
    getRange: (date) => plainDateInterval(date, date.add({ days: 1 })),
    navigate: (date, delta) => date.add({ days: delta }),
    getTitle: (range, { locale }) => range.start.toLocaleString(locale, { dateStyle: "full" }),
    project: ({ snapshot, instantRange }) => snapshot.queryTimed(instantRange),
  },
  Renderer: ({ projection }) => (
    <ul>
      {projection.map((meeting) => (
        <li key={meeting.id}>{meeting.title}</li>
      ))}
    </ul>
  ),
});

const Calendar = createCalendar<Meeting>()({ eventAdapter, views: [dayView] });

export function MeetingCalendar({ meetings }: { meetings: readonly Meeting[] }) {
  return (
    <Calendar.Root
      events={meetings}
      defaultAnchorDate={Temporal.PlainDate.from("2026-10-08")}
      defaultTimeZone="Europe/Berlin"
      locale="en-US"
      weekRules={{ firstDay: 1, minimalDays: 4, weekend: [6, 7] }}
    >
      <Calendar.PreviousTrigger>Previous</Calendar.PreviousTrigger>
      <Calendar.Title />
      <Calendar.NextTrigger>Next</Calendar.NextTrigger>
      <Calendar.ActiveView />
    </Calendar.Root>
  );
}

Add the built-in views

The styled views aren't in the npm package. Add the week and day, month, and agenda views with the shadcn CLI:

npx shadcn@latest add \
  https://time.molten.sh/r/time-grid-view.json \
  https://time.molten.sh/r/month-view.json \
  https://time.molten.sh/r/list-view.json

The files land in components/calendar/, along with the theme, the toolbar and the view switcher. The Quick start wires them into createCalendar.

Packages

Most apps import @moltenship/calendar alone. It re-exports the React, pointer-interaction, core and Temporal packages.

Package What it does
@moltenship/calendar The package you install: React components and hooks, the event engine, Temporal helpers and pointer interactions.
@moltenship/calendar-recurrence RRULE expansion inside a range, exceptions and series edits.
@moltenship/ics Typed iCalendar (RFC 5545) parsing into Temporal values, with Standard Schema support.
@moltenship/calendar-dnd-kit A dnd-kit adapter: drag your own items into the calendar and events out.
@moltenship/calendar-testing Test helpers: a deterministic environment, builders and fixtures, a render harness, and keyboard and pointer drivers.
@moltenship/calendar-react The headless React components and hooks.
@moltenship/calendar-dnd Pointer drag, resize and create interactions for views.
@moltenship/calendar-core The framework-independent engine: event data, projection, layout and interactions.
@moltenship/calendar-temporal Framework-independent Temporal utilities.

Documentation

The docs are at time.molten.sh. Good places to start:

To work on the docs, run vp run dev and edit the MDX in apps/showcase/content/docs. Start the demo with vp run demo#dev.

Contributing

The repository uses the Vite+ toolchain (vp) and Node.js 26.

vp install         # install dependencies
vp check           # format, lint, and type-check
vp test            # run the tests
vp run ready       # everything CI runs
vp run ready:full  # the release gate

License

MIT. @moltenship/ics also bundles Unicode CLDR data under the Unicode License v3, so it's MIT AND Unicode-3.0; see its THIRD-PARTY-NOTICES.md.

About

A headless React calendar built on the Temporal API. Week, day, month, year, agenda and resource views you own as shadcn/ui source, with exact time zones and DST.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages