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

@bhavishyjain/react-native-date-time-picker

v0.1.2

Published

A smooth, animated date and time picker for React Native with no native dependencies

Readme

react-native-date-time-picker

A smooth, fully-animated date & time picker for React Native — zero native modules, zero date libraries.

npm MIT License TypeScript Expo Compatible Platform


Demo

A minimal demo page can be found in the example directory.

🌐 Live demo is also available:
👉 https://react-native-date-time-picker.vercel.app/


Features

  • 7 picker modes — date, time, datetime, range, multi, month, year
  • 2 date UI variants — interactive calendar or scroll wheel
  • 2 time UI variants — scroll wheel or analog clock (with 24h support)
  • Inline or modal — embed directly, or open as a bottom / center / top sheet
  • Full timezone support via IANA identifiers
  • Internationalization — any BCP-47 locale, RTL-aware formatting
  • Accessibility — ARIA roles, keyboard navigation, reduced-motion support
  • Fully typed — complete TypeScript definitions exported
  • No native linking — pure JS + Reanimated + Gesture Handler
  • Cross-platform — iOS, Android, and Web (React Native Web / Expo Web)

Platform Support

| Platform | Supported | | --------------------- | --------- | | iOS | ✅ | | Android | ✅ | | Expo (managed & bare) | ✅ | | React Native Web | ✅ | | Expo Web | ✅ |

No Expo dependency required. The library only depends on react-native, react-native-reanimated, react-native-gesture-handler, and react-native-safe-area-context — all of which work in bare React Native, Expo managed workflow, and on the web.


Installation

npm install @bhavishyjain/react-native-date-time-picker\
            react-native-reanimated \
            react-native-gesture-handler \
            react-native-safe-area-context

Babel plugin (Expo / Metro)

Add the Reanimated plugin to your babel.config.js:

module.exports = {
  presets: ["babel-preset-expo"],
  plugins: ["react-native-reanimated/plugin"],
};

Entry-point import

Add this to the very top of your app entry file (before any other imports):

import "react-native-gesture-handler";

Wrap your app

import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <SafeAreaProvider>{/* your app */}</SafeAreaProvider>
    </GestureHandlerRootView>
  );
}

Quick Start

import React, { useState } from "react";
import { DateTimePicker } from "react-native-date-time-picker";

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

  return <DateTimePicker inline mode="date" value={date} onChange={setDate} />;
}

Usage Examples

Date picker

<DateTimePicker inline mode="date" value={date} onChange={setDate} />

Time picker (12-hour, 5-minute steps)

<DateTimePicker
  inline
  mode="time"
  is24Hour={false}
  minuteInterval={5}
  value={date}
  onChange={setDate}
/>

Date + Time (combined)

<DateTimePicker
  inline
  mode="datetime"
  datePickerVariant="calendar"
  timePickerVariant="wheel"
  value={date}
  onChange={setDate}
/>

Date range

import { DateRange } from "react-native-date-time-picker";

const [range, setRange] = useState<DateRange>({ start: null, end: null });

<DateTimePicker
  inline
  mode="range"
  value={range}
  onChange={(v) => setRange(v as DateRange)}
  onRangeIncomplete={() => Alert.alert("Please select an end date")}
/>;

Multi-date selection

<DateTimePicker
  inline
  mode="multi"
  maxMultiSelect={5}
  value={dates}
  onChange={(v) => setDates(v as Date[])}
  onMaxReached={() => Alert.alert("Maximum 5 dates")}
/>

Month picker

import { MonthValue } from "react-native-date-time-picker";

const [month, setMonth] = useState<MonthValue>({
  year: new Date().getFullYear(),
  month: new Date().getMonth(),
});

<DateTimePicker
  inline
  mode="month"
  value={month}
  onChange={(v) => setMonth(v as MonthValue)}
/>;

Year picker

<DateTimePicker
  inline
  mode="year"
  value={new Date().getFullYear()}
  onChange={(v) => setYear(v as number)}
