Skip to content

Commit 9e18b4a

Browse files
authored
chore: fix S2 datepicker errorMessage type (adobe#9909)
* chore: fix S2 DatePicker errorMessage type * small fix * spacing * update commment * update types for date range picker
1 parent b65a4aa commit 9e18b4a

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

packages/@react-spectrum/s2/src/DatePicker.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ export interface DatePickerProps<T extends DateValue> extends
5252
* The maximum number of months to display at once in the calendar popover, if screen space permits.
5353
* @default 1
5454
*/
55-
maxVisibleMonths?: number,
56-
/**
57-
* The error message to display when the calendar is invalid.
58-
*/
59-
errorMessage?: ReactNode
55+
maxVisibleMonths?: number
6056
}
6157

6258
export const DatePickerContext = createContext<ContextValue<Partial<DatePickerProps<any>>, HTMLDivElement>>(null);
@@ -167,6 +163,10 @@ export const DatePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(function
167163
let timeMaxValue = props.maxValue && 'hour' in props.maxValue ? props.maxValue : undefined;
168164
let timeGranularity = state.granularity === 'hour' || state.granularity === 'minute' || state.granularity === 'second' ? state.granularity : undefined;
169165
let showTimeField = !!timeGranularity;
166+
167+
// Ideally, we could omit errorMessage here and let S2 Calendar read it from RAC's CalendarContext which already contains the resolved value via calendarProps from useDatePicker.
168+
// However, RAC's CalendarProps omits errorMessage, so reading it back from the context would require an unsafe cast. Instead, we resolve it here using the same logic as useDatePicker.
169+
let resolvedErrorMessage = typeof errorMessage === 'function' ? errorMessage(state.displayValidation) : (errorMessage || state.displayValidation.validationErrors.join(' '));
170170
return (
171171
<>
172172
<FieldLabel
@@ -208,7 +208,7 @@ export const DatePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(function
208208
<Calendar
209209
visibleMonths={maxVisibleMonths}
210210
createCalendar={createCalendar}
211-
errorMessage={errorMessage} />
211+
errorMessage={resolvedErrorMessage} />
212212
{showTimeField && (
213213
<div className={style({display: 'flex', gap: 16, contain: 'inline-size'})}>
214214
<TimeField
@@ -231,7 +231,7 @@ export const DatePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(function
231231
isDisabled={isDisabled}
232232
isInvalid={isInvalid}
233233
description={descriptionMessage}>
234-
{errorMessage}
234+
{resolvedErrorMessage}
235235
</HelpText>
236236
</>
237237
);

packages/@react-spectrum/s2/src/DateRangePicker.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
} from 'react-aria-components/DateRangePicker';
1818
import {CalendarButton, CalendarPopover, timeField} from './DatePicker';
1919
import {ContextValue} from 'react-aria-components/slots';
20-
import {createContext, forwardRef, ReactElement, ReactNode, Ref, useContext, useState} from 'react';
20+
import {createContext, forwardRef, ReactElement, Ref, useContext, useState} from 'react';
2121
import {DateInput, DateInputContainer, InvalidIndicator} from './DateField';
2222
import {field, fieldInput, getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
2323
import {FieldGroup, FieldLabel, HelpText} from './Field';
@@ -50,11 +50,7 @@ export interface DateRangePickerProps<T extends DateValue> extends
5050
* The maximum number of months to display at once in the calendar popover, if screen space permits.
5151
* @default 1
5252
*/
53-
maxVisibleMonths?: number,
54-
/**
55-
* The error message to display when the calendar is invalid.
56-
*/
57-
errorMessage?: ReactNode
53+
maxVisibleMonths?: number
5854
}
5955

6056
export const DateRangePickerContext = createContext<ContextValue<Partial<DateRangePickerProps<any>>, HTMLDivElement>>(null);
@@ -111,6 +107,10 @@ export const DateRangePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(func
111107
|| state.granularity === 'second'
112108
? state.granularity : undefined;
113109
let showTimeField = !!timeGranularity;
110+
111+
// Ideally, we could omit errorMessage here and let S2 Calendar read it from RAC's CalendarContext which already contains the resolved value via calendarProps from useDatePicker.
112+
// However, RAC's CalendarProps omits errorMessage, so reading it back from the context would require an unsafe cast. Instead, we resolve it here using the same logic as useDatePicker.
113+
let resolvedErrorMessage = typeof errorMessage === 'function' ? errorMessage(state.displayValidation) : (errorMessage || state.displayValidation.validationErrors.join(' '));
114114
return (
115115
<>
116116
<FieldLabel
@@ -156,7 +156,7 @@ export const DateRangePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(func
156156
visibleMonths={maxVisibleMonths}
157157
createCalendar={createCalendar}
158158
interactOutsideBehavior={interactOutsideBehavior}
159-
errorMessage={errorMessage} />
159+
errorMessage={resolvedErrorMessage} />
160160
{showTimeField && (
161161
<div className={style({display: 'flex', gap: 16, contain: 'inline-size', marginTop: 24})}>
162162
<TimeField
@@ -189,7 +189,7 @@ export const DateRangePicker = /*#__PURE__*/ (forwardRef as forwardRefType)(func
189189
isDisabled={isDisabled}
190190
isInvalid={isInvalid}
191191
description={descriptionMessage}>
192-
{errorMessage}
192+
{resolvedErrorMessage}
193193
</HelpText>
194194
</>
195195
);

0 commit comments

Comments
 (0)