Skip to content
Open
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
10 changes: 5 additions & 5 deletions packages/react-aria-components/src/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,13 @@ export interface DatePickerProps<T extends DateValue>
*/
className?: ClassNameOrFunction<DatePickerRenderProps>;
}
export interface DateRangePickerProps<T extends DateValue>
export interface DateRangePickerProps<T extends DateValue, Target extends Element = Element>
extends
Omit<
AriaDateRangePickerProps<T>,
AriaDateRangePickerProps<T, Target>,
'label' | 'description' | 'errorMessage' | 'validationState' | 'validationBehavior'
>,
Pick<DateRangePickerStateOptions<T>, 'shouldCloseOnSelect'>,
Pick<DateRangePickerStateOptions<T, Target>, 'shouldCloseOnSelect'>,
RACValidation,
RenderProps<DateRangePickerRenderProps>,
SlotProps,
Expand Down Expand Up @@ -271,8 +271,8 @@ export const DatePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(function
* users to enter or select a date and time range.
*/
export const DateRangePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(
function DateRangePicker<T extends DateValue>(
props: DateRangePickerProps<T>,
function DateRangePicker<T extends DateValue, Target extends Element = Element>(
props: DateRangePickerProps<T, Target>,
ref: ForwardedRef<HTMLDivElement>
) {
[props, ref] = useContextProps(props, ref, DateRangePickerContext);
Expand Down
7 changes: 7 additions & 0 deletions packages/react-aria-components/test/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,10 @@ motion(RAC.Text);
motion(RAC.TextField);
motion(RAC.ToggleButton);
motion(RAC.Tooltip);

// DateRangePicker should accept form library focus handlers targeting an HTMLElement.
let dateRangePickerFormProps = {
onBlur: (event?: React.FocusEvent<HTMLElement>) => event?.currentTarget.focus(),
onFocus: (event?: React.FocusEvent<HTMLElement>) => event?.currentTarget.focus()
} satisfies RAC.DateRangePickerProps<RAC.DateValue, HTMLElement>;
<RAC.DateRangePicker {...dateRangePickerFormProps} />;
18 changes: 11 additions & 7 deletions packages/react-aria/src/datepicker/useDateRangePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
privateValidationStateProp
} from 'react-stately/private/form/useFormValidationState';
import {filterDOMProps} from '../utils/filterDOMProps';
import {FocusEvent, useMemo, useRef} from 'react';
import {focusManagerSymbol, roleSymbol} from './useDateField';
import intlMessages from '../../intl/datepicker/*.json';
import {mergeProps} from '../utils/mergeProps';
Expand All @@ -48,10 +49,13 @@ import {useFocusWithin} from '../interactions/useFocusWithin';
import {useId} from '../utils/useId';
import {useLocale} from '../i18n/I18nProvider';
import {useLocalizedStringFormatter} from '../i18n/useLocalizedStringFormatter';
import {useMemo, useRef} from 'react';

export interface AriaDateRangePickerProps<T extends DateValue>
extends DateRangePickerProps<T>, AriaLabelingProps, Omit<InputDOMProps, 'name'>, DOMProps {}
export interface AriaDateRangePickerProps<T extends DateValue, Target extends Element = Element>
extends
DateRangePickerProps<T, Target>,
AriaLabelingProps,
Omit<InputDOMProps, 'name'>,
DOMProps {}

export interface DateRangePickerAria extends ValidationResult {
/** Props for the date range picker's visible label element, if any. */
Expand Down Expand Up @@ -79,8 +83,8 @@ export interface DateRangePickerAria extends ValidationResult {
* A date range picker combines two DateFields and a RangeCalendar popover to allow
* users to enter or select a date and time range.
*/
export function useDateRangePicker<T extends DateValue>(
props: AriaDateRangePickerProps<T>,
export function useDateRangePicker<T extends DateValue, Target extends Element = Element>(
props: AriaDateRangePickerProps<T, Target>,
state: DateRangePickerState,
ref: RefObject<Element | null>
): DateRangePickerAria {
Expand Down Expand Up @@ -158,14 +162,14 @@ export function useDateRangePicker<T extends DateValue>(
let dialog = document.getElementById(dialogId);
if (!nodeContains(dialog, e.relatedTarget)) {
isFocused.current = false;
props.onBlur?.(e);
props.onBlur?.(e as FocusEvent<Target>);
props.onFocusChange?.(false);
}
},
onFocusWithin: e => {
if (!isFocused.current) {
isFocused.current = true;
props.onFocus?.(e);
props.onFocus?.(e as FocusEvent<Target>);
props.onFocusChange?.(true);
}
}
Expand Down
16 changes: 11 additions & 5 deletions packages/react-stately/src/datepicker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@ export type MappedTimeValue<T> = T extends ZonedDateTime
: never;

export type Granularity = 'day' | 'hour' | 'minute' | 'second';
interface DateFieldBase<T extends DateValue>
extends InputBase, Validation<MappedDateValue<T>>, FocusableProps, LabelableProps, HelpTextProps {
interface DateFieldBase<T extends DateValue, Target extends Element = Element>
extends
InputBase,
Validation<MappedDateValue<T>>,
FocusableProps<Target>,
LabelableProps,
HelpTextProps {
/** The minimum allowed date that a user may select. */
minValue?: DateValue | null;
/** The maximum allowed date that a user may select. */
Expand Down Expand Up @@ -85,7 +90,8 @@ interface DateFieldBase<T extends DateValue>
export interface DateFieldProps<T extends DateValue>
extends DateFieldBase<T>, ValueBase<T | null, MappedDateValue<T> | null> {}

interface DatePickerBase<T extends DateValue> extends DateFieldBase<T>, OverlayTriggerProps {
interface DatePickerBase<T extends DateValue, Target extends Element = Element>
extends DateFieldBase<T, Target>, OverlayTriggerProps {
/**
* Controls the behavior of paging. Pagination either works by advancing the visible page by
* visibleDuration (default) or one unit of visibleDuration.
Expand All @@ -102,9 +108,9 @@ interface DatePickerBase<T extends DateValue> extends DateFieldBase<T>, OverlayT
export interface DatePickerProps<T extends DateValue>
extends DatePickerBase<T>, ValueBase<T | null, MappedDateValue<T> | null> {}

export interface DateRangePickerProps<T extends DateValue>
export interface DateRangePickerProps<T extends DateValue, Target extends Element = Element>
extends
Omit<DatePickerBase<T>, 'validate' | 'isDateUnavailable'>,
Omit<DatePickerBase<T, Target>, 'validate' | 'isDateUnavailable'>,
Validation<RangeValue<MappedDateValue<T>>>,
ValueBase<RangeValue<T> | null, RangeValue<MappedDateValue<T>> | null> {
/**
Expand Down
12 changes: 7 additions & 5 deletions packages/react-stately/src/datepicker/useDateRangePickerState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ import {useControlledState} from '../utils/useControlledState';
import {useMemo, useState} from 'react';

export interface DateRangePickerStateOptions<
T extends DateValue = DateValue
> extends DateRangePickerProps<T> {
T extends DateValue = DateValue,
Target extends Element = Element
> extends DateRangePickerProps<T, Target> {
/**
* Determines whether the date picker popover should close automatically when a date is selected.
*
Expand Down Expand Up @@ -106,9 +107,10 @@ export interface DateRangePickerState extends OverlayTriggerState, FormValidatio
* A date range picker combines two DateFields and a RangeCalendar popover to allow
* users to enter or select a date and time range.
*/
export function useDateRangePickerState<T extends DateValue = DateValue>(
props: DateRangePickerStateOptions<T>
): DateRangePickerState {
export function useDateRangePickerState<
T extends DateValue = DateValue,
Target extends Element = Element
>(props: DateRangePickerStateOptions<T, Target>): DateRangePickerState {
let overlayState = useOverlayTriggerState(props);
let [controlledValue, setControlledValue] = useControlledState<
DateRange | null,
Expand Down