Skip to content

Commit

Permalink
[pickers] Simplify internals of *Wrapper components (#25369)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon authored Mar 16, 2021
1 parent c3a1af1 commit cf9db48
Show file tree
Hide file tree
Showing 20 changed files with 210 additions and 996 deletions.
96 changes: 18 additions & 78 deletions packages/material-ui-lab/src/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
OverrideParsableDateProps,
} from '../internal/pickers/hooks/date-helpers-hooks';
import { ExportedDayPickerProps } from '../DayPicker/DayPicker';
import { SomeWrapper, PublicWrapperProps } from '../internal/pickers/wrappers/Wrapper';
import { makeValidationHook, ValidationProps } from '../internal/pickers/hooks/useValidation';
import {
ParsableDate,
Expand All @@ -30,24 +29,18 @@ import Picker from '../internal/pickers/Picker/Picker';
import { KeyboardDateInput } from '../internal/pickers/KeyboardDateInput';
import { PureDateInput } from '../internal/pickers/PureDateInput';
import { usePickerState, PickerStateValueManager } from '../internal/pickers/hooks/usePickerState';
import { BasePickerProps } from '../internal/pickers/typings/BasePicker';
import {
StaticWrapperProps,
DateInputPropsLike,
WrapperProps,
} from '../internal/pickers/wrappers/WrapperProps';

type AllPickerProps<T, TWrapper extends SomeWrapper = SomeWrapper> = T &
type AllResponsiveDatePickerProps = BaseDatePickerProps<unknown> &
AllSharedPickerProps &
PublicWrapperProps<TWrapper>;
ResponsiveWrapperProps;

const valueManager: PickerStateValueManager<unknown, unknown> = {
emptyValue: null,
parseInput: parsePickerInputValue,
areValuesEqual: (utils: MuiPickersAdapter, a: unknown, b: unknown) => utils.isEqual(a, b),
};

type SharedPickerProps<TDate, TWrapper extends SomeWrapper> = PublicWrapperProps<TWrapper> &
type SharedPickerProps<TDate, PublicWrapperProps> = PublicWrapperProps &
AllSharedPickerProps<ParsableDate<TDate>, TDate | null> &
React.RefAttributes<HTMLInputElement>;

Expand All @@ -71,7 +64,7 @@ export const datePickerConfig = {
minDate: __minDate = defaultMinDate,
maxDate: __maxDate = defaultMaxDate,
...other
}: AllPickerProps<BaseDatePickerProps<unknown>>) => {
}: BaseDatePickerProps<unknown> & AllSharedPickerProps) => {
const utils = useUtils();
const minDate = useParsedDate(__minDate);
const maxDate = useParsedDate(__maxDate);
Expand All @@ -87,69 +80,16 @@ export const datePickerConfig = {
},
};

