npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@calendarjs/react

v1.0.8

Published

React wrappers for CalendarJS Calendar, Schedule, and Timeline. One install, named imports, idiomatic React API (camelCase callbacks, controlled components, ref forwarding).

Readme

@calendarjs/react

React wrappers for the CalendarJS family of components — Calendar, Schedule, and Timeline — published as a single package.

npm install @calendarjs/react react

Usage

import { Calendar, Schedule, Timeline } from '@calendarjs/react';

Stylesheets are loaded automatically when you import the module, provided your bundler handles import '*.css' (Webpack, Vite, Next.js, CRA, etc.). If you need the consolidated stylesheet directly:

import '@calendarjs/react/style.css';

Included components

Calendar

A date picker supporting single dates, ranges, time, validation, and inline / popup display.

import React, { useState } from 'react';
import { Calendar } from '@calendarjs/react';

export default function App() {
    const [value, setValue] = useState('2025-01-15');
    return <Calendar type="inline" value={value} onChange={setValue} />;
}

Schedule

An event scheduler with day / week / weekdays views, drag-and-drop, conflict detection, and undo/redo.

import React, { useRef, useState } from 'react';
import { Schedule } from '@calendarjs/react';

export default function App() {
    const ref = useRef();
    const [events, setEvents] = useState([
        { title: 'Meeting', start: '09:00', end: '10:00', date: '2025-01-15', color: '#3498db' },
    ]);
    return (
        <Schedule
            ref={ref}
            type="week"
            value="2025-01-15"
            data={events}
            onCreate={(events) => console.log('created', events)}
            onChangeEvent={(event, oldValue, newValue) => console.log('updated', event)}
            onDelete={(event) => console.log('deleted', event)}
        />
    );
}

Timeline

A chronological event display with monthly grouping, sorting, and custom alignment.

import React from 'react';
import { Timeline } from '@calendarjs/react';

export default function App() {
    const data = [
        { title: 'Issue Identification', date: new Date(2025, 5, 1) },
        { title: 'Root Cause Analysis', date: new Date(2025, 5, 2) },
        { title: 'Implementation', date: new Date(2025, 5, 3), borderColor: '#808000', borderStyle: 'dashed' },
    ];
    return <Timeline data={data} type="monthly" />;
}

Idiomatic React API

All three components support:

  • camelCase callbacksonChange, onCreate, onUpdate, onClose, onOpen, onDelete, onError, onChangeEvent, onBeforeChange, onBeforeCreate, onBeforeChangeEvent, onBeforeInsert, onEdition, onDblClick. The wrapper drops the leading self argument before invoking your handler — the underlying instance is available via the forwarded ref.
  • ref forwarding<Calendar ref={r} /> followed by r.current.next() etc.
  • children — render overlays alongside the component.
  • className / style — forwarded to the wrapper element.
  • data-* / aria-* / role — passed through to the wrapper <div> (handy for Playwright / Testing Library).
<Schedule data-testid="weekly-schedule" aria-label="Class timetable" data={events} />

Controlled vs imperative

Both modes are first-class. Pick by interaction style:

  • Controlled — React state is the source of truth. Best for read-mostly views (timetable display, dashboards).
  • Imperative — talk to the instance via the ref. Best for edit-heavy interaction where a full re-render would lose focus / drag selection (drag-to-create, in-place mutations).
// Controlled — replace the array reference to update.
const [events, setEvents] = useState([
    { start: '09:00', end: '10:00', date: '2025-01-15', title: 'Meeting' },
]);

return (
    <Schedule
        data={events}
        onCreate={(created) => setEvents((prev) => [...prev, ...created])}
    />
);
// Imperative — mutate via the ref, no React re-render.
const ref = useRef();

const flagWarning = (guid) => {
    const ev = ref.current.data.find((e) => e.guid === guid);
    ev.warning = true;
    ref.current.render();
};

return <Schedule ref={ref} data={initialEvents} />;

Reference identity matters

The wrapper diff-checks props with !==. Replace the array to trigger a re-render; mutating in place won't:

// ✅ New reference — re-renders
setEvents([...events, newEvent]);

// ❌ Same reference — no re-render
events.push(newEvent);

If you need to edit events in place (toggle warning, adjust color, etc.), use the imperative ref pattern above and call ref.current.render().

Memoize handlers

The prop sync runs on every parent render. Inline arrow functions reallocate every time; lemonadejs's !== check absorbs the no-op, but useCallback makes the intent explicit and keeps the prop diff cheap:

const onCreate = useCallback(
    (created) => setEvents((prev) => [...prev, ...created]),
    [],
);
return <Schedule data={events} onCreate={onCreate} />;

Hooks

useCalendar / useSchedule / useTimeline are an optional alternative to manual refs. Each returns a callback ref to pass to the component plus a reactive instance that is null before mount and the lemonadejs instance after — useful when you want to render conditionally based on whether the component is mounted.

import { Schedule, useSchedule } from '@calendarjs/react';

export default function App() {
    const { ref, instance } = useSchedule();
    const [events, setEvents] = useState([]);

    return (
        <>
            <button disabled={!instance} onClick={() => instance.addEvents([{ start: '09:00' }])}>
                Add event
            </button>
            <Schedule
                ref={ref}
                data={events}
                onCreate={(created) => setEvents((prev) => [...prev, ...created])}
            />
        </>
    );
}

The plain useRef pattern is still fully supported — pick whichever fits your component shape.

Migrating from @calendarjs/ce + a hand-rolled adapter

If your app currently wraps the vanilla CalendarJS bundle in a custom React adapter, you can drop in @calendarjs/react and delete the adapter:

| Before | After | | --------------------------------------------------------- | ------------------------------------------------------ | | import calendarjs from '@calendarjs/ce' | import { Schedule } from '@calendarjs/react' | | Custom <ScheduleAdapter> around calendarjs.Schedule | Use <Schedule> directly | | adapter.current.instance.addEvents(...) | ref.current.addEvents(...) (or useSchedule) | | Hand-rolled prop diff in useEffect | Built in — pass props normally | | Manual import 'calendarjs/dist/style.css' | Auto-loaded; or import '@calendarjs/react/style.css' | | (self, events) => handler(events) callback wrapper | onCreate={(events) => ...} — no self argument | | events as Schedule.Event[] cast on input data | Loose Schedule.EventInput[] accepted directly | | Array.isArray(events) ? events : [events] in onCreate | events is always Schedule.Event[] (length ≥ 1) |

For per-component option, method, and event details, see:

Versioning

@calendarjs/react is a thin re-export package. It tracks the underlying plugins via semver-compatible peer ranges. To pin specific plugin versions, install them directly alongside this package.

License

MIT.