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

reapex-date

v0.2.0

Published

Headless, accessible, fully customizable React Date & Time Picker with i18n, range selection, and data-attribute styling

Readme

ReApexDate

A headless, accessible, and highly customizable React Date & Time Picker for modern applications.

npm TypeScript License: MIT Package Size

Live Playground · npm · GitHub


Why ReApexDate?

Most datepickers force their design on your app. ReApexDate doesn't.

It handles the hard parts — you control the look and feel.

ReApexDate handles:

✅ Date calculations & calendar math
✅ Single / Range / Multi-select logic
✅ Date + Time with seconds precision
✅ Keyboard navigation (arrow keys, Enter, Escape)
✅ WAI-ARIA accessibility & focus trapping
✅ 8 built-in locales with auto-RTL
✅ Min/max dates, disabled dates
✅ Typed input with auto-inserted separators (new in 0.2)
✅ Dual-month view, portal, match-width popover (new in 0.2)
✅ Form props, error state, uncontrolled mode (new in 0.2)

YOU control:

🎨 Design & colors
🎨 CSS framework (Tailwind, vanilla, anything)
🎨 Layout & spacing
🎨 Typography & branding
🎨 Component structure

Style everything through data-* attributes — no CSS imports, no style overrides, no !important hacks.


📦 Install

npm install reapex-date

Peer deps: react >= 18.0.0, react-dom >= 18.0.0
Installed automatically: dayjs, @floating-ui/react


⚡ 30-Second Quick Start

import { useState } from 'react';
import { DatePickerInput } from 'reapex-date';

function App() {
  const [date, setDate] = useState<Date | null>(null);

  return (
    <DatePickerInput
      config={{ mode: 'single', value: date, onChange: setDate }}
      placeholder="Pick a date..."
      allowClear
    />
  );
}

That's it. No CSS import. No theme provider. Just works.


🎯 What Can You Build?

Single Date Picker

<DatePickerInput
  config={{ mode: 'single', value, onChange: setValue }}
  locale={en}
  placeholder="Select date..."
/>

Date Range Picker

<DatePickerInput
  config={{ mode: 'range', value: range, onChange: setRange }}
  format="DD/MM/YYYY"
  placeholder="Start → End"
/>

DateTime Picker (with Input + Popover)

<DateTimePickerInput
  value={dateTime}
  onChange={setDateTime}
  use12Hour            // 12h with AM/PM
  showSeconds          // HH:MM:SS precision
  minuteStep={5}       // 5-min intervals
  okText="Confirm"
/>

Multi-Select Calendar

<CalendarRoot
  config={{ mode: 'multiple', value: dates, onChange: setDates }}
  renderFooter={() => <span>{dates.length} selected</span>}
/>

Localized (RTL Arabic)

import { ar } from 'reapex-date';

<DatePickerInput config={config} locale={ar} />
// Automatically sets dir="rtl", Arabic month/day names, Saturday start

🆕 What's New in 0.2.0

| Feature | Prop | Notes | |---------|------|-------| | Typed input + auto separators | editable | Type 15012026 → 15/01/2026. Committed on Enter / blur, invalid or disabled dates are rejected (onInvalidInput). Single & range modes. Opt-in (default false). | | Dual-month view | monthsToShow={2} | Two months side by side, works in every mode. Default 1. | | Portal | portal, portalContainer | Render the popover in document.body so overflow:hidden parents can't clip it. | | Match input width | matchWidth | Popover is at least as wide as the input. | | Placement | placement | Optional override. Default is automatic: flips upward / aligns to the end when there is no room. | | Form integration | name, id, required, ref, onFocus, onBlur | Renders hidden input(s) for native form submit (display format; range → name_start / name_end). ref points at the visible input. | | Error state | error | Sets aria-invalid + data-invalid on the wrapper. Style it yourself, e.g. [data-datepicker-wrapper][data-invalid] [data-datepicker-input] { border-color: #ef4444 } | | Uncontrolled mode | config.defaultValue | Omit value and let the picker manage its own state; onChange still fires. | | Smarter fallback placement | — | Popover flip fallbacks are now top-start, top-end, bottom-end. |