export type DatePickerGenericComponent<TWrapper extends SomeWrapper> = (<TDate>(
props: BaseDatePickerProps<TDate> & SharedPickerProps<TDate, TWrapper>,
export type DatePickerGenericComponent<PublicWrapperProps> = (<TDate>(
props: BaseDatePickerProps<TDate> & SharedPickerProps<TDate, PublicWrapperProps>,
) => JSX.Element) & { propTypes?: any };

const name = 'MuiDatePicker';
const { DefaultToolbarComponent, useInterceptProps, useValidation } = datePickerConfig;

interface DatePickerWrapperProps
extends Partial<BasePickerProps<any, any>>,
ResponsiveWrapperProps,
StaticWrapperProps {
children: React.ReactNode;
DateInputProps: DateInputPropsLike;
wrapperProps: Omit<WrapperProps, 'DateInputProps'>;
}

function DatePickerWrapper(props: DatePickerWrapperProps) {
const {
disableCloseOnSelect,
cancelText,
clearable,
clearText,
DateInputProps,
DialogProps,
displayStaticWrapperAs,
inputFormat,
okText,
onAccept,
onChange,
onClose,
onOpen,
open,
PopperProps,
todayText,
value,
wrapperProps,
...other
} = props;

const TypedWrapper = ResponsiveWrapper as SomeWrapper;

return (
<TypedWrapper
clearable={clearable}
clearText={clearText}
DialogProps={DialogProps}
PopperProps={PopperProps}
okText={okText}
todayText={todayText}
cancelText={cancelText}
DateInputProps={DateInputProps}
KeyboardDateInputComponent={KeyboardDateInput}
PureDateInputComponent={PureDateInput}
displayStaticWrapperAs={displayStaticWrapperAs}
{...wrapperProps}
{...other}
/>
);
}

export interface DatePickerProps<TDate = unknown>
extends BaseDatePickerProps<unknown>,
PublicWrapperProps<typeof ResponsiveWrapper>,
ResponsiveWrapperProps,
AllSharedPickerProps<ParsableDate<TDate>, TDate> {}

/**
Expand All @@ -166,17 +106,11 @@ const DatePicker = React.forwardRef(function DatePicker<TDate>(
inProps: DatePickerProps<TDate>,
ref: React.Ref<HTMLInputElement>,
) {
const allProps = useInterceptProps(inProps) as AllPickerProps<
BaseDatePickerProps<unknown>,
typeof ResponsiveWrapper
>;
const allProps = useInterceptProps(inProps) as AllResponsiveDatePickerProps;

// This is technically unsound if the type parameters appear in optional props.
// Optional props can be filled by `useThemeProps` with types that don't match the type parameters.
const props: AllPickerProps<
BaseDatePickerProps<unknown>,
typeof ResponsiveWrapper
> = useThemeProps({
const props: AllResponsiveDatePickerProps = useThemeProps({
props: allProps,
name,
});
Expand All @@ -193,17 +127,23 @@ const DatePicker = React.forwardRef(function DatePicker<TDate>(
const AllDateInputProps = { ...inputProps, ...other, ref, validationError };

return (
<DatePickerWrapper wrapperProps={wrapperProps} DateInputProps={AllDateInputProps} {...other}>
<ResponsiveWrapper
{...other}
{...wrapperProps}
DateInputProps={AllDateInputProps}
KeyboardDateInputComponent={KeyboardDateInput}
PureDateInputComponent={PureDateInput}
>
<Picker
{...pickerProps}
toolbarTitle={props.label || props.toolbarTitle}
ToolbarComponent={other.ToolbarComponent || DefaultToolbarComponent}
DateInputProps={AllDateInputProps}
{...other}
/>
</DatePickerWrapper>
</ResponsiveWrapper>
);
}) as DatePickerGenericComponent<typeof ResponsiveWrapper>;
}) as DatePickerGenericComponent<ResponsiveWrapperProps>;

DatePicker.propTypes /* remove-proptypes */ = {
// ----------------------------- Warning --------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { unstable_useThemeProps as useThemeProps } from '@material-ui/core/style
import { useUtils } from '../internal/pickers/hooks/useUtils';
import { useParsedDate } from '../internal/pickers/hooks/date-helpers-hooks';
import { defaultMinDate, defaultMaxDate } from '../internal/pickers/constants/prop-types';
import { SomeWrapper, PublicWrapperProps } from '../internal/pickers/wrappers/Wrapper';
import { SomeWrapper } from '../internal/pickers/wrappers/Wrapper';
import { RangeInput, AllSharedDateRangePickerProps, DateRange } from './RangeTypes';
import { makeValidationHook, ValidationProps } from '../internal/pickers/hooks/useValidation';
import { usePickerState, PickerStateValueManager } from '../internal/pickers/hooks/usePickerState';
Expand All @@ -14,13 +14,10 @@ import {
validateDateRange,
DateRangeValidationError,
} from '../internal/pickers/date-utils';
import {
DateInputPropsLike,
StaticWrapperProps,
WrapperProps,
} from '../internal/pickers/wrappers/WrapperProps';
import { DateInputPropsLike, PrivateWrapperProps } from '../internal/pickers/wrappers/WrapperProps';
import { BasePickerProps } from '../internal/pickers/typings/BasePicker';
import { ResponsiveWrapperProps } from '../internal/pickers/wrappers/ResponsiveWrapper';
import { StaticWrapperProps } from '../internal/pickers/wrappers/StaticWrapper';

export interface BaseDateRangePickerProps<TDate>
extends ExportedDateRangePickerViewProps<TDate>,
Expand All @@ -38,9 +35,9 @@ export interface BaseDateRangePickerProps<TDate>
endText?: React.ReactNode;
}

export type DateRangePickerComponent<TWrapper extends SomeWrapper> = (<TDate>(
export type DateRangePickerComponent<PublicWrapperProps> = (<TDate>(
props: BaseDateRangePickerProps<TDate> &
PublicWrapperProps<TWrapper> &
PublicWrapperProps &
AllSharedDateRangePickerProps<TDate> &
React.RefAttributes<HTMLDivElement>,
) => JSX.Element) & { propTypes: unknown };
Expand All @@ -56,13 +53,16 @@ export const useDateRangeValidation = makeValidationHook<
interface WithWrapperProps {
children: React.ReactNode;
DateInputProps: DateInputPropsLike;
wrapperProps: Omit<WrapperProps, 'DateInputProps'>;
wrapperProps: Omit<
PrivateWrapperProps & StaticWrapperProps & ResponsiveWrapperProps,
'DateInputProps'
>;
}

export function makeDateRangePicker<TWrapper extends SomeWrapper>(
export function makeDateRangePicker<PublicWrapperProps>(
name: string,
Wrapper: TWrapper,
): DateRangePickerComponent<TWrapper> {
Wrapper: React.JSXElementConstructor<PublicWrapperProps & PrivateWrapperProps>,
): DateRangePickerComponent<PublicWrapperProps> {
const KeyboardDateInputComponent = DateRangePickerInput as React.FC<DateInputPropsLike>;
const PureDateInputComponent = DateRangePickerInput as React.FC<DateInputPropsLike>;
function WrapperComponent(
Expand Down Expand Up @@ -123,7 +123,7 @@ export function makeDateRangePicker<TWrapper extends SomeWrapper>(
function RangePickerWithStateAndWrapper<TDate>(
inProps: BaseDateRangePickerProps<TDate> &
AllSharedDateRangePickerProps<TDate> &
PublicWrapperProps<TWrapper>,
PublicWrapperProps,
) {
const props = useThemeProps({ props: inProps, name });

Expand Down
94 changes: 15 additions & 79 deletions packages/material-ui-lab/src/DateTimePicker/DateTimePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
OverrideParsableDateProps,
} from '../internal/pickers/hooks/date-helpers-hooks';
import { ExportedDayPickerProps } from '../DayPicker/DayPicker';
import { SomeWrapper, PublicWrapperProps } from '../internal/pickers/wrappers/Wrapper';
import { WithViewsProps, AllSharedPickerProps } from '../internal/pickers/Picker/SharedPickerProps';
import { DateAndTimeValidationError, validateDateAndTime } from './date-time-utils';
import { makeValidationHook, ValidationProps } from '../internal/pickers/hooks/useValidation';
Expand All @@ -28,24 +27,18 @@ import { parsePickerInputValue } from '../internal/pickers/date-utils';
import { KeyboardDateInput } from '../internal/pickers/KeyboardDateInput';
import { PureDateInput } from '../internal/pickers/PureDateInput';
import { usePickerState, PickerStateValueManager } from '../internal/pickers/hooks/usePickerState';
import { BasePickerProps } from '../internal/pickers/typings/BasePicker';
import {
StaticWrapperProps,
DateInputPropsLike,
WrapperProps,
} from '../internal/pickers/wrappers/WrapperProps';

type AllPickerProps<T, TWrapper extends SomeWrapper = SomeWrapper> = T &
type AllResponsiveDateTimePickerProps = BaseDateTimePickerProps<unknown> &
AllSharedPickerProps &
PublicWrapperProps<TWrapper>;
ResponsiveWrapperProps;

const valueManager: PickerStateValueManager<unknown, unknown> = {
emptyValue: null,
parseInput: parsePickerInputValue,
areValuesEqual: (utils: MuiPickersAdapter, a: unknown, b: unknown) => utils.isEqual(a, b),
};

type SharedPickerProps<TDate, TWrapper extends SomeWrapper> = PublicWrapperProps<TWrapper> &
type SharedPickerProps<TDate, PublicWrapperProps> = PublicWrapperProps &
AllSharedPickerProps<ParsableDate<TDate>, TDate | null> &
React.RefAttributes<HTMLInputElement>;

Expand Down Expand Up @@ -150,68 +143,15 @@ export const dateTimePickerConfig = {
DefaultToolbarComponent: DateTimePickerToolbar,
};

export type DateTimePickerGenericComponent<TWrapper extends SomeWrapper> = (<TDate>(
props: BaseDateTimePickerProps<TDate> & SharedPickerProps<TDate, TWrapper>,
export type DateTimePickerGenericComponent<PublicWrapperProps> = (<TDate>(
props: BaseDateTimePickerProps<TDate> & SharedPickerProps<TDate, PublicWrapperProps>,
) => JSX.Element) & { propTypes?: unknown };

const { DefaultToolbarComponent } = dateTimePickerConfig;

interface DateTimePickerWrapperProps
extends Partial<BasePickerProps<any, any>>,
ResponsiveWrapperProps,
StaticWrapperProps {
children: React.ReactNode;
DateInputProps: DateInputPropsLike;
wrapperProps: Omit<WrapperProps, 'DateInputProps'>;
}

function DateTimePickerWrapper(props: DateTimePickerWrapperProps) {
const {
disableCloseOnSelect,
cancelText,
clearable,
clearText,
DateInputProps,
DialogProps,
displayStaticWrapperAs,
inputFormat,
okText,
onAccept,
onChange,
onClose,
onOpen,
open,
PopperProps,
todayText,
value,
wrapperProps,
...other
} = props;

const TypedWrapper = ResponsiveWrapper as SomeWrapper;

return (
<TypedWrapper
clearable={clearable}
clearText={clearText}
DialogProps={DialogProps}
PopperProps={PopperProps}
okText={okText}
todayText={todayText}
cancelText={cancelText}
DateInputProps={DateInputProps}
KeyboardDateInputComponent={KeyboardDateInput}
PureDateInputComponent={PureDateInput}
displayStaticWrapperAs={displayStaticWrapperAs}
{...wrapperProps}
{...other}
/>
);
}

export interface DateTimePickerProps<TDate = unknown>
extends BaseDateTimePickerProps<unknown>,
PublicWrapperProps<typeof ResponsiveWrapper>,
ResponsiveWrapperProps,
AllSharedPickerProps<ParsableDate<TDate>, TDate> {}

/**
Expand All @@ -228,17 +168,11 @@ const DateTimePicker = React.forwardRef(function DateTimePicker<TDate>(
inProps: DateTimePickerProps<TDate>,
ref: React.Ref<HTMLInputElement>,
) {
const allProps = useInterceptProps(inProps) as AllPickerProps<
BaseDateTimePickerProps<unknown>,
typeof ResponsiveWrapper
>;
const allProps = useInterceptProps(inProps) as AllResponsiveDateTimePickerProps;

// This is technically unsound if the type parameters appear in optional props.
// Optional props can be filled by `useThemeProps` with types that don't match the type parameters.
const props: AllPickerProps<
BaseDateTimePickerProps<unknown>,
typeof ResponsiveWrapper
> = useThemeProps({
const props: AllResponsiveDateTimePickerProps = useThemeProps({
props: allProps,
name: 'MuiDateTimePicker',
});
Expand All @@ -255,10 +189,12 @@ const DateTimePicker = React.forwardRef(function DateTimePicker<TDate>(
const AllDateInputProps = { ...inputProps, ...other, ref, validationError };

return (
<DateTimePickerWrapper
wrapperProps={wrapperProps}
DateInputProps={AllDateInputProps}
<ResponsiveWrapper
{...other}
{...wrapperProps}
DateInputProps={AllDateInputProps}
KeyboardDateInputComponent={KeyboardDateInput}
PureDateInputComponent={PureDateInput}
>
<Picker
{...pickerProps}
Expand All @@ -267,9 +203,9 @@ const DateTimePicker = React.forwardRef(function DateTimePicker<TDate>(
DateInputProps={AllDateInputProps}
{...other}
/>
</DateTimePickerWrapper>
</ResponsiveWrapper>
);
}) as DateTimePickerGenericComponent<typeof ResponsiveWrapper>;
}) as DateTimePickerGenericComponent<ResponsiveWrapperProps>;

DateTimePicker.propTypes /* remove-proptypes */ = {
// ----------------------------- Warning --------------------------------
Expand Down
Loading

0 comments on commit cf9db48

Please sign in to comment.