MCPcopy Index your code
hub / github.com/afonsojramos/super-calendar

github.com/afonsojramos/super-calendar @v2.1.5

Chat with this repo
repository ↗ · DeepWiki ↗ · release v2.1.5 ↗ · + Follow
248 symbols 665 edges 81 files 1 documented · 0%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

super-calendar

A generic, themeable month / week / day calendar for React Native.

npm version JSR version npmx CI status MIT license

Month, week, 3-day, day and schedule views of super-calendar

Documentation · Quickstart · Live demo · API reference

  • 📆 Month grid plus day / 3-day / week / custom-N time-grids
  • 🤏 Zoomable week/day grid: pinch on iOS & Android, Ctrl/Cmd + scroll on web (UI thread, no re-renders)
  • ♾️ Virtualized, snap-paging months/weeks/days via @legendapp/list
  • 🧩 Bring-your-own event type (CalendarEvent<T>) and a renderEvent escape hatch
  • 🗓️ Date selection (single / multiple / range via useDateRange), disabled days, and a scrolling MonthList
  • 🪝 Headless useMonthGrid hook to build a fully custom calendar
  • 🎨 Fully themeable, with sensible defaults (no styling library required)
  • 🌐 Runs on iOS, Android and web (web via react-native-web; see Web)

Relationship to react-native-big-calendar

This is a ground-up reimagining inspired by the excellent react-native-big-calendar. It keeps the familiar month/week/day model but is built around Reanimated and modern list virtualization — trading framework-agnosticism for a richer, gesture-driven experience. It's not a fork; the API differs, and the name is an homage. 🙇

Already using react-native-big-calendar? The migration guide has a copy-paste prompt for your coding agent plus a manual prop mapping.

At a glance

Capability super-calendar react-native-big-calendar
Month / week / day / 3-day / custom / agenda
Generic event typing (CalendarEvent<T>)
Virtualized, snap-paged views ❌ renders all dates
Pinch-to-zoom (native) / Ctrl-scroll (web)
Drag to move & resize events ❌ (declined upstream)
Date selection (single / range / multiple) useDateRange + disabled days
Headless grid hook (useMonthGrid)
Overlapping events ✅ side-by-side columns ⚠️ stacked / indented
Month paging fires onChangeDate ⚠️ known gaps
Recurring events expandRecurringEvents ❌ expand them yourself
Time-zone display eventsInTimeZone
Dark mode darkTheme preset ❌ bring your own palette
renderEvent across every mode & event type ⚠️ breaks for all-day/multi-day
Web ✅ arrow-key paging, Ctrl-scroll zoom ⚠️ partial
Runtime dependencies Reanimated + Gesture Handler + Legend List dayjs + calendarize (lighter)

Legend: ✅ supported · ⚠️ partial or with known issues · ❌ not available. The last row is the honest trade-off: big-calendar has a smaller footprint and fewer native peers, so it can be the simpler choice when you don't need the gestures, virtualization, or the helpers above.

What it adds over react-native-big-calendar

  • 🤏 Pinch-to-zoom time grid — row height is a Reanimated shared value, so zooming runs on the UI thread with zero React re-renders.
  • ♾️ Virtualized, snap-paged views (via @legendapp/list) — swipe across years of dates, with native one-page paging (or opt into freeSwipe).
  • 🧩 Generic events + render-prop componentCalendarEvent<T> carries your own fields, and renderEvent is a component (so it may use hooks) that receives the event box's live pixel height for progressive disclosure as the grid zooms.

Feature parity. It also covers the rest of react-native-big-calendar's surface: month / day / 3-day / week / custom N-day (and weekEndsOn partial-weeks) / agenda (schedule) modes, all-day events (lane + allDay flag, toggle the lane with showAllDayEventCell), multi-day clipping, minHour/maxHour, ampm (hour axis and event times), showTime, timeslots, hideHours, showWeekNumber, weekNumberPrefix, hourComponent, sortedMonthView, moreLabel, showAdjacentMonths, showSixWeeks, disableMonthEventCellPress, a default month weekday header (renderHeaderForMonthView), a custom month date badge (renderCustomDateForMonth), activeDate, per-event disabled, onPress/onLongPress for events, cells and date headers, onChangeDateRange, resetPageOnPressCell, swipeEnabled, verticalScrollEnabled, showVerticalScrollIndicator, an agenda itemSeparatorComponent, eventCellStyle, calendarCellStyle, a headerComponent slot, date-fns locale, right-to-left column order (isRTL), and theming. Text styling that big-calendar exposes via calendarCellTextStyle is covered by CalendarTheme.text; overlapping events are laid out in side-by-side columns automatically.

