# DateRangePicker

Der DateRangePicker erlaubt die Eingabe einer Zeitspanne per Tastatur oder die Auswahl über einen visuellen Kalender.

## Overview

# Playground

Verwende `<DateRangePicker />`, um einen DateRangePicker darzustellen. Nutze ein
`<Label />`, um Informationen zu vermitteln, die das Verständnis der
Eingabeanforderungen erleichtern.

Die Values des DateRangePickers sind Objekte aus dem
[@internationalized/date Package](https://react-spectrum.adobe.com/internationalized/date/).

```tsx
import {
  DateRangePicker,
  Label,
} from "@mittwald/flow-react-components";

<DateRangePicker>
  <Label>Zeitraum</Label>
</DateRangePicker>
```

---

# Min- und Max-Values

Der auswählbare Datumsbereich lässt sich über `minValue` und `maxValue`
begrenzen.

```tsx
import {
  DateRangePicker,
  Label,
} from "@mittwald/flow-react-components";
import {
  getLocalTimeZone,
  today,
} from "@internationalized/date";

<DateRangePicker minValue={today(getLocalTimeZone())}>
  <Label>Zeitraum</Label>
</DateRangePicker>
```

---

# Disabled

Ist der DateRangePicker **disabled**, ist keine Interaktion möglich.

```tsx
import {
  DateRangePicker,
  Label,
} from "@mittwald/flow-react-components";

<DateRangePicker isDisabled>
  <Label>Zeitraum</Label>
</DateRangePicker>
```

---

# Mit FieldDescription

Um wichtige Hinweise zum DateRangePicker bereitzustellen, kann unterhalb eine
`<FieldDescription />` eingebaut werden.

```tsx
import {
  DateRangePicker,
  FieldDescription,
  Label,
} from "@mittwald/flow-react-components";

<DateRangePicker>
  <Label>Zeitraum</Label>
  <FieldDescription>Weitere Informationen</FieldDescription>
</DateRangePicker>
```

---

# Mit Presets

Mit `withDatePickerPresets` lassen sich Presets anzeigen, die eine beschleunigte
Auswahl von Datumsbereichen ermöglichen.

```tsx
import {
  DateRangePicker,
  Label,
  Section,
} from "@mittwald/flow-react-components";

export default () => {
  return (
    <Section>
      <DateRangePicker withDatePickerPresets>
        <Label>Zeitraum</Label>
      </DateRangePicker>
    </Section>
  );
}
```

---

# Mit Custom Presets

Wird `withDatePickerPresets` ein Array mit eigenen Presets übergeben, werden
diese anstelle der Default Presets verwendet.

```tsx
import {
  DateRangePicker,
  Label,
  Section,
  type DateRangePresets,
} from "@mittwald/flow-react-components";
import { CalendarDate } from "@internationalized/date";

export default () => {
  const customPresets: DateRangePresets = [
    {
      start: new CalendarDate(2050, 1, 1),
      end: new CalendarDate(2100, 1, 1),
      label: "Custom Preset",
    },
  ];

  return (
    <Section>
      <DateRangePicker
        withDatePickerPresets={customPresets}
      >
        <Label>Zeitraum</Label>
      </DateRangePicker>
    </Section>
  );
}
```

---

# Kombiniere mit ...

## ContextualHelp

Benutze das [ContextualHelp](/04-components/overlays/contextual-help/overview),
wenn zusätzliche Informationen bereitgestellt werden sollen, die zu umfangreich
für die FieldDescription sind.

```tsx
import {
  Button,
  ContextualHelp,
  ContextualHelpTrigger,
  DateRangePicker,
  Heading,
  Label,
  Text,
} from "@mittwald/flow-react-components";

<DateRangePicker>
  <Label>
    Zeitraum
    <ContextualHelpTrigger>
      <Button />
      <ContextualHelp>
        <Heading>Weitere Informationen</Heading>
        <Text>
          Hier gibt es weitere Informationen, die zu lang
          für die FieldDescription sind.
        </Text>
      </ContextualHelp>
    </ContextualHelpTrigger>
  </Label>
</DateRangePicker>
```

## React Hook Form

Weitere Details zur Formularlogik und -validierung sind in der Component
[Form (React Hook Form)](/04-components/react-hook-form/form/overview) zu
finden.

```tsx
import {
  DateRangePicker,
  Label,
  Section,
} from "@mittwald/flow-react-components";
import { useForm } from "react-hook-form";
import {
  Form,
  SubmitButton,
  typedField,
} from "@mittwald/flow-react-components/react-hook-form";
import type { CalendarDate } from "@internationalized/date";
import { sleep } from "@/content/04-components/actions/action/examples/lib";

export default () => {
  const form = useForm<{
    range: { start: CalendarDate; end: CalendarDate };
  }>();
  const Field = typedField(form);

  return (
    <Section>
      <Form form={form} onSubmit={sleep}>
        <Field
          name="range"
          rules={{
            required: "Bitte wähle einen Zeitraum aus",
          }}
        >
          <DateRangePicker>
            <Label>Zeitraum</Label>
          </DateRangePicker>
        </Field>
        <SubmitButton>Speichern</SubmitButton>
      </Form>
    </Section>
  );
}
```


## Develop

# Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `withDatePickerPresets` | `boolean \| DateRangePresets` | - | - |
| `id` | `string` | - | The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id). |
| `translate` | `"yes" \| "no"` | - | - |
| `className` | `ClassNameOrFunction<DateRangePickerRenderProps>` | `'react-aria-DateRangePicker'` | The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. A function may be provided to compute the class based on component state. |
| `isOpen` | `boolean` | - | Whether the overlay is open by default (controlled). |
| `defaultOpen` | `boolean` | - | Whether the overlay is open by default (uncontrolled). |
| `style` | `StyleOrFunction<TooltipRenderProps>` | - | The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state. |
| `render` | `DOMRenderFunction<"div", TooltipRenderProps>` | - | Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Requirements: - You must render the expected element type (e.g. if `<button>` is expected, you cannot render an `<a>`). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate. |
| `dir` | `string` | - | - |
| `lang` | `string` | - | - |
| `hidden` | `boolean` | - | - |
| `inert` | `boolean` | - | - |
| `validationBehavior` | `"native" \| "aria"` | `'native'` | Whether to use native HTML form validation to prevent form submission when the value is missing or invalid, or mark the field as required or invalid via ARIA. |
| `hourCycle` | `12 \| 24` | - | Whether to display the time in 12 or 24 hour format. By default, this is determined by the user's locale. |
| `granularity` | `"hour" \| "minute" \| "second"` | `'minute'` | Determines the smallest unit that is displayed in the time picker. |
| `hideTimeZone` | `boolean` | - | Whether to hide the time zone abbreviation. |
| `shouldForceLeadingZeros` | `boolean` | - | Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale. |
| `placeholderValue` | `TimeValue` | - | A placeholder time that influences the format of the placeholder shown when no value is selected. Defaults to 12:00 AM or 00:00 depending on the hour cycle. |
| `minValue` | `TimeValue` | - | The minimum allowed time that a user may select. |
| `maxValue` | `TimeValue` | - | The maximum allowed time that a user may select. |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed by the user. |
| `isRequired` | `boolean` | - | Whether user input is required on the input before form submission. |
| `isInvalid` | `boolean` | - | Whether the input value is invalid. |
| `validate` | `((value: TimeValue) => true \| ValidationError)` | - | A function that returns an error message if a given value is invalid. Validation errors are displayed to the user when the form is submitted if `validationBehavior="native"`. For realtime validation, use the `isInvalid` prop instead. |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render. |
| `value` | `TimeValue` | - | The current value (controlled). |
| `defaultValue` | `TimeValue` | - | The default value (uncontrolled). |
| `form` | `string` | - | The `<form>` element to associate the input with. The value of this attribute must be the id of a `<form>` in the same document. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input#form). |
| `slot` | `string` | - | A slot name for the component. Slots allow the component to receive props from a parent component. An explicit `null` value indicates that the local props completely override all props received from a parent. |
| `shouldCloseOnSelect` | `boolean \| (() => boolean)` | `true` | Determines whether the date picker popover should close automatically when a date is selected. |
| `isDateUnavailable` | `((date: DateValue, anchorDate: CalendarDate) => boolean)` | - | Callback that is called for each date of the calendar. If it returns true, then the date is unavailable. |
| `pageBehavior` | `PageBehavior` | `visible` | Controls the behavior of paging. Pagination either works by advancing the visible page by visibleDuration (default) or one unit of visibleDuration. |
| `firstDayOfWeek` | `"sun" \| "mon" \| "tue" \| "wed" \| "thu" \| "fri" \| "sat"` | - | The day that starts the week. |
| `allowsNonContiguousRanges` | `boolean` | - | When combined with `isDateUnavailable`, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected. |
| `startName` | `string` | - | The name of the start date input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
| `endName` | `string` | - | The name of the end date input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
| `children` | `ReactNode` | - | - |
| `wrapWith` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | - | - |
| `ref` | `Ref<HTMLSpanElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see [React Docs](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom) |
| `key` | `Key` | - | - |

### Events

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `onOpenChange` | `((isOpen: boolean) => void)` | - | Handler that is called when the overlay's open state changes. |
| `onClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onAuxClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onAuxClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onContextMenu` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onContextMenuCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onDoubleClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onDoubleClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseDown` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseDownCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseEnter` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseLeave` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseMove` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseMoveCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOut` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOutCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOver` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOverCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseUp` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseUpCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onTouchCancel` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchCancelCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchEnd` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchEndCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchMove` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchMoveCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchStart` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchStartCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onPointerDown` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerDownCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerMove` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerMoveCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerUp` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerUpCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerCancel` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerCancelCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerEnter` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerLeave` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOver` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOverCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOut` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOutCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onGotPointerCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onGotPointerCaptureCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onLostPointerCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onLostPointerCaptureCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onScroll` | `UIEventHandler<HTMLDivElement>` | - | - |
| `onScrollCapture` | `UIEventHandler<HTMLDivElement>` | - | - |
| `onWheel` | `WheelEventHandler<HTMLDivElement>` | - | - |
| `onWheelCapture` | `WheelEventHandler<HTMLDivElement>` | - | - |
| `onAnimationStart` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationStartCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationEnd` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationEndCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationIteration` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationIterationCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onTransitionCancel` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionCancelCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionEnd` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionEndCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionRun` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionRunCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionStart` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionStartCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onFocus` | `((e: FocusEvent<Element, Element>) => void)` | - | Handler that is called when the element receives focus. |
| `onBlur` | `((e: FocusEvent<Element, Element>) => void)` | - | Handler that is called when the element loses focus. |
| `onFocusChange` | `((isFocused: boolean) => void)` | - | Handler that is called when the element's focus status changes. |
| `onKeyDown` | `((e: KeyboardEvent) => void)` | - | Handler that is called when a key is pressed. |
| `onKeyUp` | `((e: KeyboardEvent) => void)` | - | Handler that is called when a key is released. |
| `onChange` | `((value: TimeValue) => void)` | - | Handler that is called when the value changes. |

### Accessibility

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `aria-label` | `string` | - | Defines a string value that labels the current element. |
| `aria-labelledby` | `string` | - | Identifies the element (or elements) that labels the current element. |
| `aria-describedby` | `string` | - | Identifies the element (or elements) that describes the object. |
| `aria-details` | `string` | - | Identifies the element (or elements) that provide a detailed, extended description for the object. |


## Guidelines

# Grundlagen

## Best practices

Achte bei der Verwendung eines DateRangePickers darauf, dass ...

- ein verständliches [Label](/04-components/content/label/overview) wie
  „Zeitraum“ verwendet wird.
- das Datumsformat dem gewohnten Format des Users und dem Nutzungskontext
  entspricht.
- sinnvolle Defaultwerte gewählt werden.
- der auswählbare Zeitraum ggf. mit `minValue` und `maxValue` eingeschränkt
  wird.

## Verwendung

Verwende einen DateRangePicker, um ...

- dem User die Möglichkeit zu geben, einen Zeitraum für mehrtägige Termine
  auszuwählen.
- einen Datensatz auf einen bestimmten Zeitraum zu begrenzen, z. B. bei der
  Darstellung von Diagrammen.

