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 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-daterange-lite

v0.1.2

Published

A lightweight, performant React date range picker using dayjs - optimized for modern React applications

Readme

React Date Range Lite

A lightweight, performant React date range picker library built with dayjs. Optimized for modern React applications with minimal bundle size, tree-shaking support, and full TypeScript coverage.

Features

  • 🚀 Lightweight: Uses dayjs (~2KB) for smaller bundle size
  • 📦 Tree-shakable: Named exports allow bundlers to eliminate unused code
  • Performant: Optimized with React.memo, useMemo, and useCallback
  • 🎨 Modern UI: Clean, accessible interface with smooth interactions
  • 🔧 TypeScript: Full TypeScript support with comprehensive type definitions
  • Accessible: WCAG 2.1 AA compliant with keyboard navigation
  • 🎨 Customizable: Theme colors, custom styles, and flexible date formatting

Quick Start

Installation

npm install react-daterange-lite dayjs
# or
yarn add react-daterange-lite dayjs
# or
pnpm add react-daterange-lite dayjs

Basic Usage

Predefined ranges (Today, Yesterday, This Week, Last 7 Days, Last 30 Days, This Month, Last Month) are visible by default. No configuration needed!

import React, { useState } from 'react';
import { DateRangePicker } from 'react-daterange-lite';
import 'react-daterange-lite/styles';

function App() {
  const [state, setState] = useState({
    selection: {
      startDate: new Date(),
      endDate: new Date(),
      key: 'selection',
    },
  });

  return (
    <DateRangePicker
      onChange={(item) => setState({ selection: item.selection })}
      ranges={[state.selection]}
    />
  );
}

With Custom Theme Color

<DateRangePicker
  onChange={(item) => setState({ selection: item.selection })}
  ranges={[state.selection]}
  themeColor="#3d91ff" // Customize selected range color, hover borders, focus styles
/>

Customizing Predefined Ranges

By default, predefined ranges are visible. You can customize them or disable them:

Use Custom Predefined Ranges:

import dayjs from 'dayjs';

const customStaticRanges = [
  {
    label: 'Last 14 Days',
    range: () => ({
      startDate: dayjs().subtract(13, 'day').toDate(),
      endDate: dayjs().toDate(),
      key: 'last14Days',
    }),
    isSelected: (range) => {
      if (!range.startDate || !range.endDate) return false;
      const start = dayjs().subtract(13, 'day');
      const end = dayjs();
      return dayjs(range.startDate).isSame(start, 'day') && dayjs(range.endDate).isSame(end, 'day');
    },
  },
  {
    label: 'Last 90 Days',
    range: () => ({
      startDate: dayjs().subtract(89, 'day').toDate(),
      endDate: dayjs().toDate(),
      key: 'last90Days',
    }),
    isSelected: (range) => {
      if (!range.startDate || !range.endDate) return false;
      const start = dayjs().subtract(89, 'day');
      const end = dayjs();
      return dayjs(range.startDate).isSame(start, 'day') && dayjs(range.endDate).isSame(end, 'day');
    },
  },
];

<DateRangePicker
  onChange={(item) => setState({ selection: item.selection })}
  ranges={[state.selection]}
  staticRanges={customStaticRanges}
/>

Disable Predefined Ranges:

<DateRangePicker
  onChange={(item) => setState({ selection: item.selection })}
  ranges={[state.selection]}
  staticRanges={[]} // Empty array disables predefined ranges
/>

Access Default Predefined Ranges:

If you want to extend or modify the default ranges, you can import them:

import { DateRangePicker, defaultStaticRanges } from 'react-daterange-lite';

// Extend default ranges
const customRanges = [
  ...defaultStaticRanges,
  {
    label: 'Custom Range',
    range: () => ({
      startDate: dayjs().subtract(10, 'day').toDate(),
      endDate: dayjs().toDate(),
      key: 'custom',
    }),
    isSelected: (range) => {
      // Your selection logic
      return false;
    },
  },
];

