Flash Calendar
An incredibly fast and flexible way to build calendars in React Native.
Flash Calendar started as a dependency of something else. I was building date pickers for Moni, a personal finance app I work on in my free time, and the options available didn't fit: no bottom sheet support, inconsistent spacing between five- and six-week months, a bundle heavier than it needed to be.
I had been maintaining a patch against the most popular alternative for three years. At some point maintaining someone else's calendar became more work than writing my own.
Solve fewer needs better
The library that came before tried to do everything, and paid for it in surface area. Flash Calendar goes the other way: it builds calendars and calendar lists well, and declines the rest. Agenda mode is explicitly out of scope.
That constraint is what makes the rest possible. There isn't much surface to optimise, so it stays fast, and there isn't much to configure, so customising it never turns into a prop soup. It fits in 18kb.
import { Calendar, toDateId } from "@marceloterreiro/flash-calendar";
const today = toDateId(new Date());
<Calendar
calendarActiveDateRanges={[{ startId: selected, endId: selected }]}
calendarMonthId={today}
onCalendarDayPress={setSelected}
/>;
Every prop contains the word calendar (calendarMinDateId,
calendarActiveDateRanges, getCalendarDayFormat), so autocomplete finds them
without you remembering the name.
The hooks underneath
Under the components sit useCalendar and useCalendarList, hooks that hand
you the structure (weeks, days, active ranges, disabled states) and stop there.
When the default theme doesn't match your product, you render your own
components against the same hooks instead of fighting a styling API.
Infinite scroll, localization, dark mode, and bottom sheet compatibility come from that same structure rather than from flags.
What maintaining it taught me
The interesting part turned out not to be the date math. It was everything downstream of other people depending on you. A version number is a promise you have to keep. Documentation has to answer the question someone actually has, which is rarely the question that's easiest to write up. And when the same workaround shows up in a third issue, the API is wrong and that workaround is what the API should have been.