Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions packages/@react-aria/datepicker/docs/useDateField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ input via the `aria-describedby` attribute.

Note that most of this anatomy is shared with [useTimeField](useTimeField.html), so you can reuse many components between them if you have both.

State is managed by the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useDatePickerFieldState} /> hook from `@react-stately/datepicker`.
State is managed by the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useDateFieldState} /> hook from `@react-stately/datepicker`.
The state object should be passed as an option to `useDateField` and `useDateSegment`.

If the date field does not have a visible label, an `aria-label` or `aria-labelledby` prop must be passed instead to
Expand All @@ -86,19 +86,19 @@ Dates and times are represented in many different ways by cultures around the wo

<TypeLink links={docs.links} type={docs.exports.useDateField} /> uses the [@internationalized/date](../internationalized/date/) library to represent dates and times. This package provides a library of objects and functions to perform date and time related manipulation, queries, and conversions that work across locales and calendars. Date and time objects can be converted to and from native JavaScript `Date` objects or [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) strings. See the [documentation](../internationalized/date/), or the [examples below](#value) for more details.

<TypeLink links={statelyDocs.links} type={statelyDocs.exports.useDatePickerFieldState} /> requires a `createCalendar` function to be provided, which is used to implement date manipulation across multiple calendar systems. The default implementation in `@internationalized/date` includes all supported calendar systems. While this library is quite small (8 kB minified + Brotli), you can reduce its bundle size further by providing your own implementation that includes only your supported calendars. See [below](#reducing-bundle-size) for an example.
<TypeLink links={statelyDocs.links} type={statelyDocs.exports.useDateFieldState} /> requires a `createCalendar` function to be provided, which is used to implement date manipulation across multiple calendar systems. The default implementation in `@internationalized/date` includes all supported calendar systems. While this library is quite small (8 kB minified + Brotli), you can reduce its bundle size further by providing your own implementation that includes only your supported calendars. See [below](#reducing-bundle-size) for an example.

## Example

```tsx example export=true
import {useDatePickerFieldState} from '@react-stately/datepicker';
import {useDateFieldState} from '@react-stately/datepicker';
import {useDateField, useDateSegment} from '@react-aria/datepicker';
import {createCalendar} from '@internationalized/date';
import {useLocale} from '@react-aria/i18n';

export function DateField(props) {
let {locale} = useLocale();
let state = useDatePickerFieldState({
let state = useDateFieldState({
...props,
locale,
createCalendar
Expand Down Expand Up @@ -388,14 +388,14 @@ By default, `useDateField` displays times in either 12 or 24 hour hour format de

### Reducing bundle size

In the example above, the <TypeLink links={i18nDocs.links} type={i18nDocs.exports.createCalendar} /> function from the [@internationalized/date](../internationalized/date/) package is passed to the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useDatePickerFieldState} /> hook. This function receives a [calendar identifier](../internationalized/date/Calendar.html#calendar-identifiers) string, and provides <TypeLink links={i18nDocs.links} type={i18nDocs.exports.Calendar} /> instances to React Stately, which are used to implement date manipulation.
In the example above, the <TypeLink links={i18nDocs.links} type={i18nDocs.exports.createCalendar} /> function from the [@internationalized/date](../internationalized/date/) package is passed to the <TypeLink links={statelyDocs.links} type={statelyDocs.exports.useDateFieldState} /> hook. This function receives a [calendar identifier](../internationalized/date/Calendar.html#calendar-identifiers) string, and provides <TypeLink links={i18nDocs.links} type={i18nDocs.exports.Calendar} /> instances to React Stately, which are used to implement date manipulation.

By default, this includes [all calendar systems](../internationalized/date/Calendar.html#implementations) supported by `@internationalized/date`. However, if your application supports a more limited set of regions, or you know you will only be picking dates in a certain calendar system, you can reduce your bundle size by providing your own implementation of `createCalendar` that includes a subset of these `Calendar` implementations.

For example, if your application only supports Gregorian dates, you could implement a `createCalendar` function like this:

```jsx
import {useDatePickerFieldState} from '@react-stately/datepicker';
import {useDateFieldState} from '@react-stately/datepicker';
import {useLocale} from '@react-aria/i18n';
import {GregorianCalendar} from '@internationalized/date';

Expand All @@ -410,7 +410,7 @@ function createCalendar(identifier) {

export function DateField(props) {
let {locale} = useLocale();
let state = useDatePickerFieldState({
let state = useDateFieldState({
...props,
locale,
createCalendar
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/datepicker/docs/useDatePicker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,12 @@ The `DateField` component implements the keyboard editable input used in a `Date

```tsx example export=true render=false
import {useLocale} from '@react-aria/i18n';
import {useDatePickerFieldState} from '@react-stately/datepicker';
import {useDateFieldState} from '@react-stately/datepicker';
import {useDateField, useDateSegment} from '@react-aria/datepicker';

function DateField(props) {
let {locale} = useLocale();
let state = useDatePickerFieldState({
let state = useDateFieldState({
...props,
locale,
createCalendar
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/datepicker/docs/useDateRangePicker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,12 @@ The `DateField` component implements the keyboard editable inputs used in a `Dat

```tsx example export=true render=false
import {useLocale} from '@react-aria/i18n';
import {useDatePickerFieldState} from '@react-stately/datepicker';
import {useDateFieldState} from '@react-stately/datepicker';
import {useDateField, useDateSegment} from '@react-aria/datepicker';

function DateField(props) {
let {locale} = useLocale();
let state = useDatePickerFieldState({
let state = useDateFieldState({
...props,
locale,
createCalendar
Expand Down
12 changes: 5 additions & 7 deletions packages/@react-aria/datepicker/src/useDateField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@

import {AriaDatePickerProps, AriaTimeFieldProps, DateValue, TimeValue} from '@react-types/datepicker';
import {createFocusManager, FocusManager} from '@react-aria/focus';
import {DatePickerFieldState} from '@react-stately/datepicker';
import {DateFieldState} from '@react-stately/datepicker';
import {focusManagerSymbol} from './useDateRangePicker';
import {HTMLAttributes, RefObject, useEffect, useMemo, useRef} from 'react';
import {mergeProps, useDescription} from '@react-aria/utils';
import {useDateFormatter} from '@react-aria/i18n';
import {useDatePickerGroup} from './useDatePickerGroup';
import {useField} from '@react-aria/label';
import {useFocusWithin} from '@react-aria/interactions';
Expand All @@ -42,14 +41,14 @@ interface HookData {
focusManager: FocusManager
}

export const hookData = new WeakMap<DatePickerFieldState, HookData>();
export const hookData = new WeakMap<DateFieldState, HookData>();

/**
* Provides the behavior and accessibility implementation for a date field component.
* A date field allows users to enter and edit date and time values using a keyboard.
* Each part of a date value is displayed in an individually editable segment.
*/
export function useDateField<T extends DateValue>(props: DateFieldProps<T>, state: DatePickerFieldState, ref: RefObject<HTMLElement>): DateFieldAria {
export function useDateField<T extends DateValue>(props: DateFieldProps<T>, state: DateFieldState, ref: RefObject<HTMLElement>): DateFieldAria {
let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useField({
...props,
labelElementType: 'span'
Expand All @@ -63,8 +62,7 @@ export function useDateField<T extends DateValue>(props: DateFieldProps<T>, stat
}
});

let formatter = useDateFormatter(state.getFormatOptions({month: 'long'}));
let descProps = useDescription(state.value ? formatter.format(state.dateValue) : null);
let descProps = useDescription(state.formatValue({month: 'long'}));

let segmentLabelledBy = fieldProps['aria-labelledby'] || fieldProps.id;
let describedBy = [descProps['aria-describedby'], fieldProps['aria-describedby']].filter(Boolean).join(' ') || undefined;
Expand Down Expand Up @@ -108,6 +106,6 @@ export function useDateField<T extends DateValue>(props: DateFieldProps<T>, stat
* A time field allows users to enter and edit time values using a keyboard.
* Each part of a time value is displayed in an individually editable segment.
*/
export function useTimeField<T extends TimeValue>(props: AriaTimeFieldProps<T>, state: DatePickerFieldState, ref: RefObject<HTMLElement>): DateFieldAria {
export function useTimeField<T extends TimeValue>(props: AriaTimeFieldProps<T>, state: DateFieldState, ref: RefObject<HTMLElement>): DateFieldAria {
return useDateField(props, state, ref);
}
4 changes: 2 additions & 2 deletions packages/@react-aria/datepicker/src/useDatePickerGroup.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {DatePickerFieldState, DatePickerState, DateRangePickerState} from '@react-stately/datepicker';
import {DateFieldState, DatePickerState, DateRangePickerState} from '@react-stately/datepicker';
import {getFocusableTreeWalker} from '@react-aria/focus';
import {KeyboardEvent} from '@react-types/shared';
import {mergeProps} from '@react-aria/utils';
import {RefObject} from 'react';
import {usePress} from '@react-aria/interactions';

export function useDatePickerGroup(state: DatePickerState | DateRangePickerState | DatePickerFieldState, ref: RefObject<HTMLElement>) {
export function useDatePickerGroup(state: DatePickerState | DateRangePickerState | DateFieldState, ref: RefObject<HTMLElement>) {
// Open the popover on alt + arrow down
let onKeyDown = (e: KeyboardEvent) => {
if (e.altKey && e.key === 'ArrowDown' && 'setOpen' in state) {
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-aria/datepicker/src/useDateSegment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import {DatePickerFieldState, DateSegment} from '@react-stately/datepicker';
import {DateFieldState, DateSegment} from '@react-stately/datepicker';
import {getScrollParent, isIOS, isMac, mergeProps, scrollIntoView, useEvent, useId} from '@react-aria/utils';
import {hookData} from './useDateField';
import {NumberParser} from '@internationalized/number';
Expand All @@ -30,7 +30,7 @@ interface DateSegmentAria {
* A date segment displays an individual unit of a date and time, and allows users to edit
* the value by typing or using the arrow keys to increment and decrement.
*/
export function useDateSegment(segment: DateSegment, state: DatePickerFieldState, ref: RefObject<HTMLElement>): DateSegmentAria {
export function useDateSegment(segment: DateSegment, state: DateFieldState, ref: RefObject<HTMLElement>): DateSegmentAria {
let enteredKeys = useRef('');
let {locale, direction} = useLocale();
let displayNames = useDisplayNames();
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/datepicker/src/DateField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {Field} from '@react-spectrum/label';
import {Input} from './Input';
import React, {useRef} from 'react';
import {useDateField} from '@react-aria/datepicker';
import {useDatePickerFieldState} from '@react-stately/datepicker';
import {useDateFieldState} from '@react-stately/datepicker';
import {useFormatHelpText} from './utils';
import {useLocale} from '@react-aria/i18n';
import {useProviderProps} from '@react-spectrum/provider';
Expand All @@ -40,7 +40,7 @@ export function DateField<T extends DateValue>(props: SpectrumDateFieldProps<T>)

let ref = useRef();
let {locale} = useLocale();
let state = useDatePickerFieldState({
let state = useDateFieldState({
...props,
locale,
createCalendar
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/datepicker/src/DatePickerField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import datepickerStyles from './index.css';
import {DateValue, SpectrumDatePickerProps} from '@react-types/datepicker';
import React, {useRef} from 'react';
import {useDateField} from '@react-aria/datepicker';
import {useDatePickerFieldState} from '@react-stately/datepicker';
import {useDateFieldState} from '@react-stately/datepicker';
import {useLocale} from '@react-aria/i18n';

interface DatePickerFieldProps<T extends DateValue> extends SpectrumDatePickerProps<T> {
Expand All @@ -35,7 +35,7 @@ export function DatePickerField<T extends DateValue>(props: DatePickerFieldProps
} = props;
let ref = useRef();
let {locale} = useLocale();
let state = useDatePickerFieldState({
let state = useDateFieldState({
...props,
locale,
createCalendar
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/datepicker/src/DatePickerSegment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
*/

import {classNames} from '@react-spectrum/utils';
import {DateFieldState, DateSegment} from '@react-stately/datepicker';
import {DatePickerBase, DateValue} from '@react-types/datepicker';
import {DatePickerFieldState, DateSegment} from '@react-stately/datepicker';
import {NumberParser} from '@internationalized/number';
import React, {useMemo, useRef} from 'react';
import styles from './index.css';
Expand All @@ -21,7 +21,7 @@ import {useLocale} from '@react-aria/i18n';

interface DatePickerSegmentProps extends DatePickerBase<DateValue> {
segment: DateSegment,
state: DatePickerFieldState
state: DateFieldState
}

interface LiteralSegmentProps {
Expand Down
40 changes: 40 additions & 0 deletions packages/@react-stately/calendar/docs/useCalendarState.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{/* Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-stately/calendar';
import {ClassAPI, HeaderInfo, TypeContext, FunctionAPI, TypeLink, PageDescription} from '@react-spectrum/docs';
import packageData from '@react-stately/calendar/package.json';

---
category: Date and Time
keywords: [date, calendar, state]
---

# useCalendarState

<PageDescription>{docs.exports.useCalendarState.description}</PageDescription>

<HeaderInfo
packageData={packageData}
componentNames={['useCalendarState']} />

## API

<FunctionAPI function={docs.exports.useCalendarState} links={docs.links} />

## Interface

<ClassAPI links={docs.links} class={docs.links[docs.exports.useCalendarState.return.id]} />

## Example

See the docs for [useCalendar](/react-aria/useCalendar.html) in react-aria for an example of `useCalendarState`.
40 changes: 40 additions & 0 deletions packages/@react-stately/calendar/docs/useRangeCalendarState.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{/* Copyright 2020 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '@react-spectrum/docs';
export default Layout;

import docs from 'docs:@react-stately/calendar';
import {ClassAPI, HeaderInfo, TypeContext, FunctionAPI, TypeLink, PageDescription} from '@react-spectrum/docs';
import packageData from '@react-stately/calendar/package.json';

---
category: Date and Time
keywords: [date, calendar, state]
---

# useRangeCalendarState

<PageDescription>{docs.exports.useRangeCalendarState.description}</PageDescription>

<HeaderInfo
packageData={packageData}
componentNames={['useRangeCalendarState']} />

## API

<FunctionAPI function={docs.exports.useRangeCalendarState} links={docs.links} />

## Interface

<ClassAPI links={docs.links} class={docs.links[docs.exports.useRangeCalendarState.return.id]} />

## Example

See the docs for [useRangeCalendar](/react-aria/useRangeCalendar.html) in react-aria for an example of `useRangeCalendarState`.
20 changes: 18 additions & 2 deletions packages/@react-stately/calendar/src/useCalendarState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,30 @@ import {useControlledState} from '@react-stately/utils';
import {useDateFormatter} from '@react-aria/i18n';
import {useMemo, useRef, useState} from 'react';

interface CalendarStateOptions<T extends DateValue> extends CalendarProps<T> {
interface CalendarStateOptions extends CalendarProps<DateValue> {
/** The locale to display and edit the value according to. */
locale: string,
/**
* A function that creates a [Calendar](../internationalized/date/Calendar.html)
* object for a given calendar identifier. Such a function may be imported from the
* `@internationalized/date` package, or manually implemented to include support for
* only certain calendars.
*/
createCalendar: (name: string) => Calendar,
/**
* The amount of days that will be displayed at once. This affects how pagination works.
* @default {months: 1}
*/
visibleDuration?: DateDuration,
/** Determines how to align the initial selection relative to the visible date range. */
selectionAlignment?: 'start' | 'center' | 'end'
}

export function useCalendarState<T extends DateValue>(props: CalendarStateOptions<T>): CalendarState {
/**
* Provides state management for a calendar component.
* A calendar displays one or more date grids and allows users to select a single date.
*/
export function useCalendarState(props: CalendarStateOptions): CalendarState {
let defaultFormatter = useDateFormatter();
let resolvedOptions = useMemo(() => defaultFormatter.resolvedOptions(), [defaultFormatter]);
let {
Expand Down
19 changes: 17 additions & 2 deletions packages/@react-stately/calendar/src/useRangeCalendarState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,28 @@ import {useCalendarState} from './useCalendarState';
import {useControlledState} from '@react-stately/utils';
import {useMemo, useRef, useState} from 'react';

interface RangeCalendarStateOptions<T extends DateValue> extends RangeCalendarProps<T> {
interface RangeCalendarStateOptions extends RangeCalendarProps<DateValue> {
/** The locale to display and edit the value according to. */
locale: string,
/**
* A function that creates a [Calendar](../internationalized/date/Calendar.html)
* object for a given calendar identifier. Such a function may be imported from the
* `@internationalized/date` package, or manually implemented to include support for
* only certain calendars.
*/
createCalendar: (name: string) => Calendar,
/**
* The amount of days that will be displayed at once. This affects how pagination works.
* @default {months: 1}
*/
visibleDuration?: DateDuration
}

export function useRangeCalendarState<T extends DateValue>(props: RangeCalendarStateOptions<T>): RangeCalendarState {
/**
* Provides state management for a range calendar component.
* A range calendar displays one or more date grids and allows users to select a contiguous range of dates.
*/
export function useRangeCalendarState(props: RangeCalendarStateOptions): RangeCalendarState {
let {value: valueProp, defaultValue, onChange, createCalendar, locale, visibleDuration = {months: 1}, minValue, maxValue, ...calendarProps} = props;
let [value, setValue] = useControlledState<DateRange>(
valueProp,
Expand Down
Loading