<DateRangePicker
  onChange={(item) => setState({ selection: item.selection })}
  ranges={[state.selection]}
  staticRanges={customRanges}
/>

Examples

Editable Date Inputs

<DateRangePicker
  ranges={[state.selection]}
  onChange={(item) => setState({ selection: item.selection })}
  editableDateInputs={true}
  dateDisplayFormat="MM/DD/YYYY"
/>

Disabled Dates

import dayjs from 'dayjs';

<DateRangePicker
  ranges={[state.selection]}
  onChange={(item) => setState({ selection: item.selection })}
  disabledDates={[dayjs().add(1, 'day').toDate(), dayjs().add(2, 'day').toDate()]}
  minDate={dayjs().subtract(1, 'month').toDate()}
  maxDate={dayjs().add(3, 'month').toDate()}
  disabledDay={(date) => date.day() === 0 || date.day() === 6} // Disable weekends
/>;

Single Month Display

<DateRangePicker
  ranges={[state.selection]}
  onChange={(item) => setState({ selection: item.selection })}
  months={1}
/>

Custom Styling

<DateRangePicker
  ranges={[state.selection]}
  onChange={(item) => setState({ selection: item.selection })}
  themeColor="#ff6b6b"
  classNames={{
    dateRangePickerWrapper: 'custom-wrapper',
    calendarWrapper: 'custom-calendar',
  }}
  styles={{
    dateDisplay: {
      backgroundColor: '#f8f9fa',
    },
  }}
/>

API Reference

DateRangePicker Props

| Prop | Type | Default | Description | | ------------------------------- | ------------------------------------------ | --------------- | -------------------------------------------------------------------- | | ranges | Range[] | - | Array of range objects to display | | onChange | (item: RangeKeyDict) => void | - | Callback fired when the user changes the date | | onRangeFocusChange | (focusedRange: [number, number]) => void | - | Callback fired when the user changes the focused range | | startDate | DateInput | - | Initial start date | | endDate | DateInput | - | Initial end date | | focusedRange | [number, number] | [0, 0] | Initial focused range | | initialFocusedRange | [number, number] | [0, 0] | Initial focused range | | months | number | 2 | Number of months to display | | direction | 'horizontal' \| 'vertical' | 'horizontal' | Direction of calendar months | | showMonthArrow | boolean | true | Show month navigation arrows | | showDateDisplay | boolean | true | Show date display | | showPreview | boolean | true | Show preview range | | editableDateInputs | boolean | false | Allow manual date input | | dragSelectionEnabled | boolean | true | Enable drag selection | | moveRangeOnFirstSelection | boolean | false | Move range on first selection | | retainEndDateOnFirstSelection | boolean | false | Retain end date on first selection | | calendarFocus | 'forwards' \| 'backwards' | 'forwards' | Which calendar to focus | | disabledDates | DateInput[] | - | Array of disabled dates | | disabledDay | (date: Dayjs) => boolean | - | Function to disable days | | minDate | DateInput | - | Minimum selectable date | | maxDate | DateInput | - | Maximum selectable date | | dateDisplayFormat | string | 'MMM D, YYYY' | Date display format | | monthDisplayFormat | string | 'MMMM YYYY' | Month display format | | weekdayDisplayFormat | string | 'dd' | Weekday format | | dayDisplayFormat | string | 'D' | Day format | | weekStartsOn | number | 0 | Week start day (0-6, 0 = Sunday) | | locale | LocaleConfig | - | Locale configuration | | className | string | - | Custom CSS class | | classNames | ClassNames | - | Custom class names object | | styles | Styles | - | Custom styles object | | themeColor | string | '#3d91ff' | Primary theme color for selected ranges, hover borders, focus styles | | color | string | '#3d91ff' | Legacy prop, use themeColor instead | | staticRanges | StaticRange[] | defaultStaticRanges | Predefined ranges (default: Today, Yesterday, This Week, Last 7 Days, Last 30 Days, This Month, Last Month). Pass [] to disable. | | inputRanges | InputRange[] | - | Input-based ranges | | onShownDateChange | (shownDate: Dayjs) => void | - | Callback for shown date change | | onPreviewChange | (preview: Range \| null) => void | - | Callback for preview change | | renderStaticRangeLabel | (staticRange: StaticRange) => ReactNode | - | Custom render function | | renderInputRangeLabel | (inputRange: InputRange) => ReactNode | - | Custom render function | | ariaLabels | AriaLabels | - | ARIA labels object | | wrapperClassName | string | - | Wrapper class name |

