npm package: @shanzy3/react-native-ui-datepicker
Description: Customizable date picker for React Native with minute interval and year-only picker support
Author: Eric Boles
Latest version: 3.2.3

<p align="center">
<img src="/.github/images/rnui-datepicker.png" alt="react-native-ui-datepicker" />
</p>

<div align="center">

[![npm version](https://img.shields.io/npm/v/@shanzy3/react-native-ui-datepicker)](https://www.npmjs.com/package/@shanzy3/react-native-ui-datepicker)
[![npm downloads](https://img.shields.io/npm/dm/@shanzy3/react-native-ui-datepicker.svg)](https://www.npmjs.com/package/@shanzy3/react-native-ui-datepicker)
[![Github](https://img.shields.io/github/license/Shanzy3/react-native-ui-datepicker)](https://github.com/Shanzy3/react-native-ui-datepicker)
[![gzipped size](https://img.shields.io/bundlephobia/minzip/@shanzy3/react-native-ui-datepicker)](https://www.npmjs.com/package/@shanzy3/react-native-ui-datepicker)

</div>

DateTimePicker component for React Native that allows you to create a customizable datetime picker. The component uses extensive set of props that allows you to customizing the calendar based on your own UI design.

## 🎉 Enhanced Fork Features

This fork extends the original [react-native-ui-datepicker](https://github.com/farhoudshapouran/react-native-ui-datepicker) with additional features:

- ⏰ **Minute Interval Support** - Control time picker intervals (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 minutes)
- 📅 **Year-Only Picker** - Dedicated year picker that returns just the year integer
- 🎨 **View Toggle Header** - Optional header with date/time toggle buttons
- 🌓 **Enhanced Dark Mode** - Improved theme support throughout all components

### New Props

| Prop                    | Type                                                                           | Description                                        |
| ----------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------- |
| `minuteInterval`        | `1` \| `2` \| `3` \| `4` \| `5` \| `6` \| `10` \| `12` \| `15` \| `20` \| `30` | Sets the minute interval for the time picker       |
| `yearPickerOnly`        | `boolean`                                                                      | Shows only year picker and returns year as integer |
| `showViewPickerButtons` | `boolean`                                                                      | Shows date/time toggle buttons in header           |
| `toggleHeaderLabel`     | `string`                                                                       | Optional label for the toggle header               |

## Features

- 📅 Supports different selection modes: single, range, and multiple days.
- 🌿 Unstyled by default, every component is minimally styled and fully customizable.
- 🛠️ Extensive set of props for fine-tuned calendar customization.
- 🎨 Fully compatible with [NativeWind](https://www.nativewind.dev/).
- 🌎 Easily localizable into any language.
- 🕗 Handles different time zones seamlessly.
- ⚙️ Customizable components allow extending rendered elements.
- ⚡ Fast & lightweight, only re-renders the elements that actually change.

## Installation

```sh
npm install @shanzy3/react-native-ui-datepicker
```

Or

```sh
yarn add @shanzy3/react-native-ui-datepicker
```

## Basic Usage

1. Import the component and default styles or classNames from `react-native-ui-datepicker`.
2. Choose a selection mode using the `mode` prop. The available modes are: `single`, `range`, and `multiple`.

```jsx
import { useState } from  'react';
import DateTimePicker, { DateType, useDefaultStyles } from '@shanzy3/react-native-ui-datepicker';

export function Calendar() {
  const defaultStyles = useDefaultStyles();
  const [selected, setSelected] = useState<DateType>();

  return (
    <DateTimePicker
      mode="single"
      date={selected}
      onChange={({ date }) =>  setSelected(date)}
      styles={defaultStyles}
    />
  );
}
```

## Calendar Base Props

| Name             | Type                                          | Description                                                                                                                    |
| ---------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `mode`           | `"single"` \| `"range"` \| `"multiple"`       | Defines the DatePicker mode.                                                                                                   |
| `calendar`       | `"gregory"` \| `"jalali"`                     | Defines the calendar type of DatePicker.                                                                                       |
| `minDate`        | `DateType`                                    | Defines the minimum selectable date in the DatePicker.                                                                         |
| `maxDate`        | `DateType`                                    | Defines the maximum selectable date in the DatePicker.                                                                         |
| `enabledDates`   | `DateType[]` \| `(date: DateType) => boolean` | Defines an array of enabled dates or a function that returns `true` for enabled dates. It takes precedence over disabledDates. |
| `disabledDates`  | `DateType[]` \| `(date: DateType) => boolean` | Defines an array of disabled dates or a function that returns `true` for disabled dates.                                       |
| `firstDayOfWeek` | `number`                                      | Defines the first day of the week: 0-6 (0 = Sunday, 6 = Saturday).                                                             |
| `initialView`    | `"day"` \| `"month"` \| `"year"` \| `"time"`  | Defines the initial view of the DatePicker                                                                                     |
| `month`          | `number`                                      | Defines the currently selected month.                                                                                          |
| `year`           | `number`                                      | Defines the currently selected year.                                                                                           |
| `onMonthChange`  | `(month: number) => void`                     | Callback function triggered when the current month changes.                                                                    |
| `onYearChange`   | `(year: number) => void`                      | Callback function triggered when the current year changes.                                                                     |

## Example

```jsx
export function Calendar() {
  let today = new Date();
  const [selected, setSelected] = useState<DateType>();

  return (
    <DateTimePicker
      mode="single"
      date={selected}
      onChange={({ date }) =>  setSelected(date)}
      minDate={today} // Set the minimum selectable date to today
      enabledDates={(date) => dayjs(date).day() === 1} // Enable only Mondays (takes precedence over disabledDates)
      disabledDates={(date) => [0, 6].includes(dayjs(date).day())} // Disable weekends
    />
  );
}
```

<p align="center">
<img src="/.github/images/modes-screenshot.png" />
</p>

## 🎯 New Feature Examples

### Minute Interval Time Picker

Control the time picker to show only specific minute intervals (e.g., 15-minute increments):

```jsx
import DateTimePicker from '@shanzy3/react-native-ui-datepicker';

export function AppointmentPicker() {
  const [date, setDate] = useState<DateType>();

  return (
    <DateTimePicker
      mode="single"
      date={date}
      onChange={({ date }) => setDate(date)}
      timePicker
      minuteInterval={15}  // Only show :00, :15, :30, :45
    />
  );
}
```

**Available intervals:** 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30 minutes

### Year-Only Picker

Perfect for birth year selection or any scenario where you only need a year:

```jsx
import DateTimePicker from '@shanzy3/react-native-ui-datepicker';

export function BirthYearPicker() {
  const [birthYear, setBirthYear] = useState<number>();

  return (
    <DateTimePicker
      mode="single"
      yearPickerOnly
      startYear={1920}
      endYear={new Date().getFullYear()}
      onChange={({ date }) => {
        // date is now just the year integer (e.g., 1984)
        setBirthYear(date as number);
      }}
    />
  );
}
```

Features:

- Returns just the year as an integer (e.g., `1984`)
- Shows year range in header (e.g., "2020 - 2031")
- Navigation buttons to move between year ranges
- Fully themed for light/dark mode

### View Toggle Header

Add toggle buttons to switch between date and time views:

```jsx
import DateTimePicker from '@shanzy3/react-native-ui-datepicker';

export function FlightTimePicker() {
  const [date, setDate] = useState<DateType>();

  return (
    <DateTimePicker
      mode="single"
      date={date}
      onChange={({ date }) => setDate(date)}
      timePicker
      minuteInterval={15}
      showViewPickerButtons
      toggleHeaderLabel="Departure Time"
    />
  );
}
```

This creates a header with:

- Label on the left (e.g., "Departure Time")
- Date and time toggle buttons on the right
- Active button highlighted with primary theme color
- Clean separation line at the bottom

## Single Mode props

| Name         | Type               | Description                                                 |
| ------------ | ------------------ | ----------------------------------------------------------- |
| `date`       | `DateType`         | Specifies the currently selected date.                      |
| `onChange`   | `({date}) => void` | Callback function triggered when the date change.           |
| `timePicker` | `boolean`          | Whether to enable the time picker.                          |
| `use12Hours` | `boolean`          | Whether to use a 12-hour format (AM/PM) in the time picker. |

## Range Mode props

| Name        | Type                             | Description                                                |
| ----------- | -------------------------------- | ---------------------------------------------------------- |
| `startDate` | `DateType`                       | Defines the start date for a range selection.              |
| `endDate`   | `DateType`                       | Defines the end date for a range selection.                |
| `onChange`  | `({startDate, endDate}) => void` | Callback function triggered when the start and end change. |
| `min`       | `number`                         | Defines the minimum allowed nights.                        |
| `max`       | `number`                         | Defines the maximum allowed nights.                        |

## Multiple Mode props

| Name             | Type                | Description                                                 |
| ---------------- | ------------------- | ----------------------------------------------------------- |
| `dates`          | `DateType[]`        | Defines the selected dates for multiple date selection.     |
| `onChange`       | `({dates}) => void` | Callback function triggered when the dates change.          |
| `max`            | `number`            | Defines the maximum allowed days to select.                 |
| `multiRangeMode` | `boolean`           | Whether to display selecting multiple dates in a range row. |

![react-native-ui-datepicker-styles](https://user-images.githubusercontent.com/7857656/227260476-30ee8c25-f809-4dcf-bccf-cd1ffab8795a.jpg)

## Customization

| Name                 | Type                                | Description                                               |
| -------------------- | ----------------------------------- | --------------------------------------------------------- |
| `showOutsideDays`    | `boolean`                           | Whether to show the days of the previous and next months. |
| `navigationPosition` | `"around"` \| `"right"` \| `"left"` | Defines the position of the navigation.                   |
| `containerHeight`    | `number`                            | Defines the height of the calendar days container.        |
| `weekdaysHeight`     | `number`                            | Defines the height of the weekdays row.                   |
| `weekdaysFormat`     | `"short"` \| `"full"` \| `"min"`    | Defines the format for displaying weekdays.               |
| `monthsFormat`       | `"short"` \| `"full"`               | Defines the format for displaying months.                 |
| `monthCaptionFormat` | `"short"` \| `"full"`               | Defines the format for displaying the month caption.      |
| `hideHeader`         | `boolean`                           | Whether to hide the calendar header.                      |
| `hideWeekdays`       | `boolean`                           | Whether to hide the weekdays row.                         |
| `disableMonthPicker` | `boolean`                           | Whether to disable the month picker.                      |
| `disableYearPicker`  | `boolean`                           | Whether to disable the year picker.                       |

## Styling

DateTimePicker comes with a minimal style, making it easy to extend and customize according to your needs.

| Name         | Type         | Description                                                    |
| ------------ | ------------ | -------------------------------------------------------------- |
| `style`      | `ViewStyle`  | style for the calendar container.                              |
| `className`  | `string`     | className for the calendar container.                          |
| `styles`     | `Styles`     | Custom styles for specific components inside the calendar.     |
| `classNames` | `ClassNames` | Custom classNames for specific components inside the calendar. |

## Custom Styles

Use the `styles` prop to apply custom styles instead of the default ones.

These styles are mapped to the values of the [UI Theme](https://github.com/farhoudshapouran/react-native-ui-datepicker/blob/main/src/ui.ts) enums.

```jsx
import DateTimePicker, { useDefaultStyles } from 'react-native-ui-datepicker';

export function Calendar() {
  const defaultStyles = useDefaultStyles();

  return (
    <DateTimePicker
      styles={{
        ...defaultStyles,
        today: { borderColor: 'blue', borderWidth: 1 }, // Add a border to today's date
        selected: { backgroundColor: 'blue' }, // Highlight the selected day
        selected_label: { color: 'white' }, // Highlight the selected day label
      }}
    />
  );
}
```

## NativeWind (Tailwind CSS)

If you're using [NativeWind](https://www.nativewind.dev/) in your project, apply Tailwind CSS class names to style the calendar.
Use the `classNames` prop to apply custom class names instead of the default ones.

These class names are mapped to the values of the [UI Theme](https://github.com/farhoudshapouran/react-native-ui-datepicker/blob/main/src/ui.ts) enums.

```jsx
import DateTimePicker, {
  useDefaultClassNames,
} from 'react-native-ui-datepicker';

export function Calendar() {
  const defaultClassNames = useDefaultClassNames();

  return (
    <DateTimePicker
      classNames={{
        ...defaultClassNames,
        today: 'border-amber-500', // Add a border to today's date
        selected: 'bg-amber-500 border-amber-500', // Highlight the selected day
        selected_label: 'text-white', // Highlight the selected day label
        day: `${defaultClassNames.day} hover:bg-amber-100`, // Change background color on hover
        disabled: 'opacity-50', // Make disabled dates appear more faded
      }}
    />
  );
}
```

## Time Zones

Use the `timeZone` prop to set the time zone for the calendar.

| Name       | Type     | Description                              |
| ---------- | -------- | ---------------------------------------- |
| `timeZone` | `string` | Defines the timezone for the DatePicker. |

The time zone can be set using either an [IANA time zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) identifier or a UTC offset.

```jsx
<DateTimePicker timeZone="UTC" /> // Use Coordinated Universal Time
<DateTimePicker timeZone="Asia/Tokyo" /> //  Use Japan Standard Time (JST)
```

## Localization

DateTimePicker offers multiple options to customize the calendar for different languages.

| Name       | Type                                 | Description                                                  |
| ---------- | ------------------------------------ | ------------------------------------------------------------ |
| `locale`   | `string`                             | Defines the locale of the DateTimePicker. Default is `en`    |
| `numerals` | [Numerals](#list-of-numeral-systems) | Specifies the numeral system to use (e.g., Arabic, Persian). |

## Custom Components

Use the `components` prop to replace the default rendered elements with your own custom components.

| Name         | Type                 | Description                                             |
| ------------ | -------------------- | ------------------------------------------------------- |
| `components` | `CalendarComponents` | Custom components to replace default calendar elements. |

## Implementing a Custom Component

Pass the custom components to the `components` prop. Refer to the list below for available [custom components](#list-of-custom-components).

```jsx
import DateTimePicker, {
  CalendarDay,
  CalendarMonth,
  CalendarComponents,
} from 'react-native-ui-datepicker';

const components: CalendarComponents = {
  Day: (day: CalendarDay) => <YourCustomDay day={day} />,
  Month: (month: CalendarMonth) => <YourCustomMonth month={month} />
  // etc
};

export function Calendar() {
  return (
      <DateTimePicker
        components={components}
      />
  );
}
```

## List of Custom Components

| Name       | Type                                   | Description                                            |
| ---------- | -------------------------------------- | ------------------------------------------------------ |
| `Day`      | `(day: CalendarDay) => ReactNode`      | The component containing the day in the days grid.     |
| `Month`    | `(month: CalendarMonth) => ReactNode`  | The component containing the month in the months grid. |
| `Year`     | `(year: CalendarYear) => ReactNode`    | The component containing the year in the years grid.   |
| `Weekday`  | `(weekday: CalendarWeek) => ReactNode` | The component containing the weekday in the header.    |
| `IconPrev` | `ReactNode`                            | The previous month/year button icon in the header.     |
| `IconNext` | `ReactNode`                            | The next month button/year icon in the header.         |

## Type Definitions

```typescript
type DateType = string | number | Dayjs | Date | null | undefined;

type CalendarMode = 'single' | 'range' | 'multiple';

type NavigationPosition = 'around' | 'right' | 'left';

type WeekdayFormat = 'min' | 'short' | 'full';

type MonthFormat = 'short' | 'full';

type CalendarDay = {
  number: number;
  text: string;
  date: string;
  isDisabled: boolean;
  isCurrentMonth: boolean;
  dayOfMonth?: number;
  isToday: boolean;
  isSelected: boolean;
  inRange: boolean;
  leftCrop: boolean;
  rightCrop: boolean;
  isStartOfWeek: boolean;
  isEndOfWeek: boolean;
  isCrop: boolean;
  inMiddle: boolean;
  rangeStart: boolean;
  rangeEnd: boolean;
};

type CalendarWeek = {
  index: number;
  name: {
    full: string;
    short: string;
    min: string;
  };
};

type CalendarMonth = {
  index: number;
  name: {
    full: string;
    short: string;
  };
  isSelected: boolean;
};

type CalendarYear = {
  number: number;
  text: string;
  isSelected: boolean;
  isActivated: boolean;
};
```

## List of Numeral Systems

| Name      | Description                                   |
| --------- | --------------------------------------------- |
| `latn`    | Western Latin.                                |
| `arab`    | Standard Arabic.                              |
| `arabext` | Eastern Arabic-Indic (Persian).               |
| `deva`    | Devanagari, used in Indian languages.         |
| `beng`    | Bengali, used in Bengali and Assamese.        |
| `guru`    | Gurmukhi, used in Punjab, India.              |
| `gujr`    | Gujarati, used in Gujarat, India.             |
| `orya`    | Odia, used in Odisha, India.                  |
| `tamldec` | Tamil, used in Tamil-speaking regions.        |
| `telu`    | Telugu, used in Andhra Pradesh and Telangana. |
| `knda`    | Kannada, used in Karnataka, India.            |
| `mlym`    | Malayalam, used in Kerala, India.             |

<p align="center">
<img src="https://user-images.githubusercontent.com/7857656/227187674-93012672-495d-4955-b4d3-46c3d016684e.jpg" alt="react-native-ui-datepicker" />
</p>

## License

MIT. See the [LICENSE](https://github.com/farhoudshapouran/react-native-ui-datepicker/blob/main/LICENSE) file for more details.

## Contributing

Contributions are welcome! Please feel free to submit a PR.