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

@cyberlz/react-date-range

v1.3.0

Published

Modern maintained fork/rescue of react-date-range. Stable 1.3.x — configurable UI slots, opt-in design tokens, input-trigger pickers, accessibility and RTL support.

Readme

@cyberlz/react-date-range

Maintained fork/rescue of react-date-range. Current channel: 1.3.x is the stable release line on npm latest. It adds configurable UI slots and opt-in design tokens on top of the 1.2.x input-trigger picker and named range-slot baseline. The rc tag remains on 1.0.0-rc.0 for historical validation. See Dist-tag policy below.

Quick links

| Install | Getting started | Component reference | Accessibility | Troubleshooting | Integration snippets | Migration guide | Landing demo | Changelog | |---|---|---|---|---|---|---|---|---|


What is this?

This is a personal open-source initiative to rescue and modernize react-date-range, a popular React date range picker that has been archived by its original maintainer.

Not affiliated with the original maintainers, any commercial project, or any company. This workspace exists on a personal machine for convenience; it carries no branding or association beyond what is stated here.

Why?

react-date-range has 2,600+ GitHub stars, 700+ forks, and broad real-world usage, but the upstream repository is read-only and no longer maintained. Open issues include:

  • React 19 compatibility (#661, #662)
  • date-fns v3/v4 compatibility (#649, #663, #667)
  • TypeScript improvements (#260, #439, #513)
  • Accessibility (#373, #415/#416 — labels, roles, focus-visible states, and live-region announcements resolved)
  • RTL layout support (#669)
  • Cross-month passive-day range selection UX (#495)
  • React 18 StrictMode scroll bugs (#577, #653)

There are community forks, but none clearly active in 2026 with a published React 19 fix. This project aims to fill that gap.

Install

npm install @cyberlz/react-date-range
import { DatePickerInput, DateRangePicker } from '@cyberlz/react-date-range';
import '@cyberlz/react-date-range/styles.css';
import '@cyberlz/react-date-range/theme/default.css';

Migrating from react-date-range upstream? See docs/migration-from-upstream.md.

Accessibility baseline

The fork now covers the core ARIA labels and states tracked by upstream #415/#416:

| Area | Behavior | |------|----------| | Calendar grid | Named with ariaLabels.calendar and described with ariaLabels.calendarRoleDescription. | | Defined ranges | Static range buttons expose aria-pressed for the active preset. | | Input ranges | Number-of-days inputs are named by their rendered labels via aria-labelledby. | | Date display | The start/end date inputs are grouped with role="group" and ariaLabels.dateDisplay. Per-range labels are available via Range.label — when set, the per-range wrapper renders as a named role="group" with aria-labelledby. | | DatePickerInput | Read-only trigger input opens a named role="dialog" popover, reflects aria-expanded, closes on Escape/outside click/date selection, and returns focus to the trigger. | | DateRangePicker | Wrapper renders as role="region" named by ariaLabels.dateRangePicker; set ariaLabels.dateRangePicker = false to opt out. | | Calendar live region | Committed month/year navigation announced via aria-live="polite" region (customizable via ariaLabels.liveRegionMonthYear). Hover, drag movement, date selection, and scroll do not announce from Calendar itself. | | DateRange live region | Committed range selections announced via aria-live="polite" / aria-atomic="true" after DateRange normalizes the selected range. Customizable via ariaLabels.liveRegionSelection. Hover, preview, and drag movement do not announce. |

aria-live month/year and DateRange selection announcements are available. Announcements are tied to committed state changes only, so hover, preview, and drag-move updates do not over-announce.

Multi-range with labels

Assign label to each Range to name range slots for users and assistive tech:

const [ranges, setRanges] = useState([
  { startDate: new Date(), endDate: new Date('2026-07-14'), key: 'trip1', label: 'Trip 1' },
  { startDate: new Date('2026-08-01'), endDate: new Date('2026-08-07'), key: 'trip2', label: 'Trip 2' },
]);

<DateRangePicker ranges={ranges} onChange={({ trip1, trip2 }) => setRanges([trip1, trip2])} />

When label is set, DateDisplay renders each range inside role="group" aria-labelledby={id} so screen readers announce the label as the group's accessible name. Labels are rendered as plain text and are XSS-safe by design.

Input-trigger date picker

Use DatePickerInput when the UI needs a compact input trigger instead of an always-inline Calendar. The trigger is read-only in this first slice: users pick from the calendar popover, and manual text parsing is deferred.

import { useState } from 'react';
import { DatePickerInput } from '@cyberlz/react-date-range';

function TripDateField() {
  const [date, setDate] = useState(new Date());

  return (
    <DatePickerInput
      date={date}
      onChange={setDate}
      ariaLabel="Trip date"
      popoverLabel="Choose trip date"
      placeholder="Select a date"
      calendarProps={{ months: 1 }}
    />
  );
}

Controlled popover state is also supported via open, defaultOpen, and onOpenChange:

<DatePickerInput
  date={date}
  onChange={setDate}
  open={isOpen}
  onOpenChange={setIsOpen}
  ariaLabel="Controlled trip date"
/>

Input-trigger date range picker

Use DateRangeInput when the UI needs a compact input trigger for range selection instead of an always-inline DateRangePicker. The trigger is read-only: users pick from the calendar popover, and manual text parsing is deferred.

import { useState } from 'react';
import { DateRangeInput } from '@cyberlz/react-date-range';

function TripRangeField() {
  const [ranges, setRanges] = useState([
    { startDate: new Date(), endDate: new Date('2026-07-14'), key: 'trip' },
  ]);

  return (
    <DateRangeInput
      ranges={ranges}
      onChange={({ trip }) => setRanges([trip])}
      ariaLabel="Trip date range"
      popoverLabel="Choose trip dates"
      triggerPlaceholder="Select trip dates"
      calendarProps={{ months: 1 }}
    />
  );
}

Controlled popover state is also supported via open, defaultOpen, and onOpenChange:

<DateRangeInput
  ranges={ranges}
  onChange={({ trip }) => setRanges([trip])}
  open={isOpen}
  onOpenChange={setIsOpen}
  ariaLabel="Controlled trip date range"
/>

RTL layout support

Calendar, DateRange, and DateRangePicker accept an additive dir prop:

<DateRangePicker dir="rtl" direction="horizontal" />

| dir value | Behavior | |-------------|----------| | "rtl" | Renders dir="rtl", applies the rdrRtl class hook, mirrors navigation glyphs visually, and reverses horizontal month flow. | | "ltr" | Renders dir="ltr" without the RTL class hook. | | omitted | Leaves dir unset so the calendar can inherit direction from an ancestor. |

The existing direction prop still controls layout orientation ("vertical" or "horizontal"); it is separate from text direction. Consumers can override the RTL hook with classNames={{ rtl: 'my-rtl' }}.

Custom navigatorRenderer output is not wrapped or transformed by the library. If a custom renderer uses chevrons, alignment, or directional icons, it must handle RTL mirroring itself.

Goal

A modern, maintained, production-ready date range picker for React that:

  • Works with React 18 and 19 without warnings or workarounds
  • Is fully typed (TypeScript-first)
  • Has a modern build (ESM + CJS, real tree-shaking, no side-effect imports)
  • Is SSR-safe
  • Preserves the existing API so current users can upgrade without rewrites
  • Keeps the compatibility surface focused on the maintained react-date-range experience

Current phase

| Phase | Status | |-------|--------| | Phase 0 — Audit & planning | Complete | | Phase 1 — Compatible rescue | Complete | | Phase 3 — Core refactor | Complete (Slices 1–21 done) |

@cyberlz/[email protected] is the stable release line on npm latest. 1.0/1.1/1.2/1.3 are stable, additive, and non-breaking. 1.3 adds configurable UI slots and opt-in CSS design tokens on top of the 1.2 input-trigger picker baseline. Future work is tracked separately. See docs/fork-roadmap.md for the full plan and docs/refactor-roadmap.md for incremental refactor slices.

Dist-tag policy

npm has four relevant dist-tags for this package:

  • latest — points to the current 1.3.x stable release. Default install path: npm install @cyberlz/react-date-range.
  • rc — points to 1.0.0-rc.0. Historical release candidate for pre-release validation: npm install @cyberlz/react-date-range@rc.
  • beta — points to 0.1.0-beta.0. Legacy prerelease channel.
  • alpha — points to 0.1.0-alpha.3. Legacy prerelease channel.

For stable installs, consumers use npm install @cyberlz/react-date-range (no tag). See docs/migration-from-upstream.md for upgrade instructions. See docs/release-flow.md for the full policy.

Build pipeline

Package build produces consumable dist/ output:

npm run build          # tsdown (JS, multi-entry + unbundle) + sass (CSS) + types copy

Output: | Path | Purpose | |------|---------| | dist/index.mjs | ESM barrel (bundlers, import) | | dist/index.cjs | CJS barrel (Node.js require) | | dist/components/<Component>/index.{mjs,cjs} | Per-component sub-modules (preserved by multi-entry glob for real tree-shaking) | | dist/styles.css | Compiled CSS (import separately) | | dist/index.d.ts | TypeScript declarations | | dist/theme/default.css | Default theme CSS | | dist/theme/tokens.css | Optional CSS custom-property token layer |

Consumer import (ESM / TSX):

import { DateRangePicker } from '@cyberlz/react-date-range';
import '@cyberlz/react-date-range/styles.css';

Consumer import (CJS):

const { DateRangePicker } = require('@cyberlz/react-date-range');
require('@cyberlz/react-date-range/styles.css');

No custom Vite/esbuild loaders required — the compiled output is plain JS/CSS.

Smoke-test fixtures:

  • spikes/consumer-js/ — JS consumer importing compiled output
  • spikes/consumer-tsx/ — TSX consumer with type validation (tsc --noEmit)
  • spikes/tree-shaking/ — Tree-shaking analysis (Calendar-only vs DateRangePicker)

Tree-shaking

Tree-shaking works since 0.1.0-alpha.3 and remains part of the stable 1.x line. The build uses tsdown with unbundle: true and a multi-entry glob, so each component is emitted as its own file and bundlers can drop unused exports. Verified empirically with spikes/tree-shaking/analyze.mjs:

| Consumer import | Output size | |-----------------|-------------| | import { Calendar } | ~41 KB | | import { DateRangePicker } | ~58 KB | | Delta | +17 KB (real tree-shaking) |

CJS consumers do not benefit equally (CJS is not tree-shakeable by design); ESM + modern bundlers (Vite, Webpack 5, esbuild, Rollup) get the full benefit.

Not committed for 1.x

  • Breaking API changes
  • Speculative visual redesign tracks such as dual skins or Tailwind theming
  • Breaking feature tracks without a compatibility plan

Demo and documentation roadmap

  • Local demo: demo/ is the current verified Vite consumer. During development it resolves package imports to local src/ so unreleased fixes are exercised before publishing.
  • Public demo: https://sokaluis.github.io/react-date-range/ is deployed with GitHub Pages from demo/.
  • Full library documentation: available — component reference at docs/components/, covering props, examples, migration notes, styling, accessibility, and roadmap status.

See docs/docs-site-plan.md for the landing/docs plan and docs/post-1.0-roadmap.md for the broader post-1.0 direction.

License

Upstream is MIT. This package is published as MIT and preserves upstream attribution in NOTICE.md.

Navigation

Links