diff --git a/change/@fluentui-react-datepicker-compat-f7349def-c3e5-4ea0-9ca7-e2be0c852515.json b/change/@fluentui-react-datepicker-compat-f7349def-c3e5-4ea0-9ca7-e2be0c852515.json new file mode 100644 index 00000000000000..989091ae937ff5 --- /dev/null +++ b/change/@fluentui-react-datepicker-compat-f7349def-c3e5-4ea0-9ca7-e2be0c852515.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "fix: Make onValidationError onValidationResult so the error is updated when there's no longer an error.", + "packageName": "@fluentui/react-datepicker-compat", + "email": "esteban.230@hotmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-datepicker-compat/etc/react-datepicker-compat.api.md b/packages/react-components/react-datepicker-compat/etc/react-datepicker-compat.api.md index d6ad592e1bb4dd..f6efab232fb882 100644 --- a/packages/react-components/react-datepicker-compat/etc/react-datepicker-compat.api.md +++ b/packages/react-components/react-datepicker-compat/etc/react-datepicker-compat.api.md @@ -153,9 +153,7 @@ export const DatePicker: ForwardRefComponent; export const datePickerClassNames: SlotClassNames; // @public -export type DatePickerErrorData = { - error: 'invalid-input' | 'out-of-bounds' | 'required-input'; -}; +export type DatePickerErrorType = 'invalid-input' | 'out-of-bounds' | 'required-input'; // @public (undocumented) export type DatePickerProps = Omit>, 'defaultValue' | 'value'> & { @@ -172,7 +170,7 @@ export type DatePickerProps = Omit>, 'de defaultOpen?: boolean; open?: boolean; onOpenChange?: (open: boolean) => void; - onValidationError?: (data: DatePickerErrorData) => void; + onValidationResult?: (data: DatePickerValidationResultData) => void; inlinePopup?: boolean; positioning?: PositioningProps; placeholder?: string; @@ -196,6 +194,11 @@ export type DatePickerProps = Omit>, 'de showCloseButton?: boolean; }; +// @public +export type DatePickerValidationResultData = { + error?: DatePickerErrorType; +}; + // @public export enum DateRangeType { // (undocumented) @@ -230,7 +233,7 @@ export enum DayOfWeek { export const DAYS_IN_WEEK = 7; // @public (undocumented) -export const defaultDatePickerErrorStrings: Record; +export const defaultDatePickerErrorStrings: Record; // @public (undocumented) export const defaultDatePickerStrings: CalendarStrings; diff --git a/packages/react-components/react-datepicker-compat/src/components/DatePicker/DatePicker.types.ts b/packages/react-components/react-datepicker-compat/src/components/DatePicker/DatePicker.types.ts index 950ec49fa96b18..7418c522045b40 100644 --- a/packages/react-components/react-datepicker-compat/src/components/DatePicker/DatePicker.types.ts +++ b/packages/react-components/react-datepicker-compat/src/components/DatePicker/DatePicker.types.ts @@ -105,9 +105,9 @@ export type DatePickerProps = Omit>, 'de onOpenChange?: (open: boolean) => void; /** - * Callback to run when the DatePicker encounters an error when validating the input + * Callback to run after the DatePicker's input has been validated */ - onValidationError?: (data: DatePickerErrorData) => void; + onValidationResult?: (data: DatePickerValidationResultData) => void; /** * Whether the DatePicker should render the popup as inline or in a portal @@ -238,9 +238,14 @@ export type DatePickerState = ComponentState & { }; /** - * Data passed to the `onValidationError` callback. + * Data passed to the `onValidationResult` callback. */ -export type DatePickerErrorData = { +export type DatePickerValidationResultData = { /** The error found when validating the input. */ - error: 'invalid-input' | 'out-of-bounds' | 'required-input'; + error?: DatePickerErrorType; }; + +/** + * Error types returned by the `onValidationResult` callback. + */ +export type DatePickerErrorType = 'invalid-input' | 'out-of-bounds' | 'required-input'; diff --git a/packages/react-components/react-datepicker-compat/src/components/DatePicker/defaults.ts b/packages/react-components/react-datepicker-compat/src/components/DatePicker/defaults.ts index 6906ad13d407cb..d1b88828b935e7 100644 --- a/packages/react-components/react-datepicker-compat/src/components/DatePicker/defaults.ts +++ b/packages/react-components/react-datepicker-compat/src/components/DatePicker/defaults.ts @@ -1,6 +1,6 @@ import { defaultCalendarStrings } from '../Calendar/defaults'; import type { CalendarStrings } from '../../utils/index'; -import type { DatePickerErrorData } from './DatePicker.types'; +import type { DatePickerErrorType } from './DatePicker.types'; export const defaultDatePickerStrings: CalendarStrings = { ...defaultCalendarStrings, @@ -11,7 +11,7 @@ export const defaultDatePickerStrings: CalendarStrings = { closeButtonAriaLabel: 'Close date picker', }; -export const defaultDatePickerErrorStrings: Record = { +export const defaultDatePickerErrorStrings: Record = { 'invalid-input': 'Invalid date format', 'out-of-bounds': 'Date is out of bounds', 'required-input': 'Field is required', diff --git a/packages/react-components/react-datepicker-compat/src/components/DatePicker/useDatePicker.tsx b/packages/react-components/react-datepicker-compat/src/components/DatePicker/useDatePicker.tsx index 09d3846e29fa08..b5325235b64d57 100644 --- a/packages/react-components/react-datepicker-compat/src/components/DatePicker/useDatePicker.tsx +++ b/packages/react-components/react-datepicker-compat/src/components/DatePicker/useDatePicker.tsx @@ -20,7 +20,7 @@ import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts import { useFocusFinders, useModalAttributes } from '@fluentui/react-tabster'; import { usePopupPositioning } from '../../utils/usePopupPositioning'; import type { CalendarProps, ICalendar } from '../Calendar/Calendar.types'; -import type { DatePickerProps, DatePickerState } from './DatePicker.types'; +import type { DatePickerProps, DatePickerState, DatePickerValidationResultData } from './DatePicker.types'; import type { InputProps, InputOnChangeData } from '@fluentui/react-input'; function isDateOutOfBounds(date: Date, minDate?: Date, maxDate?: Date): boolean { @@ -129,7 +129,7 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref { + let error: DatePickerValidationResultData['error'] | undefined; + if (allowTextInput) { if (formattedDate || date) { // Don't parse if the selected date has the same formatted string as what we're about to parse. @@ -169,24 +171,26 @@ export const useDatePicker_unstable = (props: DatePickerProps, ref: React.Ref { const styles = useStyles(); - const [error, setError] = React.useState(undefined); + const [error, setError] = React.useState(undefined); return ( { maxDate={maxDate} placeholder="Select a date..." allowTextInput - onValidationError={data => setError(data.error)} + onValidationResult={data => setError(data.error)} className={styles.control} /> ); }; + +ErrorHandling.parameters = { + docs: { + description: { + story: + 'To add error handling to a DatePicker, use `onValidationResult` along with Field. `onValidationResult`' + + 'provides an error type string that can be used with defaultDatePickerErrorStrings to get default messages.', + }, + }, +};