Trade-offs (where react-native-big-calendar may suit you better)

  • It's opinionated about peers: Reanimated, Gesture Handler and @legendapp/list are required. react-native-big-calendar is more self-contained (no Reanimated/Gesture Handler).
  • RTL is cosmetic (isRTL reverses the day-column order, like big-calendar's): the hour gutter stays on the left and paging follows the system scroll direction. Enable React Native's I18nManager for full RTL.

Relationship to flash-calendar

The date-picker surface (MonthList, useDateRange, and the headless useMonthGrid) is inspired by flash-calendar, an excellent headless date picker for React Native. If you only need date selection, flash-calendar is the lighter, more focused choice: a dedicated, FlashList-based picker with no event model. super-calendar folds picking into a full gesture calendar, so one library covers events and date selection, at the cost of the Reanimated, Gesture Handler, and Legend List peers. Pick flash-calendar for a standalone picker; pick this when you also need the event views.

Install

npm install @super-calendar/native

Also published on JSR: deno add jsr:@super-calendar/native (or npx jsr add @super-calendar/native).

Peer dependencies

The full calendar relies on the following being installed in your app:

npm install react-native-reanimated react-native-worklets react-native-gesture-handler @legendapp/list date-fns

Make sure Reanimated and Gesture Handler are set up per their own docs (Babel plugin, GestureHandlerRootView at the root of your app).

These are declared as optional peers so web-only installs (@super-calendar/dom) and the picker (the @super-calendar/native/picker subpath) aren't asked to install React Native packages they don't use. The full calendar still needs them: because its components import Reanimated and Gesture Handler directly, a missing one surfaces as a clear Metro Unable to resolve "react-native-reanimated" build error rather than a silent failure, so install the line above when you use Calendar or the time grid.

Picker only? Skip Reanimated

If you only need date selection, import it from the @super-calendar/native/picker subpath. It contains the month grid, selection, and the headless useMonthGrid, with none of the timetable code and no Reanimated dependency, so it works on every bundler (Metro included) without shipping the week/day grid. A picker-only app installs just:

npm install react-native-gesture-handler @legendapp/list date-fns
import { MonthList, useDateRange } from "@super-calendar/native/picker";

react-native-reanimated and react-native-worklets are declared as optional peers, so this subpath won't pull them in. (Metro doesn't tree-shake the @super-calendar/native barrel, so the subpath is what guarantees the timetable code is left out.)

React DOM (web without React Native)

For a plain react-dom app (no React Native, no react-native-web), install the @super-calendar/dom package. It ships real DOM components, MonthView, MonthList (the date picker), and TimeGrid (day/week/N-day, with Ctrl/⌘-scroll and pinch zoom plus drag to move and resize), built on the same pure core and Legend List's DOM renderer. A web app installs just:

npm install @super-calendar/dom react react-dom @legendapp/list date-fns
import { MonthList, TimeGrid, useDateRange } from "@super-calendar/dom";

The React Native peers (react-native, react-native-gesture-handler, react-native-reanimated, react-native-worklets) are all optional, so a web install pulls none of them. Styling is plain inline styles driven by a theme prop (defaultDomTheme / darkDomTheme), no stylesheet import required.

A selected range renders as a centered rounded "pill" band by default (its height and colour are the rangeBandHeight / rangeBackground theme tokens). Pass fillCellOnSelection to MonthView / MonthList to fill the whole cell edge to edge instead.

Headless core (any renderer)

Want the date math and selection model without any of the built-in UI? The @super-calendar/core package exports just the pure pieces, buildMonthGrid / useMonthGrid, useDateRange and the selection helpers, layoutDayEvents, and the date utilities, with zero React Native, Reanimated, or Legend List imports. It's what the DOM components are built on, and it works in any React renderer (react-dom, Solid via its React compat, your own).