/>

Modal with placeholder trigger

<DateTimePicker
  mode="datetime"
  inline={false}
  placeholder="Select a date & time"
  value={date ?? undefined}
  onChange={setDate}
  modalPosition="bottom"
  onOpen={() => console.log("opened")}
  onClose={() => console.log("closed")}
/>

Live preview (onChangeImmediate)

const [committed, setCommitted] = useState<Date | null>(null);
const [preview, setPreview] = useState<Date | null>(null);

<DateTimePicker
  inline
  mode="datetime"
  value={committed}
  onChange={setCommitted}
  onChangeImmediate={(v) => setPreview(v as Date)}
/>;

Disabled dates

// Array of specific dates
<DateTimePicker
  inline
  mode="date"
  disabledDates={[new Date('2025-12-25'), new Date('2025-12-26')]}
  value={date}
  onChange={setDate}
/>

// Date range
<DateTimePicker
  inline
  mode="date"
  disabledDates={[{ from: new Date('2025-06-01'), to: new Date('2025-06-15') }]}
  value={date}
  onChange={setDate}
/>

// Custom function
<DateTimePicker
  inline
  mode="date"
  disabledDates={(d) => d.getDay() === 0 || d.getDay() === 6} // disable weekends
  value={date}
  onChange={setDate}
/>

Marked dates

import { MarkedDate } from "react-native-date-time-picker";

const marked: MarkedDate[] = [
  { date: new Date(), dot: "#f43f5e" },
  { date: new Date("2025-12-25"), label: "🎄" },
];

<DateTimePicker
  inline
  mode="date"
  markedDates={marked}
  value={date}
  onChange={setDate}
/>;

Custom theme

<DateTimePicker
  inline
  mode="date"
  accentColor="#f97316"
  darkMode={false}
  customTheme={{
    background: "#FFF8F0",
    surface: "#FEF3E2",
    accent: "#F97316",
    text: "#1C0A00",
    border: "#FDE8C8",
    rangeBackground: "#FDBA7420",
    radius: 20,
  }}
  value={date}
  onChange={setDate}
/>

Min / Max time

<DateTimePicker
  inline
  mode="time"
  minTime="09:00"
  maxTime="18:00"
  value={date}
  onChange={setDate}
/>

Timezone & locale

<DateTimePicker
  inline
  mode="datetime"
  locale="ja-JP"
  timezone="Asia/Tokyo"
  value={date}
  onChange={setDate}
/>

Modes

| Mode | value type | Description | | ---------- | ---------------------------------------- | -------------------------------------- | | date | Date \| null | Single date picker | | time | Date \| null | Time-only picker | | datetime | Date \| null | Combined date + time | | range | { start: Date\|null; end: Date\|null } | Start / end date range | | multi | Date[] | Multiple date selection | | month | { year: number; month: number } | Month-only picker (month is 0-indexed) | | year | number | Year-only picker |


Props

Core

| Prop | Type | Default | Description | | ------------------- | --------------------------------------------------------------------------- | ------------ | ------------------------------------------------------------ | | mode | 'date' \| 'time' \| 'datetime' \| 'range' \| 'multi' \| 'month' \| 'year' | required | Picker presentation mode | | value | Date \| DateRange \| Date[] \| MonthValue \| number \| null | undefined | Controlled selected value | | onChange | (value: PickerValue) => void | required | Called when the value is committed (Confirm pressed) | | onChangeImmediate | (value: PickerValue) => void | undefined | Called on every intermediate selection change (live preview) |

Date options

