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
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@

import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import { Field } from '@fluentui/react-field';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { IBaseProps } from '@fluentui/utilities';
import type { ICalloutProps } from '@fluentui/react';
import type { IComponentAs } from '@fluentui/utilities';
import { InputField_unstable } from '@fluentui/react-input';
import { Input } from '@fluentui/react-input';
import type { InputProps } from '@fluentui/react-input';
import type { IStyle } from '@fluentui/style-utilities';
import type { IStyleFunctionOrObject } from '@fluentui/utilities';
import type { ITextFieldProps } from '@fluentui/react';
import type { ITheme } from '@fluentui/style-utilities';
import type { PopoverProps } from '@fluentui/react-popover';
import type { PopoverSurfaceProps } from '@fluentui/react-popover';
import { PopoverSurface } from '@fluentui/react-popover';
import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';

Expand Down Expand Up @@ -415,9 +415,8 @@ export type DatePickerProps = ComponentProps<Partial<DatePickerSlots>> & {
componentRef?: React_2.RefObject<IDatePicker>;
styles?: IStyleFunctionOrObject<DatePickerStyleProps, DatePickerStyles>;
theme?: ITheme;
calloutProps?: ICalloutProps;
calendarProps?: CalendarProps;
textField?: ITextFieldProps;
textField?: InputProps;
calendarAs?: IComponentAs<CalendarProps>;
onSelectDate?: (date: Date | null | undefined) => void;
label?: string;
Expand Down Expand Up @@ -465,7 +464,6 @@ export interface DatePickerStrings extends CalendarStrings {

// @public (undocumented)
export interface DatePickerStyleProps {
className?: string;
// (undocumented)
disabled?: boolean;
// (undocumented)
Expand Down Expand Up @@ -691,7 +689,7 @@ export const useCalendarYearStyles_unstable: (props: CalendarYearStyleProps) =>
export const useDatePicker_unstable: (props: DatePickerProps, ref: React_2.Ref<HTMLElement>) => DatePickerState;

// @public
export const useDatePickerStyles_unstable: (props: DatePickerStyleProps) => Record<keyof DatePickerStyles, string>;
export const useDatePickerStyles_unstable: (state: DatePickerState) => DatePickerState;

// @public (undocumented)
export interface WeekCorners {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-components/react-datepicker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"@fluentui/react-utilities": "^9.5.1",
"@fluentui/keyboard-keys": "^9.0.1",
"@fluentui/utilities": "^8.13.6",
"@fluentui/react": "^8.105.5",
"@fluentui/react-field": "9.0.0-alpha.18",
"@fluentui/react-icons": "^2.0.175",
"@fluentui/react-shared-contexts": "^9.2.0",
"@fluentui/react-tabster": "^9.5.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import * as React from 'react';
import { renderDatePicker_unstable } from './renderDatePicker';
import { useDatePicker_unstable } from './useDatePicker';
import { useDatePickerStyles_unstable } from './useDatePickerStyles';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import type { DatePickerProps } from './DatePicker.types';

export const DatePicker: ForwardRefComponent<DatePickerProps> = React.forwardRef((props, ref) => {
const state = useDatePicker_unstable(props, ref);

useDatePickerStyles_unstable(state);
return renderDatePicker_unstable(state);
}) as ForwardRefComponent<DatePickerProps>;
DatePicker.displayName = 'DatePicker';
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as React from 'react';
import { InputField_unstable as InputField } from '@fluentui/react-input';
import { Input } from '@fluentui/react-input';
import { Field } from '@fluentui/react-field';
import { DayOfWeek, FirstWeekOfYear } from '../../utils';
import type { ICalloutProps, ITextFieldProps } from '@fluentui/react';
import type { PopoverProps, PopoverSurfaceProps } from '@fluentui/react-popover';
import { PopoverSurface } from '@fluentui/react-popover';
import type { InputProps } from '@fluentui/react-input';
import type { PopoverProps } from '@fluentui/react-popover';
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
import type { IStyle, ITheme } from '@fluentui/style-utilities';
import type { IStyleFunctionOrObject, IComponentAs } from '@fluentui/utilities';
Expand All @@ -11,9 +13,11 @@ import type { CalendarStrings, DateFormatting } from '../../utils';

export type DatePickerSlots = {
root: NonNullable<Slot<'div'>>;
// eslint-disable-next-line deprecation/deprecation -- https://github.com/microsoft/fluentui/issues/26505
inputField: NonNullable<Slot<typeof InputField>>;
inputField: NonNullable<Slot<typeof Field>>;
input: NonNullable<Slot<typeof Input>>;
wrapper: NonNullable<Slot<'div'>>;
popover: NonNullable<Slot<Partial<PopoverProps>>>;
popoverSurface: NonNullable<Slot<typeof PopoverSurface>>;
};

// eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down Expand Up @@ -45,11 +49,6 @@ export type DatePickerProps = ComponentProps<Partial<DatePickerSlots>> & {
*/
theme?: ITheme;

/**
* Pass callout props to callout component
*/
calloutProps?: ICalloutProps;

/**
* Pass calendar props to calendar component
*/
Expand All @@ -59,7 +58,7 @@ export type DatePickerProps = ComponentProps<Partial<DatePickerSlots>> & {
* Pass textField props to textField component.
* Prop name is "textField" for compatibility with upcoming slots work.
*/
textField?: ITextFieldProps;
textField?: InputProps;

/**
* Custom Calendar to be used for date picking
Expand Down Expand Up @@ -260,8 +259,8 @@ export type DatePickerProps = ComponentProps<Partial<DatePickerSlots>> & {
export type DatePickerState = ComponentState<DatePickerSlots> &
Required<Pick<DatePickerProps, 'calendarAs'>> & {
calendar: CalendarProps;
popover: Partial<PopoverProps>;
popoverSurface: PopoverSurfaceProps;
disabled: boolean;
isDatePickerShown: boolean;
};

/**
Expand Down Expand Up @@ -295,11 +294,6 @@ export interface DatePickerStrings extends CalendarStrings {
* {@docCategory DatePicker}
*/
export interface DatePickerStyleProps {
/**
* Accept custom classNames
*/
className?: string;

// Insert DatePicker style props below
disabled?: boolean;
underlined?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Popover, PopoverSurface, PopoverTrigger } from '@fluentui/react-popover';
import { PopoverTrigger } from '@fluentui/react-popover';
import { getSlots } from '@fluentui/react-utilities';
import type { PopoverProps } from '@fluentui/react-popover';
import type { DatePickerSlots, DatePickerState } from './DatePicker.types';

/**
Expand All @@ -9,23 +10,27 @@ import type { DatePickerSlots, DatePickerState } from './DatePicker.types';
export const renderDatePicker_unstable = (state: DatePickerState) => {
const { slots, slotProps } = getSlots<DatePickerSlots>(state);

const { calendar, calendarAs: Calendar, popover, popoverSurface } = state;
const { calendar, calendarAs: Calendar } = state;

return (
<slots.root {...slotProps.root}>
<slots.wrapper {...slotProps.wrapper}>
<Popover {...popover}>
<slots.popover {...(slotProps.popover as PopoverProps)}>
<PopoverTrigger>
{popoverTriggerChildProps => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const rootProps: any = { root: popoverTriggerChildProps };
return <slots.inputField {...slotProps.inputField} {...rootProps} />;
return (
<slots.inputField {...slotProps.inputField}>
<slots.input {...slotProps.input} {...rootProps} />
</slots.inputField>
);
}}
</PopoverTrigger>
<PopoverSurface {...popoverSurface}>
<slots.popoverSurface {...slotProps.popoverSurface}>
<Calendar {...calendar} />
</PopoverSurface>
</Popover>
</slots.popoverSurface>
</slots.popover>
</slots.wrapper>
</slots.root>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import * as React from 'react';
import { ArrowDown, Enter, Escape } from '@fluentui/keyboard-keys';
import { CalendarMonthRegular } from '@fluentui/react-icons';
import { InputField_unstable as InputField } from '@fluentui/react-input';
import { getNativeElementProps, resolveShorthand, useControllableState, useId } from '@fluentui/react-utilities';
import { Input } from '@fluentui/react-input';
import { Field } from '@fluentui/react-field';
import {
getNativeElementProps,
mergeCallbacks,
resolveShorthand,
useControllableState,
useId,
} from '@fluentui/react-utilities';
import { Async } from '@fluentui/utilities';
import { mergeClasses } from '@griffel/react';
import { compareDatePart, getDatePartHashValue, DayOfWeek, FirstWeekOfYear } from '../../utils';
import { Calendar } from '../Calendar/Calendar';
import { defaultDatePickerStrings } from './defaults';
import { useDatePickerStyles_unstable } from './useDatePickerStyles';
import type { ITextField } from '@fluentui/react';
import type { InputOnChangeData, InputFieldProps_unstable as InputFieldProps } from '@fluentui/react-input';
import type { OnOpenChangeData, OpenPopoverEvents } from '@fluentui/react-popover';
import { OnOpenChangeData, OpenPopoverEvents, Popover } from '@fluentui/react-popover';
import { PopoverSurface } from '@fluentui/react-popover';
import type { PopoverProps } from '@fluentui/react-popover';
import type { InputProps, InputOnChangeData } from '@fluentui/react-input';
import type { ICalendar } from '../Calendar/Calendar.types';
import type { DatePickerProps, DatePickerState } from './DatePicker.types';

Expand All @@ -20,7 +26,7 @@ function isDateOutOfBounds(date: Date, minDate?: Date, maxDate?: Date): boolean
}

function useFocusLogic() {
const textFieldRef = React.useRef<ITextField>(null);
const textFieldRef = React.useRef<{ focus: () => void }>(null);
const preventFocusOpeningPicker = React.useRef(false);

const focus = () => {
Expand Down Expand Up @@ -217,8 +223,6 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
borderless = false,
calendarAs = Calendar,
calendarProps,
calloutProps,
className,
dateTimeFormatter,
disabled,
disableAutoFocus = true,
Expand Down Expand Up @@ -391,10 +395,8 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
setFormattedDate(newValue);
}
}

props.textField?.onChange?.(ev, newValue);
},
[allowTextInput, dismissDatePickerPopup, isCalendarShown, props.textField, setFormattedDate],
[allowTextInput, dismissDatePickerPopup, isCalendarShown, setFormattedDate],
);

const onTextFieldKeyDown = React.useCallback(
Expand Down Expand Up @@ -500,14 +502,6 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
// );
// };

const classNames = useDatePickerStyles_unstable({
className,
disabled,
underlined,
label: !!label,
isDatePickerShown: isCalendarShown,
});

// const nativeProps = getNativeProps<React.HTMLAttributes<HTMLDivElement>>(props, divProperties, ['value']);
// // const iconProps = textFieldProps && textFieldProps.iconProps;
const textFieldId =
Expand All @@ -518,8 +512,7 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
// // eslint-disable-next-line @typescript-eslint/no-explicit-any
// (textFieldProps as any)?.['data-is-focusable'] ?? (props as any)['data-is-focusable'] ?? true;

// eslint-disable-next-line deprecation/deprecation -- https://github.com/microsoft/fluentui/issues/26505
const inputAppearance: InputFieldProps['appearance'] = underlined
const inputAppearance: InputProps['appearance'] = underlined
? 'underline'
: borderless
? 'filled-lighter'
Expand All @@ -537,10 +530,10 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
const root = getNativeElementProps('div', {
ref,
...props,
className: classNames.root,
});

const inputFieldShorthand = resolveShorthand(props.inputField, {
const inputShorthand = resolveShorthand(props.input, {
required: true,
defaultProps: {
appearance: inputAppearance,
'aria-controls': isCalendarShown ? calloutId : undefined,
Expand All @@ -554,38 +547,62 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
/>
),
disabled,
label,
id: textFieldId,
placeholder,
readOnly: !allowTextInput,
required: isRequired,
role: 'combobox',
tabIndex,
...textFieldProps,
},
});

const inputFieldShorthand = resolveShorthand(props.inputField, {
defaultProps: {
label,
required: isRequired,
validationMessage: errorMessage ?? statusMessage,
validationState: errorMessage ? 'error' : undefined,
// eslint-disable-next-line deprecation/deprecation -- https://github.com/microsoft/fluentui/issues/26505
...(textFieldProps as InputFieldProps),
className: mergeClasses(classNames.textField, textFieldProps?.className),
id: textFieldId,
},
required: true,
});
inputFieldShorthand.onBlur = onTextFieldBlur;
inputFieldShorthand.onChange = onTextFieldChanged;
inputFieldShorthand.onClick = onTextFieldClick;
inputFieldShorthand.onFocus = onTextFieldFocus;
inputFieldShorthand.onKeyDown = onTextFieldKeyDown;
inputFieldShorthand.value = formattedDate;
inputShorthand.onBlur = onTextFieldBlur;
inputShorthand.onClick = onTextFieldClick;
inputShorthand.onFocus = onTextFieldFocus;
inputShorthand.onKeyDown = onTextFieldKeyDown;
inputShorthand.onChange = mergeCallbacks(onTextFieldChanged, props.textField?.onChange);
inputShorthand.value = formattedDate;

const wrapperShorthand = resolveShorthand(props.wrapper, {
defaultProps: {
'aria-owns': isCalendarShown ? calloutId : undefined,
className: classNames.wrapper,
},
required: true,
});

const popoverShorthand = resolveShorthand(props.popover, {
defaultProps: {
onOpenChange: onPopoverOpenChange,
open: isCalendarShown,
positioning: 'below-start',
trapFocus: true,
},
required: true,
});

const popoverSurfaceShorthand = resolveShorthand(props.popoverSurface, {
defaultProps: {
'aria-label': pickerAriaLabel,
id: calloutId,
role: 'dialog',
},
required: true,
});

return {
calendarAs,
disabled: !!disabled,
isDatePickerShown: isCalendarShown,

calendar: {
...calendarProps,
Expand All @@ -609,28 +626,21 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref<HT
today,
value: selectedDate || initialPickerDate,
},
popover: {
onOpenChange: onPopoverOpenChange,
open: isCalendarShown,
positioning: 'below-start',
trapFocus: true,
},
popoverSurface: {
'aria-label': pickerAriaLabel,
className: mergeClasses(classNames.callout, calloutProps?.className),
id: calloutId,
role: 'dialog',
},
popover: popoverShorthand,
popoverSurface: popoverSurfaceShorthand,

// Slots definition
components: {
root: 'div',
// eslint-disable-next-line deprecation/deprecation -- https://github.com/microsoft/fluentui/issues/26505
inputField: InputField,
inputField: Field,
input: Input,
wrapper: 'div',
popover: Popover as React.FC<Partial<PopoverProps>>,
popoverSurface: PopoverSurface,
},

inputField: inputFieldShorthand,
input: inputShorthand,
root,
wrapper: wrapperShorthand,
};
Expand Down
Loading