npm install @super-calendar/core react date-fns
import { buildMonthGrid, nextDateRange } from "@super-calendar/core";

Usage

import { useState } from "react";
import { Calendar, type CalendarEvent } from "@super-calendar/native";

type MyEvent = { id: string; color: string };

const events: CalendarEvent<MyEvent>[] = [
  {
    id: "1",
    color: "#1F6FEB",
    title: "Lecture",
    start: new Date(2026, 5, 19, 10, 0),
    end: new Date(2026, 5, 19, 11, 30),
  },
];

export function MyCalendar() {
  const [mode, setMode] = useState<"month" | "week" | "day">("week");
  const [date, setDate] = useState(new Date());

  return (
    <Calendar
      mode={mode}
      date={date}
      events={events}
      weekStartsOn={1}
      onChangeDate={setDate}
      onPressEvent={(event) => console.log(event.id)}
      onPressDay={(day) => {
        setDate(day);
        setMode("day");
      }}
    />
  );
}

Custom events

The built-in renderer draws a simple titled box. Pass renderEventa React component, not a callback — to take full control. Because it's rendered as a component, it may use hooks. The same renderer is used in every mode — month chips, the all-day lane, the timed grid and the schedule list — and always receives isAllDay (plus continuesBefore/continuesAfter for clipped multi-day segments on the grid), so one component covers them all. On the week/day grid you also receive boxHeight, a Reanimated shared value tracking the live pixel height of the box (driven by pinch-zoom), so you can reveal detail progressively without re-rendering:

```tsx import Animated, { useAnimatedStyle } from "react-native-reanimated"; import { Pressable, Text } from "react-native"; import type { RenderEventArgs } from "@super-calendar/native";

// Define the component once (don't inline it, or it remounts every render). function MyEvent({ event, boxHeight, onPress }: RenderEventArgs) { const detailStyle = useAnimatedStyle(() => ({ display: (boxHeight?.value ?? Infinity) >= 84 ? "flex" : "none", })); return ( <Pressable style={{ flex: 1, backgroundColor: e

Extension points exported contracts — how you extend this code

DomRenderEventArgs (Interface)
(no doc)
packages/dom/src/TimeGrid.tsx
CalendarColors (Interface)
(no doc)
packages/core/src/tokens.ts
CalendarTheme (Interface)
(no doc)
packages/native/src/theme.ts
TimeGridProps (Interface)
(no doc)
packages/dom/src/TimeGrid.tsx
ICalendarEvent (Interface)
(no doc)
packages/core/src/types.ts
MonthListProps (Interface)
(no doc)
packages/dom/src/MonthList.tsx
RecurrenceRule (Interface)
(no doc)
packages/core/src/types.ts
DomMonthEventArgs (Interface)
(no doc)
packages/dom/src/MonthView.tsx

Core symbols most depended-on inside this repo

at
called by 28
examples/shared/src/events.ts
layoutDayEvents
called by 20
packages/core/src/utils/layout.ts
getViewDays
called by 14
packages/core/src/utils/dates.ts
eventTimeLabel
called by 14
packages/core/src/utils/eventDisplay.ts
useCalendarTheme
called by 14
packages/native/src/theme.ts
isDateSelectable
called by 13
packages/core/src/utils/dateRange.ts
isAllDayEvent
called by 13
packages/core/src/utils/layout.ts
snapDeltaMinutes
called by 12
packages/core/src/utils/drag.ts

Shape

Function 221
Interface 24
Class 2
Method 1

Languages

TypeScript100%

Modules by API surface

packages/dom/src/TimeGrid.tsx21 symbols
packages/native/src/components/TimeGrid.tsx20 symbols
examples/shared/src/ContextMenu.tsx16 symbols
packages/dom/src/MonthView.tsx14 symbols
scripts/visual-parity.mjs13 symbols
packages/core/src/utils/dateRange.ts13 symbols
packages/core/src/utils/eventDisplay.ts9 symbols
packages/core/src/utils/dates.ts9 symbols
packages/core/src/utils/layout.ts8 symbols
packages/core/src/utils/monthGrid.ts7 symbols
examples/web/src/App.tsx7 symbols
examples/native/App.tsx7 symbols

For agents

$ claude mcp add super-calendar \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page