import * as React from 'react'; import * as PropTypes from 'prop-types'; import { useUtils } from '../_shared/hooks/useUtils'; import { MobileWrapper } from '../wrappers/MobileWrapper'; import { withDefaultProps } from '../_shared/withDefaultProps'; import { useParsedDate } from '../_shared/hooks/date-helpers-hooks'; import { withDateAdapterProp } from '../_shared/withDateAdapterProp'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { ResponsiveTooltipWrapper } from '../wrappers/ResponsiveWrapper'; import { defaultMinDate, defaultMaxDate, date } from '../constants/prop-types'; import { DesktopTooltipWrapper } from '../wrappers/DesktopTooltipWrapper'; import { SomeWrapper, ExtendWrapper, StaticWrapper } from '../wrappers/Wrapper'; import { RangeInput, AllSharedDateRangePickerProps, DateRange } from './RangeTypes'; import { makeValidationHook, ValidationProps } from '../_shared/hooks/useValidation'; import { usePickerState, PickerStateValueManager } from '../_shared/hooks/usePickerState'; import { DateRangePickerView, ExportedDateRangePickerViewProps } from './DateRangePickerView'; import { DateRangePickerInput, ExportedDateRangePickerInputProps, DateRangeInputProps, } from './DateRangePickerInput'; import { parseRangeInputValue, validateDateRange, DateRangeValidationError, } from '../_helpers/date-utils'; export interface BaseDateRangePickerProps extends ExportedDateRangePickerViewProps, ValidationProps>, ExportedDateRangePickerInputProps { /** * Text for start input label and toolbar placeholder * * @default "Start" */ startText?: React.ReactNode; /** * Text for end input label and toolbar placeholder * * @default "end" */ endText?: React.ReactNode; } type RangePickerComponent = ( props: BaseDateRangePickerProps & ExtendWrapper & AllSharedDateRangePickerProps & React.RefAttributes ) => JSX.Element; export const useDateRangeValidation = makeValidationHook< DateRangeValidationError, RangeInput, BaseDateRangePickerProps >(validateDateRange, { defaultValidationError: [null, null], isSameError: (a, b) => a[1] === b[1] && a[0] === b[0], }); export function makeRangePicker( name: string, Wrapper: TWrapper ): RangePickerComponent { const WrapperComponent = makeWrapperComponent(Wrapper, { KeyboardDateInputComponent: DateRangePickerInput, PureDateInputComponent: DateRangePickerInput, }); const rangePickerValueManager: PickerStateValueManager = { emptyValue: [null, null], parseInput: parseRangeInputValue, areValuesEqual: (utils, a, b) => utils.isEqual(a[0], b[0]) && utils.isEqual(a[1], b[1]), }; function RangePickerWithStateAndWrapper({ calendars, value, onChange, mask = '__/__/____', startText = 'Start', endText = 'End', inputFormat: passedInputFormat, minDate: __minDate = defaultMinDate as TDate, maxDate: __maxDate = defaultMaxDate as TDate, ...other }: BaseDateRangePickerProps & AllSharedDateRangePickerProps & ExtendWrapper) { const utils = useUtils(); const minDate = useParsedDate(__minDate); const maxDate = useParsedDate(__maxDate); const [currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd] = React.useState< 'start' | 'end' >('start'); const pickerStateProps = { ...other, value, onChange, inputFormat: passedInputFormat || utils.formats.keyboardDate, }; const restProps = { ...other, minDate, maxDate, }; const { pickerProps, inputProps, wrapperProps } = usePickerState< RangeInput, DateRange >(pickerStateProps, rangePickerValueManager); const validationError = useDateRangeValidation(value, restProps); const DateInputProps = { ...inputProps, ...restProps, currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, startText, endText, mask, validationError, }; return ( open={wrapperProps.open} DateInputProps={DateInputProps} calendars={calendars} currentlySelectingRangeEnd={currentlySelectingRangeEnd} setCurrentlySelectingRangeEnd={setCurrentlySelectingRangeEnd} startText={startText} endText={endText} {...pickerProps} {...restProps} /> ); } RangePickerWithStateAndWrapper.propTypes = { value: PropTypes.arrayOf(date).isRequired, onChange: PropTypes.func.isRequired, startText: PropTypes.node, endText: PropTypes.node, } as any; const FinalPickerComponent = withDefaultProps( { name }, withDateAdapterProp(RangePickerWithStateAndWrapper) ); // @ts-ignore @see lib/src/Picker/makePickerWithState.tsx:95 return React.forwardRef< HTMLDivElement, React.ComponentProps >((props, ref) => ); } export const DateRangePicker = makeRangePicker( 'MuiPickersDateRangePicker', ResponsiveTooltipWrapper ); export type DateRangePickerProps = React.ComponentProps; export const DesktopDateRangePicker = makeRangePicker( 'MuiDesktopDateRangePicker', DesktopTooltipWrapper ); export type DesktopDateRangePickerProps = React.ComponentProps; export const MobileDateRangePicker = makeRangePicker('MuiMobileDateRangePicker', MobileWrapper); export type MobileDateRangePickerProps = React.ComponentProps; export const StaticDateRangePicker = makeRangePicker('MuiStaticDateRangePicker', StaticWrapper); export type StaticDateRangePickerProps = React.ComponentProps; export { DateRangeDelimiter } from './DateRangeDelimiter';