import { Story, ArgTypes, Canvas, Meta } from '@storybook/addon-docs/blocks';
import DatePicker from '../DatePicker';
import DatePickerInput from '../DatePickerInput';
import * as DatePickerStories from './DatePicker.stories';
import { stackblitzPrefillConfig } from '../../../previewer/codePreviewer';

<Meta isTemplate />

# Date Picker

[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/DatePicker)
&nbsp;|&nbsp;
[Usage guidelines](https://www.carbondesignsystem.com/components/date-picker/usage)
&nbsp;|&nbsp;
[Accessibility](https://www.carbondesignsystem.com/components/date-picker/accessibility)

{/* <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> */}

## Table of Contents

- [Overview](#overview)
  - [Simple DatePicker](#simple-datepicker)
  - [Range Datepicker](#range-datepicker)
  - [Skeleton state](#skeleton-state)
  - [AI label](#ai-label)
- [Component API](#component-api)
  - [DatePicker `appendTo`](#datepicker-appendto)
  - [DatePicker `className`](#datepicker-classname)
  - [DatePicker `dateFormat`](#datepicker-dateformat)
  - [DatePicker `parseDate`](#datepicker-parsedate)
  - [DatePicker `datePickerType`](#datepicker-datepickertype)
  - [DatePicker `light`](#datepicker-light)
  - [DatePicker `locale`](#datepicker-locale)
  - [DatePicker `maxDate`](#datepicker-maxdate)
  - [DatePicker `minDate`](#datepicker-mindate)
  - [DatePicker `disable` and `enable`](#datepicker-disable-and-enable)
  - [DatePicker `value`](#datepicker-value)
- [References](#references)
- [Feedback](#feedback)

{/* <!-- END doctoc generated TOC please keep comment here to allow auto update --> */}

## Overview

Date pickers allow users to select a single or a range of dates. Pickers are
used to display past, present, or future dates. The kind of date (exact,
approximate, memorable) you are requesting from the user will determine which
picker is best to use. Each picker’s format can be customized depending on
location or need. The `DatePicker` component expects a `DatePickerInput` as a
child.

<Canvas of={DatePickerStories.Default} />

### Simple DatePicker

The simple date input provides the user with only a text field in which they can
manually input a date. It allows dates to be entered without adding unnecessary
interactions that come with the calendar menu or a dropdown.

<Canvas
  of={DatePickerStories.Simple}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(DatePickerStories.Simple),
    },
  ]}
/>

### Range Datepicker

Calendar pickers default to showing today’s date when opened and only one month
is shown at a time. Calendar pickers allow users to navigate through months and
years, however they work best when used for recent or near future dates.

<Canvas
  of={DatePickerStories.SingleWithCalendar}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () =>
        stackblitzPrefillConfig(DatePickerStories.SingleWithCalendar),
    },
  ]}
/>
<Canvas
  of={DatePickerStories.RangeWithCalendar}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () =>
        stackblitzPrefillConfig(DatePickerStories.RangeWithCalendar),
    },
  ]}
/>

### Skeleton state

You can use the `DatePickerSkeleton` component to render a skeleton variant of a
`DatePicker`. This is useful to display while an initial date range in your
`DatePicker` is being fetched from an external resource like an API.

<Canvas
  of={DatePickerStories.Skeleton}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(DatePickerStories.Skeleton),
    },
  ]}
/>

### AI label

<Canvas
  of={DatePickerStories.withAILabel}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(DatePickerStories.withAILabel),
    },
  ]}
/>

## Component API

<ArgTypes />

### DatePicker `appendTo`

By default, the `DatePicker` menu will be appended to the end of the `body`
element. If you would like to attach it to a different node, you can specify a
DOM element with the `appendTo` prop.

```jsx
const node = document.querySelector('#my-node');

<DatePicker appendTo={node}>...</DatePicker>;
```

### DatePicker `className`

The className prop passed into `DatePicker` will be forwarded along to the
underlying wrapper `div.cds--date-picker` element. This is useful for specifying
a custom class name for layout.

```jsx
<DatePicker className="some-class">...</DatePicker>
```

### DatePicker `dateFormat`

You can use the `dateFormat` prop to change how the selected date is displayed
in the input. For a complete list of supported date formatting tokens, please
see the Flatpickr
[documentation](https://flatpickr.js.org/formatting/#date-formatting-tokens).

When configuring `dateFormat`, a `parseDate` function can be specified to modify
the date correction behavior that is sometimes undesirable due to
[oddities in how the native date methods work](https://github.com/carbon-design-system/carbon/issues/15432#issuecomment-1967447677).

<DatePicker datePickerType="single" dateFormat="Y-m-d">
  <DatePickerInput
    placeholder="yyyy-mm-dd"
    id="date-picker-1"
    labelText="Date format example"
  />
</DatePicker>

```jsx
<DatePicker datePickerType="single" dateFormat="Y-m-d">
  <DatePickerInput placeholder="mm/dd/yyyy" />
</DatePicker>
```

### DatePicker `parseDate`

Most often used when configuring `dateFormat`, a `parseDate` function can be
specified to modify the date correction behavior that is sometimes undesirable
due to
[oddities in how the native date methods work](https://github.com/carbon-design-system/carbon/issues/15432#issuecomment-1967447677).

The specified `parseDate` function will be called before the date is actually
set. It's called with a date parameter, the input value, that should be parsed
and return a valid date string. The
[internal/default implementation](https://github.com/search?q=repo%3Acarbon-design-system%2Fcarbon+symbol%3AparseDate+language%3ATSX&type=code&l=TSX)
can be copied and used as a starting point.

### DatePicker `datePickerType`

There are three supported variations of `DatePicker` in Carbon.

- `simple` will render a simple text input _without_ a calendar dropdown.
- `single` will render a a single text input _with_ a calendar dropdown.
- `range` will indicate that multiple `DatePicker` inputs will be rendered. Two
  `DatePickerInput` will need to be provided as children.

```jsx
<DatePicker datePickerType="range">
  <DatePickerInput placeholder="Start" />
  <DatePickerInput placeholder="End" />
</DatePicker>
```

### DatePicker `light`

In certain circumstances, a `DatePicker` will exist on a container element with
the same background color. To improve contrast, you can use the `light` property
to toggle the light variant of the `DatePicker`.

```jsx
<DatePicker light>...</DatePicker>
```

### DatePicker `locale`

The `locale` prop can be used to help with internationalization. For best
results, combine with the `dateFormat` prop. We pass this under the hood to the
FlatPickr instance. A complete list of valid locales can be found in the
[component API](#component-api) section

<DatePicker locale="no" dateFormat="d/m/Y" datePickerType="single">
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-2"
    labelText="Locale example"
  />
</DatePicker>

```jsx
// Load Norwegian text with the proper date format
<DatePicker locale="no" dateFormat="d/m/Y" datePickerType="single">
  <DatePickerInput placeholder="dd/mm/yyyy" />
</DatePicker>
```

### DatePicker `maxDate`

Limits the date selection to any date before the date specified. The string
format depends on the `locale` specified. For example, the top example below is
using the default US date format, and the one below it is using the same format
as the `locale` prop example. One is setting it as September 1st, and the other
is setting it as January 9th.

<DatePicker maxDate="09/01/2020" datePickerType="single">
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-3"
    labelText="US format"
  />
</DatePicker>
<br />
<DatePicker
  maxDate="09/01/2020"
  datePickerType="single"
  locale="no"
  dateFormat="d/m/Y">
  <DatePickerInput
    placeholder="mm/dd/yyyy"
    id="date-picker-4"
    labelText="European format"
  />
</DatePicker>

```jsx
<DatePicker maxDate="09/01/2020">
  <DatePickerInput placeholder="mm/dd/yyyy" />
</DatePicker>

<DatePicker
  maxDate="09/01/2020"
  datePickerType="single"
  locale="no"
  dateFormat="d/m/Y">
  <DatePickerInput placeholder="mm/dd/yyyy" />
</DatePicker>;
```

### DatePicker `minDate`

Works similarly to the `maxDate` prop. [See above](#datepicker-maxdate).

<DatePicker
  minDate={new Date().setDate(new Date().getDate() - 5)}
  datePickerType="single"
  value={new Date()}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-5"
    labelText="minDate example"
  />
</DatePicker>

```jsx
<DatePicker
  minDate={new Date().setDate(new Date().getDate() - 5)}
  datePickerType="single"
  value={new Date()}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-5"
    labelText="minDate example"
  />
</DatePicker>
```

### DatePicker `disable` and `enable`

This uses the Flatpickr `disable` option which allows a user to disable certain
dates. The disable takes in a array of date strings, or you can pass in a date
function to the array that will disable dates that returns true.
[See the Flatpickr documentation for more info](https://flatpickr.js.org/examples/#disabling-dates).

<DatePicker
  datePickerType="single"
  disable={[(date) => date.getDay() === 0 || date.getDay() === 6]}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-8"
    labelText="minDate example"
  />
</DatePicker>

```jsx
<DatePicker
  datePickerType="single"
  disable={[(date) => date.getDay() === 0 || date.getDay() === 6]}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-8"
    labelText="minDate example"
  />
</DatePicker>
```

The `enable` option works the same, but will disable all dates that are not
explicitly added to the array.
[See the flatpickr documentation for more info](https://flatpickr.js.org/examples/#disabling-all-dates-except-select-few).

<DatePicker
  datePickerType="single"
  value="04/20/2023"
  enable={[
    {
      from: '04/10/2023',
      to: '04/25/2023',
    },
  ]}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-8"
    labelText="minDate example"
  />
</DatePicker>

```jsx
<DatePicker
  datePickerType="single"
  value="04/20/2023"
  enable={[
    {
      from: '04/10/2023',
      to: '04/25/2023',
    },
  ]}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-8"
    labelText="minDate example"
  />
</DatePicker>
```

### DatePicker `value`

By default `DatePicker` will set the current date as its value. If you'd like to
start this at a different date, you can pass in a date string or date object.

<DatePicker datePickerType="single" value="07/15/1988">
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-6"
    labelText="Value as string example"
  />
</DatePicker>
<br />
<DatePicker datePickerType="single" value={new Date()}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-7"
    labelText="Value as object example"
  />
</DatePicker>

```jsx
<DatePicker datePickerType="single" value="07/15/1988">
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-6"
    labelText="Value as string example"
  />
</DatePicker>
<br />
<DatePicker datePickerType="single" value={new Date()}>
  <DatePickerInput
    placeholder="dd/mm/yyyy"
    id="date-picker-7"
    labelText="Value as object example"
  />
</DatePicker>
```

## References

- The `DatePicker` component utilizes Flatpickr under the hood. We will pass any
  extra options down to the FlatPickr instance. For a full list of options,
  please see the [Flatpickr docs](https://flatpickr.js.org/options/)
- The `DatePickerInput` takes in similar props to the `TextInput` component,
  such as `size` and `placeholder`. For more information on these props, check
  out the `TextInput` page.

## Feedback

Help us improve this component by providing feedback, asking questions on Slack,
or updating this file on
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/react/src/components/DatePicker/DatePicker.mdx).