Range Interface

interface Range {
  startDate?: DateInput;
  endDate?: DateInput;
  color?: string;
  key?: string;
  autoFocus?: boolean;
  disabled?: boolean;
  showDateDisplay?: boolean;
}

DateInput Type

type DateInput = string | number | Date | Dayjs | null | undefined;

StaticRange Interface

interface StaticRange {
  label: string;
  range: () => Range;
  isSelected: (range: Range) => boolean;
}

Development

To preview the component locally:

# Install dependencies
npm install

# Start preview server
npm run preview
# or
npm run dev

This will start a development server with multiple examples showcasing different features of the date range picker.

Performance

  • Bundle Size: ~8-10KB gzipped (ESM: ~10KB, CJS: ~9KB) + ~2.4KB CSS
  • Tree-shaking: All utilities and components are tree-shakable
  • Optimizations:
    • React.memo for all components
    • useMemo for expensive calculations
    • useCallback for event handlers
    • Efficient date calculations with dayjs
    • Debounced hover and drag handlers

Browser Support

  • Chrome (last 2 versions)
  • Firefox (last 2 versions)
  • Safari (last 2 versions)
  • Edge (last 2 versions)

TypeScript

Full TypeScript support is included. All components and utilities are fully typed.

import { DateRangePicker, Range, RangeKeyDict } from 'react-daterange-lite';

const handleChange = (item: RangeKeyDict) => {
  const range: Range = item.selection;
  // TypeScript knows the structure
};

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

TODO / Future Improvements

The following items are planned for future releases:

Testing

  • [ ] Unit tests for utility functions (dateUtils, rangeUtils)
  • [ ] Component tests for DateRangePicker, Calendar, DateInput, DefinedRanges
  • [ ] Integration tests for user interactions (click, drag, keyboard navigation)
  • [ ] Visual regression tests
  • [ ] Accessibility tests (a11y)
  • [ ] Test coverage reporting (aim for >80% coverage)

Documentation

  • [ ] Storybook for interactive component documentation
  • [ ] More code examples and use cases
  • [ ] Migration guide from other date picker libraries
  • [ ] CHANGELOG.md for version history
  • [ ] CONTRIBUTING.md guidelines
  • [ ] API documentation with JSDoc comments

Features

  • [ ] Multiple range selection support
  • [ ] Internationalization (i18n) with locale support
  • [ ] More predefined range templates
  • [ ] Custom date formatting with dayjs plugins
  • [ ] Server-side rendering (SSR) optimization
  • [ ] React Server Components compatibility
  • [ ] Keyboard shortcuts documentation
  • [ ] Touch/mobile gesture improvements

Developer Experience

  • [ ] CI/CD pipeline (GitHub Actions)
  • [ ] Automated releases with semantic versioning
  • [ ] Bundle size monitoring
  • [ ] Performance benchmarking
  • [ ] TypeScript strict mode improvements
  • [ ] ESLint warnings resolution

Performance

  • [ ] Code splitting for large date ranges
  • [ ] Virtual scrolling for long date lists
  • [ ] Memoization optimizations
  • [ ] Bundle size analysis and optimization

License

MIT

Acknowledgments

This library provides a modern, lightweight date range picker solution using dayjs for optimal performance and bundle size.