From d9c7277dbcd2f315f22bfeb002d02ea5ec51aedb Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 9 May 2020 13:49:25 +0300 Subject: [PATCH] Improve input customization exprience and add new examples --- .../datepicker/AdvancedKeyboard.example.jsx | 28 ------------------- .../demo/datepicker/CustomInput.example.jsx | 28 +++++++++++++++++++ docs/pages/demo/datepicker/index.mdx | 8 +++--- .../CustomRangeInputs.example.tsx | 22 +++++++++++++++ docs/pages/demo/daterangepicker/index.mdx | 8 ++++++ .../DateRangePicker/DateRangePickerInput.tsx | 6 +++- lib/src/_shared/PureDateInput.tsx | 12 +++++--- lib/src/_shared/hooks/useMaskedInput.tsx | 27 ++++++++++-------- 8 files changed, 90 insertions(+), 49 deletions(-) delete mode 100644 docs/pages/demo/datepicker/AdvancedKeyboard.example.jsx create mode 100644 docs/pages/demo/datepicker/CustomInput.example.jsx create mode 100644 docs/pages/demo/daterangepicker/CustomRangeInputs.example.tsx diff --git a/docs/pages/demo/datepicker/AdvancedKeyboard.example.jsx b/docs/pages/demo/datepicker/AdvancedKeyboard.example.jsx deleted file mode 100644 index eb9f10150..000000000 --- a/docs/pages/demo/datepicker/AdvancedKeyboard.example.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { Fragment, useState } from 'react'; -import EventNoteIcon from '@material-ui/icons/EventNote'; -import { TextField } from '@material-ui/core'; -import { DesktopDatePicker } from '@material-ui/pickers'; - -function AdvancedKeyboardExample(props) { - const [selectedDate, handleDateChange] = useState(new Date()); - - return ( - - } - value={selectedDate} - onChange={date => handleDateChange(date)} - renderInput={props => } - /> - - ); -} - -export default AdvancedKeyboardExample; diff --git a/docs/pages/demo/datepicker/CustomInput.example.jsx b/docs/pages/demo/datepicker/CustomInput.example.jsx new file mode 100644 index 000000000..ecd54c9e0 --- /dev/null +++ b/docs/pages/demo/datepicker/CustomInput.example.jsx @@ -0,0 +1,28 @@ +import React, { useState } from 'react'; +import { styled } from '@material-ui/core'; +import { DesktopDatePicker } from '@material-ui/pickers'; + +const InputContainer = styled('div')({ + display: 'flex', + alignItems: 'center', +}); + +function CustomInput() { + const [selectedDate, handleDateChange] = useState(new Date()); + + return ( + handleDateChange(date)} + renderInput={({ ref, inputProps, InputProps }) => ( + + + {InputProps.endAdornment} + + )} + /> + ); +} + +export default CustomInput; diff --git a/docs/pages/demo/datepicker/index.mdx b/docs/pages/demo/datepicker/index.mdx index e46155515..b137262e3 100644 --- a/docs/pages/demo/datepicker/index.mdx +++ b/docs/pages/demo/datepicker/index.mdx @@ -10,7 +10,7 @@ import * as ViewsDatePicker from './ViewsDatePicker.example'; import * as BasicDatePicker from './BasicDatePicker.example'; import * as StaticDatePicker from './StaticDatePicker.example'; import * as DatePickers from './DatePickers.example'; -import * as AdvancedKeyboard from './AdvancedKeyboard.example'; +import * as CustomInput from './CustomInput.example'; @@ -53,11 +53,11 @@ For that use `StaticDatePicker`. -#### Advanced keyboard input +#### Custom input component -We are providing default localized formats, but you can change this behaviour with `format` and `mask` props. +You can customize rendering input by `renderInput` prop. But make sure you will spread `ref` and `inputProps` correctly to the custom input component. - + #### Customization diff --git a/docs/pages/demo/daterangepicker/CustomRangeInputs.example.tsx b/docs/pages/demo/daterangepicker/CustomRangeInputs.example.tsx new file mode 100644 index 000000000..7206bc4ee --- /dev/null +++ b/docs/pages/demo/daterangepicker/CustomRangeInputs.example.tsx @@ -0,0 +1,22 @@ +import React, { useState } from 'react'; +import { DateRangePicker, DateRange } from '@material-ui/pickers'; + +function CustomRangeInputs() { + const [selectedDate, handleDateChange] = useState([null, null]); + + return ( + handleDateChange(date)} + renderInput={(startProps, endProps) => ( + <> + } {...startProps.inputProps} /> + } {...endProps.inputProps} /> + + )} + /> + ); +} + +export default CustomRangeInputs; diff --git a/docs/pages/demo/daterangepicker/index.mdx b/docs/pages/demo/daterangepicker/index.mdx index 07296a39c..433988733 100644 --- a/docs/pages/demo/daterangepicker/index.mdx +++ b/docs/pages/demo/daterangepicker/index.mdx @@ -9,6 +9,7 @@ import * as ResponsiveDateRangePicker from './ResponsiveDateRangePicker.example' import * as MinMaxDateRangePicker from './MinMaxDateRangePicker.example'; import * as CalendarsDateRangePicker from './CalendarsDateRangePicker.example'; import * as StaticDateRangePicker from './StaticDateRangePicker.example'; +import * as CustomRangeInputs from './CustomRangeInputs.example'; @@ -43,6 +44,13 @@ Disabling dates performs just like in simple `DatePicker` +#### Custom input component + +You can customize rendering input by `renderInput` prop. For `DateRangePicker` it takes **2** parameters – for start and end input respectively. +So if you need to render custom input make sure you will spread `ref` and `inputProps` correctly to the input components. + + + #### Static mode It is possible to render any picker without modal or popper. For that use `StaticDateRangePicker`. diff --git a/lib/src/DateRangePicker/DateRangePickerInput.tsx b/lib/src/DateRangePicker/DateRangePickerInput.tsx index 41b7d22da..5bdb56933 100644 --- a/lib/src/DateRangePicker/DateRangePickerInput.tsx +++ b/lib/src/DateRangePicker/DateRangePickerInput.tsx @@ -7,8 +7,8 @@ import { CurrentlySelectingRangeEndProps } from './RangeTypes'; import { useMaskedInput } from '../_shared/hooks/useMaskedInput'; import { DateRangeValidationError } from '../_helpers/date-utils'; import { WrapperVariantContext } from '../wrappers/WrapperVariantContext'; -import { DateInputProps, MuiTextFieldProps } from '../_shared/PureDateInput'; import { mergeRefs, executeInTheNextEventLoopTick } from '../_helpers/utils'; +import { DateInputProps, MuiTextFieldProps } from '../_shared/PureDateInput'; export const useStyles = makeStyles( theme => ({ @@ -147,6 +147,8 @@ export const DateRangePickerInput: React.FC = ({ ref: startRef, variant: 'outlined', focused: open && currentlySelectingRangeEnd === 'start', + }, + inputProps: { onClick: !openOnFocus ? openRangeStartSelection : undefined, onFocus: openOnFocus ? openRangeStartSelection : undefined, }, @@ -164,6 +166,8 @@ export const DateRangePickerInput: React.FC = ({ ref: endRef, variant: 'outlined', focused: open && currentlySelectingRangeEnd === 'end', + }, + inputProps: { onClick: !openOnFocus ? openRangeEndSelection : undefined, onFocus: openOnFocus ? openRangeEndSelection : undefined, }, diff --git a/lib/src/_shared/PureDateInput.tsx b/lib/src/_shared/PureDateInput.tsx index 005ecbbdb..b54d4f268 100644 --- a/lib/src/_shared/PureDateInput.tsx +++ b/lib/src/_shared/PureDateInput.tsx @@ -123,11 +123,15 @@ export const PureDateInput: React.FC = ({ ref: containerRef, inputRef: forwardedRef, error: validationError, - 'aria-label': getOpenDialogAriaText(rawValue, utils), - onClick: onOpen, - value: inputValue, InputProps: PureDateInputProps, - onKeyDown: onSpaceOrEnter(onOpen), + inputProps: { + disabled, + 'aria-readonly': true, + 'aria-label': getOpenDialogAriaText(rawValue, utils), + value: inputValue, + onClick: onOpen, + onKeyDown: onSpaceOrEnter(onOpen), + }, ...TextFieldProps, }); }; diff --git a/lib/src/_shared/hooks/useMaskedInput.tsx b/lib/src/_shared/hooks/useMaskedInput.tsx index 939db0261..8dfda76f6 100644 --- a/lib/src/_shared/hooks/useMaskedInput.tsx +++ b/lib/src/_shared/hooks/useMaskedInput.tsx @@ -21,7 +21,7 @@ type MaskedInputProps = Omit< | 'disableOpenPicker' | 'getOpenDialogAriaText' | 'OpenPickerButtonProps' ->; +> & { inputProps?: Partial> }; export function useMaskedInput({ disableMaskedInput, @@ -37,6 +37,7 @@ export function useMaskedInput({ readOnly, TextFieldProps, label, + inputProps, }: MaskedInputProps): MuiTextFieldProps { const utils = useUtils(); const isFocusedRef = React.useRef(false); @@ -99,23 +100,25 @@ export function useMaskedInput({ }; return { - ...inputStateArgs, label, disabled, - placeholder: formatHelperText, error: validationError, helperText: formatHelperText, // @ts-ignore ??? fix typings for textfield finally 'data-mui-test': 'keyboard-date-input', - inputProps: { readOnly, type: shouldUseMaskedInput ? 'tel' : 'text' }, + inputProps: { + ...inputStateArgs, + disabled, // make spreading in custom input easier + placeholder: formatHelperText, + readOnly, + type: shouldUseMaskedInput ? 'tel' : 'text', + ...inputProps, + onFocus: createDelegatedEventHandler( + () => (isFocusedRef.current = true), + inputProps?.onFocus + ), + onBlur: createDelegatedEventHandler(() => (isFocusedRef.current = false), inputProps?.onBlur), + }, ...TextFieldProps, - onFocus: createDelegatedEventHandler( - () => (isFocusedRef.current = true), - TextFieldProps?.onFocus - ), - onBlur: createDelegatedEventHandler( - () => (isFocusedRef.current = false), - TextFieldProps?.onBlur - ), }; }