| Prop | Type | Default | Description | | ------------------- | ------------------------------------------------------------ | ------------ | ------------------------------------------------------- | | datePickerVariant | 'calendar' \| 'wheel' | 'calendar' | Date UI for date, datetime, and month modes | | firstDayOfWeek | 0 \| 1 | 0 | 0 = Sunday, 1 = Monday | | highlightToday | boolean | true | Show a border ring on today's date | | showWeekNumbers | boolean | false | Show ISO week number column | | minDate | Date | undefined | Disable dates before this date | | maxDate | Date | undefined | Disable dates after this date | | disabledDates | Date[] \| DisabledDateRange[] \| ((date: Date) => boolean) | undefined | Disable specific dates, ranges, or via custom predicate | | markedDates | MarkedDate[] | undefined | Add dot or label markers to specific calendar dates |

Time options

| Prop | Type | Default | Description | | ------------------- | -------------------------- | ----------- | ----------------------------------------------- | | timePickerVariant | 'wheel' \| 'clock' | 'wheel' | Time UI for time and datetime modes | | is24Hour | boolean | false | 24-hour vs 12-hour (AM/PM) display | | showSeconds | boolean | false | Enable second selection | | minuteInterval | 1 \| 5 \| 10 \| 15 \| 30 | 1 | Minute scroll step | | minTime | string | undefined | Minimum selectable time (HH:mm or HH:mm:ss) | | maxTime | string | undefined | Maximum selectable time (HH:mm or HH:mm:ss) |

Multi-select options

| Prop | Type | Default | Description | | ---------------- | ------------ | ----------- | ----------------------------------------- | | maxMultiSelect | number | undefined | Maximum dates selectable in multi mode | | onMaxReached | () => void | undefined | Called when user exceeds maxMultiSelect |

Range options

| Prop | Type | Default | Description | | ------------------- | ------------ | ----------- | ------------------------------------------------------------- | | onRangeIncomplete | () => void | undefined | Called on Confirm when range has a start date but no end date |

Theming

| Prop | Type | Default | Description | | ------------- | ---------------------------- | -------------- | ------------------------------------ | | accentColor | string | '#3B82F6' | Primary selection / highlight colour | | darkMode | boolean | follows system | Force dark or light palette | | customTheme | Partial<PickerThemeValues> | undefined | Override individual palette tokens |

customTheme keys: accent, background, surface, text, textMuted, border, rangeBackground, selectedText, todayBorder, radius, wheelHighlight

Modal / Display

| Prop | Type | Default | Description | | ------------------ | ------------------------------- | ----------- | ----------------------------------------------------------- | | inline | boolean | true | Embed inline or show as a modal sheet | | visible | boolean | false | Controls modal visibility (ignored when inline) | | modalPosition | 'top' \| 'center' \| 'bottom' | 'center' | Anchor position for modal presentation | | placeholder | string | undefined | Renders a trigger button and manages modal state internally | | placeholderStyle | TextStyle | undefined | Override trigger button text style | | confirmLabel | string | 'Confirm' | Footer confirm button text | | clearLabel | string | 'Clear' | Footer clear/reset button text | | disabled | boolean | false | Dim and block all interaction |

Callbacks

| Prop | Type | Description | | --------------- | --------------------------------------- | ---------------------------------------------- | | onOpen | () => void | Called when modal becomes visible | | onClose | () => void | Called when backdrop tapped or modal dismissed | | onDismiss | () => void | Called after modal animation completes | | onMonthChange | (year: number, month: number) => void | Called when visible calendar month changes |

Locale

| Prop | Type | Default | Description | | ---------- | -------- | ---------------- | --------------------------------------------- | | locale | string | system / en-US | BCP-47 locale for labels and formatting | | timezone | string | device timezone | IANA time zone ('UTC', 'Asia/Kolkata', …) |


Peer Dependencies

| Package | Version | | -------------------------------- | --------- | | react | >= 17 | | react-native | >= 0.71 | | react-native-reanimated | >= 3.0 | | react-native-gesture-handler | >= 2.0 | | react-native-safe-area-context | >= 4.0 |


Contributing

See CONTRIBUTING.md. Bug reports and pull requests are welcome.


License

MIT © Bhavishy Jain