From 071c86a4fe2cef21a812d555b6fdb0598f69d6c0 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Fri, 6 Mar 2020 13:00:03 +0200 Subject: [PATCH 01/72] Make value for picker be a generic type --- docs/layout/components/navigationMap.ts | 1 + .../BasicDateRangePicker.example.jsx | 15 +++++ docs/pages/demo/daterangepicker/index.mdx | 22 +++++++ lib/src/DateRangePicker/DateRangePicker.tsx | 38 ++++++++++++ lib/src/LocalizationProvider.tsx | 2 +- lib/src/Picker/Picker.tsx | 19 +++--- lib/src/Picker/makePickerWithState.tsx | 43 ++++++++++--- lib/src/_helpers/date-utils.ts | 24 ++++++++ lib/src/_shared/PureDateInput.tsx | 6 +- lib/src/_shared/hooks/useOpenState.ts | 2 +- lib/src/_shared/hooks/usePickerState.ts | 61 +++++++------------ lib/src/constants/prop-types.ts | 2 +- lib/src/index.ts | 2 + lib/src/typings/BasePicker.tsx | 8 +-- lib/src/wrappers/Wrapper.tsx | 8 ++- 15 files changed, 185 insertions(+), 68 deletions(-) create mode 100644 docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx create mode 100644 docs/pages/demo/daterangepicker/index.mdx create mode 100644 lib/src/DateRangePicker/DateRangePicker.tsx diff --git a/docs/layout/components/navigationMap.ts b/docs/layout/components/navigationMap.ts index 3e4121d08..0142e347f 100644 --- a/docs/layout/components/navigationMap.ts +++ b/docs/layout/components/navigationMap.ts @@ -21,6 +21,7 @@ export const navItems = [ title: 'Components Demo', children: [ { title: 'Date Picker', href: '/demo/datepicker' }, + { title: 'Date Range Picker', href: '/demo/daterangepicker' }, { title: 'Time Picker', href: '/demo/timepicker' }, { title: 'Date & Time Picker', href: '/demo/datetime-picker' }, ], diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx new file mode 100644 index 000000000..5aa141b40 --- /dev/null +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -0,0 +1,15 @@ +import React, { useState } from 'react'; +import { DateRangePicker } from '@material-ui/pickers'; + +function BasicDateRangePicker() { + const [selectedDate, handleDateChange] = useState([new Date()]); + + return ( + handleDateChange(date)} + /> + ); +} + +export default BasicDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/index.mdx b/docs/pages/demo/daterangepicker/index.mdx new file mode 100644 index 000000000..f4c765c40 --- /dev/null +++ b/docs/pages/demo/daterangepicker/index.mdx @@ -0,0 +1,22 @@ +import Ad from '_shared/Ad'; +import Example from '_shared/Example'; +import PageMeta from '_shared/PageMeta'; +import LinkedComponents from '_shared/LinkedComponents'; + +import * as BasicDateRangePicker from './BasicDateRangePicker.example'; + + + + +## Date picker + +[Date pickers](https://material.io/components/pickers/) let users select a date, or a range of dates. They should be suitable for the context in which they appear. + + + +#### Basic usage + +Will be rendered to modal dialog on mobile and textfield with popover on desktop. + + + diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx new file mode 100644 index 000000000..79a2dd693 --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { ParsableDate } from '../constants/prop-types'; +import { MaterialUiPickersDate } from '../typings/date'; +import { DesktopWrapper } from '../wrappers/DesktopWrapper'; +import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; + +interface RangePickerProps { + value: [ParsableDate, ParsableDate]; + onChange: (value: [MaterialUiPickersDate, MaterialUiPickersDate] | null) => void; +} + +const RangePicker: React.FC = ({}) => { + return
makePickerWithStateAndWrapper
; +}; + +export const DateRangePicker = makePickerWithStateAndWrapper< + RangePickerProps, + [ParsableDate, ParsableDate], + [MaterialUiPickersDate, MaterialUiPickersDate] +>(DesktopWrapper, { + KeyboardDateInputComponent: RangePicker, + PureDateInputComponent: RangePicker, + PickerComponent: RangePicker, + useDefaultProps: () => ({ + inputFormat: 'mmm', + }), + DefaultToolbarComponent: () => null, + useParseInputValue: ({ value }) => { + const utils = useUtils(); + return value.map(unparsedValue => utils.date(unparsedValue)) as [ + MaterialUiPickersDate, + MaterialUiPickersDate + ]; + }, +}); + +; diff --git a/lib/src/LocalizationProvider.tsx b/lib/src/LocalizationProvider.tsx index fdf6c2ad9..0f0362090 100644 --- a/lib/src/LocalizationProvider.tsx +++ b/lib/src/LocalizationProvider.tsx @@ -28,8 +28,8 @@ export const LocalizationProvider: React.FC = ({ return ; }; +// @ts-ignore LocalizationProvider.propTypes = { - // @ts-ignore dateAdapter: PropTypes.func.isRequired, locale: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), children: PropTypes.oneOfType([ diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index 4a6d2ee35..cdd9fca72 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -5,6 +5,7 @@ import { useViews } from '../_shared/hooks/useViews'; import { makeStyles } from '@material-ui/core/styles'; import { DateTimePickerView } from '../DateTimePicker'; import { WithViewsProps } from './makePickerWithState'; +import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; @@ -37,27 +38,31 @@ export type ToolbarComponentProps = BaseDatePickerPr getMobileKeyboardInputViewButtonText?: () => string; }; -export interface PickerViewProps +export interface ExportedPickerProps extends Omit, WithViewsProps, BaseDatePickerProps, ExportedClockViewProps { toolbarTitle?: string; showToolbar?: boolean; - ToolbarComponent: React.ComponentType>; + ToolbarComponent?: React.ComponentType>; // TODO move out, cause it is DateTimePickerOnly hideTabs?: boolean; dateRangeIcon?: React.ReactNode; timeIcon?: React.ReactNode; } -interface PickerProps extends PickerViewProps { +export interface PickerProps< + T extends PickerView, + TInputValue = ParsableDate, + TDateValue = MaterialUiPickersDate +> extends ExportedPickerProps { isMobileKeyboardViewOpen: boolean; toggleMobileKeyboardView: () => void; - DateInputProps: DateInputProps; - date: MaterialUiPickersDate; + DateInputProps: DateInputProps; + date: TDateValue | null; onDateChange: ( - date: MaterialUiPickersDate, + date: TDateValue, currentVariant: WrapperVariant, isFinish?: boolean | symbol ) => void; @@ -97,7 +102,7 @@ export function Picker({ toolbarTitle, showToolbar, onDateChange, - ToolbarComponent, + ToolbarComponent = () => null, orientation, DateInputProps, isMobileKeyboardViewOpen, diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index c9fd186d4..ec8b8cf8f 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -1,13 +1,15 @@ import * as React from 'react'; -import { MakeOptional } from '../typings/helpers'; import { DateTimePickerView } from '../DateTimePicker'; +import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; +import { MaterialUiPickersDate } from '../typings/date'; import { usePickerState } from '../_shared/hooks/usePickerState'; -import { ExportedDateInputProps } from '../_shared/PureDateInput'; +import { useParsePickerInputValue } from '../_helpers/date-utils'; import { DateValidationProps } from '../_helpers/text-field-helper'; import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; -import { Picker, ToolbarComponentProps, PickerViewProps } from './Picker'; +import { ExportedDateInputProps, DateInputProps } from '../_shared/PureDateInput'; import { SomeWrapper, ExtendWrapper, OmitInnerWrapperProps } from '../wrappers/Wrapper'; +import { Picker, ToolbarComponentProps, PickerProps, ExportedPickerProps } from './Picker'; import { withDateAdapterProp, WithDateAdapterProps } from '../_shared/withDateAdapterProp'; export interface WithViewsProps { @@ -21,19 +23,34 @@ export interface WithViewsProps { export type WithDateInputProps = DateValidationProps & BasePickerProps & ExportedDateInputProps; -export interface MakePickerOptions { +export interface MakePickerOptions { useDefaultProps: (props: T) => Partial & { inputFormat?: string }; DefaultToolbarComponent: React.ComponentType; + PickerComponent?: React.ComponentType>; + useParseInputValue?: (props: BasePickerProps) => TDateValue; + PureDateInputComponent?: React.FC>; + KeyboardDateInputComponent?: React.FC>; } -type ExportedPickerProps = MakeOptional, 'ToolbarComponent'>; - export function makePickerWithStateAndWrapper< - T extends ExportedPickerProps & DateValidationProps & Pick, + T extends ExportedPickerProps & + DateValidationProps & + Pick, 'onChange' | 'value'>, + TInputValue = ParsableDate, + TDateValue = MaterialUiPickersDate, TWrapper extends SomeWrapper = any >( Wrapper: TWrapper, - { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions + { + // @ts-ignore Technically we cannot have a default value here, but left for consistency + PickerComponent = Picker, + // @ts-ignore + useParseInputValue = useParsePickerInputValue, + KeyboardDateInputComponent, + PureDateInputComponent, + useDefaultProps, + DefaultToolbarComponent, + }: MakePickerOptions ): React.FC> { function PickerWithState(props: T & Partial>) { const defaultProps = useDefaultProps(props); @@ -98,7 +115,11 @@ export function makePickerWithStateAndWrapper< ...restPropsForTextField } = allProps; - const { pickerProps, inputProps, wrapperProps } = usePickerState(allProps); + const { pickerProps, inputProps, wrapperProps } = usePickerState( + allProps, + useParseInputValue + ); + const WrapperComponent = Wrapper as SomeWrapper; return ( @@ -110,12 +131,14 @@ export function makePickerWithStateAndWrapper< todayLabel={todayLabel} cancelLabel={cancelLabel} DateInputProps={inputProps} + KeyboardDateInputComponent={KeyboardDateInputComponent} + PureDateInputComponent={PureDateInputComponent} wider={wider} showTabs={showTabs} {...wrapperProps} {...restPropsForTextField} > - , + { value, defaultHighlight }: BasePickerProps +) => { + const now = useNow(); + const date = utils.date(value || defaultHighlight || now); + + return date && utils.isValid(date) ? date : now; +}; + +export function useParsePickerInputValue(props: BasePickerProps): MaterialUiPickersDate | null { + const utils = useUtils(); + const date = useValueToDate(utils, props); + const inputFormat = props.inputFormat; + + if (!inputFormat) { + throw new Error('format prop is required'); + } + + return date; +} diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 5ae150644..f1b24d313 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -9,11 +9,11 @@ import { IconButtonProps } from '@material-ui/core/IconButton'; import { InputAdornmentProps } from '@material-ui/core/InputAdornment'; import { getDisplayDate, getTextFieldAriaText } from '../_helpers/text-field-helper'; -export interface DateInputProps +export interface DateInputProps extends ExtendMui { - rawValue: ParsableDate; + rawValue: TInputValue; inputFormat: string; - onChange: (date: MaterialUiPickersDate | null, keyboardInputValue?: string) => void; + onChange: (date: TDateValue | null, keyboardInputValue?: string) => void; openPicker: () => void; validationError?: React.ReactNode; /** Override input component */ diff --git a/lib/src/_shared/hooks/useOpenState.ts b/lib/src/_shared/hooks/useOpenState.ts index 5af192f80..c6fbc5e10 100644 --- a/lib/src/_shared/hooks/useOpenState.ts +++ b/lib/src/_shared/hooks/useOpenState.ts @@ -2,7 +2,7 @@ import { BasePickerProps } from '../../typings/BasePicker'; import { useCallback, useState, Dispatch, SetStateAction } from 'react'; -export function useOpenState({ open, onOpen, onClose }: BasePickerProps) { +export function useOpenState({ open, onOpen, onClose }: BasePickerProps) { let setIsOpenState: null | Dispatch> = null; if (open === undefined || open === null) { // The component is uncontrolled, so we need to give it its own state. diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 08a96a8ab..5e9d71fb4 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -1,42 +1,25 @@ import { useUtils, useNow } from './useUtils'; -import { IUtils } from '@date-io/core/IUtils'; import { useOpenState } from './useOpenState'; import { WrapperVariant } from '../../wrappers/Wrapper'; -import { MaterialUiPickersDate } from '../../typings/date'; import { BasePickerProps } from '../../typings/BasePicker'; import { validate } from '../../_helpers/text-field-helper'; import { useCallback, useDebugValue, useEffect, useMemo, useState } from 'react'; -const useValueToDate = ( - utils: IUtils, - { value, defaultHighlight }: BasePickerProps -) => { - const now = useNow(); - const date = utils.date(value || defaultHighlight || now); - - return date && utils.isValid(date) ? date : now; -}; +export const FORCE_FINISH_PICKER = Symbol('Force closing picker, used for accessibility '); -function useDateValues(props: BasePickerProps) { - const utils = useUtils(); - const date = useValueToDate(utils, props); - const inputFormat = props.inputFormat; +export function usePickerState( + props: BasePickerProps, + useParseInputValue: (props: BasePickerProps) => TOutput | null +) { + const { autoOk, inputFormat, disabled, readOnly, onAccept, onChange, onError, value } = props; if (!inputFormat) { - throw new Error('format prop is required'); + throw new Error("inputFormat prop is required") } - return { date, inputFormat }; -} - -export const FORCE_FINISH_PICKER = Symbol('Force closing picker, used for accessibility '); - -export function usePickerState(props: BasePickerProps) { - const { autoOk, disabled, readOnly, onAccept, onChange, onError, value } = props; - - const utils = useUtils(); const now = useNow(); - const { date, inputFormat } = useDateValues(props); + const utils = useUtils(); + const date = useParseInputValue(props); const [pickerDate, setPickerDate] = useState(date); // Mobile keyboard view is a special case. @@ -52,7 +35,7 @@ export function usePickerState(props: BasePickerProps) { }, [date, isMobileKeyboardViewOpen, isOpen, pickerDate, utils]); const acceptDate = useCallback( - (acceptedDate: MaterialUiPickersDate, needClosePicker: boolean) => { + (acceptedDate: TOutput | null, needClosePicker: boolean) => { onChange(acceptedDate); if (needClosePicker) { @@ -74,8 +57,9 @@ export function usePickerState(props: BasePickerProps) { onAccept: () => acceptDate(pickerDate, true), onDismiss: () => setIsOpen(false), onSetToday: () => { - setPickerDate(now); - acceptDate(now, Boolean(autoOk)); + // TODO FIX ME + setPickerDate(now as any); + acceptDate(now as any, Boolean(autoOk)); }, }), [acceptDate, autoOk, inputFormat, isOpen, now, pickerDate, setIsOpen] @@ -94,7 +78,7 @@ export function usePickerState(props: BasePickerProps) { setMobileKeyboardViewOpen(!isMobileKeyboardViewOpen); }, onDateChange: ( - newDate: MaterialUiPickersDate, + newDate: TOutput, currentVariant: WrapperVariant, isFinish: boolean | symbol = true ) => { @@ -117,22 +101,23 @@ export function usePickerState(props: BasePickerProps) { [acceptDate, autoOk, isMobileKeyboardViewOpen, pickerDate] ); - const validationError = validate(value, utils, props as any); - useEffect(() => { - if (onError) { - onError(validationError, value); - } - }, [onError, validationError, value]); + // TODO FIX ME + // const validationError = validate(value, utils, props as any); + // useEffect(() => { + // if (onError) { + // onError(validationError, value); + // } + // }, [onError, validationError, value]); const inputProps = useMemo( () => ({ onChange, inputFormat, rawValue: value, - validationError, + validationError: undefined, openPicker: () => !readOnly && !disabled && setIsOpen(true), }), - [disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] + [disabled, inputFormat, onChange, readOnly, setIsOpen, value] ); const pickerState = { pickerProps, inputProps, wrapperProps }; diff --git a/lib/src/constants/prop-types.ts b/lib/src/constants/prop-types.ts index 3925a446f..cba959efc 100644 --- a/lib/src/constants/prop-types.ts +++ b/lib/src/constants/prop-types.ts @@ -11,7 +11,7 @@ const date = PropTypes.oneOfType([ const datePickerView = PropTypes.oneOf(['year', 'month', 'day']); -export type ParsableDate = object | string | number | Date | null | undefined; +export type ParsableDate = string | number | Date | null | undefined; export const DomainPropTypes = { date, datePickerView }; diff --git a/lib/src/index.ts b/lib/src/index.ts index c801607c6..bcad47d84 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -6,6 +6,8 @@ export * from './TimePicker'; export * from './DateTimePicker'; +export * from './DateRangePicker/DateRangePicker'; + export { Calendar } from './views/Calendar/Calendar'; export * from './views/Calendar/CalendarView'; diff --git a/lib/src/typings/BasePicker.tsx b/lib/src/typings/BasePicker.tsx index ad95103f5..8ce751289 100644 --- a/lib/src/typings/BasePicker.tsx +++ b/lib/src/typings/BasePicker.tsx @@ -2,11 +2,11 @@ import { MaterialUiPickersDate } from './date'; import { ParsableDate } from '../constants/prop-types'; import { ToolbarComponentProps } from '../Picker/Picker'; -export interface BasePickerProps { +export interface BasePickerProps { /** Picker value */ - value: ParsableDate; + value: TInputValue; /** onChange callback @DateIOType */ - onChange: (date: MaterialUiPickersDate | null, keyboardInputValue?: string) => void; + onChange: (date: TDateValue | null, keyboardInputValue?: string) => void; /** * Auto accept date on selection * @default false @@ -21,7 +21,7 @@ export interface BasePickerProps { /** Date that will be initially highlighted if null was passed */ defaultHighlight?: ParsableDate; /** Callback fired when date is accepted @DateIOType */ - onAccept?: (date: MaterialUiPickersDate) => void; + onAccept?: (date: TDateValue | null) => void; /** Callback fired when new error should be displayed * (!! This is a side effect. Be careful if you want to rerender the component) @DateIOType */ diff --git a/lib/src/wrappers/Wrapper.tsx b/lib/src/wrappers/Wrapper.tsx index 14f9bd2fa..28a1c656e 100644 --- a/lib/src/wrappers/Wrapper.tsx +++ b/lib/src/wrappers/Wrapper.tsx @@ -4,16 +4,18 @@ import { MobileWrapper, MobileWrapperProps } from './MobileWrapper'; import { DesktopWrapper, DesktopWrapperProps } from './DesktopWrapper'; import { ResponsiveWrapper, ResponsiveWrapperProps } from './ResponsiveWrapper'; -export interface WrapperProps { +export interface WrapperProps> { open: boolean; onAccept: () => void; onDismiss: () => void; onClear: () => void; onSetToday: () => void; - DateInputProps: DateInputProps; + DateInputProps: TInputProps; + KeyboardDateInputComponent?: React.ComponentType; + PureDateInputComponent?: React.ComponentType; } -export type OmitInnerWrapperProps = Omit; +export type OmitInnerWrapperProps> = Omit>; export type SomeWrapper = | typeof ResponsiveWrapper From 6278df7728a0942a14008ce66cc4486541cbe9fc Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Fri, 6 Mar 2020 14:01:51 +0200 Subject: [PATCH 02/72] Spread new props from passing to the dom element --- lib/src/wrappers/DesktopWrapper.tsx | 4 +++- lib/src/wrappers/MobileWrapper.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/src/wrappers/DesktopWrapper.tsx b/lib/src/wrappers/DesktopWrapper.tsx index 1c73792ff..2388c65a9 100644 --- a/lib/src/wrappers/DesktopWrapper.tsx +++ b/lib/src/wrappers/DesktopWrapper.tsx @@ -46,6 +46,8 @@ export const DesktopWrapper: React.FC = ({ showTodayButton, clearable, DialogProps, + PureDateInputComponent, + KeyboardDateInputComponent = KeyboardDateInput, ...other }) => { const ref = React.useRef(); @@ -53,7 +55,7 @@ export const DesktopWrapper: React.FC = ({ return ( - + = ({ onDismiss, onSetToday, PopoverProps, + KeyboardDateInputComponent, + PureDateInputComponent = PureDateInput, ...other }) => { return ( - + Date: Wed, 11 Mar 2020 12:43:51 +0200 Subject: [PATCH 03/72] Split makePickerWith state hoc --- .../BasicDateRangePicker.example.jsx | 2 +- lib/.size-snapshot.json | 24 +-- lib/src/DatePicker/DatePicker.tsx | 3 +- lib/src/DateRangePicker/DateRangePicker.tsx | 82 +++++--- .../DateRangePicker/DateRangePickerInput.tsx | 20 ++ lib/src/DateTimePicker/DateTimePicker.tsx | 7 +- lib/src/Picker/Picker.tsx | 2 +- lib/src/Picker/WithViewsProps.tsx | 15 ++ lib/src/Picker/makePickerWithState.tsx | 188 +++--------------- lib/src/Picker/makePickerWithWrapper.tsx | 173 ++++++++++++++++ lib/src/TimePicker/TimePicker.tsx | 3 +- lib/src/_helpers/date-utils.ts | 28 +-- lib/src/_shared/hooks/usePickerState.ts | 14 +- 13 files changed, 330 insertions(+), 231 deletions(-) create mode 100644 lib/src/DateRangePicker/DateRangePickerInput.tsx create mode 100644 lib/src/Picker/WithViewsProps.tsx create mode 100644 lib/src/Picker/makePickerWithWrapper.tsx diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index 5aa141b40..46b5d7c5b 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { DateRangePicker } from '@material-ui/pickers'; function BasicDateRangePicker() { - const [selectedDate, handleDateChange] = useState([new Date()]); + const [selectedDate, handleDateChange] = useState([new Date(), null]); return ( void; +export type RangeInput = [ParsableDate, ParsableDate]; +export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; + +interface RangePickerProps extends BasePickerProps { + howManyCalendars: 2; } const RangePicker: React.FC = ({}) => { return
makePickerWithStateAndWrapper
; }; -export const DateRangePicker = makePickerWithStateAndWrapper< - RangePickerProps, - [ParsableDate, ParsableDate], - [MaterialUiPickersDate, MaterialUiPickersDate] ->(DesktopWrapper, { - KeyboardDateInputComponent: RangePicker, - PureDateInputComponent: RangePicker, - PickerComponent: RangePicker, - useDefaultProps: () => ({ - inputFormat: 'mmm', - }), - DefaultToolbarComponent: () => null, - useParseInputValue: ({ value }) => { - const utils = useUtils(); - return value.map(unparsedValue => utils.date(unparsedValue)) as [ - MaterialUiPickersDate, - MaterialUiPickersDate - ]; - }, -}); +export function parseRangeInputValue( + now: MaterialUiPickersDate, + utils: MuiPickersAdapter, + { value = [null, null], defaultHighlight }: BasePickerProps +) { + return value.map(date => + parsePickerInputValue(now, utils, { value: date, defaultHighlight }) + ); +} + +export function makeRangePicker(Wrapper: TWrapper) { + const PickerComponentWithWrapper = makePickerWithWrapper(Wrapper, { + PickerComponent: RangePicker, + DefaultToolbarComponent: () => null, + KeyboardDateInputComponent: DateRangePickerInput, + PureDateInputComponent: DateRangePickerInput, + }); + + function RangePickerWithStateAndWrapper( + allProps: RangePickerProps & Partial> + ) { + const { pickerProps, inputProps, wrapperProps } = usePickerState< + RangeInput, + DateRange + >(allProps, parseRangeInputValue); + + return ( + + ); + } + + RangePickerWithStateAndWrapper.defaultProps = { + inputFormat: 'MM' + } + + return RangePickerWithStateAndWrapper; +} + +export const DateRangePicker = makeRangePicker(DesktopWrapper); ; diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx new file mode 100644 index 000000000..c8b400f9c --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import KeyboardDateInput from '../_shared/KeyboardDateInput'; +import { TextField } from '@material-ui/core'; +import { DateInputProps } from '../_shared/PureDateInput'; +import { RangeInput, DateRange } from './DateRangePicker'; + +export const DateRangePickerInput: React.FC> = ({ + rawValue, + onChange, + ...other +}) => { + console.log(rawValue) + const [start, end] = rawValue; + return ( + <> + + + + ); +}; diff --git a/lib/src/DateTimePicker/DateTimePicker.tsx b/lib/src/DateTimePicker/DateTimePicker.tsx index 2049c9b67..66c91fed2 100644 --- a/lib/src/DateTimePicker/DateTimePicker.tsx +++ b/lib/src/DateTimePicker/DateTimePicker.tsx @@ -4,13 +4,10 @@ import { DateTimePickerToolbar } from './DateTimePickerToolbar'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; +import { WithViewsProps, WithDateInputProps } from '../Picker/WithViewsProps'; +import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { InlineWrapper, ModalWrapper, StaticWrapper } from '../wrappers/Wrapper'; import { dateTimePickerDefaultProps, ParsableDate } from '../constants/prop-types'; -import { - makePickerWithStateAndWrapper, - WithDateInputProps, - WithViewsProps, -} from '../Picker/makePickerWithState'; export type DateTimePickerView = 'year' | 'date' | 'month' | 'hours' | 'minutes' | 'seconds'; diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index cdd9fca72..a5f4f0663 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import clsx from 'clsx'; +import { WithViewsProps } from "./WithViewsProps"; import { WrapperVariant } from '../wrappers/Wrapper'; import { useViews } from '../_shared/hooks/useViews'; import { makeStyles } from '@material-ui/core/styles'; import { DateTimePickerView } from '../DateTimePicker'; -import { WithViewsProps } from './makePickerWithState'; import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; diff --git a/lib/src/Picker/WithViewsProps.tsx b/lib/src/Picker/WithViewsProps.tsx new file mode 100644 index 000000000..205b41287 --- /dev/null +++ b/lib/src/Picker/WithViewsProps.tsx @@ -0,0 +1,15 @@ +import { DateTimePickerView } from '../DateTimePicker'; +import { BasePickerProps } from '../typings/BasePicker'; +import { ExportedDateInputProps } from '../_shared/PureDateInput'; +import { DateValidationProps } from '../_helpers/text-field-helper'; + +export interface WithViewsProps { + /** + * Array of views to show + */ + views?: T[]; + /** First view to show */ + openTo?: T; +} + +export type WithDateInputProps = DateValidationProps & BasePickerProps & ExportedDateInputProps; diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index ec8b8cf8f..315912194 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -1,187 +1,57 @@ import * as React from 'react'; -import { DateTimePickerView } from '../DateTimePicker'; +import KeyboardDateInput from '../_shared/KeyboardDateInput'; import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; +import { PureDateInput } from '../_shared/PureDateInput'; +import { parsePickerInputValue } from '../_helpers/date-utils'; +import { makePickerWithWrapper } from './makePickerWithWrapper'; import { usePickerState } from '../_shared/hooks/usePickerState'; -import { useParsePickerInputValue } from '../_helpers/date-utils'; import { DateValidationProps } from '../_helpers/text-field-helper'; +import { WithDateAdapterProps } from '../_shared/withDateAdapterProp'; import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; -import { ExportedDateInputProps, DateInputProps } from '../_shared/PureDateInput'; -import { SomeWrapper, ExtendWrapper, OmitInnerWrapperProps } from '../wrappers/Wrapper'; -import { Picker, ToolbarComponentProps, PickerProps, ExportedPickerProps } from './Picker'; -import { withDateAdapterProp, WithDateAdapterProps } from '../_shared/withDateAdapterProp'; +import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; +import { SomeWrapper, OmitInnerWrapperProps, ExtendWrapper } from '../wrappers/Wrapper'; -export interface WithViewsProps { - /** - * Array of views to show - */ - views?: T[]; - /** First view to show */ - openTo?: T; -} - -export type WithDateInputProps = DateValidationProps & BasePickerProps & ExportedDateInputProps; - -export interface MakePickerOptions { - useDefaultProps: (props: T) => Partial & { inputFormat?: string }; +export interface MakePickerOptions { + useDefaultProps: (props: T) => Partial & { inputFormat: string }; DefaultToolbarComponent: React.ComponentType; - PickerComponent?: React.ComponentType>; - useParseInputValue?: (props: BasePickerProps) => TDateValue; - PureDateInputComponent?: React.FC>; - KeyboardDateInputComponent?: React.FC>; } export function makePickerWithStateAndWrapper< T extends ExportedPickerProps & DateValidationProps & - Pick, 'onChange' | 'value'>, - TInputValue = ParsableDate, - TDateValue = MaterialUiPickersDate, + Pick, 'onChange' | 'value'>, TWrapper extends SomeWrapper = any >( Wrapper: TWrapper, - { - // @ts-ignore Technically we cannot have a default value here, but left for consistency - PickerComponent = Picker, - // @ts-ignore - useParseInputValue = useParsePickerInputValue, - KeyboardDateInputComponent, - PureDateInputComponent, - useDefaultProps, - DefaultToolbarComponent, - }: MakePickerOptions + { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions ): React.FC> { + const PickerComponentWithWrapper = makePickerWithWrapper(Wrapper, { + PickerComponent: Picker, + DefaultToolbarComponent: DefaultToolbarComponent, + KeyboardDateInputComponent: KeyboardDateInput, + PureDateInputComponent: PureDateInput, + }); + function PickerWithState(props: T & Partial>) { const defaultProps = useDefaultProps(props); const allProps = { ...defaultProps, ...props }; - const { - allowKeyboardControl, - ampm, - ampmInClock, - autoOk, - dateRangeIcon, - disableFuture, - disablePast, - showToolbar, - inputFormat, - hideTabs, - defaultHighlight, - leftArrowButtonProps, - leftArrowIcon, - loadingIndicator, - maxDate, - minDate, - minutesStep, - onAccept, - onChange, - onClose, - onMonthChange, - onOpen, - onYearChange, - openTo, - orientation, - renderDay, - rightArrowButtonProps, - rightArrowIcon, - shouldDisableDate, - shouldDisableTime, - strictCompareDates, - timeIcon, - toolbarFormat, - ToolbarComponent = DefaultToolbarComponent, - value, - views, - toolbarTitle, - invalidDateMessage, - minDateMessage, - wider, - showTabs, - maxDateMessage, - disableTimeValidationIgnoreDatePart, - showDaysOutsideCurrentMonth, - disableHighlightToday, - // WrapperProps - clearable, - clearLabel, - DialogProps, - PopoverProps, - okLabel, - cancelLabel, - todayLabel, - minTime, - maxTime, - ...restPropsForTextField - } = allProps; - - const { pickerProps, inputProps, wrapperProps } = usePickerState( - allProps, - useParseInputValue - ); - - const WrapperComponent = Wrapper as SomeWrapper; + const { pickerProps, inputProps, wrapperProps } = usePickerState< + ParsableDate, + MaterialUiPickersDate + >(allProps, parsePickerInputValue); return ( - - - + ); } - // @ts-ignore (why prop-types validation is appearing here?) - return withDateAdapterProp(PickerWithState); + return PickerWithState; } diff --git a/lib/src/Picker/makePickerWithWrapper.tsx b/lib/src/Picker/makePickerWithWrapper.tsx new file mode 100644 index 000000000..f67717983 --- /dev/null +++ b/lib/src/Picker/makePickerWithWrapper.tsx @@ -0,0 +1,173 @@ +import React from 'react'; +import { BasePickerProps } from '../typings/BasePicker'; +import { DateInputProps } from '../_shared/PureDateInput'; +import { DateValidationProps } from '../_helpers/text-field-helper'; +import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; +import { ToolbarComponentProps, PickerProps, ExportedPickerProps } from './Picker'; +import { WithDateAdapterProps, withDateAdapterProp } from '../_shared/withDateAdapterProp'; +import { + OmitInnerWrapperProps, + SomeWrapper, + ExtendWrapper, + WrapperProps, +} from '../wrappers/Wrapper'; + +interface MakePickerOptions { + DefaultToolbarComponent: React.ComponentType; + PickerComponent: React.ComponentType>; + PureDateInputComponent?: React.FC>; + KeyboardDateInputComponent?: React.FC>; +} + +type AllPickerProps = ExportedPickerProps & + DateValidationProps & + Pick, 'onChange' | 'value'>; + +interface WithWrapperProps { + inputProps: DateInputProps; + wrapperProps: Omit; + pickerProps: Omit, 'DateInputProps'>; +} + +export function makePickerWithWrapper< + TInputValue, + TDateValue, + TProps extends AllPickerProps & + WithWrapperProps, + TWrapper extends SomeWrapper = any +>( + Wrapper: TWrapper, + { + PickerComponent, + KeyboardDateInputComponent, + PureDateInputComponent, + DefaultToolbarComponent, + }: MakePickerOptions +): React.FC> { + function PickerWithState(props: TProps & Partial>) { + const { + allowKeyboardControl, + ampm, + ampmInClock, + autoOk, + dateRangeIcon, + disableFuture, + disablePast, + showToolbar, + inputFormat, + hideTabs, + defaultHighlight, + leftArrowButtonProps, + leftArrowIcon, + loadingIndicator, + maxDate, + minDate, + minutesStep, + onAccept, + onChange, + onClose, + onMonthChange, + onOpen, + onYearChange, + openTo, + orientation, + renderDay, + rightArrowButtonProps, + rightArrowIcon, + shouldDisableDate, + shouldDisableTime, + strictCompareDates, + timeIcon, + toolbarFormat, + ToolbarComponent = DefaultToolbarComponent, + value, + views, + toolbarTitle, + invalidDateMessage, + minDateMessage, + wider, + showTabs, + maxDateMessage, + disableTimeValidationIgnoreDatePart, + showDaysOutsideCurrentMonth, + disableHighlightToday, + // WrapperProps + clearable, + clearLabel, + DialogProps, + PopoverProps, + okLabel, + cancelLabel, + todayLabel, + minTime, + maxTime, + inputProps, + wrapperProps, + pickerProps, + ...restPropsForTextField + } = props; + + const WrapperComponent = Wrapper as SomeWrapper; + + return ( + + + + ); + } + + return withDateAdapterProp(PickerWithState); +} diff --git a/lib/src/TimePicker/TimePicker.tsx b/lib/src/TimePicker/TimePicker.tsx index 08e27f0f6..177324313 100644 --- a/lib/src/TimePicker/TimePicker.tsx +++ b/lib/src/TimePicker/TimePicker.tsx @@ -5,11 +5,10 @@ import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; import { useUtils, MuiPickersAdapter } from '../_shared/hooks/useUtils'; +import { WithViewsProps, WithDateInputProps } from "../Picker/WithViewsProps"; import { timePickerDefaultProps, ParsableDate } from '../constants/prop-types'; import { ModalWrapper, InlineWrapper, StaticWrapper } from '../wrappers/Wrapper'; import { - WithDateInputProps, - WithViewsProps, makePickerWithStateAndWrapper, } from '../Picker/makePickerWithState'; diff --git a/lib/src/_helpers/date-utils.ts b/lib/src/_helpers/date-utils.ts index c499f7640..1500a51b4 100644 --- a/lib/src/_helpers/date-utils.ts +++ b/lib/src/_helpers/date-utils.ts @@ -3,7 +3,7 @@ import { IUtils } from '@date-io/core/IUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; import { DatePickerView } from '../DatePicker/DatePicker'; -import { useNow, useUtils } from '../_shared/hooks/useUtils'; +import { useNow, useUtils, MuiPickersAdapter } from '../_shared/hooks/useUtils'; interface FindClosestDateParams { date: MaterialUiPickersDate; @@ -97,24 +97,12 @@ export const getFormatByViews = ( return utils.formats.keyboardDate; }; -const useValueToDate = ( - utils: IUtils, - { value, defaultHighlight }: BasePickerProps -) => { - const now = useNow(); - const date = utils.date(value || defaultHighlight || now); - - return date && utils.isValid(date) ? date : now; -}; - -export function useParsePickerInputValue(props: BasePickerProps): MaterialUiPickersDate | null { - const utils = useUtils(); - const date = useValueToDate(utils, props); - const inputFormat = props.inputFormat; - - if (!inputFormat) { - throw new Error('format prop is required'); - } +export function parsePickerInputValue( + now: MaterialUiPickersDate, + utils: MuiPickersAdapter, + { value, defaultHighlight }: Pick +): MaterialUiPickersDate | null { + const parsedValue = utils.date(value || defaultHighlight || now); - return date; + return parsedValue && utils.isValid(parsedValue) ? parsedValue : now; } diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 5e9d71fb4..825d0ec79 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -1,25 +1,31 @@ -import { useUtils, useNow } from './useUtils'; import { useOpenState } from './useOpenState'; import { WrapperVariant } from '../../wrappers/Wrapper'; import { BasePickerProps } from '../../typings/BasePicker'; +import { MaterialUiPickersDate } from '../../typings/date'; import { validate } from '../../_helpers/text-field-helper'; +import { useUtils, useNow, MuiPickersAdapter } from './useUtils'; import { useCallback, useDebugValue, useEffect, useMemo, useState } from 'react'; export const FORCE_FINISH_PICKER = Symbol('Force closing picker, used for accessibility '); export function usePickerState( props: BasePickerProps, - useParseInputValue: (props: BasePickerProps) => TOutput | null + parseInputValue: ( + now: MaterialUiPickersDate, + utils: MuiPickersAdapter, + props: BasePickerProps + ) => TOutput | null ) { + console.log('updating state'); const { autoOk, inputFormat, disabled, readOnly, onAccept, onChange, onError, value } = props; if (!inputFormat) { - throw new Error("inputFormat prop is required") + throw new Error('inputFormat prop is required'); } const now = useNow(); const utils = useUtils(); - const date = useParseInputValue(props); + const date = parseInputValue(now, utils, props); const [pickerDate, setPickerDate] = useState(date); // Mobile keyboard view is a special case. From c3e90c9c62fbda9e8076af4c1a35b446a1ea4f53 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 14:15:37 +0200 Subject: [PATCH 04/72] Better type inference for new makePickerWithWrapper --- lib/src/DateRangePicker/DateRangePicker.tsx | 42 ++++++++----------- .../DateRangePickerCalendar.tsx | 13 ++++++ lib/src/DateRangePicker/RangeTypes.ts | 5 +++ lib/src/Picker/Picker.tsx | 7 ++-- lib/src/Picker/makePickerWithState.tsx | 12 +++--- lib/src/Picker/makePickerWithWrapper.tsx | 21 +++++++--- lib/src/TimePicker/TimePicker.tsx | 6 +-- 7 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 lib/src/DateRangePicker/DateRangePickerCalendar.tsx create mode 100644 lib/src/DateRangePicker/RangeTypes.ts diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 9804d438a..920d27d78 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { ParsableDate } from '../constants/prop-types'; +import { DateRange, RangeInput } from './RangeTypes'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; import { DesktopWrapper } from '../wrappers/DesktopWrapper'; @@ -10,17 +10,7 @@ import { usePickerState } from '../_shared/hooks/usePickerState'; import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; import { makePickerWithWrapper } from '../Picker/makePickerWithWrapper'; import { SomeWrapper, OmitInnerWrapperProps } from '../wrappers/Wrapper'; - -export type RangeInput = [ParsableDate, ParsableDate]; -export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; - -interface RangePickerProps extends BasePickerProps { - howManyCalendars: 2; -} - -const RangePicker: React.FC = ({}) => { - return
makePickerWithStateAndWrapper
; -}; +import { DateRangePickerCalendar, DateRangePickerCalendarProps } from './DateRangePickerCalendar'; export function parseRangeInputValue( now: MaterialUiPickersDate, @@ -29,24 +19,30 @@ export function parseRangeInputValue( ) { return value.map(date => parsePickerInputValue(now, utils, { value: date, defaultHighlight }) - ); + ) as DateRange; } export function makeRangePicker(Wrapper: TWrapper) { - const PickerComponentWithWrapper = makePickerWithWrapper(Wrapper, { - PickerComponent: RangePicker, + const PickerComponentWithWrapper = makePickerWithWrapper< + RangeInput, + DateRange, + DateRangePickerCalendarProps & Pick, 'onChange' | 'value'> + >(Wrapper, { + PickerComponent: DateRangePickerCalendar, DefaultToolbarComponent: () => null, KeyboardDateInputComponent: DateRangePickerInput, PureDateInputComponent: DateRangePickerInput, }); function RangePickerWithStateAndWrapper( - allProps: RangePickerProps & Partial> + allProps: DateRangePickerCalendarProps & + Pick, 'onChange' | 'value'> & + Partial> ) { - const { pickerProps, inputProps, wrapperProps } = usePickerState< - RangeInput, - DateRange - >(allProps, parseRangeInputValue); + const { pickerProps, inputProps, wrapperProps } = usePickerState( + allProps, + parseRangeInputValue + ); return ( (Wrapper: TWrapper) } RangePickerWithStateAndWrapper.defaultProps = { - inputFormat: 'MM' - } + inputFormat: 'MM', + }; return RangePickerWithStateAndWrapper; } export const DateRangePicker = makeRangePicker(DesktopWrapper); - -; diff --git a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx new file mode 100644 index 000000000..d1b255296 --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import { RangeInput, DateRange } from './RangeTypes'; +import { ExportedPickerProps } from '../Picker/Picker'; + +export interface DateRangePickerCalendarProps { + calendars?: 1 | 2; +} + + +export const DateRangePickerCalendar: React.FC> = ({}) => { + return <>ewfojweiof; +}; diff --git a/lib/src/DateRangePicker/RangeTypes.ts b/lib/src/DateRangePicker/RangeTypes.ts new file mode 100644 index 000000000..ccd1c77ff --- /dev/null +++ b/lib/src/DateRangePicker/RangeTypes.ts @@ -0,0 +1,5 @@ +import { ParsableDate } from "../constants/prop-types"; +import { MaterialUiPickersDate } from "../typings/date"; + +export type RangeInput = [ParsableDate, ParsableDate]; +export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index a5f4f0663..a9ffc2283 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import clsx from 'clsx'; -import { WithViewsProps } from "./WithViewsProps"; +import { WithViewsProps } from './WithViewsProps'; import { WrapperVariant } from '../wrappers/Wrapper'; import { useViews } from '../_shared/hooks/useViews'; import { makeStyles } from '@material-ui/core/styles'; @@ -38,9 +38,8 @@ export type ToolbarComponentProps = BaseDatePickerPr getMobileKeyboardInputViewButtonText?: () => string; }; -export interface ExportedPickerProps +export interface ExportedPickerProps extends Omit, - WithViewsProps, BaseDatePickerProps, ExportedClockViewProps { toolbarTitle?: string; @@ -56,7 +55,7 @@ export interface PickerProps< T extends PickerView, TInputValue = ParsableDate, TDateValue = MaterialUiPickersDate -> extends ExportedPickerProps { +> extends ExportedPickerProps, WithViewsProps { isMobileKeyboardViewOpen: boolean; toggleMobileKeyboardView: () => void; DateInputProps: DateInputProps; diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 315912194..580c45335 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -1,17 +1,16 @@ import * as React from 'react'; -import KeyboardDateInput from '../_shared/KeyboardDateInput'; import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; import { PureDateInput } from '../_shared/PureDateInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { makePickerWithWrapper } from './makePickerWithWrapper'; +import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; +import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { DateValidationProps } from '../_helpers/text-field-helper'; import { WithDateAdapterProps } from '../_shared/withDateAdapterProp'; -import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; -import { SomeWrapper, OmitInnerWrapperProps, ExtendWrapper } from '../wrappers/Wrapper'; export interface MakePickerOptions { useDefaultProps: (props: T) => Partial & { inputFormat: string }; @@ -19,14 +18,14 @@ export interface MakePickerOptions { } export function makePickerWithStateAndWrapper< - T extends ExportedPickerProps & + T extends ExportedPickerProps & DateValidationProps & Pick, 'onChange' | 'value'>, TWrapper extends SomeWrapper = any >( Wrapper: TWrapper, { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions -): React.FC> { +) { const PickerComponentWithWrapper = makePickerWithWrapper(Wrapper, { PickerComponent: Picker, DefaultToolbarComponent: DefaultToolbarComponent, @@ -34,7 +33,7 @@ export function makePickerWithStateAndWrapper< PureDateInputComponent: PureDateInput, }); - function PickerWithState(props: T & Partial>) { + function PickerWithState(props: T & WithDateAdapterProps & ExtendWrapper) { const defaultProps = useDefaultProps(props); const allProps = { ...defaultProps, ...props }; @@ -44,6 +43,7 @@ export function makePickerWithStateAndWrapper< >(allProps, parsePickerInputValue); return ( + // @ts-ignore { KeyboardDateInputComponent?: React.FC>; } -type AllPickerProps = ExportedPickerProps & +type AllPickerProps = ExportedPickerProps & DateValidationProps & Pick, 'onChange' | 'value'>; interface WithWrapperProps { - inputProps: DateInputProps; + inputProps: DateInputProps; wrapperProps: Omit; pickerProps: Omit, 'DateInputProps'>; } @@ -32,8 +32,7 @@ interface WithWrapperProps { export function makePickerWithWrapper< TInputValue, TDateValue, - TProps extends AllPickerProps & - WithWrapperProps, + TProps extends AllPickerProps, TWrapper extends SomeWrapper = any >( Wrapper: TWrapper, @@ -43,8 +42,18 @@ export function makePickerWithWrapper< PureDateInputComponent, DefaultToolbarComponent, }: MakePickerOptions -): React.FC> { - function PickerWithState(props: TProps & Partial>) { +): React.FC< + TProps & + WithWrapperProps & + WithDateAdapterProps & + ExtendWrapper +> { + function PickerWithState( + props: TProps & + WithDateAdapterProps & + WithWrapperProps & + Partial> + ) { const { allowKeyboardControl, ampm, diff --git a/lib/src/TimePicker/TimePicker.tsx b/lib/src/TimePicker/TimePicker.tsx index 177324313..d7563b078 100644 --- a/lib/src/TimePicker/TimePicker.tsx +++ b/lib/src/TimePicker/TimePicker.tsx @@ -5,12 +5,10 @@ import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; import { useUtils, MuiPickersAdapter } from '../_shared/hooks/useUtils'; -import { WithViewsProps, WithDateInputProps } from "../Picker/WithViewsProps"; +import { WithViewsProps, WithDateInputProps } from '../Picker/WithViewsProps'; +import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { timePickerDefaultProps, ParsableDate } from '../constants/prop-types'; import { ModalWrapper, InlineWrapper, StaticWrapper } from '../wrappers/Wrapper'; -import { - makePickerWithStateAndWrapper, -} from '../Picker/makePickerWithState'; export interface TimePickerProps extends ExportedClockViewProps, From 09e701d15ac61c2d703f5cff067fb2c9d814285f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 18:24:47 +0200 Subject: [PATCH 05/72] Refactor and opimize shared prop types inference for pickers --- lib/src/DatePicker/DatePicker.tsx | 30 +-- lib/src/DateRangePicker/DateRangePicker.tsx | 21 +- .../DateRangePickerCalendar.tsx | 4 +- lib/src/DateTimePicker/DateTimePicker.tsx | 19 +- lib/src/Picker/Picker.tsx | 64 +++--- lib/src/Picker/WithViewsProps.tsx | 4 +- lib/src/Picker/makePickerWithState.tsx | 116 ++++++++--- lib/src/Picker/makePickerWithWrapper.tsx | 182 ------------------ lib/src/Picker/makeWrapperComponent.tsx | 88 +++++++++ lib/src/TimePicker/TimePicker.tsx | 9 +- lib/src/_helpers/text-field-helper.ts | 9 +- lib/src/_shared/PickerToolbar.tsx | 2 +- lib/src/_shared/hooks/useViews.tsx | 6 +- lib/src/typings/BasePicker.tsx | 14 +- lib/src/views/Calendar/CalendarView.tsx | 2 + 15 files changed, 266 insertions(+), 304 deletions(-) delete mode 100644 lib/src/Picker/makePickerWithWrapper.tsx create mode 100644 lib/src/Picker/makeWrapperComponent.tsx diff --git a/lib/src/DatePicker/DatePicker.tsx b/lib/src/DatePicker/DatePicker.tsx index 5ceeeec34..5c19754de 100644 --- a/lib/src/DatePicker/DatePicker.tsx +++ b/lib/src/DatePicker/DatePicker.tsx @@ -1,32 +1,22 @@ import { useUtils } from '../_shared/hooks/useUtils'; -import { MaterialUiPickersDate } from '../typings/date'; import { DatePickerToolbar } from './DatePickerToolbar'; import { getFormatByViews } from '../_helpers/date-utils'; +import { WithViewsProps } from '../Picker/WithViewsProps'; import { datePickerDefaultProps } from '../constants/prop-types'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; -import { WithViewsProps, WithDateInputProps } from "../Picker/WithViewsProps"; +import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { ModalWrapper, InlineWrapper, StaticWrapper } from '../wrappers/Wrapper'; -import { - makePickerWithStateAndWrapper, -} from '../Picker/makePickerWithState'; export type DatePickerView = 'year' | 'date' | 'month'; -export interface BaseDatePickerProps extends ExportedCalendarViewProps { - /** Callback firing on year change @DateIOType */ - onYearChange?: (date: MaterialUiPickersDate) => void; - /** Date format, that is displaying in toolbar */ - toolbarFormat?: string; -} - -export type DatePickerProps = BaseDatePickerProps & - WithDateInputProps & - WithViewsProps<'year' | 'date' | 'month'>; +export interface BaseDatePickerProps + extends WithViewsProps<'year' | 'date' | 'month'>, + ExportedCalendarViewProps {} const datePickerConfig = { DefaultToolbarComponent: DatePickerToolbar, - useDefaultProps: ({ openTo = 'date', views = ['year', 'date'] }: DatePickerProps) => { + useDefaultProps: ({ openTo = 'date', views = ['year', 'date'] }: BaseDatePickerProps) => { const utils = useUtils(); return { @@ -39,22 +29,22 @@ const datePickerConfig = { }, }; -export const DatePicker = makePickerWithStateAndWrapper( +export const DatePicker = makePickerWithStateAndWrapper( ResponsiveWrapper, datePickerConfig ); -export const MobileDatePicker = makePickerWithStateAndWrapper( +export const MobileDatePicker = makePickerWithStateAndWrapper( ModalWrapper, datePickerConfig ); -export const DesktopDatePicker = makePickerWithStateAndWrapper( +export const DesktopDatePicker = makePickerWithStateAndWrapper( InlineWrapper, datePickerConfig ); -export const StaticDatePicker = makePickerWithStateAndWrapper( +export const StaticDatePicker = makePickerWithStateAndWrapper( StaticWrapper, datePickerConfig ); diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 920d27d78..2206e30e7 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -7,8 +7,8 @@ import { DateRangePickerInput } from './DateRangePickerInput'; import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; +import { makeWrapperComponent } from '../Picker/makeWrapperComponent'; import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; -import { makePickerWithWrapper } from '../Picker/makePickerWithWrapper'; import { SomeWrapper, OmitInnerWrapperProps } from '../wrappers/Wrapper'; import { DateRangePickerCalendar, DateRangePickerCalendarProps } from './DateRangePickerCalendar'; @@ -23,13 +23,7 @@ export function parseRangeInputValue( } export function makeRangePicker(Wrapper: TWrapper) { - const PickerComponentWithWrapper = makePickerWithWrapper< - RangeInput, - DateRange, - DateRangePickerCalendarProps & Pick, 'onChange' | 'value'> - >(Wrapper, { - PickerComponent: DateRangePickerCalendar, - DefaultToolbarComponent: () => null, + const PickerComponentWithWrapper = makeWrapperComponent(Wrapper, { KeyboardDateInputComponent: DateRangePickerInput, PureDateInputComponent: DateRangePickerInput, }); @@ -44,13 +38,12 @@ export function makeRangePicker(Wrapper: TWrapper) parseRangeInputValue ); + const { calendars, ...other } = allProps; + return ( - + + + ); } diff --git a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx index d1b255296..cbd14a444 100644 --- a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx +++ b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx @@ -6,8 +6,6 @@ export interface DateRangePickerCalendarProps { calendars?: 1 | 2; } - -export const DateRangePickerCalendar: React.FC> = ({}) => { +export const DateRangePickerCalendar: React.FC = ({}) => { return <>ewfojweiof; }; diff --git a/lib/src/DateTimePicker/DateTimePicker.tsx b/lib/src/DateTimePicker/DateTimePicker.tsx index 66c91fed2..98c9baa67 100644 --- a/lib/src/DateTimePicker/DateTimePicker.tsx +++ b/lib/src/DateTimePicker/DateTimePicker.tsx @@ -1,19 +1,20 @@ import { useUtils } from '../_shared/hooks/useUtils'; -import { BaseDatePickerProps } from '../DatePicker/DatePicker'; +import { WithViewsProps } from '../Picker/WithViewsProps'; import { DateTimePickerToolbar } from './DateTimePickerToolbar'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; -import { WithViewsProps, WithDateInputProps } from '../Picker/WithViewsProps'; -import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; +import { ExportedCalendarProps } from '../views/Calendar/Calendar'; import { InlineWrapper, ModalWrapper, StaticWrapper } from '../wrappers/Wrapper'; import { dateTimePickerDefaultProps, ParsableDate } from '../constants/prop-types'; +import { makePickerWithStateAndWrapper, AllSharedPickerProps } from '../Picker/makePickerWithState'; export type DateTimePickerView = 'year' | 'date' | 'month' | 'hours' | 'minutes' | 'seconds'; -export type BaseDateTimePickerProps = ExportedClockViewProps & BaseDatePickerProps; - -export interface DateTimePickerViewsProps extends BaseDateTimePickerProps { +export interface DateTimePickerProps + extends WithViewsProps<'year' | 'date' | 'month' | 'hours' | 'minutes'>, + ExportedClockViewProps, + ExportedCalendarProps { /** To show tabs */ hideTabs?: boolean; /** Date tab icon */ @@ -28,10 +29,6 @@ export interface DateTimePickerViewsProps extends BaseDateTimePickerProps { toolbarFormat?: string; } -export type DateTimePickerProps = WithDateInputProps & - DateTimePickerViewsProps & - WithViewsProps<'year' | 'date' | 'month' | 'hours' | 'minutes'>; - function useDefaultProps({ ampm, mask, @@ -41,7 +38,7 @@ function useDefaultProps({ orientation = 'portrait', openTo = 'date', views = ['year', 'date', 'hours', 'minutes'], -}: DateTimePickerProps) { +}: DateTimePickerProps & AllSharedPickerProps) { const utils = useUtils(); const willUseAmPm = ampm ?? utils.is12HourCycleInCurrentLocale(); diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index a9ffc2283..229494d3c 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import clsx from 'clsx'; -import { WithViewsProps } from './WithViewsProps'; import { WrapperVariant } from '../wrappers/Wrapper'; import { useViews } from '../_shared/hooks/useViews'; import { makeStyles } from '@material-ui/core/styles'; @@ -9,42 +8,42 @@ import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; -import { CalendarView } from '../views/Calendar/CalendarView'; +import { DatePickerView } from '../DatePicker/DatePicker'; +import { WithViewsProps, AnyPickerView } from './WithViewsProps'; import { useIsLandscape } from '../_shared/hooks/useIsLandscape'; import { DIALOG_WIDTH, VIEW_HEIGHT } from '../constants/dimensions'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; import { ClockView, ExportedClockViewProps } from '../views/Clock/ClockView'; -import { BaseDatePickerProps, DatePickerView } from '../DatePicker/DatePicker'; +import { CalendarView, ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; -export type PickerView = DateTimePickerView; +type CalendarAndClockProps = ExportedCalendarViewProps & ExportedClockViewProps; -export type ToolbarComponentProps = BaseDatePickerProps & - ExportedClockViewProps & { - views: T[]; - openView: T; - date: MaterialUiPickersDate; - setOpenView: (view: T) => void; - onChange: (date: MaterialUiPickersDate, isFinish?: boolean) => void; - toolbarTitle?: string; - // TODO move out, cause it is DateTimePickerOnly - hideTabs?: boolean; - dateRangeIcon?: React.ReactNode; - timeIcon?: React.ReactNode; - isLandscape: boolean; - ampmInClock?: boolean; - isMobileKeyboardViewOpen: boolean; - toggleMobileKeyboardView: () => void; - getMobileKeyboardInputViewButtonText?: () => string; - }; +export type ToolbarComponentProps< + T extends AnyPickerView = AnyPickerView +> = CalendarAndClockProps & { + views: T[]; + openView: T; + date: MaterialUiPickersDate; + setOpenView: (view: T) => void; + onChange: (date: MaterialUiPickersDate, isFinish?: boolean) => void; + toolbarTitle?: React.ReactNode; + toolbarFormat?: string; + // TODO move out, cause it is DateTimePickerOnly + hideTabs?: boolean; + dateRangeIcon?: React.ReactNode; + timeIcon?: React.ReactNode; + isLandscape: boolean; + ampmInClock?: boolean; + isMobileKeyboardViewOpen: boolean; + toggleMobileKeyboardView: () => void; + getMobileKeyboardInputViewButtonText?: () => string; +}; -export interface ExportedPickerProps +export interface ExportedPickerProps extends Omit, - BaseDatePickerProps, - ExportedClockViewProps { - toolbarTitle?: string; - showToolbar?: boolean; - ToolbarComponent?: React.ComponentType>; + CalendarAndClockProps, + WithViewsProps { // TODO move out, cause it is DateTimePickerOnly hideTabs?: boolean; dateRangeIcon?: React.ReactNode; @@ -52,10 +51,10 @@ export interface ExportedPickerProps } export interface PickerProps< - T extends PickerView, + TView extends AnyPickerView, TInputValue = ParsableDate, TDateValue = MaterialUiPickersDate -> extends ExportedPickerProps, WithViewsProps { +> extends ExportedPickerProps { isMobileKeyboardViewOpen: boolean; toggleMobileKeyboardView: () => void; DateInputProps: DateInputProps; @@ -106,8 +105,9 @@ export function Picker({ DateInputProps, isMobileKeyboardViewOpen, toggleMobileKeyboardView, + toolbarFormat, ...other -}: PickerProps) { +}: PickerProps) { const classes = useStyles(); const isLandscape = useIsLandscape(views, orientation); const wrapperVariant = React.useContext(WrapperVariantContext); @@ -145,7 +145,7 @@ export function Picker({ setOpenView={setOpenView} openView={openView} toolbarTitle={toolbarTitle} - ampmInClock={other.ampmInClock} + toolbarFormat={toolbarFormat} isMobileKeyboardViewOpen={isMobileKeyboardViewOpen} toggleMobileKeyboardView={toggleMobileKeyboardView} /> diff --git a/lib/src/Picker/WithViewsProps.tsx b/lib/src/Picker/WithViewsProps.tsx index 205b41287..6557c998a 100644 --- a/lib/src/Picker/WithViewsProps.tsx +++ b/lib/src/Picker/WithViewsProps.tsx @@ -3,7 +3,9 @@ import { BasePickerProps } from '../typings/BasePicker'; import { ExportedDateInputProps } from '../_shared/PureDateInput'; import { DateValidationProps } from '../_helpers/text-field-helper'; -export interface WithViewsProps { +export type AnyPickerView = DateTimePickerView; + +export interface WithViewsProps { /** * Array of views to show */ diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 580c45335..38dd335eb 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -1,39 +1,40 @@ import * as React from 'react'; +import { AnyPickerView } from './WithViewsProps'; import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; -import { PureDateInput } from '../_shared/PureDateInput'; +import { makeWrapperComponent } from './makeWrapperComponent'; import { parsePickerInputValue } from '../_helpers/date-utils'; -import { makePickerWithWrapper } from './makePickerWithWrapper'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { DateValidationProps } from '../_helpers/text-field-helper'; -import { WithDateAdapterProps } from '../_shared/withDateAdapterProp'; import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; +import { PureDateInput, ExportedDateInputProps } from '../_shared/PureDateInput'; +import { WithDateAdapterProps, withDateAdapterProp } from '../_shared/withDateAdapterProp'; + +export type AllSharedPickerProps = WithDateAdapterProps & + BasePickerProps & + ExportedDateInputProps & + DateValidationProps; + +type AllAvailableForOverrideProps = ExportedPickerProps; export interface MakePickerOptions { - useDefaultProps: (props: T) => Partial & { inputFormat: string }; + useDefaultProps: (props: T & AllSharedPickerProps) => Partial & { inputFormat: string }; DefaultToolbarComponent: React.ComponentType; } export function makePickerWithStateAndWrapper< - T extends ExportedPickerProps & - DateValidationProps & - Pick, 'onChange' | 'value'>, + T extends AllAvailableForOverrideProps, TWrapper extends SomeWrapper = any ->( - Wrapper: TWrapper, - { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions -) { - const PickerComponentWithWrapper = makePickerWithWrapper(Wrapper, { - PickerComponent: Picker, - DefaultToolbarComponent: DefaultToolbarComponent, +>(Wrapper: TWrapper, { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions) { + const PickerWrapper = makeWrapperComponent(Wrapper, { KeyboardDateInputComponent: KeyboardDateInput, PureDateInputComponent: PureDateInput, }); - function PickerWithState(props: T & WithDateAdapterProps & ExtendWrapper) { + function PickerWithState(props: T & AllSharedPickerProps & ExtendWrapper) { const defaultProps = useDefaultProps(props); const allProps = { ...defaultProps, ...props }; @@ -42,16 +43,85 @@ export function makePickerWithStateAndWrapper< MaterialUiPickersDate >(allProps, parsePickerInputValue); + const { + allowKeyboardControl, + ampm, + ampmInClock, + dateRangeIcon, + disableFuture, + disablePast, + showToolbar, + hideTabs, + leftArrowButtonProps, + leftArrowIcon, + loadingIndicator, + maxDate, + minDate, + minutesStep, + onMonthChange, + onYearChange, + openTo, + orientation, + renderDay, + rightArrowButtonProps, + rightArrowIcon, + shouldDisableDate, + shouldDisableTime, + timeIcon, + toolbarFormat, + ToolbarComponent = DefaultToolbarComponent, + views, + toolbarTitle, + disableTimeValidationIgnoreDatePart, + showDaysOutsideCurrentMonth, + disableHighlightToday, + minTime, + maxTime, + ...restPropsForTextField + } = allProps; + return ( - // @ts-ignore - + + + ); } - return PickerWithState; + return withDateAdapterProp(PickerWithState); } diff --git a/lib/src/Picker/makePickerWithWrapper.tsx b/lib/src/Picker/makePickerWithWrapper.tsx deleted file mode 100644 index 8cd005ad6..000000000 --- a/lib/src/Picker/makePickerWithWrapper.tsx +++ /dev/null @@ -1,182 +0,0 @@ -import React from 'react'; -import { BasePickerProps } from '../typings/BasePicker'; -import { DateInputProps } from '../_shared/PureDateInput'; -import { DateValidationProps } from '../_helpers/text-field-helper'; -import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; -import { ToolbarComponentProps, PickerProps, ExportedPickerProps } from './Picker'; -import { WithDateAdapterProps, withDateAdapterProp } from '../_shared/withDateAdapterProp'; -import { - OmitInnerWrapperProps, - SomeWrapper, - ExtendWrapper, - WrapperProps, -} from '../wrappers/Wrapper'; - -interface MakePickerOptions { - DefaultToolbarComponent: React.ComponentType; - PickerComponent: React.ComponentType>; - PureDateInputComponent?: React.FC>; - KeyboardDateInputComponent?: React.FC>; -} - -type AllPickerProps = ExportedPickerProps & - DateValidationProps & - Pick, 'onChange' | 'value'>; - -interface WithWrapperProps { - inputProps: DateInputProps; - wrapperProps: Omit; - pickerProps: Omit, 'DateInputProps'>; -} - -export function makePickerWithWrapper< - TInputValue, - TDateValue, - TProps extends AllPickerProps, - TWrapper extends SomeWrapper = any ->( - Wrapper: TWrapper, - { - PickerComponent, - KeyboardDateInputComponent, - PureDateInputComponent, - DefaultToolbarComponent, - }: MakePickerOptions -): React.FC< - TProps & - WithWrapperProps & - WithDateAdapterProps & - ExtendWrapper -> { - function PickerWithState( - props: TProps & - WithDateAdapterProps & - WithWrapperProps & - Partial> - ) { - const { - allowKeyboardControl, - ampm, - ampmInClock, - autoOk, - dateRangeIcon, - disableFuture, - disablePast, - showToolbar, - inputFormat, - hideTabs, - defaultHighlight, - leftArrowButtonProps, - leftArrowIcon, - loadingIndicator, - maxDate, - minDate, - minutesStep, - onAccept, - onChange, - onClose, - onMonthChange, - onOpen, - onYearChange, - openTo, - orientation, - renderDay, - rightArrowButtonProps, - rightArrowIcon, - shouldDisableDate, - shouldDisableTime, - strictCompareDates, - timeIcon, - toolbarFormat, - ToolbarComponent = DefaultToolbarComponent, - value, - views, - toolbarTitle, - invalidDateMessage, - minDateMessage, - wider, - showTabs, - maxDateMessage, - disableTimeValidationIgnoreDatePart, - showDaysOutsideCurrentMonth, - disableHighlightToday, - // WrapperProps - clearable, - clearLabel, - DialogProps, - PopoverProps, - okLabel, - cancelLabel, - todayLabel, - minTime, - maxTime, - inputProps, - wrapperProps, - pickerProps, - ...restPropsForTextField - } = props; - - const WrapperComponent = Wrapper as SomeWrapper; - - return ( - - - - ); - } - - return withDateAdapterProp(PickerWithState); -} diff --git a/lib/src/Picker/makeWrapperComponent.tsx b/lib/src/Picker/makeWrapperComponent.tsx new file mode 100644 index 000000000..bef60d4f0 --- /dev/null +++ b/lib/src/Picker/makeWrapperComponent.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import { BasePickerProps } from '../typings/BasePicker'; +import { DateInputProps } from '../_shared/PureDateInput'; +import { DateValidationProps } from '../_helpers/text-field-helper'; +import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; +import { + OmitInnerWrapperProps, + SomeWrapper, + WrapperProps, +} from '../wrappers/Wrapper'; + +interface MakePickerOptions { + PureDateInputComponent?: React.FC>; + KeyboardDateInputComponent?: React.FC>; +} + +interface WithWrapperProps { + children: React.ReactNode; + inputProps: DateInputProps; + wrapperProps: Omit; +} + +/** Creates a component that rendering modal/popover/nothing and spreading props down to text field */ +export function makeWrapperComponent( + Wrapper: TWrapper, + { KeyboardDateInputComponent, PureDateInputComponent }: MakePickerOptions +) { + function WrapperComponent( + props: Partial> & + DateValidationProps & + WithWrapperProps & + Partial> + ) { + const { + open, + value, + autoOk, + inputFormat, + minDateMessage, + maxDateMessage, + invalidDateMessage, + defaultHighlight, + onChange, + children, + clearable, + clearLabel, + DialogProps, + PopoverProps, + okLabel, + cancelLabel, + todayLabel, + inputProps, + wrapperProps, + wider, + showTabs, + onAccept, + onClose, + onOpen, + onError, + strictCompareDates, + ...restPropsForTextField + } = props; + + const WrapperComponent = Wrapper as SomeWrapper; + + return ( + + {children} + + ); + } + + return WrapperComponent; +} diff --git a/lib/src/TimePicker/TimePicker.tsx b/lib/src/TimePicker/TimePicker.tsx index d7563b078..a79e68b63 100644 --- a/lib/src/TimePicker/TimePicker.tsx +++ b/lib/src/TimePicker/TimePicker.tsx @@ -1,19 +1,18 @@ import React from 'react'; import ClockIcon from '../_shared/icons/ClockIcon'; import { TimePickerToolbar } from './TimePickerToolbar'; +import { WithViewsProps } from '../Picker/WithViewsProps'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; import { useUtils, MuiPickersAdapter } from '../_shared/hooks/useUtils'; -import { WithViewsProps, WithDateInputProps } from '../Picker/WithViewsProps'; -import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { timePickerDefaultProps, ParsableDate } from '../constants/prop-types'; import { ModalWrapper, InlineWrapper, StaticWrapper } from '../wrappers/Wrapper'; +import { makePickerWithStateAndWrapper, AllSharedPickerProps } from '../Picker/makePickerWithState'; export interface TimePickerProps extends ExportedClockViewProps, - WithViewsProps<'hours' | 'minutes' | 'seconds'>, - WithDateInputProps {} + WithViewsProps<'hours' | 'minutes' | 'seconds'> {} export function getTextFieldAriaText(value: ParsableDate, utils: MuiPickersAdapter) { return value && utils.isValid(utils.date(value)) @@ -27,7 +26,7 @@ function useDefaultProps({ inputFormat, openTo = 'hours', views = ['hours', 'minutes'], -}: TimePickerProps) { +}: TimePickerProps & AllSharedPickerProps) { const utils = useUtils(); const willUseAmPm = ampm ?? utils.is12HourCycleInCurrentLocale(); diff --git a/lib/src/_helpers/text-field-helper.ts b/lib/src/_helpers/text-field-helper.ts index aa34a7317..7420459d6 100644 --- a/lib/src/_helpers/text-field-helper.ts +++ b/lib/src/_helpers/text-field-helper.ts @@ -1,8 +1,8 @@ -import { DatePickerProps } from '../DatePicker'; import { ParsableDate } from '../constants/prop-types'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; +import { ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; export function getTextFieldAriaText(rawValue: ParsableDate, utils: MuiPickersAdapter) { return rawValue && utils.isValid(utils.date(rawValue)) @@ -44,6 +44,11 @@ export interface DateValidationProps extends BaseValidationProps { * @default 'Date should not be after maximal date' */ maxDateMessage?: React.ReactNode; + /** + * Compare dates by the exact timestamp, instead of start/end of date + * @default false + */ + strictCompareDates?: boolean; } const getComparisonMaxDate = ( @@ -82,7 +87,7 @@ export const validate = ( minDateMessage, invalidDateMessage, strictCompareDates, - }: Omit + }: ExportedCalendarViewProps & DateValidationProps ): React.ReactNode => { const parsedValue = utils.date(value); diff --git a/lib/src/_shared/PickerToolbar.tsx b/lib/src/_shared/PickerToolbar.tsx index 55897001f..d5c6711f9 100644 --- a/lib/src/_shared/PickerToolbar.tsx +++ b/lib/src/_shared/PickerToolbar.tsx @@ -48,7 +48,7 @@ interface PickerToolbarProps | 'isMobileKeyboardViewOpen' | 'toggleMobileKeyboardView' > { - toolbarTitle: string; + toolbarTitle: React.ReactNode; landscapeDirection?: 'row' | 'column'; isLandscape: boolean; penIconClassName?: string; diff --git a/lib/src/_shared/hooks/useViews.tsx b/lib/src/_shared/hooks/useViews.tsx index af4a6475c..120e07f92 100644 --- a/lib/src/_shared/hooks/useViews.tsx +++ b/lib/src/_shared/hooks/useViews.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import { PickerView } from '../../Picker/Picker'; import { arrayIncludes } from '../../_helpers/utils'; import { MaterialUiPickersDate } from '../../typings/date'; +import { AnyPickerView } from '../../Picker/WithViewsProps'; export type PickerOnChangeFn = (date: MaterialUiPickersDate, isFinish?: boolean | symbol) => void; @@ -12,8 +12,8 @@ export function useViews({ isMobileKeyboardViewOpen, toggleMobileKeyboardView, }: { - views: PickerView[]; - openTo: PickerView; + views: AnyPickerView[]; + openTo: AnyPickerView; onChange: PickerOnChangeFn; isMobileKeyboardViewOpen: boolean; toggleMobileKeyboardView: () => void; diff --git a/lib/src/typings/BasePicker.tsx b/lib/src/typings/BasePicker.tsx index 8ce751289..638c1dcc0 100644 --- a/lib/src/typings/BasePicker.tsx +++ b/lib/src/typings/BasePicker.tsx @@ -2,7 +2,10 @@ import { MaterialUiPickersDate } from './date'; import { ParsableDate } from '../constants/prop-types'; import { ToolbarComponentProps } from '../Picker/Picker'; -export interface BasePickerProps { +export interface BasePickerProps< + TInputValue = ParsableDate, + TDateValue = MaterialUiPickersDate | null +> { /** Picker value */ value: TInputValue; /** onChange callback @DateIOType */ @@ -44,10 +47,7 @@ export interface BasePickerProps boolean; + /** Callback firing on year change @DateIOType */ + onYearChange?: (date: MaterialUiPickersDate) => void; } export type ExportedCalendarViewProps = Omit< From 88489b555ab0d0d6410b61e03134f4303eda3961 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 18:27:57 +0200 Subject: [PATCH 06/72] Rename eome type names and files --- lib/src/DatePicker/DatePicker.tsx | 2 +- lib/src/DateRangePicker/DateRangePicker.tsx | 2 +- lib/src/DateTimePicker/DateTimePicker.tsx | 4 ++-- lib/src/Picker/Picker.tsx | 2 +- .../{WithViewsProps.tsx => SharedPickerProps.tsx} | 6 ++++++ lib/src/Picker/makePickerWithState.tsx | 15 ++++----------- lib/src/TimePicker/TimePicker.tsx | 4 ++-- lib/src/_shared/hooks/useViews.tsx | 2 +- .../{Picker => wrappers}/makeWrapperComponent.tsx | 4 ++-- 9 files changed, 20 insertions(+), 21 deletions(-) rename lib/src/Picker/{WithViewsProps.tsx => SharedPickerProps.tsx} (73%) rename lib/src/{Picker => wrappers}/makeWrapperComponent.tsx (95%) diff --git a/lib/src/DatePicker/DatePicker.tsx b/lib/src/DatePicker/DatePicker.tsx index 5c19754de..237cfe648 100644 --- a/lib/src/DatePicker/DatePicker.tsx +++ b/lib/src/DatePicker/DatePicker.tsx @@ -1,7 +1,7 @@ import { useUtils } from '../_shared/hooks/useUtils'; import { DatePickerToolbar } from './DatePickerToolbar'; import { getFormatByViews } from '../_helpers/date-utils'; -import { WithViewsProps } from '../Picker/WithViewsProps'; +import { WithViewsProps } from '../Picker/SharedPickerProps'; import { datePickerDefaultProps } from '../constants/prop-types'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 2206e30e7..8954ea2b5 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -7,8 +7,8 @@ import { DateRangePickerInput } from './DateRangePickerInput'; import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; -import { makeWrapperComponent } from '../Picker/makeWrapperComponent'; import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; +import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { SomeWrapper, OmitInnerWrapperProps } from '../wrappers/Wrapper'; import { DateRangePickerCalendar, DateRangePickerCalendarProps } from './DateRangePickerCalendar'; diff --git a/lib/src/DateTimePicker/DateTimePicker.tsx b/lib/src/DateTimePicker/DateTimePicker.tsx index 98c9baa67..93148f063 100644 --- a/lib/src/DateTimePicker/DateTimePicker.tsx +++ b/lib/src/DateTimePicker/DateTimePicker.tsx @@ -1,13 +1,13 @@ import { useUtils } from '../_shared/hooks/useUtils'; -import { WithViewsProps } from '../Picker/WithViewsProps'; import { DateTimePickerToolbar } from './DateTimePickerToolbar'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; import { ExportedCalendarProps } from '../views/Calendar/Calendar'; +import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { InlineWrapper, ModalWrapper, StaticWrapper } from '../wrappers/Wrapper'; +import { WithViewsProps, AllSharedPickerProps } from '../Picker/SharedPickerProps'; import { dateTimePickerDefaultProps, ParsableDate } from '../constants/prop-types'; -import { makePickerWithStateAndWrapper, AllSharedPickerProps } from '../Picker/makePickerWithState'; export type DateTimePickerView = 'year' | 'date' | 'month' | 'hours' | 'minutes' | 'seconds'; diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index 229494d3c..558d01728 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -9,8 +9,8 @@ import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { DatePickerView } from '../DatePicker/DatePicker'; -import { WithViewsProps, AnyPickerView } from './WithViewsProps'; import { useIsLandscape } from '../_shared/hooks/useIsLandscape'; +import { WithViewsProps, AnyPickerView } from './SharedPickerProps'; import { DIALOG_WIDTH, VIEW_HEIGHT } from '../constants/dimensions'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; diff --git a/lib/src/Picker/WithViewsProps.tsx b/lib/src/Picker/SharedPickerProps.tsx similarity index 73% rename from lib/src/Picker/WithViewsProps.tsx rename to lib/src/Picker/SharedPickerProps.tsx index 6557c998a..53b57f92b 100644 --- a/lib/src/Picker/WithViewsProps.tsx +++ b/lib/src/Picker/SharedPickerProps.tsx @@ -2,9 +2,15 @@ import { DateTimePickerView } from '../DateTimePicker'; import { BasePickerProps } from '../typings/BasePicker'; import { ExportedDateInputProps } from '../_shared/PureDateInput'; import { DateValidationProps } from '../_helpers/text-field-helper'; +import { WithDateAdapterProps } from '../_shared/withDateAdapterProp'; export type AnyPickerView = DateTimePickerView; +export type AllSharedPickerProps = WithDateAdapterProps & + BasePickerProps & + ExportedDateInputProps & + DateValidationProps; + export interface WithViewsProps { /** * Array of views to show diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 38dd335eb..1cd906186 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -1,22 +1,15 @@ import * as React from 'react'; -import { AnyPickerView } from './WithViewsProps'; import { ParsableDate } from '../constants/prop-types'; -import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; -import { makeWrapperComponent } from './makeWrapperComponent'; +import { PureDateInput } from '../_shared/PureDateInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; -import { DateValidationProps } from '../_helpers/text-field-helper'; +import { withDateAdapterProp } from '../_shared/withDateAdapterProp'; +import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; +import { AnyPickerView, AllSharedPickerProps } from './SharedPickerProps'; import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; -import { PureDateInput, ExportedDateInputProps } from '../_shared/PureDateInput'; -import { WithDateAdapterProps, withDateAdapterProp } from '../_shared/withDateAdapterProp'; - -export type AllSharedPickerProps = WithDateAdapterProps & - BasePickerProps & - ExportedDateInputProps & - DateValidationProps; type AllAvailableForOverrideProps = ExportedPickerProps; diff --git a/lib/src/TimePicker/TimePicker.tsx b/lib/src/TimePicker/TimePicker.tsx index a79e68b63..2bf3c1bc7 100644 --- a/lib/src/TimePicker/TimePicker.tsx +++ b/lib/src/TimePicker/TimePicker.tsx @@ -1,14 +1,14 @@ import React from 'react'; import ClockIcon from '../_shared/icons/ClockIcon'; import { TimePickerToolbar } from './TimePickerToolbar'; -import { WithViewsProps } from '../Picker/WithViewsProps'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; import { useUtils, MuiPickersAdapter } from '../_shared/hooks/useUtils'; +import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { timePickerDefaultProps, ParsableDate } from '../constants/prop-types'; import { ModalWrapper, InlineWrapper, StaticWrapper } from '../wrappers/Wrapper'; -import { makePickerWithStateAndWrapper, AllSharedPickerProps } from '../Picker/makePickerWithState'; +import { WithViewsProps, AllSharedPickerProps } from '../Picker/SharedPickerProps'; export interface TimePickerProps extends ExportedClockViewProps, diff --git a/lib/src/_shared/hooks/useViews.tsx b/lib/src/_shared/hooks/useViews.tsx index 120e07f92..eaa05ab2a 100644 --- a/lib/src/_shared/hooks/useViews.tsx +++ b/lib/src/_shared/hooks/useViews.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { arrayIncludes } from '../../_helpers/utils'; import { MaterialUiPickersDate } from '../../typings/date'; -import { AnyPickerView } from '../../Picker/WithViewsProps'; +import { AnyPickerView } from '../../Picker/SharedPickerProps'; export type PickerOnChangeFn = (date: MaterialUiPickersDate, isFinish?: boolean | symbol) => void; diff --git a/lib/src/Picker/makeWrapperComponent.tsx b/lib/src/wrappers/makeWrapperComponent.tsx similarity index 95% rename from lib/src/Picker/makeWrapperComponent.tsx rename to lib/src/wrappers/makeWrapperComponent.tsx index bef60d4f0..b6df08809 100644 --- a/lib/src/Picker/makeWrapperComponent.tsx +++ b/lib/src/wrappers/makeWrapperComponent.tsx @@ -1,13 +1,13 @@ import React from 'react'; import { BasePickerProps } from '../typings/BasePicker'; import { DateInputProps } from '../_shared/PureDateInput'; +import { ResponsiveWrapperProps } from './ResponsiveWrapper'; import { DateValidationProps } from '../_helpers/text-field-helper'; -import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; import { OmitInnerWrapperProps, SomeWrapper, WrapperProps, -} from '../wrappers/Wrapper'; +} from './Wrapper'; interface MakePickerOptions { PureDateInputComponent?: React.FC>; From c72bc5f3b2ca8ce39f84f70edec2199311990d17 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 18:42:39 +0200 Subject: [PATCH 07/72] Integrate validation back to usePickerState --- lib/src/DatePicker/DatePicker.tsx | 12 ++++----- lib/src/Picker/makePickerWithState.tsx | 3 ++- .../__tests__/e2e/KeyboardDatePicker.test.tsx | 4 +-- lib/src/_helpers/text-field-helper.ts | 9 +++---- lib/src/_shared/hooks/usePickerState.ts | 26 ++++++++++--------- lib/src/constants/prop-types.ts | 6 ++--- lib/src/index.ts | 2 +- lib/src/typings/BasePicker.tsx | 2 +- 8 files changed, 33 insertions(+), 31 deletions(-) diff --git a/lib/src/DatePicker/DatePicker.tsx b/lib/src/DatePicker/DatePicker.tsx index 237cfe648..60e997fc5 100644 --- a/lib/src/DatePicker/DatePicker.tsx +++ b/lib/src/DatePicker/DatePicker.tsx @@ -10,13 +10,13 @@ import { ModalWrapper, InlineWrapper, StaticWrapper } from '../wrappers/Wrapper' export type DatePickerView = 'year' | 'date' | 'month'; -export interface BaseDatePickerProps +export interface DatePickerProps extends WithViewsProps<'year' | 'date' | 'month'>, ExportedCalendarViewProps {} const datePickerConfig = { DefaultToolbarComponent: DatePickerToolbar, - useDefaultProps: ({ openTo = 'date', views = ['year', 'date'] }: BaseDatePickerProps) => { + useDefaultProps: ({ openTo = 'date', views = ['year', 'date'] }: DatePickerProps) => { const utils = useUtils(); return { @@ -29,22 +29,22 @@ const datePickerConfig = { }, }; -export const DatePicker = makePickerWithStateAndWrapper( +export const DatePicker = makePickerWithStateAndWrapper( ResponsiveWrapper, datePickerConfig ); -export const MobileDatePicker = makePickerWithStateAndWrapper( +export const MobileDatePicker = makePickerWithStateAndWrapper( ModalWrapper, datePickerConfig ); -export const DesktopDatePicker = makePickerWithStateAndWrapper( +export const DesktopDatePicker = makePickerWithStateAndWrapper( InlineWrapper, datePickerConfig ); -export const StaticDatePicker = makePickerWithStateAndWrapper( +export const StaticDatePicker = makePickerWithStateAndWrapper( StaticWrapper, datePickerConfig ); diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 1cd906186..cf77b3dc7 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -6,6 +6,7 @@ import { parsePickerInputValue } from '../_helpers/date-utils'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; +import { validateDateValue } from '../_helpers/text-field-helper'; import { withDateAdapterProp } from '../_shared/withDateAdapterProp'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { AnyPickerView, AllSharedPickerProps } from './SharedPickerProps'; @@ -34,7 +35,7 @@ export function makePickerWithStateAndWrapper< const { pickerProps, inputProps, wrapperProps } = usePickerState< ParsableDate, MaterialUiPickersDate - >(allProps, parsePickerInputValue); + >(allProps, parsePickerInputValue, validateDateValue); const { allowKeyboardControl, diff --git a/lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx b/lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx index 462faf97c..a690aeada 100644 --- a/lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx +++ b/lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx @@ -90,7 +90,7 @@ describe('e2e -- KeyboardDatePicker validation errors', () => { /> ); - expect(component.find('ForwardRef(TextField)').prop('helperText')).toBe(''); + expect(component.find('ForwardRef(TextField)').prop('helperText')).toBe(undefined); }); it('Should render error message if date is after maxDate with strict comparison', () => { @@ -119,7 +119,7 @@ describe('e2e -- KeyboardDatePicker validation errors', () => { /> ); - expect(component.find('ForwardRef(TextField)').prop('helperText')).toBe(''); + expect(component.find('ForwardRef(TextField)').prop('helperText')).toBe(undefined); }); it('Should render error message if date is after minDate with strict comparison', () => { diff --git a/lib/src/_helpers/text-field-helper.ts b/lib/src/_helpers/text-field-helper.ts index 7420459d6..8021952af 100644 --- a/lib/src/_helpers/text-field-helper.ts +++ b/lib/src/_helpers/text-field-helper.ts @@ -2,7 +2,6 @@ import { ParsableDate } from '../constants/prop-types'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; -import { ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; export function getTextFieldAriaText(rawValue: ParsableDate, utils: MuiPickersAdapter) { return rawValue && utils.isValid(utils.date(rawValue)) @@ -75,7 +74,7 @@ const getComparisonMinDate = ( return utils.startOfDay(date); }; -export const validate = ( +export const validateDateValue = ( value: ParsableDate, utils: MuiPickersAdapter, { @@ -87,13 +86,13 @@ export const validate = ( minDateMessage, invalidDateMessage, strictCompareDates, - }: ExportedCalendarViewProps & DateValidationProps + }: any // TODO change the typings when doing hard update of validation system ): React.ReactNode => { const parsedValue = utils.date(value); // if null - do not show error if (value === null) { - return ''; + return undefined; } if (!utils.isValid(value)) { @@ -133,7 +132,7 @@ export const validate = ( return minDateMessage; } - return ''; + return undefined; }; export function pick12hOr24hFormat( diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 825d0ec79..49976b2c0 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -2,7 +2,6 @@ import { useOpenState } from './useOpenState'; import { WrapperVariant } from '../../wrappers/Wrapper'; import { BasePickerProps } from '../../typings/BasePicker'; import { MaterialUiPickersDate } from '../../typings/date'; -import { validate } from '../../_helpers/text-field-helper'; import { useUtils, useNow, MuiPickersAdapter } from './useUtils'; import { useCallback, useDebugValue, useEffect, useMemo, useState } from 'react'; @@ -14,9 +13,13 @@ export function usePickerState( now: MaterialUiPickersDate, utils: MuiPickersAdapter, props: BasePickerProps - ) => TOutput | null + ) => TOutput | null, + validateInputValue: ( + value: TInput, + utils: MuiPickersAdapter, + props: BasePickerProps + ) => React.ReactNode | undefined ) { - console.log('updating state'); const { autoOk, inputFormat, disabled, readOnly, onAccept, onChange, onError, value } = props; if (!inputFormat) { @@ -107,23 +110,22 @@ export function usePickerState( [acceptDate, autoOk, isMobileKeyboardViewOpen, pickerDate] ); - // TODO FIX ME - // const validationError = validate(value, utils, props as any); - // useEffect(() => { - // if (onError) { - // onError(validationError, value); - // } - // }, [onError, validationError, value]); + const validationError = validateInputValue(value, utils, props); + useEffect(() => { + if (onError) { + onError(validationError, value); + } + }, [onError, validationError, value]); const inputProps = useMemo( () => ({ onChange, inputFormat, rawValue: value, - validationError: undefined, + validationError, openPicker: () => !readOnly && !disabled && setIsOpen(true), }), - [disabled, inputFormat, onChange, readOnly, setIsOpen, value] + [disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] ); const pickerState = { pickerProps, inputProps, wrapperProps }; diff --git a/lib/src/constants/prop-types.ts b/lib/src/constants/prop-types.ts index cba959efc..97eaaafff 100644 --- a/lib/src/constants/prop-types.ts +++ b/lib/src/constants/prop-types.ts @@ -1,5 +1,5 @@ import * as PropTypes from 'prop-types'; -import { BaseDatePickerProps } from '../DatePicker/DatePicker'; +import { DatePickerProps } from '../DatePicker/DatePicker'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; const date = PropTypes.oneOfType([ @@ -26,10 +26,10 @@ export const datePickerDefaultProps = { invalidDateMessage: 'Invalid Date Format', minDateMessage: 'Date should not be before minimal date', maxDateMessage: 'Date should not be after maximal date', -} as BaseDatePickerProps; +} as DatePickerProps; export const dateTimePickerDefaultProps = { ...timePickerDefaultProps, ...datePickerDefaultProps, showTabs: true, -} as ExportedClockViewProps & BaseDatePickerProps; +} as ExportedClockViewProps & DatePickerProps; diff --git a/lib/src/index.ts b/lib/src/index.ts index bcad47d84..890085817 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -24,7 +24,7 @@ export { Picker } from './Picker/Picker'; export { makePickerWithStateAndWrapper as makePickerWithState } from './Picker/makePickerWithState'; -export { validate } from './_helpers/text-field-helper'; +export { validateDateValue as validate } from './_helpers/text-field-helper'; export { useUtils } from './_shared/hooks/useUtils'; diff --git a/lib/src/typings/BasePicker.tsx b/lib/src/typings/BasePicker.tsx index 638c1dcc0..853437d60 100644 --- a/lib/src/typings/BasePicker.tsx +++ b/lib/src/typings/BasePicker.tsx @@ -28,7 +28,7 @@ export interface BasePickerProps< /** Callback fired when new error should be displayed * (!! This is a side effect. Be careful if you want to rerender the component) @DateIOType */ - onError?: (error: React.ReactNode, value: MaterialUiPickersDate | ParsableDate) => void; + onError?: (error: React.ReactNode, value: TInputValue | TDateValue) => void; /** On open callback */ onOpen?: () => void; /** On close callback */ From eb95e4dbd0dea73f2d80e1c9db5f96d49fb24889 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 18:43:09 +0200 Subject: [PATCH 08/72] Remove DateRangePicker code --- lib/src/DateRangePicker/DateRangePicker.tsx | 57 ------------------- .../DateRangePickerCalendar.tsx | 11 ---- .../DateRangePicker/DateRangePickerInput.tsx | 20 ------- lib/src/DateRangePicker/RangeTypes.ts | 5 -- 4 files changed, 93 deletions(-) delete mode 100644 lib/src/DateRangePicker/DateRangePicker.tsx delete mode 100644 lib/src/DateRangePicker/DateRangePickerCalendar.tsx delete mode 100644 lib/src/DateRangePicker/DateRangePickerInput.tsx delete mode 100644 lib/src/DateRangePicker/RangeTypes.ts diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx deleted file mode 100644 index 8954ea2b5..000000000 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from 'react'; -import { DateRange, RangeInput } from './RangeTypes'; -import { MaterialUiPickersDate } from '../typings/date'; -import { BasePickerProps } from '../typings/BasePicker'; -import { DesktopWrapper } from '../wrappers/DesktopWrapper'; -import { DateRangePickerInput } from './DateRangePickerInput'; -import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; -import { parsePickerInputValue } from '../_helpers/date-utils'; -import { usePickerState } from '../_shared/hooks/usePickerState'; -import { ResponsiveWrapperProps } from '../wrappers/ResponsiveWrapper'; -import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; -import { SomeWrapper, OmitInnerWrapperProps } from '../wrappers/Wrapper'; -import { DateRangePickerCalendar, DateRangePickerCalendarProps } from './DateRangePickerCalendar'; - -export function parseRangeInputValue( - now: MaterialUiPickersDate, - utils: MuiPickersAdapter, - { value = [null, null], defaultHighlight }: BasePickerProps -) { - return value.map(date => - parsePickerInputValue(now, utils, { value: date, defaultHighlight }) - ) as DateRange; -} - -export function makeRangePicker(Wrapper: TWrapper) { - const PickerComponentWithWrapper = makeWrapperComponent(Wrapper, { - KeyboardDateInputComponent: DateRangePickerInput, - PureDateInputComponent: DateRangePickerInput, - }); - - function RangePickerWithStateAndWrapper( - allProps: DateRangePickerCalendarProps & - Pick, 'onChange' | 'value'> & - Partial> - ) { - const { pickerProps, inputProps, wrapperProps } = usePickerState( - allProps, - parseRangeInputValue - ); - - const { calendars, ...other } = allProps; - - return ( - - - - ); - } - - RangePickerWithStateAndWrapper.defaultProps = { - inputFormat: 'MM', - }; - - return RangePickerWithStateAndWrapper; -} - -export const DateRangePicker = makeRangePicker(DesktopWrapper); diff --git a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx deleted file mode 100644 index cbd14a444..000000000 --- a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; -import { RangeInput, DateRange } from './RangeTypes'; -import { ExportedPickerProps } from '../Picker/Picker'; - -export interface DateRangePickerCalendarProps { - calendars?: 1 | 2; -} - -export const DateRangePickerCalendar: React.FC = ({}) => { - return <>ewfojweiof; -}; diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx deleted file mode 100644 index c8b400f9c..000000000 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; -import KeyboardDateInput from '../_shared/KeyboardDateInput'; -import { TextField } from '@material-ui/core'; -import { DateInputProps } from '../_shared/PureDateInput'; -import { RangeInput, DateRange } from './DateRangePicker'; - -export const DateRangePickerInput: React.FC> = ({ - rawValue, - onChange, - ...other -}) => { - console.log(rawValue) - const [start, end] = rawValue; - return ( - <> - - - - ); -}; diff --git a/lib/src/DateRangePicker/RangeTypes.ts b/lib/src/DateRangePicker/RangeTypes.ts deleted file mode 100644 index ccd1c77ff..000000000 --- a/lib/src/DateRangePicker/RangeTypes.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ParsableDate } from "../constants/prop-types"; -import { MaterialUiPickersDate } from "../typings/date"; - -export type RangeInput = [ParsableDate, ParsableDate]; -export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; From f19294a78032c9e82c4ab4c2cf46cd5535f7d645 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 18:43:54 +0200 Subject: [PATCH 09/72] Remove DateRangePickerUsage from index module --- lib/src/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/index.ts b/lib/src/index.ts index 890085817..53d9eceb3 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -6,8 +6,6 @@ export * from './TimePicker'; export * from './DateTimePicker'; -export * from './DateRangePicker/DateRangePicker'; - export { Calendar } from './views/Calendar/Calendar'; export * from './views/Calendar/CalendarView'; From a6f90a5ded67ef6a6a9d4a11ba278304e74140b8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 11 Mar 2020 18:50:00 +0200 Subject: [PATCH 10/72] Fix small linter and ts errors --- lib/src/LocalizationProvider.tsx | 4 ++-- lib/src/_helpers/date-utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/LocalizationProvider.tsx b/lib/src/LocalizationProvider.tsx index 0f0362090..be4470d8e 100644 --- a/lib/src/LocalizationProvider.tsx +++ b/lib/src/LocalizationProvider.tsx @@ -28,7 +28,7 @@ export const LocalizationProvider: React.FC = ({ return ; }; -// @ts-ignore + LocalizationProvider.propTypes = { dateAdapter: PropTypes.func.isRequired, locale: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), @@ -36,6 +36,6 @@ LocalizationProvider.propTypes = { PropTypes.element.isRequired, PropTypes.arrayOf(PropTypes.element.isRequired), ]).isRequired, -}; +} as any; export default LocalizationProvider; diff --git a/lib/src/_helpers/date-utils.ts b/lib/src/_helpers/date-utils.ts index 1500a51b4..7e45955b7 100644 --- a/lib/src/_helpers/date-utils.ts +++ b/lib/src/_helpers/date-utils.ts @@ -3,7 +3,7 @@ import { IUtils } from '@date-io/core/IUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; import { DatePickerView } from '../DatePicker/DatePicker'; -import { useNow, useUtils, MuiPickersAdapter } from '../_shared/hooks/useUtils'; +import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; interface FindClosestDateParams { date: MaterialUiPickersDate; From beb6f3989d297fd039110891ae5a50000a3ebaea Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 12 Mar 2020 14:19:30 +0200 Subject: [PATCH 11/72] Fix build erros --- .../BasicDateRangePicker.example.jsx | 9 ++----- docs/pages/demo/daterangepicker/index.mdx | 2 -- docs/tsconfig.json | 2 +- lib/.size-snapshot.json | 24 +++++++++---------- lib/src/DateTimePicker/DateTimePicker.tsx | 4 ++-- lib/src/constants/prop-types.ts | 3 ++- 6 files changed, 19 insertions(+), 25 deletions(-) diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index 46b5d7c5b..b6ffc8123 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -1,15 +1,10 @@ import React, { useState } from 'react'; -import { DateRangePicker } from '@material-ui/pickers'; +import { DatePicker as DateRangePicker } from '@material-ui/pickers'; function BasicDateRangePicker() { const [selectedDate, handleDateChange] = useState([new Date(), null]); - return ( - handleDateChange(date)} - /> - ); + return handleDateChange(date)} />; } export default BasicDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/index.mdx b/docs/pages/demo/daterangepicker/index.mdx index f4c765c40..d1c14f72b 100644 --- a/docs/pages/demo/daterangepicker/index.mdx +++ b/docs/pages/demo/daterangepicker/index.mdx @@ -5,7 +5,6 @@ import LinkedComponents from '_shared/LinkedComponents'; import * as BasicDateRangePicker from './BasicDateRangePicker.example'; - ## Date picker @@ -19,4 +18,3 @@ import * as BasicDateRangePicker from './BasicDateRangePicker.example'; Will be rendered to modal dialog on mobile and textfield with popover on desktop. - diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 1f74c1342..bd91fd82a 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -19,5 +19,5 @@ "target": "esnext", "resolveJsonModule": true }, - "include": ["../docs/**/*.ts*", "../lib/typings.d.ts"] + "include": ["../docs/**/*.ts*", "./typings.d.ts", "../lib/typings.d.ts"] } diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index 8980797c4..aeefd56ac 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,26 +1,26 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 148219, - "minified": 81418, - "gzipped": 21568, + "bundled": 145384, + "minified": 79576, + "gzipped": 21474, "treeshaked": { "rollup": { - "code": 66594, - "import_statements": 2167 + "code": 65692, + "import_statements": 2099 }, "webpack": { - "code": 74225 + "code": 73171 } } }, "build/dist/material-ui-pickers.umd.js": { - "bundled": 602739, - "minified": 224747, - "gzipped": 46056 + "bundled": 599635, + "minified": 223221, + "gzipped": 45558 }, "build/dist/material-ui-pickers.umd.min.js": { - "bundled": 542486, - "minified": 206234, - "gzipped": 41259 + "bundled": 539383, + "minified": 204705, + "gzipped": 40705 } } diff --git a/lib/src/DateTimePicker/DateTimePicker.tsx b/lib/src/DateTimePicker/DateTimePicker.tsx index 93148f063..3bd8c1bb0 100644 --- a/lib/src/DateTimePicker/DateTimePicker.tsx +++ b/lib/src/DateTimePicker/DateTimePicker.tsx @@ -3,7 +3,7 @@ import { DateTimePickerToolbar } from './DateTimePickerToolbar'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { pick12hOr24hFormat } from '../_helpers/text-field-helper'; -import { ExportedCalendarProps } from '../views/Calendar/Calendar'; +import { ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; import { makePickerWithStateAndWrapper } from '../Picker/makePickerWithState'; import { InlineWrapper, ModalWrapper, StaticWrapper } from '../wrappers/Wrapper'; import { WithViewsProps, AllSharedPickerProps } from '../Picker/SharedPickerProps'; @@ -14,7 +14,7 @@ export type DateTimePickerView = 'year' | 'date' | 'month' | 'hours' | 'minutes' export interface DateTimePickerProps extends WithViewsProps<'year' | 'date' | 'month' | 'hours' | 'minutes'>, ExportedClockViewProps, - ExportedCalendarProps { + ExportedCalendarViewProps { /** To show tabs */ hideTabs?: boolean; /** Date tab icon */ diff --git a/lib/src/constants/prop-types.ts b/lib/src/constants/prop-types.ts index 97eaaafff..261c4b8a9 100644 --- a/lib/src/constants/prop-types.ts +++ b/lib/src/constants/prop-types.ts @@ -1,4 +1,5 @@ import * as PropTypes from 'prop-types'; +import { MaterialUiPickersDate } from '../typings/date'; import { DatePickerProps } from '../DatePicker/DatePicker'; import { ExportedClockViewProps } from '../views/Clock/ClockView'; @@ -11,7 +12,7 @@ const date = PropTypes.oneOfType([ const datePickerView = PropTypes.oneOf(['year', 'month', 'day']); -export type ParsableDate = string | number | Date | null | undefined; +export type ParsableDate = string | number | Date | null | undefined | MaterialUiPickersDate; export const DomainPropTypes = { date, datePickerView }; From 3dc7bbaafa9dc77dbff68b73b80a7f27e571de60 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 12 Mar 2020 14:25:02 +0200 Subject: [PATCH 12/72] Run prettier manually --- lib/src/LocalizationProvider.tsx | 1 - lib/src/_helpers/date-utils.ts | 2 +- lib/src/wrappers/makeWrapperComponent.tsx | 6 +----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/src/LocalizationProvider.tsx b/lib/src/LocalizationProvider.tsx index be4470d8e..f3b77ab7e 100644 --- a/lib/src/LocalizationProvider.tsx +++ b/lib/src/LocalizationProvider.tsx @@ -28,7 +28,6 @@ export const LocalizationProvider: React.FC = ({ return ; }; - LocalizationProvider.propTypes = { dateAdapter: PropTypes.func.isRequired, locale: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), diff --git a/lib/src/_helpers/date-utils.ts b/lib/src/_helpers/date-utils.ts index 7e45955b7..0ce13a08c 100644 --- a/lib/src/_helpers/date-utils.ts +++ b/lib/src/_helpers/date-utils.ts @@ -3,7 +3,7 @@ import { IUtils } from '@date-io/core/IUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; import { DatePickerView } from '../DatePicker/DatePicker'; -import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; +import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; interface FindClosestDateParams { date: MaterialUiPickersDate; diff --git a/lib/src/wrappers/makeWrapperComponent.tsx b/lib/src/wrappers/makeWrapperComponent.tsx index b6df08809..12aab4a3f 100644 --- a/lib/src/wrappers/makeWrapperComponent.tsx +++ b/lib/src/wrappers/makeWrapperComponent.tsx @@ -3,11 +3,7 @@ import { BasePickerProps } from '../typings/BasePicker'; import { DateInputProps } from '../_shared/PureDateInput'; import { ResponsiveWrapperProps } from './ResponsiveWrapper'; import { DateValidationProps } from '../_helpers/text-field-helper'; -import { - OmitInnerWrapperProps, - SomeWrapper, - WrapperProps, -} from './Wrapper'; +import { OmitInnerWrapperProps, SomeWrapper, WrapperProps } from './Wrapper'; interface MakePickerOptions { PureDateInputComponent?: React.FC>; From 300bb038d23bc0dcbd58119dedcf91c11df7f3b0 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Fri, 13 Mar 2020 19:25:26 +0200 Subject: [PATCH 13/72] Display calendars for date range --- .../BasicDateRangePicker.example.jsx | 2 +- docs/prop-types.json | 1206 ++++++++--------- lib/src/DateRangePicker/DateRangePicker.tsx | 80 ++ .../DateRangePickerCalendar.tsx | 89 ++ .../DateRangePicker/DateRangePickerInput.tsx | 20 + .../DesktopDateRangePicker.tsx | 64 + lib/src/DateRangePicker/RangeTypes.ts | 5 + lib/src/Picker/Picker.tsx | 18 +- lib/src/Picker/SharedPickerProps.tsx | 28 +- lib/src/Picker/makePickerWithState.tsx | 8 +- lib/src/_shared/PureDateInput.tsx | 4 +- lib/src/_shared/hooks/usePickerState.ts | 39 +- lib/src/index.ts | 2 + lib/src/typings/BasePicker.tsx | 5 +- lib/src/typings/overrides.ts | 4 + lib/src/views/Calendar/Calendar.tsx | 33 +- lib/src/views/Calendar/CalendarView.tsx | 182 +-- lib/src/views/Calendar/SlideTransition.tsx | 4 +- lib/src/views/Calendar/useCalendarState.tsx | 183 +++ 19 files changed, 1145 insertions(+), 831 deletions(-) create mode 100644 lib/src/DateRangePicker/DateRangePicker.tsx create mode 100644 lib/src/DateRangePicker/DateRangePickerCalendar.tsx create mode 100644 lib/src/DateRangePicker/DateRangePickerInput.tsx create mode 100644 lib/src/DateRangePicker/DesktopDateRangePicker.tsx create mode 100644 lib/src/DateRangePicker/RangeTypes.ts create mode 100644 lib/src/views/Calendar/useCalendarState.tsx diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index b6ffc8123..e261f09ea 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { DatePicker as DateRangePicker } from '@material-ui/pickers'; +import { DateRangePicker } from '@material-ui/pickers'; function BasicDateRangePicker() { const [selectedDate, handleDateChange] = useState([new Date(), null]); diff --git a/docs/prop-types.json b/docs/prop-types.json index c90894540..3225cd7c6 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -236,30 +236,30 @@ } }, "DatePicker": { - "onYearChange": { + "views": { "defaultValue": null, - "description": "Callback firing on year change", - "name": "onYearChange", + "description": "Array of views to show", + "name": "views", "parent": { - "fileName": "material-ui-pickers/lib/src/DatePicker/DatePicker.tsx", - "name": "BaseDatePickerProps" + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" }, "required": false, "type": { - "name": "(date: DateIOType) => void" + "name": "(\"year\" | \"date\" | \"month\")[]" } }, - "toolbarFormat": { + "openTo": { "defaultValue": null, - "description": "Date format, that is displaying in toolbar", - "name": "toolbarFormat", + "description": "First view to show", + "name": "openTo", "parent": { - "fileName": "material-ui-pickers/lib/src/DatePicker/DatePicker.tsx", - "name": "BaseDatePickerProps" + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" }, "required": false, "type": { - "name": "string" + "name": "\"year\" | \"date\" | \"month\"" } }, "disableHighlightToday": { @@ -380,7 +380,7 @@ }, "required": false, "type": { - "name": "(currentView: \"date\" | \"year\" | \"month\") => string" + "name": "(currentView: \"year\" | \"date\" | \"month\") => string" } }, "minDate": { @@ -395,7 +395,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "maxDate": { @@ -410,7 +410,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "disablePast": { @@ -456,32 +456,30 @@ "name": "(date: DateIOType) => void | Promise" } }, - "reduceAnimations": { - "defaultValue": { - "value": "/(android)/i.test(navigator.userAgent)" - }, - "description": "Do not show heavy animations, significantly improves performance on slow devices", - "name": "reduceAnimations", + "shouldDisableDate": { + "defaultValue": null, + "description": "Disable specific date", + "name": "shouldDisableDate", "parent": { "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", "name": "CalendarViewProps" }, "required": false, "type": { - "name": "boolean" + "name": "(day: DateIOType) => boolean" } }, - "shouldDisableDate": { + "onYearChange": { "defaultValue": null, - "description": "Disable specific date", - "name": "shouldDisableDate", + "description": "Callback firing on year change", + "name": "onYearChange", "parent": { "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", "name": "CalendarViewProps" }, "required": false, "type": { - "name": "(day: DateIOType) => boolean" + "name": "(date: DateIOType) => void" } }, "renderDay": { @@ -494,7 +492,7 @@ }, "required": false, "type": { - "name": "(day: DateIOType, selectedDate: DateIOType, DayComponentProps: DayProps) => Element" + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" } }, "allowKeyboardControl": { @@ -525,51 +523,6 @@ "name": "Element" } }, - "minDateMessage": { - "defaultValue": { - "value": "'Date should not be before minimal date'" - }, - "description": "Error message, shown if date is less then minimal date", - "name": "minDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maxDateMessage": { - "defaultValue": { - "value": "'Date should not be after maximal date'" - }, - "description": "Error message, shown if date is more then maximal date", - "name": "maxDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "invalidDateMessage": { - "defaultValue": { - "value": "'Invalid Date Format'" - }, - "description": "Message, appearing when date cannot be parsed", - "name": "invalidDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "BaseValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, "value": { "defaultValue": null, "description": "Picker value", @@ -580,7 +533,7 @@ }, "required": true, "type": { - "name": "ParsableDate" + "name": "any" } }, "onChange": { @@ -660,7 +613,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "onAccept": { @@ -764,7 +717,7 @@ }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "ComponentClass, any> | FunctionComponent>" } }, "toolbarTitle": { @@ -779,22 +732,20 @@ }, "required": false, "type": { - "name": "string" + "name": "ReactNode" } }, - "strictCompareDates": { - "defaultValue": { - "value": "false" - }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar", + "name": "toolbarFormat", "parent": { "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "string" } }, "mask": { @@ -960,46 +911,80 @@ }, "required": false, "type": { - "name": "(value: ParsableDate, utils: MuiPickersAdapter) => string" + "name": "(value: any, utils: MuiPickersAdapter) => string" } }, - "views": { + "dateAdapter": { "defaultValue": null, - "description": "Array of views to show", - "name": "views", + "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/makePickerWithState.tsx", - "name": "WithViewsProps" + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" }, "required": false, "type": { - "name": "(\"date\" | \"year\" | \"month\")[]" + "name": "MuiPickersAdapter" } }, - "openTo": { - "defaultValue": null, - "description": "First view to show", - "name": "openTo", + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/makePickerWithState.tsx", - "name": "WithViewsProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "\"date\" | \"year\" | \"month\"" + "name": "ReactNode" } }, - "dateAdapter": { - "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", - "name": "dateAdapter", + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", - "name": "WithDateAdapterProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "MuiPickersAdapter" + "name": "ReactNode" + } + }, + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" } } }, @@ -1074,7 +1059,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "maxTime": { @@ -1087,7 +1072,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "shouldDisableTime": { @@ -1121,7 +1106,7 @@ "description": "Array of views to show", "name": "views", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/makePickerWithState.tsx", + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", "name": "WithViewsProps" }, "required": false, @@ -1134,7 +1119,7 @@ "description": "First view to show", "name": "openTo", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/makePickerWithState.tsx", + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", "name": "WithViewsProps" }, "required": false, @@ -1142,51 +1127,6 @@ "name": "\"hours\" | \"minutes\" | \"seconds\"" } }, - "minDateMessage": { - "defaultValue": { - "value": "'Date should not be before minimal date'" - }, - "description": "Error message, shown if date is less then minimal date", - "name": "minDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maxDateMessage": { - "defaultValue": { - "value": "'Date should not be after maximal date'" - }, - "description": "Error message, shown if date is more then maximal date", - "name": "maxDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "invalidDateMessage": { - "defaultValue": { - "value": "'Invalid Date Format'" - }, - "description": "Message, appearing when date cannot be parsed", - "name": "invalidDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "BaseValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, "value": { "defaultValue": null, "description": "Picker value", @@ -1197,7 +1137,7 @@ }, "required": true, "type": { - "name": "ParsableDate" + "name": "any" } }, "onChange": { @@ -1277,7 +1217,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "onAccept": { @@ -1381,7 +1321,7 @@ }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "ComponentClass, any> | FunctionComponent>" } }, "toolbarTitle": { @@ -1396,22 +1336,20 @@ }, "required": false, "type": { - "name": "string" + "name": "ReactNode" } }, - "strictCompareDates": { - "defaultValue": { - "value": "false" - }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar", + "name": "toolbarFormat", "parent": { "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "string" } }, "mask": { @@ -1577,7 +1515,7 @@ }, "required": false, "type": { - "name": "(value: ParsableDate, utils: MuiPickersAdapter) => string" + "name": "(value: any, utils: MuiPickersAdapter) => string" } }, "dateAdapter": { @@ -1592,9 +1530,7 @@ "type": { "name": "MuiPickersAdapter" } - } - }, - "DateTimePicker": { + }, "minDateMessage": { "defaultValue": { "value": "'Date should not be before minimal date'" @@ -1625,6 +1561,21 @@ "name": "ReactNode" } }, + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, "invalidDateMessage": { "defaultValue": { "value": "'Invalid Date Format'" @@ -1639,905 +1590,924 @@ "type": { "name": "ReactNode" } - }, - "value": { + } + }, + "DateTimePicker": { + "hideTabs": { "defaultValue": null, - "description": "Picker value", - "name": "value", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "description": "To show tabs", + "name": "hideTabs", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" }, - "required": true, + "required": false, "type": { - "name": "ParsableDate" + "name": "boolean" } }, - "onChange": { + "dateRangeIcon": { "defaultValue": null, - "description": "onChange callback", - "name": "onChange", + "description": "Date tab icon", + "name": "dateRangeIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" }, - "required": true, + "required": false, "type": { - "name": "(date: DateIOType, keyboardInputValue?: string) => void" + "name": "ReactNode" } }, - "autoOk": { - "defaultValue": { - "value": "false" - }, - "description": "Auto accept date on selection", - "name": "autoOk", + "timeIcon": { + "defaultValue": null, + "description": "Time tab icon", + "name": "timeIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "ReactNode" } }, - "inputFormat": { + "minDateTime": { "defaultValue": null, - "description": "Format string", - "name": "inputFormat", + "description": "Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`", + "name": "minDateTime", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" }, "required": false, "type": { - "name": "string" + "name": "any" } }, - "disabled": { + "maxDateTime": { "defaultValue": null, - "description": "Disable picker and text field", - "name": "disabled", + "description": "Minimal selectable moment of time with binding to date, to set max time in each day use `maxTime`", + "name": "maxDateTime", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "any" } }, - "readOnly": { + "toolbarFormat": { "defaultValue": null, - "description": "Make picker read only", - "name": "readOnly", + "description": "Date format, that is displaying in toolbar\nDate format, that is displaying in toolbar", + "name": "toolbarFormat", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "string" } }, - "defaultHighlight": { + "views": { "defaultValue": null, - "description": "Date that will be initially highlighted if null was passed", - "name": "defaultHighlight", + "description": "Array of views to show", + "name": "views", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" }, "required": false, "type": { - "name": "ParsableDate" + "name": "(\"year\" | \"date\" | \"month\" | \"hours\" | \"minutes\")[]" } }, - "onAccept": { + "openTo": { "defaultValue": null, - "description": "Callback fired when date is accepted", - "name": "onAccept", + "description": "First view to show", + "name": "openTo", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" }, "required": false, "type": { - "name": "(date: DateIOType) => void" + "name": "\"year\" | \"date\" | \"month\" | \"hours\" | \"minutes\"" } }, - "onError": { - "defaultValue": null, - "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", - "name": "onError", + "ampm": { + "defaultValue": { + "value": "true" + }, + "description": "12h/24h view for hour selection clock", + "name": "ampm", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { - "name": "(error: ReactNode, value: DateIOType) => void" + "name": "boolean" } }, - "onOpen": { - "defaultValue": null, - "description": "On open callback", - "name": "onOpen", + "minutesStep": { + "defaultValue": { + "value": "1" + }, + "description": "Step over minutes", + "name": "minutesStep", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { - "name": "() => void" + "name": "number" } }, - "onClose": { - "defaultValue": null, - "description": "On close callback", - "name": "onClose", + "ampmInClock": { + "defaultValue": { + "value": "false" + }, + "description": "Display ampm controls under the clock (instead of in the toolbar)", + "name": "ampmInClock", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { - "name": "() => void" + "name": "boolean" } }, - "open": { - "defaultValue": null, - "description": "Controlled picker open state", - "name": "open", + "allowKeyboardControl": { + "defaultValue": { + "value": "currentWrapper !== 'static'" + }, + "description": "Enables keyboard listener for moving between days in calendar", + "name": "allowKeyboardControl", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { "name": "boolean" } }, - "showToolbar": { + "minTime": { "defaultValue": null, - "description": "Show toolbar even in desktop mode", - "name": "showToolbar", + "description": "Min time, date part by default, will be ignored", + "name": "minTime", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { - "name": "boolean" + "name": "any" } }, - "orientation": { + "maxTime": { "defaultValue": null, - "description": "Force rendering in particular orientation", - "name": "orientation", + "description": "Max time, date part by default, will be ignored", + "name": "maxTime", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { - "name": "\"portrait\" | \"landscape\"" + "name": "any" } }, - "ToolbarComponent": { + "shouldDisableTime": { "defaultValue": null, - "description": "Component that will replace default toolbar renderer", - "name": "ToolbarComponent", + "description": "Dynamically check if time is disabled or not", + "name": "shouldDisableTime", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "(timeValue: number, clockType: \"hours\" | \"minutes\" | \"seconds\") => boolean" } }, - "toolbarTitle": { + "disableTimeValidationIgnoreDatePart": { + "defaultValue": null, + "description": "Do not ignore date part when validating min/max time", + "name": "disableTimeValidationIgnoreDatePart", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableHighlightToday": { "defaultValue": { - "value": "\"SELECT DATE\"" + "value": "false" }, - "description": "Mobile picker title, displaying in the toolbar", - "name": "toolbarTitle", + "description": "Disable highlighting today date with a circle", + "name": "disableHighlightToday", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" }, "required": false, "type": { - "name": "string" + "name": "boolean" } }, - "strictCompareDates": { + "showDaysOutsideCurrentMonth": { "defaultValue": { "value": "false" }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", + "description": "Display disabled dates outside the current month", + "name": "showDaysOutsideCurrentMonth", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" }, "required": false, "type": { "name": "boolean" } }, - "mask": { + "leftArrowIcon": { "defaultValue": null, - "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", - "name": "mask", + "description": "Left arrow icon", + "name": "leftArrowIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "string" + "name": "ReactNode" } }, - "TextFieldComponent": { + "rightArrowIcon": { "defaultValue": null, - "description": "Override input component", - "name": "TextFieldComponent", + "description": "Right arrow icon", + "name": "rightArrowIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "ComponentClass | FunctionComponent" + "name": "ReactNode" } }, - "emptyInputText": { - "defaultValue": { - "value": "' '" - }, - "description": "Message displaying in read-only text field when null passed", - "name": "emptyInputText", + "leftArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to left arrow button", + "name": "leftArrowButtonProps", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "string" + "name": "Partial" } }, - "keyboardIcon": { + "rightArrowButtonProps": { "defaultValue": null, - "description": "Icon displaying for open picker button", - "name": "keyboardIcon", + "description": "Props to pass to right arrow button", + "name": "rightArrowButtonProps", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "Partial" } }, - "maskChar": { - "defaultValue": { - "value": "'_'" - }, - "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", - "name": "maskChar", + "leftArrowButtonText": { + "defaultValue": null, + "description": "Left arrow icon aria-label text", + "name": "leftArrowButtonText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { "name": "string" } }, - "acceptRegex": { - "defaultValue": { - "value": "/\\dap/gi" - }, - "description": "Regular expression to detect \"accepted\" symbols", - "name": "acceptRegex", + "rightArrowButtonText": { + "defaultValue": null, + "description": "Right arrow icon aria-label text", + "name": "rightArrowButtonText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "RegExp" + "name": "string" } }, - "InputAdornmentProps": { + "getViewSwitchingButtonText": { "defaultValue": null, - "description": "Props to pass to keyboard input adornment", - "name": "InputAdornmentProps", + "description": "Get aria-label text for switching between views button", + "name": "getViewSwitchingButtonText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", + "name": "CalendarHeaderProps" }, "required": false, "type": { - "name": "Partial" + "name": "(currentView: \"year\" | \"date\" | \"month\") => string" } }, - "KeyboardButtonProps": { - "defaultValue": null, - "description": "Props to pass to keyboard adornment button", - "name": "KeyboardButtonProps", + "minDate": { + "defaultValue": { + "value": "Date(1900-01-01)" + }, + "description": "Min selectable date", + "name": "minDate", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "Partial" + "name": "any" } }, - "rifmFormatter": { - "defaultValue": null, - "description": "Custom formatter to be passed into Rifm component", - "name": "rifmFormatter", + "maxDate": { + "defaultValue": { + "value": "Date(2100-01-01)" + }, + "description": "Max selectable date", + "name": "maxDate", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "(str: string) => string" + "name": "any" } }, - "hideOpenPickerButton": { + "disablePast": { "defaultValue": { "value": "false" }, - "description": "Do not render open picker button (renders only text field with validation)", - "name": "hideOpenPickerButton", + "description": "Disable past dates", + "name": "disablePast", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { "name": "boolean" } }, - "disableMaskedInput": { + "disableFuture": { "defaultValue": { "value": "false" }, - "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", - "name": "disableMaskedInput", + "description": "Disable future dates", + "name": "disableFuture", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { "name": "boolean" } }, - "getOpenDialogAriaText": { + "onMonthChange": { "defaultValue": null, - "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", - "name": "getOpenDialogAriaText", + "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", + "name": "onMonthChange", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "(value: ParsableDate, utils: MuiPickersAdapter) => string" + "name": "(date: DateIOType) => void | Promise" } }, - "hideTabs": { + "shouldDisableDate": { "defaultValue": null, - "description": "To show tabs", - "name": "hideTabs", + "description": "Disable specific date", + "name": "shouldDisableDate", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerViewsProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "boolean" + "name": "(day: DateIOType) => boolean" } }, - "dateRangeIcon": { + "onYearChange": { "defaultValue": null, - "description": "Date tab icon", - "name": "dateRangeIcon", + "description": "Callback firing on year change", + "name": "onYearChange", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerViewsProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "(date: DateIOType) => void" } }, - "timeIcon": { + "renderDay": { "defaultValue": null, - "description": "Time tab icon", - "name": "timeIcon", + "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", + "name": "renderDay", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerViewsProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" } }, - "minDateTime": { + "loadingIndicator": { "defaultValue": null, - "description": "Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`", - "name": "minDateTime", + "description": "Custom loading indicator", + "name": "loadingIndicator", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerViewsProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "ParsableDate" + "name": "Element" } }, - "maxDateTime": { + "value": { "defaultValue": null, - "description": "Minimal selectable moment of time with binding to date, to set max time in each day use `maxTime`", - "name": "maxDateTime", + "description": "Picker value", + "name": "value", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerViewsProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { - "name": "ParsableDate" + "name": "any" } }, - "toolbarFormat": { + "onChange": { "defaultValue": null, - "description": "Date format, that is displaying in toolbar", - "name": "toolbarFormat", + "description": "onChange callback", + "name": "onChange", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerViewsProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { - "name": "string" + "name": "(date: DateIOType, keyboardInputValue?: string) => void" } }, - "ampm": { + "autoOk": { "defaultValue": { - "value": "true" + "value": "false" }, - "description": "12h/24h view for hour selection clock", - "name": "ampm", + "description": "Auto accept date on selection", + "name": "autoOk", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "boolean" } }, - "minutesStep": { - "defaultValue": { - "value": "1" - }, - "description": "Step over minutes", - "name": "minutesStep", + "inputFormat": { + "defaultValue": null, + "description": "Format string", + "name": "inputFormat", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "number" + "name": "string" } }, - "ampmInClock": { - "defaultValue": { - "value": "false" - }, - "description": "Display ampm controls under the clock (instead of in the toolbar)", - "name": "ampmInClock", + "disabled": { + "defaultValue": null, + "description": "Disable picker and text field", + "name": "disabled", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "boolean" } }, - "allowKeyboardControl": { - "defaultValue": { - "value": "currentWrapper !== 'static'\ncurrentWrapper !== 'static'" - }, - "description": "Enables keyboard listener for moving between days in calendar\nEnables keyboard listener for moving between days in calendar", - "name": "allowKeyboardControl", + "readOnly": { + "defaultValue": null, + "description": "Make picker read only", + "name": "readOnly", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "boolean" } }, - "minTime": { + "defaultHighlight": { "defaultValue": null, - "description": "Min time, date part by default, will be ignored", - "name": "minTime", + "description": "Date that will be initially highlighted if null was passed", + "name": "defaultHighlight", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, - "maxTime": { + "onAccept": { "defaultValue": null, - "description": "Max time, date part by default, will be ignored", - "name": "maxTime", + "description": "Callback fired when date is accepted", + "name": "onAccept", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ParsableDate" + "name": "(date: DateIOType) => void" } }, - "shouldDisableTime": { + "onError": { "defaultValue": null, - "description": "Dynamically check if time is disabled or not", - "name": "shouldDisableTime", + "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", + "name": "onError", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "(timeValue: number, clockType: \"hours\" | \"minutes\" | \"seconds\") => boolean" + "name": "(error: ReactNode, value: DateIOType) => void" } }, - "disableTimeValidationIgnoreDatePart": { + "onOpen": { "defaultValue": null, - "description": "Do not ignore date part when validating min/max time", - "name": "disableTimeValidationIgnoreDatePart", + "description": "On open callback", + "name": "onOpen", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "() => void" } }, - "onYearChange": { + "onClose": { "defaultValue": null, - "description": "Callback firing on year change", - "name": "onYearChange", + "description": "On close callback", + "name": "onClose", "parent": { - "fileName": "material-ui-pickers/lib/src/DatePicker/DatePicker.tsx", - "name": "BaseDatePickerProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "(date: DateIOType) => void" + "name": "() => void" } }, - "disableHighlightToday": { - "defaultValue": { - "value": "false" - }, - "description": "Disable highlighting today date with a circle", - "name": "disableHighlightToday", + "open": { + "defaultValue": null, + "description": "Controlled picker open state", + "name": "open", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "boolean" } }, - "showDaysOutsideCurrentMonth": { - "defaultValue": { - "value": "false" - }, - "description": "Display disabled dates outside the current month", - "name": "showDaysOutsideCurrentMonth", + "showToolbar": { + "defaultValue": null, + "description": "Show toolbar even in desktop mode", + "name": "showToolbar", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "boolean" } }, - "leftArrowIcon": { + "orientation": { "defaultValue": null, - "description": "Left arrow icon", - "name": "leftArrowIcon", + "description": "Force rendering in particular orientation", + "name": "orientation", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "\"portrait\" | \"landscape\"" } }, - "rightArrowIcon": { + "ToolbarComponent": { "defaultValue": null, - "description": "Right arrow icon", - "name": "rightArrowIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "description": "Component that will replace default toolbar renderer", + "name": "ToolbarComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "ComponentClass, any> | FunctionComponent>" } }, - "leftArrowButtonProps": { - "defaultValue": null, - "description": "Props to pass to left arrow button", - "name": "leftArrowButtonProps", + "toolbarTitle": { + "defaultValue": { + "value": "\"SELECT DATE\"" + }, + "description": "Mobile picker title, displaying in the toolbar", + "name": "toolbarTitle", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "Partial" + "name": "ReactNode" } }, - "rightArrowButtonProps": { + "mask": { "defaultValue": null, - "description": "Props to pass to right arrow button", - "name": "rightArrowButtonProps", + "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", + "name": "mask", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "Partial" + "name": "string" } }, - "leftArrowButtonText": { + "TextFieldComponent": { "defaultValue": null, - "description": "Left arrow icon aria-label text", - "name": "leftArrowButtonText", + "description": "Override input component", + "name": "TextFieldComponent", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "string" + "name": "ComponentClass | FunctionComponent" } }, - "rightArrowButtonText": { - "defaultValue": null, - "description": "Right arrow icon aria-label text", - "name": "rightArrowButtonText", + "emptyInputText": { + "defaultValue": { + "value": "' '" + }, + "description": "Message displaying in read-only text field when null passed", + "name": "emptyInputText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { "name": "string" } }, - "getViewSwitchingButtonText": { + "keyboardIcon": { "defaultValue": null, - "description": "Get aria-label text for switching between views button", - "name": "getViewSwitchingButtonText", + "description": "Icon displaying for open picker button", + "name": "keyboardIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", - "name": "CalendarHeaderProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(currentView: DatePickerView) => string" + "name": "ReactNode" } }, - "minDate": { + "maskChar": { "defaultValue": { - "value": "Date(1900-01-01)" + "value": "'_'" }, - "description": "Min selectable date", - "name": "minDate", + "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", + "name": "maskChar", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "ParsableDate" + "name": "string" } }, - "maxDate": { + "acceptRegex": { "defaultValue": { - "value": "Date(2100-01-01)" + "value": "/\\dap/gi" }, - "description": "Max selectable date", - "name": "maxDate", + "description": "Regular expression to detect \"accepted\" symbols", + "name": "acceptRegex", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "ParsableDate" + "name": "RegExp" } }, - "disablePast": { - "defaultValue": { - "value": "false" - }, - "description": "Disable past dates", - "name": "disablePast", + "InputAdornmentProps": { + "defaultValue": null, + "description": "Props to pass to keyboard input adornment", + "name": "InputAdornmentProps", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "boolean" + "name": "Partial" } }, - "disableFuture": { - "defaultValue": { - "value": "false" - }, - "description": "Disable future dates", - "name": "disableFuture", + "KeyboardButtonProps": { + "defaultValue": null, + "description": "Props to pass to keyboard adornment button", + "name": "KeyboardButtonProps", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "boolean" + "name": "Partial" } }, - "onMonthChange": { + "rifmFormatter": { "defaultValue": null, - "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", - "name": "onMonthChange", + "description": "Custom formatter to be passed into Rifm component", + "name": "rifmFormatter", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(date: DateIOType) => void | Promise" + "name": "(str: string) => string" } }, - "reduceAnimations": { + "hideOpenPickerButton": { "defaultValue": { - "value": "/(android)/i.test(navigator.userAgent)" + "value": "false" }, - "description": "Do not show heavy animations, significantly improves performance on slow devices", - "name": "reduceAnimations", + "description": "Do not render open picker button (renders only text field with validation)", + "name": "hideOpenPickerButton", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { "name": "boolean" } }, - "shouldDisableDate": { - "defaultValue": null, - "description": "Disable specific date", - "name": "shouldDisableDate", + "disableMaskedInput": { + "defaultValue": { + "value": "false" + }, + "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", + "name": "disableMaskedInput", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(day: DateIOType) => boolean" + "name": "boolean" } }, - "renderDay": { + "getOpenDialogAriaText": { "defaultValue": null, - "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", - "name": "renderDay", + "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", + "name": "getOpenDialogAriaText", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(day: DateIOType, selectedDate: DateIOType, DayComponentProps: DayProps) => Element" + "name": "(value: any, utils: MuiPickersAdapter) => string" } }, - "loadingIndicator": { + "dateAdapter": { "defaultValue": null, - "description": "Custom loading indicator", - "name": "loadingIndicator", + "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" }, "required": false, "type": { - "name": "Element" + "name": "MuiPickersAdapter" } }, - "views": { - "defaultValue": null, - "description": "Array of views to show", - "name": "views", + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/makePickerWithState.tsx", - "name": "WithViewsProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "(\"date\" | \"year\" | \"month\" | \"hours\" | \"minutes\")[]" + "name": "ReactNode" } }, - "openTo": { - "defaultValue": null, - "description": "First view to show", - "name": "openTo", + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/makePickerWithState.tsx", - "name": "WithViewsProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "\"date\" | \"year\" | \"month\" | \"hours\" | \"minutes\"" + "name": "ReactNode" } }, - "dateAdapter": { - "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", - "name": "dateAdapter", + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", - "name": "WithDateAdapterProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "MuiPickersAdapter" + "name": "boolean" } - } - }, - "Calendar": { - "date": { - "defaultValue": null, - "description": "Calendar Date", - "name": "date", + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" }, - "required": true, + "required": false, "type": { - "name": "DateIOType" + "name": "ReactNode" } - }, + } + }, + "Calendar": { "onChange": { "defaultValue": null, "description": "Calendar onChange", @@ -2591,7 +2561,7 @@ }, "required": false, "type": { - "name": "(day: DateIOType, selectedDate: DateIOType, DayComponentProps: DayProps) => Element" + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" } }, "allowKeyboardControl": { @@ -2995,7 +2965,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "maxTime": { @@ -3008,7 +2978,7 @@ }, "required": false, "type": { - "name": "ParsableDate" + "name": "any" } }, "shouldDisableTime": { diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx new file mode 100644 index 000000000..b00111c39 --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -0,0 +1,80 @@ +import * as React from 'react'; +import { DateRange, RangeInput } from './RangeTypes'; +import { MaterialUiPickersDate } from '../typings/date'; +import { BasePickerProps } from '../typings/BasePicker'; +import { DesktopWrapper } from '../wrappers/DesktopWrapper'; +import { DateRangePickerInput } from './DateRangePickerInput'; +import { parsePickerInputValue } from '../_helpers/date-utils'; +import { usePickerState } from '../_shared/hooks/usePickerState'; +import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; +import { AllSharedPickerProps } from '../Picker/SharedPickerProps'; +import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; +import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; +import { DateRangePickerCalendar, DateRangePickerCalendarProps } from './DateRangePickerCalendar'; + +export function parseRangeInputValue( + now: MaterialUiPickersDate, + utils: MuiPickersAdapter, + { value = [null, null], defaultHighlight }: BasePickerProps +) { + return value.map(date => + parsePickerInputValue(now, utils, { value: date, defaultHighlight }) + ) as DateRange; +} + +export function makeRangePicker(Wrapper: TWrapper) { + const WrapperComponent = makeWrapperComponent(Wrapper, { + KeyboardDateInputComponent: DateRangePickerInput, + PureDateInputComponent: DateRangePickerInput, + }); + + function RangePickerWithStateAndWrapper({ + calendars, + minDate, + maxDate, + disablePast, + disableFuture, + shouldDisableDate, + showDaysOutsideCurrentMonth, + onMonthChange, + disableHighlightToday, + reduceAnimations, + ...other + }: DateRangePickerCalendarProps & + AllSharedPickerProps & + ExtendWrapper) { + const utils = useUtils(); + const { pickerProps, inputProps, wrapperProps } = usePickerState(other, { + parseInput: parseRangeInputValue, + areValuesEqual: (a, b) => utils.isEqual(a[0], b[0]) && utils.isEqual(a[1], b[1]), + validateInput: () => undefined, + }); + + return ( + + + + ); + } + + RangePickerWithStateAndWrapper.defaultProps = { + inputFormat: 'MM', + }; + + return RangePickerWithStateAndWrapper; +} + +export const DateRangePicker = makeRangePicker(DesktopWrapper); diff --git a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx new file mode 100644 index 000000000..6df0b31a9 --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePickerCalendar.tsx @@ -0,0 +1,89 @@ +import * as React from 'react'; +import { RangeInput, DateRange } from './RangeTypes'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { MaterialUiPickersDate } from '../typings/date'; +import { useParsedDate } from '../_shared/hooks/useParsedDate'; +import { SharedPickerProps } from '../Picker/SharedPickerProps'; +import { useCalendarState } from '../views/Calendar/useCalendarState'; +import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; +import { ExportedCalendarViewProps, defaultReduceAnimations } from '../views/Calendar/CalendarView'; +import { + DesktopDateRangeCalendar, + ExportedDesktopDateRangeCalendarProps, +} from './DesktopDateRangePicker'; + +type BaseCalendarPropsToReuse = Omit; + +export interface DateRangePickerCalendarProps + extends BaseCalendarPropsToReuse, + ExportedDesktopDateRangeCalendarProps, + SharedPickerProps { + reduceAnimations?: boolean; +} + +export const DateRangePickerCalendar: React.FC = ({ + date, + calendars, + minDate: unparsedMinDate = new Date('1900-01-01'), + maxDate: unparsedMaxDate = new Date('2100-01-01'), + disableFuture, + disablePast, + shouldDisableDate, + disableHighlightToday, + onMonthChange, + onDateChange, + reduceAnimations = defaultReduceAnimations, +}) => { + const utils = useUtils(); + const wrapperVariant = React.useContext(WrapperVariantContext); + const minDate = useParsedDate(unparsedMinDate)!; + const maxDate = useParsedDate(unparsedMaxDate)!; + + const [start, end] = date!; + const { + changeMonth, + calendarState, + isDateDisabled, + onMonthSwitchingAnimationEnd, + changeFocusedDay, + } = useCalendarState({ + date: start, + minDate, + maxDate, + reduceAnimations, + disablePast, + disableFuture, + onMonthChange, + shouldDisableDate, + }); + + const handleChange = React.useCallback( + (date: MaterialUiPickersDate) => { + onDateChange([date, end], wrapperVariant, false); + }, + [end, onDateChange, wrapperVariant] + ); + + switch (wrapperVariant) { + case 'desktop': { + return ( + + ); + } + + default: { + throw new Error('Only desktop wrapper supported for DateRangePicker'); + } + } +}; diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx new file mode 100644 index 000000000..8da7500bb --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import KeyboardDateInput from '../_shared/KeyboardDateInput'; +import { TextField } from '@material-ui/core'; +import { DateInputProps } from '../_shared/PureDateInput'; +import { RangeInput, DateRange } from './DateRangePicker'; + +export const DateRangePickerInput: React.FC> = ({ + rawValue, + onChange, + ...other +}) => { + console.log(rawValue); + const [start, end] = rawValue; + return ( + <> + + + + ); +}; diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx new file mode 100644 index 000000000..a2541b619 --- /dev/null +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -0,0 +1,64 @@ +import * as React from 'react'; +import { makeStyles } from '@material-ui/core'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { MaterialUiPickersDate } from '../typings/date'; +import { ArrowSwitcher } from '../_shared/ArrowSwitcher'; +import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; + +export interface ExportedDesktopDateRangeCalendarProps { + calendars?: 1 | 2; +} + +interface DesktopDateRangeCalendarProps + extends ExportedDesktopDateRangeCalendarProps, + CalendarProps { + changeMonth: (date: MaterialUiPickersDate) => void; +} + +export const useStyles = makeStyles( + theme => ({ + dateRangeContainer: { + display: 'flex', + flexDirection: 'row', + }, + }), + { name: 'MuiPickersDesktopDateRangeCalendar' } +); + +export const DesktopDateRangeCalendar: React.FC = ({ + calendars = 2, + changeMonth, + ...CalendarProps +}) => { + const utils = useUtils(); + const classes = useStyles(); + + return ( +
+ {new Array(calendars).fill(0).map((_, index) => { + const monthOnIteration = utils.setMonth( + CalendarProps.currentMonth, + utils.getMonth(CalendarProps.currentMonth) + index + ); + + console.log(monthOnIteration); + + return ( +
+ changeMonth(utils.getPreviousMonth(CalendarProps.currentMonth))} + onRightClick={() => changeMonth(utils.getNextMonth(CalendarProps.currentMonth))} + /> + + +
+ ); + })} +
+ ); +}; diff --git a/lib/src/DateRangePicker/RangeTypes.ts b/lib/src/DateRangePicker/RangeTypes.ts new file mode 100644 index 000000000..0379a21d3 --- /dev/null +++ b/lib/src/DateRangePicker/RangeTypes.ts @@ -0,0 +1,5 @@ +import { ParsableDate } from '../constants/prop-types'; +import { MaterialUiPickersDate } from '../typings/date'; + +export type RangeInput = [ParsableDate, ParsableDate]; +export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index 558d01728..73550ea7d 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -1,20 +1,18 @@ import * as React from 'react'; import clsx from 'clsx'; -import { WrapperVariant } from '../wrappers/Wrapper'; import { useViews } from '../_shared/hooks/useViews'; import { makeStyles } from '@material-ui/core/styles'; import { DateTimePickerView } from '../DateTimePicker'; import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; import { MaterialUiPickersDate } from '../typings/date'; -import { DateInputProps } from '../_shared/PureDateInput'; import { DatePickerView } from '../DatePicker/DatePicker'; import { useIsLandscape } from '../_shared/hooks/useIsLandscape'; -import { WithViewsProps, AnyPickerView } from './SharedPickerProps'; import { DIALOG_WIDTH, VIEW_HEIGHT } from '../constants/dimensions'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; import { ClockView, ExportedClockViewProps } from '../views/Clock/ClockView'; +import { WithViewsProps, AnyPickerView, SharedPickerProps } from './SharedPickerProps'; import { CalendarView, ExportedCalendarViewProps } from '../views/Calendar/CalendarView'; type CalendarAndClockProps = ExportedCalendarViewProps & ExportedClockViewProps; @@ -50,21 +48,11 @@ export interface ExportedPickerProps timeIcon?: React.ReactNode; } -export interface PickerProps< +export type PickerProps< TView extends AnyPickerView, TInputValue = ParsableDate, TDateValue = MaterialUiPickersDate -> extends ExportedPickerProps { - isMobileKeyboardViewOpen: boolean; - toggleMobileKeyboardView: () => void; - DateInputProps: DateInputProps; - date: TDateValue | null; - onDateChange: ( - date: TDateValue, - currentVariant: WrapperVariant, - isFinish?: boolean | symbol - ) => void; -} +> = ExportedPickerProps & SharedPickerProps; export const useStyles = makeStyles( { diff --git a/lib/src/Picker/SharedPickerProps.tsx b/lib/src/Picker/SharedPickerProps.tsx index 53b57f92b..d57fc2f0b 100644 --- a/lib/src/Picker/SharedPickerProps.tsx +++ b/lib/src/Picker/SharedPickerProps.tsx @@ -1,16 +1,34 @@ +import { WrapperVariant } from '../wrappers/Wrapper'; import { DateTimePickerView } from '../DateTimePicker'; +import { ParsableDate } from '../constants/prop-types'; import { BasePickerProps } from '../typings/BasePicker'; -import { ExportedDateInputProps } from '../_shared/PureDateInput'; +import { MaterialUiPickersDate } from '../typings/date'; import { DateValidationProps } from '../_helpers/text-field-helper'; import { WithDateAdapterProps } from '../_shared/withDateAdapterProp'; +import { ExportedDateInputProps, DateInputProps } from '../_shared/PureDateInput'; export type AnyPickerView = DateTimePickerView; -export type AllSharedPickerProps = WithDateAdapterProps & - BasePickerProps & - ExportedDateInputProps & +export type AllSharedPickerProps< + TInputValue = ParsableDate, + TDateValue = MaterialUiPickersDate +> = BasePickerProps & + ExportedDateInputProps & + WithDateAdapterProps & DateValidationProps; +export interface SharedPickerProps { + isMobileKeyboardViewOpen: boolean; + toggleMobileKeyboardView: () => void; + DateInputProps: DateInputProps; + date: TDateValue | null; + onDateChange: ( + date: TDateValue, + currentVariant: WrapperVariant, + isFinish?: boolean | symbol + ) => void; +} + export interface WithViewsProps { /** * Array of views to show @@ -19,5 +37,3 @@ export interface WithViewsProps { /** First view to show */ openTo?: T; } - -export type WithDateInputProps = DateValidationProps & BasePickerProps & ExportedDateInputProps; diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index cf77b3dc7..654b3937a 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { useUtils } from '../_shared/hooks/useUtils'; import { ParsableDate } from '../constants/prop-types'; import { MaterialUiPickersDate } from '../typings/date'; import { PureDateInput } from '../_shared/PureDateInput'; @@ -29,13 +30,18 @@ export function makePickerWithStateAndWrapper< }); function PickerWithState(props: T & AllSharedPickerProps & ExtendWrapper) { + const utils = useUtils(); const defaultProps = useDefaultProps(props); const allProps = { ...defaultProps, ...props }; const { pickerProps, inputProps, wrapperProps } = usePickerState< ParsableDate, MaterialUiPickersDate - >(allProps, parsePickerInputValue, validateDateValue); + >(allProps, { + parseInput: parsePickerInputValue, + validateInput: validateDateValue, + areValuesEqual: utils.isEqual, + }); const { allowKeyboardControl, diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index f1b24d313..15ccf2b12 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -67,8 +67,8 @@ export interface DateInputProps = Omit< + DateInputProps, | 'openPicker' | 'inputValue' | 'onChange' diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 49976b2c0..5c1766ed2 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -7,18 +7,21 @@ import { useCallback, useDebugValue, useEffect, useMemo, useState } from 'react' export const FORCE_FINISH_PICKER = Symbol('Force closing picker, used for accessibility '); -export function usePickerState( - props: BasePickerProps, - parseInputValue: ( - now: MaterialUiPickersDate, - utils: MuiPickersAdapter, - props: BasePickerProps - ) => TOutput | null, - validateInputValue: ( - value: TInput, - utils: MuiPickersAdapter, - props: BasePickerProps - ) => React.ReactNode | undefined +export function usePickerState( + props: BasePickerProps, + valueManager: { + parseInput: ( + now: MaterialUiPickersDate, + utils: MuiPickersAdapter, + props: BasePickerProps + ) => TDateValue | null; + validateInput: ( + value: TInput, + utils: MuiPickersAdapter, + props: BasePickerProps + ) => React.ReactNode | undefined; + areValuesEqual: (valueLeft: TDateValue | null, valueRight: TDateValue | null) => boolean; + } ) { const { autoOk, inputFormat, disabled, readOnly, onAccept, onChange, onError, value } = props; @@ -28,7 +31,7 @@ export function usePickerState( const now = useNow(); const utils = useUtils(); - const date = parseInputValue(now, utils, props); + const date = valueManager.parseInput(now, utils, props); const [pickerDate, setPickerDate] = useState(date); // Mobile keyboard view is a special case. @@ -38,13 +41,13 @@ export function usePickerState( useEffect(() => { // if value was changed in closed state or from mobile keyboard view - treat it as accepted - if ((!isOpen || isMobileKeyboardViewOpen) && !utils.isEqual(pickerDate, date)) { + if ((!isOpen || isMobileKeyboardViewOpen) && !valueManager.areValuesEqual(pickerDate, date)) { setPickerDate(date); } - }, [date, isMobileKeyboardViewOpen, isOpen, pickerDate, utils]); + }, [date, isMobileKeyboardViewOpen, isOpen, pickerDate, utils, valueManager]); const acceptDate = useCallback( - (acceptedDate: TOutput | null, needClosePicker: boolean) => { + (acceptedDate: TDateValue | null, needClosePicker: boolean) => { onChange(acceptedDate); if (needClosePicker) { @@ -87,7 +90,7 @@ export function usePickerState( setMobileKeyboardViewOpen(!isMobileKeyboardViewOpen); }, onDateChange: ( - newDate: TOutput, + newDate: TDateValue, currentVariant: WrapperVariant, isFinish: boolean | symbol = true ) => { @@ -110,7 +113,7 @@ export function usePickerState( [acceptDate, autoOk, isMobileKeyboardViewOpen, pickerDate] ); - const validationError = validateInputValue(value, utils, props); + const validationError = valueManager.validateInput(value, utils, props); useEffect(() => { if (onError) { onError(validationError, value); diff --git a/lib/src/index.ts b/lib/src/index.ts index 53d9eceb3..890085817 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -6,6 +6,8 @@ export * from './TimePicker'; export * from './DateTimePicker'; +export * from './DateRangePicker/DateRangePicker'; + export { Calendar } from './views/Calendar/Calendar'; export * from './views/Calendar/CalendarView'; diff --git a/lib/src/typings/BasePicker.tsx b/lib/src/typings/BasePicker.tsx index 853437d60..56743c14d 100644 --- a/lib/src/typings/BasePicker.tsx +++ b/lib/src/typings/BasePicker.tsx @@ -2,10 +2,7 @@ import { MaterialUiPickersDate } from './date'; import { ParsableDate } from '../constants/prop-types'; import { ToolbarComponentProps } from '../Picker/Picker'; -export interface BasePickerProps< - TInputValue = ParsableDate, - TDateValue = MaterialUiPickersDate | null -> { +export interface BasePickerProps { /** Picker value */ value: TInputValue; /** onChange callback @DateIOType */ diff --git a/lib/src/typings/overrides.ts b/lib/src/typings/overrides.ts index 37e20d45c..fa1d8227a 100644 --- a/lib/src/typings/overrides.ts +++ b/lib/src/typings/overrides.ts @@ -61,4 +61,8 @@ export interface MuiPickersOverrides { MuiPickersDatePickerRoot?: Classes; MuiPickerDTToolbar?: Classes; MuiBasePickerStyles?: Classes; + // consider using inline import type notation + MuiPickersDesktopDateRangeCalendar?: Classes< + typeof import('../DateRangePicker/DesktopDateRangePicker').useStyles + >; } diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index d41a1e85c..904e41e8d 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import clsx from 'clsx'; import DayWrapper from './DayWrapper'; import SlideTransition, { SlideDirection } from './SlideTransition'; import { Day, DayProps } from './Day'; @@ -11,8 +12,6 @@ import { useGlobalKeyDown, keycode } from '../../_shared/hooks/useKeyDown'; export interface ExportedCalendarProps extends Pick { - /** Calendar Date @DateIOType */ - date: MaterialUiPickersDate; /** Calendar onChange */ onChange: PickerOnChangeFn; /** @@ -28,7 +27,7 @@ export interface ExportedCalendarProps /** Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day) @DateIOType */ renderDay?: ( day: MaterialUiPickersDate, - selectedDate: MaterialUiPickersDate, + selectedDates: MaterialUiPickersDate[], DayComponentProps: DayProps ) => JSX.Element; /** @@ -41,6 +40,7 @@ export interface ExportedCalendarProps } export interface CalendarProps extends ExportedCalendarProps { + date: MaterialUiPickersDate | MaterialUiPickersDate[]; minDate?: MaterialUiPickersDate; maxDate?: MaterialUiPickersDate; isDateDisabled: (day: MaterialUiPickersDate) => boolean; @@ -51,12 +51,16 @@ export interface CalendarProps extends ExportedCalendarProps { changeFocusedDay: (newFocusedDay: MaterialUiPickersDate) => void; isMonthSwitchingAnimating: boolean; onMonthSwitchingAnimationEnd: () => void; + allowOverflowingSlideTransition?: boolean; } export const useStyles = makeStyles(theme => ({ transitionContainer: { minHeight: 36 * 6 + 20, }, + transitionContainerOverflowAllowed: { + overflowX: 'visible', + }, progressContainer: { width: '100%', height: '100%', @@ -111,6 +115,7 @@ export const Calendar: React.FC = ({ isDateDisabled, disableHighlightToday, showDaysOutsideCurrentMonth, + allowOverflowingSlideTransition, }) => { const now = useNow(); const utils = useUtils(); @@ -119,16 +124,17 @@ export const Calendar: React.FC = ({ const handleDaySelect = React.useCallback( (day: MaterialUiPickersDate, isFinish: boolean | symbol = true) => { - onChange(utils.mergeDateAndTime(day, date), isFinish); + onChange(Array.isArray(date) ? day : utils.mergeDateAndTime(day, date), isFinish); }, [date, onChange, utils] ); + const initialDate = Array.isArray(date) ? date[0] : date; React.useEffect(() => { - if (isDateDisabled(date)) { + if (isDateDisabled(initialDate)) { const closestEnabledDate = findClosestEnabledDate({ - date, utils, + date: initialDate, minDate: utils.date(minDate), maxDate: utils.date(maxDate), disablePast: Boolean(disablePast), @@ -140,7 +146,7 @@ export const Calendar: React.FC = ({ } }, []); // eslint-disable-line - const nowFocusedDay = focusedDay || date; + const nowFocusedDay = focusedDay || initialDate; useGlobalKeyDown(Boolean(allowKeyboardControl), { [keycode.ArrowUp]: () => changeFocusedDay(utils.addDays(nowFocusedDay, -7)), [keycode.ArrowDown]: () => changeFocusedDay(utils.addDays(nowFocusedDay, 7)), @@ -154,9 +160,12 @@ export const Calendar: React.FC = ({ [keycode.PageDown]: () => changeFocusedDay(utils.getPreviousMonth(nowFocusedDay)), }); - const selectedDate = utils.startOfDay(date); const currentMonthNumber = utils.getMonth(currentMonth); + const selectedDates = (Array.isArray(date) ? date : [date]) + .filter(Boolean) + .map(selectedDateItem => utils.startOfDay(selectedDateItem)); + console.log(utils.getWeekArray(currentMonth)); return ( <>
@@ -176,7 +185,9 @@ export const Calendar: React.FC = ({ reduceAnimations={reduceAnimations} slideDirection={slideDirection} transKey={currentMonthNumber} - className={classes.transitionContainer} + className={clsx(classes.transitionContainer, { + [classes.transitionContainerOverflowAllowed]: allowOverflowingSlideTransition, + })} >
{utils.getWeekArray(currentMonth).map(week => ( @@ -195,7 +206,7 @@ export const Calendar: React.FC = ({ isToday: utils.isSameDay(day, now), hidden: !isDayInCurrentMonth, isInCurrentMonth: isDayInCurrentMonth, - selected: utils.isSameDay(selectedDate, day), + selected: selectedDates.some(selectedDate => utils.isSameDay(selectedDate, day)), disableHighlightToday, showDaysOutsideCurrentMonth, focusable: @@ -204,7 +215,7 @@ export const Calendar: React.FC = ({ }; let dayComponent = renderDay ? ( - renderDay(day, selectedDate, dayProps) + renderDay(day, selectedDates, dayProps) ) : ( ); diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index 11253f5f7..d5bed725b 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -1,15 +1,13 @@ import * as React from 'react'; -import { IUtils } from '@date-io/core/IUtils'; import { YearSelection } from './YearSelection'; import { MonthSelection } from './MonthSelection'; import { DatePickerView } from '../../DatePicker'; -import { SlideDirection } from './SlideTransition'; +import { useCalendarState } from './useCalendarState'; import { VIEW_HEIGHT } from '../../constants/dimensions'; import { ParsableDate } from '../../constants/prop-types'; import { MaterialUiPickersDate } from '../../typings/date'; import { FadeTransitionGroup } from './FadeTransitionGroup'; import { Calendar, ExportedCalendarProps } from './Calendar'; -import { useUtils, useNow } from '../../_shared/hooks/useUtils'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; import { useParsedDate } from '../../_shared/hooks/useParsedDate'; import { CalendarHeader, CalendarHeaderProps } from './CalendarHeader'; @@ -45,10 +43,6 @@ export interface CalendarViewProps extends ExportedCalendarProps, PublicCalendar * @default Date(2100-01-01) */ maxDate?: ParsableDate; - /** Do not show heavy animations, significantly improves performance on slow devices - * @default /(android)/i.test(navigator.userAgent) - */ - reduceAnimations?: boolean; /** Disable specific date @DateIOType */ shouldDisableDate?: (day: MaterialUiPickersDate) => boolean; /** Callback firing on year change @DateIOType */ @@ -60,76 +54,6 @@ export type ExportedCalendarViewProps = Omit< 'date' | 'view' | 'views' | 'onChange' | 'changeView' | 'slideDirection' | 'currentMonth' >; -type ReducerAction = { type: TType } & TAdditional; - -interface ChangeMonthPayload { - direction: SlideDirection; - newMonth: MaterialUiPickersDate; -} - -interface State { - isMonthSwitchingAnimating: boolean; - loadingQueue: number; - currentMonth: MaterialUiPickersDate; - focusedDay: MaterialUiPickersDate | null; - slideDirection: SlideDirection; -} - -const createCalendarStateReducer = ( - reduceAnimations: boolean, - utils: IUtils -) => ( - state: State, - action: - | ReducerAction<'popLoadingQueue'> - | ReducerAction<'finishMonthSwitchingAnimation'> - | ReducerAction<'changeMonth', ChangeMonthPayload> - | ReducerAction<'changeMonthLoading', ChangeMonthPayload> - | ReducerAction<'changeFocusedDay', { focusedDay: MaterialUiPickersDate }> -): State => { - switch (action.type) { - case 'changeMonthLoading': { - return { - ...state, - loadingQueue: state.loadingQueue + 1, - slideDirection: action.direction, - currentMonth: action.newMonth, - isMonthSwitchingAnimating: !reduceAnimations, - }; - } - case 'changeMonth': { - return { - ...state, - slideDirection: action.direction, - currentMonth: action.newMonth, - isMonthSwitchingAnimating: !reduceAnimations, - }; - } - case 'popLoadingQueue': { - return { - ...state, - loadingQueue: state.loadingQueue <= 0 ? 0 : state.loadingQueue - 1, - }; - } - case 'finishMonthSwitchingAnimation': { - return { - ...state, - isMonthSwitchingAnimating: false, - }; - } - case 'changeFocusedDay': { - const needMonthSwitch = !utils.isSameMonth(state.currentMonth, action.focusedDay); - return { - ...state, - focusedDay: action.focusedDay, - isMonthSwitchingAnimating: needMonthSwitch && !reduceAnimations, - currentMonth: needMonthSwitch ? utils.startOfMonth(action.focusedDay) : state.currentMonth, - slideDirection: utils.isAfterDay(action.focusedDay, state.currentMonth) ? 'left' : 'right', - }; - } - } -}; - export const useStyles = makeStyles( { viewTransitionContainer: { @@ -144,6 +68,9 @@ export const useStyles = makeStyles( { name: 'MuiPickersCalendarView' } ); +export const defaultReduceAnimations = + typeof window !== 'undefined' && /(android)/i.test(window.navigator.userAgent); + export const CalendarView: React.FC = ({ date, view, @@ -152,14 +79,14 @@ export const CalendarView: React.FC = ({ onMonthChange, minDate: unparsedMinDate = new Date('1900-01-01'), maxDate: unparsedMaxDate = new Date('2100-01-01'), - reduceAnimations = typeof window !== 'undefined' && /(android)/i.test(window.navigator.userAgent), + reduceAnimations = defaultReduceAnimations, loadingIndicator = , shouldDisableDate, allowKeyboardControl: allowKeyboardControlProp, + disablePast, + disableFuture, ...other }) => { - const now = useNow(); - const utils = useUtils(); const classes = useStyles(); const minDate = useParsedDate(unparsedMinDate)!; const maxDate = useParsedDate(unparsedMaxDate)!; @@ -167,87 +94,41 @@ export const CalendarView: React.FC = ({ const wrapperVariant = React.useContext(WrapperVariantContext); const allowKeyboardControl = allowKeyboardControlProp ?? wrapperVariant !== 'static'; - const [ - { currentMonth, isMonthSwitchingAnimating, focusedDay, loadingQueue, slideDirection }, - dispatch, - ] = React.useReducer(createCalendarStateReducer(reduceAnimations, utils), { - isMonthSwitchingAnimating: false, - loadingQueue: 0, - focusedDay: date, - currentMonth: utils.startOfMonth(date), - slideDirection: 'left', + const { + loadingQueue, + calendarState, + changeFocusedDay, + changeMonth, + isDateDisabled, + handleChangeMonth, + onMonthSwitchingAnimationEnd, + } = useCalendarState({ + date, + reduceAnimations, + onMonthChange, + minDate, + maxDate, + shouldDisableDate, + disablePast, + disableFuture, }); - const handleChangeMonth = React.useCallback( - (payload: ChangeMonthPayload) => { - const returnedPromise = onMonthChange && onMonthChange(payload.newMonth); - - if (returnedPromise) { - dispatch({ - type: 'changeMonthLoading', - ...payload, - }); - - returnedPromise.then(() => dispatch({ type: 'popLoadingQueue' })); - } else { - dispatch({ - type: 'changeMonth', - ...payload, - }); - } - }, - [onMonthChange] - ); - - const changeMonth = React.useCallback( - (date: MaterialUiPickersDate) => { - if (utils.isSameMonth(date, currentMonth)) { - return; - } - - handleChangeMonth({ - newMonth: utils.startOfMonth(date), - direction: utils.isAfterDay(date, currentMonth) ? 'left' : 'right', - }); - }, - [currentMonth, handleChangeMonth, utils] - ); - React.useEffect(() => { changeMonth(date); }, [date]); // eslint-disable-line React.useEffect(() => { if (view === 'date') { - dispatch({ type: 'changeFocusedDay', focusedDay: date }); + changeFocusedDay(date); } }, [view]); // eslint-disable-line - const validateMinMaxDate = React.useCallback( - (day: MaterialUiPickersDate) => { - return Boolean( - (other.disableFuture && utils.isAfterDay(day, now)) || - (other.disablePast && utils.isBeforeDay(day, now)) || - (minDate && utils.isBeforeDay(day, minDate)) || - (maxDate && utils.isAfterDay(day, maxDate)) - ); - }, - [maxDate, minDate, now, other.disableFuture, other.disablePast, utils] - ); - - const isDateDisabled = React.useCallback( - (day: MaterialUiPickersDate) => { - return validateMinMaxDate(day) || Boolean(shouldDisableDate && shouldDisableDate(day)); - }, - [shouldDisableDate, validateMinMaxDate] - ); - return ( <> handleChangeMonth({ newMonth, direction })} minDate={minDate} @@ -297,15 +178,10 @@ export const CalendarView: React.FC = ({ ) : ( - dispatch({ type: 'finishMonthSwitchingAnimation' }) - } - focusedDay={focusedDay} - changeFocusedDay={focusedDay => dispatch({ type: 'changeFocusedDay', focusedDay })} + {...calendarState} + onMonthSwitchingAnimationEnd={onMonthSwitchingAnimationEnd} + changeFocusedDay={changeFocusedDay} reduceAnimations={reduceAnimations} - currentMonth={currentMonth} - slideDirection={slideDirection} date={date} onChange={onChange} minDate={minDate} diff --git a/lib/src/views/Calendar/SlideTransition.tsx b/lib/src/views/Calendar/SlideTransition.tsx index e8a7bc06c..786e81161 100644 --- a/lib/src/views/Calendar/SlideTransition.tsx +++ b/lib/src/views/Calendar/SlideTransition.tsx @@ -50,12 +50,12 @@ export const useStyles = makeStyles( }, 'slideExitActiveLeft-left': { willChange: 'transform', - transform: 'translate(-200%)', + transform: 'translate(-100%)', transition: slideTransition, }, 'slideExitActiveLeft-right': { willChange: 'transform', - transform: 'translate(200%)', + transform: 'translate(100%)', transition: slideTransition, }, }; diff --git a/lib/src/views/Calendar/useCalendarState.tsx b/lib/src/views/Calendar/useCalendarState.tsx new file mode 100644 index 000000000..3aa0316ae --- /dev/null +++ b/lib/src/views/Calendar/useCalendarState.tsx @@ -0,0 +1,183 @@ +import * as React from 'react'; +import { CalendarViewProps } from './CalendarView'; +import { SlideDirection } from './SlideTransition'; +import { MaterialUiPickersDate } from '../../typings/date'; +import { MuiPickersAdapter, useUtils, useNow } from '../../_shared/hooks/useUtils'; + +interface State { + isMonthSwitchingAnimating: boolean; + loadingQueue: number; + currentMonth: MaterialUiPickersDate; + focusedDay: MaterialUiPickersDate | null; + slideDirection: SlideDirection; +} + +type ReducerAction = { type: TType } & TAdditional; + +interface ChangeMonthPayload { + direction: SlideDirection; + newMonth: MaterialUiPickersDate; +} + +export const createCalendarStateReducer = (reduceAnimations: boolean, utils: MuiPickersAdapter) => ( + state: State, + action: + | ReducerAction<'popLoadingQueue'> + | ReducerAction<'finishMonthSwitchingAnimation'> + | ReducerAction<'changeMonth', ChangeMonthPayload> + | ReducerAction<'changeMonthLoading', ChangeMonthPayload> + | ReducerAction<'changeFocusedDay', { focusedDay: MaterialUiPickersDate }> +): State => { + switch (action.type) { + case 'changeMonthLoading': { + return { + ...state, + loadingQueue: state.loadingQueue + 1, + slideDirection: action.direction, + currentMonth: action.newMonth, + isMonthSwitchingAnimating: !reduceAnimations, + }; + } + case 'changeMonth': { + return { + ...state, + slideDirection: action.direction, + currentMonth: action.newMonth, + isMonthSwitchingAnimating: !reduceAnimations, + }; + } + case 'popLoadingQueue': { + return { + ...state, + loadingQueue: state.loadingQueue <= 0 ? 0 : state.loadingQueue - 1, + }; + } + case 'finishMonthSwitchingAnimation': { + return { + ...state, + isMonthSwitchingAnimating: false, + }; + } + case 'changeFocusedDay': { + const needMonthSwitch = !utils.isSameMonth(state.currentMonth, action.focusedDay); + return { + ...state, + focusedDay: action.focusedDay, + isMonthSwitchingAnimating: needMonthSwitch && !reduceAnimations, + currentMonth: needMonthSwitch ? utils.startOfMonth(action.focusedDay) : state.currentMonth, + slideDirection: utils.isAfterDay(action.focusedDay, state.currentMonth) ? 'left' : 'right', + }; + } + } +}; + +type CalendarStateInput = Pick< + CalendarViewProps, + | 'disableFuture' + | 'disablePast' + | 'shouldDisableDate' + | 'date' + | 'reduceAnimations' + | 'onMonthChange' +> & { + minDate: MaterialUiPickersDate; + maxDate: MaterialUiPickersDate; +}; + +export function useCalendarState({ + date, + reduceAnimations, + onMonthChange, + disablePast, + disableFuture, + minDate, + maxDate, + shouldDisableDate, +}: CalendarStateInput) { + const now = useNow(); + const utils = useUtils(); + const [{ loadingQueue, ...calendarState }, dispatch] = React.useReducer( + createCalendarStateReducer(Boolean(reduceAnimations), utils), + { + isMonthSwitchingAnimating: false, + loadingQueue: 0, + focusedDay: date, + currentMonth: utils.startOfMonth(date), + slideDirection: 'left', + } + ); + + const handleChangeMonth = React.useCallback( + (payload: ChangeMonthPayload) => { + const returnedPromise = onMonthChange && onMonthChange(payload.newMonth); + + if (returnedPromise) { + dispatch({ + type: 'changeMonthLoading', + ...payload, + }); + + returnedPromise.then(() => dispatch({ type: 'popLoadingQueue' })); + } else { + dispatch({ + type: 'changeMonth', + ...payload, + }); + } + }, + [onMonthChange] + ); + + const changeMonth = React.useCallback( + (date: MaterialUiPickersDate) => { + if (utils.isSameMonth(date, calendarState.currentMonth)) { + return; + } + + handleChangeMonth({ + newMonth: utils.startOfMonth(date), + direction: utils.isAfterDay(date, calendarState.currentMonth) ? 'left' : 'right', + }); + }, + [calendarState.currentMonth, handleChangeMonth, utils] + ); + + const validateMinMaxDate = React.useCallback( + (day: MaterialUiPickersDate) => { + return Boolean( + (disableFuture && utils.isAfterDay(day, now)) || + (disablePast && utils.isBeforeDay(day, now)) || + (minDate && utils.isBeforeDay(day, minDate)) || + (maxDate && utils.isAfterDay(day, maxDate)) + ); + }, + [disableFuture, disablePast, maxDate, minDate, now, utils] + ); + + const isDateDisabled = React.useCallback( + (day: MaterialUiPickersDate) => { + return validateMinMaxDate(day) || Boolean(shouldDisableDate && shouldDisableDate(day)); + }, + [shouldDisableDate, validateMinMaxDate] + ); + + const onMonthSwitchingAnimationEnd = React.useCallback(() => { + dispatch({ type: 'finishMonthSwitchingAnimation' }); + }, []); + + const changeFocusedDay = React.useCallback( + (newFocusedDate: MaterialUiPickersDate) => + dispatch({ type: 'changeFocusedDay', focusedDay: newFocusedDate }), + [] + ); + + return { + loadingQueue, + calendarState, + changeMonth, + changeFocusedDay, + isDateDisabled, + onMonthSwitchingAnimationEnd, + handleChangeMonth, + }; +} From e8553638b1603b1ba7c478d3f273a662c7743ed1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 19 Mar 2020 11:53:48 +0200 Subject: [PATCH 14/72] [WiP] Work on displaying 2 calendars one by one --- lib/src/DateRangePicker/DesktopDateRangePicker.tsx | 7 ++++++- lib/src/views/Calendar/Calendar.tsx | 4 +++- lib/src/views/Calendar/Day.tsx | 2 ++ lib/src/views/Calendar/SlideTransition.tsx | 4 ++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index a2541b619..376cadb8c 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -20,6 +20,10 @@ export const useStyles = makeStyles( dateRangeContainer: { display: 'flex', flexDirection: 'row', + padding: '0 16px 8px 0', + }, + calendar: { + padding: '0 16px', }, }), { name: 'MuiPickersDesktopDateRangeCalendar' } @@ -51,8 +55,9 @@ export const DesktopDateRangeCalendar: React.FC = /> diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 904e41e8d..938f74f33 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -52,6 +52,7 @@ export interface CalendarProps extends ExportedCalendarProps { isMonthSwitchingAnimating: boolean; onMonthSwitchingAnimationEnd: () => void; allowOverflowingSlideTransition?: boolean; + className?: string; } export const useStyles = makeStyles(theme => ({ @@ -116,6 +117,7 @@ export const Calendar: React.FC = ({ disableHighlightToday, showDaysOutsideCurrentMonth, allowOverflowingSlideTransition, + className, }) => { const now = useNow(); const utils = useUtils(); @@ -189,7 +191,7 @@ export const Calendar: React.FC = ({ [classes.transitionContainerOverflowAllowed]: allowOverflowingSlideTransition, })} > -
+
{utils.getWeekArray(currentMonth).map(week => (
{week.map(day => { diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 499335e97..1eefc0143 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -15,6 +15,8 @@ export const useStyles = makeStyles( height: daySize + 2, borderRadius: '50%', padding: 0, + // background required here to prevent collides with the other days when animating with transition group + backgroundColor: theme.palette.background.paper, color: theme.palette.text.primary, fontSize: theme.typography.caption.fontSize, fontWeight: theme.typography.fontWeightMedium, diff --git a/lib/src/views/Calendar/SlideTransition.tsx b/lib/src/views/Calendar/SlideTransition.tsx index 786e81161..992529250 100644 --- a/lib/src/views/Calendar/SlideTransition.tsx +++ b/lib/src/views/Calendar/SlideTransition.tsx @@ -36,10 +36,12 @@ export const useStyles = makeStyles( 'slideEnter-left': { willChange: 'transform', transform: 'translate(100%)', + zIndex: 1, }, 'slideEnter-right': { willChange: 'transform', transform: 'translate(-100%)', + zIndex: 1, }, slideEnterActive: { transform: 'translate(0%)', @@ -52,11 +54,13 @@ export const useStyles = makeStyles( willChange: 'transform', transform: 'translate(-100%)', transition: slideTransition, + zIndex: 0, }, 'slideExitActiveLeft-right': { willChange: 'transform', transform: 'translate(100%)', transition: slideTransition, + zIndex: 0, }, }; }, From b8bfdffc306dca9dc93de56283d50e8d89efeb7f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sun, 22 Mar 2020 08:48:23 +0200 Subject: [PATCH 15/72] WATER ON MY MAC --- docs/prop-types.json | 26 ++++++++ lib/src/DateRangePicker/DateRangeDay.tsx | 44 +++++++++++++ lib/src/DateRangePicker/DateRangePicker.tsx | 12 +++- ...erCalendar.tsx => DateRangePickerView.tsx} | 18 +++-- .../DesktopDateRangePicker.tsx | 65 ++++++++++++++----- lib/src/_shared/ArrowSwitcher.tsx | 23 +++++-- lib/src/views/Calendar/Calendar.tsx | 11 +--- lib/src/views/Calendar/CalendarView.tsx | 2 + lib/src/views/Calendar/useCalendarState.tsx | 18 +++-- 9 files changed, 171 insertions(+), 48 deletions(-) create mode 100644 lib/src/DateRangePicker/DateRangeDay.tsx rename lib/src/DateRangePicker/{DateRangePickerCalendar.tsx => DateRangePickerView.tsx} (79%) diff --git a/docs/prop-types.json b/docs/prop-types.json index 3225cd7c6..c33037781 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -443,6 +443,19 @@ "name": "boolean" } }, + "reduceAnimations": { + "defaultValue": null, + "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", + "name": "reduceAnimations", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, "onMonthChange": { "defaultValue": null, "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", @@ -1990,6 +2003,19 @@ "name": "boolean" } }, + "reduceAnimations": { + "defaultValue": null, + "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", + "name": "reduceAnimations", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, "onMonthChange": { "defaultValue": null, "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangeDay.tsx new file mode 100644 index 000000000..5f1363622 --- /dev/null +++ b/lib/src/DateRangePicker/DateRangeDay.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import WAclsx from 'clsx'; +import { DateRange } from './RangeTypes'; +import { makeStyles } from '@material-ui/core'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { Day, DayProps } from '../views/Calendar/Day'; + +interface DateRangeDayProps extends DayProps { + selectedRange: DateRange; +} + +const useStyles = makeStyles( + theme => ({ + rangeIntervalHighlighted: { + borderRadius: 0, + color: theme.palette.primary, + backgroundColor: theme.palette.primary.light, + }, + }), + { name: 'MuiPickersDateRangeDay' } +); + +export const DateRangeDay: React.FC = ({ + selectedRange, + className, + ...other +}) => { + const utils = useUtils(); + const classes = useStyles(0); + + return ( + + ); +}; diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index b00111c39..332fe2cbb 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -10,7 +10,7 @@ import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { AllSharedPickerProps } from '../Picker/SharedPickerProps'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; -import { DateRangePickerCalendar, DateRangePickerCalendarProps } from './DateRangePickerCalendar'; +import { DateRangePickerView, DateRangePickerViewProps } from './DateRangePickerView'; export function parseRangeInputValue( now: MaterialUiPickersDate, @@ -40,10 +40,14 @@ export function makeRangePicker(Wrapper: TWrapper) disableHighlightToday, reduceAnimations, ...other - }: DateRangePickerCalendarProps & + }: DateRangePickerViewProps & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); + const [currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd] = React.useState< + 'start' | 'end' + >('start'); + const { pickerProps, inputProps, wrapperProps } = usePickerState(other, { parseInput: parseRangeInputValue, areValuesEqual: (a, b) => utils.isEqual(a[0], b[0]) && utils.isEqual(a[1], b[1]), @@ -52,7 +56,7 @@ export function makeRangePicker(Wrapper: TWrapper) return ( - (Wrapper: TWrapper) onMonthChange={onMonthChange} disableHighlightToday={disableHighlightToday} reduceAnimations={reduceAnimations} + currentlySelectingRangeEnd={currentlySelectingRangeEnd} + setCurrentlySelectingRangeEnd={setCurrentlySelectingRangeEnd} {...pickerProps} /> diff --git a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx similarity index 79% rename from lib/src/DateRangePicker/DateRangePickerCalendar.tsx rename to lib/src/DateRangePicker/DateRangePickerView.tsx index 6df0b31a9..53ddfa923 100644 --- a/lib/src/DateRangePicker/DateRangePickerCalendar.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -14,14 +14,15 @@ import { type BaseCalendarPropsToReuse = Omit; -export interface DateRangePickerCalendarProps +export interface DateRangePickerViewProps extends BaseCalendarPropsToReuse, ExportedDesktopDateRangeCalendarProps, SharedPickerProps { - reduceAnimations?: boolean; + currentlySelectingRangeEnd: 'start' | 'end'; + setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; } -export const DateRangePickerCalendar: React.FC = ({ +export const DateRangePickerView: React.FC = ({ date, calendars, minDate: unparsedMinDate = new Date('1900-01-01'), @@ -32,6 +33,7 @@ export const DateRangePickerCalendar: React.FC = ( disableHighlightToday, onMonthChange, onDateChange, + setCurrentlySelectingRangeEnd, reduceAnimations = defaultReduceAnimations, }) => { const utils = useUtils(); @@ -59,9 +61,15 @@ export const DateRangePickerCalendar: React.FC = ( const handleChange = React.useCallback( (date: MaterialUiPickersDate) => { - onDateChange([date, end], wrapperVariant, false); + if (start === null || utils.isBefore(date, start)) { + setCurrentlySelectingRangeEnd('start'); + onDateChange([date, end], wrapperVariant, false); + } else { + setCurrentlySelectingRangeEnd('end'); + onDateChange([start, date], wrapperVariant, true); + } }, - [end, onDateChange, wrapperVariant] + [end, onDateChange, setCurrentlySelectingRangeEnd, start, utils, wrapperVariant] ); switch (wrapperVariant) { diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index 376cadb8c..68d45a947 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -1,9 +1,11 @@ import * as React from 'react'; -import { makeStyles } from '@material-ui/core'; +import { DateRange } from './RangeTypes'; +import { DateRangeDay } from './DateRangeDay'; import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; -import { ArrowSwitcher } from '../_shared/ArrowSwitcher'; +import { makeStyles, Typography } from '@material-ui/core'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; +import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; export interface ExportedDesktopDateRangeCalendarProps { calendars?: 1 | 2; @@ -11,7 +13,9 @@ export interface ExportedDesktopDateRangeCalendarProps { interface DesktopDateRangeCalendarProps extends ExportedDesktopDateRangeCalendarProps, - CalendarProps { + CalendarProps, + ExportedArrowSwitcherProps { + date: DateRange; changeMonth: (date: MaterialUiPickersDate) => void; } @@ -20,46 +24,75 @@ export const useStyles = makeStyles( dateRangeContainer: { display: 'flex', flexDirection: 'row', - padding: '0 16px 8px 0', + }, + rangeCalendarContainer: { + '&:not(:last-child)': { + borderRight: `2px solid ${theme.palette.divider}`, + }, }, calendar: { - padding: '0 16px', + minWidth: 312, + }, + arrowSwitcher: { + padding: '16px 16px 8px 16px', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', }, }), { name: 'MuiPickersDesktopDateRangeCalendar' } ); export const DesktopDateRangeCalendar: React.FC = ({ + date, calendars = 2, changeMonth, + leftArrowButtonProps, + leftArrowButtonText, + leftArrowIcon, + rightArrowButtonProps, + rightArrowButtonText, + rightArrowIcon, ...CalendarProps }) => { const utils = useUtils(); const classes = useStyles(); + const { currentMonth } = CalendarProps; return (
{new Array(calendars).fill(0).map((_, index) => { - const monthOnIteration = utils.setMonth( - CalendarProps.currentMonth, - utils.getMonth(CalendarProps.currentMonth) + index - ); - - console.log(monthOnIteration); + const monthOnIteration = utils.setMonth(currentMonth, utils.getMonth(currentMonth) + index); return ( -
+
changeMonth(utils.getPreviousMonth(CalendarProps.currentMonth))} - onRightClick={() => changeMonth(utils.getNextMonth(CalendarProps.currentMonth))} - /> + className={classes.arrowSwitcher} + onLeftClick={() => changeMonth(utils.getPreviousMonth(currentMonth))} + onRightClick={() => changeMonth(utils.getNextMonth(currentMonth))} + isLeftHidden={index !== 0} + isRightHidden={index !== calendars - 1} + isLeftDisabled={false} + isRightDisabled={false} + leftArrowButtonProps={leftArrowButtonProps} + leftArrowButtonText={leftArrowButtonText} + leftArrowIcon={leftArrowIcon} + rightArrowButtonProps={rightArrowButtonProps} + rightArrowButtonText={rightArrowButtonText} + rightArrowIcon={rightArrowIcon} + > + + {utils.format(monthOnIteration, 'monthAndYear')} + + } />
); diff --git a/lib/src/_shared/ArrowSwitcher.tsx b/lib/src/_shared/ArrowSwitcher.tsx index 17589ce9d..435ef1ee0 100644 --- a/lib/src/_shared/ArrowSwitcher.tsx +++ b/lib/src/_shared/ArrowSwitcher.tsx @@ -26,6 +26,8 @@ export interface ExportedArrowSwitcherProps { } interface ArrowSwitcherProps extends ExportedArrowSwitcherProps, React.HTMLProps { + isLeftHidden?: boolean; + isRightHidden?: boolean; isLeftDisabled: boolean; isRightDisabled: boolean; onLeftClick: () => void; @@ -40,6 +42,9 @@ const useStyles = makeStyles(theme => ({ previousMonthButton: { marginRight: 24, }, + hidden: { + visibility: 'hidden', + }, })); export const ArrowSwitcher: React.FC = ({ @@ -48,12 +53,15 @@ export const ArrowSwitcher: React.FC = ({ leftArrowButtonText, rightArrowButtonProps, rightArrowButtonText, + isLeftHidden, + isRightHidden, isLeftDisabled, isRightDisabled, onLeftClick, onRightClick, leftArrowIcon = , rightArrowIcon = , + children, ...other }) => { const classes = useStyles(); @@ -69,15 +77,16 @@ export const ArrowSwitcher: React.FC = ({ {...leftArrowButtonProps} disabled={isLeftDisabled} onClick={onLeftClick} - className={clsx( - classes.iconButton, - classes.previousMonthButton, - leftArrowButtonProps?.className - )} + className={clsx(classes.iconButton, leftArrowButtonProps?.className, { + [classes.hidden]: Boolean(isLeftHidden), + [classes.previousMonthButton]: !Boolean(className), + })} > {isRtl ? rightArrowIcon : leftArrowIcon} + {children} + = ({ {...rightArrowButtonProps} disabled={isRightDisabled} onClick={onRightClick} - className={clsx(classes.iconButton, rightArrowButtonProps?.className)} + className={clsx(classes.iconButton, rightArrowButtonProps?.className, { + [classes.hidden]: Boolean(isRightHidden), + })} > {isRtl ? leftArrowIcon : rightArrowIcon} diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 938f74f33..12c1090a4 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -51,7 +51,6 @@ export interface CalendarProps extends ExportedCalendarProps { changeFocusedDay: (newFocusedDay: MaterialUiPickersDate) => void; isMonthSwitchingAnimating: boolean; onMonthSwitchingAnimationEnd: () => void; - allowOverflowingSlideTransition?: boolean; className?: string; } @@ -116,7 +115,6 @@ export const Calendar: React.FC = ({ isDateDisabled, disableHighlightToday, showDaysOutsideCurrentMonth, - allowOverflowingSlideTransition, className, }) => { const now = useNow(); @@ -167,7 +165,6 @@ export const Calendar: React.FC = ({ .filter(Boolean) .map(selectedDateItem => utils.startOfDay(selectedDateItem)); - console.log(utils.getWeekArray(currentMonth)); return ( <>
@@ -183,15 +180,13 @@ export const Calendar: React.FC = ({
-
+
{utils.getWeekArray(currentMonth).map(week => (
{week.map(day => { diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index d5bed725b..5564b18c9 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -31,6 +31,8 @@ export interface CalendarViewProps extends ExportedCalendarProps, PublicCalendar views: DatePickerView[]; changeView: (view: DatePickerView) => void; onChange: PickerOnChangeFn; + /** Disable heavy animations @default /(android)/i.test(window.navigator.userAgent) */ + reduceAnimations?: boolean; /** Callback firing on month change. Return promise to render spinner till it will not be resolved @DateIOType */ onMonthChange?: (date: MaterialUiPickersDate) => void | Promise; /** diff --git a/lib/src/views/Calendar/useCalendarState.tsx b/lib/src/views/Calendar/useCalendarState.tsx index 3aa0316ae..e6d757a11 100644 --- a/lib/src/views/Calendar/useCalendarState.tsx +++ b/lib/src/views/Calendar/useCalendarState.tsx @@ -96,16 +96,14 @@ export function useCalendarState({ }: CalendarStateInput) { const now = useNow(); const utils = useUtils(); - const [{ loadingQueue, ...calendarState }, dispatch] = React.useReducer( - createCalendarStateReducer(Boolean(reduceAnimations), utils), - { - isMonthSwitchingAnimating: false, - loadingQueue: 0, - focusedDay: date, - currentMonth: utils.startOfMonth(date), - slideDirection: 'left', - } - ); + const reducerFn = React.useRef(createCalendarStateReducer(Boolean(reduceAnimations), utils)); + const [{ loadingQueue, ...calendarState }, dispatch] = React.useReducer(reducerFn.current, { + isMonthSwitchingAnimating: false, + loadingQueue: 0, + focusedDay: date, + currentMonth: utils.startOfMonth(date), + slideDirection: 'left', + }); const handleChangeMonth = React.useCallback( (payload: ChangeMonthPayload) => { From c10707ecdea6c0be4743c29075970a54a0570478 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 23 Mar 2020 13:42:28 +0200 Subject: [PATCH 16/72] Proper display days with margins with range highlights --- docs/prop-types.json | 8 +-- lib/src/DateRangePicker/DateRangeDay.tsx | 76 +++++++++++++++++++----- lib/src/_shared/ArrowSwitcher.tsx | 29 +++++---- lib/src/constants/dimensions.ts | 6 +- lib/src/typings/overrides.ts | 1 + lib/src/views/Calendar/Calendar.tsx | 38 +++++------- lib/src/views/Calendar/Day.tsx | 30 +++++----- lib/src/views/Calendar/DayWrapper.tsx | 40 ------------- 8 files changed, 115 insertions(+), 113 deletions(-) delete mode 100644 lib/src/views/Calendar/DayWrapper.tsx diff --git a/docs/prop-types.json b/docs/prop-types.json index c33037781..acf494aa3 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -2693,10 +2693,10 @@ "name": "boolean" } }, - "isInCurrentMonth": { + "inCurrentMonth": { "defaultValue": null, "description": "Is day in current month", - "name": "isInCurrentMonth", + "name": "inCurrentMonth", "parent": { "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", "name": "DayProps" @@ -2719,12 +2719,12 @@ "name": "boolean" } }, - "isToday": { + "today": { "defaultValue": { "value": false }, "description": "Is today?", - "name": "isToday", + "name": "today", "parent": { "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", "name": "DayProps" diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangeDay.tsx index 5f1363622..49103b800 100644 --- a/lib/src/DateRangePicker/DateRangeDay.tsx +++ b/lib/src/DateRangePicker/DateRangeDay.tsx @@ -1,44 +1,88 @@ import * as React from 'react'; -import WAclsx from 'clsx'; +import clsx from 'clsx'; import { DateRange } from './RangeTypes'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles, fade } from '@material-ui/core'; import { useUtils } from '../_shared/hooks/useUtils'; +import { DAY_MARGIN } from '../constants/dimensions'; import { Day, DayProps } from '../views/Calendar/Day'; interface DateRangeDayProps extends DayProps { selectedRange: DateRange; } +const endBorderStyle = { + borderTopRightRadius: '60%', + borderBottomRightRadius: '60%', +}; + +const startBorderStyle = { + borderTopLeftRadius: '60%', + borderBottomLeftRadius: '60%', +}; + const useStyles = makeStyles( theme => ({ - rangeIntervalHighlighted: { + rangeIntervalDay: { + padding: `0 ${DAY_MARGIN}px`, + }, + rangeIntervalDayHighlight: { borderRadius: 0, - color: theme.palette.primary, - backgroundColor: theme.palette.primary.light, + color: theme.palette.primary.contrastText, + backgroundColor: fade(theme.palette.primary.light, 0.6), + '&:first-child': startBorderStyle, + '&:last-child': endBorderStyle, + }, + rangeIntervalDayHighlightStart: { + ...startBorderStyle, + paddingLeft: 0, + marginLeft: DAY_MARGIN / 2, + }, + rangeIntervalDayHighlightEnd: { + ...endBorderStyle, + paddingRight: 0, + marginRight: DAY_MARGIN / 2, + }, + dayInsideRangeInterval: { + backgroundColor: 'transparent', + color: theme.palette.getContrastText(fade(theme.palette.primary.light, 0.6)), }, + rangeIntervalStart: {}, }), { name: 'MuiPickersDateRangeDay' } ); export const DateRangeDay: React.FC = ({ + day, selectedRange, className, + selected, ...other }) => { const utils = useUtils(); const classes = useStyles(0); + const [start, end] = selectedRange; return ( - +
+ +
); }; diff --git a/lib/src/_shared/ArrowSwitcher.tsx b/lib/src/_shared/ArrowSwitcher.tsx index 435ef1ee0..8054d86d3 100644 --- a/lib/src/_shared/ArrowSwitcher.tsx +++ b/lib/src/_shared/ArrowSwitcher.tsx @@ -34,18 +34,21 @@ interface ArrowSwitcherProps extends ExportedArrowSwitcherProps, React.HTMLProps onRightClick: () => void; } -const useStyles = makeStyles(theme => ({ - iconButton: { - zIndex: 1, - backgroundColor: theme.palette.background.paper, - }, - previousMonthButton: { - marginRight: 24, - }, - hidden: { - visibility: 'hidden', - }, -})); +export const useStyles = makeStyles( + theme => ({ + iconButton: { + zIndex: 1, + backgroundColor: theme.palette.background.paper, + }, + previousMonthButtonMargin: { + marginRight: 24, + }, + hidden: { + visibility: 'hidden', + }, + }), + { name: 'MuiPickersArrowSwitcher' } +); export const ArrowSwitcher: React.FC = ({ className, @@ -79,7 +82,7 @@ export const ArrowSwitcher: React.FC = ({ onClick={onLeftClick} className={clsx(classes.iconButton, leftArrowButtonProps?.className, { [classes.hidden]: Boolean(isLeftHidden), - [classes.previousMonthButton]: !Boolean(className), + [classes.previousMonthButtonMargin]: !Boolean(children), })} > {isRtl ? rightArrowIcon : leftArrowIcon} diff --git a/lib/src/constants/dimensions.ts b/lib/src/constants/dimensions.ts index 5fc349d12..ec5cca9dc 100644 --- a/lib/src/constants/dimensions.ts +++ b/lib/src/constants/dimensions.ts @@ -2,4 +2,8 @@ export const DIALOG_WIDTH = 320; export const DIALOG_WIDTH_WIDER = 325; -export const VIEW_HEIGHT = 330; +export const VIEW_HEIGHT = 340; + +export const DAY_SIZE = 36; + +export const DAY_MARGIN = 2; diff --git a/lib/src/typings/overrides.ts b/lib/src/typings/overrides.ts index fa1d8227a..134ddae01 100644 --- a/lib/src/typings/overrides.ts +++ b/lib/src/typings/overrides.ts @@ -65,4 +65,5 @@ export interface MuiPickersOverrides { MuiPickersDesktopDateRangeCalendar?: Classes< typeof import('../DateRangePicker/DesktopDateRangePicker').useStyles >; + MuiPickersArrowSwitcher?: Classes; } diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 12c1090a4..3f85966af 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -1,13 +1,15 @@ import * as React from 'react'; import clsx from 'clsx'; -import DayWrapper from './DayWrapper'; import SlideTransition, { SlideDirection } from './SlideTransition'; import { Day, DayProps } from './Day'; +import { onSpaceOrEnter } from '../../_helpers/utils'; import { MaterialUiPickersDate } from '../../typings/date'; import { useUtils, useNow } from '../../_shared/hooks/useUtils'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; +import { DAY_SIZE, DAY_MARGIN } from '../../constants/dimensions'; import { findClosestEnabledDate } from '../../_helpers/date-utils'; import { makeStyles, useTheme, Typography } from '@material-ui/core'; +import { FORCE_FINISH_PICKER } from '../../_shared/hooks/usePickerState'; import { useGlobalKeyDown, keycode } from '../../_shared/hooks/useKeyDown'; export interface ExportedCalendarProps @@ -56,7 +58,7 @@ export interface CalendarProps extends ExportedCalendarProps { export const useStyles = makeStyles(theme => ({ transitionContainer: { - minHeight: 36 * 6 + 20, + minHeight: (DAY_SIZE + DAY_MARGIN * 2) * 6, }, transitionContainerOverflowAllowed: { overflowX: 'visible', @@ -69,6 +71,7 @@ export const useStyles = makeStyles(theme => ({ alignItems: 'center', }, week: { + margin: `${DAY_MARGIN}px 0`, display: 'flex', justifyContent: 'center', }, @@ -193,40 +196,29 @@ export const Calendar: React.FC = ({ const disabled = isDateDisabled(day); const isDayInCurrentMonth = utils.getMonth(day) === currentMonthNumber; - const dayProps = { + const dayProps: DayProps = { day: day, + role: 'cell', isAnimating: isMonthSwitchingAnimating, disabled: disabled, allowKeyboardControl: allowKeyboardControl, focused: Boolean(focusedDay) && utils.isSameDay(day, focusedDay), - onFocus: () => changeFocusedDay(day), - isToday: utils.isSameDay(day, now), - hidden: !isDayInCurrentMonth, - isInCurrentMonth: isDayInCurrentMonth, + today: utils.isSameDay(day, now), + inCurrentMonth: isDayInCurrentMonth, selected: selectedDates.some(selectedDate => utils.isSameDay(selectedDate, day)), disableHighlightToday, showDaysOutsideCurrentMonth, focusable: Boolean(nowFocusedDay) && utils.toJsDate(nowFocusedDay).getDate() === utils.toJsDate(day).getDate(), + onFocus: () => changeFocusedDay(day), + onClick: () => !disabled && handleDaySelect(day, true), + onKeyDown: onSpaceOrEnter( + () => !disabled && handleDaySelect(day, FORCE_FINISH_PICKER) + ), }; - let dayComponent = renderDay ? ( - renderDay(day, selectedDates, dayProps) - ) : ( - - ); - - return ( - - ); + return renderDay ? renderDay(day, selectedDates, dayProps) : ; })}
))} diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 1eefc0143..425d5aea9 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -6,13 +6,13 @@ import { useUtils } from '../../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../../typings/date'; import { makeStyles, fade } from '@material-ui/core/styles'; import { ButtonBase, ButtonBaseProps } from '@material-ui/core'; +import { DAY_SIZE, DAY_MARGIN } from '../../constants/dimensions'; -const daySize = 36; export const useStyles = makeStyles( theme => ({ day: { - width: daySize + 4, - height: daySize + 2, + width: DAY_SIZE, + height: DAY_SIZE, borderRadius: '50%', padding: 0, // background required here to prevent collides with the other days when animating with transition group @@ -32,9 +32,7 @@ export const useStyles = makeStyles( }, }, dayWithMargin: { - margin: '1px 2px', - width: daySize, - height: daySize, + margin: `0px ${DAY_MARGIN}px`, }, dayOutsideMonth: { color: theme.palette.text.hint, @@ -79,11 +77,11 @@ export interface DayProps extends ExtendMui { /** Can be focused by tabbing in */ focusable?: boolean; /** Is day in current month */ - isInCurrentMonth: boolean; + inCurrentMonth: boolean; /** Is switching month animation going on right now */ isAnimating?: boolean; /** Is today? */ - isToday?: boolean; + today?: boolean; /** Disabled? */ disabled?: boolean; /** Selected? */ @@ -107,8 +105,9 @@ export const Day: React.FC = ({ className, day, disabled, - isInCurrentMonth, - isToday, + hidden, + inCurrentMonth: isInCurrentMonth, + today: isToday, selected, focused = false, focusable = false, @@ -137,9 +136,10 @@ export const Day: React.FC = ({ } }, [allowKeyboardControl, disabled, focused, isAnimating, isInCurrentMonth]); + const isHidden = !isInCurrentMonth && !showDaysOutsideCurrentMonth; return ( = ({ [classes.dayDisabled]: disabled, [classes.dayWithMargin]: !disableMargin, [classes.today]: !disableHighlightToday && isToday, - [classes.hidden]: !isInCurrentMonth && !showDaysOutsideCurrentMonth, + [classes.hidden]: isHidden, [classes.dayOutsideMonth]: !isInCurrentMonth && showDaysOutsideCurrentMonth, }, className @@ -172,15 +172,13 @@ export const Day: React.FC = ({ Day.displayName = 'Day'; Day.propTypes = { - isToday: PropTypes.bool, + today: PropTypes.bool, disabled: PropTypes.bool, - hidden: PropTypes.bool, selected: PropTypes.bool, }; Day.defaultProps = { disabled: false, - hidden: false, - isToday: false, + today: false, selected: false, }; diff --git a/lib/src/views/Calendar/DayWrapper.tsx b/lib/src/views/Calendar/DayWrapper.tsx deleted file mode 100644 index d29cc6bcd..000000000 --- a/lib/src/views/Calendar/DayWrapper.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import { onSpaceOrEnter } from '../../_helpers/utils'; -import { MaterialUiPickersDate } from '../../typings/date'; -import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; -import { FORCE_FINISH_PICKER } from '../../_shared/hooks/usePickerState'; - -export interface DayWrapperProps { - value: MaterialUiPickersDate; - children: React.ReactNode; - dayInCurrentMonth?: boolean; - disabled?: boolean; - onSelect: PickerOnChangeFn; -} - -const DayWrapper: React.FC = ({ - children, - value, - disabled, - onSelect, - dayInCurrentMonth, - ...other -}) => { - const handleSelection = (isFinish: symbol | boolean) => { - if (!disabled) { - onSelect(value, isFinish); - } - }; - - return ( -
handleSelection(true)} - onKeyDown={onSpaceOrEnter(() => handleSelection(FORCE_FINISH_PICKER))} - children={children} - {...other} - /> - ); -}; - -export default DayWrapper; From 6af226970389f1a2182a77c523b120d8c62f63de Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 23 Mar 2020 14:21:00 +0200 Subject: [PATCH 17/72] Fix unexpected month switchings --- lib/src/DateRangePicker/DateRangePicker.tsx | 2 +- lib/src/DateRangePicker/DateRangePickerView.tsx | 1 + lib/src/views/Calendar/useCalendarState.tsx | 16 +++++++++++++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 332fe2cbb..29b3eb320 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -18,7 +18,7 @@ export function parseRangeInputValue( { value = [null, null], defaultHighlight }: BasePickerProps ) { return value.map(date => - parsePickerInputValue(now, utils, { value: date, defaultHighlight }) + utils.startOfDay(parsePickerInputValue(now, utils, { value: date, defaultHighlight })) ) as DateRange; } diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 53ddfa923..1108e6e46 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -57,6 +57,7 @@ export const DateRangePickerView: React.FC = ({ disableFuture, onMonthChange, shouldDisableDate, + disableSwitchToMonthOnDayFocus: true, }); const handleChange = React.useCallback( diff --git a/lib/src/views/Calendar/useCalendarState.tsx b/lib/src/views/Calendar/useCalendarState.tsx index e6d757a11..ee89d2f33 100644 --- a/lib/src/views/Calendar/useCalendarState.tsx +++ b/lib/src/views/Calendar/useCalendarState.tsx @@ -19,7 +19,11 @@ interface ChangeMonthPayload { newMonth: MaterialUiPickersDate; } -export const createCalendarStateReducer = (reduceAnimations: boolean, utils: MuiPickersAdapter) => ( +export const createCalendarStateReducer = ( + reduceAnimations: boolean, + disableSwitchToMonthOnDayFocus: boolean, + utils: MuiPickersAdapter +) => ( state: State, action: | ReducerAction<'popLoadingQueue'> @@ -59,7 +63,9 @@ export const createCalendarStateReducer = (reduceAnimations: boolean, utils: Mui }; } case 'changeFocusedDay': { - const needMonthSwitch = !utils.isSameMonth(state.currentMonth, action.focusedDay); + const needMonthSwitch = + !disableSwitchToMonthOnDayFocus && + !utils.isSameMonth(state.currentMonth, action.focusedDay); return { ...state, focusedDay: action.focusedDay, @@ -82,6 +88,7 @@ type CalendarStateInput = Pick< > & { minDate: MaterialUiPickersDate; maxDate: MaterialUiPickersDate; + disableSwitchToMonthOnDayFocus?: boolean; }; export function useCalendarState({ @@ -93,10 +100,13 @@ export function useCalendarState({ minDate, maxDate, shouldDisableDate, + disableSwitchToMonthOnDayFocus = false, }: CalendarStateInput) { const now = useNow(); const utils = useUtils(); - const reducerFn = React.useRef(createCalendarStateReducer(Boolean(reduceAnimations), utils)); + const reducerFn = React.useRef( + createCalendarStateReducer(Boolean(reduceAnimations), disableSwitchToMonthOnDayFocus, utils) + ); const [{ loadingQueue, ...calendarState }, dispatch] = React.useReducer(reducerFn.current, { isMonthSwitchingAnimating: false, loadingQueue: 0, From b1dd4d6f152080c4db17bbd70afd65d7d3a97bfe Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 23 Mar 2020 17:37:42 +0200 Subject: [PATCH 18/72] Implement range preview --- lib/src/DateRangePicker/DateRangeDay.tsx | 120 ++++++++++++------ .../DesktopDateRangePicker.tsx | 53 +++++++- lib/src/constants/dimensions.ts | 2 +- lib/src/views/Calendar/Calendar.tsx | 4 +- 4 files changed, 136 insertions(+), 43 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangeDay.tsx index 49103b800..0b26f4ec3 100644 --- a/lib/src/DateRangePicker/DateRangeDay.tsx +++ b/lib/src/DateRangePicker/DateRangeDay.tsx @@ -1,13 +1,19 @@ import * as React from 'react'; import clsx from 'clsx'; -import { DateRange } from './RangeTypes'; import { makeStyles, fade } from '@material-ui/core'; import { useUtils } from '../_shared/hooks/useUtils'; import { DAY_MARGIN } from '../constants/dimensions'; import { Day, DayProps } from '../views/Calendar/Day'; +import { MaterialUiPickersDate } from '../typings/date'; interface DateRangeDayProps extends DayProps { - selectedRange: DateRange; + isHighlighting: boolean; + isEndOfHighlighting: boolean; + isStartOfHighlighting: boolean; + isPreviewing: boolean; + isEndOfPreviewing: boolean; + isStartOfPreviewing: boolean; + rangePreviewDay: MaterialUiPickersDate; } const endBorderStyle = { @@ -42,47 +48,85 @@ const useStyles = makeStyles( paddingRight: 0, marginRight: DAY_MARGIN / 2, }, + day: { + // Required to overlap preview border + transform: 'scale(1.1)', + '&:hover': { + border: `2px solid ${theme.palette.grey[500]}`, + }, + }, dayInsideRangeInterval: { - backgroundColor: 'transparent', color: theme.palette.getContrastText(fade(theme.palette.primary.light, 0.6)), }, - rangeIntervalStart: {}, + notSelectedDate: { + backgroundColor: 'transparent', + }, + rangeIntervalPreview: { + borderTop: '2px solid transparent', + borderBottom: '2px solid transparent', + }, + rangeIntervalDayPreview: { + borderRadius: 0, + borderTop: `2px dashed ${theme.palette.divider}`, + borderBottom: `2px dashed ${theme.palette.divider}`, + }, + rangeIntervalDayPreviewStart: { + ...startBorderStyle, + }, + rangeIntervalDayPreviewEnd: { + ...endBorderStyle, + }, }), { name: 'MuiPickersDateRangeDay' } ); -export const DateRangeDay: React.FC = ({ - day, - selectedRange, - className, - selected, - ...other -}) => { - const utils = useUtils(); - const classes = useStyles(0); - const [start, end] = selectedRange; +export const DateRangeDay: React.FC = React.memo( + ({ + day, + className, + selected, + isPreviewing, + isStartOfPreviewing, + isEndOfPreviewing, + isHighlighting, + isEndOfHighlighting, + isStartOfHighlighting, + ...other + }) => { + const classes = useStyles(); - return ( -
- -
- ); -}; + return ( +
+
+ +
+
+ ); + } +); diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index 68d45a947..a9bff4bfb 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -32,6 +32,7 @@ export const useStyles = makeStyles( }, calendar: { minWidth: 312, + minHeight: 288, }, arrowSwitcher: { padding: '16px 16px 8px 16px', @@ -53,11 +54,45 @@ export const DesktopDateRangeCalendar: React.FC = rightArrowButtonProps, rightArrowButtonText, rightArrowIcon, + onChange, ...CalendarProps }) => { const utils = useUtils(); const classes = useStyles(); const { currentMonth } = CalendarProps; + const [start, end] = date; + const [rangePreviewDay, setRangePreviewDay] = React.useState( + new Date('2020-04-24T14:34:19.027Z') + ); + + const previewingRange: DateRange | null = Boolean(rangePreviewDay) + ? utils.isAfter(start, rangePreviewDay) + ? [rangePreviewDay, start] + : [end, rangePreviewDay] + : null; + + const handleDayChange = (day: MaterialUiPickersDate) => { + setRangePreviewDay(null); + onChange(day); + }; + + const handlePreviewDayChange = (newPreviewRequest: MaterialUiPickersDate) => { + if (!utils.isWithinRange(newPreviewRequest, date)) { + setRangePreviewDay(newPreviewRequest); + } + }; + + const isWithinRange = (day: MaterialUiPickersDate, range: DateRange | null) => { + return Boolean(range && utils.isWithinRange(day, range)); + }; + + const isStartOfRange = (day: MaterialUiPickersDate, range: DateRange | null) => { + return Boolean(range && utils.isSameDay(day, range[0])); + }; + + const isEndOfRange = (day: MaterialUiPickersDate, range: DateRange | null) => { + return Boolean(range && utils.isSameDay(day, range[1])); + }; return (
@@ -87,12 +122,26 @@ export const DesktopDateRangeCalendar: React.FC = } + renderDay={(day, _, DayProps) => ( + handlePreviewDayChange(day)} + onMouseOut={() => handlePreviewDayChange(null)} + {...DayProps} + /> + )} />
); diff --git a/lib/src/constants/dimensions.ts b/lib/src/constants/dimensions.ts index ec5cca9dc..fd31a2dab 100644 --- a/lib/src/constants/dimensions.ts +++ b/lib/src/constants/dimensions.ts @@ -2,7 +2,7 @@ export const DIALOG_WIDTH = 320; export const DIALOG_WIDTH_WIDER = 325; -export const VIEW_HEIGHT = 340; +export const VIEW_HEIGHT = 360; export const DAY_SIZE = 36; diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 3f85966af..a15c1605a 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -58,7 +58,7 @@ export interface CalendarProps extends ExportedCalendarProps { export const useStyles = makeStyles(theme => ({ transitionContainer: { - minHeight: (DAY_SIZE + DAY_MARGIN * 2) * 6, + minHeight: (DAY_SIZE + DAY_MARGIN * 4) * 6, }, transitionContainerOverflowAllowed: { overflowX: 'visible', @@ -71,7 +71,7 @@ export const useStyles = makeStyles(theme => ({ alignItems: 'center', }, week: { - margin: `${DAY_MARGIN}px 0`, + margin: `${DAY_MARGIN * 2}px 0`, display: 'flex', justifyContent: 'center', }, From f0960dda9de8893bb8db156620bedb149e577edc Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 23 Mar 2020 19:05:10 +0200 Subject: [PATCH 19/72] Optimize rerenders of Day and DateRangeDay, closes #1306 --- lib/src/DateRangePicker/DateRangeDay.tsx | 92 +++++++++++-------- .../DesktopDateRangePicker.tsx | 10 +- lib/src/views/Calendar/Calendar.tsx | 5 +- lib/src/views/Calendar/Day.tsx | 21 ++++- lib/src/views/Calendar/SlideTransition.tsx | 6 +- 5 files changed, 86 insertions(+), 48 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangeDay.tsx index 0b26f4ec3..9f2e3c9e8 100644 --- a/lib/src/DateRangePicker/DateRangeDay.tsx +++ b/lib/src/DateRangePicker/DateRangeDay.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import clsx from 'clsx'; import { makeStyles, fade } from '@material-ui/core'; -import { useUtils } from '../_shared/hooks/useUtils'; import { DAY_MARGIN } from '../constants/dimensions'; import { Day, DayProps } from '../views/Calendar/Day'; import { MaterialUiPickersDate } from '../typings/date'; @@ -13,7 +12,6 @@ interface DateRangeDayProps extends DayProps { isPreviewing: boolean; isEndOfPreviewing: boolean; isStartOfPreviewing: boolean; - rangePreviewDay: MaterialUiPickersDate; } const endBorderStyle = { @@ -80,8 +78,8 @@ const useStyles = makeStyles( { name: 'MuiPickersDateRangeDay' } ); -export const DateRangeDay: React.FC = React.memo( - ({ +const PureDateRangeDay: React.FC = ({ ...props }) => { + const { day, className, selected, @@ -92,41 +90,61 @@ export const DateRangeDay: React.FC = React.memo( isEndOfHighlighting, isStartOfHighlighting, ...other - }) => { - const classes = useStyles(); + } = props; + // useTraceUpdate(props); + const classes = useStyles(); - return ( + return ( +
-
- -
+
- ); - } -); +
+ ); +}; + +export const DateRangeDay = React.memo(PureDateRangeDay, (prevProps, nextProps) => { + return ( + prevProps.isEndOfHighlighting === nextProps.isEndOfHighlighting && + prevProps.isStartOfHighlighting === nextProps.isStartOfHighlighting && + prevProps.isPreviewing === nextProps.isPreviewing && + prevProps.isEndOfPreviewing === nextProps.isEndOfPreviewing && + prevProps.isStartOfPreviewing === nextProps.isStartOfPreviewing && + prevProps.focused === nextProps.focused && + prevProps.focusable === nextProps.focusable && + prevProps.isAnimating === nextProps.isAnimating && + prevProps.today === nextProps.today && + prevProps.disabled === nextProps.disabled && + prevProps.selected === nextProps.selected && + prevProps.allowKeyboardControl === nextProps.allowKeyboardControl && + prevProps.disableMargin === nextProps.disableMargin && + prevProps.showDaysOutsideCurrentMonth === nextProps.showDaysOutsideCurrentMonth && + prevProps.disableHighlightToday === nextProps.disableHighlightToday + ); +}); diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index a9bff4bfb..2fba301b9 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -94,6 +94,13 @@ export const DesktopDateRangeCalendar: React.FC = return Boolean(range && utils.isSameDay(day, range[1])); }; + const CalendarTransitionProps = React.useMemo( + () => ({ + onMouseLeave: () => setRangePreviewDay(null), + }), + [] + ); + return (
{new Array(calendars).fill(0).map((_, index) => { @@ -128,9 +135,9 @@ export const DesktopDateRangeCalendar: React.FC = className={classes.calendar} onChange={handleDayChange} currentMonth={monthOnIteration} + TransitionProps={CalendarTransitionProps} renderDay={(day, _, DayProps) => ( = isStartOfHighlighting={isStartOfRange(day, date)} isEndOfHighlighting={isEndOfRange(day, date)} onMouseOver={() => handlePreviewDayChange(day)} - onMouseOut={() => handlePreviewDayChange(null)} {...DayProps} /> )} diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index a15c1605a..7a89a1a6a 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import clsx from 'clsx'; -import SlideTransition, { SlideDirection } from './SlideTransition'; import { Day, DayProps } from './Day'; import { onSpaceOrEnter } from '../../_helpers/utils'; import { MaterialUiPickersDate } from '../../typings/date'; @@ -8,6 +7,7 @@ import { useUtils, useNow } from '../../_shared/hooks/useUtils'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; import { DAY_SIZE, DAY_MARGIN } from '../../constants/dimensions'; import { findClosestEnabledDate } from '../../_helpers/date-utils'; +import { SlideTransition, SlideDirection } from './SlideTransition'; import { makeStyles, useTheme, Typography } from '@material-ui/core'; import { FORCE_FINISH_PICKER } from '../../_shared/hooks/usePickerState'; import { useGlobalKeyDown, keycode } from '../../_shared/hooks/useKeyDown'; @@ -54,6 +54,7 @@ export interface CalendarProps extends ExportedCalendarProps { isMonthSwitchingAnimating: boolean; onMonthSwitchingAnimationEnd: () => void; className?: string; + TransitionProps?: Slide; } export const useStyles = makeStyles(theme => ({ @@ -119,6 +120,7 @@ export const Calendar: React.FC = ({ disableHighlightToday, showDaysOutsideCurrentMonth, className, + TransitionProps, }) => { const now = useNow(); const utils = useUtils(); @@ -188,6 +190,7 @@ export const Calendar: React.FC = ({ reduceAnimations={reduceAnimations} slideDirection={slideDirection} className={clsx(classes.transitionContainer, className)} + {...TransitionProps} >
{utils.getWeekArray(currentMonth).map(week => ( diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 425d5aea9..03cf804c5 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -101,7 +101,7 @@ export interface DayProps extends ExtendMui { disableHighlightToday?: boolean; } -export const Day: React.FC = ({ +const PureDay: React.FC = ({ className, day, disabled, @@ -169,15 +169,28 @@ export const Day: React.FC = ({ ); }; -Day.displayName = 'Day'; +export const Day = React.memo(PureDay, (prevProps, nextProps) => { + return ( + prevProps.focused === nextProps.focused && + prevProps.focusable === nextProps.focusable && + prevProps.isAnimating === nextProps.isAnimating && + prevProps.today === nextProps.today && + prevProps.disabled === nextProps.disabled && + prevProps.selected === nextProps.selected && + prevProps.allowKeyboardControl === nextProps.allowKeyboardControl && + prevProps.disableMargin === nextProps.disableMargin && + prevProps.showDaysOutsideCurrentMonth === nextProps.showDaysOutsideCurrentMonth && + prevProps.disableHighlightToday === nextProps.disableHighlightToday + ); +}); -Day.propTypes = { +PureDay.propTypes = { today: PropTypes.bool, disabled: PropTypes.bool, selected: PropTypes.bool, }; -Day.defaultProps = { +PureDay.defaultProps = { disabled: false, today: false, selected: false, diff --git a/lib/src/views/Calendar/SlideTransition.tsx b/lib/src/views/Calendar/SlideTransition.tsx index 992529250..e6020c007 100644 --- a/lib/src/views/Calendar/SlideTransition.tsx +++ b/lib/src/views/Calendar/SlideTransition.tsx @@ -5,7 +5,7 @@ import { CSSTransition, TransitionGroup } from 'react-transition-group'; import { CSSTransitionProps } from 'react-transition-group/CSSTransition'; export type SlideDirection = 'right' | 'left'; -interface SlideTransitionProps extends Omit { +export interface SlideTransitionProps extends Omit { transKey: React.Key; className?: string; reduceAnimations: boolean; @@ -67,7 +67,7 @@ export const useStyles = makeStyles( { name: 'MuiPickersSlideTransition' } ); -const SlideTransition: React.SFC = ({ +export const SlideTransition: React.SFC = ({ children, transKey, reduceAnimations, @@ -110,5 +110,3 @@ const SlideTransition: React.SFC = ({ ); }; - -export default SlideTransition; From 61341c6cb94489c2479a6fc6768b837a564162b9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 23 Mar 2020 19:10:04 +0200 Subject: [PATCH 20/72] Fix crash and missing rerender --- lib/src/DateRangePicker/DateRangeDay.tsx | 4 ++++ lib/src/DateRangePicker/DesktopDateRangePicker.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangeDay.tsx index 9f2e3c9e8..7ee155365 100644 --- a/lib/src/DateRangePicker/DateRangeDay.tsx +++ b/lib/src/DateRangePicker/DateRangeDay.tsx @@ -49,6 +49,9 @@ const useStyles = makeStyles( day: { // Required to overlap preview border transform: 'scale(1.1)', + '& > *': { + transform: 'scale(0.9)', + }, '&:hover': { border: `2px solid ${theme.palette.grey[500]}`, }, @@ -131,6 +134,7 @@ const PureDateRangeDay: React.FC = ({ ...props }) => { export const DateRangeDay = React.memo(PureDateRangeDay, (prevProps, nextProps) => { return ( + prevProps.isHighlighting === nextProps.isHighlighting && prevProps.isEndOfHighlighting === nextProps.isEndOfHighlighting && prevProps.isStartOfHighlighting === nextProps.isStartOfHighlighting && prevProps.isPreviewing === nextProps.isPreviewing && diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index 2fba301b9..c096a26a3 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -83,7 +83,7 @@ export const DesktopDateRangeCalendar: React.FC = }; const isWithinRange = (day: MaterialUiPickersDate, range: DateRange | null) => { - return Boolean(range && utils.isWithinRange(day, range)); + return Boolean(range && utils.isBefore(range[0], range[1]) && utils.isWithinRange(day, range)); }; const isStartOfRange = (day: MaterialUiPickersDate, range: DateRange | null) => { From 9d026403ef601e26dbb4ce8899a1bef6cdd74a79 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 24 Mar 2020 14:45:20 +0200 Subject: [PATCH 21/72] Optimize rerendering performace of --- lib/src/DateRangePicker/DateRangeDay.tsx | 79 ++++++++++--------- .../DesktopDateRangePicker.tsx | 27 ++++--- lib/src/_helpers/utils.ts | 9 ++- lib/src/_shared/ArrowSwitcher.tsx | 19 +++-- lib/src/_shared/hooks/useTraceUpdate.tsx | 19 +++++ lib/src/views/Calendar/Calendar.tsx | 7 +- lib/src/views/Calendar/Day.tsx | 55 ++++++++++--- 7 files changed, 144 insertions(+), 71 deletions(-) create mode 100644 lib/src/_shared/hooks/useTraceUpdate.tsx diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangeDay.tsx index 7ee155365..b8a83b22a 100644 --- a/lib/src/DateRangePicker/DateRangeDay.tsx +++ b/lib/src/DateRangePicker/DateRangeDay.tsx @@ -2,8 +2,8 @@ import * as React from 'react'; import clsx from 'clsx'; import { makeStyles, fade } from '@material-ui/core'; import { DAY_MARGIN } from '../constants/dimensions'; -import { Day, DayProps } from '../views/Calendar/Day'; -import { MaterialUiPickersDate } from '../typings/date'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { Day, DayProps, areDayPropsEqual } from '../views/Calendar/Day'; interface DateRangeDayProps extends DayProps { isHighlighting: boolean; @@ -15,19 +15,21 @@ interface DateRangeDayProps extends DayProps { } const endBorderStyle = { - borderTopRightRadius: '60%', - borderBottomRightRadius: '60%', + borderTopRightRadius: '50%', + borderBottomRightRadius: '50%', }; const startBorderStyle = { - borderTopLeftRadius: '60%', - borderBottomLeftRadius: '60%', + borderTopLeftRadius: '50%', + borderBottomLeftRadius: '50%', }; const useStyles = makeStyles( theme => ({ rangeIntervalDay: { padding: `0 ${DAY_MARGIN}px`, + '&:first-child $rangeIntervalDayPreview': startBorderStyle, + '&:last-child $rangeIntervalDayPreview': endBorderStyle, }, rangeIntervalDayHighlight: { borderRadius: 0, @@ -52,8 +54,10 @@ const useStyles = makeStyles( '& > *': { transform: 'scale(0.9)', }, + }, + dayOutsideRangeInterval: { '&:hover': { - border: `2px solid ${theme.palette.grey[500]}`, + border: `1px solid ${theme.palette.grey[500]}`, }, }, dayInsideRangeInterval: { @@ -81,47 +85,51 @@ const useStyles = makeStyles( { name: 'MuiPickersDateRangeDay' } ); -const PureDateRangeDay: React.FC = ({ ...props }) => { - const { - day, - className, - selected, - isPreviewing, - isStartOfPreviewing, - isEndOfPreviewing, - isHighlighting, - isEndOfHighlighting, - isStartOfHighlighting, - ...other - } = props; - // useTraceUpdate(props); +export const PureDateRangeDay = ({ + day, + className, + selected, + isPreviewing, + isStartOfPreviewing, + isEndOfPreviewing, + isHighlighting, + isEndOfHighlighting, + isStartOfHighlighting, + inCurrentMonth, + ...other +}: DateRangeDayProps) => { + const utils = useUtils(); const classes = useStyles(); + const isEndOfMonth = utils.isSameDay(day, utils.endOfMonth(day)); + const isStartOfMonth = utils.isSameDay(day, utils.startOfMonth(day)); + return (
= ({ ...props }) => { ); }; +PureDateRangeDay.displayName = 'DateRangeDay'; + export const DateRangeDay = React.memo(PureDateRangeDay, (prevProps, nextProps) => { return ( prevProps.isHighlighting === nextProps.isHighlighting && @@ -140,15 +150,6 @@ export const DateRangeDay = React.memo(PureDateRangeDay, (prevProps, nextProps) prevProps.isPreviewing === nextProps.isPreviewing && prevProps.isEndOfPreviewing === nextProps.isEndOfPreviewing && prevProps.isStartOfPreviewing === nextProps.isStartOfPreviewing && - prevProps.focused === nextProps.focused && - prevProps.focusable === nextProps.focusable && - prevProps.isAnimating === nextProps.isAnimating && - prevProps.today === nextProps.today && - prevProps.disabled === nextProps.disabled && - prevProps.selected === nextProps.selected && - prevProps.allowKeyboardControl === nextProps.allowKeyboardControl && - prevProps.disableMargin === nextProps.disableMargin && - prevProps.showDaysOutsideCurrentMonth === nextProps.showDaysOutsideCurrentMonth && - prevProps.disableHighlightToday === nextProps.disableHighlightToday + areDayPropsEqual(prevProps, nextProps) ); }); diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index c096a26a3..9c051ef6d 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import { DateRange } from './RangeTypes'; import { DateRangeDay } from './DateRangeDay'; +import { makeStyles } from '@material-ui/core'; import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; -import { makeStyles, Typography } from '@material-ui/core'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; @@ -61,9 +61,7 @@ export const DesktopDateRangeCalendar: React.FC = const classes = useStyles(); const { currentMonth } = CalendarProps; const [start, end] = date; - const [rangePreviewDay, setRangePreviewDay] = React.useState( - new Date('2020-04-24T14:34:19.027Z') - ); + const [rangePreviewDay, setRangePreviewDay] = React.useState(null); const previewingRange: DateRange | null = Boolean(rangePreviewDay) ? utils.isAfter(start, rangePreviewDay) @@ -101,6 +99,14 @@ export const DesktopDateRangeCalendar: React.FC = [] ); + const selectNextMonth = React.useCallback(() => { + changeMonth(utils.getNextMonth(currentMonth)); + }, [changeMonth, currentMonth, utils]); + + const selectPreviousMonth = React.useCallback(() => { + changeMonth(utils.getPreviousMonth(currentMonth)); + }, [changeMonth, currentMonth, utils]); + return (
{new Array(calendars).fill(0).map((_, index) => { @@ -110,8 +116,8 @@ export const DesktopDateRangeCalendar: React.FC =
changeMonth(utils.getPreviousMonth(currentMonth))} - onRightClick={() => changeMonth(utils.getNextMonth(currentMonth))} + onLeftClick={selectPreviousMonth} + onRightClick={selectNextMonth} isLeftHidden={index !== 0} isRightHidden={index !== calendars - 1} isLeftDisabled={false} @@ -122,11 +128,8 @@ export const DesktopDateRangeCalendar: React.FC = rightArrowButtonProps={rightArrowButtonProps} rightArrowButtonText={rightArrowButtonText} rightArrowIcon={rightArrowIcon} - > - - {utils.format(monthOnIteration, 'monthAndYear')} - - + text={utils.format(monthOnIteration, 'monthAndYear')} + /> = isHighlighting={isWithinRange(day, date)} isStartOfHighlighting={isStartOfRange(day, date)} isEndOfHighlighting={isEndOfRange(day, date)} - onMouseOver={() => handlePreviewDayChange(day)} + onMouseEnter={() => handlePreviewDayChange(day)} {...DayProps} /> )} diff --git a/lib/src/_helpers/utils.ts b/lib/src/_helpers/utils.ts index 656885111..75297ab91 100644 --- a/lib/src/_helpers/utils.ts +++ b/lib/src/_helpers/utils.ts @@ -9,7 +9,10 @@ export function arrayIncludes(array: T[] | readonly T[], itemOrItems: T | T[] return array.indexOf(itemOrItems) !== -1; } -export const onSpaceOrEnter = (innerFn: () => void) => (e: React.KeyboardEvent) => { +export const onSpaceOrEnter = ( + innerFn: () => void, + onFocus?: (e: React.KeyboardEvent) => void +) => (e: React.KeyboardEvent) => { if (e.key === 'Enter' || e.key === ' ') { innerFn(); @@ -17,6 +20,10 @@ export const onSpaceOrEnter = (innerFn: () => void) => (e: React.KeyboardEvent) e.preventDefault(); e.stopPropagation(); } + + if (onFocus) { + onFocus(e); + } }; /** Quick untyped helper to improve function composition readability */ diff --git a/lib/src/_shared/ArrowSwitcher.tsx b/lib/src/_shared/ArrowSwitcher.tsx index 8054d86d3..8d8917ef4 100644 --- a/lib/src/_shared/ArrowSwitcher.tsx +++ b/lib/src/_shared/ArrowSwitcher.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import clsx from 'clsx'; import { ArrowLeftIcon } from './icons/ArrowLeftIcon'; import { ArrowRightIcon } from './icons/ArrowRightIcon'; -import { IconButton, IconButtonProps, makeStyles, useTheme } from '@material-ui/core'; +import { IconButton, IconButtonProps, makeStyles, useTheme, Typography } from '@material-ui/core'; export interface ExportedArrowSwitcherProps { /** Left arrow icon */ @@ -32,6 +32,7 @@ interface ArrowSwitcherProps extends ExportedArrowSwitcherProps, React.HTMLProps isRightDisabled: boolean; onLeftClick: () => void; onRightClick: () => void; + text?: string; } export const useStyles = makeStyles( @@ -50,7 +51,7 @@ export const useStyles = makeStyles( { name: 'MuiPickersArrowSwitcher' } ); -export const ArrowSwitcher: React.FC = ({ +const PureArrowSwitcher: React.FC = ({ className, leftArrowButtonProps, leftArrowButtonText, @@ -64,7 +65,7 @@ export const ArrowSwitcher: React.FC = ({ onRightClick, leftArrowIcon = , rightArrowIcon = , - children, + text, ...other }) => { const classes = useStyles(); @@ -82,13 +83,17 @@ export const ArrowSwitcher: React.FC = ({ onClick={onLeftClick} className={clsx(classes.iconButton, leftArrowButtonProps?.className, { [classes.hidden]: Boolean(isLeftHidden), - [classes.previousMonthButtonMargin]: !Boolean(children), + [classes.previousMonthButtonMargin]: !Boolean(text), })} > {isRtl ? rightArrowIcon : leftArrowIcon} - {children} + {text && ( + + {text} + + )} = ({
); }; + +PureArrowSwitcher.displayName = 'ArrowSwitcher'; + +export const ArrowSwitcher = React.memo(PureArrowSwitcher); diff --git a/lib/src/_shared/hooks/useTraceUpdate.tsx b/lib/src/_shared/hooks/useTraceUpdate.tsx new file mode 100644 index 000000000..cd5ac981b --- /dev/null +++ b/lib/src/_shared/hooks/useTraceUpdate.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +// ! Important not to use this hook in production build + +export function useDebuggingTraceUpdate(props: any) { + const prev = React.useRef(props); + React.useEffect(() => { + // @ts-ignore + const changedProps = Object.entries(props).reduce((ps, [k, v]) => { + if (prev.current[k] !== v) { + ps[k] = [prev.current[k], v]; + } + return ps; + }, {}); + if (Object.keys(changedProps).length > 0) { + console.log('Changed props:', changedProps); + } + prev.current = props; + }); +} diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 7a89a1a6a..851dfc6ec 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -214,11 +214,8 @@ export const Calendar: React.FC = ({ focusable: Boolean(nowFocusedDay) && utils.toJsDate(nowFocusedDay).getDate() === utils.toJsDate(day).getDate(), - onFocus: () => changeFocusedDay(day), - onClick: () => !disabled && handleDaySelect(day, true), - onKeyDown: onSpaceOrEnter( - () => !disabled && handleDaySelect(day, FORCE_FINISH_PICKER) - ), + onDayFocus: changeFocusedDay, + onDaySelect: handleDaySelect, }; return renderDay ? renderDay(day, selectedDates, dayProps) : ; diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 03cf804c5..b0527e4f1 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -2,11 +2,13 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; import clsx from 'clsx'; import { ExtendMui } from '../../typings/helpers'; +import { onSpaceOrEnter } from '../../_helpers/utils'; import { useUtils } from '../../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../../typings/date'; import { makeStyles, fade } from '@material-ui/core/styles'; import { ButtonBase, ButtonBaseProps } from '@material-ui/core'; import { DAY_SIZE, DAY_MARGIN } from '../../constants/dimensions'; +import { FORCE_FINISH_PICKER } from '../../_shared/hooks/usePickerState'; export const useStyles = makeStyles( theme => ({ @@ -99,6 +101,8 @@ export interface DayProps extends ExtendMui { * @default false */ disableHighlightToday?: boolean; + onDayFocus: (day: MaterialUiPickersDate) => void; + onDaySelect: (day: MaterialUiPickersDate, isFinish: boolean | symbol) => void; } const PureDay: React.FC = ({ @@ -112,7 +116,11 @@ const PureDay: React.FC = ({ focused = false, focusable = false, isAnimating, + onDayFocus, + onDaySelect, onFocus, + onClick, + onKeyDown, disableMargin = false, allowKeyboardControl, disableHighlightToday = false, @@ -132,10 +140,36 @@ const PureDay: React.FC = ({ ref.current && allowKeyboardControl ) { - ref.current.focus(); + // ref.current.focus(); } }, [allowKeyboardControl, disabled, focused, isAnimating, isInCurrentMonth]); + const handleFocus = (e: React.FocusEvent) => { + if (!focused) { + onDayFocus(day); + } + + if (onFocus) { + onFocus(e); + } + }; + + const handleClick = (e: React.MouseEvent) => { + if (!disabled) { + onDaySelect(day, true); + } + + if (onClick) { + onClick(e); + } + }; + + const handleKeyDown = onSpaceOrEnter(() => { + if (!disabled) { + onDaySelect(day, FORCE_FINISH_PICKER); + } + }, onKeyDown); + const isHidden = !isInCurrentMonth && !showDaysOutsideCurrentMonth; return ( = ({ }, className )} - onFocus={e => { - if (!focused && onFocus) { - onFocus(e); - } - }} {...other} + onFocus={handleFocus} + onKeyDown={handleKeyDown} + onClick={handleClick} > {utils.format(day, 'dayOfMonth')} ); }; -export const Day = React.memo(PureDay, (prevProps, nextProps) => { +export const areDayPropsEqual = (prevProps: DayProps, nextProps: DayProps) => { return ( prevProps.focused === nextProps.focused && prevProps.focusable === nextProps.focusable && @@ -180,9 +212,14 @@ export const Day = React.memo(PureDay, (prevProps, nextProps) => { prevProps.allowKeyboardControl === nextProps.allowKeyboardControl && prevProps.disableMargin === nextProps.disableMargin && prevProps.showDaysOutsideCurrentMonth === nextProps.showDaysOutsideCurrentMonth && - prevProps.disableHighlightToday === nextProps.disableHighlightToday + prevProps.disableHighlightToday === nextProps.disableHighlightToday && + prevProps.className === nextProps.className ); -}); +}; + +export const Day = React.memo(PureDay, areDayPropsEqual); + +PureDay.displayName = 'Day'; PureDay.propTypes = { today: PropTypes.bool, From 71c675452f4669183644c07a6366e7b643ffd779 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 24 Mar 2020 15:11:06 +0200 Subject: [PATCH 22/72] Use popper for date range wrapper --- lib/src/DateRangePicker/DateRangePicker.tsx | 4 +- lib/src/_shared/hooks/useKeyDown.ts | 1 + lib/src/_shared/hooks/usePickerState.ts | 5 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 66 +++++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 lib/src/wrappers/DesktopPopperWrapper.tsx diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 29b3eb320..b63747194 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -2,12 +2,12 @@ import * as React from 'react'; import { DateRange, RangeInput } from './RangeTypes'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; -import { DesktopWrapper } from '../wrappers/DesktopWrapper'; import { DateRangePickerInput } from './DateRangePickerInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { AllSharedPickerProps } from '../Picker/SharedPickerProps'; +import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { DateRangePickerView, DateRangePickerViewProps } from './DateRangePickerView'; @@ -83,4 +83,4 @@ export function makeRangePicker(Wrapper: TWrapper) return RangePickerWithStateAndWrapper; } -export const DateRangePicker = makeRangePicker(DesktopWrapper); +export const DateRangePicker = makeRangePicker(DesktopPopperWrapper); diff --git a/lib/src/_shared/hooks/useKeyDown.ts b/lib/src/_shared/hooks/useKeyDown.ts index 65ffd7be0..cab390f8d 100644 --- a/lib/src/_shared/hooks/useKeyDown.ts +++ b/lib/src/_shared/hooks/useKeyDown.ts @@ -55,4 +55,5 @@ export const keycode = { End: 35, PageUp: 33, PageDown: 34, + Esc: 27, }; diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 5c1766ed2..48c8b2cb6 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -40,11 +40,10 @@ export function usePickerState( const { isOpen, setIsOpen } = useOpenState(props); useEffect(() => { - // if value was changed in closed state or from mobile keyboard view - treat it as accepted - if ((!isOpen || isMobileKeyboardViewOpen) && !valueManager.areValuesEqual(pickerDate, date)) { + if (!valueManager.areValuesEqual(pickerDate, date)) { setPickerDate(date); } - }, [date, isMobileKeyboardViewOpen, isOpen, pickerDate, utils, valueManager]); + }, [value]); // eslint-disable-line const acceptDate = useCallback( (acceptedDate: TDateValue | null, needClosePicker: boolean) => { diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx new file mode 100644 index 000000000..00b8711dd --- /dev/null +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import Paper from '@material-ui/core/Paper'; +import Popper, { PopperProps } from '@material-ui/core/Popper'; +import ClickAwayListener from '@material-ui/core/ClickAwayListener'; +import { WrapperProps } from './Wrapper'; +import { InnerMobileWrapperProps } from './MobileWrapper'; +import { WrapperVariantContext } from './WrapperVariantContext'; +import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; +import { useGlobalKeyDown, keycode } from '../_shared/hooks/useKeyDown'; + +export interface InnerDesktopPopperWrapperProps { + /** Popover props passed to material-ui Popover */ + PopperProps?: Partial; +} + +export interface DesktopWrapperProps + extends InnerDesktopPopperWrapperProps, + WrapperProps, + Partial {} + +export const DesktopPopperWrapper: React.FC = ({ + open, + wider, + children, + PopperProps, + onClear, + onDismiss, + onSetToday, + onAccept, + showTabs, + DateInputProps, + okLabel, + cancelLabel, + clearLabel, + todayLabel, + showTodayButton, + clearable, + DialogProps, + PureDateInputComponent, + KeyboardDateInputComponent = KeyboardDateInput, + ...other +}) => { + const ref = React.useRef(null); + + useGlobalKeyDown(open, { + [keycode.Esc]: onDismiss, + }); + + return ( + + + + + + {children} + + + + ); +}; From 3bea3586dd6d8300ada9949e3332b8311f917cfd Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 24 Mar 2020 16:47:28 +0200 Subject: [PATCH 23/72] Proper displaying values in DateRangePIckerInput --- lib/src/DateRangePicker/DateRangePicker.tsx | 24 ++++-- .../DateRangePicker/DateRangePickerInput.tsx | 73 ++++++++++++++++--- lib/src/_shared/KeyboardDateInput.tsx | 1 + lib/src/_shared/PureDateInput.tsx | 2 + lib/src/_shared/hooks/usePickerState.ts | 3 +- lib/src/typings/overrides.ts | 3 + 6 files changed, 89 insertions(+), 17 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index b63747194..64ed040a0 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { DateRange, RangeInput } from './RangeTypes'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; -import { DateRangePickerInput } from './DateRangePickerInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; @@ -11,6 +10,7 @@ import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { DateRangePickerView, DateRangePickerViewProps } from './DateRangePickerView'; +import { DateRangePickerInput, DateRangePickerInputSpecificProps } from './DateRangePickerInput'; export function parseRangeInputValue( now: MaterialUiPickersDate, @@ -39,8 +39,10 @@ export function makeRangePicker(Wrapper: TWrapper) onMonthChange, disableHighlightToday, reduceAnimations, + inputFormat: passedInputFormat, ...other }: DateRangePickerViewProps & + DateRangePickerInputSpecificProps & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); @@ -48,11 +50,19 @@ export function makeRangePicker(Wrapper: TWrapper) 'start' | 'end' >('start'); - const { pickerProps, inputProps, wrapperProps } = usePickerState(other, { - parseInput: parseRangeInputValue, - areValuesEqual: (a, b) => utils.isEqual(a[0], b[0]) && utils.isEqual(a[1], b[1]), - validateInput: () => undefined, - }); + const pickerStateProps = { + ...other, + inputFormat: passedInputFormat || utils.formats.keyboardDate, + }; + + const { pickerProps, inputProps, wrapperProps } = usePickerState( + pickerStateProps, + { + parseInput: parseRangeInputValue, + areValuesEqual: (a, b) => utils.isEqual(a[0], b[0]) && utils.isEqual(a[1], b[1]), + validateInput: () => undefined, + } + ); return ( @@ -77,7 +87,7 @@ export function makeRangePicker(Wrapper: TWrapper) } RangePickerWithStateAndWrapper.defaultProps = { - inputFormat: 'MM', + mask: '__/__/____', }; return RangePickerWithStateAndWrapper; diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 8da7500bb..c5ad12502 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -1,20 +1,75 @@ import * as React from 'react'; import KeyboardDateInput from '../_shared/KeyboardDateInput'; -import { TextField } from '@material-ui/core'; +import { RangeInput, DateRange } from './RangeTypes'; +import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; -import { RangeInput, DateRange } from './DateRangePicker'; +import { makeStyles, Typography } from '@material-ui/core'; -export const DateRangePickerInput: React.FC> = ({ +export const useStyles = makeStyles( + _ => ({ + rangeInputsContainer: { + display: 'flex', + alignItems: 'center', + }, + toLabelDelimiter: { + margin: '0 16px', + }, + }), + { name: 'MuiPickersDateRangePickerInput' } +); + +export interface DateRangePickerInputSpecificProps { + toText?: React.ReactNode; +} + +// prettier-ignore +export const DateRangePickerInput: React.FC< + DateRangePickerInputSpecificProps & + DateInputProps +> = ({ + toText = 'to', rawValue, onChange, + onClick, + parsedDateValue, ...other }) => { - console.log(rawValue); - const [start, end] = rawValue; + const classes = useStyles(); + const [start, end] = parsedDateValue ?? [null, null]; + const handleStartChange = (date: MaterialUiPickersDate, inputString?: string) => { + onChange([date, end], inputString); + }; + + const handleEndChange = (date: MaterialUiPickersDate, inputString?: string) => { + onChange([start, date], inputString); + }; + + const sharedInputProps = { + onClicK: other.openPicker, + onFocus: other.openPicker + } + return ( - <> - - - +
+ + + {toText} + + +
); }; diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index 374dd4816..4d54de567 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -37,6 +37,7 @@ export const KeyboardDateInput: React.FC = ({ ignoreInvalidInputs, onFocus, onBlur, + parsedDateValue, getOpenDialogAriaText = getTextFieldAriaText, ...other }) => { diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 15ccf2b12..e1e979315 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -12,6 +12,7 @@ import { getDisplayDate, getTextFieldAriaText } from '../_helpers/text-field-hel export interface DateInputProps extends ExtendMui { rawValue: TInputValue; + parsedDateValue: TDateValue | null; inputFormat: string; onChange: (date: TDateValue | null, keyboardInputValue?: string) => void; openPicker: () => void; @@ -97,6 +98,7 @@ export const PureDateInput: React.FC = ({ ignoreInvalidInputs, KeyboardButtonProps, disableMaskedInput, + parsedDateValue, getOpenDialogAriaText = getTextFieldAriaText, ...other }) => { diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 48c8b2cb6..3b5e5dd6c 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -125,9 +125,10 @@ export function usePickerState( inputFormat, rawValue: value, validationError, + parsedDateValue: date, openPicker: () => !readOnly && !disabled && setIsOpen(true), }), - [disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] + [date, disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] ); const pickerState = { pickerProps, inputProps, wrapperProps }; diff --git a/lib/src/typings/overrides.ts b/lib/src/typings/overrides.ts index 134ddae01..f10d3eb84 100644 --- a/lib/src/typings/overrides.ts +++ b/lib/src/typings/overrides.ts @@ -66,4 +66,7 @@ export interface MuiPickersOverrides { typeof import('../DateRangePicker/DesktopDateRangePicker').useStyles >; MuiPickersArrowSwitcher?: Classes; + MuiPickersDateRangePickerInput?: Classes< + typeof import('../DateRangePicker/DateRangePickerInput').useStyles + >; } From 6a606f3ddb5e5c349db78b906098e6977317a425 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 24 Mar 2020 19:07:04 +0200 Subject: [PATCH 24/72] Implement ClickAwayListner for popper wrapper --- .../DateRangePicker/DateRangePickerInput.tsx | 3 ++- .../DateRangePicker/DateRangePickerView.tsx | 4 +-- .../DesktopDateRangePicker.tsx | 4 +-- lib/src/views/Calendar/Calendar.tsx | 1 + lib/src/wrappers/DesktopPopperWrapper.tsx | 25 +++++++++++-------- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 145a9879a..2c9cd5d5a 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -45,8 +45,9 @@ export const DateRangePickerInput: React.FC< }; const sharedInputProps = { + onFocus: other.openPicker, // onClick: other.openPicker, - onFocus: other.openPicker + // onFocus: other.openPicker } return ( diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 1108e6e46..5f9bcd8db 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -8,7 +8,7 @@ import { useCalendarState } from '../views/Calendar/useCalendarState'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; import { ExportedCalendarViewProps, defaultReduceAnimations } from '../views/Calendar/CalendarView'; import { - DesktopDateRangeCalendar, + DesktopDateRangePicker, ExportedDesktopDateRangeCalendarProps, } from './DesktopDateRangePicker'; @@ -76,7 +76,7 @@ export const DateRangePickerView: React.FC = ({ switch (wrapperVariant) { case 'desktop': { return ( - = ({ +export const DesktopDateRangePicker: React.FC = ({ date, calendars = 2, changeMonth, @@ -113,7 +113,7 @@ export const DesktopDateRangeCalendar: React.FC = const monthOnIteration = utils.setMonth(currentMonth, utils.getMonth(currentMonth) + index); return ( -
+
= ({ const isDayInCurrentMonth = utils.getMonth(day) === currentMonthNumber; const dayProps: DayProps = { + key: day?.toString(), day: day, role: 'cell', isAnimating: isMonthSwitchingAnimating, diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 00b8711dd..498efbff9 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -40,24 +40,29 @@ export const DesktopPopperWrapper: React.FC = ({ KeyboardDateInputComponent = KeyboardDateInput, ...other }) => { - const ref = React.useRef(null); + const ref = React.useRef(null); useGlobalKeyDown(open, { [keycode.Esc]: onDismiss, }); + const handleClickAway = (e: React.MouseEvent) => { + if (!open || (e.target as HTMLElement)?.dataset?.muiPickersInput !== 'true') { + onDismiss(); + } + }; + return ( - + - - + + {children} From 99978af2f71e4c2bacad2b26f344abb9ed048eed Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 24 Mar 2020 19:34:40 +0200 Subject: [PATCH 25/72] Fix slide animation in date range picker --- lib/src/DateRangePicker/DateRangePickerInput.tsx | 12 ++++++++---- lib/src/DateRangePicker/DesktopDateRangePicker.tsx | 2 +- lib/src/views/Calendar/Calendar.tsx | 6 ++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 2c9cd5d5a..ba994cfa2 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import KeyboardDateInput from '../_shared/KeyboardDateInput'; import { RangeInput, DateRange } from './RangeTypes'; +import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { makeStyles, Typography } from '@material-ui/core'; @@ -34,20 +35,23 @@ export const DateRangePickerInput: React.FC< parsedDateValue, ...other }) => { + const utils = useUtils() const classes = useStyles(); const [start, end] = parsedDateValue ?? [null, null]; const handleStartChange = (date: MaterialUiPickersDate, inputString?: string) => { - onChange([date, end], inputString); + if (date === null || utils.isValid(date)) { + onChange([date, end], inputString); + } }; const handleEndChange = (date: MaterialUiPickersDate, inputString?: string) => { - onChange([start, date], inputString); + if (utils.isValid(date)) { + onChange([start, date], inputString); + } }; const sharedInputProps = { onFocus: other.openPicker, - // onClick: other.openPicker, - // onFocus: other.openPicker } return ( diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index 9bf98793c..a6717ce29 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -113,7 +113,7 @@ export const DesktopDateRangePicker: React.FC = ( const monthOnIteration = utils.setMonth(currentMonth, utils.getMonth(currentMonth) + index); return ( -
+
{ @@ -54,7 +52,7 @@ export interface CalendarProps extends ExportedCalendarProps { isMonthSwitchingAnimating: boolean; onMonthSwitchingAnimationEnd: () => void; className?: string; - TransitionProps?: Slide; + TransitionProps?: SlideTransitionProps; } export const useStyles = makeStyles(theme => ({ From b87ddc249465e602709d2698611d42d972365188 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 25 Mar 2020 14:09:21 +0200 Subject: [PATCH 26/72] Reorganize test folders --- .../MuiPickersUtilsProvider.test.tsx | 21 ------------------- .../{_helpers => }/date-utils.test.tsx | 4 ++-- .../{_shared => shallow}/ModalDialog.test.tsx | 0 .../{DatePicker => shallow}/Month.test.tsx | 0 .../MonthSelection.test.tsx | 0 .../{_helpers => }/text-field-helper.test.tsx | 4 ++-- 6 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 lib/src/__tests__/MuiPickersUtilsProvider.test.tsx rename lib/src/__tests__/{_helpers => }/date-utils.test.tsx (98%) rename lib/src/__tests__/{_shared => shallow}/ModalDialog.test.tsx (100%) rename lib/src/__tests__/{DatePicker => shallow}/Month.test.tsx (100%) rename lib/src/__tests__/{DatePicker => shallow}/MonthSelection.test.tsx (100%) rename lib/src/__tests__/{_helpers => }/text-field-helper.test.tsx (96%) diff --git a/lib/src/__tests__/MuiPickersUtilsProvider.test.tsx b/lib/src/__tests__/MuiPickersUtilsProvider.test.tsx deleted file mode 100644 index 3daec6844..000000000 --- a/lib/src/__tests__/MuiPickersUtilsProvider.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -// required to use just shallow here because utils prop override -import * as React from 'react'; -import DateFnsUtils from '@date-io/date-fns'; -import LocalizationProvider, { LocalizationProviderProps } from '../LocalizationProvider'; -import { shallow, ShallowWrapper } from 'enzyme'; // required to use just shallow here because utils prop override - -describe('LocalizationProvider', () => { - let component: ShallowWrapper; - - beforeEach(() => { - component = shallow( - -
- - ); - }); - - it('Should render context provider', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/lib/src/__tests__/_helpers/date-utils.test.tsx b/lib/src/__tests__/date-utils.test.tsx similarity index 98% rename from lib/src/__tests__/_helpers/date-utils.test.tsx rename to lib/src/__tests__/date-utils.test.tsx index 15abd71d7..9b51df67f 100644 --- a/lib/src/__tests__/_helpers/date-utils.test.tsx +++ b/lib/src/__tests__/date-utils.test.tsx @@ -1,5 +1,5 @@ -import { utilsToUse } from '../test-utils'; -import { findClosestEnabledDate } from '../../_helpers/date-utils'; +import { utilsToUse } from './test-utils'; +import { findClosestEnabledDate } from '../_helpers/date-utils'; describe('findClosestEnabledDate', () => { const day18thText = utilsToUse.format(utilsToUse.date('2018-08-18'), 'dayOfMonth'); diff --git a/lib/src/__tests__/_shared/ModalDialog.test.tsx b/lib/src/__tests__/shallow/ModalDialog.test.tsx similarity index 100% rename from lib/src/__tests__/_shared/ModalDialog.test.tsx rename to lib/src/__tests__/shallow/ModalDialog.test.tsx diff --git a/lib/src/__tests__/DatePicker/Month.test.tsx b/lib/src/__tests__/shallow/Month.test.tsx similarity index 100% rename from lib/src/__tests__/DatePicker/Month.test.tsx rename to lib/src/__tests__/shallow/Month.test.tsx diff --git a/lib/src/__tests__/DatePicker/MonthSelection.test.tsx b/lib/src/__tests__/shallow/MonthSelection.test.tsx similarity index 100% rename from lib/src/__tests__/DatePicker/MonthSelection.test.tsx rename to lib/src/__tests__/shallow/MonthSelection.test.tsx diff --git a/lib/src/__tests__/_helpers/text-field-helper.test.tsx b/lib/src/__tests__/text-field-helper.test.tsx similarity index 96% rename from lib/src/__tests__/_helpers/text-field-helper.test.tsx rename to lib/src/__tests__/text-field-helper.test.tsx index e86c74a9c..144b699e5 100644 --- a/lib/src/__tests__/_helpers/text-field-helper.test.tsx +++ b/lib/src/__tests__/text-field-helper.test.tsx @@ -1,11 +1,11 @@ import LuxonUtils from '@date-io/luxon'; import DateFnsUtils from '@date-io/date-fns'; -import { utilsToUse } from '../test-utils'; +import { utilsToUse } from './test-utils'; import { maskedDateFormatter, pick12hOr24hFormat, checkMaskIsValidForCurrentFormat, -} from '../../_helpers/text-field-helper'; +} from '../_helpers/text-field-helper'; const refuse = /[\d]/gi; describe('test-field-helper', () => { From 983301f31e430fc182ea59e3957a4bb87f05839d Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 25 Mar 2020 14:11:11 +0200 Subject: [PATCH 27/72] Reorganize integration test folder --- lib/src/__tests__/{e2e => }/DatePicker.test.tsx | 6 +++--- lib/src/__tests__/{e2e => }/DatePickerProps.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/DatePickerRoot.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/DateTimePicker.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/DateTimePickerRoot.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/KeyboardDatePicker.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/KeyboardDateTimePicker.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/Theme.test.tsx | 6 +++--- lib/src/__tests__/{e2e => }/TimePicker.test.tsx | 4 ++-- lib/src/__tests__/{e2e => }/commands.tsx | 0 lib/src/__tests__/test-utils.tsx | 2 +- lib/src/__tests__/{ => unit}/date-utils.test.tsx | 4 ++-- lib/src/__tests__/{ => unit}/text-field-helper.test.tsx | 4 ++-- 13 files changed, 25 insertions(+), 25 deletions(-) rename lib/src/__tests__/{e2e => }/DatePicker.test.tsx (98%) rename lib/src/__tests__/{e2e => }/DatePickerProps.test.tsx (95%) rename lib/src/__tests__/{e2e => }/DatePickerRoot.test.tsx (96%) rename lib/src/__tests__/{e2e => }/DateTimePicker.test.tsx (94%) rename lib/src/__tests__/{e2e => }/DateTimePickerRoot.test.tsx (94%) rename lib/src/__tests__/{e2e => }/KeyboardDatePicker.test.tsx (97%) rename lib/src/__tests__/{e2e => }/KeyboardDateTimePicker.test.tsx (89%) rename lib/src/__tests__/{e2e => }/Theme.test.tsx (81%) rename lib/src/__tests__/{e2e => }/TimePicker.test.tsx (99%) rename lib/src/__tests__/{e2e => }/commands.tsx (100%) rename lib/src/__tests__/{ => unit}/date-utils.test.tsx (98%) rename lib/src/__tests__/{ => unit}/text-field-helper.test.tsx (96%) diff --git a/lib/src/__tests__/e2e/DatePicker.test.tsx b/lib/src/__tests__/DatePicker.test.tsx similarity index 98% rename from lib/src/__tests__/e2e/DatePicker.test.tsx rename to lib/src/__tests__/DatePicker.test.tsx index 0df80067d..86b26a7aa 100644 --- a/lib/src/__tests__/e2e/DatePicker.test.tsx +++ b/lib/src/__tests__/DatePicker.test.tsx @@ -1,14 +1,14 @@ import * as React from 'react'; // import { act } from 'react-dom' import { ReactWrapper } from 'enzyme'; -import { Picker } from '../../Picker/Picker'; -import { mount, utilsToUse } from '../test-utils'; +import { Picker } from '../Picker/Picker'; +import { mount, utilsToUse } from './test-utils'; import { DatePicker, MobileDatePicker, DesktopDatePicker, DatePickerProps, -} from '../../DatePicker/DatePicker'; +} from '../DatePicker/DatePicker'; describe('e2e - DatePicker default year format', () => { let component: ReactWrapper; diff --git a/lib/src/__tests__/e2e/DatePickerProps.test.tsx b/lib/src/__tests__/DatePickerProps.test.tsx similarity index 95% rename from lib/src/__tests__/e2e/DatePickerProps.test.tsx rename to lib/src/__tests__/DatePickerProps.test.tsx index 7a7afa640..a17b3d4f0 100644 --- a/lib/src/__tests__/e2e/DatePickerProps.test.tsx +++ b/lib/src/__tests__/DatePickerProps.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { mount, utilsToUse } from '../test-utils'; -import { DatePicker, MobileDatePicker } from '../../DatePicker/DatePicker'; +import { mount, utilsToUse } from './test-utils'; +import { DatePicker, MobileDatePicker } from '../DatePicker/DatePicker'; describe('DatePicker - different props', () => { it('Should not render toolbar if onlyCalendar = true', () => { diff --git a/lib/src/__tests__/e2e/DatePickerRoot.test.tsx b/lib/src/__tests__/DatePickerRoot.test.tsx similarity index 96% rename from lib/src/__tests__/e2e/DatePickerRoot.test.tsx rename to lib/src/__tests__/DatePickerRoot.test.tsx index 3e96635e3..a7b04d268 100644 --- a/lib/src/__tests__/e2e/DatePickerRoot.test.tsx +++ b/lib/src/__tests__/DatePickerRoot.test.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { ReactWrapper } from 'enzyme'; import { clickOKButton } from './commands'; -import { mount, utilsToUse } from '../test-utils'; -import { DatePicker, DatePickerProps } from '../../DatePicker'; +import { mount, utilsToUse } from './test-utils'; +import { DatePicker, DatePickerProps } from '../DatePicker'; describe('e2e - DatePicker', () => { let component: ReactWrapper; diff --git a/lib/src/__tests__/e2e/DateTimePicker.test.tsx b/lib/src/__tests__/DateTimePicker.test.tsx similarity index 94% rename from lib/src/__tests__/e2e/DateTimePicker.test.tsx rename to lib/src/__tests__/DateTimePicker.test.tsx index 8b8044870..c1b59358e 100644 --- a/lib/src/__tests__/e2e/DateTimePicker.test.tsx +++ b/lib/src/__tests__/DateTimePicker.test.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import { ReactWrapper } from 'enzyme'; -import { mount, utilsToUse } from '../test-utils'; +import { mount, utilsToUse } from './test-utils'; import { mount as enzymeDefaultMount } from 'enzyme'; import { ThemeProvider, createMuiTheme } from '@material-ui/core'; -import { DateTimePicker, DateTimePickerProps } from '../../DateTimePicker/DateTimePicker'; +import { DateTimePicker, DateTimePickerProps } from '../DateTimePicker/DateTimePicker'; const format = process.env.UTILS === 'moment' ? 'MM/DD/YYYY HH:mm' : 'MM/dd/yyyy hh:mm'; diff --git a/lib/src/__tests__/e2e/DateTimePickerRoot.test.tsx b/lib/src/__tests__/DateTimePickerRoot.test.tsx similarity index 94% rename from lib/src/__tests__/e2e/DateTimePickerRoot.test.tsx rename to lib/src/__tests__/DateTimePickerRoot.test.tsx index 34e4592c0..211dfbcbb 100644 --- a/lib/src/__tests__/e2e/DateTimePickerRoot.test.tsx +++ b/lib/src/__tests__/DateTimePickerRoot.test.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { ReactWrapper } from 'enzyme'; import { clickOKButton } from './commands'; -import { mount, utilsToUse, toHaveBeenCalledExceptMoment } from '../test-utils'; -import { MobileDateTimePicker, DateTimePickerProps } from '../../DateTimePicker/DateTimePicker'; +import { mount, utilsToUse, toHaveBeenCalledExceptMoment } from './test-utils'; +import { MobileDateTimePicker, DateTimePickerProps } from '../DateTimePicker/DateTimePicker'; describe('e2e - DateTimePicker', () => { let component: ReactWrapper; diff --git a/lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx b/lib/src/__tests__/KeyboardDatePicker.test.tsx similarity index 97% rename from lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx rename to lib/src/__tests__/KeyboardDatePicker.test.tsx index a690aeada..0eef560c4 100644 --- a/lib/src/__tests__/e2e/KeyboardDatePicker.test.tsx +++ b/lib/src/__tests__/KeyboardDatePicker.test.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import addDays from 'date-fns/addDays'; +import { mount } from './test-utils'; import { ReactWrapper } from 'enzyme'; -import { mount } from '../test-utils'; -import { DesktopDatePicker, DatePickerProps } from '../../DatePicker/DatePicker'; +import { DesktopDatePicker, DatePickerProps } from '../DatePicker/DatePicker'; describe('e2e -- DatePicker keyboard input', () => { const onChangeMock = jest.fn(); diff --git a/lib/src/__tests__/e2e/KeyboardDateTimePicker.test.tsx b/lib/src/__tests__/KeyboardDateTimePicker.test.tsx similarity index 89% rename from lib/src/__tests__/e2e/KeyboardDateTimePicker.test.tsx rename to lib/src/__tests__/KeyboardDateTimePicker.test.tsx index 7911b2f8e..de300b848 100644 --- a/lib/src/__tests__/e2e/KeyboardDateTimePicker.test.tsx +++ b/lib/src/__tests__/KeyboardDateTimePicker.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { ReactWrapper } from 'enzyme'; -import { mount, utilsToUse } from '../test-utils'; -import { DesktopDateTimePicker, DateTimePickerProps } from '../../DateTimePicker/DateTimePicker'; +import { mount, utilsToUse } from './test-utils'; +import { DesktopDateTimePicker, DateTimePickerProps } from '../DateTimePicker/DateTimePicker'; const format = process.env.UTILS === 'moment' ? 'MM/DD/YYYY HH:mm' : 'MM/dd/yyyy hh:mm'; diff --git a/lib/src/__tests__/e2e/Theme.test.tsx b/lib/src/__tests__/Theme.test.tsx similarity index 81% rename from lib/src/__tests__/e2e/Theme.test.tsx rename to lib/src/__tests__/Theme.test.tsx index ff9c77efe..1d8538a50 100644 --- a/lib/src/__tests__/e2e/Theme.test.tsx +++ b/lib/src/__tests__/Theme.test.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { mount } from '../test-utils'; -import { DatePicker } from '../../DatePicker'; +import { mount } from './test-utils'; +import { DatePicker } from '../DatePicker'; import { ThemeProvider } from '@material-ui/core/styles'; import { createMuiTheme } from '@material-ui/core/styles'; -import { DateTimePicker } from '../../DateTimePicker/DateTimePicker'; +import { DateTimePicker } from '../DateTimePicker/DateTimePicker'; const theme = createMuiTheme({ palette: { diff --git a/lib/src/__tests__/e2e/TimePicker.test.tsx b/lib/src/__tests__/TimePicker.test.tsx similarity index 99% rename from lib/src/__tests__/e2e/TimePicker.test.tsx rename to lib/src/__tests__/TimePicker.test.tsx index 3967b574e..87ad68344 100644 --- a/lib/src/__tests__/e2e/TimePicker.test.tsx +++ b/lib/src/__tests__/TimePicker.test.tsx @@ -1,13 +1,13 @@ import * as React from 'react'; import { ReactWrapper } from 'enzyme'; import { clickOKButton } from './commands'; -import { mount, utilsToUse, toHaveBeenCalledExceptMoment } from '../test-utils'; +import { mount, utilsToUse, toHaveBeenCalledExceptMoment } from './test-utils'; import { MobileTimePicker, DesktopTimePicker, TimePicker, TimePickerProps, -} from '../../TimePicker/TimePicker'; +} from '../TimePicker/TimePicker'; const fakeTouchEvent = { buttons: 1, diff --git a/lib/src/__tests__/e2e/commands.tsx b/lib/src/__tests__/commands.tsx similarity index 100% rename from lib/src/__tests__/e2e/commands.tsx rename to lib/src/__tests__/commands.tsx diff --git a/lib/src/__tests__/test-utils.tsx b/lib/src/__tests__/test-utils.tsx index 1165c4653..3b8acd389 100644 --- a/lib/src/__tests__/test-utils.tsx +++ b/lib/src/__tests__/test-utils.tsx @@ -5,8 +5,8 @@ import MomentUtils from '@date-io/moment'; import DateFnsUtils from '@date-io/date-fns'; import LocalizationProvider from '../LocalizationProvider'; import { IUtils } from '@date-io/core/IUtils'; -import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; +import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'; interface WithUtilsProps { utils: IUtils; diff --git a/lib/src/__tests__/date-utils.test.tsx b/lib/src/__tests__/unit/date-utils.test.tsx similarity index 98% rename from lib/src/__tests__/date-utils.test.tsx rename to lib/src/__tests__/unit/date-utils.test.tsx index 9b51df67f..15abd71d7 100644 --- a/lib/src/__tests__/date-utils.test.tsx +++ b/lib/src/__tests__/unit/date-utils.test.tsx @@ -1,5 +1,5 @@ -import { utilsToUse } from './test-utils'; -import { findClosestEnabledDate } from '../_helpers/date-utils'; +import { utilsToUse } from '../test-utils'; +import { findClosestEnabledDate } from '../../_helpers/date-utils'; describe('findClosestEnabledDate', () => { const day18thText = utilsToUse.format(utilsToUse.date('2018-08-18'), 'dayOfMonth'); diff --git a/lib/src/__tests__/text-field-helper.test.tsx b/lib/src/__tests__/unit/text-field-helper.test.tsx similarity index 96% rename from lib/src/__tests__/text-field-helper.test.tsx rename to lib/src/__tests__/unit/text-field-helper.test.tsx index 144b699e5..e86c74a9c 100644 --- a/lib/src/__tests__/text-field-helper.test.tsx +++ b/lib/src/__tests__/unit/text-field-helper.test.tsx @@ -1,11 +1,11 @@ import LuxonUtils from '@date-io/luxon'; import DateFnsUtils from '@date-io/date-fns'; -import { utilsToUse } from './test-utils'; +import { utilsToUse } from '../test-utils'; import { maskedDateFormatter, pick12hOr24hFormat, checkMaskIsValidForCurrentFormat, -} from '../_helpers/text-field-helper'; +} from '../../_helpers/text-field-helper'; const refuse = /[\d]/gi; describe('test-field-helper', () => { From b279d924399c028610ce97565a07ae0395decdbb Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Wed, 25 Mar 2020 22:58:44 +0200 Subject: [PATCH 28/72] Add focus managment logic --- docs/pages/regression/Regression.tsx | 10 +++- e2e/integration/DateRange.spec.ts | 36 +++++++++++ lib/package.json | 4 +- lib/src/DateRangePicker/DateRangePicker.tsx | 18 ++++-- ...ateRangeDay.tsx => DateRangePickerDay.tsx} | 4 ++ .../DateRangePicker/DateRangePickerInput.tsx | 59 +++++++++++++++---- .../DateRangePicker/DateRangePickerView.tsx | 41 +++++++++---- .../DesktopDateRangePicker.tsx | 31 ++++++---- lib/src/DateRangePicker/date-range-manager.ts | 33 +++++++++++ lib/src/Picker/SharedPickerProps.tsx | 2 +- lib/src/__tests__/tsconfig.json | 2 +- .../__tests__/unit/date-range-manager.test.ts | 33 +++++++++++ ...date-utils.test.tsx => date-utils.test.ts} | 0 ...per.test.tsx => text-field-helper.test.ts} | 0 lib/src/_shared/PureDateInput.tsx | 5 +- lib/src/_shared/hooks/usePickerState.ts | 10 ++-- lib/src/typings/BasePicker.tsx | 9 ++- 17 files changed, 245 insertions(+), 52 deletions(-) create mode 100644 e2e/integration/DateRange.spec.ts rename lib/src/DateRangePicker/{DateRangeDay.tsx => DateRangePickerDay.tsx} (94%) create mode 100644 lib/src/DateRangePicker/date-range-manager.ts create mode 100644 lib/src/__tests__/unit/date-range-manager.test.ts rename lib/src/__tests__/unit/{date-utils.test.tsx => date-utils.test.ts} (100%) rename lib/src/__tests__/unit/{text-field-helper.test.tsx => text-field-helper.test.ts} (100%) diff --git a/docs/pages/regression/Regression.tsx b/docs/pages/regression/Regression.tsx index b82351d4f..cb801d8a5 100644 --- a/docs/pages/regression/Regression.tsx +++ b/docs/pages/regression/Regression.tsx @@ -2,9 +2,10 @@ import React, { useState, useContext } from 'react'; import LeftArrowIcon from '@material-ui/icons/KeyboardArrowLeft'; import RightArrowIcon from '@material-ui/icons/KeyboardArrowRight'; import { Grid, Typography } from '@material-ui/core'; -import { MuiPickersContext } from '@material-ui/pickers'; +import { MuiPickersContext, DateRangePicker } from '@material-ui/pickers'; import { createRegressionDay as createRegressionDayRenderer } from './RegressionDay'; import { + DateRange, MobileDatePicker, DesktopDatePicker, MobileTimePicker, @@ -13,6 +14,7 @@ import { function Regression() { const utils = useContext(MuiPickersContext); + const [range, changeRange] = useState([new Date('2019-01-01T00:00:00.000'), null]); const [date, changeDate] = useState(new Date('2019-01-01T00:00:00.000')); const sharedProps = { @@ -64,6 +66,12 @@ function Regression() { + + + DateRangePicker + + +
); } diff --git a/e2e/integration/DateRange.spec.ts b/e2e/integration/DateRange.spec.ts new file mode 100644 index 000000000..3c9447cf3 --- /dev/null +++ b/e2e/integration/DateRange.spec.ts @@ -0,0 +1,36 @@ +describe('DateRangePicker', () => { + beforeEach(() => { + cy.visit('/regression'); + cy.viewport('macbook-13'); + }); + + it('Opens and selecting a range in DateRangePicker', () => { + cy.get('#desktop-range-picker input') + .first() + .focus(); + cy.get('[aria-label="Jan 24, 2019"').click(); + + cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 24); + }); + + it('Opens and selecting a range on the next month', () => { + cy.get('#desktop-range-picker input') + .first() + .focus(); + + cy.get('[data-mui-test="next-arrow-button"]') + .eq(1) + .click(); + + cy.get('[aria-label="Mar 19, 2019"').click(); + cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 47); + }); + + it.skip('Shows range preview on hover', () => { + cy.get('#desktop-range-picker input') + .first() + .focus(); + + cy.get('[aria-label="Jan 24, 2019"').trigger('mouseover'); + }); +}); diff --git a/lib/package.json b/lib/package.json index 9e6e82807..4a236847c 100644 --- a/lib/package.json +++ b/lib/package.json @@ -122,11 +122,11 @@ "setupFilesAfterEnv": [ "/src/__tests__/setup.js" ], - "testRegex": "./src/__tests__/.*\\.test\\.(js|tsx)$", + "testRegex": "./src/__tests__/.*\\.test\\.(js|tsx|ts)$", "testURL": "http://localhost/", "collectCoverage": true, "transform": { - "^.+\\.tsx?$": "ts-jest" + "^.+\\.(ts|tsx)?$": "ts-jest" }, "moduleFileExtensions": [ "ts", diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 64ed040a0..57e385e30 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -10,7 +10,7 @@ import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { DateRangePickerView, DateRangePickerViewProps } from './DateRangePickerView'; -import { DateRangePickerInput, DateRangePickerInputSpecificProps } from './DateRangePickerInput'; +import { DateRangePickerInput, ExportedDateRangePickerInputProps } from './DateRangePickerInput'; export function parseRangeInputValue( now: MaterialUiPickersDate, @@ -18,7 +18,9 @@ export function parseRangeInputValue( { value = [null, null], defaultHighlight }: BasePickerProps ) { return value.map(date => - utils.startOfDay(parsePickerInputValue(now, utils, { value: date, defaultHighlight })) + date === null + ? null + : utils.startOfDay(parsePickerInputValue(now, utils, { value: date, defaultHighlight })) ) as DateRange; } @@ -42,7 +44,7 @@ export function makeRangePicker(Wrapper: TWrapper) inputFormat: passedInputFormat, ...other }: DateRangePickerViewProps & - DateRangePickerInputSpecificProps & + ExportedDateRangePickerInputProps & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); @@ -65,7 +67,13 @@ export function makeRangePicker(Wrapper: TWrapper) ); return ( - + (Wrapper: TWrapper) } export const DateRangePicker = makeRangePicker(DesktopPopperWrapper); + +export { DateRange }; diff --git a/lib/src/DateRangePicker/DateRangeDay.tsx b/lib/src/DateRangePicker/DateRangePickerDay.tsx similarity index 94% rename from lib/src/DateRangePicker/DateRangeDay.tsx rename to lib/src/DateRangePicker/DateRangePickerDay.tsx index b8a83b22a..03998fb0e 100644 --- a/lib/src/DateRangePicker/DateRangeDay.tsx +++ b/lib/src/DateRangePicker/DateRangePickerDay.tsx @@ -106,6 +106,7 @@ export const PureDateRangeDay = ({ return (
({ + theme => ({ rangeInputsContainer: { display: 'flex', alignItems: 'center', @@ -15,29 +16,54 @@ export const useStyles = makeStyles( toLabelDelimiter: { margin: '0 16px', }, + highlighted: { + backgroundColor: theme.palette.grey[500], + }, }), { name: 'MuiPickersDateRangePickerInput' } ); -export interface DateRangePickerInputSpecificProps { +export interface ExportedDateRangePickerInputProps { toText?: React.ReactNode; + rangeChangingStrategy?: 'expand' | 'circular'; +} + +interface DateRangeInputProps + extends ExportedDateRangePickerInputProps, + DateInputProps { + currentlySelectingRangeEnd: 'start' | 'end'; + setCurrentlySelectingRangeEnd: (newSelectionEnd: 'start' | 'end') => void; } // prettier-ignore -export const DateRangePickerInput: React.FC< - DateRangePickerInputSpecificProps & - DateInputProps -> = ({ +export const DateRangePickerInput: React.FC = ({ toText = 'to', rawValue, onChange, onClick, parsedDateValue, + id, + className, + forwardedRef, + currentlySelectingRangeEnd, + setCurrentlySelectingRangeEnd, + openPicker, ...other }) => { const utils = useUtils() const classes = useStyles(); + const startRef = React.useRef(null) + const endRef = React.useRef(null) const [start, end] = parsedDateValue ?? [null, null]; + + React.useEffect(() => { + if (currentlySelectingRangeEnd === 'start') { + startRef.current?.focus() + } else { + endRef.current?.focus() + } + }, [currentlySelectingRangeEnd]) + const handleStartChange = (date: MaterialUiPickersDate, inputString?: string) => { if (date === null || utils.isValid(date)) { onChange([date, end], inputString); @@ -50,30 +76,41 @@ export const DateRangePickerInput: React.FC< } }; - const sharedInputProps = { - onFocus: other.openPicker, + const openRangeStartSelection = () => { + setCurrentlySelectingRangeEnd('start') + openPicker() + } + + const openRangeEndSelection = () => { + setCurrentlySelectingRangeEnd('end') + openPicker() } return ( -
+
{}} + onFocus={openRangeStartSelection} + className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd !== 'end' })} /> {toText} {}} + onFocus={openRangeEndSelection} />
); diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 5f9bcd8db..017993160 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { RangeInput, DateRange } from './RangeTypes'; import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; +import { calculateRangeChange } from './date-range-manager'; import { useParsedDate } from '../_shared/hooks/useParsedDate'; import { SharedPickerProps } from '../Picker/SharedPickerProps'; import { useCalendarState } from '../views/Calendar/useCalendarState'; @@ -33,6 +34,7 @@ export const DateRangePickerView: React.FC = ({ disableHighlightToday, onMonthChange, onDateChange, + currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, reduceAnimations = defaultReduceAnimations, }) => { @@ -41,7 +43,7 @@ export const DateRangePickerView: React.FC = ({ const minDate = useParsedDate(unparsedMinDate)!; const maxDate = useParsedDate(unparsedMaxDate)!; - const [start, end] = date!; + const [start, end] = date; const { changeMonth, calendarState, @@ -60,17 +62,35 @@ export const DateRangePickerView: React.FC = ({ disableSwitchToMonthOnDayFocus: true, }); + React.useEffect(() => { + const monthToShow = currentlySelectingRangeEnd === 'start' ? start : end; + + if (monthToShow && !utils.isSameMonth(monthToShow, calendarState.currentMonth)) { + changeMonth(monthToShow); + } + }, [currentlySelectingRangeEnd]); // eslint-disable-line + const handleChange = React.useCallback( - (date: MaterialUiPickersDate) => { - if (start === null || utils.isBefore(date, start)) { - setCurrentlySelectingRangeEnd('start'); - onDateChange([date, end], wrapperVariant, false); - } else { - setCurrentlySelectingRangeEnd('end'); - onDateChange([start, date], wrapperVariant, true); - } + (newDate: MaterialUiPickersDate) => { + const { nextSelection, newRange } = calculateRangeChange({ + newDate, + utils, + range: date, + currentlySelectingRangeEnd, + }); + + console.log(newRange); + setCurrentlySelectingRangeEnd(nextSelection); + onDateChange(newRange, wrapperVariant, false); }, - [end, onDateChange, setCurrentlySelectingRangeEnd, start, utils, wrapperVariant] + [ + currentlySelectingRangeEnd, + date, + onDateChange, + setCurrentlySelectingRangeEnd, + utils, + wrapperVariant, + ] ); switch (wrapperVariant) { @@ -87,6 +107,7 @@ export const DateRangePickerView: React.FC = ({ disableHighlightToday={disableHighlightToday} onMonthSwitchingAnimationEnd={onMonthSwitchingAnimationEnd} changeMonth={changeMonth} + currentlySelectingRangeEnd={currentlySelectingRangeEnd} /> ); } diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index a6717ce29..e76e0007c 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; import { DateRange } from './RangeTypes'; -import { DateRangeDay } from './DateRangeDay'; import { makeStyles } from '@material-ui/core'; +import { DateRangeDay } from './DateRangePickerDay'; import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; +import { calculateRangeChange } from './date-range-manager'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; @@ -17,6 +18,7 @@ interface DesktopDateRangeCalendarProps ExportedArrowSwitcherProps { date: DateRange; changeMonth: (date: MaterialUiPickersDate) => void; + currentlySelectingRangeEnd: 'start' | 'end'; } export const useStyles = makeStyles( @@ -55,33 +57,32 @@ export const DesktopDateRangePicker: React.FC = ( rightArrowButtonText, rightArrowIcon, onChange, + currentlySelectingRangeEnd, ...CalendarProps }) => { const utils = useUtils(); const classes = useStyles(); const { currentMonth } = CalendarProps; - const [start, end] = date; const [rangePreviewDay, setRangePreviewDay] = React.useState(null); - const previewingRange: DateRange | null = Boolean(rangePreviewDay) - ? utils.isAfter(start, rangePreviewDay) - ? [rangePreviewDay, start] - : [end, rangePreviewDay] - : null; + const previewingRange = calculateRangeChange({ + utils, + range: date, + newDate: rangePreviewDay, + currentlySelectingRangeEnd, + }).newRange; const handleDayChange = (day: MaterialUiPickersDate) => { setRangePreviewDay(null); onChange(day); }; - const handlePreviewDayChange = (newPreviewRequest: MaterialUiPickersDate) => { - if (!utils.isWithinRange(newPreviewRequest, date)) { - setRangePreviewDay(newPreviewRequest); - } + const isRangeValid = (range: DateRange | null) => { + return Boolean(range && utils.isBefore(range[0], range[1])); }; const isWithinRange = (day: MaterialUiPickersDate, range: DateRange | null) => { - return Boolean(range && utils.isBefore(range[0], range[1]) && utils.isWithinRange(day, range)); + return isRangeValid(range) && utils.isWithinRange(day, range); }; const isStartOfRange = (day: MaterialUiPickersDate, range: DateRange | null) => { @@ -92,6 +93,12 @@ export const DesktopDateRangePicker: React.FC = ( return Boolean(range && utils.isSameDay(day, range[1])); }; + const handlePreviewDayChange = (newPreviewRequest: MaterialUiPickersDate) => { + if (!isWithinRange(newPreviewRequest, date)) { + setRangePreviewDay(newPreviewRequest); + } + }; + const CalendarTransitionProps = React.useMemo( () => ({ onMouseLeave: () => setRangePreviewDay(null), diff --git a/lib/src/DateRangePicker/date-range-manager.ts b/lib/src/DateRangePicker/date-range-manager.ts new file mode 100644 index 000000000..80615d7e4 --- /dev/null +++ b/lib/src/DateRangePicker/date-range-manager.ts @@ -0,0 +1,33 @@ +import { DateRange } from './DateRangePicker'; +import { MaterialUiPickersDate } from '../typings/date'; +import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; + +interface CalculateRangeChangeOptions { + utils: MuiPickersAdapter; + range: DateRange; + newDate: MaterialUiPickersDate; + currentlySelectingRangeEnd: 'start' | 'end'; +} + +export function calculateRangeChange({ + utils, + range, + newDate: selectedDate, + currentlySelectingRangeEnd, +}: CalculateRangeChangeOptions): { nextSelection: 'start' | 'end'; newRange: DateRange } { + const [start, end] = range; + const isRangeFilledPartially = start === null || end === null; + + if (isRangeFilledPartially) { + } + + if (currentlySelectingRangeEnd === 'start') { + return utils.isAfter(selectedDate, end) + ? { nextSelection: 'end', newRange: [selectedDate, null] } + : { nextSelection: 'end', newRange: [selectedDate, end] }; + } else { + return utils.isBefore(selectedDate, start) + ? { nextSelection: 'end', newRange: [selectedDate, null] } + : { nextSelection: 'end', newRange: [start, selectedDate] }; + } +} diff --git a/lib/src/Picker/SharedPickerProps.tsx b/lib/src/Picker/SharedPickerProps.tsx index d57fc2f0b..1ae3d8db2 100644 --- a/lib/src/Picker/SharedPickerProps.tsx +++ b/lib/src/Picker/SharedPickerProps.tsx @@ -21,7 +21,7 @@ export interface SharedPickerProps { isMobileKeyboardViewOpen: boolean; toggleMobileKeyboardView: () => void; DateInputProps: DateInputProps; - date: TDateValue | null; + date: TDateValue; onDateChange: ( date: TDateValue, currentVariant: WrapperVariant, diff --git a/lib/src/__tests__/tsconfig.json b/lib/src/__tests__/tsconfig.json index 26187c5b2..1d867ff0d 100644 --- a/lib/src/__tests__/tsconfig.json +++ b/lib/src/__tests__/tsconfig.json @@ -1,5 +1,5 @@ { "extends": "../../tsconfig.json", - "include": ["./**/*.tsx", "../../typings.d.ts"], + "include": ["./**/*.tsx", "./**/*.ts", "../../typings.d.ts"], "exclude": [] } diff --git a/lib/src/__tests__/unit/date-range-manager.test.ts b/lib/src/__tests__/unit/date-range-manager.test.ts new file mode 100644 index 000000000..0925c7160 --- /dev/null +++ b/lib/src/__tests__/unit/date-range-manager.test.ts @@ -0,0 +1,33 @@ +import { utilsToUse } from '../test-utils'; +import { calculateRangeChange } from '../../DateRangePicker/date-range-manager'; + +const start2018 = utilsToUse.date(new Date('2018-01-01T00:00:00.000Z')); +const mid2018 = utilsToUse.date(new Date('2018-06-01T00:00:00.000Z')); +const end2019 = utilsToUse.date(new Date('2019-01-01T00:00:00.000Z')); + +test.each` + range | selectingEnd | newDate | expectedRange | expectedNextSelection + ${[null, null]} | ${'start'} | ${start2018} | ${[start2018, null]} | ${'end'} + ${[start2018, null]} | ${'start'} | ${end2019} | ${[end2019, null]} | ${'end'} + ${[null, end2019]} | ${'start'} | ${mid2018} | ${[mid2018, end2019]} | ${'end'} + ${[mid2018, null]} | ${'start'} | ${start2018} | ${[start2018, null]} | ${'end'} + ${[start2018, end2019]} | ${'start'} | ${mid2018} | ${[mid2018, end2019]} | ${'end'} + ${[start2018, end2019]} | ${'end'} | ${mid2018} | ${[start2018, mid2018]} | ${'end'} + ${[mid2018, end2019]} | ${'start'} | ${start2018} | ${[start2018, end2019]} | ${'end'} + ${[start2018, mid2018]} | ${'end'} | ${mid2018} | ${[start2018, mid2018]} | ${'end'} +`( + 'calculateRangeChange should return $expectedRange when selecting $selectingEnd of $range with user input $newDate', + ({ range, selectingEnd, newDate, expectedRange, expectedNextSelection }) => { + expect( + calculateRangeChange({ + utils: utilsToUse, + range, + newDate, + currentlySelectingRangeEnd: selectingEnd, + }) + ).toEqual({ + nextSelection: expectedNextSelection, + newRange: expectedRange, + }); + } +); diff --git a/lib/src/__tests__/unit/date-utils.test.tsx b/lib/src/__tests__/unit/date-utils.test.ts similarity index 100% rename from lib/src/__tests__/unit/date-utils.test.tsx rename to lib/src/__tests__/unit/date-utils.test.ts diff --git a/lib/src/__tests__/unit/text-field-helper.test.tsx b/lib/src/__tests__/unit/text-field-helper.test.ts similarity index 100% rename from lib/src/__tests__/unit/text-field-helper.test.tsx rename to lib/src/__tests__/unit/text-field-helper.test.ts diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index adcb94425..4071c8bed 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -12,9 +12,9 @@ import { getDisplayDate, getTextFieldAriaText } from '../_helpers/text-field-hel export interface DateInputProps extends ExtendMui { rawValue: TInputValue; - parsedDateValue: TDateValue | null; + parsedDateValue: TDateValue; inputFormat: string; - onChange: (date: TDateValue | null, keyboardInputValue?: string) => void; + onChange: (date: TDateValue, keyboardInputValue?: string) => void; openPicker: () => void; validationError?: React.ReactNode; /** Override input component */ @@ -79,6 +79,7 @@ export type ExportedDateInputProps = Omit< | 'validationError' | 'rawValue' | 'forwardedRef' + | 'parsedDateValue' >; export const PureDateInput: React.FC = ({ diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 3b5e5dd6c..26861a01a 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -14,13 +14,13 @@ export function usePickerState( now: MaterialUiPickersDate, utils: MuiPickersAdapter, props: BasePickerProps - ) => TDateValue | null; + ) => TDateValue; validateInput: ( value: TInput, utils: MuiPickersAdapter, props: BasePickerProps ) => React.ReactNode | undefined; - areValuesEqual: (valueLeft: TDateValue | null, valueRight: TDateValue | null) => boolean; + areValuesEqual: (valueLeft: TDateValue, valueRight: TDateValue) => boolean; } ) { const { autoOk, inputFormat, disabled, readOnly, onAccept, onChange, onError, value } = props; @@ -46,7 +46,7 @@ export function usePickerState( }, [value]); // eslint-disable-line const acceptDate = useCallback( - (acceptedDate: TDateValue | null, needClosePicker: boolean) => { + (acceptedDate: TDateValue, needClosePicker: boolean) => { onChange(acceptedDate); if (needClosePicker) { @@ -125,10 +125,10 @@ export function usePickerState( inputFormat, rawValue: value, validationError, - parsedDateValue: date, + parsedDateValue: pickerDate, openPicker: () => !readOnly && !disabled && setIsOpen(true), }), - [date, disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] + [pickerDate, disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] ); const pickerState = { pickerProps, inputProps, wrapperProps }; diff --git a/lib/src/typings/BasePicker.tsx b/lib/src/typings/BasePicker.tsx index 56743c14d..a91c9957c 100644 --- a/lib/src/typings/BasePicker.tsx +++ b/lib/src/typings/BasePicker.tsx @@ -2,11 +2,14 @@ import { MaterialUiPickersDate } from './date'; import { ParsableDate } from '../constants/prop-types'; import { ToolbarComponentProps } from '../Picker/Picker'; -export interface BasePickerProps { +export interface BasePickerProps< + TInputValue = ParsableDate, + TDateValue = MaterialUiPickersDate | null +> { /** Picker value */ value: TInputValue; /** onChange callback @DateIOType */ - onChange: (date: TDateValue | null, keyboardInputValue?: string) => void; + onChange: (date: TDateValue, keyboardInputValue?: string) => void; /** * Auto accept date on selection * @default false @@ -21,7 +24,7 @@ export interface BasePickerProps void; + onAccept?: (date: TDateValue) => void; /** Callback fired when new error should be displayed * (!! This is a side effect. Be careful if you want to rerender the component) @DateIOType */ From 1fc147e040fa11a0801df1ad43120894c7c2c48f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 26 Mar 2020 14:25:34 +0200 Subject: [PATCH 29/72] Implement autoscrolling for switching between range start/end --- e2e/integration/DateRange.spec.ts | 77 ++++++++++++++++++- .../DateRangePicker/DateRangePickerInput.tsx | 5 +- .../DateRangePicker/DateRangePickerView.tsx | 56 ++++++++++---- 3 files changed, 120 insertions(+), 18 deletions(-) diff --git a/e2e/integration/DateRange.spec.ts b/e2e/integration/DateRange.spec.ts index 3c9447cf3..3eb9e7600 100644 --- a/e2e/integration/DateRange.spec.ts +++ b/e2e/integration/DateRange.spec.ts @@ -8,7 +8,8 @@ describe('DateRangePicker', () => { cy.get('#desktop-range-picker input') .first() .focus(); - cy.get('[aria-label="Jan 24, 2019"').click(); + cy.get('[aria-label="Jan 1, 2019"]').click(); + cy.get('[aria-label="Jan 24, 2019"]').click(); cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 24); }); @@ -18,11 +19,13 @@ describe('DateRangePicker', () => { .first() .focus(); + cy.get('[aria-label="Jan 1, 2019"]').click(); cy.get('[data-mui-test="next-arrow-button"]') .eq(1) .click(); - cy.get('[aria-label="Mar 19, 2019"').click(); + cy.get('[aria-label="Mar 19, 2019"]').click(); + cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 47); }); @@ -33,4 +36,74 @@ describe('DateRangePicker', () => { cy.get('[aria-label="Jan 24, 2019"').trigger('mouseover'); }); + + it.only('Allows pure keyboard input control', () => { + cy.get('#desktop-range-picker input') + .eq(0) + .clear() + .type('06/06/2019'); + + cy.contains('June 2019'); + cy.contains('July 2019'); + + cy.get('#desktop-range-picker input') + .eq(1) + .focus() + .clear() + .type('08/08/2019'); + + cy.contains('July 2019'); + cy.contains('August 2019'); + + cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 39); + }); + + it('Scrolls current month to the active selection on focusing start field', () => { + cy.get('#desktop-range-picker input') + .first() + .click(); + + cy.get('[aria-label="Jan 19, 2019"]').click(); + cy.get('[aria-label="Feb 19, 2019"]').click(); + + cy.get('[data-mui-test="previous-arrow-button"]') + .eq(0) + .click() + .click(); + + cy.get('#desktop-range-picker input') + .first() + .click(); + + cy.contains('January 2019'); + }); + + it('Scrolls current month to the active selection on focusing end field', () => { + cy.get('#desktop-range-picker input') + .first() + .click(); + + cy.get('[aria-label="Jan 19, 2019"]').click(); + cy.get('[data-mui-test="next-arrow-button"]') + .eq(1) + .click(); + + cy.get('[aria-label="Mar 19, 2019"]').click(); + + cy.get('[data-mui-test="previous-arrow-button"]') + .eq(0) + .click() + .click(); + + cy.get('#desktop-range-picker input') + .eq(0) + .click(); + + cy.get('#desktop-range-picker input') + .eq(1) + .click(); + + cy.contains('February 2019'); + cy.contains('March 2019'); + }); }); diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index fd58fd590..7b392119e 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -17,7 +17,7 @@ export const useStyles = makeStyles( margin: '0 16px', }, highlighted: { - backgroundColor: theme.palette.grey[500], + backgroundColor: theme.palette.divider, }, }), { name: 'MuiPickersDateRangePickerInput' } @@ -97,7 +97,7 @@ export const DateRangePickerInput: React.FC = ({ hideOpenPickerButton openPicker={() => {}} onFocus={openRangeStartSelection} - className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd !== 'end' })} + className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'start' })} /> {toText} @@ -111,6 +111,7 @@ export const DateRangePickerInput: React.FC = ({ hideOpenPickerButton openPicker={() => {}} onFocus={openRangeEndSelection} + className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'end' })} />
); diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 017993160..cd7674d46 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -19,24 +19,30 @@ export interface DateRangePickerViewProps extends BaseCalendarPropsToReuse, ExportedDesktopDateRangeCalendarProps, SharedPickerProps { + /** + * if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date + * @default false + */ + disableAutoMonthSwitching?: boolean; currentlySelectingRangeEnd: 'start' | 'end'; setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; } export const DateRangePickerView: React.FC = ({ + calendars = 2, + currentlySelectingRangeEnd, date, - calendars, - minDate: unparsedMinDate = new Date('1900-01-01'), - maxDate: unparsedMaxDate = new Date('2100-01-01'), + disableAutoMonthSwitching = false, disableFuture, - disablePast, - shouldDisableDate, disableHighlightToday, - onMonthChange, + disablePast, + maxDate: unparsedMaxDate = new Date('2100-01-01'), + minDate: unparsedMinDate = new Date('1900-01-01'), onDateChange, - currentlySelectingRangeEnd, - setCurrentlySelectingRangeEnd, + onMonthChange, reduceAnimations = defaultReduceAnimations, + setCurrentlySelectingRangeEnd, + shouldDisableDate, }) => { const utils = useUtils(); const wrapperVariant = React.useContext(WrapperVariantContext); @@ -62,13 +68,36 @@ export const DateRangePickerView: React.FC = ({ disableSwitchToMonthOnDayFocus: true, }); + const scrollToDayIfNeeded = (day: MaterialUiPickersDate) => { + const currentViewingRange = calendars - 1; + const currentMonthNumber = utils.getMonth(calendarState.currentMonth); + const requestedMonthNumber = utils.getMonth(day); + + if ( + requestedMonthNumber < currentMonthNumber || + requestedMonthNumber > currentMonthNumber + currentViewingRange + ) { + const newMonth = + currentlySelectingRangeEnd === 'start' ? start : utils.addMonths(end, -currentViewingRange); + + changeMonth(newMonth); + } + }; + React.useEffect(() => { - const monthToShow = currentlySelectingRangeEnd === 'start' ? start : end; + if (disableAutoMonthSwitching) { + return; + } - if (monthToShow && !utils.isSameMonth(monthToShow, calendarState.currentMonth)) { - changeMonth(monthToShow); + if ( + (currentlySelectingRangeEnd === 'start' && !start) || + (currentlySelectingRangeEnd === 'end' && !end) + ) { + return; } - }, [currentlySelectingRangeEnd]); // eslint-disable-line + + scrollToDayIfNeeded(currentlySelectingRangeEnd === 'start' ? start : end); + }, [currentlySelectingRangeEnd, date]); // eslint-disable-line const handleChange = React.useCallback( (newDate: MaterialUiPickersDate) => { @@ -79,7 +108,6 @@ export const DateRangePickerView: React.FC = ({ currentlySelectingRangeEnd, }); - console.log(newRange); setCurrentlySelectingRangeEnd(nextSelection); onDateChange(newRange, wrapperVariant, false); }, @@ -99,7 +127,7 @@ export const DateRangePickerView: React.FC = ({ Date: Thu, 26 Mar 2020 20:50:08 +0200 Subject: [PATCH 30/72] Improve date range picker with disabling min/max dates --- .../CalendarsDateRangePicker.example.jsx | 34 +++++++++++++ .../MinMaxDateRangePicker.example.jsx | 27 +++++++++++ docs/pages/demo/daterangepicker/index.mdx | 14 +++++- docs/prop-types.json | 6 +-- lib/src/DateRangePicker/DateRangePicker.tsx | 1 + .../DateRangePicker/DateRangePickerInput.tsx | 12 ++++- .../DateRangePicker/DateRangePickerView.tsx | 21 +++++--- .../DesktopDateRangePicker.tsx | 22 +++++++-- lib/src/_shared/KeyboardDateInput.tsx | 1 + lib/src/_shared/PureDateInput.tsx | 2 + lib/src/_shared/hooks/date-helpers-hooks.tsx | 48 +++++++++++++++++++ lib/src/_shared/hooks/useParsedDate.tsx | 11 ----- lib/src/_shared/hooks/usePickerState.ts | 1 + lib/src/views/Calendar/Calendar.tsx | 6 +-- lib/src/views/Calendar/CalendarHeader.tsx | 27 ++++------- lib/src/views/Calendar/CalendarView.tsx | 2 +- lib/src/views/Clock/ClockView.tsx | 4 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 17 ++++++- 18 files changed, 204 insertions(+), 52 deletions(-) create mode 100644 docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx create mode 100644 docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx create mode 100644 lib/src/_shared/hooks/date-helpers-hooks.tsx delete mode 100644 lib/src/_shared/hooks/useParsedDate.tsx diff --git a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx new file mode 100644 index 000000000..f6a952ad3 --- /dev/null +++ b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx @@ -0,0 +1,34 @@ +import React, { useState } from 'react'; +import { Grid, Typography } from '@material-ui/core'; +import { DateRangePicker } from '@material-ui/pickers'; + +function CalendarsDateRangePicker() { + /** @type import('@material-ui/pickers').DateRange */ + const initialValue = [null, null]; + const [selectedDate, handleDateChange] = useState(initialValue); + + return ( + + 1 calendar + handleDateChange(date)} + /> + 2 calendars + handleDateChange(date)} + /> + 3 calendars + handleDateChange(date)} + /> + + ); +} + +export default CalendarsDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx new file mode 100644 index 000000000..aac36ad23 --- /dev/null +++ b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx @@ -0,0 +1,27 @@ +import React, { useState } from 'react'; +import isWeekend from 'date-fns/isWeekend'; +// this guy required only on the docs site to work with dynamic date library +import { makeJSDateObject } from '../../../utils/helpers'; +import { DateRangePicker, useUtils } from '@material-ui/pickers'; + +function disableWeekends(date) { + // TODO: replace with implementation for your date library + return isWeekend(makeJSDateObject(date)); +} + +function MinMaxDateRangePicker() { + const utils = useUtils(); + const [selectedRange, handleDateChange] = useState([new Date(), null]); + + return ( + handleDateChange(date)} + /> + ); +} + +export default MinMaxDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/index.mdx b/docs/pages/demo/daterangepicker/index.mdx index d1c14f72b..7f2b566d2 100644 --- a/docs/pages/demo/daterangepicker/index.mdx +++ b/docs/pages/demo/daterangepicker/index.mdx @@ -4,6 +4,8 @@ import PageMeta from '_shared/PageMeta'; import LinkedComponents from '_shared/LinkedComponents'; import * as BasicDateRangePicker from './BasicDateRangePicker.example'; +import * as MinMaxDateRangePicker from './MinMaxDateRangePicker.example'; +import * as CalendarsDateRangePicker from './CalendarsDateRangePicker.example'; @@ -15,6 +17,16 @@ import * as BasicDateRangePicker from './BasicDateRangePicker.example'; #### Basic usage -Will be rendered to modal dialog on mobile and textfield with popover on desktop. +Basic DateRangePicker example + +#### Different amount of calendars + + + +#### Disabling dates + +Disabling dates performs just like in simple `DatePicker` + + diff --git a/docs/prop-types.json b/docs/prop-types.json index 93c5d3df0..20e89edc4 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -389,7 +389,7 @@ "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { "name": "boolean" } @@ -1286,7 +1286,7 @@ "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { "name": "boolean" } @@ -2021,7 +2021,7 @@ "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { "name": "boolean" } diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 57e385e30..be7e0863a 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -75,6 +75,7 @@ export function makeRangePicker(Wrapper: TWrapper) {...other} > = ({ onClick, parsedDateValue, id, + open, className, + containerRef, forwardedRef, currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, @@ -57,12 +59,16 @@ export const DateRangePickerInput: React.FC = ({ const [start, end] = parsedDateValue ?? [null, null]; React.useEffect(() => { + if (!open) { + return + } + if (currentlySelectingRangeEnd === 'start') { startRef.current?.focus() } else { endRef.current?.focus() } - }, [currentlySelectingRangeEnd]) + }, [currentlySelectingRangeEnd, open]) const handleStartChange = (date: MaterialUiPickersDate, inputString?: string) => { if (date === null || utils.isValid(date)) { @@ -87,9 +93,10 @@ export const DateRangePickerInput: React.FC = ({ } return ( -
+
= ({ void; } export const DateRangePickerView: React.FC = ({ + open, calendars = 2, currentlySelectingRangeEnd, date, @@ -43,6 +45,7 @@ export const DateRangePickerView: React.FC = ({ reduceAnimations = defaultReduceAnimations, setCurrentlySelectingRangeEnd, shouldDisableDate, + ...other }) => { const utils = useUtils(); const wrapperVariant = React.useContext(WrapperVariantContext); @@ -57,7 +60,7 @@ export const DateRangePickerView: React.FC = ({ onMonthSwitchingAnimationEnd, changeFocusedDay, } = useCalendarState({ - date: start, + date: start || end || utils.date(), minDate, maxDate, reduceAnimations, @@ -80,18 +83,19 @@ export const DateRangePickerView: React.FC = ({ const newMonth = currentlySelectingRangeEnd === 'start' ? start : utils.addMonths(end, -currentViewingRange); + console.log('CHAING MONTH'); changeMonth(newMonth); } }; React.useEffect(() => { - if (disableAutoMonthSwitching) { + if (disableAutoMonthSwitching || !open) { return; } if ( - (currentlySelectingRangeEnd === 'start' && !start) || - (currentlySelectingRangeEnd === 'end' && !end) + (currentlySelectingRangeEnd === 'start' && start === null) || + (currentlySelectingRangeEnd === 'end' && end === null) ) { return; } @@ -126,7 +130,6 @@ export const DateRangePickerView: React.FC = ({ return ( = ({ onMonthSwitchingAnimationEnd={onMonthSwitchingAnimationEnd} changeMonth={changeMonth} currentlySelectingRangeEnd={currentlySelectingRangeEnd} + disableFuture={disableFuture} + disablePast={disablePast} + minDate={minDate} + maxDate={maxDate} + {...calendarState} + {...other} /> ); } diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index e76e0007c..9344ed226 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -7,9 +7,14 @@ import { MaterialUiPickersDate } from '../typings/date'; import { calculateRangeChange } from './date-range-manager'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; +import { + usePreviousMonthDisabled, + useParsedDate, + useNextMonthDisabled, +} from '../_shared/hooks/date-helpers-hooks'; export interface ExportedDesktopDateRangeCalendarProps { - calendars?: 1 | 2; + calendars?: 1 | 2 | 3; } interface DesktopDateRangeCalendarProps @@ -57,6 +62,10 @@ export const DesktopDateRangePicker: React.FC = ( rightArrowButtonText, rightArrowIcon, onChange, + disableFuture, + disablePast, + minDate, + maxDate, currentlySelectingRangeEnd, ...CalendarProps }) => { @@ -65,6 +74,9 @@ export const DesktopDateRangePicker: React.FC = ( const { currentMonth } = CalendarProps; const [rangePreviewDay, setRangePreviewDay] = React.useState(null); + const isNextMonthDisabled = useNextMonthDisabled(currentMonth, { disableFuture, maxDate }); + const isPreviousMonthDisabled = usePreviousMonthDisabled(currentMonth, { disablePast, minDate }); + const previewingRange = calculateRangeChange({ utils, range: date, @@ -127,8 +139,8 @@ export const DesktopDateRangePicker: React.FC = ( onRightClick={selectNextMonth} isLeftHidden={index !== 0} isRightHidden={index !== calendars - 1} - isLeftDisabled={false} - isRightDisabled={false} + isLeftDisabled={isPreviousMonthDisabled} + isRightDisabled={isNextMonthDisabled} leftArrowButtonProps={leftArrowButtonProps} leftArrowButtonText={leftArrowButtonText} leftArrowIcon={leftArrowIcon} @@ -142,6 +154,10 @@ export const DesktopDateRangePicker: React.FC = ( {...CalendarProps} key={index} date={date} + minDate={minDate} + maxDate={maxDate} + disablePast={disablePast} + disableFuture={disableFuture} className={classes.calendar} onChange={handleDayChange} currentMonth={monthOnIteration} diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index 09da9b1d4..d5dd81c7e 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -40,6 +40,7 @@ export const KeyboardDateInput: React.FC = ({ parsedDateValue, forwardedRef, containerRef, + open, getOpenDialogAriaText = getTextFieldAriaText, ...other }) => { diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 4071c8bed..3e3d5dd72 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -66,6 +66,7 @@ export interface DateInputProps string; // ?? TODO when it will be possible to display "empty" date in datepicker use it instead of ignoring invalid inputs ignoreInvalidInputs?: boolean; + open: boolean; containerRef?: React.Ref; forwardedRef?: React.Ref; } @@ -104,6 +105,7 @@ export const PureDateInput: React.FC = ({ parsedDateValue, forwardedRef, containerRef, + open, getOpenDialogAriaText = getTextFieldAriaText, ...other }) => { diff --git a/lib/src/_shared/hooks/date-helpers-hooks.tsx b/lib/src/_shared/hooks/date-helpers-hooks.tsx new file mode 100644 index 000000000..95c077e1e --- /dev/null +++ b/lib/src/_shared/hooks/date-helpers-hooks.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { useUtils } from './useUtils'; +import { MaterialUiPickersDate } from '../../typings/date'; + +export function useParsedDate(possiblyUnparsedValue: any) { + const utils = useUtils(); + return React.useMemo( + () => + typeof possiblyUnparsedValue === 'undefined' ? undefined : utils.date(possiblyUnparsedValue)!, + [possiblyUnparsedValue, utils] + ); +} + +interface MonthValidationOptions { + disablePast?: boolean; + disableFuture?: boolean; + minDate: MaterialUiPickersDate; + maxDate: MaterialUiPickersDate; +} + +export function useNextMonthDisabled( + month: MaterialUiPickersDate, + { disableFuture, maxDate }: Pick +) { + const utils = useUtils(); + return React.useMemo(() => { + const now = utils.date(); + const lastEnabledMonth = utils.startOfMonth( + disableFuture && utils.isBefore(now, maxDate) ? now : maxDate + ); + return !utils.isAfter(lastEnabledMonth, month); + }, [disableFuture, maxDate, month, utils]); +} + +export function usePreviousMonthDisabled( + month: MaterialUiPickersDate, + { disablePast, minDate }: Pick +) { + const utils = useUtils(); + + return React.useMemo(() => { + const now = utils.date(); + const firstEnabledMonth = utils.startOfMonth( + disablePast && utils.isAfter(now, minDate) ? now : minDate + ); + return !utils.isBefore(firstEnabledMonth, month); + }, [disablePast, minDate, month, utils]); +} diff --git a/lib/src/_shared/hooks/useParsedDate.tsx b/lib/src/_shared/hooks/useParsedDate.tsx deleted file mode 100644 index a21c97e2e..000000000 --- a/lib/src/_shared/hooks/useParsedDate.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; -import { useUtils } from './useUtils'; - -export function useParsedDate(possiblyUnparsedValue: any) { - const utils = useUtils(); - return React.useMemo( - () => - typeof possiblyUnparsedValue === 'undefined' ? undefined : utils.date(possiblyUnparsedValue)!, - [possiblyUnparsedValue, utils] - ); -} diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 26861a01a..f2dc91f5d 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -123,6 +123,7 @@ export function usePickerState( () => ({ onChange, inputFormat, + open: isOpen, rawValue: value, validationError, parsedDateValue: pickerDate, diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index a48e86fca..e8619ad67 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -41,8 +41,8 @@ export interface ExportedCalendarProps export interface CalendarProps extends ExportedCalendarProps { date: MaterialUiPickersDate | MaterialUiPickersDate[]; - minDate?: MaterialUiPickersDate; - maxDate?: MaterialUiPickersDate; + minDate: MaterialUiPickersDate; + maxDate: MaterialUiPickersDate; isDateDisabled: (day: MaterialUiPickersDate) => boolean; slideDirection: SlideDirection; currentMonth: MaterialUiPickersDate; @@ -52,7 +52,7 @@ export interface CalendarProps extends ExportedCalendarProps { isMonthSwitchingAnimating: boolean; onMonthSwitchingAnimationEnd: () => void; className?: string; - TransitionProps?: SlideTransitionProps; + TransitionProps?: Partial; } export const useStyles = makeStyles(theme => ({ diff --git a/lib/src/views/Calendar/CalendarHeader.tsx b/lib/src/views/Calendar/CalendarHeader.tsx index 7594be468..c9b8171df 100644 --- a/lib/src/views/Calendar/CalendarHeader.tsx +++ b/lib/src/views/Calendar/CalendarHeader.tsx @@ -1,18 +1,22 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; import clsx from 'clsx'; +import Fade from '@material-ui/core/Fade'; import Typography from '@material-ui/core/Typography'; import IconButton from '@material-ui/core/IconButton'; -import Fade from '@material-ui/core/Fade'; -import { makeStyles } from '@material-ui/core/styles'; import { CalendarProps } from './Calendar'; import { DatePickerView } from '../../DatePicker'; import { SlideDirection } from './SlideTransition'; +import { makeStyles } from '@material-ui/core/styles'; import { useUtils } from '../../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../../typings/date'; import { FadeTransitionGroup } from './FadeTransitionGroup'; import { ArrowDropDownIcon } from '../../_shared/icons/ArrowDropDownIcon'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../../_shared/ArrowSwitcher'; +import { + usePreviousMonthDisabled, + useNextMonthDisabled, +} from '../../_shared/hooks/date-helpers-hooks'; export interface CalendarHeaderProps extends ExportedArrowSwitcherProps, @@ -102,23 +106,8 @@ export const CalendarHeader: React.SFC = ({ const selectNextMonth = () => onMonthChange(utils.getNextMonth(month), 'left'); const selectPreviousMonth = () => onMonthChange(utils.getPreviousMonth(month), 'right'); - const isPreviousMonthDisabled = React.useMemo(() => { - const now = utils.date(); - const firstEnabledMonth = utils.startOfMonth( - disablePast && utils.isAfter(now, minDate) ? now : minDate - ); - - return !utils.isBefore(firstEnabledMonth, month); - }, [disablePast, minDate, month, utils]); - - const isNextMonthDisabled = React.useMemo(() => { - const now = utils.date(); - const lastEnabledMonth = utils.startOfMonth( - disableFuture && utils.isBefore(now, maxDate) ? now : maxDate - ); - - return !utils.isAfter(lastEnabledMonth, month); - }, [disableFuture, maxDate, month, utils]); + const isNextMonthDisabled = useNextMonthDisabled(month, { disableFuture, maxDate }); + const isPreviousMonthDisabled = usePreviousMonthDisabled(month, { disablePast, minDate }); const toggleView = () => { if (views.length === 1) { diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index 8dee7d6eb..3212cbff5 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -10,7 +10,7 @@ import { FadeTransitionGroup } from './FadeTransitionGroup'; import { Calendar, ExportedCalendarProps } from './Calendar'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; import { makeStyles, CircularProgress } from '@material-ui/core'; -import { useParsedDate } from '../../_shared/hooks/useParsedDate'; +import { useParsedDate } from '../../_shared/hooks/date-helpers-hooks'; import { CalendarHeader, CalendarHeaderProps } from './CalendarHeader'; import { WrapperVariantContext } from '../../wrappers/WrapperVariantContext'; diff --git a/lib/src/views/Clock/ClockView.tsx b/lib/src/views/Clock/ClockView.tsx index a6d54af52..bded0faf2 100644 --- a/lib/src/views/Clock/ClockView.tsx +++ b/lib/src/views/Clock/ClockView.tsx @@ -1,15 +1,15 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; -import { makeStyles } from '@material-ui/core/styles'; import Clock from './Clock'; import { pipe } from '../../_helpers/utils'; +import { makeStyles } from '@material-ui/core/styles'; import { useUtils } from '../../_shared/hooks/useUtils'; import { ParsableDate } from '../../constants/prop-types'; import { MaterialUiPickersDate } from '../../typings/date'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; -import { useParsedDate } from '../../_shared/hooks/useParsedDate'; import { getHourNumbers, getMinutesNumbers } from './ClockNumbers'; import { useMeridiemMode } from '../../TimePicker/TimePickerToolbar'; +import { useParsedDate } from '../../_shared/hooks/date-helpers-hooks'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../../_shared/ArrowSwitcher'; import { convertValueToMeridiem, createIsAfterIgnoreDatePart } from '../../_helpers/time-utils'; diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 498efbff9..4bc9e632b 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -1,8 +1,10 @@ import * as React from 'react'; +import clsx from 'clsx'; import Paper from '@material-ui/core/Paper'; import Popper, { PopperProps } from '@material-ui/core/Popper'; import ClickAwayListener from '@material-ui/core/ClickAwayListener'; import { WrapperProps } from './Wrapper'; +import { makeStyles } from '@material-ui/core'; import { InnerMobileWrapperProps } from './MobileWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; @@ -18,6 +20,12 @@ export interface DesktopWrapperProps WrapperProps, Partial {} +const useStyles = makeStyles(theme => ({ + popper: { + zIndex: theme.zIndex.modal, + }, +})); + export const DesktopPopperWrapper: React.FC = ({ open, wider, @@ -40,6 +48,7 @@ export const DesktopPopperWrapper: React.FC = ({ KeyboardDateInputComponent = KeyboardDateInput, ...other }) => { + const classes = useStyles(); const ref = React.useRef(null); useGlobalKeyDown(open, { @@ -61,7 +70,13 @@ export const DesktopPopperWrapper: React.FC = ({ inputProps={{ 'data-mui-pickers-input': true }} /> - + {children} From 91e1edeeb52123a48e71dfd6053ab8e33f40bb00 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 26 Mar 2020 22:03:57 +0200 Subject: [PATCH 31/72] Update date-io adapter version to 2.5.0 --- .../DesktopDateRangePicker.tsx | 3 +- yarn.lock | 64 +++++++++---------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index 9344ed226..eef4079b7 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -9,7 +9,6 @@ import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; import { usePreviousMonthDisabled, - useParsedDate, useNextMonthDisabled, } from '../_shared/hooks/date-helpers-hooks'; @@ -89,7 +88,7 @@ export const DesktopDateRangePicker: React.FC = ( onChange(day); }; - const isRangeValid = (range: DateRange | null) => { + const isRangeValid = (range: DateRange | null): range is DateRange => { return Boolean(range && utils.isBefore(range[0], range[1])); }; diff --git a/yarn.lock b/yarn.lock index 35bc18afe..0faf534f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1353,52 +1353,52 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@date-io/core@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.4.0.tgz#59e1c6de1d48ee63c6e97681b415076d04e7b5bf" - integrity sha512-XUr4TSwFmthcCn5QYnGqobbnBqOsSyCggRfvieMQHPSz5zei8KYpw4xlvFFQfu/MI3CmCHDjWMkVaPy/uFIDNA== +"@date-io/core@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.5.0.tgz#afb3a82e989a925755cba139b71f95b6b396dce2" + integrity sha512-GifWlc0hyLdYwivltV8KVwE+OOVgYoHF4DvvKn6VOA73iVvqxbXXeL18PVFjMw8r0JUHmuhP6S+4TD8INBzXZA== "@date-io/date-fns@^2.1.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.4.0.tgz#d41aa353806a3b8aa28fbcadf2c860438bcbfaa9" - integrity sha512-DYlfSiTs6GuPmbAmJ9ws7aaOd8f89lVBBqU+71w4Qxxv9DW2qQvBWwOkvCJ5qSp4ae4+PtCzy6JKQDKsdgBaJg== + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.5.0.tgz#10ff3b2220f1814e1d4d835dbfb9fb6f497e83aa" + integrity sha512-HiQqjVLFUPsOYtW3damMw5jsY5Yk2KG3LcI7s2eioce+jgxZ6XjhGiyWur14btgTVihhkVjfdzmd5XMfpRXH1Q== dependencies: - "@date-io/core" "^2.4.0" + "@date-io/core" "^2.5.0" "@date-io/dayjs@^2.1.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.4.0.tgz#972094ba29af18422c01e2674a3d5c5704382a76" - integrity sha512-U4IxzpK4Us9lkMN+iTzwJayKjIcb+0X2Kdpt+XoB+0kug7ri+wGwypxncaYnRwwztYGBKWJcQiDlSOBU+0pkBA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.5.0.tgz#41d4b627914da8e4ac20ec7e15f9de507449fa0a" + integrity sha512-FCgx9Vql+BJMhu0t6Ou474b2O52EEwy1nfznvzeWewMUa1vJkeXrCQm11LlUZQcAOcUhF7L7zuSUST8IlFKyDQ== dependencies: - "@date-io/core" "^2.4.0" + "@date-io/core" "^2.5.0" "@date-io/hijri@^2.2.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/hijri/-/hijri-2.4.0.tgz#0deaabd0f3431c357912defd4037e7b717906e58" - integrity sha512-0ZHbKvFCzncdc920wnVfIU1p/So9NNFXT7X0QvP0XzhQIq3qVMYuJsmpaogU20UNZrMQ612yOjuz94HtmdEjUA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/hijri/-/hijri-2.5.0.tgz#dd803611561ed55bed5d0ddc77fc187f86e49119" + integrity sha512-3CBDxPUmVhwX38OwTXK6VfvvYsBHZOxE5CuDjPGyhDilMW7Nl1Y4EYcaNXY8b/0FhDCyAVK7I/7PbaN25q9SvQ== dependencies: - "@date-io/moment" "^2.4.0" + "@date-io/moment" "^2.5.0" "@date-io/jalaali@^2.0.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/jalaali/-/jalaali-2.4.0.tgz#58a2a5df813285fe5d3c477d7d1b2a0a2cdd344a" - integrity sha512-f9Uj11F2KUmlp3AA+ocddXaK4Wit5Pc7tUVz90sS8Um1jM2vHb/f6F4d+RhouH0/8DuIFClMGCYPFWRvUjN1YQ== + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/jalaali/-/jalaali-2.5.0.tgz#d13ffd06896c0d8944682042cd086c8e217d0a48" + integrity sha512-3taCWs9AbWHQHdg1tg4jTBHX1f+/XmYnfps/ufAe8nKL8KnR6Bbs/gGoObw6VoD+jLy6+utXDpmyX1WsKsX/0g== dependencies: - "@date-io/moment" "^2.4.0" + "@date-io/moment" "^2.5.0" "@date-io/luxon@^2.1.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.4.0.tgz#b032f1d4eac47c18dc1c447e9235295cf95bf166" - integrity sha512-EFbLSYVhXcxMxg4pJF7e5yCwB9KZc4MJlsWSpXUla29ylcB9rlU07AeV74ogdy+kzakFFN/QdFxhuMvxqyBAxw== + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.5.0.tgz#0b29de3a64ad31aa5f8ccb9295df821148993525" + integrity sha512-N1bBoU1+5eTI+F8t06N3MoMd4Q46UMPCe20Hr/rGGKPfxEWDsG9uz6UU1orYWtZbWRyaBMPHZbzOKt+DKtC4/w== dependencies: - "@date-io/core" "^2.4.0" + "@date-io/core" "^2.5.0" -"@date-io/moment@^2.1.0", "@date-io/moment@^2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.4.0.tgz#84612f4cf175ec8093c43a6b6176f874d2d1f007" - integrity sha512-857C9idmZGpD8NygxQsOXPa3OePC6UFAhU996dCUv8cY17p1tkjgj7/JZ3J7PTV2i8ybeUDUD/tAadACEtI05g== +"@date-io/moment@^2.1.0", "@date-io/moment@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.5.0.tgz#f66e604a38f0687dfb410a2ae8dd8ea139322a86" + integrity sha512-PRdmnbpNMWWQ6ykaMUF7rROWuGl0l9GOdsTO8wRnZjJG19tb+3gE03iGL+UajjB9EJrtgTmihIUoOt6wUhh5Bg== dependencies: - "@date-io/core" "^2.4.0" + "@date-io/core" "^2.5.0" "@emotion/hash@^0.8.0": version "0.8.0" @@ -2085,9 +2085,9 @@ integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== "@types/luxon@^1.11.0": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.21.0.tgz#db792d29f535d49522cb6d94dd9da053efc950a1" - integrity sha512-Zhrf65tpjOlVIYrUhX9eu1VzRo8iixQDLFPbfqFxPpG4pBTNNPZ2BFhYE0IAsDfW9GWg+RcrUqiLwrGJH4rq4w== + version "1.22.0" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.22.0.tgz#dbdf2cc7ba3dfce98c57a3f0e003791122cba009" + integrity sha512-riAvdx85rU7OXCrjW3f7dIf7fuJDrxck2Dkjd0weh6ul7q+wumrwe6+/tD8v7yOKnZAuEnTFF4FU7b+5W/I3bw== "@types/minimatch@*": version "3.0.3" From 4930936d0b5918adc3f26a9553caafbb7f79caf0 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Fri, 27 Mar 2020 15:45:11 +0200 Subject: [PATCH 32/72] Do not display range preview on highlighted days --- .../DesktopDateRangePicker.tsx | 8 ++++--- lib/src/DateRangePicker/date-range-manager.ts | 23 +++++++++++++++---- lib/src/wrappers/DesktopPopperWrapper.tsx | 14 +++++++---- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index eef4079b7..fbf9e1de4 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -4,7 +4,7 @@ import { makeStyles } from '@material-ui/core'; import { DateRangeDay } from './DateRangePickerDay'; import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; -import { calculateRangeChange } from './date-range-manager'; +import { calculateRangePreview } from './date-range-manager'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; import { @@ -76,12 +76,12 @@ export const DesktopDateRangePicker: React.FC = ( const isNextMonthDisabled = useNextMonthDisabled(currentMonth, { disableFuture, maxDate }); const isPreviousMonthDisabled = usePreviousMonthDisabled(currentMonth, { disablePast, minDate }); - const previewingRange = calculateRangeChange({ + const previewingRange = calculateRangePreview({ utils, range: date, newDate: rangePreviewDay, currentlySelectingRangeEnd, - }).newRange; + }); const handleDayChange = (day: MaterialUiPickersDate) => { setRangePreviewDay(null); @@ -107,6 +107,8 @@ export const DesktopDateRangePicker: React.FC = ( const handlePreviewDayChange = (newPreviewRequest: MaterialUiPickersDate) => { if (!isWithinRange(newPreviewRequest, date)) { setRangePreviewDay(newPreviewRequest); + } else { + setRangePreviewDay(null); } }; diff --git a/lib/src/DateRangePicker/date-range-manager.ts b/lib/src/DateRangePicker/date-range-manager.ts index 80615d7e4..2ce5e5685 100644 --- a/lib/src/DateRangePicker/date-range-manager.ts +++ b/lib/src/DateRangePicker/date-range-manager.ts @@ -16,10 +16,6 @@ export function calculateRangeChange({ currentlySelectingRangeEnd, }: CalculateRangeChangeOptions): { nextSelection: 'start' | 'end'; newRange: DateRange } { const [start, end] = range; - const isRangeFilledPartially = start === null || end === null; - - if (isRangeFilledPartially) { - } if (currentlySelectingRangeEnd === 'start') { return utils.isAfter(selectedDate, end) @@ -31,3 +27,22 @@ export function calculateRangeChange({ : { nextSelection: 'end', newRange: [start, selectedDate] }; } } + +export function calculateRangePreview(options: CalculateRangeChangeOptions): DateRange { + if (!options.newDate) { + return [null, null]; + } + + const [start, end] = options.range; + const { newRange } = calculateRangeChange(options); + + if (!start || !end) { + return newRange; + } + + const [previewStart, previewEnd] = newRange; + // prettier-ignore + return options.currentlySelectingRangeEnd === 'end' + ? [end, previewEnd] + : [previewStart, start]; +} diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 4bc9e632b..0176c3daf 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -1,10 +1,11 @@ import * as React from 'react'; import clsx from 'clsx'; +import Fade from '@material-ui/core/Fade'; import Paper from '@material-ui/core/Paper'; import Popper, { PopperProps } from '@material-ui/core/Popper'; import ClickAwayListener from '@material-ui/core/ClickAwayListener'; import { WrapperProps } from './Wrapper'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import { InnerMobileWrapperProps } from './MobileWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; @@ -71,15 +72,20 @@ export const DesktopPopperWrapper: React.FC = ({ /> - - {children} - + {({ TransitionProps }) => ( + + + {children} + + + )} ); From d08fa224edb513ee31e188c751c16284652470c2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Fri, 27 Mar 2020 20:37:00 +0200 Subject: [PATCH 33/72] Better focus and blur handling for popper --- .../DateRangePicker/DateRangePickerInput.tsx | 6 ++- lib/src/_helpers/utils.ts | 15 +++++++ lib/src/wrappers/DesktopPopperWrapper.tsx | 40 ++++++++++++++----- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 1072e1ea7..6841998b3 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -6,6 +6,7 @@ import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { makeStyles, Typography } from '@material-ui/core'; +import { createDelegatedEventHandler } from '../_helpers/utils'; export const useStyles = makeStyles( theme => ({ @@ -50,6 +51,7 @@ export const DateRangePickerInput: React.FC = ({ currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, openPicker, + onFocus, ...other }) => { const utils = useUtils() @@ -103,7 +105,7 @@ export const DateRangePickerInput: React.FC = ({ onChange={handleStartChange} hideOpenPickerButton openPicker={() => {}} - onFocus={openRangeStartSelection} + onFocus={createDelegatedEventHandler(openRangeStartSelection, onFocus)} className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'start' })} /> @@ -118,7 +120,7 @@ export const DateRangePickerInput: React.FC = ({ onChange={handleEndChange} hideOpenPickerButton openPicker={() => {}} - onFocus={openRangeEndSelection} + onFocus={createDelegatedEventHandler(openRangeEndSelection, onFocus)} className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'end' })} />
diff --git a/lib/src/_helpers/utils.ts b/lib/src/_helpers/utils.ts index 75297ab91..5f701c1b6 100644 --- a/lib/src/_helpers/utils.ts +++ b/lib/src/_helpers/utils.ts @@ -32,3 +32,18 @@ export const pipe = (...fns: ((...args: any[]) => any)[]) => (prevFn, nextFn) => (...args) => nextFn(prevFn(...args)), value => value ); + +export const executeInTheNextEventLoopTick = (fn: () => void) => setTimeout(fn, 0); + +export function createDelegatedEventHandler( + fn: (e: TEvent) => void, + onEvent?: (e: TEvent) => void +) { + return (e: TEvent) => { + fn(e); + + if (onEvent) { + onEvent(e); + } + }; +} diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 0176c3daf..f41fb4709 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -2,14 +2,16 @@ import * as React from 'react'; import clsx from 'clsx'; import Fade from '@material-ui/core/Fade'; import Paper from '@material-ui/core/Paper'; +// @ts-ignore TODO make definitions +import TrapFocus from '@material-ui/core/Modal/TrapFocus'; import Popper, { PopperProps } from '@material-ui/core/Popper'; -import ClickAwayListener from '@material-ui/core/ClickAwayListener'; import { WrapperProps } from './Wrapper'; import { makeStyles } from '@material-ui/core/styles'; import { InnerMobileWrapperProps } from './MobileWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { useGlobalKeyDown, keycode } from '../_shared/hooks/useKeyDown'; +import { executeInTheNextEventLoopTick, createDelegatedEventHandler } from '../_helpers/utils'; export interface InnerDesktopPopperWrapperProps { /** Popover props passed to material-ui Popover */ @@ -50,16 +52,24 @@ export const DesktopPopperWrapper: React.FC = ({ ...other }) => { const classes = useStyles(); - const ref = React.useRef(null); + const inputRef = React.useRef(null); + const popperRef = React.useRef(null); useGlobalKeyDown(open, { [keycode.Esc]: onDismiss, }); - const handleClickAway = (e: React.MouseEvent) => { - if (!open || (e.target as HTMLElement)?.dataset?.muiPickersInput !== 'true') { + const handleBlur = () => { + executeInTheNextEventLoopTick(() => { + if ( + inputRef.current?.contains(document.activeElement) || + popperRef.current?.contains(document.activeElement) + ) { + return; + } + onDismiss(); - } + }); }; return ( @@ -67,24 +77,32 @@ export const DesktopPopperWrapper: React.FC = ({ {({ TransitionProps }) => ( - + popperRef.current?.ownerDocument ?? document} + isEnabled={() => true} + > - {children} + + {children} + - + )} From 164f12f799e209eabd6db52925f497dba10ef2b4 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 28 Mar 2020 11:54:25 +0200 Subject: [PATCH 34/72] Fix range preview border style --- .../DateRangePicker/DateRangePickerDay.tsx | 38 ++++++++++++------- .../DesktopDateRangePicker.tsx | 2 +- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerDay.tsx b/lib/src/DateRangePicker/DateRangePickerDay.tsx index 03998fb0e..9deaecff5 100644 --- a/lib/src/DateRangePicker/DateRangePickerDay.tsx +++ b/lib/src/DateRangePicker/DateRangePickerDay.tsx @@ -27,9 +27,14 @@ const startBorderStyle = { const useStyles = makeStyles( theme => ({ rangeIntervalDay: { - padding: `0 ${DAY_MARGIN}px`, - '&:first-child $rangeIntervalDayPreview': startBorderStyle, - '&:last-child $rangeIntervalDayPreview': endBorderStyle, + '&:first-child $rangeIntervalDayPreview': { + ...startBorderStyle, + borderLeftColor: theme.palette.divider, + }, + '&:last-child $rangeIntervalDayPreview': { + ...endBorderStyle, + borderRightColor: theme.palette.divider, + }, }, rangeIntervalDayHighlight: { borderRadius: 0, @@ -67,18 +72,20 @@ const useStyles = makeStyles( backgroundColor: 'transparent', }, rangeIntervalPreview: { - borderTop: '2px solid transparent', - borderBottom: '2px solid transparent', + border: '2px solid transparent', }, rangeIntervalDayPreview: { borderRadius: 0, - borderTop: `2px dashed ${theme.palette.divider}`, - borderBottom: `2px dashed ${theme.palette.divider}`, + border: `2px dashed ${theme.palette.divider}`, + borderLeftColor: 'transparent', + borderRightColor: 'transparent', }, rangeIntervalDayPreviewStart: { + borderLeftColor: theme.palette.divider, ...startBorderStyle, }, rangeIntervalDayPreviewEnd: { + borderRightColor: theme.palette.divider, ...endBorderStyle, }, }), @@ -104,21 +111,26 @@ export const PureDateRangeDay = ({ const isEndOfMonth = utils.isSameDay(day, utils.endOfMonth(day)); const isStartOfMonth = utils.isSameDay(day, utils.startOfMonth(day)); + const shouldRenderHighlight = isHighlighting && inCurrentMonth; + const shouldRenderPreview = isPreviewing && inCurrentMonth; + return (
= ( const CalendarTransitionProps = React.useMemo( () => ({ - onMouseLeave: () => setRangePreviewDay(null), + // onMouseLeave: () => setRangePreviewDay(null), }), [] ); From 07768281d183ffc11dd895df09ca1472847699b6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 28 Mar 2020 12:19:33 +0200 Subject: [PATCH 35/72] Fix type erros --- lib/.size-snapshot.json | 12 ++++---- lib/src/DateRangePicker/DateRangePicker.tsx | 28 ++++++++++++------- .../DateRangePicker/DateRangePickerInput.tsx | 2 +- lib/src/Picker/makePickerWithState.tsx | 14 ++++++---- lib/src/_shared/hooks/usePickerState.ts | 17 +++++++++-- lib/src/views/Calendar/CalendarView.tsx | 2 +- lib/src/views/Calendar/Day.tsx | 2 +- lib/src/views/Calendar/Year.tsx | 2 +- lib/src/wrappers/makeWrapperComponent.tsx | 23 +++++++++------ 9 files changed, 66 insertions(+), 36 deletions(-) diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index aeefd56ac..9b6499012 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,15 +1,15 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 145384, - "minified": 79576, - "gzipped": 21474, + "bundled": 179687, + "minified": 97432, + "gzipped": 25772, "treeshaked": { "rollup": { - "code": 65692, - "import_statements": 2099 + "code": 80989, + "import_statements": 2227 }, "webpack": { - "code": 73171 + "code": 89612 } } }, diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index be7e0863a..92c6ac85a 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; -import { DateRange, RangeInput } from './RangeTypes'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; +import { DateRangeInputProps } from './DateRangePickerInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { AllSharedPickerProps } from '../Picker/SharedPickerProps'; +import { DateRange as DateRangeType, RangeInput } from './RangeTypes'; import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; @@ -25,10 +26,13 @@ export function parseRangeInputValue( } export function makeRangePicker(Wrapper: TWrapper) { - const WrapperComponent = makeWrapperComponent(Wrapper, { - KeyboardDateInputComponent: DateRangePickerInput, - PureDateInputComponent: DateRangePickerInput, - }); + const WrapperComponent = makeWrapperComponent( + Wrapper, + { + KeyboardDateInputComponent: DateRangePickerInput, + PureDateInputComponent: DateRangePickerInput, + } + ); function RangePickerWithStateAndWrapper({ calendars, @@ -63,15 +67,18 @@ export function makeRangePicker(Wrapper: TWrapper) parseInput: parseRangeInputValue, areValuesEqual: (a, b) => utils.isEqual(a[0], b[0]) && utils.isEqual(a[1], b[1]), validateInput: () => undefined, + emptyValue: [null, null], } ); return ( (Wrapper: TWrapper) return RangePickerWithStateAndWrapper; } -export const DateRangePicker = makeRangePicker(DesktopPopperWrapper); +// TODO replace with new export type syntax +export type DateRange = DateRangeType; -export { DateRange }; +export const DateRangePicker = makeRangePicker(DesktopPopperWrapper); diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 6841998b3..a4f419de2 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -29,7 +29,7 @@ export interface ExportedDateRangePickerInputProps { rangeChangingStrategy?: 'expand' | 'circular'; } -interface DateRangeInputProps +export interface DateRangeInputProps extends ExportedDateRangePickerInputProps, DateInputProps { currentlySelectingRangeEnd: 'start' | 'end'; diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 7a9895911..f71878c77 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { useUtils } from '../_shared/hooks/useUtils'; import { ParsableDate } from '../constants/prop-types'; import { MaterialUiPickersDate } from '../typings/date'; -import { PureDateInput } from '../_shared/PureDateInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; @@ -11,6 +10,7 @@ import { validateDateValue } from '../_helpers/text-field-helper'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { withDateAdapterProp } from '../_shared/withDateAdapterProp'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; +import { PureDateInput, DateInputProps } from '../_shared/PureDateInput'; import { AnyPickerView, AllSharedPickerProps } from './SharedPickerProps'; import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; @@ -25,10 +25,13 @@ export function makePickerWithStateAndWrapper< T extends AllAvailableForOverrideProps, TWrapper extends SomeWrapper = typeof ResponsiveWrapper >(Wrapper: TWrapper, { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions) { - const PickerWrapper = makeWrapperComponent(Wrapper, { - KeyboardDateInputComponent: KeyboardDateInput, - PureDateInputComponent: PureDateInput, - }); + const PickerWrapper = makeWrapperComponent( + Wrapper, + { + KeyboardDateInputComponent: KeyboardDateInput, + PureDateInputComponent: PureDateInput, + } + ); function PickerWithState(props: T & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); @@ -39,6 +42,7 @@ export function makePickerWithStateAndWrapper< ParsableDate, MaterialUiPickersDate >(allProps, { + emptyValue: null, parseInput: parsePickerInputValue, validateInput: validateDateValue, areValuesEqual: utils.isEqual, diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index f2dc91f5d..5fde3749e 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -20,6 +20,7 @@ export function usePickerState( utils: MuiPickersAdapter, props: BasePickerProps ) => React.ReactNode | undefined; + emptyValue: TDateValue; areValuesEqual: (valueLeft: TDateValue, valueRight: TDateValue) => boolean; } ) { @@ -64,7 +65,7 @@ export function usePickerState( () => ({ open: isOpen, format: inputFormat, - onClear: () => acceptDate(null, true), + onClear: () => acceptDate(valueManager.emptyValue, true), onAccept: () => acceptDate(pickerDate, true), onDismiss: () => setIsOpen(false), onSetToday: () => { @@ -73,7 +74,7 @@ export function usePickerState( acceptDate(now as any, Boolean(autoOk)); }, }), - [acceptDate, autoOk, inputFormat, isOpen, now, pickerDate, setIsOpen] + [acceptDate, autoOk, inputFormat, isOpen, now, pickerDate, setIsOpen, valueManager.emptyValue] ); const pickerProps = useMemo( @@ -129,7 +130,17 @@ export function usePickerState( parsedDateValue: pickerDate, openPicker: () => !readOnly && !disabled && setIsOpen(true), }), - [pickerDate, disabled, inputFormat, onChange, readOnly, setIsOpen, validationError, value] + [ + onChange, + inputFormat, + isOpen, + value, + validationError, + pickerDate, + readOnly, + disabled, + setIsOpen, + ] ); const pickerState = { pickerProps, inputProps, wrapperProps }; diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index 3212cbff5..bb01726c8 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -9,7 +9,7 @@ import { MaterialUiPickersDate } from '../../typings/date'; import { FadeTransitionGroup } from './FadeTransitionGroup'; import { Calendar, ExportedCalendarProps } from './Calendar'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; -import { makeStyles, CircularProgress } from '@material-ui/core'; +import { makeStyles, CircularProgress, Grid } from '@material-ui/core'; import { useParsedDate } from '../../_shared/hooks/date-helpers-hooks'; import { CalendarHeader, CalendarHeaderProps } from './CalendarHeader'; import { WrapperVariantContext } from '../../wrappers/WrapperVariantContext'; diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 44d272406..ad546edb3 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -154,7 +154,7 @@ const PureDay: React.FC = ({ } }; - const handleClick = (e: React.MouseEvent) => { + const handleClick = (e: React.MouseEvent) => { if (!disabled) { onDaySelect(day, true); } diff --git a/lib/src/views/Calendar/Year.tsx b/lib/src/views/Calendar/Year.tsx index e951489e5..1c0f7798a 100644 --- a/lib/src/views/Calendar/Year.tsx +++ b/lib/src/views/Calendar/Year.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import clsx from 'clsx'; import Typography from '@material-ui/core/Typography'; -import { makeStyles, fade } from '@material-ui/core/styles'; import { onSpaceOrEnter } from '../../_helpers/utils'; +import { makeStyles, fade } from '@material-ui/core/styles'; import { WrapperVariantContext } from '../../wrappers/WrapperVariantContext'; export interface YearProps { diff --git a/lib/src/wrappers/makeWrapperComponent.tsx b/lib/src/wrappers/makeWrapperComponent.tsx index 12aab4a3f..fd1cfaf61 100644 --- a/lib/src/wrappers/makeWrapperComponent.tsx +++ b/lib/src/wrappers/makeWrapperComponent.tsx @@ -5,26 +5,31 @@ import { ResponsiveWrapperProps } from './ResponsiveWrapper'; import { DateValidationProps } from '../_helpers/text-field-helper'; import { OmitInnerWrapperProps, SomeWrapper, WrapperProps } from './Wrapper'; -interface MakePickerOptions { - PureDateInputComponent?: React.FC>; - KeyboardDateInputComponent?: React.FC>; +interface MakePickerOptions { + PureDateInputComponent?: React.FC; + KeyboardDateInputComponent?: React.FC; } -interface WithWrapperProps { +interface WithWrapperProps { children: React.ReactNode; - inputProps: DateInputProps; + inputProps: TInputProps; wrapperProps: Omit; } /** Creates a component that rendering modal/popover/nothing and spreading props down to text field */ -export function makeWrapperComponent( +export function makeWrapperComponent< + TInputProps extends DateInputProps, + TInputValue, + TDateValue, + TWrapper extends SomeWrapper = any +>( Wrapper: TWrapper, - { KeyboardDateInputComponent, PureDateInputComponent }: MakePickerOptions + { KeyboardDateInputComponent, PureDateInputComponent }: MakePickerOptions ) { function WrapperComponent( props: Partial> & DateValidationProps & - WithWrapperProps & + WithWrapperProps & Partial> ) { const { @@ -68,7 +73,9 @@ export function makeWrapperComponent Date: Sat, 28 Mar 2020 17:15:11 +0200 Subject: [PATCH 36/72] Fix fantom borders appearing --- .../DateRangePicker/DateRangePickerDay.tsx | 26 ++++++++++--------- .../DesktopDateRangePicker.tsx | 2 +- lib/src/views/MobileKeyboardInputView.tsx | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerDay.tsx b/lib/src/DateRangePicker/DateRangePickerDay.tsx index 9deaecff5..b58d4e184 100644 --- a/lib/src/DateRangePicker/DateRangePickerDay.tsx +++ b/lib/src/DateRangePicker/DateRangePickerDay.tsx @@ -72,6 +72,7 @@ const useStyles = makeStyles( backgroundColor: 'transparent', }, rangeIntervalPreview: { + // replace default day component margin with transparent border to avoid jumping on preview border: '2px solid transparent', }, rangeIntervalDayPreview: { @@ -79,15 +80,18 @@ const useStyles = makeStyles( border: `2px dashed ${theme.palette.divider}`, borderLeftColor: 'transparent', borderRightColor: 'transparent', + + '&$rangeIntervalDayPreviewStart': { + borderLeftColor: theme.palette.divider, + ...startBorderStyle, + }, + '&$rangeIntervalDayPreviewEnd': { + borderRightColor: theme.palette.divider, + ...endBorderStyle, + }, }, - rangeIntervalDayPreviewStart: { - borderLeftColor: theme.palette.divider, - ...startBorderStyle, - }, - rangeIntervalDayPreviewEnd: { - borderRightColor: theme.palette.divider, - ...endBorderStyle, - }, + rangeIntervalDayPreviewStart: {}, + rangeIntervalDayPreviewEnd: {}, }), { name: 'MuiPickersDateRangeDay' } ); @@ -127,10 +131,8 @@ export const PureDateRangeDay = ({ data-mui-test={shouldRenderPreview ? 'DateRangePreview' : undefined} className={clsx(classes.rangeIntervalPreview, { [classes.rangeIntervalDayPreview]: shouldRenderPreview, - [classes.rangeIntervalDayPreviewEnd]: - isEndOfPreviewing || (shouldRenderPreview && isEndOfMonth), - [classes.rangeIntervalDayPreviewStart]: - isStartOfPreviewing || (shouldRenderPreview && isStartOfMonth), + [classes.rangeIntervalDayPreviewEnd]: isEndOfPreviewing || isEndOfMonth, + [classes.rangeIntervalDayPreviewStart]: isStartOfPreviewing || isStartOfMonth, })} > = ( const CalendarTransitionProps = React.useMemo( () => ({ - // onMouseLeave: () => setRangePreviewDay(null), + onMouseLeave: () => setRangePreviewDay(null), }), [] ); diff --git a/lib/src/views/MobileKeyboardInputView.tsx b/lib/src/views/MobileKeyboardInputView.tsx index 2ff95dd69..00877533e 100644 --- a/lib/src/views/MobileKeyboardInputView.tsx +++ b/lib/src/views/MobileKeyboardInputView.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; import KeyboardDateInput from '../_shared/KeyboardDateInput'; +import { makeStyles } from '@material-ui/core/styles'; import { DateInputProps } from '../_shared/PureDateInput'; import { InnerMobileWrapperProps } from '../wrappers/MobileWrapper'; From 50801c2c95fb0e63815b11843c653516a3b40b01 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 28 Mar 2020 17:56:05 +0200 Subject: [PATCH 37/72] Better styling for popper and possibility to replace transition --- lib/.size-snapshot.json | 12 ++++---- lib/rollup.config.js | 3 ++ .../DateRangePicker/DateRangePickerDay.tsx | 2 +- .../DateRangePicker/DateRangePickerInput.tsx | 3 +- .../DateRangePicker/DateRangePickerView.tsx | 15 ++++++---- .../DesktopDateRangePicker.tsx | 2 +- lib/src/_shared/ArrowSwitcher.tsx | 4 ++- lib/src/views/Calendar/Calendar.tsx | 3 +- lib/src/views/Calendar/CalendarView.tsx | 4 ++- lib/src/views/Calendar/Day.tsx | 2 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 30 +++++++++++++++---- lib/typings.d.ts | 2 +- 12 files changed, 56 insertions(+), 26 deletions(-) diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index 9b6499012..5f65a1162 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,15 +1,15 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 179687, - "minified": 97432, - "gzipped": 25772, + "bundled": 180316, + "minified": 97608, + "gzipped": 25789, "treeshaked": { "rollup": { - "code": 80989, - "import_statements": 2227 + "code": 81201, + "import_statements": 2175 }, "webpack": { - "code": 89612 + "code": 89920 } } }, diff --git a/lib/rollup.config.js b/lib/rollup.config.js index 0628df6f9..2b07257bc 100644 --- a/lib/rollup.config.js +++ b/lib/rollup.config.js @@ -38,6 +38,9 @@ const globals = { '@material-ui/core/Toolbar': 'material-ui.Toolbar', '@material-ui/core/Typography': 'material-ui.Typography', '@material-ui/core/useMediaQuery': 'material-ui.useMediaQuery', + '@material-ui/core/Modal/TrapFocus': 'material-ui.TrapFocus', + '@material-ui/core/Modal/Grow': 'material-ui.Grow', + '@material-ui/core/Modal/Popper': 'material-ui.Popper', }; const extensions = ['.ts', '.tsx', '.js']; diff --git a/lib/src/DateRangePicker/DateRangePickerDay.tsx b/lib/src/DateRangePicker/DateRangePickerDay.tsx index b58d4e184..9f54cb312 100644 --- a/lib/src/DateRangePicker/DateRangePickerDay.tsx +++ b/lib/src/DateRangePicker/DateRangePickerDay.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import clsx from 'clsx'; -import { makeStyles, fade } from '@material-ui/core'; import { DAY_MARGIN } from '../constants/dimensions'; import { useUtils } from '../_shared/hooks/useUtils'; +import { makeStyles, fade } from '@material-ui/core/styles'; import { Day, DayProps, areDayPropsEqual } from '../views/Calendar/Day'; interface DateRangeDayProps extends DayProps { diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index a4f419de2..73bae287d 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; import clsx from 'clsx'; +import Typography from '@material-ui/core/Typography'; import KeyboardDateInput from '../_shared/KeyboardDateInput'; import { RangeInput, DateRange } from './RangeTypes'; import { useUtils } from '../_shared/hooks/useUtils'; +import { makeStyles } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; -import { makeStyles, Typography } from '@material-ui/core'; import { createDelegatedEventHandler } from '../_helpers/utils'; export const useStyles = makeStyles( diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 56965914c..25d763821 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { RangeInput, DateRange } from './RangeTypes'; -import { useUtils } from '../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { calculateRangeChange } from './date-range-manager'; +import { useUtils, useNow } from '../_shared/hooks/useUtils'; import { SharedPickerProps } from '../Picker/SharedPickerProps'; import { useParsedDate } from '../_shared/hooks/date-helpers-hooks'; import { useCalendarState } from '../views/Calendar/useCalendarState'; @@ -47,6 +47,7 @@ export const DateRangePickerView: React.FC = ({ shouldDisableDate, ...other }) => { + const now = useNow(); const utils = useUtils(); const wrapperVariant = React.useContext(WrapperVariantContext); const minDate = useParsedDate(unparsedMinDate)!; @@ -60,7 +61,7 @@ export const DateRangePickerView: React.FC = ({ onMonthSwitchingAnimationEnd, changeFocusedDay, } = useCalendarState({ - date: start || end || utils.date(), + date: start || end || now, minDate, maxDate, reduceAnimations, @@ -72,18 +73,20 @@ export const DateRangePickerView: React.FC = ({ }); const scrollToDayIfNeeded = (day: MaterialUiPickersDate) => { - const currentViewingRange = calendars - 1; + const displayingMonthRange = calendars - 1; const currentMonthNumber = utils.getMonth(calendarState.currentMonth); const requestedMonthNumber = utils.getMonth(day); if ( requestedMonthNumber < currentMonthNumber || - requestedMonthNumber > currentMonthNumber + currentViewingRange + requestedMonthNumber > currentMonthNumber + displayingMonthRange ) { const newMonth = - currentlySelectingRangeEnd === 'start' ? start : utils.addMonths(end, -currentViewingRange); + currentlySelectingRangeEnd === 'start' + ? start + : // If need to focus end, scroll to the state when "end" is displaying in the last calendar + utils.addMonths(end, -displayingMonthRange); - console.log('CHAING MONTH'); changeMonth(newMonth); } }; diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index fbf9e1de4..9c3e6c544 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { DateRange } from './RangeTypes'; -import { makeStyles } from '@material-ui/core'; import { DateRangeDay } from './DateRangePickerDay'; import { useUtils } from '../_shared/hooks/useUtils'; +import { makeStyles } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; import { calculateRangePreview } from './date-range-manager'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; diff --git a/lib/src/_shared/ArrowSwitcher.tsx b/lib/src/_shared/ArrowSwitcher.tsx index 8d8917ef4..3ea35d481 100644 --- a/lib/src/_shared/ArrowSwitcher.tsx +++ b/lib/src/_shared/ArrowSwitcher.tsx @@ -1,8 +1,10 @@ import * as React from 'react'; import clsx from 'clsx'; +import Typography from '@material-ui/core/Typography'; +import IconButton, { IconButtonProps } from '@material-ui/core/IconButton'; import { ArrowLeftIcon } from './icons/ArrowLeftIcon'; import { ArrowRightIcon } from './icons/ArrowRightIcon'; -import { IconButton, IconButtonProps, makeStyles, useTheme, Typography } from '@material-ui/core'; +import { makeStyles, useTheme } from '@material-ui/core/styles'; export interface ExportedArrowSwitcherProps { /** Left arrow icon */ diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index e8619ad67..9d18c3452 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -1,12 +1,13 @@ import * as React from 'react'; import clsx from 'clsx'; +import Typography from '@material-ui/core/Typography'; import { Day, DayProps } from './Day'; import { MaterialUiPickersDate } from '../../typings/date'; import { useUtils, useNow } from '../../_shared/hooks/useUtils'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; +import { makeStyles, useTheme } from '@material-ui/core/styles'; import { DAY_SIZE, DAY_MARGIN } from '../../constants/dimensions'; import { findClosestEnabledDate } from '../../_helpers/date-utils'; -import { makeStyles, useTheme, Typography } from '@material-ui/core'; import { useGlobalKeyDown, keycode } from '../../_shared/hooks/useKeyDown'; import { SlideTransition, SlideDirection, SlideTransitionProps } from './SlideTransition'; diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index bb01726c8..3a6c855e7 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -1,15 +1,17 @@ import * as React from 'react'; +import Grid from '@material-ui/core/Grid'; +import CircularProgress from '@material-ui/core/CircularProgress'; import { YearSelection } from './YearSelection'; import { MonthSelection } from './MonthSelection'; import { DatePickerView } from '../../DatePicker'; import { useCalendarState } from './useCalendarState'; +import { makeStyles } from '@material-ui/core/styles'; import { VIEW_HEIGHT } from '../../constants/dimensions'; import { ParsableDate } from '../../constants/prop-types'; import { MaterialUiPickersDate } from '../../typings/date'; import { FadeTransitionGroup } from './FadeTransitionGroup'; import { Calendar, ExportedCalendarProps } from './Calendar'; import { PickerOnChangeFn } from '../../_shared/hooks/useViews'; -import { makeStyles, CircularProgress, Grid } from '@material-ui/core'; import { useParsedDate } from '../../_shared/hooks/date-helpers-hooks'; import { CalendarHeader, CalendarHeaderProps } from './CalendarHeader'; import { WrapperVariantContext } from '../../wrappers/WrapperVariantContext'; diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index ad546edb3..729796bb1 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -140,7 +140,7 @@ const PureDay: React.FC = ({ ref.current && allowKeyboardControl ) { - // ref.current.focus(); + ref.current.focus(); } }, [allowKeyboardControl, disabled, focused, isAnimating, isInCurrentMonth]); diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index f41fb4709..ea961d0c0 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import clsx from 'clsx'; -import Fade from '@material-ui/core/Fade'; +import Grow from '@material-ui/core/Grow'; import Paper from '@material-ui/core/Paper'; // @ts-ignore TODO make definitions import TrapFocus from '@material-ui/core/Modal/TrapFocus'; @@ -11,11 +11,13 @@ import { InnerMobileWrapperProps } from './MobileWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { useGlobalKeyDown, keycode } from '../_shared/hooks/useKeyDown'; +import { TransitionProps } from '@material-ui/core/transitions/transition'; import { executeInTheNextEventLoopTick, createDelegatedEventHandler } from '../_helpers/utils'; export interface InnerDesktopPopperWrapperProps { /** Popover props passed to material-ui Popover */ PopperProps?: Partial; + TransitionComponent?: React.ComponentType; } export interface DesktopWrapperProps @@ -27,6 +29,15 @@ const useStyles = makeStyles(theme => ({ popper: { zIndex: theme.zIndex.modal, }, + paper: { + transformOrigin: 'top center', + '&:focus': { + outline: 'auto', + '@media (pointer:coarse)': { + outline: 0, + }, + }, + }, })); export const DesktopPopperWrapper: React.FC = ({ @@ -48,6 +59,7 @@ export const DesktopPopperWrapper: React.FC = ({ clearable, DialogProps, PureDateInputComponent, + TransitionComponent = Grow, KeyboardDateInputComponent = KeyboardDateInput, ...other }) => { @@ -92,16 +104,22 @@ export const DesktopPopperWrapper: React.FC = ({ {({ TransitionProps }) => ( popperRef.current?.ownerDocument ?? document} + disableEnforceFocus isEnabled={() => true} + getDoc={() => popperRef.current?.ownerDocument ?? document} > - - + + {children} - + )} diff --git a/lib/typings.d.ts b/lib/typings.d.ts index d58eafa3c..6069a01af 100644 --- a/lib/typings.d.ts +++ b/lib/typings.d.ts @@ -7,7 +7,7 @@ declare module '@date-io/type' { declare module '@material-ui/core/internal/svg-icons/createSvgIcon' { import * as React from 'react'; - import { SvgIconProps } from '@material-ui/core'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; declare const createSvgIcon: (path: React.ReactNode, name: string) => React.FC; export default createSvgIcon; From 3b175567b6e4d6a2b252ecc9def89ecfd581464f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 28 Mar 2020 17:57:42 +0200 Subject: [PATCH 38/72] Fix missing mui globals --- lib/.size-snapshot.json | 12 ++++++------ lib/rollup.config.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index 5f65a1162..1398db75e 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -14,13 +14,13 @@ } }, "build/dist/material-ui-pickers.umd.js": { - "bundled": 599635, - "minified": 223221, - "gzipped": 45558 + "bundled": 296515, + "minified": 117118, + "gzipped": 33379 }, "build/dist/material-ui-pickers.umd.min.js": { - "bundled": 539383, - "minified": 204705, - "gzipped": 40705 + "bundled": 250115, + "minified": 105323, + "gzipped": 30011 } } diff --git a/lib/rollup.config.js b/lib/rollup.config.js index 2b07257bc..9fe6f3da7 100644 --- a/lib/rollup.config.js +++ b/lib/rollup.config.js @@ -39,8 +39,8 @@ const globals = { '@material-ui/core/Typography': 'material-ui.Typography', '@material-ui/core/useMediaQuery': 'material-ui.useMediaQuery', '@material-ui/core/Modal/TrapFocus': 'material-ui.TrapFocus', - '@material-ui/core/Modal/Grow': 'material-ui.Grow', - '@material-ui/core/Modal/Popper': 'material-ui.Popper', + '@material-ui/core/Grow': 'material-ui.Grow', + '@material-ui/core/Popper': 'material-ui.Popper', }; const extensions = ['.ts', '.tsx', '.js']; From e313edda2abac4f8e4179e00b5d350b35e0250d2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 30 Mar 2020 14:12:49 +0300 Subject: [PATCH 39/72] Fix werid memoization issue in Safari --- .../MinMaxDateRangePicker.example.jsx | 2 +- lib/src/DateRangePicker/DesktopDateRangePicker.tsx | 12 ++++++++---- lib/src/DateRangePicker/date-range-manager.ts | 4 ++-- lib/src/views/Calendar/Calendar.tsx | 4 +++- lib/src/views/Calendar/Day.tsx | 4 +++- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx index aac36ad23..61e29d4ab 100644 --- a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx @@ -18,7 +18,7 @@ function MinMaxDateRangePicker() { disablePast value={selectedRange} shouldDisableDate={disableWeekends} - maxDate={utils.addMonths(selectedRange[0], 12)} + maxDate={utils.addMonths(utils.date(selectedRange[0]), 12)} onChange={date => handleDateChange(date)} /> ); diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx index 9c3e6c544..dc568be19 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DesktopDateRangePicker.tsx @@ -83,10 +83,13 @@ export const DesktopDateRangePicker: React.FC = ( currentlySelectingRangeEnd, }); - const handleDayChange = (day: MaterialUiPickersDate) => { - setRangePreviewDay(null); - onChange(day); - }; + const handleDayChange = React.useCallback( + (day: MaterialUiPickersDate) => { + setRangePreviewDay(null); + onChange(day); + }, + [onChange] + ); const isRangeValid = (range: DateRange | null): range is DateRange => { return Boolean(range && utils.isBefore(range[0], range[1])); @@ -152,6 +155,7 @@ export const DesktopDateRangePicker: React.FC = ( /> = ({ isAnimating: isMonthSwitchingAnimating, disabled: disabled, allowKeyboardControl: allowKeyboardControl, - focused: Boolean(focusedDay) && utils.isSameDay(day, focusedDay), + focused: + allowKeyboardControl && Boolean(focusedDay) && utils.isSameDay(day, focusedDay), today: utils.isSameDay(day, now), inCurrentMonth: isDayInCurrentMonth, selected: selectedDates.some(selectedDate => utils.isSameDay(selectedDate, day)), disableHighlightToday, showDaysOutsideCurrentMonth, focusable: + allowKeyboardControl && Boolean(nowFocusedDay) && utils.toJsDate(nowFocusedDay).getDate() === utils.toJsDate(day).getDate(), onDayFocus: changeFocusedDay, diff --git a/lib/src/views/Calendar/Day.tsx b/lib/src/views/Calendar/Day.tsx index 729796bb1..d0ea28e87 100644 --- a/lib/src/views/Calendar/Day.tsx +++ b/lib/src/views/Calendar/Day.tsx @@ -213,7 +213,9 @@ export const areDayPropsEqual = (prevProps: DayProps, nextProps: DayProps) => { prevProps.disableMargin === nextProps.disableMargin && prevProps.showDaysOutsideCurrentMonth === nextProps.showDaysOutsideCurrentMonth && prevProps.disableHighlightToday === nextProps.disableHighlightToday && - prevProps.className === nextProps.className + prevProps.className === nextProps.className && + prevProps.onDayFocus === nextProps.onDayFocus && + prevProps.onDaySelect === nextProps.onDaySelect ); }; From 30c88f358125952ca210ec8ddbcfd90c7b480888 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 30 Mar 2020 20:31:37 +0300 Subject: [PATCH 40/72] Implement mobile version of DateRangePicker --- .../BasicDateRangePicker.example.jsx | 4 +- docs/prop-types.json | 6 +- lib/src/DatePicker/DatePickerToolbar.tsx | 4 +- lib/src/DateRangePicker/DateRangePicker.tsx | 4 + .../DateRangePicker/DateRangePickerInput.tsx | 14 +++- .../DateRangePickerToolbar.tsx | 77 +++++++++++++++++++ .../DateRangePicker/DateRangePickerView.tsx | 54 +++++++++++-- ...ker.tsx => DateRangePickerViewDesktop.tsx} | 34 +++----- .../DateRangePickerViewMobile.tsx | 69 +++++++++++++++++ lib/src/DateRangePicker/RangeTypes.ts | 5 ++ lib/src/Picker/Picker.tsx | 13 ++-- lib/src/_helpers/date-utils.ts | 32 ++++++++ lib/src/_shared/KeyboardDateInput.tsx | 6 ++ lib/src/_shared/PureDateInput.tsx | 1 + lib/src/_shared/ToolbarButton.tsx | 6 +- lib/src/typings/overrides.ts | 2 +- lib/src/views/Calendar/CalendarHeader.tsx | 37 ++++----- lib/src/views/Calendar/CalendarView.tsx | 2 +- lib/src/wrappers/MobileWrapper.tsx | 2 +- 19 files changed, 298 insertions(+), 74 deletions(-) create mode 100644 lib/src/DateRangePicker/DateRangePickerToolbar.tsx rename lib/src/DateRangePicker/{DesktopDateRangePicker.tsx => DateRangePickerViewDesktop.tsx} (80%) create mode 100644 lib/src/DateRangePicker/DateRangePickerViewMobile.tsx diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index e261f09ea..4f74ad481 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -1,10 +1,10 @@ import React, { useState } from 'react'; -import { DateRangePicker } from '@material-ui/pickers'; +import { MobileDateRangePicker } from '@material-ui/pickers'; function BasicDateRangePicker() { const [selectedDate, handleDateChange] = useState([new Date(), null]); - return handleDateChange(date)} />; + return handleDateChange(date)} />; } export default BasicDateRangePicker; diff --git a/docs/prop-types.json b/docs/prop-types.json index 20e89edc4..77c2c1733 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -430,7 +430,7 @@ }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "ComponentClass, any> | FunctionComponent>" } }, "toolbarTitle": { @@ -1327,7 +1327,7 @@ }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "ComponentClass, any> | FunctionComponent>" } }, "toolbarTitle": { @@ -2062,7 +2062,7 @@ }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "ComponentClass, any> | FunctionComponent>" } }, "toolbarTitle": { diff --git a/lib/src/DatePicker/DatePickerToolbar.tsx b/lib/src/DatePicker/DatePickerToolbar.tsx index 0b21afdbc..b442f6bde 100644 --- a/lib/src/DatePicker/DatePickerToolbar.tsx +++ b/lib/src/DatePicker/DatePickerToolbar.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import clsx from 'clsx'; -import { makeStyles } from '@material-ui/core/styles'; -import Typography from '@material-ui/core/Typography'; import PickerToolbar from '../_shared/PickerToolbar'; +import Typography from '@material-ui/core/Typography'; import { DatePickerView } from './DatePicker'; import { useUtils } from '../_shared/hooks/useUtils'; +import { makeStyles } from '@material-ui/core/styles'; import { ToolbarComponentProps } from '../Picker/Picker'; import { isYearAndMonthViews, isYearOnlyView } from '../_helpers/date-utils'; diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 92c6ac85a..063643543 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; +import { MobileWrapper } from '../wrappers/MobileWrapper'; import { DateRangeInputProps } from './DateRangePickerInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; @@ -76,6 +77,7 @@ export function makeRangePicker(Wrapper: TWrapper) wrapperProps={wrapperProps} inputProps={{ ...inputProps, + readOnly: true, currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, }} @@ -113,3 +115,5 @@ export function makeRangePicker(Wrapper: TWrapper) export type DateRange = DateRangeType; export const DateRangePicker = makeRangePicker(DesktopPopperWrapper); + +export const MobileDateRangePicker = makeRangePicker(MobileWrapper); diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 73bae287d..e59cde20d 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -14,6 +14,10 @@ export const useStyles = makeStyles( rangeInputsContainer: { display: 'flex', alignItems: 'center', + // ? TBD + [theme.breakpoints.down('xs')]: { + flexDirection: 'column', + }, }, toLabelDelimiter: { margin: '0 16px', @@ -33,6 +37,7 @@ export interface ExportedDateRangePickerInputProps { export interface DateRangeInputProps extends ExportedDateRangePickerInputProps, DateInputProps { + readOnly: boolean; currentlySelectingRangeEnd: 'start' | 'end'; setCurrentlySelectingRangeEnd: (newSelectionEnd: 'start' | 'end') => void; } @@ -53,6 +58,7 @@ export const DateRangePickerInput: React.FC = ({ setCurrentlySelectingRangeEnd, openPicker, onFocus, + readOnly, ...other }) => { const utils = useUtils() @@ -106,7 +112,9 @@ export const DateRangePickerInput: React.FC = ({ onChange={handleStartChange} hideOpenPickerButton openPicker={() => {}} - onFocus={createDelegatedEventHandler(openRangeStartSelection, onFocus)} + readOnly={readOnly} + onClick={readOnly ? createDelegatedEventHandler(openRangeStartSelection, onClick) : undefined} + onFocus={!readOnly ? createDelegatedEventHandler(openRangeStartSelection, onFocus) : undefined} className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'start' })} /> @@ -121,7 +129,9 @@ export const DateRangePickerInput: React.FC = ({ onChange={handleEndChange} hideOpenPickerButton openPicker={() => {}} - onFocus={createDelegatedEventHandler(openRangeEndSelection, onFocus)} + readOnly={readOnly} + onClick={readOnly ? createDelegatedEventHandler(openRangeEndSelection, onClick) : undefined} + onFocus={!readOnly ? createDelegatedEventHandler(openRangeEndSelection, onFocus) : undefined} className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'end' })} />
diff --git a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx new file mode 100644 index 000000000..c3a0ef26e --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; +import PickerToolbar from '../_shared/PickerToolbar'; +import Typography from '@material-ui/core/Typography'; +import { DateRange, CurrentlySelectingRangeEndProps } from './RangeTypes'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { makeStyles } from '@material-ui/core/styles'; +import { ToolbarComponentProps } from '../Picker/Picker'; +import { ToolbarButton } from '../_shared/ToolbarButton'; + +export const useStyles = makeStyles( + { + penIcon: { + position: 'relative', + top: 4, + }, + dateTextContainer: { + display: 'flex', + }, + }, + { name: 'MuiPickersDatePickerRoot' } +); + +interface DateRangePickerToolbarProps + extends CurrentlySelectingRangeEndProps, + Pick< + ToolbarComponentProps, + 'isMobileKeyboardViewOpen' | 'toggleMobileKeyboardView' | 'toolbarTitle' | 'toolbarFormat' + > { + date: DateRange; + currentlySelectingRangeEnd: 'start' | 'end'; + setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; +} + +export const DateRangePickerToolbar: React.FC = ({ + date: [start, end], + toolbarFormat, + isMobileKeyboardViewOpen, + toggleMobileKeyboardView, + currentlySelectingRangeEnd, + setCurrentlySelectingRangeEnd, + toolbarTitle = 'SELECT DATE RANGE', +}) => { + const utils = useUtils(); + const classes = useStyles(); + + const startText = start + ? utils.formatByString(start, toolbarFormat || utils.formats.shortDate) + : 'Start'; + + const endText = end ? utils.formatByString(end, toolbarFormat || utils.formats.shortDate) : 'End'; + + return ( + +
+ setCurrentlySelectingRangeEnd('start')} + /> +  {'–'}  + setCurrentlySelectingRangeEnd('end')} + /> +
+
+ ); +}; diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 25d763821..1345d936a 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -1,32 +1,33 @@ import * as React from 'react'; -import { RangeInput, DateRange } from './RangeTypes'; import { MaterialUiPickersDate } from '../typings/date'; import { calculateRangeChange } from './date-range-manager'; import { useUtils, useNow } from '../_shared/hooks/useUtils'; import { SharedPickerProps } from '../Picker/SharedPickerProps'; +import { DateRangePickerToolbar } from './DateRangePickerToolbar'; import { useParsedDate } from '../_shared/hooks/date-helpers-hooks'; import { useCalendarState } from '../views/Calendar/useCalendarState'; +import { DateRangePickerViewMobile } from './DateRangePickerViewMobile'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; +import { RangeInput, DateRange, CurrentlySelectingRangeEndProps } from './RangeTypes'; import { ExportedCalendarViewProps, defaultReduceAnimations } from '../views/Calendar/CalendarView'; import { - DesktopDateRangePicker, + DateRangePickerViewDesktop, ExportedDesktopDateRangeCalendarProps, -} from './DesktopDateRangePicker'; +} from './DateRangePickerViewDesktop'; type BaseCalendarPropsToReuse = Omit; export interface DateRangePickerViewProps extends BaseCalendarPropsToReuse, ExportedDesktopDateRangeCalendarProps, - SharedPickerProps { + SharedPickerProps, + CurrentlySelectingRangeEndProps { /** * if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date * @default false */ disableAutoMonthSwitching?: boolean; open: boolean; - currentlySelectingRangeEnd: 'start' | 'end'; - setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; } export const DateRangePickerView: React.FC = ({ @@ -45,6 +46,8 @@ export const DateRangePickerView: React.FC = ({ reduceAnimations = defaultReduceAnimations, setCurrentlySelectingRangeEnd, shouldDisableDate, + toggleMobileKeyboardView, + isMobileKeyboardViewOpen, ...other }) => { const now = useNow(); @@ -73,7 +76,7 @@ export const DateRangePickerView: React.FC = ({ }); const scrollToDayIfNeeded = (day: MaterialUiPickersDate) => { - const displayingMonthRange = calendars - 1; + const displayingMonthRange = wrapperVariant === 'mobile' ? 0 : calendars - 1; const currentMonthNumber = utils.getMonth(calendarState.currentMonth); const requestedMonthNumber = utils.getMonth(day); @@ -128,10 +131,14 @@ export const DateRangePickerView: React.FC = ({ ] ); + if (isMobileKeyboardViewOpen) { + return <>"LOL KEK CHEBUREK"; + } + switch (wrapperVariant) { case 'desktop': { return ( - = ({ ); } + case 'mobile': { + return ( + <> + + + + + ); + } + default: { throw new Error('Only desktop wrapper supported for DateRangePicker'); } diff --git a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx similarity index 80% rename from lib/src/DateRangePicker/DesktopDateRangePicker.tsx rename to lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx index dc568be19..b27f4387f 100644 --- a/lib/src/DateRangePicker/DesktopDateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx @@ -6,6 +6,7 @@ import { makeStyles } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; import { calculateRangePreview } from './date-range-manager'; import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; +import { isWithinRange, isStartOfRange, isEndOfRange } from '../_helpers/date-utils'; import { ArrowSwitcher, ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; import { usePreviousMonthDisabled, @@ -50,7 +51,7 @@ export const useStyles = makeStyles( { name: 'MuiPickersDesktopDateRangeCalendar' } ); -export const DesktopDateRangePicker: React.FC = ({ +export const DateRangePickerViewDesktop: React.FC = ({ date, calendars = 2, changeMonth, @@ -91,24 +92,8 @@ export const DesktopDateRangePicker: React.FC = ( [onChange] ); - const isRangeValid = (range: DateRange | null): range is DateRange => { - return Boolean(range && utils.isBefore(range[0], range[1])); - }; - - const isWithinRange = (day: MaterialUiPickersDate, range: DateRange | null) => { - return isRangeValid(range) && utils.isWithinRange(day, range); - }; - - const isStartOfRange = (day: MaterialUiPickersDate, range: DateRange | null) => { - return Boolean(range && utils.isSameDay(day, range[0])); - }; - - const isEndOfRange = (day: MaterialUiPickersDate, range: DateRange | null) => { - return Boolean(range && utils.isSameDay(day, range[1])); - }; - const handlePreviewDayChange = (newPreviewRequest: MaterialUiPickersDate) => { - if (!isWithinRange(newPreviewRequest, date)) { + if (!isWithinRange(utils, newPreviewRequest, date)) { setRangePreviewDay(newPreviewRequest); } else { setRangePreviewDay(null); @@ -155,7 +140,6 @@ export const DesktopDateRangePicker: React.FC = ( /> = ( TransitionProps={CalendarTransitionProps} renderDay={(day, _, DayProps) => ( handlePreviewDayChange(day)} {...DayProps} /> diff --git a/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx b/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx new file mode 100644 index 000000000..6a434a317 --- /dev/null +++ b/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx @@ -0,0 +1,69 @@ +import * as React from 'react'; +import CalendarHeader from '../views/Calendar/CalendarHeader'; +import { DateRange } from './RangeTypes'; +import { DateRangeDay } from './DateRangePickerDay'; +import { useUtils } from '../_shared/hooks/useUtils'; +import { MaterialUiPickersDate } from '../typings/date'; +import { Calendar, CalendarProps } from '../views/Calendar/Calendar'; +import { ExportedArrowSwitcherProps } from '../_shared/ArrowSwitcher'; +import { isWithinRange, isStartOfRange, isEndOfRange } from '../_helpers/date-utils'; + +export interface ExportedMobileDateRangeCalendarProps {} + +interface DesktopDateRangeCalendarProps + extends ExportedMobileDateRangeCalendarProps, + CalendarProps, + ExportedArrowSwitcherProps { + date: DateRange; + changeMonth: (date: MaterialUiPickersDate) => void; +} + +export const DateRangePickerViewMobile: React.FC = ({ + date, + changeMonth, + leftArrowButtonProps, + leftArrowButtonText, + leftArrowIcon, + rightArrowButtonProps, + rightArrowButtonText, + rightArrowIcon, + onChange, + ...CalendarProps +}) => { + const utils = useUtils(); + + return ( + <> + ({})} + onMonthChange={changeMonth} + leftArrowButtonProps={leftArrowButtonProps} + leftArrowButtonText={leftArrowButtonText} + leftArrowIcon={leftArrowIcon} + rightArrowButtonProps={rightArrowButtonProps} + rightArrowButtonText={rightArrowButtonText} + rightArrowIcon={rightArrowIcon} + {...CalendarProps} + /> + + ( + + )} + /> + + ); +}; diff --git a/lib/src/DateRangePicker/RangeTypes.ts b/lib/src/DateRangePicker/RangeTypes.ts index 0379a21d3..5a39025e3 100644 --- a/lib/src/DateRangePicker/RangeTypes.ts +++ b/lib/src/DateRangePicker/RangeTypes.ts @@ -3,3 +3,8 @@ import { MaterialUiPickersDate } from '../typings/date'; export type RangeInput = [ParsableDate, ParsableDate]; export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; + +export interface CurrentlySelectingRangeEndProps { + currentlySelectingRangeEnd: 'start' | 'end'; + setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; +} diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index 73550ea7d..85c92a9f3 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -18,13 +18,14 @@ import { CalendarView, ExportedCalendarViewProps } from '../views/Calendar/Calen type CalendarAndClockProps = ExportedCalendarViewProps & ExportedClockViewProps; export type ToolbarComponentProps< - T extends AnyPickerView = AnyPickerView + TDate = MaterialUiPickersDate, + TView extends AnyPickerView = AnyPickerView > = CalendarAndClockProps & { - views: T[]; - openView: T; - date: MaterialUiPickersDate; - setOpenView: (view: T) => void; - onChange: (date: MaterialUiPickersDate, isFinish?: boolean) => void; + views: TView[]; + openView: TView; + date: TDate; + setOpenView: (view: TView) => void; + onChange: (date: TDate, isFinish?: boolean) => void; toolbarTitle?: React.ReactNode; toolbarFormat?: string; // TODO move out, cause it is DateTimePickerOnly diff --git a/lib/src/_helpers/date-utils.ts b/lib/src/_helpers/date-utils.ts index 0ce13a08c..2d7a725eb 100644 --- a/lib/src/_helpers/date-utils.ts +++ b/lib/src/_helpers/date-utils.ts @@ -3,6 +3,7 @@ import { IUtils } from '@date-io/core/IUtils'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; import { DatePickerView } from '../DatePicker/DatePicker'; +import { DateRange } from '../DateRangePicker/RangeTypes'; import { MuiPickersAdapter } from '../_shared/hooks/useUtils'; interface FindClosestDateParams { @@ -106,3 +107,34 @@ export function parsePickerInputValue( return parsedValue && utils.isValid(parsedValue) ? parsedValue : now; } + +export const isRangeValid = ( + utils: MuiPickersAdapter, + range: DateRange | null +): range is DateRange => { + return Boolean(range && utils.isBefore(range[0], range[1])); +}; + +export const isWithinRange = ( + utils: MuiPickersAdapter, + day: MaterialUiPickersDate, + range: DateRange | null +) => { + return isRangeValid(utils, range) && utils.isWithinRange(day, range); +}; + +export const isStartOfRange = ( + utils: MuiPickersAdapter, + day: MaterialUiPickersDate, + range: DateRange | null +) => { + return Boolean(range && utils.isSameDay(day, range[0])); +}; + +export const isEndOfRange = ( + utils: MuiPickersAdapter, + day: MaterialUiPickersDate, + range: DateRange | null +) => { + return Boolean(range && utils.isSameDay(day, range[1])); +}; diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index d5dd81c7e..779d920ab 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -41,6 +41,8 @@ export const KeyboardDateInput: React.FC = ({ forwardedRef, containerRef, open, + readOnly, + inputProps: inputPropsPassed, getOpenDialogAriaText = getTextFieldAriaText, ...other }) => { @@ -105,6 +107,10 @@ export const KeyboardDateInput: React.FC = ({ helperText: validationError, 'data-mui-test': 'keyboard-date-input', ...other, + inputProps: { + ...inputPropsPassed, + readOnly, + }, InputProps: { ...InputProps, [`${adornmentPosition}Adornment`]: hideOpenPickerButton ? ( diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 3e3d5dd72..3cef8f11b 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -16,6 +16,7 @@ export interface DateInputProps void; openPicker: () => void; + readOnly?: boolean; validationError?: React.ReactNode; /** Override input component */ TextFieldComponent?: React.ComponentType; diff --git a/lib/src/_shared/ToolbarButton.tsx b/lib/src/_shared/ToolbarButton.tsx index 179a267a2..01d251c63 100644 --- a/lib/src/_shared/ToolbarButton.tsx +++ b/lib/src/_shared/ToolbarButton.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import clsx from 'clsx'; +import ToolbarText from './ToolbarText'; import Button, { ButtonProps } from '@material-ui/core/Button'; +import { ExtendMui } from '../typings/helpers'; import { makeStyles } from '@material-ui/core/styles'; import { TypographyProps } from '@material-ui/core/Typography'; -import ToolbarText from './ToolbarText'; -import { ExtendMui } from '../typings/helpers'; export interface ToolbarButtonProps extends ExtendMui { variant: TypographyProps['variant']; @@ -25,7 +25,7 @@ export const useStyles = makeStyles( { name: 'MuiPickersToolbarButton' } ); -const ToolbarButton: React.FunctionComponent = ({ +export const ToolbarButton: React.FunctionComponent = ({ className = null, label, selected, diff --git a/lib/src/typings/overrides.ts b/lib/src/typings/overrides.ts index f10d3eb84..9fc1b83c1 100644 --- a/lib/src/typings/overrides.ts +++ b/lib/src/typings/overrides.ts @@ -63,7 +63,7 @@ export interface MuiPickersOverrides { MuiBasePickerStyles?: Classes; // consider using inline import type notation MuiPickersDesktopDateRangeCalendar?: Classes< - typeof import('../DateRangePicker/DesktopDateRangePicker').useStyles + typeof import('../DateRangePicker/DateRangePickerViewDesktop').useStyles >; MuiPickersArrowSwitcher?: Classes; MuiPickersDateRangePickerInput?: Classes< diff --git a/lib/src/views/Calendar/CalendarHeader.tsx b/lib/src/views/Calendar/CalendarHeader.tsx index c9b8171df..030a04c3c 100644 --- a/lib/src/views/Calendar/CalendarHeader.tsx +++ b/lib/src/views/Calendar/CalendarHeader.tsx @@ -23,8 +23,7 @@ export interface CalendarHeaderProps Pick { view: DatePickerView; views: DatePickerView[]; - month: MaterialUiPickersDate; - + currentMonth: MaterialUiPickersDate; /** Get aria-label text for switching between views button */ getViewSwitchingButtonText?: (currentView: DatePickerView) => string; reduceAnimations: boolean; @@ -84,7 +83,7 @@ function getSwitchingViewAriaText(view: DatePickerView) { export const CalendarHeader: React.SFC = ({ view, views, - month, + currentMonth: month, changeView, minDate, maxDate, @@ -123,10 +122,6 @@ export const CalendarHeader: React.SFC = ({ } }; - if (views.length === 1) { - return null; - } - return ( <>
@@ -157,19 +152,21 @@ export const CalendarHeader: React.SFC = ({ /> - - - + {views.length > 1 && ( + + + + )}
diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index 3a6c855e7..ab56d18ff 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -132,7 +132,7 @@ export const CalendarView: React.FC = ({ handleChangeMonth({ newMonth, direction })} minDate={minDate} diff --git a/lib/src/wrappers/MobileWrapper.tsx b/lib/src/wrappers/MobileWrapper.tsx index 1b98efba2..09c7b2bb7 100644 --- a/lib/src/wrappers/MobileWrapper.tsx +++ b/lib/src/wrappers/MobileWrapper.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; -import { DialogProps as MuiDialogProps } from '@material-ui/core/Dialog'; import ModalDialog from '../_shared/ModalDialog'; import { WrapperProps } from './Wrapper'; import { PureDateInput } from '../_shared/PureDateInput'; import { InnerDesktopWrapperProps } from './DesktopWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; +import { DialogProps as MuiDialogProps } from '@material-ui/core/Dialog'; export interface InnerMobileWrapperProps { /** From c1b0b7ba84bad92efbbe8a7ecc4094a7fe0624b4 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 30 Mar 2020 22:29:52 +0300 Subject: [PATCH 41/72] Better displaying in mobile mode --- docs/prop-types.json | 12 +-- lib/src/DateRangePicker/DateRangePicker.tsx | 15 ++- .../DateRangePicker/DateRangePickerInput.tsx | 63 ++++++----- .../DateRangePickerToolbar.tsx | 2 +- .../DateRangePicker/DateRangePickerView.tsx | 100 ++++++++++-------- lib/src/Picker/Picker.tsx | 3 +- lib/src/_shared/KeyboardDateInput.tsx | 2 +- lib/src/_shared/PureDateInput.tsx | 4 +- lib/src/views/MobileKeyboardInputView.tsx | 8 +- lib/src/wrappers/MobileWrapper.tsx | 2 +- 10 files changed, 123 insertions(+), 88 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index 77c2c1733..acd2f31e6 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -884,12 +884,12 @@ "name": "(str: string) => string" } }, - "hideOpenPickerButton": { + "disableOpenPicker": { "defaultValue": { "value": "false" }, "description": "Do not render open picker button (renders only text field with validation)", - "name": "hideOpenPickerButton", + "name": "disableOpenPicker", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", "name": "DateInputProps" @@ -1509,12 +1509,12 @@ "name": "(str: string) => string" } }, - "hideOpenPickerButton": { + "disableOpenPicker": { "defaultValue": { "value": "false" }, "description": "Do not render open picker button (renders only text field with validation)", - "name": "hideOpenPickerButton", + "name": "disableOpenPicker", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", "name": "DateInputProps" @@ -2503,12 +2503,12 @@ "name": "(str: string) => string" } }, - "hideOpenPickerButton": { + "disableOpenPicker": { "defaultValue": { "value": "false" }, "description": "Do not render open picker button (renders only text field with validation)", - "name": "hideOpenPickerButton", + "name": "disableOpenPicker", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", "name": "DateInputProps" diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 063643543..b6cbe0714 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -47,7 +47,7 @@ export function makeRangePicker(Wrapper: TWrapper) disableHighlightToday, reduceAnimations, inputFormat: passedInputFormat, - ...other + ...restPropsForTextField }: DateRangePickerViewProps & ExportedDateRangePickerInputProps & AllSharedPickerProps & @@ -58,7 +58,7 @@ export function makeRangePicker(Wrapper: TWrapper) >('start'); const pickerStateProps = { - ...other, + ...restPropsForTextField, inputFormat: passedInputFormat || utils.formats.keyboardDate, }; @@ -77,15 +77,19 @@ export function makeRangePicker(Wrapper: TWrapper) wrapperProps={wrapperProps} inputProps={{ ...inputProps, - readOnly: true, currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, }} - {...other} + {...restPropsForTextField} > (Wrapper: TWrapper) RangePickerWithStateAndWrapper.defaultProps = { mask: '__/__/____', + variant: 'outlined', }; return RangePickerWithStateAndWrapper; diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index e59cde20d..e388682d1 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -7,6 +7,7 @@ import { useUtils } from '../_shared/hooks/useUtils'; import { makeStyles } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; +import { CurrentlySelectingRangeEndProps } from './RangeTypes'; import { createDelegatedEventHandler } from '../_helpers/utils'; export const useStyles = makeStyles( @@ -21,6 +22,9 @@ export const useStyles = makeStyles( }, toLabelDelimiter: { margin: '0 16px', + [theme.breakpoints.down('xs')]: { + margin: '8px 0', + }, }, highlighted: { backgroundColor: theme.palette.divider, @@ -36,13 +40,9 @@ export interface ExportedDateRangePickerInputProps { export interface DateRangeInputProps extends ExportedDateRangePickerInputProps, - DateInputProps { - readOnly: boolean; - currentlySelectingRangeEnd: 'start' | 'end'; - setCurrentlySelectingRangeEnd: (newSelectionEnd: 'start' | 'end') => void; -} + CurrentlySelectingRangeEndProps, + DateInputProps {} -// prettier-ignore export const DateRangePickerInput: React.FC = ({ toText = 'to', rawValue, @@ -59,25 +59,26 @@ export const DateRangePickerInput: React.FC = ({ openPicker, onFocus, readOnly, + disableOpenPicker, ...other }) => { - const utils = useUtils() + const utils = useUtils(); const classes = useStyles(); - const startRef = React.useRef(null) - const endRef = React.useRef(null) + const startRef = React.useRef(null); + const endRef = React.useRef(null); const [start, end] = parsedDateValue ?? [null, null]; React.useEffect(() => { if (!open) { - return + return; } if (currentlySelectingRangeEnd === 'start') { - startRef.current?.focus() - } else { - endRef.current?.focus() + startRef.current?.focus(); + } else if (currentlySelectingRangeEnd === 'end') { + endRef.current?.focus(); } - }, [currentlySelectingRangeEnd, open]) + }, [currentlySelectingRangeEnd, open]); const handleStartChange = (date: MaterialUiPickersDate, inputString?: string) => { if (date === null || utils.isValid(date)) { @@ -86,20 +87,24 @@ export const DateRangePickerInput: React.FC = ({ }; const handleEndChange = (date: MaterialUiPickersDate, inputString?: string) => { - if (utils.isValid(date)) { + if (date === null || utils.isValid(date)) { onChange([start, date], inputString); } }; const openRangeStartSelection = () => { - setCurrentlySelectingRangeEnd('start') - openPicker() - } + if (!disableOpenPicker && setCurrentlySelectingRangeEnd) { + setCurrentlySelectingRangeEnd('start'); + openPicker(); + } + }; const openRangeEndSelection = () => { - setCurrentlySelectingRangeEnd('end') - openPicker() - } + if (!disableOpenPicker && setCurrentlySelectingRangeEnd) { + setCurrentlySelectingRangeEnd('end'); + openPicker(); + } + }; return (
@@ -110,11 +115,15 @@ export const DateRangePickerInput: React.FC = ({ rawValue={start} parsedDateValue={start} onChange={handleStartChange} - hideOpenPickerButton + disableOpenPicker openPicker={() => {}} readOnly={readOnly} - onClick={readOnly ? createDelegatedEventHandler(openRangeStartSelection, onClick) : undefined} - onFocus={!readOnly ? createDelegatedEventHandler(openRangeStartSelection, onFocus) : undefined} + onClick={ + readOnly ? createDelegatedEventHandler(openRangeStartSelection, onClick) : undefined + } + onFocus={ + !readOnly ? createDelegatedEventHandler(openRangeStartSelection, onFocus) : undefined + } className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'start' })} /> @@ -127,11 +136,13 @@ export const DateRangePickerInput: React.FC = ({ rawValue={end} parsedDateValue={end} onChange={handleEndChange} - hideOpenPickerButton + disableOpenPicker openPicker={() => {}} readOnly={readOnly} onClick={readOnly ? createDelegatedEventHandler(openRangeEndSelection, onClick) : undefined} - onFocus={!readOnly ? createDelegatedEventHandler(openRangeEndSelection, onFocus) : undefined} + onFocus={ + !readOnly ? createDelegatedEventHandler(openRangeEndSelection, onFocus) : undefined + } className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'end' })} />
diff --git a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx index c3a0ef26e..76963a61c 100644 --- a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx +++ b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import PickerToolbar from '../_shared/PickerToolbar'; import Typography from '@material-ui/core/Typography'; -import { DateRange, CurrentlySelectingRangeEndProps } from './RangeTypes'; import { useUtils } from '../_shared/hooks/useUtils'; import { makeStyles } from '@material-ui/core/styles'; import { ToolbarComponentProps } from '../Picker/Picker'; import { ToolbarButton } from '../_shared/ToolbarButton'; +import { DateRange, CurrentlySelectingRangeEndProps } from './RangeTypes'; export const useStyles = makeStyles( { diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 1345d936a..17983facd 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -14,6 +14,9 @@ import { DateRangePickerViewDesktop, ExportedDesktopDateRangeCalendarProps, } from './DateRangePickerViewDesktop'; +import { BasePickerProps } from '../typings/BasePicker'; +import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; +import { DateRangePickerInput } from './DateRangePickerInput'; type BaseCalendarPropsToReuse = Omit; @@ -21,7 +24,8 @@ export interface DateRangePickerViewProps extends BaseCalendarPropsToReuse, ExportedDesktopDateRangeCalendarProps, SharedPickerProps, - CurrentlySelectingRangeEndProps { + CurrentlySelectingRangeEndProps, + Omit { /** * if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date * @default false @@ -48,6 +52,8 @@ export const DateRangePickerView: React.FC = ({ shouldDisableDate, toggleMobileKeyboardView, isMobileKeyboardViewOpen, + showToolbar, + DateInputProps, ...other }) => { const now = useNow(); @@ -75,6 +81,8 @@ export const DateRangePickerView: React.FC = ({ disableSwitchToMonthOnDayFocus: true, }); + const toShowToolbar = showToolbar ?? wrapperVariant !== 'desktop'; + const scrollToDayIfNeeded = (day: MaterialUiPickersDate) => { const displayingMonthRange = wrapperVariant === 'mobile' ? 0 : calendars - 1; const currentMonthNumber = utils.getMonth(calendarState.currentMonth); @@ -131,45 +139,33 @@ export const DateRangePickerView: React.FC = ({ ] ); - if (isMobileKeyboardViewOpen) { - return <>"LOL KEK CHEBUREK"; - } - - switch (wrapperVariant) { - case 'desktop': { - return ( - - ); - } - - case 'mobile': { - return ( - <> - { + switch (wrapperVariant) { + case 'desktop': { + return ( + + ); + } + case 'mobile': { + return ( = ({ {...calendarState} {...other} /> - - ); - } + ); + } - default: { - throw new Error('Only desktop wrapper supported for DateRangePicker'); + default: { + throw new Error('Only desktop wrapper supported for DateRangePicker'); + } } - } + }; + + return ( + <> + {toShowToolbar && ( + + )} + + {isMobileKeyboardViewOpen ? ( + + ) : ( + renderView() + )} + + ); }; diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index 85c92a9f3..352720123 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import clsx from 'clsx'; +import KeyboardDateInput from '../_shared/KeyboardDateInput'; import { useViews } from '../_shared/hooks/useViews'; import { makeStyles } from '@material-ui/core/styles'; import { DateTimePickerView } from '../DateTimePicker'; @@ -146,7 +147,7 @@ export function Picker({ })} > {isMobileKeyboardViewOpen ? ( - + ) : ( <> {(openView === 'year' || openView === 'month' || openView === 'date') && ( diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index 779d920ab..dae2ae885 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -33,7 +33,7 @@ export const KeyboardDateInput: React.FC = ({ keyboardIcon = , variant, emptyInputText: emptyLabel, - hideOpenPickerButton, + disableOpenPicker: hideOpenPickerButton, ignoreInvalidInputs, onFocus, onBlur, diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 3cef8f11b..f7f14fb13 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -57,7 +57,7 @@ export interface DateInputProps = ({ variant, emptyInputText: emptyLabel, keyboardIcon, - hideOpenPickerButton, + disableOpenPicker: hideOpenPickerButton, ignoreInvalidInputs, KeyboardButtonProps, disableMaskedInput, diff --git a/lib/src/views/MobileKeyboardInputView.tsx b/lib/src/views/MobileKeyboardInputView.tsx index 00877533e..eb1a0293e 100644 --- a/lib/src/views/MobileKeyboardInputView.tsx +++ b/lib/src/views/MobileKeyboardInputView.tsx @@ -1,10 +1,11 @@ import * as React from 'react'; -import KeyboardDateInput from '../_shared/KeyboardDateInput'; import { makeStyles } from '@material-ui/core/styles'; import { DateInputProps } from '../_shared/PureDateInput'; import { InnerMobileWrapperProps } from '../wrappers/MobileWrapper'; -interface MobileKeyboardInputViewProps extends DateInputProps, Partial {} +interface MobileKeyboardInputViewProps extends DateInputProps, Partial { + DateInputComponent: React.FC; +} const useStyles = makeStyles(() => ({ mobileKeyboardView: { @@ -16,12 +17,13 @@ export const MobileKeyboardInputView: React.FC = ( clearLabel, DialogProps, clearable, + DateInputComponent, ...other }) => { const classes = useStyles(); return (
- +
); }; diff --git a/lib/src/wrappers/MobileWrapper.tsx b/lib/src/wrappers/MobileWrapper.tsx index 09c7b2bb7..d8f477377 100644 --- a/lib/src/wrappers/MobileWrapper.tsx +++ b/lib/src/wrappers/MobileWrapper.tsx @@ -76,7 +76,7 @@ export const MobileWrapper: React.FC = ({ }) => { return ( - + Date: Tue, 31 Mar 2020 11:01:09 +0300 Subject: [PATCH 42/72] Make possible to switch view by clicking on month and year header --- lib/src/views/Calendar/CalendarHeader.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/views/Calendar/CalendarHeader.tsx b/lib/src/views/Calendar/CalendarHeader.tsx index 030a04c3c..ab9c1302a 100644 --- a/lib/src/views/Calendar/CalendarHeader.tsx +++ b/lib/src/views/Calendar/CalendarHeader.tsx @@ -66,6 +66,7 @@ export const useStyles = makeStyles( display: 'flex', maxHeight: 30, overflow: 'hidden', + cursor: 'pointer', }, monthText: { marginRight: 4, @@ -125,7 +126,7 @@ export const CalendarHeader: React.SFC = ({ return ( <>
-
+
Date: Tue, 31 Mar 2020 14:52:55 +0300 Subject: [PATCH 43/72] Properly spread props to mobile keyboard input view --- .../BasicDateRangePicker.example.jsx | 6 +- lib/src/DateRangePicker/DateRangePicker.tsx | 4 + .../DateRangePicker/DateRangePickerInput.tsx | 8 +- .../DateRangePicker/DateRangePickerView.tsx | 78 ++++++++----------- lib/src/Picker/Picker.tsx | 9 ++- lib/src/Picker/makePickerWithState.tsx | 1 + lib/src/_shared/KeyboardDateInput.tsx | 1 + lib/src/_shared/ToolbarText.tsx | 3 +- lib/src/_shared/hooks/usePickerState.ts | 3 +- lib/src/constants/dimensions.ts | 2 +- lib/src/views/Calendar/Calendar.tsx | 2 +- lib/src/views/Calendar/YearSelection.tsx | 2 +- lib/src/views/MobileKeyboardInputView.tsx | 32 +------- 13 files changed, 65 insertions(+), 86 deletions(-) diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index 4f74ad481..1d1fd0f02 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -1,10 +1,10 @@ import React, { useState } from 'react'; -import { MobileDateRangePicker } from '@material-ui/pickers'; +import { DateRangePicker } from '@material-ui/pickers'; function BasicDateRangePicker() { - const [selectedDate, handleDateChange] = useState([new Date(), null]); + const [selectedDate, handleDateChange] = useState([null, null]); - return handleDateChange(date)} />; + return handleDateChange(date)} />; } export default BasicDateRangePicker; diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index b6cbe0714..ca57b05bd 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -46,6 +46,8 @@ export function makeRangePicker(Wrapper: TWrapper) onMonthChange, disableHighlightToday, reduceAnimations, + value, + onChange, inputFormat: passedInputFormat, ...restPropsForTextField }: DateRangePickerViewProps & @@ -59,6 +61,8 @@ export function makeRangePicker(Wrapper: TWrapper) const pickerStateProps = { ...restPropsForTextField, + value, + onChange, inputFormat: passedInputFormat || utils.formats.keyboardDate, }; diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index e388682d1..06840bcc4 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -93,15 +93,19 @@ export const DateRangePickerInput: React.FC = ({ }; const openRangeStartSelection = () => { - if (!disableOpenPicker && setCurrentlySelectingRangeEnd) { + if (setCurrentlySelectingRangeEnd) { setCurrentlySelectingRangeEnd('start'); + } + if (!disableOpenPicker) { openPicker(); } }; const openRangeEndSelection = () => { - if (!disableOpenPicker && setCurrentlySelectingRangeEnd) { + if (setCurrentlySelectingRangeEnd) { setCurrentlySelectingRangeEnd('end'); + } + if (!disableOpenPicker) { openPicker(); } }; diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 17983facd..3094d2b8a 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -1,22 +1,22 @@ import * as React from 'react'; import { MaterialUiPickersDate } from '../typings/date'; +import { BasePickerProps } from '../typings/BasePicker'; import { calculateRangeChange } from './date-range-manager'; import { useUtils, useNow } from '../_shared/hooks/useUtils'; +import { DateRangePickerInput } from './DateRangePickerInput'; import { SharedPickerProps } from '../Picker/SharedPickerProps'; import { DateRangePickerToolbar } from './DateRangePickerToolbar'; import { useParsedDate } from '../_shared/hooks/date-helpers-hooks'; import { useCalendarState } from '../views/Calendar/useCalendarState'; import { DateRangePickerViewMobile } from './DateRangePickerViewMobile'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; +import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; import { RangeInput, DateRange, CurrentlySelectingRangeEndProps } from './RangeTypes'; import { ExportedCalendarViewProps, defaultReduceAnimations } from '../views/Calendar/CalendarView'; import { DateRangePickerViewDesktop, ExportedDesktopDateRangeCalendarProps, } from './DateRangePickerViewDesktop'; -import { BasePickerProps } from '../typings/BasePicker'; -import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; -import { DateRangePickerInput } from './DateRangePickerInput'; type BaseCalendarPropsToReuse = Omit; @@ -140,53 +140,31 @@ export const DateRangePickerView: React.FC = ({ ); const renderView = () => { + const sharedCalendarProps = { + date, + isDateDisabled, + changeFocusedDay, + onChange: handleChange, + reduceAnimations, + disableHighlightToday, + onMonthSwitchingAnimationEnd, + changeMonth, + currentlySelectingRangeEnd, + disableFuture, + disablePast, + minDate, + maxDate, + ...calendarState, + ...other, + }; + switch (wrapperVariant) { case 'desktop': { - return ( - - ); - } - - case 'mobile': { - return ( - - ); + return ; } default: { - throw new Error('Only desktop wrapper supported for DateRangePicker'); + return ; } } }; @@ -204,7 +182,15 @@ export const DateRangePickerView: React.FC = ({ )} {isMobileKeyboardViewOpen ? ( - + + + ) : ( renderView() )} diff --git a/lib/src/Picker/Picker.tsx b/lib/src/Picker/Picker.tsx index 352720123..a4d9feacc 100644 --- a/lib/src/Picker/Picker.tsx +++ b/lib/src/Picker/Picker.tsx @@ -147,7 +147,14 @@ export function Picker({ })} > {isMobileKeyboardViewOpen ? ( - + + + ) : ( <> {(openView === 'year' || openView === 'month' || openView === 'date') && ( diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index f71878c77..6fb912d89 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -73,6 +73,7 @@ export function makePickerWithStateAndWrapper< shouldDisableDate, shouldDisableTime, timeIcon, + value, toolbarFormat, ToolbarComponent = DefaultToolbarComponent, views, diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index dae2ae885..e24d52ece 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -48,6 +48,7 @@ export const KeyboardDateInput: React.FC = ({ }) => { const utils = useUtils(); const [isFocused, setIsFocused] = React.useState(false); + const getInputValue = () => getDisplayDate(rawValue, utils, { inputFormat, diff --git a/lib/src/_shared/ToolbarText.tsx b/lib/src/_shared/ToolbarText.tsx index 51407e5c6..d6bf1032d 100644 --- a/lib/src/_shared/ToolbarText.tsx +++ b/lib/src/_shared/ToolbarText.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import clsx from 'clsx'; import Typography, { TypographyProps } from '@material-ui/core/Typography'; +import { ExtendMui } from '../typings/helpers'; import { makeStyles } from '@material-ui/core/styles'; import { fade } from '@material-ui/core/styles/colorManipulator'; -import { ExtendMui } from '../typings/helpers'; export interface ToolbarTextProps extends ExtendMui { selected?: boolean; label: string; @@ -18,6 +18,7 @@ export const useStyles = makeStyles( return { toolbarTxt: { + transition: theme.transitions.create('color'), color: fade(textColor, 0.54), }, toolbarBtnSelected: { diff --git a/lib/src/_shared/hooks/usePickerState.ts b/lib/src/_shared/hooks/usePickerState.ts index 5fde3749e..62316b9e3 100644 --- a/lib/src/_shared/hooks/usePickerState.ts +++ b/lib/src/_shared/hooks/usePickerState.ts @@ -64,7 +64,6 @@ export function usePickerState( const wrapperProps = useMemo( () => ({ open: isOpen, - format: inputFormat, onClear: () => acceptDate(valueManager.emptyValue, true), onAccept: () => acceptDate(pickerDate, true), onDismiss: () => setIsOpen(false), @@ -74,7 +73,7 @@ export function usePickerState( acceptDate(now as any, Boolean(autoOk)); }, }), - [acceptDate, autoOk, inputFormat, isOpen, now, pickerDate, setIsOpen, valueManager.emptyValue] + [acceptDate, autoOk, isOpen, now, pickerDate, setIsOpen, valueManager.emptyValue] ); const pickerProps = useMemo( diff --git a/lib/src/constants/dimensions.ts b/lib/src/constants/dimensions.ts index fd31a2dab..1df551de7 100644 --- a/lib/src/constants/dimensions.ts +++ b/lib/src/constants/dimensions.ts @@ -2,7 +2,7 @@ export const DIALOG_WIDTH = 320; export const DIALOG_WIDTH_WIDER = 325; -export const VIEW_HEIGHT = 360; +export const VIEW_HEIGHT = 358; export const DAY_SIZE = 36; diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 71eeb715d..8d280b2ac 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -71,7 +71,7 @@ export const useStyles = makeStyles(theme => ({ alignItems: 'center', }, week: { - margin: `${DAY_MARGIN * 2}px 0`, + margin: `${DAY_MARGIN}px 0`, display: 'flex', justifyContent: 'center', }, diff --git a/lib/src/views/Calendar/YearSelection.tsx b/lib/src/views/Calendar/YearSelection.tsx index e85cbf2ff..fee4504ee 100644 --- a/lib/src/views/Calendar/YearSelection.tsx +++ b/lib/src/views/Calendar/YearSelection.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import Year from './Year'; import { DateType } from '@date-io/type'; -import { makeStyles, useTheme } from '@material-ui/core/styles'; import { useUtils } from '../../_shared/hooks/useUtils'; import { MaterialUiPickersDate } from '../../typings/date'; +import { makeStyles, useTheme } from '@material-ui/core/styles'; import { WrapperVariantContext } from '../../wrappers/WrapperVariantContext'; import { useGlobalKeyDown, keycode as keys } from '../../_shared/hooks/useKeyDown'; diff --git a/lib/src/views/MobileKeyboardInputView.tsx b/lib/src/views/MobileKeyboardInputView.tsx index eb1a0293e..127c98ba0 100644 --- a/lib/src/views/MobileKeyboardInputView.tsx +++ b/lib/src/views/MobileKeyboardInputView.tsx @@ -1,29 +1,5 @@ -import * as React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import { DateInputProps } from '../_shared/PureDateInput'; -import { InnerMobileWrapperProps } from '../wrappers/MobileWrapper'; +import { styled } from '@material-ui/core/styles'; -interface MobileKeyboardInputViewProps extends DateInputProps, Partial { - DateInputComponent: React.FC; -} - -const useStyles = makeStyles(() => ({ - mobileKeyboardView: { - padding: '16px 24px', - }, -})); - -export const MobileKeyboardInputView: React.FC = ({ - clearLabel, - DialogProps, - clearable, - DateInputComponent, - ...other -}) => { - const classes = useStyles(); - return ( -
- -
- ); -}; +export const MobileKeyboardInputView = styled('div')({ + padding: '16px 24px', +}); From e287d3257327c5f68b0d5399b004090e02c3c727 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 31 Mar 2020 15:34:46 +0300 Subject: [PATCH 44/72] Fix ts erros and enable api generation --- docs/prop-types.json | 894 +++++++++++++++++- docs/scripts/docgen.js | 3 +- lib/.size-snapshot.json | 24 +- lib/src/DateRangePicker/DateRangePicker.tsx | 4 +- .../DateRangePicker/DateRangePickerInput.tsx | 1 - .../DateRangePicker/DateRangePickerView.tsx | 10 +- .../DateRangePickerViewDesktop.tsx | 4 + lib/src/_shared/PureDateInput.tsx | 1 + 8 files changed, 918 insertions(+), 23 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index acd2f31e6..abb51bf3f 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -389,7 +389,7 @@ "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, - "required": true, + "required": false, "type": { "name": "boolean" } @@ -1286,7 +1286,7 @@ "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, - "required": true, + "required": false, "type": { "name": "boolean" } @@ -2021,7 +2021,7 @@ "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, - "required": true, + "required": false, "type": { "name": "boolean" } @@ -2926,6 +2926,894 @@ } } }, + "DateRangePicker": { + "disableAutoMonthSwitching": { + "defaultValue": { + "value": "false" + }, + "description": "if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date", + "name": "disableAutoMonthSwitching", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePickerView.tsx", + "name": "ExportedDateRangePickerViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableHighlightToday": { + "defaultValue": { + "value": "false" + }, + "description": "Disable highlighting today date with a circle", + "name": "disableHighlightToday", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "showDaysOutsideCurrentMonth": { + "defaultValue": { + "value": "false" + }, + "description": "Display disabled dates outside the current month", + "name": "showDaysOutsideCurrentMonth", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "leftArrowIcon": { + "defaultValue": null, + "description": "Left arrow icon", + "name": "leftArrowIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "rightArrowIcon": { + "defaultValue": null, + "description": "Right arrow icon", + "name": "rightArrowIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "leftArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to left arrow button", + "name": "leftArrowButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rightArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to right arrow button", + "name": "rightArrowButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "leftArrowButtonText": { + "defaultValue": null, + "description": "Left arrow icon aria-label text", + "name": "leftArrowButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "rightArrowButtonText": { + "defaultValue": null, + "description": "Right arrow icon aria-label text", + "name": "rightArrowButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "getViewSwitchingButtonText": { + "defaultValue": null, + "description": "Get aria-label text for switching between views button", + "name": "getViewSwitchingButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", + "name": "CalendarHeaderProps" + }, + "required": false, + "type": { + "name": "(currentView: DatePickerView) => string" + } + }, + "minDate": { + "defaultValue": { + "value": "Date(1900-01-01)" + }, + "description": "Min selectable date", + "name": "minDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "maxDate": { + "defaultValue": { + "value": "Date(2100-01-01)" + }, + "description": "Max selectable date", + "name": "maxDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "disablePast": { + "defaultValue": { + "value": "false" + }, + "description": "Disable past dates", + "name": "disablePast", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableFuture": { + "defaultValue": { + "value": "false" + }, + "description": "Disable future dates", + "name": "disableFuture", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "reduceAnimations": { + "defaultValue": null, + "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", + "name": "reduceAnimations", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "onMonthChange": { + "defaultValue": null, + "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", + "name": "onMonthChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void | Promise" + } + }, + "shouldDisableDate": { + "defaultValue": null, + "description": "Disable specific date", + "name": "shouldDisableDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(day: DateIOType) => boolean" + } + }, + "renderDay": { + "defaultValue": null, + "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", + "name": "renderDay", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" + } + }, + "allowKeyboardControl": { + "defaultValue": { + "value": "currentWrapper !== 'static'" + }, + "description": "Enables keyboard listener for moving between days in calendar", + "name": "allowKeyboardControl", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "loadingIndicator": { + "defaultValue": null, + "description": "Custom loading indicator", + "name": "loadingIndicator", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "Element" + } + }, + "calendars": { + "defaultValue": { + "value": "2" + }, + "description": "How many calendars render on **desktop** DateRangePicker", + "name": "calendars", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx", + "name": "ExportedDesktopDateRangeCalendarProps" + }, + "required": false, + "type": { + "name": "2 | 1 | 3" + } + }, + "onError": { + "defaultValue": null, + "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", + "name": "onError", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "((error: ReactNode, value: DateIOType) => void) & ((error: ReactNode, value: RangeInput | DateRange) => void)" + } + }, + "onClose": { + "defaultValue": null, + "description": "On close callback", + "name": "onClose", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "open": { + "defaultValue": null, + "description": "Controlled picker open state", + "name": "open", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "inputFormat": { + "defaultValue": null, + "description": "Format string", + "name": "inputFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "disabled": { + "defaultValue": null, + "description": "Disable picker and text field", + "name": "disabled", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "readOnly": { + "defaultValue": null, + "description": "Make picker read only", + "name": "readOnly", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "onAccept": { + "defaultValue": null, + "description": "Callback fired when date is accepted", + "name": "onAccept", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "((date: DateIOType) => void) & ((date: DateRange) => void)" + } + }, + "autoOk": { + "defaultValue": { + "value": "false" + }, + "description": "Auto accept date on selection", + "name": "autoOk", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "defaultHighlight": { + "defaultValue": null, + "description": "Date that will be initially highlighted if null was passed", + "name": "defaultHighlight", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "onOpen": { + "defaultValue": null, + "description": "On open callback", + "name": "onOpen", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "showToolbar": { + "defaultValue": null, + "description": "Show toolbar even in desktop mode", + "name": "showToolbar", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "orientation": { + "defaultValue": null, + "description": "Force rendering in particular orientation", + "name": "orientation", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "\"portrait\" | \"landscape\"" + } + }, + "ToolbarComponent": { + "defaultValue": null, + "description": "Component that will replace default toolbar renderer", + "name": "ToolbarComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ComponentClass, any> | FunctionComponent>" + } + }, + "toolbarTitle": { + "defaultValue": { + "value": "\"SELECT DATE\"" + }, + "description": "Mobile picker title, displaying in the toolbar", + "name": "toolbarTitle", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar", + "name": "toolbarFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "value": { + "defaultValue": null, + "description": "Picker value", + "name": "value", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "RangeInput" + } + }, + "onChange": { + "defaultValue": null, + "description": "onChange callback", + "name": "onChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "(date: DateRange, keyboardInputValue?: string) => void" + } + }, + "mask": { + "defaultValue": null, + "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", + "name": "mask", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "TextFieldComponent": { + "defaultValue": null, + "description": "Override input component", + "name": "TextFieldComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "emptyInputText": { + "defaultValue": { + "value": "' '" + }, + "description": "Message displaying in read-only text field when null passed", + "name": "emptyInputText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "keyboardIcon": { + "defaultValue": null, + "description": "Icon displaying for open picker button", + "name": "keyboardIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maskChar": { + "defaultValue": { + "value": "'_'" + }, + "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", + "name": "maskChar", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "acceptRegex": { + "defaultValue": { + "value": "/\\dap/gi" + }, + "description": "Regular expression to detect \"accepted\" symbols", + "name": "acceptRegex", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "RegExp" + } + }, + "InputAdornmentProps": { + "defaultValue": null, + "description": "Props to pass to keyboard input adornment", + "name": "InputAdornmentProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "KeyboardButtonProps": { + "defaultValue": null, + "description": "Props to pass to keyboard adornment button", + "name": "KeyboardButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rifmFormatter": { + "defaultValue": null, + "description": "Custom formatter to be passed into Rifm component", + "name": "rifmFormatter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(str: string) => string" + } + }, + "disableOpenPicker": { + "defaultValue": { + "value": "false" + }, + "description": "Do not render open picker button (renders only text field with validation)", + "name": "disableOpenPicker", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableMaskedInput": { + "defaultValue": { + "value": "false" + }, + "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", + "name": "disableMaskedInput", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "getOpenDialogAriaText": { + "defaultValue": null, + "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", + "name": "getOpenDialogAriaText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(value: any, utils: MuiPickersAdapter) => string" + } + }, + "dateAdapter": { + "defaultValue": null, + "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" + }, + "required": false, + "type": { + "name": "MuiPickersAdapter" + } + }, + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "okLabel": { + "defaultValue": { + "value": "\"OK\"" + }, + "description": "\"OK\" label message", + "name": "okLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "cancelLabel": { + "defaultValue": { + "value": "\"CANCEL\"" + }, + "description": "\"CANCEL\" label message", + "name": "cancelLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "clearLabel": { + "defaultValue": { + "value": "\"CLEAR\"" + }, + "description": "\"CLEAR\" label message", + "name": "clearLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "todayLabel": { + "defaultValue": { + "value": "\"TODAY\"" + }, + "description": "\"TODAY\" label message", + "name": "todayLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "showTodayButton": { + "defaultValue": { + "value": "false" + }, + "description": "If true today button will be displayed. **Note** that clear button has higher priority", + "name": "showTodayButton", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "clearable": { + "defaultValue": { + "value": "false" + }, + "description": "Show clear action in picker dialog", + "name": "clearable", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "DialogProps": { + "defaultValue": null, + "description": "Props to be passed directly to material-ui Dialog", + "name": "DialogProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "PopoverProps": { + "defaultValue": null, + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "desktopModeBreakpoint": { + "defaultValue": { + "value": "'md'" + }, + "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", + "name": "desktopModeBreakpoint", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", + "name": "ResponsiveWrapperProps" + }, + "required": false, + "type": { + "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" + } + } + }, "Calendar": { "onChange": { "defaultValue": null, diff --git a/docs/scripts/docgen.js b/docs/scripts/docgen.js index a2de7c0e2..0acd01e1f 100644 --- a/docs/scripts/docgen.js +++ b/docs/scripts/docgen.js @@ -26,10 +26,9 @@ const components = [ 'wrappers/MobileWrapper.tsx', 'wrappers/DesktopWrapper.tsx', 'DatePicker/DatePicker.tsx', - 'DatePicker/KeyboardDatePicker.tsx', 'TimePicker/TimePicker.tsx', 'DateTimePicker/DateTimePicker.tsx', - 'DateTimePicker/KeyboardDateTimePicker.tsx', + 'DateRangePicker/DateRangePicker.tsx', // internal components 'views/Calendar/Calendar.tsx', 'views/Calendar/Day.tsx', diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index 1398db75e..51ba6dc9c 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,26 +1,26 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 180316, - "minified": 97608, - "gzipped": 25789, + "bundled": 187431, + "minified": 101737, + "gzipped": 26547, "treeshaked": { "rollup": { - "code": 81201, - "import_statements": 2175 + "code": 84511, + "import_statements": 2188 }, "webpack": { - "code": 89920 + "code": 93573 } } }, "build/dist/material-ui-pickers.umd.js": { - "bundled": 296515, - "minified": 117118, - "gzipped": 33379 + "bundled": 304025, + "minified": 120648, + "gzipped": 34030 }, "build/dist/material-ui-pickers.umd.min.js": { - "bundled": 250115, - "minified": 105323, - "gzipped": 30011 + "bundled": 257625, + "minified": 108854, + "gzipped": 30652 } } diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index ca57b05bd..e7f6c7691 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -11,7 +11,7 @@ import { DateRange as DateRangeType, RangeInput } from './RangeTypes'; import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; -import { DateRangePickerView, DateRangePickerViewProps } from './DateRangePickerView'; +import { DateRangePickerView, ExportedDateRangePickerViewProps } from './DateRangePickerView'; import { DateRangePickerInput, ExportedDateRangePickerInputProps } from './DateRangePickerInput'; export function parseRangeInputValue( @@ -50,7 +50,7 @@ export function makeRangePicker(Wrapper: TWrapper) onChange, inputFormat: passedInputFormat, ...restPropsForTextField - }: DateRangePickerViewProps & + }: ExportedDateRangePickerViewProps & ExportedDateRangePickerInputProps & AllSharedPickerProps & ExtendWrapper) { diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 06840bcc4..e850d948d 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -35,7 +35,6 @@ export const useStyles = makeStyles( export interface ExportedDateRangePickerInputProps { toText?: React.ReactNode; - rangeChangingStrategy?: 'expand' | 'circular'; } export interface DateRangeInputProps diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 3094d2b8a..992f92256 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -20,17 +20,21 @@ import { type BaseCalendarPropsToReuse = Omit; -export interface DateRangePickerViewProps +export interface ExportedDateRangePickerViewProps extends BaseCalendarPropsToReuse, ExportedDesktopDateRangeCalendarProps, - SharedPickerProps, - CurrentlySelectingRangeEndProps, Omit { /** * if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date * @default false */ disableAutoMonthSwitching?: boolean; +} + +interface DateRangePickerViewProps + extends ExportedDateRangePickerViewProps, + CurrentlySelectingRangeEndProps, + SharedPickerProps { open: boolean; } diff --git a/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx b/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx index b27f4387f..d29d59d30 100644 --- a/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx +++ b/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx @@ -14,6 +14,10 @@ import { } from '../_shared/hooks/date-helpers-hooks'; export interface ExportedDesktopDateRangeCalendarProps { + /** + * How many calendars render on **desktop** DateRangePicker + * @default 2 + */ calendars?: 1 | 2 | 3; } diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index f7f14fb13..237445638 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -82,6 +82,7 @@ export type ExportedDateInputProps = Omit< | 'rawValue' | 'forwardedRef' | 'parsedDateValue' + | 'open' >; export const PureDateInput: React.FC = ({ From 6b178161bac0ba9a01e6a57d70e83026c9eafcd8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 31 Mar 2020 15:44:35 +0300 Subject: [PATCH 45/72] Fix example ts-checks --- .../demo/daterangepicker/BasicDateRangePicker.example.jsx | 4 +++- .../demo/daterangepicker/MinMaxDateRangePicker.example.jsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index 1d1fd0f02..7e3b74967 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -2,7 +2,9 @@ import React, { useState } from 'react'; import { DateRangePicker } from '@material-ui/pickers'; function BasicDateRangePicker() { - const [selectedDate, handleDateChange] = useState([null, null]); + /** @type import('@material-ui/pickers').DateRange */ + const initialValue = [null, null]; + const [selectedDate, handleDateChange] = useState(initialValue); return handleDateChange(date)} />; } diff --git a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx index 61e29d4ab..1637eb4e3 100644 --- a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx @@ -11,7 +11,9 @@ function disableWeekends(date) { function MinMaxDateRangePicker() { const utils = useUtils(); - const [selectedRange, handleDateChange] = useState([new Date(), null]); + /** @type import('@material-ui/pickers').DateRange */ + const initialValue = [new Date(), null]; + const [selectedRange, handleDateChange] = useState(initialValue); return ( Date: Tue, 31 Mar 2020 15:48:58 +0300 Subject: [PATCH 46/72] Fix ts error in ServerRerquest.example.jsx --- docs/pages/demo/datepicker/ServerRequest.example.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/demo/datepicker/ServerRequest.example.jsx b/docs/pages/demo/datepicker/ServerRequest.example.jsx index f8178ad61..546be5c3b 100644 --- a/docs/pages/demo/datepicker/ServerRequest.example.jsx +++ b/docs/pages/demo/datepicker/ServerRequest.example.jsx @@ -30,7 +30,7 @@ function ServerRequest() { renderDay={(day, selectedDate, DayComponentProps) => { const date = makeJSDateObject(day); // skip this step, it is required to support date libs const isSelected = - DayComponentProps.isInCurrentMonth && selectedDays.includes(date.getDate()); + DayComponentProps.inCurrentMonth && selectedDays.includes(date.getDate()); return ( From a827fd2084bd6536a11ba577b82884f3364d3d4c Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 13:16:12 +0300 Subject: [PATCH 47/72] Fix error if mouning in open state --- lib/src/_shared/hooks/useOpenState.ts | 40 +++++++++++++++++---------- lib/typings.d.ts | 5 +--- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/lib/src/_shared/hooks/useOpenState.ts b/lib/src/_shared/hooks/useOpenState.ts index c6fbc5e10..4d47b2464 100644 --- a/lib/src/_shared/hooks/useOpenState.ts +++ b/lib/src/_shared/hooks/useOpenState.ts @@ -1,22 +1,32 @@ -/* eslint-disable react-hooks/rules-of-hooks */ +import * as React from 'react'; import { BasePickerProps } from '../../typings/BasePicker'; -import { useCallback, useState, Dispatch, SetStateAction } from 'react'; export function useOpenState({ open, onOpen, onClose }: BasePickerProps) { - let setIsOpenState: null | Dispatch> = null; - if (open === undefined || open === null) { - // The component is uncontrolled, so we need to give it its own state. - [open, setIsOpenState] = useState(false); - } + const isControllingOpenProp = React.useRef(typeof open === 'boolean').current; + const [_open, _setIsOpen] = React.useState(false); - // prettier-ignore - const setIsOpen = useCallback((newIsOpen: boolean) => { - setIsOpenState && setIsOpenState(newIsOpen); + // It is required to update inner state in useEffect in order to aviod situation when + // Our component is not mounted yet, but `open` state is set to `true` (e.g. initially opened) + React.useEffect(() => { + if (isControllingOpenProp) { + if (typeof open !== 'boolean') { + throw new Error('You must not mix controlling and uncontrolled mode for `open` prop'); + } - return newIsOpen - ? onOpen && onOpen() - : onClose && onClose(); - }, [onOpen, onClose, setIsOpenState]); + _setIsOpen(open); + } + }, [isControllingOpenProp, open]); - return { isOpen: open, setIsOpen }; + const setIsOpen = React.useCallback( + (newIsOpen: boolean) => { + if (!isControllingOpenProp) { + _setIsOpen(newIsOpen); + } + + return newIsOpen ? onOpen && onOpen() : onClose && onClose(); + }, + [isControllingOpenProp, onOpen, onClose] + ); + + return { isOpen: _open, setIsOpen }; } diff --git a/lib/typings.d.ts b/lib/typings.d.ts index 6069a01af..c7d03c5d3 100644 --- a/lib/typings.d.ts +++ b/lib/typings.d.ts @@ -1,8 +1,5 @@ declare module '@date-io/type' { - import { Moment } from 'moment'; - import { DateTime } from 'luxon'; - - export type DateType = Moment | DateTime | Date; + export type DateType = unknown; } declare module '@material-ui/core/internal/svg-icons/createSvgIcon' { From f2b31b102a61a6de55c5aaaf72f816e39d1dc74f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 13:16:40 +0300 Subject: [PATCH 48/72] Add props test for DateRangePickers --- lib/src/__tests__/DatePicker.test.tsx | 1 - lib/src/__tests__/DateRangePicker.test.tsx | 61 ++++++++++++++++++++++ lib/src/__tests__/setup.js | 11 ++++ lib/src/__tests__/tsconfig.json | 2 +- 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 lib/src/__tests__/DateRangePicker.test.tsx diff --git a/lib/src/__tests__/DatePicker.test.tsx b/lib/src/__tests__/DatePicker.test.tsx index 86b26a7aa..2012433be 100644 --- a/lib/src/__tests__/DatePicker.test.tsx +++ b/lib/src/__tests__/DatePicker.test.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -// import { act } from 'react-dom' import { ReactWrapper } from 'enzyme'; import { Picker } from '../Picker/Picker'; import { mount, utilsToUse } from './test-utils'; diff --git a/lib/src/__tests__/DateRangePicker.test.tsx b/lib/src/__tests__/DateRangePicker.test.tsx new file mode 100644 index 000000000..31d0a83c3 --- /dev/null +++ b/lib/src/__tests__/DateRangePicker.test.tsx @@ -0,0 +1,61 @@ +// Note that most of use cases are covered in cypress tests e2e/integration/DateRange.spec.ts +// Note that most of use cases are covered in cypress tests e2e/integration/DateRange.spec.ts +import * as React from 'react'; +import { isWeekend } from 'date-fns'; +import { mount, utilsToUse } from './test-utils'; +import { DateRangePicker } from '../DateRangePicker/DateRangePicker'; + +describe('DateRangePicker', () => { + test('allows select range', () => { + const component = mount( + + ); + + expect(component.find('[data-mui-test="DateRangeHighlight"]').length).toBe(31); + }); + + test('allows disabling dates', () => { + const component = mount( + isWeekend(utilsToUse.toJsDate(date))} + onChange={jest.fn()} + value={[ + utilsToUse.date('2018-01-01T00:00:00.000'), + utilsToUse.date('2018-01-31T00:00:00.000'), + ]} + /> + ); + + expect( + component + .find('button[data-mui-test="DateRangeDay"]') + .filterWhere(wrapper => !wrapper.prop('disabled')).length + ).toBe(70); + }); + + test('prop: calendars', () => { + const component = mount( + + ); + + expect(component.find('Calendar').length).toBe(3); + expect(component.find('button[data-mui-test="DateRangeDay"]').length).toBe(105); + }); +}); diff --git a/lib/src/__tests__/setup.js b/lib/src/__tests__/setup.js index 765002fde..77bd4ba46 100644 --- a/lib/src/__tests__/setup.js +++ b/lib/src/__tests__/setup.js @@ -4,6 +4,17 @@ const EnzymeAdapter = require('enzyme-adapter-react-16'); // Setup enzyme's react adapter Enzyme.configure({ adapter: new EnzymeAdapter() }); +// Fix popper mount https://github.com/mui-org/material-ui/issues/15726 +document.createRange = () => ({ + setStart: () => {}, + setEnd: () => {}, + // @ts-ignore + commonAncestorContainer: { + nodeName: 'BODY', + ownerDocument: document, + }, +}); + // Convert any console error into a thrown error const error = console.error; console.error = (...args) => { diff --git a/lib/src/__tests__/tsconfig.json b/lib/src/__tests__/tsconfig.json index 1d867ff0d..9283d45cc 100644 --- a/lib/src/__tests__/tsconfig.json +++ b/lib/src/__tests__/tsconfig.json @@ -1,5 +1,5 @@ { "extends": "../../tsconfig.json", - "include": ["./**/*.tsx", "./**/*.ts", "../../typings.d.ts"], + "include": ["../../typings.d.ts", "./**/*.tsx", "./**/*.ts"], "exclude": [] } From 68027953aef7674f903e9d76699a867396fa965d Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 13:18:11 +0300 Subject: [PATCH 49/72] Export responsive date range picker by default --- lib/src/DateRangePicker/DateRangePicker.tsx | 11 +++- .../DateRangePickerViewMobile.tsx | 4 +- lib/src/__tests__/DateRangePicker.test.tsx | 9 ++- lib/src/_helpers/date-utils.ts | 6 +- lib/src/views/Calendar/Calendar.tsx | 8 ++- lib/src/wrappers/ResponsiveWrapper.tsx | 65 +++++++++++-------- 6 files changed, 61 insertions(+), 42 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index e7f6c7691..d929dd79e 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -5,12 +5,13 @@ import { MobileWrapper } from '../wrappers/MobileWrapper'; import { DateRangeInputProps } from './DateRangePickerInput'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; -import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { AllSharedPickerProps } from '../Picker/SharedPickerProps'; import { DateRange as DateRangeType, RangeInput } from './RangeTypes'; +import { makeResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; +import { SomeWrapper, ExtendWrapper, StaticWrapper } from '../wrappers/Wrapper'; import { DateRangePickerView, ExportedDateRangePickerViewProps } from './DateRangePickerView'; import { DateRangePickerInput, ExportedDateRangePickerInputProps } from './DateRangePickerInput'; @@ -123,6 +124,12 @@ export function makeRangePicker(Wrapper: TWrapper) // TODO replace with new export type syntax export type DateRange = DateRangeType; -export const DateRangePicker = makeRangePicker(DesktopPopperWrapper); +export const DateRangePicker = makeRangePicker( + makeResponsiveWrapper(DesktopPopperWrapper, MobileWrapper) +); + +export const DesktopDateRangePicker = makeRangePicker(DesktopPopperWrapper); export const MobileDateRangePicker = makeRangePicker(MobileWrapper); + +export const StaticDateRangePicker = makeRangePicker(StaticWrapper); diff --git a/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx b/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx index 6a434a317..5ff01328b 100644 --- a/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx +++ b/lib/src/DateRangePicker/DateRangePickerViewMobile.tsx @@ -18,6 +18,8 @@ interface DesktopDateRangeCalendarProps changeMonth: (date: MaterialUiPickersDate) => void; } +const onlyDateView = ['date'] as ['date']; + export const DateRangePickerViewMobile: React.FC = ({ date, changeMonth, @@ -36,7 +38,7 @@ export const DateRangePickerViewMobile: React.FC <> ({})} onMonthChange={changeMonth} leftArrowButtonProps={leftArrowButtonProps} diff --git a/lib/src/__tests__/DateRangePicker.test.tsx b/lib/src/__tests__/DateRangePicker.test.tsx index 31d0a83c3..4807b9e51 100644 --- a/lib/src/__tests__/DateRangePicker.test.tsx +++ b/lib/src/__tests__/DateRangePicker.test.tsx @@ -1,14 +1,13 @@ // Note that most of use cases are covered in cypress tests e2e/integration/DateRange.spec.ts -// Note that most of use cases are covered in cypress tests e2e/integration/DateRange.spec.ts import * as React from 'react'; import { isWeekend } from 'date-fns'; import { mount, utilsToUse } from './test-utils'; -import { DateRangePicker } from '../DateRangePicker/DateRangePicker'; +import { DesktopDateRangePicker } from '../DateRangePicker/DateRangePicker'; describe('DateRangePicker', () => { test('allows select range', () => { const component = mount( - { test('allows disabling dates', () => { const component = mount( - isWeekend(utilsToUse.toJsDate(date))} @@ -44,7 +43,7 @@ describe('DateRangePicker', () => { test('prop: calendars', () => { const component = mount( - { - return Boolean(range && utils.isBefore(range[0], range[1])); + return Boolean(range && range[0] && range[1] && utils.isBefore(range[0], range[1])); }; export const isWithinRange = ( @@ -128,7 +128,7 @@ export const isStartOfRange = ( day: MaterialUiPickersDate, range: DateRange | null ) => { - return Boolean(range && utils.isSameDay(day, range[0])); + return isRangeValid(utils, range) && utils.isSameDay(day, range[0]); }; export const isEndOfRange = ( @@ -136,5 +136,5 @@ export const isEndOfRange = ( day: MaterialUiPickersDate, range: DateRange | null ) => { - return Boolean(range && utils.isSameDay(day, range[1])); + return isRangeValid(utils, range) && utils.isSameDay(day, range[1]); }; diff --git a/lib/src/views/Calendar/Calendar.tsx b/lib/src/views/Calendar/Calendar.tsx index 8d280b2ac..41b0b7b59 100644 --- a/lib/src/views/Calendar/Calendar.tsx +++ b/lib/src/views/Calendar/Calendar.tsx @@ -135,7 +135,7 @@ export const Calendar: React.FC = ({ const initialDate = Array.isArray(date) ? date[0] : date; React.useEffect(() => { - if (isDateDisabled(initialDate)) { + if (initialDate && isDateDisabled(initialDate)) { const closestEnabledDate = findClosestEnabledDate({ utils, date: initialDate, @@ -193,13 +193,13 @@ export const Calendar: React.FC = ({ >
{utils.getWeekArray(currentMonth).map(week => ( -
+
{week.map(day => { const disabled = isDateDisabled(day); const isDayInCurrentMonth = utils.getMonth(day) === currentMonthNumber; const dayProps: DayProps = { - key: day?.toString(), + key: (day as any)?.toString(), day: day, role: 'cell', isAnimating: isMonthSwitchingAnimating, @@ -230,4 +230,6 @@ export const Calendar: React.FC = ({ ); }; +Calendar.displayName = 'Calendar'; + export default Calendar; diff --git a/lib/src/wrappers/ResponsiveWrapper.tsx b/lib/src/wrappers/ResponsiveWrapper.tsx index adb9def47..5e2169e5a 100644 --- a/lib/src/wrappers/ResponsiveWrapper.tsx +++ b/lib/src/wrappers/ResponsiveWrapper.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { Theme } from '@material-ui/core/styles'; import useMediaQuery from '@material-ui/core/useMediaQuery'; +import { Theme } from '@material-ui/core/styles'; import { MobileWrapperProps, MobileWrapper } from './MobileWrapper'; import { DesktopWrapperProps, DesktopWrapper } from './DesktopWrapper'; import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; @@ -12,32 +12,41 @@ export interface ResponsiveWrapperProps extends DesktopWrapperProps, MobileWrapp desktopModeBreakpoint?: Breakpoint; } -export const ResponsiveWrapper: React.FC = ({ - desktopModeBreakpoint = 'md', - okLabel, - cancelLabel, - clearLabel, - todayLabel, - showTodayButton, - clearable, - DialogProps, - PopoverProps, - ...other -}) => { - const isDesktop = useMediaQuery(theme => theme.breakpoints.up(desktopModeBreakpoint)); +export const makeResponsiveWrapper = ( + DesktopWrapperComponent: React.FC, + MobileWrapperComponent: React.FC +) => { + const ResponsiveWrapper: React.FC = ({ + desktopModeBreakpoint = 'md', + okLabel, + cancelLabel, + clearLabel, + todayLabel, + showTodayButton, + clearable, + DialogProps, + PopoverProps, + ...other + }) => { + const isDesktop = useMediaQuery(theme => theme.breakpoints.up(desktopModeBreakpoint)); - return isDesktop ? ( - - ) : ( - - ); + return isDesktop ? ( + + ) : ( + + ); + }; + + return ResponsiveWrapper; }; + +export const ResponsiveWrapper = makeResponsiveWrapper(DesktopWrapper, MobileWrapper); From 4b8173b43d278af95798a9cf2b28e01d6df9921e Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 13:22:36 +0300 Subject: [PATCH 50/72] Add missing displayName to the ToolbarButton --- lib/src/_shared/ToolbarButton.tsx | 2 ++ lib/src/_shared/hooks/useOpenState.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/src/_shared/ToolbarButton.tsx b/lib/src/_shared/ToolbarButton.tsx index 01d251c63..f2e92681f 100644 --- a/lib/src/_shared/ToolbarButton.tsx +++ b/lib/src/_shared/ToolbarButton.tsx @@ -49,4 +49,6 @@ export const ToolbarButton: React.FunctionComponent = ({ ); }; +ToolbarButton.displayName = 'ToolbarButton'; + export default ToolbarButton; diff --git a/lib/src/_shared/hooks/useOpenState.ts b/lib/src/_shared/hooks/useOpenState.ts index 4d47b2464..c3dc63b21 100644 --- a/lib/src/_shared/hooks/useOpenState.ts +++ b/lib/src/_shared/hooks/useOpenState.ts @@ -5,7 +5,7 @@ export function useOpenState({ open, onOpen, onClose }: BasePickerProps { if (isControllingOpenProp) { From fc6f92c23420a23151522183ca9aee72b2fbe7db Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 17:31:29 +0300 Subject: [PATCH 51/72] Small enhancmenets --- docs/prop-types.json | 8 ++++---- lib/src/_shared/PickerToolbar.tsx | 6 +++--- lib/src/_shared/withDateAdapterProp.tsx | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index abb51bf3f..3fedcc0ce 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -1060,7 +1060,7 @@ }, "dateAdapter": { "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", "name": "dateAdapter", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", @@ -1795,7 +1795,7 @@ }, "dateAdapter": { "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", "name": "dateAdapter", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", @@ -2854,7 +2854,7 @@ }, "dateAdapter": { "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", "name": "dateAdapter", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", @@ -3611,7 +3611,7 @@ }, "dateAdapter": { "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", "name": "dateAdapter", "parent": { "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", diff --git a/lib/src/_shared/PickerToolbar.tsx b/lib/src/_shared/PickerToolbar.tsx index 33a8cda02..9c7683770 100644 --- a/lib/src/_shared/PickerToolbar.tsx +++ b/lib/src/_shared/PickerToolbar.tsx @@ -1,13 +1,13 @@ import * as React from 'react'; import clsx from 'clsx'; -import Toolbar, { ToolbarProps } from '@material-ui/core/Toolbar'; -import { makeStyles } from '@material-ui/core/styles'; +import Grid from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import IconButton from '@material-ui/core/IconButton'; -import Grid from '@material-ui/core/Grid'; +import Toolbar, { ToolbarProps } from '@material-ui/core/Toolbar'; import { ExtendMui } from '../typings/helpers'; import { PenIcon } from '../_shared/icons/PenIcon'; import { KeyboardIcon } from './icons/KeyboardIcon'; +import { makeStyles } from '@material-ui/core/styles'; import { ToolbarComponentProps } from '../Picker/Picker'; export const useStyles = makeStyles( diff --git a/lib/src/_shared/withDateAdapterProp.tsx b/lib/src/_shared/withDateAdapterProp.tsx index 6c5e5b71d..9911a238c 100644 --- a/lib/src/_shared/withDateAdapterProp.tsx +++ b/lib/src/_shared/withDateAdapterProp.tsx @@ -4,7 +4,7 @@ import { MuiPickersAdapterContext } from '../LocalizationProvider'; export interface WithDateAdapterProps { /** - * Allows to pass configured date-io adapter directly. More info [here](/guides/date-adapter-passing) + * Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing) * ```jsx * dateAdapter={new DateFnsAdapter({ locale: ruLocale })} * ``` @@ -19,7 +19,7 @@ export function withDateAdapterProp( if (dateAdapter) { return ( - + ); } From 78a75df9d85e06f9578aef169d03db365ed68179 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 18:20:37 +0300 Subject: [PATCH 52/72] Fix inclusivity of range for non-datefns livs --- .../BasicDateRangePicker.example.jsx | 9 +- docs/prop-types.json | 116 +++++++++++++++++- lib/src/DateRangePicker/DateRangePicker.tsx | 6 +- lib/src/Picker/makePickerWithState.tsx | 2 +- lib/src/__tests__/DateRangePicker.test.tsx | 4 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 5 +- lib/src/wrappers/ResponsiveWrapper.tsx | 19 ++- yarn.lock | 36 +++--- 8 files changed, 160 insertions(+), 37 deletions(-) diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index 7e3b74967..8df70a02e 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -6,7 +6,14 @@ function BasicDateRangePicker() { const initialValue = [null, null]; const [selectedDate, handleDateChange] = useState(initialValue); - return handleDateChange(date)} />; + // prettier-ignore + return ( + handleDateChange(date)} + value={[new Date('2018-01-01T00:00:00.000Z'), new Date('2018-01-31T00:00:00.000Z')]} + /> + ); } export default BasicDateRangePicker; diff --git a/docs/prop-types.json b/docs/prop-types.json index 3fedcc0ce..13524cb75 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -1043,6 +1043,19 @@ "name": "Partial" } }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -1058,6 +1071,19 @@ "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -1778,6 +1804,19 @@ "name": "Partial" } }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -1793,6 +1832,19 @@ "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -2837,6 +2889,19 @@ "name": "Partial" } }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -2852,6 +2917,19 @@ "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -3682,6 +3760,19 @@ "name": "ReactNode" } }, + "PopoverProps": { + "defaultValue": null, + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, "okLabel": { "defaultValue": { "value": "\"OK\"" @@ -3785,17 +3876,17 @@ "name": "Partial" } }, - "PopoverProps": { + "TransitionComponent": { "defaultValue": null, - "description": "Popover props passed to material-ui Popover", - "name": "PopoverProps", + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", - "name": "InnerDesktopWrapperProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" }, "required": false, "type": { - "name": "Partial" + "name": "ComponentClass | FunctionComponent" } }, "desktopModeBreakpoint": { @@ -3812,6 +3903,19 @@ "type": { "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } + }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } } }, "Calendar": { diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index d929dd79e..6c30670ca 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -7,7 +7,7 @@ import { parsePickerInputValue } from '../_helpers/date-utils'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { AllSharedPickerProps } from '../Picker/SharedPickerProps'; import { DateRange as DateRangeType, RangeInput } from './RangeTypes'; -import { makeResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; +import { ResponsivePopperWrapper } from '../wrappers/ResponsiveWrapper'; import { DesktopPopperWrapper } from '../wrappers/DesktopPopperWrapper'; import { MuiPickersAdapter, useUtils } from '../_shared/hooks/useUtils'; import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; @@ -124,9 +124,7 @@ export function makeRangePicker(Wrapper: TWrapper) // TODO replace with new export type syntax export type DateRange = DateRangeType; -export const DateRangePicker = makeRangePicker( - makeResponsiveWrapper(DesktopPopperWrapper, MobileWrapper) -); +export const DateRangePicker = makeRangePicker(ResponsivePopperWrapper); export const DesktopDateRangePicker = makeRangePicker(DesktopPopperWrapper); diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 6fb912d89..36db75f01 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -45,7 +45,7 @@ export function makePickerWithStateAndWrapper< emptyValue: null, parseInput: parsePickerInputValue, validateInput: validateDateValue, - areValuesEqual: utils.isEqual, + areValuesEqual: (a, b) => utils.isEqual(a, b), }); const { diff --git a/lib/src/__tests__/DateRangePicker.test.tsx b/lib/src/__tests__/DateRangePicker.test.tsx index 4807b9e51..bf1ccf07a 100644 --- a/lib/src/__tests__/DateRangePicker.test.tsx +++ b/lib/src/__tests__/DateRangePicker.test.tsx @@ -11,8 +11,8 @@ describe('DateRangePicker', () => { open onChange={jest.fn()} value={[ - utilsToUse.date('2018-01-01T00:00:00.000'), - utilsToUse.date('2018-01-31T00:00:00.000'), + utilsToUse.date(new Date('2018-01-01T00:00:00.000Z')), + utilsToUse.date(new Date('2018-01-31T00:00:00.000Z')), ]} /> ); diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index ea961d0c0..522928945 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -15,12 +15,13 @@ import { TransitionProps } from '@material-ui/core/transitions/transition'; import { executeInTheNextEventLoopTick, createDelegatedEventHandler } from '../_helpers/utils'; export interface InnerDesktopPopperWrapperProps { - /** Popover props passed to material-ui Popover */ + /** Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api) */ PopperProps?: Partial; + /** Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop) */ TransitionComponent?: React.ComponentType; } -export interface DesktopWrapperProps +export interface DesktopPopperWrapperProps extends InnerDesktopPopperWrapperProps, WrapperProps, Partial {} diff --git a/lib/src/wrappers/ResponsiveWrapper.tsx b/lib/src/wrappers/ResponsiveWrapper.tsx index 5e2169e5a..6a2e713a3 100644 --- a/lib/src/wrappers/ResponsiveWrapper.tsx +++ b/lib/src/wrappers/ResponsiveWrapper.tsx @@ -4,8 +4,12 @@ import { Theme } from '@material-ui/core/styles'; import { MobileWrapperProps, MobileWrapper } from './MobileWrapper'; import { DesktopWrapperProps, DesktopWrapper } from './DesktopWrapper'; import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; +import { DesktopPopperWrapperProps, DesktopPopperWrapper } from './DesktopPopperWrapper'; -export interface ResponsiveWrapperProps extends DesktopWrapperProps, MobileWrapperProps { +export interface ResponsiveWrapperProps + extends DesktopWrapperProps, + DesktopPopperWrapperProps, + MobileWrapperProps { /** Breakpoint when `Desktop` mode will be changed to `Mobile` * @default 'md' */ @@ -13,7 +17,7 @@ export interface ResponsiveWrapperProps extends DesktopWrapperProps, MobileWrapp } export const makeResponsiveWrapper = ( - DesktopWrapperComponent: React.FC, + DesktopWrapperComponent: React.FC, MobileWrapperComponent: React.FC ) => { const ResponsiveWrapper: React.FC = ({ @@ -26,12 +30,19 @@ export const makeResponsiveWrapper = ( clearable, DialogProps, PopoverProps, + PopperProps, + TransitionComponent, ...other }) => { const isDesktop = useMediaQuery(theme => theme.breakpoints.up(desktopModeBreakpoint)); return isDesktop ? ( - + ) : ( Date: Thu, 2 Apr 2020 18:26:30 +0300 Subject: [PATCH 53/72] Fix ts error --- lib/src/wrappers/DesktopPopperWrapper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 522928945..c7aabcf0e 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -41,7 +41,7 @@ const useStyles = makeStyles(theme => ({ }, })); -export const DesktopPopperWrapper: React.FC = ({ +export const DesktopPopperWrapper: React.FC = ({ open, wider, children, From 23c600ca5ca80176f392c962b45d8a19daf195be Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 2 Apr 2020 18:31:09 +0300 Subject: [PATCH 54/72] Remove fake data from range example --- docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx index 8df70a02e..723c1e344 100644 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx @@ -11,7 +11,6 @@ function BasicDateRangePicker() { handleDateChange(date)} - value={[new Date('2018-01-01T00:00:00.000Z'), new Date('2018-01-31T00:00:00.000Z')]} /> ); } From 12c0baa88a8150058091cec37cfa99dae52136d8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 4 Apr 2020 11:56:54 +0300 Subject: [PATCH 55/72] Use tsx in date range picker examples --- docs/_shared/Code.tsx | 2 +- docs/next.config.js | 2 +- .../BasicDateRangePicker.example.jsx | 18 ---------- .../BasicDateRangePicker.example.tsx | 17 +++++++++ ...x => CalendarsDateRangePicker.example.tsx} | 8 ++--- .../MinMaxDateRangePicker.example.jsx | 29 --------------- .../MinMaxDateRangePicker.example.tsx | 35 +++++++++++++++++++ 7 files changed, 57 insertions(+), 54 deletions(-) delete mode 100644 docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx create mode 100644 docs/pages/demo/daterangepicker/BasicDateRangePicker.example.tsx rename docs/pages/demo/daterangepicker/{CalendarsDateRangePicker.example.jsx => CalendarsDateRangePicker.example.tsx} (74%) delete mode 100644 docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx create mode 100644 docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx diff --git a/docs/_shared/Code.tsx b/docs/_shared/Code.tsx index 8d898e0b6..fb96cbdf0 100644 --- a/docs/_shared/Code.tsx +++ b/docs/_shared/Code.tsx @@ -42,7 +42,7 @@ interface CodeProps { language?: 'jsx' | 'typescript' | 'markup'; } -const Code: React.SFC = ({ language = 'jsx', inline, children, withMargin }) => { +const Code: React.FC = ({ language = 'typescript', inline, children, withMargin }) => { const classes = useStyles(); const highlightedCode = highlight(children, language); diff --git a/docs/next.config.js b/docs/next.config.js index 0fe3f9c53..b9661d522 100644 --- a/docs/next.config.js +++ b/docs/next.config.js @@ -42,7 +42,7 @@ module.exports = withBundleAnalyzer( // Process examples to inject raw code strings config.module.rules.push({ - test: /\.example\.(js|jsx)$/, + test: /\.example\.(js|jsx|tsx|ts)$/, include: [path.resolve(__dirname, 'pages')], use: [ { loader: 'next-babel-loader' }, diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx deleted file mode 100644 index 723c1e344..000000000 --- a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React, { useState } from 'react'; -import { DateRangePicker } from '@material-ui/pickers'; - -function BasicDateRangePicker() { - /** @type import('@material-ui/pickers').DateRange */ - const initialValue = [null, null]; - const [selectedDate, handleDateChange] = useState(initialValue); - - // prettier-ignore - return ( - handleDateChange(date)} - /> - ); -} - -export default BasicDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.tsx new file mode 100644 index 000000000..8776a36b8 --- /dev/null +++ b/docs/pages/demo/daterangepicker/BasicDateRangePicker.example.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DateRangePicker, DateRange } from '@material-ui/pickers'; + +function BasicDateRangePicker() { + const [selectedDate, handleDateChange] = React.useState([null, null]); + + return ( + handleDateChange(date)} + /> + ); +} + +export default BasicDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx similarity index 74% rename from docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx rename to docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx index f6a952ad3..89d11a546 100644 --- a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.jsx +++ b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx @@ -1,11 +1,9 @@ -import React, { useState } from 'react'; +import * as React from 'react'; import { Grid, Typography } from '@material-ui/core'; -import { DateRangePicker } from '@material-ui/pickers'; +import { DateRangePicker, DateRange } from '@material-ui/pickers'; function CalendarsDateRangePicker() { - /** @type import('@material-ui/pickers').DateRange */ - const initialValue = [null, null]; - const [selectedDate, handleDateChange] = useState(initialValue); + const [selectedDate, handleDateChange] = React.useState([null, null]); return ( diff --git a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx deleted file mode 100644 index 1637eb4e3..000000000 --- a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React, { useState } from 'react'; -import isWeekend from 'date-fns/isWeekend'; -// this guy required only on the docs site to work with dynamic date library -import { makeJSDateObject } from '../../../utils/helpers'; -import { DateRangePicker, useUtils } from '@material-ui/pickers'; - -function disableWeekends(date) { - // TODO: replace with implementation for your date library - return isWeekend(makeJSDateObject(date)); -} - -function MinMaxDateRangePicker() { - const utils = useUtils(); - /** @type import('@material-ui/pickers').DateRange */ - const initialValue = [new Date(), null]; - const [selectedRange, handleDateChange] = useState(initialValue); - - return ( - handleDateChange(date)} - /> - ); -} - -export default MinMaxDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx new file mode 100644 index 000000000..32ab72613 --- /dev/null +++ b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx @@ -0,0 +1,35 @@ +import * as React from 'react'; +import isWeekend from 'date-fns/isWeekend'; +import { Dayjs } from 'dayjs'; +import { Moment } from 'moment'; +import { DateTime } from 'luxon'; +import { addYears } from 'date-fns'; +// this guy required only on the docs site to work with dynamic date library +import { makeJSDateObject } from '../../../utils/helpers'; +import { DateRangePicker, DateRange } from '@material-ui/pickers'; + +function disableWeekends(date: Moment | DateTime | Dayjs | Date) { + // TODO: replace with implementation for your date library + return isWeekend(makeJSDateObject(date)); +} + +function getOneYearAfter(date: Moment | DateTime | Dayjs | Date) { + // TODO: replace with implementation for your date library + return addYears(makeJSDateObject(date), 1); +} + +function MinMaxDateRangePicker() { + const [selectedRange, handleDateChange] = React.useState([new Date(), null]); + + return ( + handleDateChange(date)} + /> + ); +} + +export default MinMaxDateRangePicker; From 402e7f234fde48b21448d518e5da9d028a46aa8f Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 4 Apr 2020 11:57:06 +0300 Subject: [PATCH 56/72] Add `startText` and `endText` props --- docs/prop-types.json | 30 +++++++++++++ lib/src/DateRangePicker/DateRangePicker.tsx | 45 ++++++++++++------- .../DateRangePicker/DateRangePickerInput.tsx | 9 +++- .../DateRangePickerToolbar.tsx | 16 ++++--- .../DateRangePicker/DateRangePickerView.tsx | 6 +++ .../DateTimePicker/DateTimePickerToolbar.tsx | 10 ++--- lib/src/TimePicker/TimePickerToolbar.tsx | 12 ++--- lib/src/_shared/ToolbarButton.tsx | 8 ++-- lib/src/_shared/ToolbarText.tsx | 10 ++--- 9 files changed, 105 insertions(+), 41 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index 13524cb75..f9c9d9a0b 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -3005,6 +3005,36 @@ } }, "DateRangePicker": { + "startText": { + "defaultValue": { + "value": "\"Start\"" + }, + "description": "Text for start input label and toolbar placeholder", + "name": "startText", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePicker.tsx", + "name": "DateRangePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "endText": { + "defaultValue": { + "value": "\"end\"" + }, + "description": "Text for end input label and toolbar placeholder", + "name": "endText", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePicker.tsx", + "name": "DateRangePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, "disableAutoMonthSwitching": { "defaultValue": { "value": "false" diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 6c30670ca..9ee409b28 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -27,6 +27,21 @@ export function parseRangeInputValue( ) as DateRange; } +interface DateRangePickerProps + extends ExportedDateRangePickerViewProps, + 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; +} + export function makeRangePicker(Wrapper: TWrapper) { const WrapperComponent = makeWrapperComponent( Wrapper, @@ -49,12 +64,11 @@ export function makeRangePicker(Wrapper: TWrapper) reduceAnimations, value, onChange, + startText = 'Start', + endText = 'End', inputFormat: passedInputFormat, ...restPropsForTextField - }: ExportedDateRangePickerViewProps & - ExportedDateRangePickerInputProps & - AllSharedPickerProps & - ExtendWrapper) { + }: DateRangePickerProps & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); const [currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd] = React.useState< 'start' | 'end' @@ -77,24 +91,23 @@ export function makeRangePicker(Wrapper: TWrapper) } ); + const DateInputProps = { + ...inputProps, + currentlySelectingRangeEnd, + setCurrentlySelectingRangeEnd, + startText, + endText, + }; + return ( (Wrapper: TWrapper) reduceAnimations={reduceAnimations} currentlySelectingRangeEnd={currentlySelectingRangeEnd} setCurrentlySelectingRangeEnd={setCurrentlySelectingRangeEnd} + startText={startText} + endText={endText} {...pickerProps} /> diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index e850d948d..7eb33bbf8 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -40,7 +40,10 @@ export interface ExportedDateRangePickerInputProps { export interface DateRangeInputProps extends ExportedDateRangePickerInputProps, CurrentlySelectingRangeEndProps, - DateInputProps {} + DateInputProps { + startText: React.ReactNode; + endText: React.ReactNode; +} export const DateRangePickerInput: React.FC = ({ toText = 'to', @@ -59,6 +62,8 @@ export const DateRangePickerInput: React.FC = ({ onFocus, readOnly, disableOpenPicker, + startText, + endText, ...other }) => { const utils = useUtils(); @@ -121,6 +126,7 @@ export const DateRangePickerInput: React.FC = ({ disableOpenPicker openPicker={() => {}} readOnly={readOnly} + label={startText} onClick={ readOnly ? createDelegatedEventHandler(openRangeStartSelection, onClick) : undefined } @@ -142,6 +148,7 @@ export const DateRangePickerInput: React.FC = ({ disableOpenPicker openPicker={() => {}} readOnly={readOnly} + label={endText} onClick={readOnly ? createDelegatedEventHandler(openRangeEndSelection, onClick) : undefined} onFocus={ !readOnly ? createDelegatedEventHandler(openRangeEndSelection, onFocus) : undefined diff --git a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx index 76963a61c..58d425c0f 100644 --- a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx +++ b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx @@ -27,6 +27,8 @@ interface DateRangePickerToolbarProps 'isMobileKeyboardViewOpen' | 'toggleMobileKeyboardView' | 'toolbarTitle' | 'toolbarFormat' > { date: DateRange; + startText: React.ReactNode; + endText: React.ReactNode; currentlySelectingRangeEnd: 'start' | 'end'; setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; } @@ -38,16 +40,20 @@ export const DateRangePickerToolbar: React.FC = ({ toggleMobileKeyboardView, currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, + startText, + endText, toolbarTitle = 'SELECT DATE RANGE', }) => { const utils = useUtils(); const classes = useStyles(); - const startText = start + const startDateValue = start ? utils.formatByString(start, toolbarFormat || utils.formats.shortDate) - : 'Start'; + : startText; - const endText = end ? utils.formatByString(end, toolbarFormat || utils.formats.shortDate) : 'End'; + const endDateValue = end + ? utils.formatByString(end, toolbarFormat || utils.formats.shortDate) + : endText; return ( = ({
setCurrentlySelectingRangeEnd('start')} />  {'–'}  setCurrentlySelectingRangeEnd('end')} /> diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index 992f92256..d66a8d4a1 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -36,6 +36,8 @@ interface DateRangePickerViewProps CurrentlySelectingRangeEndProps, SharedPickerProps { open: boolean; + startText: React.ReactNode; + endText: React.ReactNode; } export const DateRangePickerView: React.FC = ({ @@ -57,6 +59,8 @@ export const DateRangePickerView: React.FC = ({ toggleMobileKeyboardView, isMobileKeyboardViewOpen, showToolbar, + startText, + endText, DateInputProps, ...other }) => { @@ -182,6 +186,8 @@ export const DateRangePickerView: React.FC = ({ toggleMobileKeyboardView={toggleMobileKeyboardView} currentlySelectingRangeEnd={currentlySelectingRangeEnd} setCurrentlySelectingRangeEnd={setCurrentlySelectingRangeEnd} + startText={startText} + endText={endText} /> )} diff --git a/lib/src/DateTimePicker/DateTimePickerToolbar.tsx b/lib/src/DateTimePicker/DateTimePickerToolbar.tsx index 610970468..0631b3e00 100644 --- a/lib/src/DateTimePicker/DateTimePickerToolbar.tsx +++ b/lib/src/DateTimePicker/DateTimePickerToolbar.tsx @@ -70,7 +70,7 @@ export const DateTimePickerToolbar: React.FC = ({ variant="subtitle1" onClick={() => setOpenView('year')} selected={openView === 'year'} - label={utils.format(date, 'year')} + value={utils.format(date, 'year')} /> = ({ data-mui-test="datetimepicker-toolbar-date" onClick={() => setOpenView('date')} selected={openView === 'date'} - label={ + value={ toolbarFormat ? utils.formatByString(date, toolbarFormat) : utils.format(date, 'shortDate') @@ -93,18 +93,18 @@ export const DateTimePickerToolbar: React.FC = ({ variant="h3" onClick={() => setOpenView('hours')} selected={openView === 'hours'} - label={ampm ? utils.format(date, 'hours12h') : utils.format(date, 'hours24h')} + value={ampm ? utils.format(date, 'hours12h') : utils.format(date, 'hours24h')} typographyClassName={classes.timeTypography} /> - + setOpenView('minutes')} selected={openView === 'minutes'} - label={utils.format(date, 'minutes')} + value={utils.format(date, 'minutes')} typographyClassName={classes.timeTypography} />
diff --git a/lib/src/TimePicker/TimePickerToolbar.tsx b/lib/src/TimePicker/TimePickerToolbar.tsx index 0ba17e581..9162ee0c3 100644 --- a/lib/src/TimePicker/TimePickerToolbar.tsx +++ b/lib/src/TimePicker/TimePickerToolbar.tsx @@ -93,7 +93,7 @@ export const TimePickerToolbar: React.FC = ({ const separator = ( = ({ variant={clockTypographyVariant} onClick={() => setOpenView('hours')} selected={openView === 'hours'} - label={ampm ? utils.format(date, 'hours12h') : utils.format(date, 'hours24h')} + value={ampm ? utils.format(date, 'hours12h') : utils.format(date, 'hours24h')} /> )} @@ -135,7 +135,7 @@ export const TimePickerToolbar: React.FC = ({ variant={clockTypographyVariant} onClick={() => setOpenView('minutes')} selected={openView === 'minutes'} - label={utils.format(date, 'minutes')} + value={utils.format(date, 'minutes')} /> )} @@ -147,7 +147,7 @@ export const TimePickerToolbar: React.FC = ({ variant={clockTypographyVariant} onClick={() => setOpenView('seconds')} selected={openView === 'seconds'} - label={utils.format(date, 'seconds')} + value={utils.format(date, 'seconds')} /> )}
@@ -164,7 +164,7 @@ export const TimePickerToolbar: React.FC = ({ data-mui-test="toolbar-am-btn" selected={meridiemMode === 'am'} typographyClassName={classes.ampmLabel} - label={utils.getMeridiemText('am')} + value={utils.getMeridiemText('am')} onClick={() => handleMeridiemChange('am')} /> @@ -174,7 +174,7 @@ export const TimePickerToolbar: React.FC = ({ data-mui-test="toolbar-pm-btn" selected={meridiemMode === 'pm'} typographyClassName={classes.ampmLabel} - label={utils.getMeridiemText('pm')} + value={utils.getMeridiemText('pm')} onClick={() => handleMeridiemChange('pm')} />
diff --git a/lib/src/_shared/ToolbarButton.tsx b/lib/src/_shared/ToolbarButton.tsx index f2e92681f..a5117e966 100644 --- a/lib/src/_shared/ToolbarButton.tsx +++ b/lib/src/_shared/ToolbarButton.tsx @@ -6,10 +6,10 @@ import { ExtendMui } from '../typings/helpers'; import { makeStyles } from '@material-ui/core/styles'; import { TypographyProps } from '@material-ui/core/Typography'; -export interface ToolbarButtonProps extends ExtendMui { +export interface ToolbarButtonProps extends ExtendMui { variant: TypographyProps['variant']; selected: boolean; - label: string; + value: React.ReactNode; align?: TypographyProps['align']; typographyClassName?: string; } @@ -27,7 +27,7 @@ export const useStyles = makeStyles( export const ToolbarButton: React.FunctionComponent = ({ className = null, - label, + value: label, selected, variant, align, @@ -42,7 +42,7 @@ export const ToolbarButton: React.FunctionComponent = ({ align={align} className={typographyClassName} variant={variant} - label={label} + value={label} selected={selected} /> diff --git a/lib/src/_shared/ToolbarText.tsx b/lib/src/_shared/ToolbarText.tsx index d6bf1032d..36151b819 100644 --- a/lib/src/_shared/ToolbarText.tsx +++ b/lib/src/_shared/ToolbarText.tsx @@ -2,11 +2,11 @@ import * as React from 'react'; import clsx from 'clsx'; import Typography, { TypographyProps } from '@material-ui/core/Typography'; import { ExtendMui } from '../typings/helpers'; -import { makeStyles } from '@material-ui/core/styles'; -import { fade } from '@material-ui/core/styles/colorManipulator'; +import { makeStyles, fade } from '@material-ui/core/styles'; + export interface ToolbarTextProps extends ExtendMui { selected?: boolean; - label: string; + value: React.ReactNode; } export const useStyles = makeStyles( @@ -29,9 +29,9 @@ export const useStyles = makeStyles( { name: 'MuiPickersToolbarText' } ); -const ToolbarText: React.FunctionComponent = ({ +const ToolbarText: React.FC = ({ selected, - label, + value: label, className = null, ...other }) => { From e9a7c16c4c4c94ecc2d0dcf9f99760da1166fc53 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 6 Apr 2020 11:08:47 +0300 Subject: [PATCH 57/72] Update material-ui and fix createSvgIcon import, closes #1619 --- .../DateRangePicker/DateRangePickerInput.tsx | 2 +- lib/src/_shared/icons/ArrowDropDownIcon.tsx | 2 +- lib/src/_shared/icons/ArrowLeftIcon.tsx | 2 +- lib/src/_shared/icons/ArrowRightIcon.tsx | 2 +- lib/src/_shared/icons/ClockIcon.tsx | 2 +- lib/src/_shared/icons/DateRangeIcon.tsx | 2 +- lib/src/_shared/icons/KeyboardIcon.tsx | 2 +- lib/src/_shared/icons/PenIcon.tsx | 2 +- lib/src/_shared/icons/TimeIcon.tsx | 2 +- lib/typings.d.ts | 8 -- yarn.lock | 136 ++++++++++-------- 11 files changed, 87 insertions(+), 75 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 7eb33bbf8..8fb6db47c 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -70,7 +70,7 @@ export const DateRangePickerInput: React.FC = ({ const classes = useStyles(); const startRef = React.useRef(null); const endRef = React.useRef(null); - const [start, end] = parsedDateValue ?? [null, null]; + const [start, end] = parsedDateValue; React.useEffect(() => { if (!open) { diff --git a/lib/src/_shared/icons/ArrowDropDownIcon.tsx b/lib/src/_shared/icons/ArrowDropDownIcon.tsx index 1515a3f8a..ab955464d 100644 --- a/lib/src/_shared/icons/ArrowDropDownIcon.tsx +++ b/lib/src/_shared/icons/ArrowDropDownIcon.tsx @@ -1,4 +1,4 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const ArrowDropDownIcon = createSvgIcon(, 'ArrowDropDownIcon'); diff --git a/lib/src/_shared/icons/ArrowLeftIcon.tsx b/lib/src/_shared/icons/ArrowLeftIcon.tsx index bc6d2c258..3131499ba 100644 --- a/lib/src/_shared/icons/ArrowLeftIcon.tsx +++ b/lib/src/_shared/icons/ArrowLeftIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const ArrowLeftIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/ArrowRightIcon.tsx b/lib/src/_shared/icons/ArrowRightIcon.tsx index 404ada98d..2a324d29e 100644 --- a/lib/src/_shared/icons/ArrowRightIcon.tsx +++ b/lib/src/_shared/icons/ArrowRightIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const ArrowRightIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/ClockIcon.tsx b/lib/src/_shared/icons/ClockIcon.tsx index 2144883de..97fe42bb0 100644 --- a/lib/src/_shared/icons/ClockIcon.tsx +++ b/lib/src/_shared/icons/ClockIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export default createSvgIcon( diff --git a/lib/src/_shared/icons/DateRangeIcon.tsx b/lib/src/_shared/icons/DateRangeIcon.tsx index 959fe8b17..74a0d8eec 100644 --- a/lib/src/_shared/icons/DateRangeIcon.tsx +++ b/lib/src/_shared/icons/DateRangeIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const DateRangeIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/KeyboardIcon.tsx b/lib/src/_shared/icons/KeyboardIcon.tsx index c8ed8edd1..801027136 100644 --- a/lib/src/_shared/icons/KeyboardIcon.tsx +++ b/lib/src/_shared/icons/KeyboardIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const KeyboardIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/PenIcon.tsx b/lib/src/_shared/icons/PenIcon.tsx index ecd02c6e6..7c1714017 100644 --- a/lib/src/_shared/icons/PenIcon.tsx +++ b/lib/src/_shared/icons/PenIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const PenIcon = createSvgIcon( , diff --git a/lib/src/_shared/icons/TimeIcon.tsx b/lib/src/_shared/icons/TimeIcon.tsx index 640df142f..3110e928a 100644 --- a/lib/src/_shared/icons/TimeIcon.tsx +++ b/lib/src/_shared/icons/TimeIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/internal/svg-icons/createSvgIcon'; +import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; export const TimeIcon = createSvgIcon( <> diff --git a/lib/typings.d.ts b/lib/typings.d.ts index c7d03c5d3..e513b388b 100644 --- a/lib/typings.d.ts +++ b/lib/typings.d.ts @@ -1,11 +1,3 @@ declare module '@date-io/type' { export type DateType = unknown; } - -declare module '@material-ui/core/internal/svg-icons/createSvgIcon' { - import * as React from 'react'; - import { SvgIconProps } from '@material-ui/core/SvgIcon'; - - declare const createSvgIcon: (path: React.ReactNode, name: string) => React.FC; - export default createSvgIcon; -} diff --git a/yarn.lock b/yarn.lock index 918159dab..c960c6f21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1237,13 +1237,20 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" + integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.1.2", "@babel/template@^7.6.0", "@babel/template@^7.7.0": version "7.7.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0" @@ -1636,9 +1643,9 @@ unist-util-visit "^1.1.3" "@material-ui/core@^4.9.7": - version "4.9.7" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.7.tgz#0c1caf123278770f34c5d8e9ecd9e1314f87a621" - integrity sha512-RTRibZgq572GHEskMAG4sP+bt3P3XyIkv3pOTR8grZAW2rSUd6JoGZLRM4S2HkuO7wS7cAU5SpU2s1EsmTgWog== + version "4.9.9" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.9.tgz#902dc37eeb415dd3288feb2c92e0dc27d9caed48" + integrity sha512-Gp0UdJLxPEnkn7O0QpJ2/LOeIuT8nX9e6CjQFuLnOy10rUGjRsOZ2T170Y057xdUmw1VNE+0bvkkO6dOghxt4g== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/styles" "^4.9.6" @@ -2185,7 +2192,15 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.8.13", "@types/react@^16.8.2": +"@types/react@*": + version "16.9.32" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.32.tgz#f6368625b224604148d1ddf5920e4fefbd98d383" + integrity sha512-fmejdp0CTH00mOJmxUPPbWCEBWPvRIL4m8r0qD+BSDUqmutPyGQCHifzMpMzdvZwROdEdL78IuZItntFWgPXHQ== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + +"@types/react@^16.8.13", "@types/react@^16.8.2": version "16.9.17" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.17.tgz#58f0cc0e9ec2425d1441dd7b623421a867aa253e" integrity sha512-UP27In4fp4sWF5JgyV6pwVPAQM83Fj76JOcg02X5BZcpSu5Wx+fP9RMqc2v0ssBoQIFvD5JdKY41gjJJKmw6Bg== @@ -3880,9 +3895,9 @@ cliui@^6.0.0: wrap-ansi "^6.2.0" clsx@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" - integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" + integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA== co@^4.6.0: version "4.6.0" @@ -4328,11 +4343,11 @@ css-vendor@^0.3.8: is-in-browser "^1.0.2" css-vendor@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.7.tgz#4e6d53d953c187981576d6a542acc9fb57174bda" - integrity sha512-VS9Rjt79+p7M0WkPqcAza4Yq1ZHrsHrwf7hPL/bjQB+c1lwmAI+1FXxYTYt818D/50fFVflw0XKleiBN5RITkg== + version "2.0.8" + resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d" + integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ== dependencies: - "@babel/runtime" "^7.6.2" + "@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" css-what@2.1: @@ -4363,9 +4378,9 @@ cssstyle@^2.0.0: cssom "~0.3.6" csstype@^2.2.0, csstype@^2.5.2, csstype@^2.6.5, csstype@^2.6.7: - version "2.6.8" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.8.tgz#0fb6fc2417ffd2816a418c9336da74d7f07db431" - integrity sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA== + version "2.6.10" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b" + integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w== cyclist@^1.0.1: version "1.0.1" @@ -4684,11 +4699,11 @@ doctrine@^3.0.0: esutils "^2.0.2" dom-helpers@^5.0.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821" - integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw== + version "5.1.4" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.4.tgz#4609680ab5c79a45f2531441f1949b79d6587f4b" + integrity sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A== dependencies: - "@babel/runtime" "^7.6.3" + "@babel/runtime" "^7.8.7" csstype "^2.6.7" dom-serializer@0, dom-serializer@^0.2.1: @@ -7635,63 +7650,63 @@ jss-nested@^6.0.1: warning "^3.0.0" jss-plugin-camel-case@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.4.tgz#3dedecec1e5bba0bf6141c2c05e2ab11ea4b468d" - integrity sha512-+wnqxJsyfUnOn0LxVg3GgZBSjfBCrjxwx7LFxwVTUih0ceGaXKZoieheNOaTo5EM4w8bt1nbb8XonpQCj67C6A== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.1.1.tgz#8e73ecc4f1d0f8dfe4dd31f6f9f2782588970e78" + integrity sha512-MDIaw8FeD5uFz1seQBKz4pnvDLnj5vIKV5hXSVdMaAVq13xR6SVTVWkIV/keyTs5txxTvzGJ9hXoxgd1WTUlBw== dependencies: "@babel/runtime" "^7.3.1" hyphenate-style-name "^1.0.3" - jss "10.0.4" + jss "10.1.1" jss-plugin-default-unit@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.4.tgz#df03885de20f20a1fc1c21bdb7c62e865ee400d9" - integrity sha512-T0mhL/Ogp/quvod/jAHEqKvptLDxq7Cj3a+7zRuqK8HxUYkftptN89wJElZC3rshhNKiogkEYhCWenpJdFvTBg== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.1.1.tgz#2df86016dfe73085eead843f5794e3890e9c5c47" + integrity sha512-UkeVCA/b3QEA4k0nIKS4uWXDCNmV73WLHdh2oDGZZc3GsQtlOCuiH3EkB/qI60v2MiCq356/SYWsDXt21yjwdg== dependencies: "@babel/runtime" "^7.3.1" - jss "10.0.4" + jss "10.1.1" jss-plugin-global@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.0.4.tgz#412245b56133cc88bec654a70d82d5922619f4c5" - integrity sha512-N8n9/GHENZce+sqE4UYiZiJtI+t+erT/BypHOrNYAfIoNEj7OYsOEKfIo2P0GpLB3QyDAYf5eo9XNdZ8veEkUA== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.1.1.tgz#36b0d6d9facb74dfd99590643708a89260747d14" + integrity sha512-VBG3wRyi3Z8S4kMhm8rZV6caYBegsk+QnQZSVmrWw6GVOT/Z4FA7eyMu5SdkorDlG/HVpHh91oFN56O4R9m2VA== dependencies: "@babel/runtime" "^7.3.1" - jss "10.0.4" + jss "10.1.1" jss-plugin-nested@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.0.4.tgz#4d15ad13995fb6e4125618006473a096d2475d75" - integrity sha512-QM21BKVt8LDeoRfowvAMh/s+/89VYrreIIE6ch4pvw0oAXDWw1iorUPlqLZ7uCO3UL0uFtQhJq3QMLN6Lr1v0A== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.1.1.tgz#5c3de2b8bda344de1ebcef3a4fd30870a29a8a8c" + integrity sha512-ozEu7ZBSVrMYxSDplPX3H82XHNQk2DQEJ9TEyo7OVTPJ1hEieqjDFiOQOxXEj9z3PMqkylnUbvWIZRDKCFYw5Q== dependencies: "@babel/runtime" "^7.3.1" - jss "10.0.4" + jss "10.1.1" tiny-warning "^1.0.2" jss-plugin-props-sort@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.4.tgz#43c880ff8dfcf858f809f663ece5e65a1d945b5a" - integrity sha512-WoETdOCjGskuin/OMt2uEdDPLZF3vfQuHXF+XUHGJrq0BAapoyGQDcv37SeReDlkRAbVXkEZPsIMvYrgHSHFiA== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.1.1.tgz#34bddcbfaf9430ec8ccdf92729f03bb10caf1785" + integrity sha512-g/joK3eTDZB4pkqpZB38257yD4LXB0X15jxtZAGbUzcKAVUHPl9Jb47Y7lYmiGsShiV4YmQRqG1p2DHMYoK91g== dependencies: "@babel/runtime" "^7.3.1" - jss "10.0.4" + jss "10.1.1" jss-plugin-rule-value-function@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.4.tgz#2f4cf4a86ad3eba875bb48cb9f4a7ed35cb354e7" - integrity sha512-0hrzOSWRF5ABJGaHrlnHbYZjU877Ofzfh2id3uLtBvemGQLHI+ldoL8/+6iPSRa7M8z8Ngfg2vfYhKjUA5gA0g== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.1.1.tgz#be00dac6fc394aaddbcef5860b9eca6224d96382" + integrity sha512-ClV1lvJ3laU9la1CUzaDugEcwnpjPTuJ0yGy2YtcU+gG/w9HMInD5vEv7xKAz53Bk4WiJm5uLOElSEshHyhKNw== dependencies: "@babel/runtime" "^7.3.1" - jss "10.0.4" + jss "10.1.1" jss-plugin-vendor-prefixer@^10.0.3: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.4.tgz#1626ef612a4541cff17cf96815e1740155214ed2" - integrity sha512-4JgEbcrdeMda1qvxTm1CnxFJAWVV++VLpP46HNTrfH7VhVlvUpihnUNs2gAlKuRT/XSBuiWeLAkrTqF4NVrPig== + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.1.1.tgz#8348b20749f790beebab3b6a8f7075b07c2cfcfd" + integrity sha512-09MZpQ6onQrhaVSF6GHC4iYifQ7+4YC/tAP6D4ZWeZotvCMq1mHLqNKRIaqQ2lkgANjlEot2JnVi1ktu4+L4pw== dependencies: "@babel/runtime" "^7.3.1" css-vendor "^2.0.7" - jss "10.0.4" + jss "10.1.1" jss-preset-default@^4.3.0: version "4.5.0" @@ -7735,17 +7750,17 @@ jss-vendor-prefixer@^7.0.0: dependencies: css-vendor "^0.3.8" -jss@10.0.4: - version "10.0.4" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.4.tgz#46ebdde1c40c9a079d64f3334cb88ae28fd90bfd" - integrity sha512-GqHmeDK83qbqMAVjxyPfN1qJVTKZne533a9bdCrllZukUM8npG/k+JumEPI86IIB5ifaZAHG2HAsUziyxOiooQ== +jss@10.1.1, jss@^10.0.3: + version "10.1.1" + resolved "https://registry.yarnpkg.com/jss/-/jss-10.1.1.tgz#450b27d53761af3e500b43130a54cdbe157ea332" + integrity sha512-Xz3qgRUFlxbWk1czCZibUJqhVPObrZHxY3FPsjCXhDld4NOj1BgM14Ir5hVm+Qr6OLqVljjGvoMcCdXNOAbdkQ== dependencies: "@babel/runtime" "^7.3.1" csstype "^2.6.5" is-in-browser "^1.1.3" tiny-warning "^1.0.2" -jss@^10.0.0, jss@^10.0.3: +jss@^10.0.0: version "10.0.3" resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.3.tgz#5c160f96aa8ce8b9f851ee0b33505dcd37f490a4" integrity sha512-AcDvFdOk16If9qvC9KN3oFXsrkHWM9+TaPMpVB9orm3z+nq1Xw3ofHyflRe/mkSucRZnaQtlhZs1hdP3DR9uRw== @@ -9474,9 +9489,9 @@ pn@^1.1.0: integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== popper.js@^1.14.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3" - integrity sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw== + version "1.16.1" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" + integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== posix-character-classes@^0.1.0: version "0.1.1" @@ -9899,11 +9914,16 @@ react-is@16.6.3: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0" integrity sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA== -react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.12.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== +react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-jss@^8.6.1: version "8.6.1" resolved "https://registry.yarnpkg.com/react-jss/-/react-jss-8.6.1.tgz#a06e2e1d2c4d91b4d11befda865e6c07fbd75252" @@ -10114,12 +10134,12 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== -regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.3: +regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.3: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== -regenerator-runtime@^0.13.4: +regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== From 9a2a75f55a03d4718f2c0f9312a7b6d6e420cb12 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 6 Apr 2020 11:45:17 +0300 Subject: [PATCH 58/72] Use new TextField `focused` prop for highlighting --- docs/layout/PageWithContext.tsx | 10 +- docs/prop-types.json | 120 ++---------------- lib/src/DateRangePicker/DateRangePicker.tsx | 11 +- .../DateRangePicker/DateRangePickerInput.tsx | 7 +- .../DateRangePickerToolbar.tsx | 4 +- lib/src/DateRangePicker/RangeTypes.ts | 2 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 3 + lib/src/wrappers/DesktopWrapper.tsx | 5 + lib/src/wrappers/ResponsiveWrapper.tsx | 5 +- yarn.lock | 88 +++++++------ 10 files changed, 88 insertions(+), 167 deletions(-) diff --git a/docs/layout/PageWithContext.tsx b/docs/layout/PageWithContext.tsx index 4a1e8d81f..a7b0bc113 100644 --- a/docs/layout/PageWithContext.tsx +++ b/docs/layout/PageWithContext.tsx @@ -9,9 +9,15 @@ import { PageContext } from '../utils/getPageContext'; import { LocalizationProvider } from '@material-ui/pickers'; import { UtilsContext } from '../_shared/UtilsServiceContext'; import { NotificationManager } from 'utils/NotificationManager'; -import { Theme, createMuiTheme, CssBaseline } from '@material-ui/core'; import { createUtilsService, UtilsLib, utilsMap } from '../utils/utilsService'; -import { ThemeProvider, jssPreset, StylesProvider } from '@material-ui/core/styles'; +import { + Theme, + createMuiTheme, + CssBaseline, + ThemeProvider, + jssPreset, + StylesProvider, +} from '@material-ui/core'; export type ThemeType = 'light' | 'dark'; export type Direction = Theme['direction']; diff --git a/docs/prop-types.json b/docs/prop-types.json index f9c9d9a0b..0f8722a8f 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -1043,19 +1043,6 @@ "name": "Partial" } }, - "TransitionComponent": { - "defaultValue": null, - "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", - "name": "TransitionComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -1071,19 +1058,6 @@ "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, - "PopperProps": { - "defaultValue": null, - "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", - "name": "PopperProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -1804,19 +1778,6 @@ "name": "Partial" } }, - "TransitionComponent": { - "defaultValue": null, - "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", - "name": "TransitionComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -1832,19 +1793,6 @@ "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, - "PopperProps": { - "defaultValue": null, - "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", - "name": "PopperProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -2889,19 +2837,6 @@ "name": "Partial" } }, - "TransitionComponent": { - "defaultValue": null, - "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", - "name": "TransitionComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -2917,19 +2852,6 @@ "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, - "PopperProps": { - "defaultValue": null, - "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", - "name": "PopperProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -3365,17 +3287,17 @@ "name": "boolean" } }, - "inputFormat": { + "onAccept": { "defaultValue": null, - "description": "Format string", - "name": "inputFormat", + "description": "Callback fired when date is accepted", + "name": "onAccept", "parent": { "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, "required": false, "type": { - "name": "string" + "name": "((date: DateIOType) => void) & ((date: DateRange) => void)" } }, "disabled": { @@ -3404,17 +3326,17 @@ "name": "boolean" } }, - "onAccept": { + "inputFormat": { "defaultValue": null, - "description": "Callback fired when date is accepted", - "name": "onAccept", + "description": "Format string", + "name": "inputFormat", "parent": { "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, "required": false, "type": { - "name": "((date: DateIOType) => void) & ((date: DateRange) => void)" + "name": "string" } }, "autoOk": { @@ -3906,19 +3828,6 @@ "name": "Partial" } }, - "TransitionComponent": { - "defaultValue": null, - "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", - "name": "TransitionComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" @@ -3933,19 +3842,6 @@ "type": { "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } - }, - "PopperProps": { - "defaultValue": null, - "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", - "name": "PopperProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } } }, "Calendar": { diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 9ee409b28..38bd454f2 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -71,8 +71,8 @@ export function makeRangePicker(Wrapper: TWrapper) }: DateRangePickerProps & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); const [currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd] = React.useState< - 'start' | 'end' - >('start'); + 'start' | 'end' | null + >(null); const pickerStateProps = { ...restPropsForTextField, @@ -93,6 +93,7 @@ export function makeRangePicker(Wrapper: TWrapper) const DateInputProps = { ...inputProps, + ...restPropsForTextField, currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd, startText, @@ -100,11 +101,7 @@ export function makeRangePicker(Wrapper: TWrapper) }; return ( - + = ({ openPicker={() => {}} readOnly={readOnly} label={startText} + focused={open && currentlySelectingRangeEnd === 'start'} onClick={ readOnly ? createDelegatedEventHandler(openRangeStartSelection, onClick) : undefined } onFocus={ !readOnly ? createDelegatedEventHandler(openRangeStartSelection, onFocus) : undefined } - className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'start' })} /> {toText} @@ -149,11 +146,11 @@ export const DateRangePickerInput: React.FC = ({ openPicker={() => {}} readOnly={readOnly} label={endText} + focused={open && currentlySelectingRangeEnd === 'end'} onClick={readOnly ? createDelegatedEventHandler(openRangeEndSelection, onClick) : undefined} onFocus={ !readOnly ? createDelegatedEventHandler(openRangeEndSelection, onFocus) : undefined } - className={clsx({ [classes.highlighted]: currentlySelectingRangeEnd === 'end' })} />
); diff --git a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx index 58d425c0f..2dae52594 100644 --- a/lib/src/DateRangePicker/DateRangePickerToolbar.tsx +++ b/lib/src/DateRangePicker/DateRangePickerToolbar.tsx @@ -65,14 +65,14 @@ export const DateRangePickerToolbar: React.FC = ({ >
setCurrentlySelectingRangeEnd('start')} />  {'–'}  setCurrentlySelectingRangeEnd('end')} diff --git a/lib/src/DateRangePicker/RangeTypes.ts b/lib/src/DateRangePicker/RangeTypes.ts index 5a39025e3..c9d467bd1 100644 --- a/lib/src/DateRangePicker/RangeTypes.ts +++ b/lib/src/DateRangePicker/RangeTypes.ts @@ -5,6 +5,6 @@ export type RangeInput = [ParsableDate, ParsableDate]; export type DateRange = [MaterialUiPickersDate, MaterialUiPickersDate]; export interface CurrentlySelectingRangeEndProps { - currentlySelectingRangeEnd: 'start' | 'end'; + currentlySelectingRangeEnd: 'start' | 'end' | null; setCurrentlySelectingRangeEnd: (newSelectingEnd: 'start' | 'end') => void; } diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index c7aabcf0e..8aa279ba2 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -19,6 +19,8 @@ export interface InnerDesktopPopperWrapperProps { PopperProps?: Partial; /** Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop) */ TransitionComponent?: React.ComponentType; + // required for spreading + PopoverProps: any; } export interface DesktopPopperWrapperProps @@ -46,6 +48,7 @@ export const DesktopPopperWrapper: React.FC = ({ wider, children, PopperProps, + PopoverProps, onClear, onDismiss, onSetToday, diff --git a/lib/src/wrappers/DesktopWrapper.tsx b/lib/src/wrappers/DesktopWrapper.tsx index 45e630eb4..738f60b27 100644 --- a/lib/src/wrappers/DesktopWrapper.tsx +++ b/lib/src/wrappers/DesktopWrapper.tsx @@ -10,6 +10,9 @@ import { WrapperVariantContext } from './WrapperVariantContext'; export interface InnerDesktopWrapperProps { /** Popover props passed to material-ui Popover */ PopoverProps?: Partial; + // required for spreading + PopperProps: any; + TransitionComponent: any; } export interface DesktopWrapperProps @@ -33,6 +36,8 @@ export const DesktopWrapper: React.FC = ({ wider, children, PopoverProps, + PopperProps, + TransitionComponent, onClear, onDismiss, onSetToday, diff --git a/lib/src/wrappers/ResponsiveWrapper.tsx b/lib/src/wrappers/ResponsiveWrapper.tsx index 6a2e713a3..e50872fa3 100644 --- a/lib/src/wrappers/ResponsiveWrapper.tsx +++ b/lib/src/wrappers/ResponsiveWrapper.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import useMediaQuery from '@material-ui/core/useMediaQuery'; -import { Theme } from '@material-ui/core/styles'; +import { Theme, useTheme } from '@material-ui/core/styles'; import { MobileWrapperProps, MobileWrapper } from './MobileWrapper'; import { DesktopWrapperProps, DesktopWrapper } from './DesktopWrapper'; import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; @@ -34,7 +34,8 @@ export const makeResponsiveWrapper = ( TransitionComponent, ...other }) => { - const isDesktop = useMediaQuery(theme => theme.breakpoints.up(desktopModeBreakpoint)); + const theme = useTheme(); + const isDesktop = useMediaQuery(theme.breakpoints.up(desktopModeBreakpoint)); return isDesktop ? ( Date: Mon, 6 Apr 2020 12:27:24 +0300 Subject: [PATCH 59/72] Close picker after range selected --- .../CalendarsDateRangePicker.example.tsx | 6 ++--- docs/prop-types.json | 16 ++++++------- lib/.size-snapshot.json | 24 +++++++++---------- lib/rollup.config.js | 2 +- lib/src/DateRangePicker/DateRangePicker.tsx | 4 ++-- .../DateRangePicker/DateRangePickerView.tsx | 9 ++++++- lib/src/DateRangePicker/RangeTypes.ts | 2 +- lib/src/_shared/KeyboardDateInput.tsx | 11 +++------ lib/src/wrappers/DesktopPopperWrapper.tsx | 2 +- lib/src/wrappers/DesktopWrapper.tsx | 4 ++-- lib/src/wrappers/ResponsiveWrapper.tsx | 3 ++- 11 files changed, 43 insertions(+), 40 deletions(-) diff --git a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx index 89d11a546..710a90525 100644 --- a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx +++ b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx @@ -7,19 +7,19 @@ function CalendarsDateRangePicker() { return ( - 1 calendar + 1 calendar handleDateChange(date)} /> - 2 calendars + 2 calendars handleDateChange(date)} /> - 3 calendars + 3 calendars void) & ((date: DateRange) => void)" + "name": "string" } }, "disabled": { @@ -3326,17 +3326,17 @@ "name": "boolean" } }, - "inputFormat": { + "onAccept": { "defaultValue": null, - "description": "Format string", - "name": "inputFormat", + "description": "Callback fired when date is accepted", + "name": "onAccept", "parent": { "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, "required": false, "type": { - "name": "string" + "name": "((date: DateIOType) => void) & ((date: DateRange) => void)" } }, "autoOk": { diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index 51ba6dc9c..c021aa065 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,26 +1,26 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 187431, - "minified": 101737, - "gzipped": 26547, + "bundled": 189586, + "minified": 102785, + "gzipped": 26591, "treeshaked": { "rollup": { - "code": 84511, - "import_statements": 2188 + "code": 85183, + "import_statements": 2109 }, "webpack": { - "code": 93573 + "code": 94264 } } }, "build/dist/material-ui-pickers.umd.js": { - "bundled": 304025, - "minified": 120648, - "gzipped": 34030 + "bundled": 299705, + "minified": 118298, + "gzipped": 33596 }, "build/dist/material-ui-pickers.umd.min.js": { - "bundled": 257625, - "minified": 108854, - "gzipped": 30652 + "bundled": 258475, + "minified": 109200, + "gzipped": 30848 } } diff --git a/lib/rollup.config.js b/lib/rollup.config.js index 9fe6f3da7..256f87aac 100644 --- a/lib/rollup.config.js +++ b/lib/rollup.config.js @@ -26,7 +26,7 @@ const globals = { '@material-ui/core/Grid': 'material-ui.Grid', '@material-ui/core/IconButton': 'material-ui.IconButton', '@material-ui/core/InputAdornment': 'material-ui.InputAdornment', - '@material-ui/core/internal/svg-icons/createSvgIcon': 'material-ui.createSvgIcon', + '@material-ui/core/utils/createSvgIcon': 'material-ui.createSvgIcon', '@material-ui/core/Paper': 'material-ui.Paper', '@material-ui/core/Popover': 'material-ui.Popover', '@material-ui/core/styles': 'material-ui', diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 38bd454f2..1dd04027e 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -71,8 +71,8 @@ export function makeRangePicker(Wrapper: TWrapper) }: DateRangePickerProps & AllSharedPickerProps & ExtendWrapper) { const utils = useUtils(); const [currentlySelectingRangeEnd, setCurrentlySelectingRangeEnd] = React.useState< - 'start' | 'end' | null - >(null); + 'start' | 'end' + >('start'); const pickerStateProps = { ...restPropsForTextField, diff --git a/lib/src/DateRangePicker/DateRangePickerView.tsx b/lib/src/DateRangePicker/DateRangePickerView.tsx index d66a8d4a1..b23065be5 100644 --- a/lib/src/DateRangePicker/DateRangePickerView.tsx +++ b/lib/src/DateRangePicker/DateRangePickerView.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { isRangeValid } from '../_helpers/date-utils'; import { MaterialUiPickersDate } from '../typings/date'; import { BasePickerProps } from '../typings/BasePicker'; import { calculateRangeChange } from './date-range-manager'; @@ -8,6 +9,7 @@ import { SharedPickerProps } from '../Picker/SharedPickerProps'; import { DateRangePickerToolbar } from './DateRangePickerToolbar'; import { useParsedDate } from '../_shared/hooks/date-helpers-hooks'; import { useCalendarState } from '../views/Calendar/useCalendarState'; +import { FORCE_FINISH_PICKER } from '../_shared/hooks/usePickerState'; import { DateRangePickerViewMobile } from './DateRangePickerViewMobile'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; import { MobileKeyboardInputView } from '../views/MobileKeyboardInputView'; @@ -135,7 +137,10 @@ export const DateRangePickerView: React.FC = ({ }); setCurrentlySelectingRangeEnd(nextSelection); - onDateChange(newRange, wrapperVariant, false); + + const isFullRangeSelected = + currentlySelectingRangeEnd === 'end' && isRangeValid(utils, newRange); + onDateChange(newRange, wrapperVariant, isFullRangeSelected ? FORCE_FINISH_PICKER : true); }, [ currentlySelectingRangeEnd, @@ -196,6 +201,8 @@ export const DateRangePickerView: React.FC = ({ void; } diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index e24d52ece..185005236 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -6,6 +6,7 @@ import { Rifm } from 'rifm'; import { useUtils } from './hooks/useUtils'; import { DateInputProps } from './PureDateInput'; import { KeyboardIcon } from './icons/KeyboardIcon'; +import { createDelegatedEventHandler } from '../_helpers/utils'; import { maskedDateFormatter, getDisplayDate, @@ -139,14 +140,8 @@ export const KeyboardDateInput: React.FC = ({ value={innerInputValue || ''} onChange={e => handleChange(e.currentTarget.value)} {...inputProps} - onFocus={e => { - setIsFocused(true); - onFocus && onFocus(e); - }} - onBlur={e => { - setIsFocused(false); - onBlur && onBlur(e); - }} + onFocus={createDelegatedEventHandler(() => setIsFocused(true), onFocus)} + onBlur={createDelegatedEventHandler(() => setIsFocused(true), onBlur)} /> ); } diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 8aa279ba2..daa3fff6d 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -20,7 +20,7 @@ export interface InnerDesktopPopperWrapperProps { /** Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop) */ TransitionComponent?: React.ComponentType; // required for spreading - PopoverProps: any; + PopoverProps?: any; } export interface DesktopPopperWrapperProps diff --git a/lib/src/wrappers/DesktopWrapper.tsx b/lib/src/wrappers/DesktopWrapper.tsx index 738f60b27..ffd80210f 100644 --- a/lib/src/wrappers/DesktopWrapper.tsx +++ b/lib/src/wrappers/DesktopWrapper.tsx @@ -11,8 +11,8 @@ export interface InnerDesktopWrapperProps { /** Popover props passed to material-ui Popover */ PopoverProps?: Partial; // required for spreading - PopperProps: any; - TransitionComponent: any; + PopperProps?: any; + TransitionComponent?: any; } export interface DesktopWrapperProps diff --git a/lib/src/wrappers/ResponsiveWrapper.tsx b/lib/src/wrappers/ResponsiveWrapper.tsx index e50872fa3..ba98059e7 100644 --- a/lib/src/wrappers/ResponsiveWrapper.tsx +++ b/lib/src/wrappers/ResponsiveWrapper.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; import useMediaQuery from '@material-ui/core/useMediaQuery'; -import { Theme, useTheme } from '@material-ui/core/styles'; +import { useTheme } from '@material-ui/core/styles'; import { MobileWrapperProps, MobileWrapper } from './MobileWrapper'; import { DesktopWrapperProps, DesktopWrapper } from './DesktopWrapper'; import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; import { DesktopPopperWrapperProps, DesktopPopperWrapper } from './DesktopPopperWrapper'; +// @ts-ignore TODO remove when fully move to Popper based pickers export interface ResponsiveWrapperProps extends DesktopWrapperProps, DesktopPopperWrapperProps, From eadb5f0b80f0dbb33302ebce820a143a7b2064bf Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 6 Apr 2020 12:57:39 +0300 Subject: [PATCH 60/72] Update jss version --- docs/package.json | 1 + e2e/integration/DateRange.spec.ts | 43 ++++++++++++------- lib/src/DateRangePicker/date-range-manager.ts | 2 +- package.json | 1 + yarn.lock | 30 ++++++++----- 5 files changed, 50 insertions(+), 27 deletions(-) diff --git a/docs/package.json b/docs/package.json index 8ccdaffe6..bbd88b9f1 100644 --- a/docs/package.json +++ b/docs/package.json @@ -26,6 +26,7 @@ "@material-ui/pickers": "^4.0.0-alpha.1", "@types/fuzzy-search": "^2.1.0", "@types/isomorphic-fetch": "^0.0.35", + "@types/jss": "^10.0.0", "@types/luxon": "^1.11.0", "@types/next": "^8.0.1", "@types/prismjs": "^1.9.1", diff --git a/e2e/integration/DateRange.spec.ts b/e2e/integration/DateRange.spec.ts index 3eb9e7600..f1eba60fc 100644 --- a/e2e/integration/DateRange.spec.ts +++ b/e2e/integration/DateRange.spec.ts @@ -37,7 +37,29 @@ describe('DateRangePicker', () => { cy.get('[aria-label="Jan 24, 2019"').trigger('mouseover'); }); - it.only('Allows pure keyboard input control', () => { + it('Properly handles selection when starting from end', () => { + cy.get('#desktop-range-picker input') + .first() + .clear(); + + cy.get('#desktop-range-picker input') + .eq(1) + .focus(); + + cy.get('[aria-label="Jan 30, 2019"]') + .first() + .click(); + cy.get('[aria-label="Jan 19, 2019"]').click(); + + cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 12); + + cy.get('[aria-label="Jan 24, 2019"]') + .first() + .click(); + cy.get('div[role="tooltip"]').should('not.be.visible'); + }); + + it('Allows pure keyboard input control', () => { cy.get('#desktop-range-picker input') .eq(0) .clear() @@ -58,16 +80,15 @@ describe('DateRangePicker', () => { cy.get('[data-mui-test="DateRangeHighlight"]').should('have.length', 39); }); - it('Scrolls current month to the active selection on focusing start field', () => { + it('Scrolls current month to the active selection on focusing appropriate field', () => { cy.get('#desktop-range-picker input') .first() .click(); cy.get('[aria-label="Jan 19, 2019"]').click(); - cy.get('[aria-label="Feb 19, 2019"]').click(); - cy.get('[data-mui-test="previous-arrow-button"]') - .eq(0) + cy.get('[data-mui-test="next-arrow-button"]') + .eq(1) .click() .click(); @@ -78,7 +99,7 @@ describe('DateRangePicker', () => { cy.contains('January 2019'); }); - it('Scrolls current month to the active selection on focusing end field', () => { + it('Opens on the current selecting range end', () => { cy.get('#desktop-range-picker input') .first() .click(); @@ -90,15 +111,7 @@ describe('DateRangePicker', () => { cy.get('[aria-label="Mar 19, 2019"]').click(); - cy.get('[data-mui-test="previous-arrow-button"]') - .eq(0) - .click() - .click(); - - cy.get('#desktop-range-picker input') - .eq(0) - .click(); - + // reopen picker cy.get('#desktop-range-picker input') .eq(1) .click(); diff --git a/lib/src/DateRangePicker/date-range-manager.ts b/lib/src/DateRangePicker/date-range-manager.ts index fb77f0eb4..689b59527 100644 --- a/lib/src/DateRangePicker/date-range-manager.ts +++ b/lib/src/DateRangePicker/date-range-manager.ts @@ -24,7 +24,7 @@ export function calculateRangeChange({ } else { return Boolean(start) && utils.isBefore(selectedDate, start) ? { nextSelection: 'end', newRange: [selectedDate, null] } - : { nextSelection: 'end', newRange: [start, selectedDate] }; + : { nextSelection: 'start', newRange: [start, selectedDate] }; } } diff --git a/package.json b/package.json index df5325bde..39ecaec23 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "husky": "^4.2.3", "lint-staged": "^10.0.8", "prettier": "^1.14.3", + "ts-loader": "^6.2.2", "wait-on": "^4.0.0" }, "husky": { diff --git a/yarn.lock b/yarn.lock index f1d993330..921d227d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2100,6 +2100,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== +"@types/jss@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@types/jss/-/jss-10.0.0.tgz#bea379e2b64d0f0f0f9e9093471036643608c676" + integrity sha512-Obo9w999hf2Q4sU/MRT7iR1UazdvFK3pEdtB6BSfO0NbmDrVMQi+RgNts4DLmlFho5Uf1PG4cMKLT8POhb6utA== + dependencies: + jss "*" + "@types/luxon@^1.11.0": version "1.22.0" resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.22.0.tgz#dbdf2cc7ba3dfce98c57a3f0e003791122cba009" @@ -7756,7 +7763,7 @@ jss-vendor-prefixer@^7.0.0: dependencies: css-vendor "^0.3.8" -jss@10.1.1, jss@^10.0.3: +jss@*, jss@10.1.1, jss@^10.0.0, jss@^10.0.3: version "10.1.1" resolved "https://registry.yarnpkg.com/jss/-/jss-10.1.1.tgz#450b27d53761af3e500b43130a54cdbe157ea332" integrity sha512-Xz3qgRUFlxbWk1czCZibUJqhVPObrZHxY3FPsjCXhDld4NOj1BgM14Ir5hVm+Qr6OLqVljjGvoMcCdXNOAbdkQ== @@ -7766,16 +7773,6 @@ jss@10.1.1, jss@^10.0.3: is-in-browser "^1.1.3" tiny-warning "^1.0.2" -jss@^10.0.0: - version "10.0.3" - resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.3.tgz#5c160f96aa8ce8b9f851ee0b33505dcd37f490a4" - integrity sha512-AcDvFdOk16If9qvC9KN3oFXsrkHWM9+TaPMpVB9orm3z+nq1Xw3ofHyflRe/mkSucRZnaQtlhZs1hdP3DR9uRw== - dependencies: - "@babel/runtime" "^7.3.1" - csstype "^2.6.5" - is-in-browser "^1.1.3" - tiny-warning "^1.0.2" - jss@^9.7.0: version "9.8.7" resolved "https://registry.yarnpkg.com/jss/-/jss-9.8.7.tgz#ed9763fc0f2f0260fc8260dac657af61e622ce05" @@ -11782,6 +11779,17 @@ ts-loader@^6.0.2: micromatch "^4.0.0" semver "^6.0.0" +ts-loader@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.2.2.tgz#dffa3879b01a1a1e0a4b85e2b8421dc0dfff1c58" + integrity sha512-HDo5kXZCBml3EUPcc7RlZOV/JGlLHwppTLEHb3SHnr5V7NXD4klMEkrhJe5wgRbaWsSXi+Y1SIBN/K9B6zWGWQ== + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^4.0.0" + semver "^6.0.0" + tslib@^1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" From 6aee13e951177e558f8dbb1bca0e6f061c06ecf9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 6 Apr 2020 13:14:09 +0300 Subject: [PATCH 61/72] Add more date-range-manager tests --- .../__tests__/unit/date-range-manager.test.ts | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/src/__tests__/unit/date-range-manager.test.ts b/lib/src/__tests__/unit/date-range-manager.test.ts index 0925c7160..7d2397de9 100644 --- a/lib/src/__tests__/unit/date-range-manager.test.ts +++ b/lib/src/__tests__/unit/date-range-manager.test.ts @@ -1,5 +1,8 @@ import { utilsToUse } from '../test-utils'; -import { calculateRangeChange } from '../../DateRangePicker/date-range-manager'; +import { + calculateRangeChange, + calculateRangePreview, +} from '../../DateRangePicker/date-range-manager'; const start2018 = utilsToUse.date(new Date('2018-01-01T00:00:00.000Z')); const mid2018 = utilsToUse.date(new Date('2018-06-01T00:00:00.000Z')); @@ -10,11 +13,12 @@ test.each` ${[null, null]} | ${'start'} | ${start2018} | ${[start2018, null]} | ${'end'} ${[start2018, null]} | ${'start'} | ${end2019} | ${[end2019, null]} | ${'end'} ${[null, end2019]} | ${'start'} | ${mid2018} | ${[mid2018, end2019]} | ${'end'} + ${[null, end2019]} | ${'end'} | ${mid2018} | ${[null, mid2018]} | ${'start'} ${[mid2018, null]} | ${'start'} | ${start2018} | ${[start2018, null]} | ${'end'} ${[start2018, end2019]} | ${'start'} | ${mid2018} | ${[mid2018, end2019]} | ${'end'} - ${[start2018, end2019]} | ${'end'} | ${mid2018} | ${[start2018, mid2018]} | ${'end'} + ${[start2018, end2019]} | ${'end'} | ${mid2018} | ${[start2018, mid2018]} | ${'start'} ${[mid2018, end2019]} | ${'start'} | ${start2018} | ${[start2018, end2019]} | ${'end'} - ${[start2018, mid2018]} | ${'end'} | ${mid2018} | ${[start2018, mid2018]} | ${'end'} + ${[start2018, mid2018]} | ${'end'} | ${mid2018} | ${[start2018, mid2018]} | ${'start'} `( 'calculateRangeChange should return $expectedRange when selecting $selectingEnd of $range with user input $newDate', ({ range, selectingEnd, newDate, expectedRange, expectedNextSelection }) => { @@ -31,3 +35,27 @@ test.each` }); } ); + +test.each` + range | selectingEnd | newDate | expectedRange + ${[start2018, end2019]} | ${'start'} | ${null} | ${[null, null]} + ${[null, null]} | ${'start'} | ${start2018} | ${[start2018, null]} + ${[start2018, null]} | ${'start'} | ${end2019} | ${[end2019, null]} + ${[null, end2019]} | ${'start'} | ${mid2018} | ${[mid2018, end2019]} + ${[null, end2019]} | ${'end'} | ${mid2018} | ${[null, mid2018]} + ${[mid2018, null]} | ${'start'} | ${start2018} | ${[start2018, null]} + ${[mid2018, end2019]} | ${'start'} | ${start2018} | ${[start2018, mid2018]} + ${[start2018, mid2018]} | ${'end'} | ${end2019} | ${[mid2018, end2019]} +`( + 'calculateRangePreview should return $expectedRange when selecting $selectingEnd of $range when user hover $newDate', + ({ range, selectingEnd, newDate, expectedRange }) => { + expect( + calculateRangePreview({ + utils: utilsToUse, + range, + newDate, + currentlySelectingRangeEnd: selectingEnd, + }) + ).toEqual(expectedRange); + } +); From 9fa0a0a30ff2fc7827d98d92e8754a19d6898d9a Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 6 Apr 2020 13:48:37 +0300 Subject: [PATCH 62/72] More examples and possibility to change wrapper mode for static wrapper --- .../datepicker/StaticDatePicker.example.jsx | 8 ++++++ .../MinMaxDateRangePicker.example.tsx | 18 ++++-------- .../ResponsiveDateRangePicker.example.tsx | 24 ++++++++++++++++ .../StaticDateRangePicker.example.tsx | 24 ++++++++++++++++ docs/pages/demo/daterangepicker/index.mdx | 28 ++++++++++++++++--- lib/src/DateRangePicker/DateRangePicker.tsx | 6 +++- lib/src/wrappers/StaticWrapper.tsx | 15 ++++++++-- lib/src/wrappers/Wrapper.tsx | 12 ++++++-- lib/src/wrappers/makeWrapperComponent.tsx | 5 +++- 9 files changed, 116 insertions(+), 24 deletions(-) create mode 100644 docs/pages/demo/daterangepicker/ResponsiveDateRangePicker.example.tsx create mode 100644 docs/pages/demo/daterangepicker/StaticDateRangePicker.example.tsx diff --git a/docs/pages/demo/datepicker/StaticDatePicker.example.jsx b/docs/pages/demo/datepicker/StaticDatePicker.example.jsx index 41d5442e2..e68a8611d 100644 --- a/docs/pages/demo/datepicker/StaticDatePicker.example.jsx +++ b/docs/pages/demo/datepicker/StaticDatePicker.example.jsx @@ -1,5 +1,12 @@ import React, { useState } from 'react'; +import isWeekend from 'date-fns/isWeekend'; import { StaticDatePicker } from '@material-ui/pickers'; +import { makeJSDateObject } from '../../../utils/helpers'; + +function disableWeekends(date) { + // TODO: replace with implementation for your date library + return isWeekend(makeJSDateObject(date)); +} const StaticDatePickerExample = () => { const [date, handleDateChange] = useState(new Date()); @@ -18,6 +25,7 @@ const StaticDatePickerExample = () => { orientation="landscape" openTo="date" value={date} + shouldDisableDate={disableWeekends} onChange={date => handleDateChange(date)} /> diff --git a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx index 32ab72613..42402d553 100644 --- a/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx +++ b/docs/pages/demo/daterangepicker/MinMaxDateRangePicker.example.tsx @@ -1,32 +1,24 @@ import * as React from 'react'; -import isWeekend from 'date-fns/isWeekend'; +import addWeeks from 'date-fns/addWeeks'; import { Dayjs } from 'dayjs'; import { Moment } from 'moment'; import { DateTime } from 'luxon'; -import { addYears } from 'date-fns'; -// this guy required only on the docs site to work with dynamic date library import { makeJSDateObject } from '../../../utils/helpers'; import { DateRangePicker, DateRange } from '@material-ui/pickers'; -function disableWeekends(date: Moment | DateTime | Dayjs | Date) { +function getWeeksAfter(date: Moment | DateTime | Dayjs | Date, amount: number) { // TODO: replace with implementation for your date library - return isWeekend(makeJSDateObject(date)); -} - -function getOneYearAfter(date: Moment | DateTime | Dayjs | Date) { - // TODO: replace with implementation for your date library - return addYears(makeJSDateObject(date), 1); + return date ? addWeeks(makeJSDateObject(date), amount) : undefined; } function MinMaxDateRangePicker() { - const [selectedRange, handleDateChange] = React.useState([new Date(), null]); + const [selectedRange, handleDateChange] = React.useState([null, null]); return ( handleDateChange(date)} /> ); diff --git a/docs/pages/demo/daterangepicker/ResponsiveDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/ResponsiveDateRangePicker.example.tsx new file mode 100644 index 000000000..d0b95f465 --- /dev/null +++ b/docs/pages/demo/daterangepicker/ResponsiveDateRangePicker.example.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import { MobileDateRangePicker, DesktopDateRangePicker, DateRange } from '@material-ui/pickers'; + +function ResponsiveDateRangePicker() { + const [selectedDate, handleDateChange] = React.useState([null, null]); + + return ( + <> + handleDateChange(date)} + /> + + handleDateChange(date)} + /> + + ); +} + +export default ResponsiveDateRangePicker; diff --git a/docs/pages/demo/daterangepicker/StaticDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/StaticDateRangePicker.example.tsx new file mode 100644 index 000000000..1d3ce1e1d --- /dev/null +++ b/docs/pages/demo/daterangepicker/StaticDateRangePicker.example.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import { StaticDateRangePicker, DateRange } from '@material-ui/pickers'; + +function StaticDateRangePickerExample() { + const [selectedDate, handleDateChange] = React.useState([null, null]); + + return ( + <> + handleDateChange(date)} + /> + + handleDateChange(date)} + /> + + ); +} + +export default StaticDateRangePickerExample; diff --git a/docs/pages/demo/daterangepicker/index.mdx b/docs/pages/demo/daterangepicker/index.mdx index 7f2b566d2..7595c5eb1 100644 --- a/docs/pages/demo/daterangepicker/index.mdx +++ b/docs/pages/demo/daterangepicker/index.mdx @@ -2,10 +2,13 @@ import Ad from '_shared/Ad'; import Example from '_shared/Example'; import PageMeta from '_shared/PageMeta'; import LinkedComponents from '_shared/LinkedComponents'; +import { Hidden } from '@material-ui/core'; import * as BasicDateRangePicker from './BasicDateRangePicker.example'; +import * as ResponsiveDateRangePicker from './ResponsiveDateRangePicker.example'; import * as MinMaxDateRangePicker from './MinMaxDateRangePicker.example'; import * as CalendarsDateRangePicker from './CalendarsDateRangePicker.example'; +import * as StaticDateRangePicker from './StaticDateRangePicker.example'; @@ -17,16 +20,33 @@ import * as CalendarsDateRangePicker from './CalendarsDateRangePicker.example'; #### Basic usage -Basic DateRangePicker example +Basic DateRangePicker example, make sure that you can pass almost any prop of [DatePicker]('/api/DatePicker') - + + +#### Responsiveness + +Date/Time pickers experience is extremely different on mobile and desktop. Here is how components will look on different devices. +The default `DateRangePicker` component is responsive, which means that `Mobile` or `Desktop` mode will be rendered according to device viewport. + + #### Different amount of calendars - +Make sure that `calendars` prop is working only for desktop mode. + + #### Disabling dates Disabling dates performs just like in simple `DatePicker` - + + +#### Static mode + +It is possible to render any picker without modal or popper. For that use `StaticDateRangePicker`. + + + + diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 1dd04027e..0a579fb5c 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -101,7 +101,11 @@ export function makeRangePicker(Wrapper: TWrapper) }; return ( - + { +export interface StaticWrapperProps { + /** + * Force static wrapper inner components to be rendered in mobile or desktop mode + * @default "static" + */ + displayStaticWrapperAs?: 'desktop' | 'mobile' | 'static'; +} + +export const StaticWrapper: React.FC = ({ + displayStaticWrapperAs = 'static', + children, +}) => { const classes = useStyles(); return ( - +
); diff --git a/lib/src/wrappers/Wrapper.tsx b/lib/src/wrappers/Wrapper.tsx index f62444442..0d24ccecb 100644 --- a/lib/src/wrappers/Wrapper.tsx +++ b/lib/src/wrappers/Wrapper.tsx @@ -1,8 +1,9 @@ -import { StaticWrapper } from './StaticWrapper'; import { DateInputProps } from '../_shared/PureDateInput'; +import { StaticWrapper, StaticWrapperProps } from './StaticWrapper'; import { MobileWrapper, MobileWrapperProps } from './MobileWrapper'; import { DesktopWrapper, DesktopWrapperProps } from './DesktopWrapper'; import { ResponsiveWrapper, ResponsiveWrapperProps } from './ResponsiveWrapper'; +import { DesktopPopperWrapper, DesktopPopperWrapperProps } from './DesktopPopperWrapper'; export interface WrapperProps> { open: boolean; @@ -21,16 +22,21 @@ export type SomeWrapper = | typeof ResponsiveWrapper | typeof StaticWrapper | typeof MobileWrapper - | typeof DesktopWrapper; + | typeof DesktopWrapper + | typeof DesktopPopperWrapper; export type ExtendWrapper = TWrapper extends typeof StaticWrapper - ? {} // no additional props + ? StaticWrapperProps : TWrapper extends typeof ResponsiveWrapper ? OmitInnerWrapperProps : TWrapper extends typeof MobileWrapper ? OmitInnerWrapperProps : TWrapper extends typeof DesktopWrapper ? OmitInnerWrapperProps + : TWrapper extends typeof DesktopWrapper + ? OmitInnerWrapperProps + : TWrapper extends typeof DesktopPopperWrapper + ? OmitInnerWrapperProps : never; export function getWrapperVariant(wrapper: SomeWrapper) { diff --git a/lib/src/wrappers/makeWrapperComponent.tsx b/lib/src/wrappers/makeWrapperComponent.tsx index fd1cfaf61..c45efebd2 100644 --- a/lib/src/wrappers/makeWrapperComponent.tsx +++ b/lib/src/wrappers/makeWrapperComponent.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { StaticWrapperProps } from './StaticWrapper'; import { BasePickerProps } from '../typings/BasePicker'; import { DateInputProps } from '../_shared/PureDateInput'; import { ResponsiveWrapperProps } from './ResponsiveWrapper'; @@ -30,7 +31,7 @@ export function makeWrapperComponent< props: Partial> & DateValidationProps & WithWrapperProps & - Partial> + Partial & StaticWrapperProps> ) { const { open, @@ -58,6 +59,7 @@ export function makeWrapperComponent< onClose, onOpen, onError, + displayStaticWrapperAs, strictCompareDates, ...restPropsForTextField } = props; @@ -79,6 +81,7 @@ export function makeWrapperComponent< PureDateInputComponent={PureDateInputComponent} wider={wider} showTabs={showTabs} + displayStaticWrapperAs={displayStaticWrapperAs} {...wrapperProps} {...restPropsForTextField} > From 2e1367025946c91f90f14951522e5b69984df81d Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Mon, 6 Apr 2020 13:58:33 +0300 Subject: [PATCH 63/72] Fix ts wrapper props inferring --- docs/prop-types.json | 393 ------------------------- lib/.size-snapshot.json | 22 +- lib/src/Picker/makePickerWithState.tsx | 4 +- 3 files changed, 13 insertions(+), 406 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index 8c5adac84..7cd22990b 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -927,137 +927,6 @@ "name": "(value: any, utils: MuiPickersAdapter) => string" } }, - "okLabel": { - "defaultValue": { - "value": "\"OK\"" - }, - "description": "\"OK\" label message", - "name": "okLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "cancelLabel": { - "defaultValue": { - "value": "\"CANCEL\"" - }, - "description": "\"CANCEL\" label message", - "name": "cancelLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "clearLabel": { - "defaultValue": { - "value": "\"CLEAR\"" - }, - "description": "\"CLEAR\" label message", - "name": "clearLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "todayLabel": { - "defaultValue": { - "value": "\"TODAY\"" - }, - "description": "\"TODAY\" label message", - "name": "todayLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "showTodayButton": { - "defaultValue": { - "value": "false" - }, - "description": "If true today button will be displayed. **Note** that clear button has higher priority", - "name": "showTodayButton", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "clearable": { - "defaultValue": { - "value": "false" - }, - "description": "Show clear action in picker dialog", - "name": "clearable", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "DialogProps": { - "defaultValue": null, - "description": "Props to be passed directly to material-ui Dialog", - "name": "DialogProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "PopoverProps": { - "defaultValue": null, - "description": "Popover props passed to material-ui Popover", - "name": "PopoverProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", - "name": "InnerDesktopWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "desktopModeBreakpoint": { - "defaultValue": { - "value": "'md'" - }, - "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", - "name": "desktopModeBreakpoint", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", - "name": "ResponsiveWrapperProps" - }, - "required": false, - "type": { - "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" - } - }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -1662,137 +1531,6 @@ "name": "boolean" } }, - "okLabel": { - "defaultValue": { - "value": "\"OK\"" - }, - "description": "\"OK\" label message", - "name": "okLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "cancelLabel": { - "defaultValue": { - "value": "\"CANCEL\"" - }, - "description": "\"CANCEL\" label message", - "name": "cancelLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "clearLabel": { - "defaultValue": { - "value": "\"CLEAR\"" - }, - "description": "\"CLEAR\" label message", - "name": "clearLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "todayLabel": { - "defaultValue": { - "value": "\"TODAY\"" - }, - "description": "\"TODAY\" label message", - "name": "todayLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "showTodayButton": { - "defaultValue": { - "value": "false" - }, - "description": "If true today button will be displayed. **Note** that clear button has higher priority", - "name": "showTodayButton", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "clearable": { - "defaultValue": { - "value": "false" - }, - "description": "Show clear action in picker dialog", - "name": "clearable", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "DialogProps": { - "defaultValue": null, - "description": "Props to be passed directly to material-ui Dialog", - "name": "DialogProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "PopoverProps": { - "defaultValue": null, - "description": "Popover props passed to material-ui Popover", - "name": "PopoverProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", - "name": "InnerDesktopWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "desktopModeBreakpoint": { - "defaultValue": { - "value": "'md'" - }, - "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", - "name": "desktopModeBreakpoint", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", - "name": "ResponsiveWrapperProps" - }, - "required": false, - "type": { - "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" - } - }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", @@ -2721,137 +2459,6 @@ "name": "boolean" } }, - "okLabel": { - "defaultValue": { - "value": "\"OK\"" - }, - "description": "\"OK\" label message", - "name": "okLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "cancelLabel": { - "defaultValue": { - "value": "\"CANCEL\"" - }, - "description": "\"CANCEL\" label message", - "name": "cancelLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "clearLabel": { - "defaultValue": { - "value": "\"CLEAR\"" - }, - "description": "\"CLEAR\" label message", - "name": "clearLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "todayLabel": { - "defaultValue": { - "value": "\"TODAY\"" - }, - "description": "\"TODAY\" label message", - "name": "todayLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "showTodayButton": { - "defaultValue": { - "value": "false" - }, - "description": "If true today button will be displayed. **Note** that clear button has higher priority", - "name": "showTodayButton", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "clearable": { - "defaultValue": { - "value": "false" - }, - "description": "Show clear action in picker dialog", - "name": "clearable", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "DialogProps": { - "defaultValue": null, - "description": "Props to be passed directly to material-ui Dialog", - "name": "DialogProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "PopoverProps": { - "defaultValue": null, - "description": "Popover props passed to material-ui Popover", - "name": "PopoverProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", - "name": "InnerDesktopWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "desktopModeBreakpoint": { - "defaultValue": { - "value": "'md'" - }, - "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", - "name": "desktopModeBreakpoint", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", - "name": "ResponsiveWrapperProps" - }, - "required": false, - "type": { - "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" - } - }, "dateAdapter": { "defaultValue": null, "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index c021aa065..19824edf3 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,26 +1,26 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 189586, - "minified": 102785, - "gzipped": 26591, + "bundled": 189902, + "minified": 102851, + "gzipped": 26620, "treeshaked": { "rollup": { - "code": 85183, + "code": 85313, "import_statements": 2109 }, "webpack": { - "code": 94264 + "code": 94396 } } }, "build/dist/material-ui-pickers.umd.js": { - "bundled": 299705, - "minified": 118298, - "gzipped": 33596 + "bundled": 300044, + "minified": 118386, + "gzipped": 33633 }, "build/dist/material-ui-pickers.umd.min.js": { - "bundled": 258475, - "minified": 109200, - "gzipped": 30848 + "bundled": 258834, + "minified": 109331, + "gzipped": 30893 } } diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 36db75f01..e38b31942 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -5,7 +5,6 @@ import { MaterialUiPickersDate } from '../typings/date'; import { parsePickerInputValue } from '../_helpers/date-utils'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; -import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { validateDateValue } from '../_helpers/text-field-helper'; import { ResponsiveWrapper } from '../wrappers/ResponsiveWrapper'; import { withDateAdapterProp } from '../_shared/withDateAdapterProp'; @@ -13,6 +12,7 @@ import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { PureDateInput, DateInputProps } from '../_shared/PureDateInput'; import { AnyPickerView, AllSharedPickerProps } from './SharedPickerProps'; import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; +import { SomeWrapper, ExtendWrapper, StaticWrapper } from '../wrappers/Wrapper'; type AllAvailableForOverrideProps = ExportedPickerProps; @@ -23,7 +23,7 @@ export interface MakePickerOptions { export function makePickerWithStateAndWrapper< T extends AllAvailableForOverrideProps, - TWrapper extends SomeWrapper = typeof ResponsiveWrapper + TWrapper extends SomeWrapper = typeof ResponsiveWrapper | typeof StaticWrapper >(Wrapper: TWrapper, { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions) { const PickerWrapper = makeWrapperComponent( Wrapper, From 573cc573e2b452634155d9bf454cb2a8679eff85 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 7 Apr 2020 15:58:08 +0300 Subject: [PATCH 64/72] Update lib/src/views/Calendar/CalendarView.tsx Co-Authored-By: Olivier Tassinari --- lib/src/views/Calendar/CalendarView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/views/Calendar/CalendarView.tsx b/lib/src/views/Calendar/CalendarView.tsx index ab56d18ff..973718070 100644 --- a/lib/src/views/Calendar/CalendarView.tsx +++ b/lib/src/views/Calendar/CalendarView.tsx @@ -73,7 +73,7 @@ export const useStyles = makeStyles( ); export const defaultReduceAnimations = - typeof window !== 'undefined' && /(android)/i.test(window.navigator.userAgent); + typeof navigator !== 'undefined' && /(android)/i.test(navigator.userAgent); export const CalendarView: React.FC = ({ date, From a9fd7ac537ed9771fb4100ad8a04841f99a87440 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 7 Apr 2020 16:15:27 +0300 Subject: [PATCH 65/72] Update docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx Co-Authored-By: Olivier Tassinari --- .../demo/daterangepicker/CalendarsDateRangePicker.example.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx index 710a90525..eba573ab4 100644 --- a/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx +++ b/docs/pages/demo/daterangepicker/CalendarsDateRangePicker.example.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; -import { Grid, Typography } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; import { DateRangePicker, DateRange } from '@material-ui/pickers'; function CalendarsDateRangePicker() { From 8865fcfe9f99ac84d3d4629a663d2b4721d96ddd Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 7 Apr 2020 20:59:23 +0300 Subject: [PATCH 66/72] Update createSvgIcon imports --- lib/src/DateRangePicker/DateRangePickerInput.tsx | 6 +++--- lib/src/_shared/icons/ArrowDropDownIcon.tsx | 2 +- lib/src/_shared/icons/ArrowLeftIcon.tsx | 2 +- lib/src/_shared/icons/ArrowRightIcon.tsx | 2 +- lib/src/_shared/icons/ClockIcon.tsx | 2 +- lib/src/_shared/icons/DateRangeIcon.tsx | 2 +- lib/src/_shared/icons/KeyboardIcon.tsx | 2 +- lib/src/_shared/icons/PenIcon.tsx | 2 +- lib/src/_shared/icons/TimeIcon.tsx | 2 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 9 +++++++-- lib/src/wrappers/MobileWrapper.tsx | 1 + 11 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 791cc2c94..f58f8d061 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -21,9 +21,9 @@ export const useStyles = makeStyles( }, }, toLabelDelimiter: { - margin: '0 16px', - [theme.breakpoints.down('xs')]: { - margin: '8px 0', + margin: '8px 0', + [theme.breakpoints.up('sm')]: { + margin: '0 16px', }, }, }), diff --git a/lib/src/_shared/icons/ArrowDropDownIcon.tsx b/lib/src/_shared/icons/ArrowDropDownIcon.tsx index ab955464d..d3bbd2432 100644 --- a/lib/src/_shared/icons/ArrowDropDownIcon.tsx +++ b/lib/src/_shared/icons/ArrowDropDownIcon.tsx @@ -1,4 +1,4 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const ArrowDropDownIcon = createSvgIcon(, 'ArrowDropDownIcon'); diff --git a/lib/src/_shared/icons/ArrowLeftIcon.tsx b/lib/src/_shared/icons/ArrowLeftIcon.tsx index 3131499ba..17a71fba1 100644 --- a/lib/src/_shared/icons/ArrowLeftIcon.tsx +++ b/lib/src/_shared/icons/ArrowLeftIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const ArrowLeftIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/ArrowRightIcon.tsx b/lib/src/_shared/icons/ArrowRightIcon.tsx index 2a324d29e..58d53dc7b 100644 --- a/lib/src/_shared/icons/ArrowRightIcon.tsx +++ b/lib/src/_shared/icons/ArrowRightIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const ArrowRightIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/ClockIcon.tsx b/lib/src/_shared/icons/ClockIcon.tsx index 97fe42bb0..0811b80d2 100644 --- a/lib/src/_shared/icons/ClockIcon.tsx +++ b/lib/src/_shared/icons/ClockIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export default createSvgIcon( diff --git a/lib/src/_shared/icons/DateRangeIcon.tsx b/lib/src/_shared/icons/DateRangeIcon.tsx index 74a0d8eec..d9487b1d7 100644 --- a/lib/src/_shared/icons/DateRangeIcon.tsx +++ b/lib/src/_shared/icons/DateRangeIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const DateRangeIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/KeyboardIcon.tsx b/lib/src/_shared/icons/KeyboardIcon.tsx index 801027136..2d6f45fce 100644 --- a/lib/src/_shared/icons/KeyboardIcon.tsx +++ b/lib/src/_shared/icons/KeyboardIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const KeyboardIcon = createSvgIcon( <> diff --git a/lib/src/_shared/icons/PenIcon.tsx b/lib/src/_shared/icons/PenIcon.tsx index 7c1714017..d9a27a393 100644 --- a/lib/src/_shared/icons/PenIcon.tsx +++ b/lib/src/_shared/icons/PenIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const PenIcon = createSvgIcon( , diff --git a/lib/src/_shared/icons/TimeIcon.tsx b/lib/src/_shared/icons/TimeIcon.tsx index 3110e928a..4efa0f867 100644 --- a/lib/src/_shared/icons/TimeIcon.tsx +++ b/lib/src/_shared/icons/TimeIcon.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import createSvgIcon from '@material-ui/core/utils/createSvgIcon'; +import { createSvgIcon } from '@material-ui/core/utils'; export const TimeIcon = createSvgIcon( <> diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index daa3fff6d..337669722 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -41,6 +41,9 @@ const useStyles = makeStyles(theme => ({ }, }, }, + topTransition: { + transformOrigin: 'bottom center', + }, })); export const DesktopPopperWrapper: React.FC = ({ @@ -105,7 +108,7 @@ export const DesktopPopperWrapper: React.FC = ({ {...PopperProps} className={clsx(classes.popper, PopperProps?.className)} > - {({ TransitionProps }) => ( + {({ TransitionProps, placement }) => ( = ({ onBlur={handleBlur} tabIndex={-1} elevation={8} - className={classes.paper} + className={clsx(classes.paper, { + [classes.topTransition]: placement === 'top', + })} > {children} diff --git a/lib/src/wrappers/MobileWrapper.tsx b/lib/src/wrappers/MobileWrapper.tsx index d8f477377..cc89fc8a6 100644 --- a/lib/src/wrappers/MobileWrapper.tsx +++ b/lib/src/wrappers/MobileWrapper.tsx @@ -70,6 +70,7 @@ export const MobileWrapper: React.FC = ({ onDismiss, onSetToday, PopoverProps, + displayStaticWrapperAs, KeyboardDateInputComponent, PureDateInputComponent = PureDateInput, ...other From e440de364d062ab375d50539bce1d69fab30da0c Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 7 Apr 2020 21:10:07 +0300 Subject: [PATCH 67/72] Fix ts inferrence for static wrapper props --- docs/prop-types.json | 2449 ++------------------- lib/src/Picker/makePickerWithState.tsx | 4 +- lib/src/wrappers/DesktopPopperWrapper.tsx | 7 +- lib/src/wrappers/DesktopWrapper.tsx | 8 +- lib/src/wrappers/MobileWrapper.tsx | 3 +- lib/src/wrappers/ResponsiveWrapper.tsx | 2 +- 6 files changed, 137 insertions(+), 2336 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index 7cd22990b..7e499f2c9 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -115,2421 +115,179 @@ "type": { "name": "Partial" } - } - }, - "DesktopWrapper": { - "PopoverProps": { - "defaultValue": null, - "description": "Popover props passed to material-ui Popover", - "name": "PopoverProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", - "name": "InnerDesktopWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "okLabel": { - "defaultValue": { - "value": "\"OK\"" - }, - "description": "\"OK\" label message", - "name": "okLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "cancelLabel": { - "defaultValue": { - "value": "\"CANCEL\"" - }, - "description": "\"CANCEL\" label message", - "name": "cancelLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "clearLabel": { - "defaultValue": { - "value": "\"CLEAR\"" - }, - "description": "\"CLEAR\" label message", - "name": "clearLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "todayLabel": { - "defaultValue": { - "value": "\"TODAY\"" - }, - "description": "\"TODAY\" label message", - "name": "todayLabel", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "showTodayButton": { - "defaultValue": { - "value": "false" - }, - "description": "If true today button will be displayed. **Note** that clear button has higher priority", - "name": "showTodayButton", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "clearable": { - "defaultValue": { - "value": "false" - }, - "description": "Show clear action in picker dialog", - "name": "clearable", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "DialogProps": { - "defaultValue": null, - "description": "Props to be passed directly to material-ui Dialog", - "name": "DialogProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" - }, - "required": false, - "type": { - "name": "Partial" - } - } - }, - "DatePicker": { - "value": { - "defaultValue": null, - "description": "Picker value", - "name": "value", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": true, - "type": { - "name": "any" - } - }, - "onChange": { - "defaultValue": null, - "description": "onChange callback", - "name": "onChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": true, - "type": { - "name": "(date: DateIOType, keyboardInputValue?: string) => void" - } - }, - "autoOk": { - "defaultValue": { - "value": "false" - }, - "description": "Auto accept date on selection", - "name": "autoOk", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "inputFormat": { - "defaultValue": null, - "description": "Format string", - "name": "inputFormat", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "disabled": { - "defaultValue": null, - "description": "Disable picker and text field", - "name": "disabled", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "readOnly": { - "defaultValue": null, - "description": "Make picker read only", - "name": "readOnly", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "defaultHighlight": { - "defaultValue": null, - "description": "Date that will be initially highlighted if null was passed", - "name": "defaultHighlight", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "onAccept": { - "defaultValue": null, - "description": "Callback fired when date is accepted", - "name": "onAccept", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void" - } - }, - "onError": { - "defaultValue": null, - "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", - "name": "onError", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "(error: ReactNode, value: DateIOType) => void" - } - }, - "onOpen": { - "defaultValue": null, - "description": "On open callback", - "name": "onOpen", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "() => void" - } - }, - "onClose": { - "defaultValue": null, - "description": "On close callback", - "name": "onClose", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "() => void" - } - }, - "open": { - "defaultValue": null, - "description": "Controlled picker open state", - "name": "open", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "showToolbar": { - "defaultValue": null, - "description": "Show toolbar even in desktop mode", - "name": "showToolbar", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "orientation": { - "defaultValue": null, - "description": "Force rendering in particular orientation", - "name": "orientation", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "\"portrait\" | \"landscape\"" - } - }, - "ToolbarComponent": { - "defaultValue": null, - "description": "Component that will replace default toolbar renderer", - "name": "ToolbarComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "ComponentClass, any> | FunctionComponent>" - } - }, - "toolbarTitle": { - "defaultValue": { - "value": "\"SELECT DATE\"" - }, - "description": "Mobile picker title, displaying in the toolbar", - "name": "toolbarTitle", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "toolbarFormat": { - "defaultValue": null, - "description": "Date format, that is displaying in toolbar", - "name": "toolbarFormat", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "views": { - "defaultValue": null, - "description": "Array of views to show", - "name": "views", - "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", - "name": "WithViewsProps" - }, - "required": false, - "type": { - "name": "(\"year\" | \"date\" | \"month\")[]" - } - }, - "disableHighlightToday": { - "defaultValue": { - "value": "false" - }, - "description": "Disable highlighting today date with a circle", - "name": "disableHighlightToday", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "showDaysOutsideCurrentMonth": { - "defaultValue": { - "value": "false" - }, - "description": "Display disabled dates outside the current month", - "name": "showDaysOutsideCurrentMonth", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "leftArrowIcon": { - "defaultValue": null, - "description": "Left arrow icon", - "name": "leftArrowIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "rightArrowIcon": { - "defaultValue": null, - "description": "Right arrow icon", - "name": "rightArrowIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "leftArrowButtonProps": { - "defaultValue": null, - "description": "Props to pass to left arrow button", - "name": "leftArrowButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "rightArrowButtonProps": { - "defaultValue": null, - "description": "Props to pass to right arrow button", - "name": "rightArrowButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "leftArrowButtonText": { - "defaultValue": null, - "description": "Left arrow icon aria-label text", - "name": "leftArrowButtonText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "rightArrowButtonText": { - "defaultValue": null, - "description": "Right arrow icon aria-label text", - "name": "rightArrowButtonText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "getViewSwitchingButtonText": { - "defaultValue": null, - "description": "Get aria-label text for switching between views button", - "name": "getViewSwitchingButtonText", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", - "name": "CalendarHeaderProps" - }, - "required": false, - "type": { - "name": "(currentView: \"year\" | \"date\" | \"month\") => string" - } - }, - "mask": { - "defaultValue": null, - "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", - "name": "mask", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "minDate": { - "defaultValue": { - "value": "Date(1900-01-01)" - }, - "description": "Min selectable date", - "name": "minDate", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "maxDate": { - "defaultValue": { - "value": "Date(2100-01-01)" - }, - "description": "Max selectable date", - "name": "maxDate", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "disablePast": { - "defaultValue": { - "value": "false" - }, - "description": "Disable past dates", - "name": "disablePast", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "disableFuture": { - "defaultValue": { - "value": "false" - }, - "description": "Disable future dates", - "name": "disableFuture", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "reduceAnimations": { - "defaultValue": null, - "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", - "name": "reduceAnimations", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "onMonthChange": { - "defaultValue": null, - "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", - "name": "onMonthChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void | Promise" - } - }, - "shouldDisableDate": { - "defaultValue": null, - "description": "Disable specific date", - "name": "shouldDisableDate", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "(day: DateIOType) => boolean" - } - }, - "onYearChange": { - "defaultValue": null, - "description": "Callback firing on year change", - "name": "onYearChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void" - } - }, - "renderDay": { - "defaultValue": null, - "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", - "name": "renderDay", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" - } - }, - "allowKeyboardControl": { - "defaultValue": { - "value": "currentWrapper !== 'static'" - }, - "description": "Enables keyboard listener for moving between days in calendar", - "name": "allowKeyboardControl", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "loadingIndicator": { - "defaultValue": null, - "description": "Custom loading indicator", - "name": "loadingIndicator", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "Element" - } - }, - "openTo": { - "defaultValue": null, - "description": "First view to show", - "name": "openTo", - "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", - "name": "WithViewsProps" - }, - "required": false, - "type": { - "name": "\"year\" | \"date\" | \"month\"" - } - }, - "TextFieldComponent": { - "defaultValue": null, - "description": "Override input component", - "name": "TextFieldComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, - "emptyInputText": { - "defaultValue": { - "value": "' '" - }, - "description": "Message displaying in read-only text field when null passed", - "name": "emptyInputText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "keyboardIcon": { - "defaultValue": null, - "description": "Icon displaying for open picker button", - "name": "keyboardIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maskChar": { - "defaultValue": { - "value": "'_'" - }, - "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", - "name": "maskChar", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "acceptRegex": { - "defaultValue": { - "value": "/\\dap/gi" - }, - "description": "Regular expression to detect \"accepted\" symbols", - "name": "acceptRegex", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "RegExp" - } - }, - "InputAdornmentProps": { - "defaultValue": null, - "description": "Props to pass to keyboard input adornment", - "name": "InputAdornmentProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "KeyboardButtonProps": { - "defaultValue": null, - "description": "Props to pass to keyboard adornment button", - "name": "KeyboardButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "rifmFormatter": { - "defaultValue": null, - "description": "Custom formatter to be passed into Rifm component", - "name": "rifmFormatter", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "(str: string) => string" - } - }, - "disableOpenPicker": { - "defaultValue": { - "value": "false" - }, - "description": "Do not render open picker button (renders only text field with validation)", - "name": "disableOpenPicker", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "disableMaskedInput": { - "defaultValue": { - "value": "false" - }, - "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", - "name": "disableMaskedInput", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "getOpenDialogAriaText": { - "defaultValue": null, - "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", - "name": "getOpenDialogAriaText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "(value: any, utils: MuiPickersAdapter) => string" - } - }, - "dateAdapter": { - "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", - "name": "dateAdapter", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", - "name": "WithDateAdapterProps" - }, - "required": false, - "type": { - "name": "MuiPickersAdapter" - } - }, - "minDateMessage": { - "defaultValue": { - "value": "'Date should not be before minimal date'" - }, - "description": "Error message, shown if date is less then minimal date", - "name": "minDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maxDateMessage": { - "defaultValue": { - "value": "'Date should not be after maximal date'" - }, - "description": "Error message, shown if date is more then maximal date", - "name": "maxDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "strictCompareDates": { - "defaultValue": { - "value": "false" - }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "invalidDateMessage": { - "defaultValue": { - "value": "'Invalid Date Format'" - }, - "description": "Message, appearing when date cannot be parsed", - "name": "invalidDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "BaseValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - } - }, - "TimePicker": { - "value": { - "defaultValue": null, - "description": "Picker value", - "name": "value", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": true, - "type": { - "name": "any" - } - }, - "onChange": { - "defaultValue": null, - "description": "onChange callback", - "name": "onChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": true, - "type": { - "name": "(date: DateIOType, keyboardInputValue?: string) => void" - } - }, - "autoOk": { - "defaultValue": { - "value": "false" - }, - "description": "Auto accept date on selection", - "name": "autoOk", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "inputFormat": { - "defaultValue": null, - "description": "Format string", - "name": "inputFormat", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "disabled": { - "defaultValue": null, - "description": "Disable picker and text field", - "name": "disabled", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "readOnly": { - "defaultValue": null, - "description": "Make picker read only", - "name": "readOnly", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "defaultHighlight": { - "defaultValue": null, - "description": "Date that will be initially highlighted if null was passed", - "name": "defaultHighlight", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "onAccept": { - "defaultValue": null, - "description": "Callback fired when date is accepted", - "name": "onAccept", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void" - } - }, - "onError": { - "defaultValue": null, - "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", - "name": "onError", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "(error: ReactNode, value: DateIOType) => void" - } - }, - "onOpen": { - "defaultValue": null, - "description": "On open callback", - "name": "onOpen", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "() => void" - } - }, - "onClose": { - "defaultValue": null, - "description": "On close callback", - "name": "onClose", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "() => void" - } - }, - "open": { - "defaultValue": null, - "description": "Controlled picker open state", - "name": "open", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "showToolbar": { - "defaultValue": null, - "description": "Show toolbar even in desktop mode", - "name": "showToolbar", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "orientation": { - "defaultValue": null, - "description": "Force rendering in particular orientation", - "name": "orientation", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "\"portrait\" | \"landscape\"" - } - }, - "ToolbarComponent": { - "defaultValue": null, - "description": "Component that will replace default toolbar renderer", - "name": "ToolbarComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "ComponentClass, any> | FunctionComponent>" - } - }, - "toolbarTitle": { - "defaultValue": { - "value": "\"SELECT DATE\"" - }, - "description": "Mobile picker title, displaying in the toolbar", - "name": "toolbarTitle", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "toolbarFormat": { - "defaultValue": null, - "description": "Date format, that is displaying in toolbar", - "name": "toolbarFormat", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "views": { - "defaultValue": null, - "description": "Array of views to show", - "name": "views", - "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", - "name": "WithViewsProps" - }, - "required": false, - "type": { - "name": "(\"hours\" | \"minutes\" | \"seconds\")[]" - } - }, - "mask": { - "defaultValue": null, - "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", - "name": "mask", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "allowKeyboardControl": { - "defaultValue": { - "value": "currentWrapper !== 'static'" - }, - "description": "Enables keyboard listener for moving between days in calendar", - "name": "allowKeyboardControl", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "TextFieldComponent": { - "defaultValue": null, - "description": "Override input component", - "name": "TextFieldComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, - "emptyInputText": { - "defaultValue": { - "value": "' '" - }, - "description": "Message displaying in read-only text field when null passed", - "name": "emptyInputText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "keyboardIcon": { - "defaultValue": null, - "description": "Icon displaying for open picker button", - "name": "keyboardIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maskChar": { - "defaultValue": { - "value": "'_'" - }, - "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", - "name": "maskChar", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "acceptRegex": { - "defaultValue": { - "value": "/\\dap/gi" - }, - "description": "Regular expression to detect \"accepted\" symbols", - "name": "acceptRegex", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "RegExp" - } - }, - "InputAdornmentProps": { - "defaultValue": null, - "description": "Props to pass to keyboard input adornment", - "name": "InputAdornmentProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "KeyboardButtonProps": { - "defaultValue": null, - "description": "Props to pass to keyboard adornment button", - "name": "KeyboardButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "rifmFormatter": { - "defaultValue": null, - "description": "Custom formatter to be passed into Rifm component", - "name": "rifmFormatter", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "(str: string) => string" - } - }, - "disableOpenPicker": { - "defaultValue": { - "value": "false" - }, - "description": "Do not render open picker button (renders only text field with validation)", - "name": "disableOpenPicker", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "disableMaskedInput": { - "defaultValue": { - "value": "false" - }, - "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", - "name": "disableMaskedInput", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "getOpenDialogAriaText": { - "defaultValue": null, - "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", - "name": "getOpenDialogAriaText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "(value: any, utils: MuiPickersAdapter) => string" - } - }, - "openTo": { - "defaultValue": null, - "description": "First view to show", - "name": "openTo", - "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", - "name": "WithViewsProps" - }, - "required": false, - "type": { - "name": "\"hours\" | \"minutes\" | \"seconds\"" - } - }, - "ampm": { - "defaultValue": { - "value": "true" - }, - "description": "12h/24h view for hour selection clock", - "name": "ampm", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "minutesStep": { - "defaultValue": { - "value": "1" - }, - "description": "Step over minutes", - "name": "minutesStep", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "number" - } - }, - "ampmInClock": { - "defaultValue": { - "value": "false" - }, - "description": "Display ampm controls under the clock (instead of in the toolbar)", - "name": "ampmInClock", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "minTime": { - "defaultValue": null, - "description": "Min time, date part by default, will be ignored", - "name": "minTime", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "maxTime": { - "defaultValue": null, - "description": "Max time, date part by default, will be ignored", - "name": "maxTime", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "shouldDisableTime": { - "defaultValue": null, - "description": "Dynamically check if time is disabled or not", - "name": "shouldDisableTime", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "(timeValue: number, clockType: \"hours\" | \"minutes\" | \"seconds\") => boolean" - } - }, - "disableTimeValidationIgnoreDatePart": { - "defaultValue": null, - "description": "Do not ignore date part when validating min/max time", - "name": "disableTimeValidationIgnoreDatePart", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "dateAdapter": { - "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", - "name": "dateAdapter", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", - "name": "WithDateAdapterProps" - }, - "required": false, - "type": { - "name": "MuiPickersAdapter" - } - }, - "minDateMessage": { - "defaultValue": { - "value": "'Date should not be before minimal date'" - }, - "description": "Error message, shown if date is less then minimal date", - "name": "minDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maxDateMessage": { - "defaultValue": { - "value": "'Date should not be after maximal date'" - }, - "description": "Error message, shown if date is more then maximal date", - "name": "maxDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "strictCompareDates": { - "defaultValue": { - "value": "false" - }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "invalidDateMessage": { - "defaultValue": { - "value": "'Invalid Date Format'" - }, - "description": "Message, appearing when date cannot be parsed", - "name": "invalidDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "BaseValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - } - }, - "DateTimePicker": { - "value": { - "defaultValue": null, - "description": "Picker value", - "name": "value", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": true, - "type": { - "name": "any" - } - }, - "onChange": { - "defaultValue": null, - "description": "onChange callback", - "name": "onChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": true, - "type": { - "name": "(date: DateIOType, keyboardInputValue?: string) => void" - } - }, - "autoOk": { - "defaultValue": { - "value": "false" - }, - "description": "Auto accept date on selection", - "name": "autoOk", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "inputFormat": { - "defaultValue": null, - "description": "Format string", - "name": "inputFormat", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "disabled": { - "defaultValue": null, - "description": "Disable picker and text field", - "name": "disabled", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "readOnly": { - "defaultValue": null, - "description": "Make picker read only", - "name": "readOnly", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "defaultHighlight": { - "defaultValue": null, - "description": "Date that will be initially highlighted if null was passed", - "name": "defaultHighlight", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "onAccept": { - "defaultValue": null, - "description": "Callback fired when date is accepted", - "name": "onAccept", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void" - } - }, - "onError": { - "defaultValue": null, - "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", - "name": "onError", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "(error: ReactNode, value: DateIOType) => void" - } - }, - "onOpen": { - "defaultValue": null, - "description": "On open callback", - "name": "onOpen", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "() => void" - } - }, - "onClose": { - "defaultValue": null, - "description": "On close callback", - "name": "onClose", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "() => void" - } - }, - "open": { - "defaultValue": null, - "description": "Controlled picker open state", - "name": "open", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "showToolbar": { - "defaultValue": null, - "description": "Show toolbar even in desktop mode", - "name": "showToolbar", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "orientation": { - "defaultValue": null, - "description": "Force rendering in particular orientation", - "name": "orientation", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "\"portrait\" | \"landscape\"" - } - }, - "ToolbarComponent": { - "defaultValue": null, - "description": "Component that will replace default toolbar renderer", - "name": "ToolbarComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "ComponentClass, any> | FunctionComponent>" - } - }, - "toolbarTitle": { - "defaultValue": { - "value": "\"SELECT DATE\"" - }, - "description": "Mobile picker title, displaying in the toolbar", - "name": "toolbarTitle", - "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "toolbarFormat": { - "defaultValue": null, - "description": "Date format, that is displaying in toolbar\nDate format, that is displaying in toolbar", - "name": "toolbarFormat", - "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "views": { - "defaultValue": null, - "description": "Array of views to show", - "name": "views", - "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", - "name": "WithViewsProps" - }, - "required": false, - "type": { - "name": "(\"year\" | \"date\" | \"month\" | \"hours\" | \"minutes\")[]" - } - }, - "disableHighlightToday": { - "defaultValue": { - "value": "false" - }, - "description": "Disable highlighting today date with a circle", - "name": "disableHighlightToday", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "showDaysOutsideCurrentMonth": { - "defaultValue": { - "value": "false" - }, - "description": "Display disabled dates outside the current month", - "name": "showDaysOutsideCurrentMonth", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "leftArrowIcon": { - "defaultValue": null, - "description": "Left arrow icon", - "name": "leftArrowIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "rightArrowIcon": { - "defaultValue": null, - "description": "Right arrow icon", - "name": "rightArrowIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "leftArrowButtonProps": { - "defaultValue": null, - "description": "Props to pass to left arrow button", - "name": "leftArrowButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "rightArrowButtonProps": { - "defaultValue": null, - "description": "Props to pass to right arrow button", - "name": "rightArrowButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "leftArrowButtonText": { - "defaultValue": null, - "description": "Left arrow icon aria-label text", - "name": "leftArrowButtonText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "rightArrowButtonText": { - "defaultValue": null, - "description": "Right arrow icon aria-label text", - "name": "rightArrowButtonText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "getViewSwitchingButtonText": { - "defaultValue": null, - "description": "Get aria-label text for switching between views button", - "name": "getViewSwitchingButtonText", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", - "name": "CalendarHeaderProps" - }, - "required": false, - "type": { - "name": "(currentView: \"year\" | \"date\" | \"month\") => string" - } - }, - "mask": { - "defaultValue": null, - "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", - "name": "mask", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "minDate": { - "defaultValue": { - "value": "Date(1900-01-01)" - }, - "description": "Min selectable date", - "name": "minDate", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "maxDate": { - "defaultValue": { - "value": "Date(2100-01-01)" - }, - "description": "Max selectable date", - "name": "maxDate", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "any" - } - }, - "disablePast": { - "defaultValue": { - "value": "false" - }, - "description": "Disable past dates", - "name": "disablePast", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "disableFuture": { - "defaultValue": { - "value": "false" - }, - "description": "Disable future dates", - "name": "disableFuture", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "reduceAnimations": { - "defaultValue": null, - "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", - "name": "reduceAnimations", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "onMonthChange": { - "defaultValue": null, - "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", - "name": "onMonthChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void | Promise" - } - }, - "shouldDisableDate": { - "defaultValue": null, - "description": "Disable specific date", - "name": "shouldDisableDate", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "(day: DateIOType) => boolean" - } - }, - "onYearChange": { - "defaultValue": null, - "description": "Callback firing on year change", - "name": "onYearChange", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" - }, - "required": false, - "type": { - "name": "(date: DateIOType) => void" - } - }, - "renderDay": { - "defaultValue": null, - "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", - "name": "renderDay", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" - } - }, - "allowKeyboardControl": { - "defaultValue": { - "value": "currentWrapper !== 'static'" - }, - "description": "Enables keyboard listener for moving between days in calendar", - "name": "allowKeyboardControl", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "loadingIndicator": { - "defaultValue": null, - "description": "Custom loading indicator", - "name": "loadingIndicator", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" - }, - "required": false, - "type": { - "name": "Element" - } - }, - "TextFieldComponent": { - "defaultValue": null, - "description": "Override input component", - "name": "TextFieldComponent", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "ComponentClass | FunctionComponent" - } - }, - "emptyInputText": { - "defaultValue": { - "value": "' '" - }, - "description": "Message displaying in read-only text field when null passed", - "name": "emptyInputText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "keyboardIcon": { - "defaultValue": null, - "description": "Icon displaying for open picker button", - "name": "keyboardIcon", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maskChar": { - "defaultValue": { - "value": "'_'" - }, - "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", - "name": "maskChar", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "string" - } - }, - "acceptRegex": { - "defaultValue": { - "value": "/\\dap/gi" - }, - "description": "Regular expression to detect \"accepted\" symbols", - "name": "acceptRegex", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "RegExp" - } - }, - "InputAdornmentProps": { - "defaultValue": null, - "description": "Props to pass to keyboard input adornment", - "name": "InputAdornmentProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "KeyboardButtonProps": { - "defaultValue": null, - "description": "Props to pass to keyboard adornment button", - "name": "KeyboardButtonProps", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "Partial" - } - }, - "rifmFormatter": { - "defaultValue": null, - "description": "Custom formatter to be passed into Rifm component", - "name": "rifmFormatter", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "(str: string) => string" - } - }, - "disableOpenPicker": { - "defaultValue": { - "value": "false" - }, - "description": "Do not render open picker button (renders only text field with validation)", - "name": "disableOpenPicker", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" - }, - "required": false, - "type": { - "name": "boolean" - } }, - "disableMaskedInput": { + "displayStaticWrapperAs": { "defaultValue": { - "value": "false" - }, - "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", - "name": "disableMaskedInput", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "value": "\"static\"" }, - "required": false, - "type": { - "name": "boolean" - } - }, - "getOpenDialogAriaText": { - "defaultValue": null, - "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", - "name": "getOpenDialogAriaText", + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" }, "required": false, "type": { - "name": "(value: any, utils: MuiPickersAdapter) => string" + "name": "\"desktop\" | \"mobile\" | \"static\"" } - }, - "openTo": { + } + }, + "DesktopWrapper": { + "PopoverProps": { "defaultValue": null, - "description": "First view to show", - "name": "openTo", + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", "parent": { - "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", - "name": "WithViewsProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" }, "required": false, "type": { - "name": "\"year\" | \"date\" | \"month\" | \"hours\" | \"minutes\"" + "name": "Partial" } }, - "ampm": { + "okLabel": { "defaultValue": { - "value": "true" - }, - "description": "12h/24h view for hour selection clock", - "name": "ampm", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" - }, - "required": false, - "type": { - "name": "boolean" - } - }, - "minDateTime": { - "defaultValue": null, - "description": "Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`", - "name": "minDateTime", - "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerProps" + "value": "\"OK\"" }, - "required": false, - "type": { - "name": "any" - } - }, - "maxDateTime": { - "defaultValue": null, - "description": "Minimal selectable moment of time with binding to date, to set max time in each day use `maxTime`", - "name": "maxDateTime", + "description": "\"OK\" label message", + "name": "okLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "any" + "name": "ReactNode" } }, - "hideTabs": { - "defaultValue": null, - "description": "To show tabs", - "name": "hideTabs", - "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerProps" + "cancelLabel": { + "defaultValue": { + "value": "\"CANCEL\"" }, - "required": false, - "type": { - "name": "boolean" - } - }, - "dateRangeIcon": { - "defaultValue": null, - "description": "Date tab icon", - "name": "dateRangeIcon", + "description": "\"CANCEL\" label message", + "name": "cancelLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { "name": "ReactNode" } }, - "timeIcon": { - "defaultValue": null, - "description": "Time tab icon", - "name": "timeIcon", + "clearLabel": { + "defaultValue": { + "value": "\"CLEAR\"" + }, + "description": "\"CLEAR\" label message", + "name": "clearLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", - "name": "DateTimePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { "name": "ReactNode" } }, - "minutesStep": { + "todayLabel": { "defaultValue": { - "value": "1" + "value": "\"TODAY\"" }, - "description": "Step over minutes", - "name": "minutesStep", + "description": "\"TODAY\" label message", + "name": "todayLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "number" + "name": "ReactNode" } }, - "ampmInClock": { + "showTodayButton": { "defaultValue": { "value": "false" }, - "description": "Display ampm controls under the clock (instead of in the toolbar)", - "name": "ampmInClock", + "description": "If true today button will be displayed. **Note** that clear button has higher priority", + "name": "showTodayButton", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { "name": "boolean" } }, - "minTime": { - "defaultValue": null, - "description": "Min time, date part by default, will be ignored", - "name": "minTime", - "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "clearable": { + "defaultValue": { + "value": "false" }, - "required": false, - "type": { - "name": "any" - } - }, - "maxTime": { - "defaultValue": null, - "description": "Max time, date part by default, will be ignored", - "name": "maxTime", + "description": "Show clear action in picker dialog", + "name": "clearable", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "any" + "name": "boolean" } }, - "shouldDisableTime": { + "DialogProps": { "defaultValue": null, - "description": "Dynamically check if time is disabled or not", - "name": "shouldDisableTime", + "description": "Props to be passed directly to material-ui Dialog", + "name": "DialogProps", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "(timeValue: number, clockType: \"hours\" | \"minutes\" | \"seconds\") => boolean" + "name": "Partial" } }, - "disableTimeValidationIgnoreDatePart": { + "PopperProps": { "defaultValue": null, - "description": "Do not ignore date part when validating min/max time", - "name": "disableTimeValidationIgnoreDatePart", + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", - "name": "ExportedClockViewProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" }, "required": false, "type": { - "name": "boolean" + "name": "Partial" } }, - "dateAdapter": { + "TransitionComponent": { "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", - "name": "dateAdapter", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", - "name": "WithDateAdapterProps" - }, - "required": false, - "type": { - "name": "MuiPickersAdapter" - } - }, - "minDateMessage": { - "defaultValue": { - "value": "'Date should not be before minimal date'" - }, - "description": "Error message, shown if date is less then minimal date", - "name": "minDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "maxDateMessage": { - "defaultValue": { - "value": "'Date should not be after maximal date'" - }, - "description": "Error message, shown if date is more then maximal date", - "name": "maxDateMessage", - "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" - }, - "required": false, - "type": { - "name": "ReactNode" - } - }, - "strictCompareDates": { - "defaultValue": { - "value": "false" - }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" }, "required": false, "type": { - "name": "boolean" + "name": "ComponentClass | FunctionComponent" } }, - "invalidDateMessage": { + "displayStaticWrapperAs": { "defaultValue": { - "value": "'Invalid Date Format'" + "value": "\"static\"" }, - "description": "Message, appearing when date cannot be parsed", - "name": "invalidDateMessage", + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "BaseValidationProps" + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "\"desktop\" | \"mobile\" | \"static\"" } } }, @@ -3332,6 +1090,21 @@ "name": "Partial" } }, + "displayStaticWrapperAs": { + "defaultValue": { + "value": "\"static\"" + }, + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" + }, + "required": false, + "type": { + "name": "\"desktop\" | \"mobile\" | \"static\"" + } + }, "okLabel": { "defaultValue": { "value": "\"OK\"" @@ -3435,6 +1208,32 @@ "name": "Partial" } }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, "desktopModeBreakpoint": { "defaultValue": { "value": "'md'" diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index e38b31942..2278a29ed 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -3,6 +3,7 @@ import { useUtils } from '../_shared/hooks/useUtils'; import { ParsableDate } from '../constants/prop-types'; import { MaterialUiPickersDate } from '../typings/date'; import { parsePickerInputValue } from '../_helpers/date-utils'; +import { SomeWrapper, ExtendWrappe } from '../wrappers/Wrapper'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { validateDateValue } from '../_helpers/text-field-helper'; @@ -12,7 +13,6 @@ import { makeWrapperComponent } from '../wrappers/makeWrapperComponent'; import { PureDateInput, DateInputProps } from '../_shared/PureDateInput'; import { AnyPickerView, AllSharedPickerProps } from './SharedPickerProps'; import { Picker, ToolbarComponentProps, ExportedPickerProps } from './Picker'; -import { SomeWrapper, ExtendWrapper, StaticWrapper } from '../wrappers/Wrapper'; type AllAvailableForOverrideProps = ExportedPickerProps; @@ -23,7 +23,7 @@ export interface MakePickerOptions { export function makePickerWithStateAndWrapper< T extends AllAvailableForOverrideProps, - TWrapper extends SomeWrapper = typeof ResponsiveWrapper | typeof StaticWrapper + TWrapper extends SomeWrapper = typeof ResponsiveWrapper >(Wrapper: TWrapper, { useDefaultProps, DefaultToolbarComponent }: MakePickerOptions) { const PickerWrapper = makeWrapperComponent( Wrapper, diff --git a/lib/src/wrappers/DesktopPopperWrapper.tsx b/lib/src/wrappers/DesktopPopperWrapper.tsx index 337669722..509dbc9d6 100644 --- a/lib/src/wrappers/DesktopPopperWrapper.tsx +++ b/lib/src/wrappers/DesktopPopperWrapper.tsx @@ -6,8 +6,10 @@ import Paper from '@material-ui/core/Paper'; import TrapFocus from '@material-ui/core/Modal/TrapFocus'; import Popper, { PopperProps } from '@material-ui/core/Popper'; import { WrapperProps } from './Wrapper'; +import { StaticWrapperProps } from './StaticWrapper'; import { makeStyles } from '@material-ui/core/styles'; import { InnerMobileWrapperProps } from './MobileWrapper'; +import { InnerDesktopWrapperProps } from './DesktopWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { useGlobalKeyDown, keycode } from '../_shared/hooks/useKeyDown'; @@ -19,14 +21,12 @@ export interface InnerDesktopPopperWrapperProps { PopperProps?: Partial; /** Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop) */ TransitionComponent?: React.ComponentType; - // required for spreading - PopoverProps?: any; } export interface DesktopPopperWrapperProps extends InnerDesktopPopperWrapperProps, WrapperProps, - Partial {} + Partial {} const useStyles = makeStyles(theme => ({ popper: { @@ -66,6 +66,7 @@ export const DesktopPopperWrapper: React.FC = ({ clearable, DialogProps, PureDateInputComponent, + displayStaticWrapperAs, TransitionComponent = Grow, KeyboardDateInputComponent = KeyboardDateInput, ...other diff --git a/lib/src/wrappers/DesktopWrapper.tsx b/lib/src/wrappers/DesktopWrapper.tsx index ffd80210f..4fedd922a 100644 --- a/lib/src/wrappers/DesktopWrapper.tsx +++ b/lib/src/wrappers/DesktopWrapper.tsx @@ -3,22 +3,21 @@ import * as PropTypes from 'prop-types'; import KeyboardDateInput from '../_shared/KeyboardDateInput'; import Popover, { PopoverProps } from '@material-ui/core/Popover'; import { WrapperProps } from './Wrapper'; +import { StaticWrapperProps } from './StaticWrapper'; import { makeStyles } from '@material-ui/core/styles'; import { InnerMobileWrapperProps } from './MobileWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; +import { InnerDesktopPopperWrapperProps } from './DesktopPopperWrapper'; export interface InnerDesktopWrapperProps { /** Popover props passed to material-ui Popover */ PopoverProps?: Partial; - // required for spreading - PopperProps?: any; - TransitionComponent?: any; } export interface DesktopWrapperProps extends InnerDesktopWrapperProps, WrapperProps, - Partial {} + Partial {} const useStyles = makeStyles({ popover: { @@ -52,6 +51,7 @@ export const DesktopWrapper: React.FC = ({ clearable, DialogProps, PureDateInputComponent, + displayStaticWrapperAs, KeyboardDateInputComponent = KeyboardDateInput, ...other }) => { diff --git a/lib/src/wrappers/MobileWrapper.tsx b/lib/src/wrappers/MobileWrapper.tsx index cc89fc8a6..4a00642ec 100644 --- a/lib/src/wrappers/MobileWrapper.tsx +++ b/lib/src/wrappers/MobileWrapper.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import * as PropTypes from 'prop-types'; import ModalDialog from '../_shared/ModalDialog'; import { WrapperProps } from './Wrapper'; +import { StaticWrapperProps } from './StaticWrapper'; import { PureDateInput } from '../_shared/PureDateInput'; import { InnerDesktopWrapperProps } from './DesktopWrapper'; import { WrapperVariantContext } from './WrapperVariantContext'; @@ -50,7 +51,7 @@ export interface InnerMobileWrapperProps { export interface MobileWrapperProps extends InnerMobileWrapperProps, WrapperProps, - Partial {} + Partial {} export const MobileWrapper: React.FC = ({ open, diff --git a/lib/src/wrappers/ResponsiveWrapper.tsx b/lib/src/wrappers/ResponsiveWrapper.tsx index ba98059e7..f3941e86b 100644 --- a/lib/src/wrappers/ResponsiveWrapper.tsx +++ b/lib/src/wrappers/ResponsiveWrapper.tsx @@ -6,7 +6,6 @@ import { DesktopWrapperProps, DesktopWrapper } from './DesktopWrapper'; import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; import { DesktopPopperWrapperProps, DesktopPopperWrapper } from './DesktopPopperWrapper'; -// @ts-ignore TODO remove when fully move to Popper based pickers export interface ResponsiveWrapperProps extends DesktopWrapperProps, DesktopPopperWrapperProps, @@ -33,6 +32,7 @@ export const makeResponsiveWrapper = ( PopoverProps, PopperProps, TransitionComponent, + displayStaticWrapperAs, ...other }) => { const theme = useTheme(); From e86fb2213898dbace0b653d0aa2057977d0222ba Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 7 Apr 2020 21:13:01 +0300 Subject: [PATCH 68/72] Add missing props spreading --- lib/src/Picker/makePickerWithState.tsx | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 2278a29ed..7fb116b8f 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -54,14 +54,19 @@ export function makePickerWithStateAndWrapper< ampmInClock, dateRangeIcon, disableFuture, + disableHighlightToday, disablePast, - showToolbar, + disableTimeValidationIgnoreDatePart, hideTabs, leftArrowButtonProps, + leftArrowButtonText, leftArrowIcon, loadingIndicator, maxDate, + maxTime, minDate, + minDateTime, + minTime, minutesStep, onMonthChange, onYearChange, @@ -69,20 +74,18 @@ export function makePickerWithStateAndWrapper< orientation, renderDay, rightArrowButtonProps, + rightArrowButtonText, rightArrowIcon, shouldDisableDate, shouldDisableTime, + showDaysOutsideCurrentMonth, + showToolbar, timeIcon, - value, - toolbarFormat, ToolbarComponent = DefaultToolbarComponent, - views, + toolbarFormat, toolbarTitle, - disableTimeValidationIgnoreDatePart, - showDaysOutsideCurrentMonth, - disableHighlightToday, - minTime, - maxTime, + value, + views, ...restPropsForTextField } = allProps; @@ -102,6 +105,7 @@ export function makePickerWithStateAndWrapper< hideTabs={hideTabs} leftArrowButtonProps={leftArrowButtonProps} leftArrowIcon={leftArrowIcon} + leftArrowButtonText={leftArrowButtonText} loadingIndicator={loadingIndicator} maxDate={maxDate} maxTime={maxTime} @@ -115,13 +119,14 @@ export function makePickerWithStateAndWrapper< renderDay={renderDay} rightArrowButtonProps={rightArrowButtonProps} rightArrowIcon={rightArrowIcon} + rightArrowButtonText={rightArrowButtonText} shouldDisableDate={shouldDisableDate} shouldDisableTime={shouldDisableTime} showDaysOutsideCurrentMonth={showDaysOutsideCurrentMonth} showToolbar={showToolbar} timeIcon={timeIcon} - toolbarFormat={toolbarFormat} ToolbarComponent={ToolbarComponent} + toolbarFormat={toolbarFormat} toolbarTitle={toolbarTitle || restPropsForTextField?.label} views={views} /> From e7f2f442d76671d210ebbe120afb488e6aec5b64 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Tue, 7 Apr 2020 21:17:55 +0300 Subject: [PATCH 69/72] Fix more build errors --- docs/prop-types.json | 2814 ++++++++++++++++++++++++ lib/.size-snapshot.json | 24 +- lib/rollup.config.js | 2 +- lib/src/Picker/makePickerWithState.tsx | 5 +- 4 files changed, 2831 insertions(+), 14 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index 7e499f2c9..016e244aa 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -291,6 +291,2820 @@ } } }, + "DatePicker": { + "value": { + "defaultValue": null, + "description": "Picker value", + "name": "value", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "any" + } + }, + "onChange": { + "defaultValue": null, + "description": "onChange callback", + "name": "onChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "(date: DateIOType, keyboardInputValue?: string) => void" + } + }, + "autoOk": { + "defaultValue": { + "value": "false" + }, + "description": "Auto accept date on selection", + "name": "autoOk", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "inputFormat": { + "defaultValue": null, + "description": "Format string", + "name": "inputFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "disabled": { + "defaultValue": null, + "description": "Disable picker and text field", + "name": "disabled", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "readOnly": { + "defaultValue": null, + "description": "Make picker read only", + "name": "readOnly", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "defaultHighlight": { + "defaultValue": null, + "description": "Date that will be initially highlighted if null was passed", + "name": "defaultHighlight", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "onAccept": { + "defaultValue": null, + "description": "Callback fired when date is accepted", + "name": "onAccept", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void" + } + }, + "onError": { + "defaultValue": null, + "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", + "name": "onError", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "(error: ReactNode, value: DateIOType) => void" + } + }, + "onOpen": { + "defaultValue": null, + "description": "On open callback", + "name": "onOpen", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "onClose": { + "defaultValue": null, + "description": "On close callback", + "name": "onClose", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "open": { + "defaultValue": null, + "description": "Controlled picker open state", + "name": "open", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "showToolbar": { + "defaultValue": null, + "description": "Show toolbar even in desktop mode", + "name": "showToolbar", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "orientation": { + "defaultValue": null, + "description": "Force rendering in particular orientation", + "name": "orientation", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "\"portrait\" | \"landscape\"" + } + }, + "ToolbarComponent": { + "defaultValue": null, + "description": "Component that will replace default toolbar renderer", + "name": "ToolbarComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ComponentClass, any> | FunctionComponent>" + } + }, + "toolbarTitle": { + "defaultValue": { + "value": "\"SELECT DATE\"" + }, + "description": "Mobile picker title, displaying in the toolbar", + "name": "toolbarTitle", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar", + "name": "toolbarFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "views": { + "defaultValue": null, + "description": "Array of views to show", + "name": "views", + "parent": { + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" + }, + "required": false, + "type": { + "name": "(\"year\" | \"date\" | \"month\")[]" + } + }, + "disableHighlightToday": { + "defaultValue": { + "value": "false" + }, + "description": "Disable highlighting today date with a circle", + "name": "disableHighlightToday", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "showDaysOutsideCurrentMonth": { + "defaultValue": { + "value": "false" + }, + "description": "Display disabled dates outside the current month", + "name": "showDaysOutsideCurrentMonth", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "leftArrowIcon": { + "defaultValue": null, + "description": "Left arrow icon", + "name": "leftArrowIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "rightArrowIcon": { + "defaultValue": null, + "description": "Right arrow icon", + "name": "rightArrowIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "leftArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to left arrow button", + "name": "leftArrowButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rightArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to right arrow button", + "name": "rightArrowButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "leftArrowButtonText": { + "defaultValue": null, + "description": "Left arrow icon aria-label text", + "name": "leftArrowButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "rightArrowButtonText": { + "defaultValue": null, + "description": "Right arrow icon aria-label text", + "name": "rightArrowButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "getViewSwitchingButtonText": { + "defaultValue": null, + "description": "Get aria-label text for switching between views button", + "name": "getViewSwitchingButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", + "name": "CalendarHeaderProps" + }, + "required": false, + "type": { + "name": "(currentView: \"year\" | \"date\" | \"month\") => string" + } + }, + "mask": { + "defaultValue": null, + "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", + "name": "mask", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "minDate": { + "defaultValue": { + "value": "Date(1900-01-01)" + }, + "description": "Min selectable date", + "name": "minDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "maxDate": { + "defaultValue": { + "value": "Date(2100-01-01)" + }, + "description": "Max selectable date", + "name": "maxDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "disablePast": { + "defaultValue": { + "value": "false" + }, + "description": "Disable past dates", + "name": "disablePast", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableFuture": { + "defaultValue": { + "value": "false" + }, + "description": "Disable future dates", + "name": "disableFuture", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "reduceAnimations": { + "defaultValue": null, + "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", + "name": "reduceAnimations", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "onMonthChange": { + "defaultValue": null, + "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", + "name": "onMonthChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void | Promise" + } + }, + "shouldDisableDate": { + "defaultValue": null, + "description": "Disable specific date", + "name": "shouldDisableDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(day: DateIOType) => boolean" + } + }, + "onYearChange": { + "defaultValue": null, + "description": "Callback firing on year change", + "name": "onYearChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void" + } + }, + "renderDay": { + "defaultValue": null, + "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", + "name": "renderDay", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" + } + }, + "allowKeyboardControl": { + "defaultValue": { + "value": "currentWrapper !== 'static'" + }, + "description": "Enables keyboard listener for moving between days in calendar", + "name": "allowKeyboardControl", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "loadingIndicator": { + "defaultValue": null, + "description": "Custom loading indicator", + "name": "loadingIndicator", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "Element" + } + }, + "openTo": { + "defaultValue": null, + "description": "First view to show", + "name": "openTo", + "parent": { + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" + }, + "required": false, + "type": { + "name": "\"year\" | \"date\" | \"month\"" + } + }, + "TextFieldComponent": { + "defaultValue": null, + "description": "Override input component", + "name": "TextFieldComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "emptyInputText": { + "defaultValue": { + "value": "' '" + }, + "description": "Message displaying in read-only text field when null passed", + "name": "emptyInputText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "keyboardIcon": { + "defaultValue": null, + "description": "Icon displaying for open picker button", + "name": "keyboardIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maskChar": { + "defaultValue": { + "value": "'_'" + }, + "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", + "name": "maskChar", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "acceptRegex": { + "defaultValue": { + "value": "/\\dap/gi" + }, + "description": "Regular expression to detect \"accepted\" symbols", + "name": "acceptRegex", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "RegExp" + } + }, + "InputAdornmentProps": { + "defaultValue": null, + "description": "Props to pass to keyboard input adornment", + "name": "InputAdornmentProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "KeyboardButtonProps": { + "defaultValue": null, + "description": "Props to pass to keyboard adornment button", + "name": "KeyboardButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rifmFormatter": { + "defaultValue": null, + "description": "Custom formatter to be passed into Rifm component", + "name": "rifmFormatter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(str: string) => string" + } + }, + "disableOpenPicker": { + "defaultValue": { + "value": "false" + }, + "description": "Do not render open picker button (renders only text field with validation)", + "name": "disableOpenPicker", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableMaskedInput": { + "defaultValue": { + "value": "false" + }, + "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", + "name": "disableMaskedInput", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "getOpenDialogAriaText": { + "defaultValue": null, + "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", + "name": "getOpenDialogAriaText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(value: any, utils: MuiPickersAdapter) => string" + } + }, + "okLabel": { + "defaultValue": { + "value": "\"OK\"" + }, + "description": "\"OK\" label message", + "name": "okLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "cancelLabel": { + "defaultValue": { + "value": "\"CANCEL\"" + }, + "description": "\"CANCEL\" label message", + "name": "cancelLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "clearLabel": { + "defaultValue": { + "value": "\"CLEAR\"" + }, + "description": "\"CLEAR\" label message", + "name": "clearLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "todayLabel": { + "defaultValue": { + "value": "\"TODAY\"" + }, + "description": "\"TODAY\" label message", + "name": "todayLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "showTodayButton": { + "defaultValue": { + "value": "false" + }, + "description": "If true today button will be displayed. **Note** that clear button has higher priority", + "name": "showTodayButton", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "clearable": { + "defaultValue": { + "value": "false" + }, + "description": "Show clear action in picker dialog", + "name": "clearable", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "DialogProps": { + "defaultValue": null, + "description": "Props to be passed directly to material-ui Dialog", + "name": "DialogProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "displayStaticWrapperAs": { + "defaultValue": { + "value": "\"static\"" + }, + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" + }, + "required": false, + "type": { + "name": "\"desktop\" | \"mobile\" | \"static\"" + } + }, + "PopoverProps": { + "defaultValue": null, + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "desktopModeBreakpoint": { + "defaultValue": { + "value": "'md'" + }, + "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", + "name": "desktopModeBreakpoint", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", + "name": "ResponsiveWrapperProps" + }, + "required": false, + "type": { + "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" + } + }, + "dateAdapter": { + "defaultValue": null, + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" + }, + "required": false, + "type": { + "name": "MuiPickersAdapter" + } + }, + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + } + }, + "TimePicker": { + "value": { + "defaultValue": null, + "description": "Picker value", + "name": "value", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "any" + } + }, + "onChange": { + "defaultValue": null, + "description": "onChange callback", + "name": "onChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "(date: DateIOType, keyboardInputValue?: string) => void" + } + }, + "autoOk": { + "defaultValue": { + "value": "false" + }, + "description": "Auto accept date on selection", + "name": "autoOk", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "inputFormat": { + "defaultValue": null, + "description": "Format string", + "name": "inputFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "disabled": { + "defaultValue": null, + "description": "Disable picker and text field", + "name": "disabled", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "readOnly": { + "defaultValue": null, + "description": "Make picker read only", + "name": "readOnly", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "defaultHighlight": { + "defaultValue": null, + "description": "Date that will be initially highlighted if null was passed", + "name": "defaultHighlight", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "onAccept": { + "defaultValue": null, + "description": "Callback fired when date is accepted", + "name": "onAccept", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void" + } + }, + "onError": { + "defaultValue": null, + "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", + "name": "onError", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "(error: ReactNode, value: DateIOType) => void" + } + }, + "onOpen": { + "defaultValue": null, + "description": "On open callback", + "name": "onOpen", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "onClose": { + "defaultValue": null, + "description": "On close callback", + "name": "onClose", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "open": { + "defaultValue": null, + "description": "Controlled picker open state", + "name": "open", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "showToolbar": { + "defaultValue": null, + "description": "Show toolbar even in desktop mode", + "name": "showToolbar", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "orientation": { + "defaultValue": null, + "description": "Force rendering in particular orientation", + "name": "orientation", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "\"portrait\" | \"landscape\"" + } + }, + "ToolbarComponent": { + "defaultValue": null, + "description": "Component that will replace default toolbar renderer", + "name": "ToolbarComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ComponentClass, any> | FunctionComponent>" + } + }, + "toolbarTitle": { + "defaultValue": { + "value": "\"SELECT DATE\"" + }, + "description": "Mobile picker title, displaying in the toolbar", + "name": "toolbarTitle", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar", + "name": "toolbarFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "views": { + "defaultValue": null, + "description": "Array of views to show", + "name": "views", + "parent": { + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" + }, + "required": false, + "type": { + "name": "(\"hours\" | \"minutes\" | \"seconds\")[]" + } + }, + "mask": { + "defaultValue": null, + "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", + "name": "mask", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "allowKeyboardControl": { + "defaultValue": { + "value": "currentWrapper !== 'static'" + }, + "description": "Enables keyboard listener for moving between days in calendar", + "name": "allowKeyboardControl", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "TextFieldComponent": { + "defaultValue": null, + "description": "Override input component", + "name": "TextFieldComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "emptyInputText": { + "defaultValue": { + "value": "' '" + }, + "description": "Message displaying in read-only text field when null passed", + "name": "emptyInputText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "keyboardIcon": { + "defaultValue": null, + "description": "Icon displaying for open picker button", + "name": "keyboardIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maskChar": { + "defaultValue": { + "value": "'_'" + }, + "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", + "name": "maskChar", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "acceptRegex": { + "defaultValue": { + "value": "/\\dap/gi" + }, + "description": "Regular expression to detect \"accepted\" symbols", + "name": "acceptRegex", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "RegExp" + } + }, + "InputAdornmentProps": { + "defaultValue": null, + "description": "Props to pass to keyboard input adornment", + "name": "InputAdornmentProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "KeyboardButtonProps": { + "defaultValue": null, + "description": "Props to pass to keyboard adornment button", + "name": "KeyboardButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rifmFormatter": { + "defaultValue": null, + "description": "Custom formatter to be passed into Rifm component", + "name": "rifmFormatter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(str: string) => string" + } + }, + "disableOpenPicker": { + "defaultValue": { + "value": "false" + }, + "description": "Do not render open picker button (renders only text field with validation)", + "name": "disableOpenPicker", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableMaskedInput": { + "defaultValue": { + "value": "false" + }, + "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", + "name": "disableMaskedInput", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "getOpenDialogAriaText": { + "defaultValue": null, + "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", + "name": "getOpenDialogAriaText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(value: any, utils: MuiPickersAdapter) => string" + } + }, + "openTo": { + "defaultValue": null, + "description": "First view to show", + "name": "openTo", + "parent": { + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" + }, + "required": false, + "type": { + "name": "\"hours\" | \"minutes\" | \"seconds\"" + } + }, + "ampm": { + "defaultValue": { + "value": "true" + }, + "description": "12h/24h view for hour selection clock", + "name": "ampm", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "minutesStep": { + "defaultValue": { + "value": "1" + }, + "description": "Step over minutes", + "name": "minutesStep", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "number" + } + }, + "ampmInClock": { + "defaultValue": { + "value": "false" + }, + "description": "Display ampm controls under the clock (instead of in the toolbar)", + "name": "ampmInClock", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "minTime": { + "defaultValue": null, + "description": "Min time, date part by default, will be ignored", + "name": "minTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "maxTime": { + "defaultValue": null, + "description": "Max time, date part by default, will be ignored", + "name": "maxTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "shouldDisableTime": { + "defaultValue": null, + "description": "Dynamically check if time is disabled or not", + "name": "shouldDisableTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "(timeValue: number, clockType: \"hours\" | \"minutes\" | \"seconds\") => boolean" + } + }, + "disableTimeValidationIgnoreDatePart": { + "defaultValue": null, + "description": "Do not ignore date part when validating min/max time", + "name": "disableTimeValidationIgnoreDatePart", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "okLabel": { + "defaultValue": { + "value": "\"OK\"" + }, + "description": "\"OK\" label message", + "name": "okLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "cancelLabel": { + "defaultValue": { + "value": "\"CANCEL\"" + }, + "description": "\"CANCEL\" label message", + "name": "cancelLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "clearLabel": { + "defaultValue": { + "value": "\"CLEAR\"" + }, + "description": "\"CLEAR\" label message", + "name": "clearLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "todayLabel": { + "defaultValue": { + "value": "\"TODAY\"" + }, + "description": "\"TODAY\" label message", + "name": "todayLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "showTodayButton": { + "defaultValue": { + "value": "false" + }, + "description": "If true today button will be displayed. **Note** that clear button has higher priority", + "name": "showTodayButton", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "clearable": { + "defaultValue": { + "value": "false" + }, + "description": "Show clear action in picker dialog", + "name": "clearable", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "DialogProps": { + "defaultValue": null, + "description": "Props to be passed directly to material-ui Dialog", + "name": "DialogProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "displayStaticWrapperAs": { + "defaultValue": { + "value": "\"static\"" + }, + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" + }, + "required": false, + "type": { + "name": "\"desktop\" | \"mobile\" | \"static\"" + } + }, + "PopoverProps": { + "defaultValue": null, + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "desktopModeBreakpoint": { + "defaultValue": { + "value": "'md'" + }, + "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", + "name": "desktopModeBreakpoint", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", + "name": "ResponsiveWrapperProps" + }, + "required": false, + "type": { + "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" + } + }, + "dateAdapter": { + "defaultValue": null, + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" + }, + "required": false, + "type": { + "name": "MuiPickersAdapter" + } + }, + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + } + }, + "DateTimePicker": { + "value": { + "defaultValue": null, + "description": "Picker value", + "name": "value", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "any" + } + }, + "onChange": { + "defaultValue": null, + "description": "onChange callback", + "name": "onChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": true, + "type": { + "name": "(date: DateIOType, keyboardInputValue?: string) => void" + } + }, + "autoOk": { + "defaultValue": { + "value": "false" + }, + "description": "Auto accept date on selection", + "name": "autoOk", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "inputFormat": { + "defaultValue": null, + "description": "Format string", + "name": "inputFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "disabled": { + "defaultValue": null, + "description": "Disable picker and text field", + "name": "disabled", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "readOnly": { + "defaultValue": null, + "description": "Make picker read only", + "name": "readOnly", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "defaultHighlight": { + "defaultValue": null, + "description": "Date that will be initially highlighted if null was passed", + "name": "defaultHighlight", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "onAccept": { + "defaultValue": null, + "description": "Callback fired when date is accepted", + "name": "onAccept", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void" + } + }, + "onError": { + "defaultValue": null, + "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", + "name": "onError", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "(error: ReactNode, value: DateIOType) => void" + } + }, + "onOpen": { + "defaultValue": null, + "description": "On open callback", + "name": "onOpen", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "onClose": { + "defaultValue": null, + "description": "On close callback", + "name": "onClose", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "() => void" + } + }, + "open": { + "defaultValue": null, + "description": "Controlled picker open state", + "name": "open", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "showToolbar": { + "defaultValue": null, + "description": "Show toolbar even in desktop mode", + "name": "showToolbar", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "orientation": { + "defaultValue": null, + "description": "Force rendering in particular orientation", + "name": "orientation", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "\"portrait\" | \"landscape\"" + } + }, + "ToolbarComponent": { + "defaultValue": null, + "description": "Component that will replace default toolbar renderer", + "name": "ToolbarComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ComponentClass, any> | FunctionComponent>" + } + }, + "toolbarTitle": { + "defaultValue": { + "value": "\"SELECT DATE\"" + }, + "description": "Mobile picker title, displaying in the toolbar", + "name": "toolbarTitle", + "parent": { + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar\nDate format, that is displaying in toolbar", + "name": "toolbarFormat", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "views": { + "defaultValue": null, + "description": "Array of views to show", + "name": "views", + "parent": { + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" + }, + "required": false, + "type": { + "name": "(\"year\" | \"date\" | \"month\" | \"hours\" | \"minutes\")[]" + } + }, + "disableHighlightToday": { + "defaultValue": { + "value": "false" + }, + "description": "Disable highlighting today date with a circle", + "name": "disableHighlightToday", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "showDaysOutsideCurrentMonth": { + "defaultValue": { + "value": "false" + }, + "description": "Display disabled dates outside the current month", + "name": "showDaysOutsideCurrentMonth", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "leftArrowIcon": { + "defaultValue": null, + "description": "Left arrow icon", + "name": "leftArrowIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "rightArrowIcon": { + "defaultValue": null, + "description": "Right arrow icon", + "name": "rightArrowIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "leftArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to left arrow button", + "name": "leftArrowButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rightArrowButtonProps": { + "defaultValue": null, + "description": "Props to pass to right arrow button", + "name": "rightArrowButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "leftArrowButtonText": { + "defaultValue": null, + "description": "Left arrow icon aria-label text", + "name": "leftArrowButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "rightArrowButtonText": { + "defaultValue": null, + "description": "Right arrow icon aria-label text", + "name": "rightArrowButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "getViewSwitchingButtonText": { + "defaultValue": null, + "description": "Get aria-label text for switching between views button", + "name": "getViewSwitchingButtonText", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", + "name": "CalendarHeaderProps" + }, + "required": false, + "type": { + "name": "(currentView: \"year\" | \"date\" | \"month\") => string" + } + }, + "mask": { + "defaultValue": null, + "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", + "name": "mask", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "minDate": { + "defaultValue": { + "value": "Date(1900-01-01)" + }, + "description": "Min selectable date", + "name": "minDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "maxDate": { + "defaultValue": { + "value": "Date(2100-01-01)" + }, + "description": "Max selectable date", + "name": "maxDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "disablePast": { + "defaultValue": { + "value": "false" + }, + "description": "Disable past dates", + "name": "disablePast", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableFuture": { + "defaultValue": { + "value": "false" + }, + "description": "Disable future dates", + "name": "disableFuture", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "reduceAnimations": { + "defaultValue": null, + "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", + "name": "reduceAnimations", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "onMonthChange": { + "defaultValue": null, + "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", + "name": "onMonthChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void | Promise" + } + }, + "shouldDisableDate": { + "defaultValue": null, + "description": "Disable specific date", + "name": "shouldDisableDate", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(day: DateIOType) => boolean" + } + }, + "onYearChange": { + "defaultValue": null, + "description": "Callback firing on year change", + "name": "onYearChange", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" + }, + "required": false, + "type": { + "name": "(date: DateIOType) => void" + } + }, + "renderDay": { + "defaultValue": null, + "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", + "name": "renderDay", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" + } + }, + "allowKeyboardControl": { + "defaultValue": { + "value": "currentWrapper !== 'static'" + }, + "description": "Enables keyboard listener for moving between days in calendar", + "name": "allowKeyboardControl", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "loadingIndicator": { + "defaultValue": null, + "description": "Custom loading indicator", + "name": "loadingIndicator", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" + }, + "required": false, + "type": { + "name": "Element" + } + }, + "TextFieldComponent": { + "defaultValue": null, + "description": "Override input component", + "name": "TextFieldComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "emptyInputText": { + "defaultValue": { + "value": "' '" + }, + "description": "Message displaying in read-only text field when null passed", + "name": "emptyInputText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "keyboardIcon": { + "defaultValue": null, + "description": "Icon displaying for open picker button", + "name": "keyboardIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maskChar": { + "defaultValue": { + "value": "'_'" + }, + "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", + "name": "maskChar", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "string" + } + }, + "acceptRegex": { + "defaultValue": { + "value": "/\\dap/gi" + }, + "description": "Regular expression to detect \"accepted\" symbols", + "name": "acceptRegex", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "RegExp" + } + }, + "InputAdornmentProps": { + "defaultValue": null, + "description": "Props to pass to keyboard input adornment", + "name": "InputAdornmentProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "KeyboardButtonProps": { + "defaultValue": null, + "description": "Props to pass to keyboard adornment button", + "name": "KeyboardButtonProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "rifmFormatter": { + "defaultValue": null, + "description": "Custom formatter to be passed into Rifm component", + "name": "rifmFormatter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(str: string) => string" + } + }, + "disableOpenPicker": { + "defaultValue": { + "value": "false" + }, + "description": "Do not render open picker button (renders only text field with validation)", + "name": "disableOpenPicker", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "disableMaskedInput": { + "defaultValue": { + "value": "false" + }, + "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", + "name": "disableMaskedInput", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "getOpenDialogAriaText": { + "defaultValue": null, + "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", + "name": "getOpenDialogAriaText", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" + }, + "required": false, + "type": { + "name": "(value: any, utils: MuiPickersAdapter) => string" + } + }, + "openTo": { + "defaultValue": null, + "description": "First view to show", + "name": "openTo", + "parent": { + "fileName": "material-ui-pickers/lib/src/Picker/SharedPickerProps.tsx", + "name": "WithViewsProps" + }, + "required": false, + "type": { + "name": "\"year\" | \"date\" | \"month\" | \"hours\" | \"minutes\"" + } + }, + "ampm": { + "defaultValue": { + "value": "true" + }, + "description": "12h/24h view for hour selection clock", + "name": "ampm", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "minDateTime": { + "defaultValue": null, + "description": "Minimal selectable moment of time with binding to date, to set min time in each day use `minTime`", + "name": "minDateTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "maxDateTime": { + "defaultValue": null, + "description": "Minimal selectable moment of time with binding to date, to set max time in each day use `maxTime`", + "name": "maxDateTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "hideTabs": { + "defaultValue": null, + "description": "To show tabs", + "name": "hideTabs", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "dateRangeIcon": { + "defaultValue": null, + "description": "Date tab icon", + "name": "dateRangeIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "timeIcon": { + "defaultValue": null, + "description": "Time tab icon", + "name": "timeIcon", + "parent": { + "fileName": "material-ui-pickers/lib/src/DateTimePicker/DateTimePicker.tsx", + "name": "DateTimePickerProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "minutesStep": { + "defaultValue": { + "value": "1" + }, + "description": "Step over minutes", + "name": "minutesStep", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "number" + } + }, + "ampmInClock": { + "defaultValue": { + "value": "false" + }, + "description": "Display ampm controls under the clock (instead of in the toolbar)", + "name": "ampmInClock", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "minTime": { + "defaultValue": null, + "description": "Min time, date part by default, will be ignored", + "name": "minTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "maxTime": { + "defaultValue": null, + "description": "Max time, date part by default, will be ignored", + "name": "maxTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "any" + } + }, + "shouldDisableTime": { + "defaultValue": null, + "description": "Dynamically check if time is disabled or not", + "name": "shouldDisableTime", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "(timeValue: number, clockType: \"hours\" | \"minutes\" | \"seconds\") => boolean" + } + }, + "disableTimeValidationIgnoreDatePart": { + "defaultValue": null, + "description": "Do not ignore date part when validating min/max time", + "name": "disableTimeValidationIgnoreDatePart", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Clock/ClockView.tsx", + "name": "ExportedClockViewProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "okLabel": { + "defaultValue": { + "value": "\"OK\"" + }, + "description": "\"OK\" label message", + "name": "okLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "cancelLabel": { + "defaultValue": { + "value": "\"CANCEL\"" + }, + "description": "\"CANCEL\" label message", + "name": "cancelLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "clearLabel": { + "defaultValue": { + "value": "\"CLEAR\"" + }, + "description": "\"CLEAR\" label message", + "name": "clearLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "todayLabel": { + "defaultValue": { + "value": "\"TODAY\"" + }, + "description": "\"TODAY\" label message", + "name": "todayLabel", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "showTodayButton": { + "defaultValue": { + "value": "false" + }, + "description": "If true today button will be displayed. **Note** that clear button has higher priority", + "name": "showTodayButton", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "clearable": { + "defaultValue": { + "value": "false" + }, + "description": "Show clear action in picker dialog", + "name": "clearable", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "DialogProps": { + "defaultValue": null, + "description": "Props to be passed directly to material-ui Dialog", + "name": "DialogProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "PopperProps": { + "defaultValue": null, + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "TransitionComponent": { + "defaultValue": null, + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" + }, + "required": false, + "type": { + "name": "ComponentClass | FunctionComponent" + } + }, + "displayStaticWrapperAs": { + "defaultValue": { + "value": "\"static\"" + }, + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" + }, + "required": false, + "type": { + "name": "\"desktop\" | \"mobile\" | \"static\"" + } + }, + "PopoverProps": { + "defaultValue": null, + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" + }, + "required": false, + "type": { + "name": "Partial" + } + }, + "desktopModeBreakpoint": { + "defaultValue": { + "value": "'md'" + }, + "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", + "name": "desktopModeBreakpoint", + "parent": { + "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", + "name": "ResponsiveWrapperProps" + }, + "required": false, + "type": { + "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" + } + }, + "dateAdapter": { + "defaultValue": null, + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", + "parent": { + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" + }, + "required": false, + "type": { + "name": "MuiPickersAdapter" + } + }, + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + }, + "strictCompareDates": { + "defaultValue": { + "value": "false" + }, + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" + }, + "required": false, + "type": { + "name": "boolean" + } + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" + } + } + }, "DateRangePicker": { "startText": { "defaultValue": { diff --git a/lib/.size-snapshot.json b/lib/.size-snapshot.json index 19824edf3..b9c9ca289 100644 --- a/lib/.size-snapshot.json +++ b/lib/.size-snapshot.json @@ -1,26 +1,26 @@ { "build/dist/material-ui-pickers.esm.js": { - "bundled": 189902, - "minified": 102851, - "gzipped": 26620, + "bundled": 190777, + "minified": 103329, + "gzipped": 26701, "treeshaked": { "rollup": { - "code": 85313, - "import_statements": 2109 + "code": 85805, + "import_statements": 2112 }, "webpack": { - "code": 94396 + "code": 95022 } } }, "build/dist/material-ui-pickers.umd.js": { - "bundled": 300044, - "minified": 118386, - "gzipped": 33633 + "bundled": 300842, + "minified": 118907, + "gzipped": 33715 }, "build/dist/material-ui-pickers.umd.min.js": { - "bundled": 258834, - "minified": 109331, - "gzipped": 30893 + "bundled": 259632, + "minified": 109852, + "gzipped": 30972 } } diff --git a/lib/rollup.config.js b/lib/rollup.config.js index 256f87aac..a5ff7ff34 100644 --- a/lib/rollup.config.js +++ b/lib/rollup.config.js @@ -26,7 +26,7 @@ const globals = { '@material-ui/core/Grid': 'material-ui.Grid', '@material-ui/core/IconButton': 'material-ui.IconButton', '@material-ui/core/InputAdornment': 'material-ui.InputAdornment', - '@material-ui/core/utils/createSvgIcon': 'material-ui.createSvgIcon', + '@material-ui/core/utils': 'material-ui.utils', '@material-ui/core/Paper': 'material-ui.Paper', '@material-ui/core/Popover': 'material-ui.Popover', '@material-ui/core/styles': 'material-ui', diff --git a/lib/src/Picker/makePickerWithState.tsx b/lib/src/Picker/makePickerWithState.tsx index 7fb116b8f..5f2548934 100644 --- a/lib/src/Picker/makePickerWithState.tsx +++ b/lib/src/Picker/makePickerWithState.tsx @@ -3,7 +3,7 @@ import { useUtils } from '../_shared/hooks/useUtils'; import { ParsableDate } from '../constants/prop-types'; import { MaterialUiPickersDate } from '../typings/date'; import { parsePickerInputValue } from '../_helpers/date-utils'; -import { SomeWrapper, ExtendWrappe } from '../wrappers/Wrapper'; +import { SomeWrapper, ExtendWrapper } from '../wrappers/Wrapper'; import { KeyboardDateInput } from '../_shared/KeyboardDateInput'; import { usePickerState } from '../_shared/hooks/usePickerState'; import { validateDateValue } from '../_helpers/text-field-helper'; @@ -65,7 +65,10 @@ export function makePickerWithStateAndWrapper< maxDate, maxTime, minDate, + // @ts-ignore Especial DateTimePicker only prop that are needed only on the upper level minDateTime, + // @ts-ignore Especial DateTimePicker only prop that are needed only on the upper level + maxDateTime, minTime, minutesStep, onMonthChange, From 1a35fd39ff24a1b799e8759b0c0e3ee09faab704 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 9 Apr 2020 12:21:27 +0300 Subject: [PATCH 70/72] Update lib/src/__tests__/setup.js Co-Authored-By: Olivier Tassinari --- lib/src/__tests__/setup.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/src/__tests__/setup.js b/lib/src/__tests__/setup.js index 77bd4ba46..d1754915c 100644 --- a/lib/src/__tests__/setup.js +++ b/lib/src/__tests__/setup.js @@ -5,6 +5,7 @@ const EnzymeAdapter = require('enzyme-adapter-react-16'); Enzyme.configure({ adapter: new EnzymeAdapter() }); // Fix popper mount https://github.com/mui-org/material-ui/issues/15726 +// TODO, upgrade jsdom to 16.0.0 and remove this line. document.createRange = () => ({ setStart: () => {}, setEnd: () => {}, From 29191fc44cf6a76346d821cc33a1287798004ede Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 9 Apr 2020 12:31:33 +0300 Subject: [PATCH 71/72] Address review --- .../DateRangePicker/DateRangePickerInput.tsx | 7 +++--- .../DateRangePickerViewDesktop.tsx | 22 +++++++++++++++---- .../DateRangePickerViewMobile.tsx | 6 ++--- lib/src/_helpers/utils.ts | 2 ++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index f58f8d061..a5c4d979e 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -8,14 +8,13 @@ import { makeStyles } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { CurrentlySelectingRangeEndProps } from './RangeTypes'; -import { createDelegatedEventHandler } from '../_helpers/utils'; +import { createDelegatedEventHandler, doNothing } from '../_helpers/utils'; export const useStyles = makeStyles( theme => ({ rangeInputsContainer: { display: 'flex', alignItems: 'center', - // ? TBD [theme.breakpoints.down('xs')]: { flexDirection: 'column', }, @@ -121,7 +120,7 @@ export const DateRangePickerInput: React.FC = ({ parsedDateValue={start} onChange={handleStartChange} disableOpenPicker - openPicker={() => {}} + openPicker={doNothing} readOnly={readOnly} label={startText} focused={open && currentlySelectingRangeEnd === 'start'} @@ -143,7 +142,7 @@ export const DateRangePickerInput: React.FC = ({ parsedDateValue={end} onChange={handleEndChange} disableOpenPicker - openPicker={() => {}} + openPicker={doNothing} readOnly={readOnly} label={endText} focused={open && currentlySelectingRangeEnd === 'end'} diff --git a/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx b/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx index d29d59d30..f3e0da160 100644 --- a/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx +++ b/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx @@ -55,6 +55,20 @@ export const useStyles = makeStyles( { name: 'MuiPickersDesktopDateRangeCalendar' } ); +function getCalendarsArray(calendars: ExportedDesktopDateRangeCalendarProps['calendars']) { + switch (calendars) { + case 1: + return [0]; + case 2: + return [0, 0]; + case 3: + return [0, 0, 0]; + // this will not work in IE11, but allows to support any amount of calendars + default: + return new Array(calendars).fill(0); + } +} + export const DateRangePickerViewDesktop: React.FC = ({ date, calendars = 2, @@ -71,11 +85,11 @@ export const DateRangePickerViewDesktop: React.FC minDate, maxDate, currentlySelectingRangeEnd, - ...CalendarProps + currentMonth, + ...other }) => { const utils = useUtils(); const classes = useStyles(); - const { currentMonth } = CalendarProps; const [rangePreviewDay, setRangePreviewDay] = React.useState(null); const isNextMonthDisabled = useNextMonthDisabled(currentMonth, { disableFuture, maxDate }); @@ -121,7 +135,7 @@ export const DateRangePickerViewDesktop: React.FC return (
- {new Array(calendars).fill(0).map((_, index) => { + {getCalendarsArray(calendars).map((_, index) => { const monthOnIteration = utils.setMonth(currentMonth, utils.getMonth(currentMonth) + index); return ( @@ -144,7 +158,7 @@ export const DateRangePickerViewDesktop: React.FC /> rightArrowButtonText, rightArrowIcon, onChange, - ...CalendarProps + ...other }) => { const utils = useUtils(); @@ -47,11 +47,11 @@ export const DateRangePickerViewMobile: React.FC rightArrowButtonProps={rightArrowButtonProps} rightArrowButtonText={rightArrowButtonText} rightArrowIcon={rightArrowIcon} - {...CalendarProps} + {...other} /> ( diff --git a/lib/src/_helpers/utils.ts b/lib/src/_helpers/utils.ts index 5f701c1b6..b15c6bbbc 100644 --- a/lib/src/_helpers/utils.ts +++ b/lib/src/_helpers/utils.ts @@ -47,3 +47,5 @@ export function createDelegatedEventHandler( } }; } + +export const doNothing = () => {}; From 12d5064a3c5980891752225e9a326f0a3a24ac0b Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Thu, 9 Apr 2020 13:24:35 +0300 Subject: [PATCH 72/72] forwardRef for DateRangePicker --- docs/prop-types.json | 978 +++++++++--------- lib/src/DateRangePicker/DateRangePicker.tsx | 16 +- .../DateRangePicker/DateRangePickerInput.tsx | 15 +- lib/src/__tests__/DateRangePicker.test.tsx | 27 + lib/src/_helpers/utils.ts | 13 + lib/src/_shared/KeyboardDateInput.tsx | 4 +- lib/src/_shared/PureDateInput.tsx | 9 +- 7 files changed, 556 insertions(+), 506 deletions(-) diff --git a/docs/prop-types.json b/docs/prop-types.json index 016e244aa..f5837f83d 100644 --- a/docs/prop-types.json +++ b/docs/prop-types.json @@ -3106,961 +3106,961 @@ } }, "DateRangePicker": { - "startText": { - "defaultValue": { - "value": "\"Start\"" - }, - "description": "Text for start input label and toolbar placeholder", - "name": "startText", + "mask": { + "defaultValue": null, + "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", + "name": "mask", "parent": { - "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePicker.tsx", - "name": "DateRangePickerProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "string" } }, - "endText": { - "defaultValue": { - "value": "\"end\"" - }, - "description": "Text for end input label and toolbar placeholder", - "name": "endText", + "onChange": { + "defaultValue": null, + "description": "onChange callback", + "name": "onChange", "parent": { - "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePicker.tsx", - "name": "DateRangePickerProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { - "name": "ReactNode" + "name": "(date: DateRange, keyboardInputValue?: string) => void" } }, - "disableAutoMonthSwitching": { - "defaultValue": { - "value": "false" - }, - "description": "if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date", - "name": "disableAutoMonthSwitching", + "inputFormat": { + "defaultValue": null, + "description": "Format string", + "name": "inputFormat", "parent": { - "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePickerView.tsx", - "name": "ExportedDateRangePickerViewProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "string" } }, - "disableHighlightToday": { - "defaultValue": { - "value": "false" - }, - "description": "Disable highlighting today date with a circle", - "name": "disableHighlightToday", + "open": { + "defaultValue": null, + "description": "Controlled picker open state", + "name": "open", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "boolean" } }, - "showDaysOutsideCurrentMonth": { - "defaultValue": { - "value": "false" - }, - "description": "Display disabled dates outside the current month", - "name": "showDaysOutsideCurrentMonth", + "onError": { + "defaultValue": null, + "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", + "name": "onError", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", - "name": "DayProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "((error: ReactNode, value: DateIOType) => void) & ((error: ReactNode, value: RangeInput | DateRange) => void)" } }, - "leftArrowIcon": { + "value": { "defaultValue": null, - "description": "Left arrow icon", - "name": "leftArrowIcon", + "description": "Picker value", + "name": "value", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, - "required": false, + "required": true, "type": { - "name": "ReactNode" + "name": "RangeInput" } }, - "rightArrowIcon": { + "disabled": { "defaultValue": null, - "description": "Right arrow icon", - "name": "rightArrowIcon", + "description": "Disable picker and text field", + "name": "disabled", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "boolean" } }, - "leftArrowButtonProps": { + "readOnly": { "defaultValue": null, - "description": "Props to pass to left arrow button", - "name": "leftArrowButtonProps", + "description": "Make picker read only", + "name": "readOnly", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "Partial" + "name": "boolean" } }, - "rightArrowButtonProps": { + "TextFieldComponent": { "defaultValue": null, - "description": "Props to pass to right arrow button", - "name": "rightArrowButtonProps", + "description": "Override input component", + "name": "TextFieldComponent", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "Partial" + "name": "ComponentClass | FunctionComponent" } }, - "leftArrowButtonText": { - "defaultValue": null, - "description": "Left arrow icon aria-label text", - "name": "leftArrowButtonText", + "emptyInputText": { + "defaultValue": { + "value": "' '" + }, + "description": "Message displaying in read-only text field when null passed", + "name": "emptyInputText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { "name": "string" } }, - "rightArrowButtonText": { + "keyboardIcon": { "defaultValue": null, - "description": "Right arrow icon aria-label text", - "name": "rightArrowButtonText", + "description": "Icon displaying for open picker button", + "name": "keyboardIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", - "name": "ExportedArrowSwitcherProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "string" + "name": "ReactNode" } }, - "getViewSwitchingButtonText": { - "defaultValue": null, - "description": "Get aria-label text for switching between views button", - "name": "getViewSwitchingButtonText", + "maskChar": { + "defaultValue": { + "value": "'_'" + }, + "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", + "name": "maskChar", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", - "name": "CalendarHeaderProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(currentView: DatePickerView) => string" + "name": "string" } }, - "minDate": { + "acceptRegex": { "defaultValue": { - "value": "Date(1900-01-01)" + "value": "/\\dap/gi" }, - "description": "Min selectable date", - "name": "minDate", + "description": "Regular expression to detect \"accepted\" symbols", + "name": "acceptRegex", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "any" + "name": "RegExp" } }, - "maxDate": { - "defaultValue": { - "value": "Date(2100-01-01)" - }, - "description": "Max selectable date", - "name": "maxDate", + "InputAdornmentProps": { + "defaultValue": null, + "description": "Props to pass to keyboard input adornment", + "name": "InputAdornmentProps", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "any" + "name": "Partial" } }, - "disablePast": { - "defaultValue": { - "value": "false" - }, - "description": "Disable past dates", - "name": "disablePast", + "KeyboardButtonProps": { + "defaultValue": null, + "description": "Props to pass to keyboard adornment button", + "name": "KeyboardButtonProps", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "boolean" + "name": "Partial" } }, - "disableFuture": { - "defaultValue": { - "value": "false" - }, - "description": "Disable future dates", - "name": "disableFuture", + "rifmFormatter": { + "defaultValue": null, + "description": "Custom formatter to be passed into Rifm component", + "name": "rifmFormatter", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "boolean" + "name": "(str: string) => string" } }, - "reduceAnimations": { - "defaultValue": null, - "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", - "name": "reduceAnimations", + "disableOpenPicker": { + "defaultValue": { + "value": "false" + }, + "description": "Do not render open picker button (renders only text field with validation)", + "name": "disableOpenPicker", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { "name": "boolean" } }, - "onMonthChange": { - "defaultValue": null, - "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", - "name": "onMonthChange", + "disableMaskedInput": { + "defaultValue": { + "value": "false" + }, + "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", + "name": "disableMaskedInput", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(date: DateIOType) => void | Promise" + "name": "boolean" } }, - "shouldDisableDate": { + "getOpenDialogAriaText": { "defaultValue": null, - "description": "Disable specific date", - "name": "shouldDisableDate", + "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", + "name": "getOpenDialogAriaText", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", - "name": "CalendarViewProps" + "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", + "name": "DateInputProps" }, "required": false, "type": { - "name": "(day: DateIOType) => boolean" + "name": "(value: any, utils: MuiPickersAdapter) => string" } }, - "renderDay": { + "onAccept": { "defaultValue": null, - "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", - "name": "renderDay", + "description": "Callback fired when date is accepted", + "name": "onAccept", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" + "name": "((date: DateIOType) => void) & ((date: DateRange) => void)" } }, - "allowKeyboardControl": { + "okLabel": { "defaultValue": { - "value": "currentWrapper !== 'static'" + "value": "\"OK\"" }, - "description": "Enables keyboard listener for moving between days in calendar", - "name": "allowKeyboardControl", + "description": "\"OK\" label message", + "name": "okLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "boolean" + "name": "ReactNode" } }, - "loadingIndicator": { - "defaultValue": null, - "description": "Custom loading indicator", - "name": "loadingIndicator", + "cancelLabel": { + "defaultValue": { + "value": "\"CANCEL\"" + }, + "description": "\"CANCEL\" label message", + "name": "cancelLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", - "name": "ExportedCalendarProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "Element" + "name": "ReactNode" } }, - "calendars": { + "clearLabel": { "defaultValue": { - "value": "2" + "value": "\"CLEAR\"" }, - "description": "How many calendars render on **desktop** DateRangePicker", - "name": "calendars", + "description": "\"CLEAR\" label message", + "name": "clearLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx", - "name": "ExportedDesktopDateRangeCalendarProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "2 | 1 | 3" + "name": "ReactNode" } }, - "onError": { - "defaultValue": null, - "description": "Callback fired when new error should be displayed\n(!! This is a side effect. Be careful if you want to rerender the component)", - "name": "onError", + "todayLabel": { + "defaultValue": { + "value": "\"TODAY\"" + }, + "description": "\"TODAY\" label message", + "name": "todayLabel", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "((error: ReactNode, value: DateIOType) => void) & ((error: ReactNode, value: RangeInput | DateRange) => void)" + "name": "ReactNode" } }, - "onClose": { - "defaultValue": null, - "description": "On close callback", - "name": "onClose", + "showTodayButton": { + "defaultValue": { + "value": "false" + }, + "description": "If true today button will be displayed. **Note** that clear button has higher priority", + "name": "showTodayButton", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "() => void" + "name": "boolean" } }, - "open": { - "defaultValue": null, - "description": "Controlled picker open state", - "name": "open", + "clearable": { + "defaultValue": { + "value": "false" + }, + "description": "Show clear action in picker dialog", + "name": "clearable", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { "name": "boolean" } }, - "inputFormat": { + "DialogProps": { "defaultValue": null, - "description": "Format string", - "name": "inputFormat", + "description": "Props to be passed directly to material-ui Dialog", + "name": "DialogProps", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", + "name": "InnerMobileWrapperProps" }, "required": false, "type": { - "name": "string" + "name": "Partial" } }, - "disabled": { + "PopperProps": { "defaultValue": null, - "description": "Disable picker and text field", - "name": "disabled", + "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", + "name": "PopperProps", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" }, "required": false, "type": { - "name": "boolean" + "name": "Partial" } }, - "readOnly": { + "TransitionComponent": { "defaultValue": null, - "description": "Make picker read only", - "name": "readOnly", + "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", + "name": "TransitionComponent", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", + "name": "InnerDesktopPopperWrapperProps" }, "required": false, "type": { - "name": "boolean" + "name": "ComponentClass | FunctionComponent" } }, - "onAccept": { - "defaultValue": null, - "description": "Callback fired when date is accepted", - "name": "onAccept", + "displayStaticWrapperAs": { + "defaultValue": { + "value": "\"static\"" + }, + "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", + "name": "displayStaticWrapperAs", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", + "name": "StaticWrapperProps" }, "required": false, "type": { - "name": "((date: DateIOType) => void) & ((date: DateRange) => void)" + "name": "\"desktop\" | \"mobile\" | \"static\"" } }, - "autoOk": { - "defaultValue": { - "value": "false" - }, - "description": "Auto accept date on selection", - "name": "autoOk", + "PopoverProps": { + "defaultValue": null, + "description": "Popover props passed to material-ui Popover", + "name": "PopoverProps", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", + "name": "InnerDesktopWrapperProps" }, "required": false, "type": { - "name": "boolean" + "name": "Partial" } }, - "defaultHighlight": { + "onClose": { "defaultValue": null, - "description": "Date that will be initially highlighted if null was passed", - "name": "defaultHighlight", + "description": "On close callback", + "name": "onClose", "parent": { "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", "name": "BasePickerProps" }, "required": false, "type": { - "name": "any" + "name": "() => void" } }, - "onOpen": { - "defaultValue": null, - "description": "On open callback", - "name": "onOpen", + "desktopModeBreakpoint": { + "defaultValue": { + "value": "'md'" + }, + "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", + "name": "desktopModeBreakpoint", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", + "name": "ResponsiveWrapperProps" }, "required": false, "type": { - "name": "() => void" + "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" } }, - "showToolbar": { - "defaultValue": null, - "description": "Show toolbar even in desktop mode", - "name": "showToolbar", + "disableHighlightToday": { + "defaultValue": { + "value": "false" + }, + "description": "Disable highlighting today date with a circle", + "name": "disableHighlightToday", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" }, "required": false, "type": { "name": "boolean" } }, - "orientation": { - "defaultValue": null, - "description": "Force rendering in particular orientation", - "name": "orientation", + "showDaysOutsideCurrentMonth": { + "defaultValue": { + "value": "false" + }, + "description": "Display disabled dates outside the current month", + "name": "showDaysOutsideCurrentMonth", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Day.tsx", + "name": "DayProps" }, "required": false, "type": { - "name": "\"portrait\" | \"landscape\"" + "name": "boolean" } }, - "ToolbarComponent": { + "leftArrowIcon": { "defaultValue": null, - "description": "Component that will replace default toolbar renderer", - "name": "ToolbarComponent", + "description": "Left arrow icon", + "name": "leftArrowIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "ComponentClass, any> | FunctionComponent>" + "name": "ReactNode" } }, - "toolbarTitle": { - "defaultValue": { - "value": "\"SELECT DATE\"" - }, - "description": "Mobile picker title, displaying in the toolbar", - "name": "toolbarTitle", + "rightArrowIcon": { + "defaultValue": null, + "description": "Right arrow icon", + "name": "rightArrowIcon", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { "name": "ReactNode" } }, - "toolbarFormat": { + "leftArrowButtonProps": { "defaultValue": null, - "description": "Date format, that is displaying in toolbar", - "name": "toolbarFormat", + "description": "Props to pass to left arrow button", + "name": "leftArrowButtonProps", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { - "name": "string" + "name": "Partial" } }, - "value": { + "rightArrowButtonProps": { "defaultValue": null, - "description": "Picker value", - "name": "value", + "description": "Props to pass to right arrow button", + "name": "rightArrowButtonProps", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, - "required": true, + "required": false, "type": { - "name": "RangeInput" + "name": "Partial" } }, - "onChange": { + "leftArrowButtonText": { "defaultValue": null, - "description": "onChange callback", - "name": "onChange", + "description": "Left arrow icon aria-label text", + "name": "leftArrowButtonText", "parent": { - "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", - "name": "BasePickerProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, - "required": true, + "required": false, "type": { - "name": "(date: DateRange, keyboardInputValue?: string) => void" + "name": "string" } }, - "mask": { + "rightArrowButtonText": { "defaultValue": null, - "description": "Custom mask. Can be used to override generate from format. (e.g. __/__/____ __:__)", - "name": "mask", + "description": "Right arrow icon aria-label text", + "name": "rightArrowButtonText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/_shared/ArrowSwitcher.tsx", + "name": "ExportedArrowSwitcherProps" }, "required": false, "type": { "name": "string" } }, - "TextFieldComponent": { + "getViewSwitchingButtonText": { "defaultValue": null, - "description": "Override input component", - "name": "TextFieldComponent", + "description": "Get aria-label text for switching between views button", + "name": "getViewSwitchingButtonText", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarHeader.tsx", + "name": "CalendarHeaderProps" }, "required": false, "type": { - "name": "ComponentClass | FunctionComponent" + "name": "(currentView: DatePickerView) => string" } }, - "emptyInputText": { + "minDate": { "defaultValue": { - "value": "' '" + "value": "Date(1900-01-01)" }, - "description": "Message displaying in read-only text field when null passed", - "name": "emptyInputText", + "description": "Min selectable date", + "name": "minDate", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "string" + "name": "any" } }, - "keyboardIcon": { - "defaultValue": null, - "description": "Icon displaying for open picker button", - "name": "keyboardIcon", + "maxDate": { + "defaultValue": { + "value": "Date(2100-01-01)" + }, + "description": "Max selectable date", + "name": "maxDate", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "any" } }, - "maskChar": { + "disablePast": { "defaultValue": { - "value": "'_'" + "value": "false" }, - "description": "Char string that will be replaced with number (for \"_\" mask will be \"__/__/____\")", - "name": "maskChar", + "description": "Disable past dates", + "name": "disablePast", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "string" + "name": "boolean" } }, - "acceptRegex": { + "disableFuture": { "defaultValue": { - "value": "/\\dap/gi" + "value": "false" }, - "description": "Regular expression to detect \"accepted\" symbols", - "name": "acceptRegex", + "description": "Disable future dates", + "name": "disableFuture", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "RegExp" + "name": "boolean" } }, - "InputAdornmentProps": { + "reduceAnimations": { "defaultValue": null, - "description": "Props to pass to keyboard input adornment", - "name": "InputAdornmentProps", + "description": "Disable heavy animations @default /(android)/i.test(window.navigator.userAgent)", + "name": "reduceAnimations", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "Partial" + "name": "boolean" } }, - "KeyboardButtonProps": { + "onMonthChange": { "defaultValue": null, - "description": "Props to pass to keyboard adornment button", - "name": "KeyboardButtonProps", + "description": "Callback firing on month change. Return promise to render spinner till it will not be resolved", + "name": "onMonthChange", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "Partial" + "name": "(date: DateIOType) => void | Promise" } }, - "rifmFormatter": { + "shouldDisableDate": { "defaultValue": null, - "description": "Custom formatter to be passed into Rifm component", - "name": "rifmFormatter", + "description": "Disable specific date", + "name": "shouldDisableDate", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/CalendarView.tsx", + "name": "CalendarViewProps" }, "required": false, "type": { - "name": "(str: string) => string" + "name": "(day: DateIOType) => boolean" } }, - "disableOpenPicker": { - "defaultValue": { - "value": "false" - }, - "description": "Do not render open picker button (renders only text field with validation)", - "name": "disableOpenPicker", + "renderDay": { + "defaultValue": null, + "description": "Custom renderer for day. Check [DayComponentProps api](https://material-ui-pickers.dev/api/Day)", + "name": "renderDay", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "boolean" + "name": "(day: DateIOType, selectedDates: DateIOType[], DayComponentProps: DayProps) => Element" } }, - "disableMaskedInput": { + "allowKeyboardControl": { "defaultValue": { - "value": "false" - }, - "description": "Disable mask on the keyboard, this should be used rarely. Consider passing proper mask for your format", - "name": "disableMaskedInput", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "value": "currentWrapper !== 'static'" }, - "required": false, - "type": { - "name": "boolean" - } - }, - "getOpenDialogAriaText": { - "defaultValue": null, - "description": "Get aria-label text for control that opens datepicker dialog. Aria-label have to include selected date.", - "name": "getOpenDialogAriaText", - "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/PureDateInput.tsx", - "name": "DateInputProps" + "description": "Enables keyboard listener for moving between days in calendar", + "name": "allowKeyboardControl", + "parent": { + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "(value: any, utils: MuiPickersAdapter) => string" + "name": "boolean" } }, - "dateAdapter": { + "loadingIndicator": { "defaultValue": null, - "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", - "name": "dateAdapter", + "description": "Custom loading indicator", + "name": "loadingIndicator", "parent": { - "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", - "name": "WithDateAdapterProps" + "fileName": "material-ui-pickers/lib/src/views/Calendar/Calendar.tsx", + "name": "ExportedCalendarProps" }, "required": false, "type": { - "name": "MuiPickersAdapter" + "name": "Element" } }, - "minDateMessage": { + "autoOk": { "defaultValue": { - "value": "'Date should not be before minimal date'" + "value": "false" }, - "description": "Error message, shown if date is less then minimal date", - "name": "minDateMessage", + "description": "Auto accept date on selection", + "name": "autoOk", "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "boolean" } }, - "maxDateMessage": { - "defaultValue": { - "value": "'Date should not be after maximal date'" - }, - "description": "Error message, shown if date is more then maximal date", - "name": "maxDateMessage", + "defaultHighlight": { + "defaultValue": null, + "description": "Date that will be initially highlighted if null was passed", + "name": "defaultHighlight", "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "any" } }, - "strictCompareDates": { - "defaultValue": { - "value": "false" - }, - "description": "Compare dates by the exact timestamp, instead of start/end of date", - "name": "strictCompareDates", + "onOpen": { + "defaultValue": null, + "description": "On open callback", + "name": "onOpen", "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "DateValidationProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "boolean" + "name": "() => void" } }, - "invalidDateMessage": { - "defaultValue": { - "value": "'Invalid Date Format'" - }, - "description": "Message, appearing when date cannot be parsed", - "name": "invalidDateMessage", + "showToolbar": { + "defaultValue": null, + "description": "Show toolbar even in desktop mode", + "name": "showToolbar", "parent": { - "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", - "name": "BaseValidationProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "boolean" } }, - "PopoverProps": { + "orientation": { "defaultValue": null, - "description": "Popover props passed to material-ui Popover", - "name": "PopoverProps", + "description": "Force rendering in particular orientation", + "name": "orientation", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopWrapper.tsx", - "name": "InnerDesktopWrapperProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "Partial" + "name": "\"portrait\" | \"landscape\"" } }, - "displayStaticWrapperAs": { - "defaultValue": { - "value": "\"static\"" - }, - "description": "Force static wrapper inner components to be rendered in mobile or desktop mode", - "name": "displayStaticWrapperAs", + "ToolbarComponent": { + "defaultValue": null, + "description": "Component that will replace default toolbar renderer", + "name": "ToolbarComponent", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/StaticWrapper.tsx", - "name": "StaticWrapperProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "\"desktop\" | \"mobile\" | \"static\"" + "name": "ComponentClass, any> | FunctionComponent>" } }, - "okLabel": { + "toolbarTitle": { "defaultValue": { - "value": "\"OK\"" + "value": "\"SELECT DATE\"" }, - "description": "\"OK\" label message", - "name": "okLabel", + "description": "Mobile picker title, displaying in the toolbar", + "name": "toolbarTitle", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { "name": "ReactNode" } }, - "cancelLabel": { - "defaultValue": { - "value": "\"CANCEL\"" - }, - "description": "\"CANCEL\" label message", - "name": "cancelLabel", + "toolbarFormat": { + "defaultValue": null, + "description": "Date format, that is displaying in toolbar", + "name": "toolbarFormat", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/typings/BasePicker.tsx", + "name": "BasePickerProps" }, "required": false, "type": { - "name": "ReactNode" + "name": "string" } }, - "clearLabel": { + "startText": { "defaultValue": { - "value": "\"CLEAR\"" + "value": "\"Start\"" }, - "description": "\"CLEAR\" label message", - "name": "clearLabel", + "description": "Text for start input label and toolbar placeholder", + "name": "startText", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePicker.tsx", + "name": "DateRangePickerProps" }, "required": false, "type": { "name": "ReactNode" } }, - "todayLabel": { + "endText": { "defaultValue": { - "value": "\"TODAY\"" + "value": "\"end\"" }, - "description": "\"TODAY\" label message", - "name": "todayLabel", + "description": "Text for end input label and toolbar placeholder", + "name": "endText", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePicker.tsx", + "name": "DateRangePickerProps" }, "required": false, "type": { "name": "ReactNode" } }, - "showTodayButton": { + "disableAutoMonthSwitching": { "defaultValue": { "value": "false" }, - "description": "If true today button will be displayed. **Note** that clear button has higher priority", - "name": "showTodayButton", + "description": "if `true` after selecting `start` date calendar will not automatically switch to the month of `end` date", + "name": "disableAutoMonthSwitching", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePickerView.tsx", + "name": "ExportedDateRangePickerViewProps" }, "required": false, "type": { "name": "boolean" } }, - "clearable": { + "calendars": { "defaultValue": { - "value": "false" + "value": "2" }, - "description": "Show clear action in picker dialog", - "name": "clearable", + "description": "How many calendars render on **desktop** DateRangePicker", + "name": "calendars", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/DateRangePicker/DateRangePickerViewDesktop.tsx", + "name": "ExportedDesktopDateRangeCalendarProps" }, "required": false, "type": { - "name": "boolean" + "name": "2 | 1 | 3" } }, - "DialogProps": { + "dateAdapter": { "defaultValue": null, - "description": "Props to be passed directly to material-ui Dialog", - "name": "DialogProps", + "description": "Allows to pass configured date-io adapter directly. More info [here](https://material-ui-pickers.dev/guides/date-adapter-passing)\n```jsx\ndateAdapter={new DateFnsAdapter({ locale: ruLocale })}\n```", + "name": "dateAdapter", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/MobileWrapper.tsx", - "name": "InnerMobileWrapperProps" + "fileName": "material-ui-pickers/lib/src/_shared/withDateAdapterProp.tsx", + "name": "WithDateAdapterProps" }, "required": false, "type": { - "name": "Partial" + "name": "MuiPickersAdapter" } }, - "PopperProps": { - "defaultValue": null, - "description": "Popper props passed to material-ui [Popper](https://material-ui.com/api/popper/#popper-api)", - "name": "PopperProps", + "minDateMessage": { + "defaultValue": { + "value": "'Date should not be before minimal date'" + }, + "description": "Error message, shown if date is less then minimal date", + "name": "minDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "Partial" + "name": "ReactNode" } }, - "TransitionComponent": { - "defaultValue": null, - "description": "Custom component for [transition](https://material-ui.com/components/transitions/#transitioncomponent-prop)", - "name": "TransitionComponent", + "maxDateMessage": { + "defaultValue": { + "value": "'Date should not be after maximal date'" + }, + "description": "Error message, shown if date is more then maximal date", + "name": "maxDateMessage", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/DesktopPopperWrapper.tsx", - "name": "InnerDesktopPopperWrapperProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "ComponentClass | FunctionComponent" + "name": "ReactNode" } }, - "desktopModeBreakpoint": { + "strictCompareDates": { "defaultValue": { - "value": "'md'" + "value": "false" }, - "description": "Breakpoint when `Desktop` mode will be changed to `Mobile`", - "name": "desktopModeBreakpoint", + "description": "Compare dates by the exact timestamp, instead of start/end of date", + "name": "strictCompareDates", "parent": { - "fileName": "material-ui-pickers/lib/src/wrappers/ResponsiveWrapper.tsx", - "name": "ResponsiveWrapperProps" + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "DateValidationProps" }, "required": false, "type": { - "name": "\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"" + "name": "boolean" + } + }, + "invalidDateMessage": { + "defaultValue": { + "value": "'Invalid Date Format'" + }, + "description": "Message, appearing when date cannot be parsed", + "name": "invalidDateMessage", + "parent": { + "fileName": "material-ui-pickers/lib/src/_helpers/text-field-helper.ts", + "name": "BaseValidationProps" + }, + "required": false, + "type": { + "name": "ReactNode" } } }, diff --git a/lib/src/DateRangePicker/DateRangePicker.tsx b/lib/src/DateRangePicker/DateRangePicker.tsx index 0a579fb5c..a9f7232e7 100644 --- a/lib/src/DateRangePicker/DateRangePicker.tsx +++ b/lib/src/DateRangePicker/DateRangePicker.tsx @@ -24,7 +24,7 @@ export function parseRangeInputValue( date === null ? null : utils.startOfDay(parsePickerInputValue(now, utils, { value: date, defaultHighlight })) - ) as DateRange; + ) as DateRangeType; } interface DateRangePickerProps @@ -64,6 +64,8 @@ export function makeRangePicker(Wrapper: TWrapper) reduceAnimations, value, onChange, + mask = '__/__/____', + variant = 'outlined', startText = 'Start', endText = 'End', inputFormat: passedInputFormat, @@ -98,6 +100,8 @@ export function makeRangePicker(Wrapper: TWrapper) setCurrentlySelectingRangeEnd, startText, endText, + mask, + variant, }; return ( @@ -129,12 +133,10 @@ export function makeRangePicker(Wrapper: TWrapper) ); } - RangePickerWithStateAndWrapper.defaultProps = { - mask: '__/__/____', - variant: 'outlined', - }; - - return RangePickerWithStateAndWrapper; + return React.forwardRef< + HTMLDivElement, + React.ComponentProps + >((props, ref) => ); } // TODO replace with new export type syntax diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index a5c4d979e..fa8fefc80 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -8,7 +8,7 @@ import { makeStyles } from '@material-ui/core/styles'; import { MaterialUiPickersDate } from '../typings/date'; import { DateInputProps } from '../_shared/PureDateInput'; import { CurrentlySelectingRangeEndProps } from './RangeTypes'; -import { createDelegatedEventHandler, doNothing } from '../_helpers/utils'; +import { mergeRefs, createDelegatedEventHandler, doNothing } from '../_helpers/utils'; export const useStyles = makeStyles( theme => ({ @@ -36,9 +36,11 @@ export interface ExportedDateRangePickerInputProps { export interface DateRangeInputProps extends ExportedDateRangePickerInputProps, CurrentlySelectingRangeEndProps, - DateInputProps { + Omit, 'forwardedRef'> { startText: React.ReactNode; endText: React.ReactNode; + forwardedRef?: React.Ref; + containerRef?: React.Ref; } export const DateRangePickerInput: React.FC = ({ @@ -46,7 +48,7 @@ export const DateRangePickerInput: React.FC = ({ rawValue, onChange, onClick, - parsedDateValue, + parsedDateValue: [start, end], id, open, className, @@ -66,7 +68,6 @@ export const DateRangePickerInput: React.FC = ({ const classes = useStyles(); const startRef = React.useRef(null); const endRef = React.useRef(null); - const [start, end] = parsedDateValue; React.useEffect(() => { if (!open) { @@ -111,7 +112,11 @@ export const DateRangePickerInput: React.FC = ({ }; return ( -
+
{ ).toBe(70); }); + test('forwardRef', () => { + const Component = () => { + const ref = React.useRef(null); + + React.useEffect(() => { + expect(ref?.current?.id).toBe('test-ref'); + expect(ref?.current).toBeInstanceOf(HTMLDivElement); + }); + + return ( + + ); + }; + + mount(); + }); + test('prop: calendars', () => { const component = mount( ( }; } +export function mergeRefs(refs: (React.Ref | undefined)[]) { + return (value: T) => { + refs.forEach(ref => { + if (typeof ref === 'function') { + ref(value); + } else if (typeof ref === 'object' && ref != null) { + // @ts-ignore .current is not a readonly, hold on ts + ref.current = value; + } + }); + }; +} + export const doNothing = () => {}; diff --git a/lib/src/_shared/KeyboardDateInput.tsx b/lib/src/_shared/KeyboardDateInput.tsx index 185005236..3101a1689 100644 --- a/lib/src/_shared/KeyboardDateInput.tsx +++ b/lib/src/_shared/KeyboardDateInput.tsx @@ -4,8 +4,8 @@ import IconButton from '@material-ui/core/IconButton'; import InputAdornment from '@material-ui/core/InputAdornment'; import { Rifm } from 'rifm'; import { useUtils } from './hooks/useUtils'; -import { DateInputProps } from './PureDateInput'; import { KeyboardIcon } from './icons/KeyboardIcon'; +import { DateInputProps, DateInputRefs } from './PureDateInput'; import { createDelegatedEventHandler } from '../_helpers/utils'; import { maskedDateFormatter, @@ -15,7 +15,7 @@ import { staticDateWith2DigitTokens, } from '../_helpers/text-field-helper'; -export const KeyboardDateInput: React.FC = ({ +export const KeyboardDateInput: React.FC = ({ disableMaskedInput, rawValue, validationError, diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 237445638..5639fbcb5 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -68,8 +68,6 @@ export interface DateInputProps; - forwardedRef?: React.Ref; } export type ExportedDateInputProps = Omit< @@ -85,7 +83,12 @@ export type ExportedDateInputProps = Omit< | 'open' >; -export const PureDateInput: React.FC = ({ +export interface DateInputRefs { + containerRef?: React.Ref; + forwardedRef?: React.Ref; +} + +export const PureDateInput: React.FC = ({ onChange, inputFormat, rifmFormatter,