// Typed range with a native form field
<form>
  <DatePickerInput
    editable
    name="period"
    format="DD/MM/YYYY"
    monthsToShow={2}
    portal
    matchWidth
    required
    error={hasError}
    config={{ mode: 'range', value: range, onChange: setRange }}
    onInvalidInput={(text) => console.warn('Bad date:', text)}
  />
</form>

// Uncontrolled
<DatePickerInput config={{ mode: 'single', defaultValue: new Date(), onChange: console.log }} />

Use shouldDisableDate: (date) => boolean in config to block custom dates (e.g. weekends); it also applies to typed input.

New utilities: applyDateMask, getMaskLength, isMaskableFormat. CalendarRoot gained monthsToShow and style; useDatePickerPopover accepts { placement, matchWidth }.


🌍 Built-in Locales

| Locale | Code | Direction | Week Start | |--------|------|-----------|------------| | English | en | LTR | Sunday | | Hindi | hi | LTR | Sunday | | French | fr | LTR | Monday | | German | de | LTR | Monday | | Spanish | es | LTR | Monday | | Japanese | ja | LTR | Sunday | | Chinese | zh | LTR | Monday | | Arabic | ar | RTL | Saturday |


🎨 Styling with Data Attributes

ReApexDate renders unstyled semantic HTML. Style it with any CSS framework:

/* Selected date */
[data-calendar-grid] td button[data-selected="true"] {
  background: #2563eb;
  color: white;
  border-radius: 50%;
}

/* Today */
[data-calendar-grid] td button[data-today="true"] {
  outline: 2px solid #3b82f6;
  font-weight: bold;
}

/* Range highlight */
[data-calendar-grid] td button[data-in-range="true"] {
  background: #dbeafe;
}

/* Disabled */
[data-calendar-grid] td button[data-disabled="true"] {
  opacity: 0.3;
  cursor: not-allowed;
}

All Data Attributes

| Attribute | Element | Description | |-----------|---------|-------------| | data-selected | Day button | Currently selected | | data-today | Day button | Today's date | | data-in-range | Day button | Between range start/end | | data-range-start | Day button | First date of range | | data-range-end | Day button | Last date of range | | data-outside-month | Day button | Prev/next month dates | | data-disabled | Day button | Cannot be selected | | data-focused | Day button | Keyboard focus | | data-time-cell | Time button | Hour/minute/second cells | | data-calendar-root | Container | Root element | | data-view | Container | day / month / year |


🏗️ Architecture

src/
├── engine/              # Pure date math (zero React imports)
├── hooks/               # Stateful React layer
├── a11y/                # Keyboard nav, focus trap, click-outside
├── locales/             # 8 i18n configurations
├── components/
│   ├── Calendar/        # CalendarRoot, Header, Grid, MonthView, YearView
│   ├── DatePickerInput/ # Input + popover for dates
│   ├── TimePicker/      # Scrollable hour/min/sec columns
│   ├── DateTimePicker/  # Inline calendar + time
│   └── DateTimePickerInput/ # Input + popover for date+time
└── utils/               # formatDate, dateAdapter

Engine layer is framework-agnostic — pure functions with zero React imports. Can be ported to Vue, Svelte, or vanilla JS.


📊 Package Size

| Metric | Size | |--------|------| | npm tarball (npm pack) | ~52 KB | | Unpacked | ~244 KB (JS + type declarations) | | Runtime dependencies | dayjs, @floating-ui/react (installed once, not bundled) |

Tree-shakeable (sideEffects: false). Only pay for what you import.


🤝 Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.


📄 License

MIT — Use it freely in personal and commercial projects.