@docsvision/material-ui-pickers 3.2.0-beta.24 → 3.2.0-beta.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.size-snapshot.json +11 -11
- package/9db1cba1a61cb58db53f38425bbd1f95.7z +0 -0
- package/build/DatePicker/DatePicker.d.ts +2 -2
- package/build/DatePicker/DatePicker.js +1 -1
- package/build/DateTimePicker/DateTimePicker.js +1 -1
- package/build/Picker/Picker.js +1 -1
- package/build/TimePicker/TimePicker.js +1 -1
- package/build/_helpers/text-field-helper.d.ts +1 -1
- package/build/_shared/KeyboardDateInput.js +1 -1
- package/build/_shared/ModalDialog.d.ts +2 -2
- package/build/_shared/PureDateInput.js +1 -1
- package/build/_shared/ToolbarButton.d.ts +2 -2
- package/build/_shared/hooks/useKeyboardPickerState.js +2 -2
- package/build/constants/prop-types.js +2 -2
- package/build/dist/material-ui-pickers.esm.js +12 -12
- package/build/dist/material-ui-pickers.esm.js.map +1 -1
- package/build/dist/material-ui-pickers.js +62 -62
- package/build/dist/material-ui-pickers.js.map +1 -1
- package/build/dist/material-ui-pickers.umd.js +5790 -4511
- package/build/dist/material-ui-pickers.umd.min.js +1 -1
- package/build/package.json +1 -1
- package/build/views/Calendar/Calendar.js +2 -2
- package/build/views/Clock/Clock.d.ts +1 -1
- package/build/views/Clock/ClockPointer.d.ts +1 -1
- package/package.json +1 -1
- package/src/DatePicker/DatePicker.tsx +91 -0
- package/src/DatePicker/DatePickerToolbar.tsx +75 -0
- package/src/DatePicker/index.ts +7 -0
- package/src/DateTimePicker/DateTimePicker.tsx +72 -0
- package/src/DateTimePicker/DateTimePickerTabs.tsx +86 -0
- package/src/DateTimePicker/DateTimePickerToolbar.tsx +123 -0
- package/src/DateTimePicker/index.ts +7 -0
- package/src/MuiPickersUtilsProvider.tsx +39 -0
- package/src/Picker/Picker.tsx +275 -0
- package/src/Picker/WrappedKeyboardPicker.tsx +136 -0
- package/src/Picker/WrappedPurePicker.tsx +128 -0
- package/src/Rifm/Rifm.ts +213 -0
- package/src/TimePicker/TimePicker.tsx +67 -0
- package/src/TimePicker/TimePickerToolbar.tsx +180 -0
- package/src/TimePicker/index.tsx +7 -0
- package/src/__tests__/DatePicker/Calendar.test.tsx +51 -0
- package/src/__tests__/DatePicker/Month.test.tsx +36 -0
- package/src/__tests__/DatePicker/MonthSelection.test.tsx +37 -0
- package/src/__tests__/MuiPickersUtilsProvider.test.tsx +21 -0
- package/src/__tests__/TimePicker/Clock.test.tsx +68 -0
- package/src/__tests__/_helpers/date-utils.test.tsx +197 -0
- package/src/__tests__/_helpers/text-field-helper.test.tsx +34 -0
- package/src/__tests__/_shared/ModalDialog.test.tsx +109 -0
- package/src/__tests__/e2e/DatePicker.test.tsx +233 -0
- package/src/__tests__/e2e/DatePickerProps.test.tsx +18 -0
- package/src/__tests__/e2e/DatePickerRoot.test.tsx +154 -0
- package/src/__tests__/e2e/DateTimePicker.test.tsx +86 -0
- package/src/__tests__/e2e/DateTimePickerRoot.test.tsx +72 -0
- package/src/__tests__/e2e/KeyboardDatePicker.test.tsx +140 -0
- package/src/__tests__/e2e/KeyboardDateTimePicker.test.tsx +48 -0
- package/src/__tests__/e2e/Theme.test.tsx +30 -0
- package/src/__tests__/e2e/TimePicker.test.tsx +121 -0
- package/src/__tests__/e2e/commands.tsx +8 -0
- package/src/__tests__/setup.js +26 -0
- package/src/__tests__/test-utils.tsx +45 -0
- package/src/__tests__/tsconfig.json +5 -0
- package/src/_helpers/date-utils.ts +92 -0
- package/src/_helpers/text-field-helper.ts +239 -0
- package/src/_helpers/time-utils.ts +83 -0
- package/src/_helpers/utils.ts +8 -0
- package/src/_shared/KeyboardDateInput.tsx +161 -0
- package/src/_shared/ModalDialog.tsx +114 -0
- package/src/_shared/PickerToolbar.tsx +52 -0
- package/src/_shared/PureDateInput.tsx +45 -0
- package/src/_shared/ToolbarButton.tsx +63 -0
- package/src/_shared/ToolbarText.tsx +49 -0
- package/src/_shared/WithUtils.tsx +19 -0
- package/src/_shared/hooks/useIsLandscape.tsx +27 -0
- package/src/_shared/hooks/useKeyDown.ts +34 -0
- package/src/_shared/hooks/useKeyboardPickerState.ts +72 -0
- package/src/_shared/hooks/useOpenState.ts +22 -0
- package/src/_shared/hooks/usePickerState.ts +134 -0
- package/src/_shared/hooks/useUtils.ts +20 -0
- package/src/_shared/hooks/useViews.tsx +31 -0
- package/src/_shared/icons/ArrowLeftIcon.tsx +11 -0
- package/src/_shared/icons/ArrowRightIcon.tsx +11 -0
- package/src/_shared/icons/DateRangeIcon.tsx +11 -0
- package/src/_shared/icons/KeyboardIcon.tsx +11 -0
- package/src/_shared/icons/TimeIcon.tsx +12 -0
- package/src/constants/ClockType.ts +11 -0
- package/src/constants/dimensions.ts +5 -0
- package/src/constants/prop-types.ts +37 -0
- package/src/index.ts +48 -0
- package/src/typings/BasePicker.tsx +60 -0
- package/src/typings/date.ts +3 -0
- package/src/typings/extendMui.ts +10 -0
- package/src/typings/overrides.ts +44 -0
- package/src/views/Calendar/Calendar.tsx +361 -0
- package/src/views/Calendar/CalendarHeader.tsx +141 -0
- package/src/views/Calendar/Day.tsx +97 -0
- package/src/views/Calendar/DayWrapper.tsx +33 -0
- package/src/views/Calendar/SlideTransition.tsx +100 -0
- package/src/views/Clock/Clock.tsx +172 -0
- package/src/views/Clock/ClockNumber.tsx +91 -0
- package/src/views/Clock/ClockNumbers.tsx +76 -0
- package/src/views/Clock/ClockPointer.tsx +104 -0
- package/src/views/Clock/ClockView.tsx +105 -0
- package/src/views/Month/Month.tsx +76 -0
- package/src/views/Month/MonthView.tsx +94 -0
- package/src/views/Year/Year.tsx +77 -0
- package/src/views/Year/YearView.tsx +91 -0
- package/src/wrappers/InlineWrapper.tsx +80 -0
- package/src/wrappers/ModalWrapper.tsx +113 -0
- package/src/wrappers/StaticWrapper.tsx +22 -0
- package/src/wrappers/Wrapper.tsx +75 -0
- package/coverage/clover.xml +0 -601
- package/coverage/coverage-final.json +0 -22
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -79
- package/coverage/lcov-report/index.html +0 -201
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -170
- package/coverage/lcov-report/src/MuiPickersUtilsProvider.tsx.html +0 -186
- package/coverage/lcov-report/src/_helpers/date-utils.ts.html +0 -345
- package/coverage/lcov-report/src/_helpers/index.html +0 -123
- package/coverage/lcov-report/src/_helpers/time-utils.ts.html +0 -318
- package/coverage/lcov-report/src/_helpers/utils.ts.html +0 -93
- package/coverage/lcov-report/src/_shared/ModalDialog.tsx.html +0 -411
- package/coverage/lcov-report/src/_shared/WithUtils.tsx.html +0 -126
- package/coverage/lcov-report/src/_shared/hooks/index.html +0 -110
- package/coverage/lcov-report/src/_shared/hooks/useKeyDown.ts.html +0 -171
- package/coverage/lcov-report/src/_shared/hooks/useUtils.ts.html +0 -129
- package/coverage/lcov-report/src/_shared/icons/ArrowLeftIcon.tsx.html +0 -102
- package/coverage/lcov-report/src/_shared/icons/ArrowRightIcon.tsx.html +0 -102
- package/coverage/lcov-report/src/_shared/icons/index.html +0 -110
- package/coverage/lcov-report/src/_shared/index.html +0 -110
- package/coverage/lcov-report/src/constants/ClockType.ts.html +0 -102
- package/coverage/lcov-report/src/constants/dimensions.ts.html +0 -84
- package/coverage/lcov-report/src/constants/index.html +0 -110
- package/coverage/lcov-report/src/index.html +0 -97
- package/coverage/lcov-report/src/views/Calendar/Calendar.tsx.html +0 -1152
- package/coverage/lcov-report/src/views/Calendar/CalendarHeader.tsx.html +0 -492
- package/coverage/lcov-report/src/views/Calendar/Day.tsx.html +0 -360
- package/coverage/lcov-report/src/views/Calendar/DayWrapper.tsx.html +0 -168
- package/coverage/lcov-report/src/views/Calendar/SlideTransition.tsx.html +0 -369
- package/coverage/lcov-report/src/views/Calendar/index.html +0 -149
- package/coverage/lcov-report/src/views/Clock/Clock.tsx.html +0 -585
- package/coverage/lcov-report/src/views/Clock/ClockPointer.tsx.html +0 -381
- package/coverage/lcov-report/src/views/Clock/index.html +0 -110
- package/coverage/lcov-report/src/views/Month/Month.tsx.html +0 -297
- package/coverage/lcov-report/src/views/Month/MonthView.tsx.html +0 -351
- package/coverage/lcov-report/src/views/Month/index.html +0 -110
- package/coverage/lcov.info +0 -1094
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import Button from '@material-ui/core/Button';
|
|
4
|
+
import DialogActions from '@material-ui/core/DialogActions';
|
|
5
|
+
import DialogContent from '@material-ui/core/DialogContent';
|
|
6
|
+
import Dialog, { DialogProps } from '@material-ui/core/Dialog';
|
|
7
|
+
import { DIALOG_WIDTH } from '../constants/dimensions';
|
|
8
|
+
import { createStyles, WithStyles, withStyles } from '@material-ui/core/styles';
|
|
9
|
+
|
|
10
|
+
export interface ModalDialogProps extends DialogProps {
|
|
11
|
+
onAccept: () => void;
|
|
12
|
+
onDismiss: () => void;
|
|
13
|
+
onClear: () => void;
|
|
14
|
+
onSetToday: () => void;
|
|
15
|
+
okLabel?: React.ReactNode;
|
|
16
|
+
cancelLabel?: React.ReactNode;
|
|
17
|
+
clearLabel?: React.ReactNode;
|
|
18
|
+
todayLabel?: React.ReactNode;
|
|
19
|
+
clearable?: boolean;
|
|
20
|
+
showTodayButton?: boolean;
|
|
21
|
+
showTabs?: boolean;
|
|
22
|
+
wider?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const ModalDialog: React.SFC<ModalDialogProps & WithStyles<typeof styles>> = ({
|
|
26
|
+
children,
|
|
27
|
+
classes,
|
|
28
|
+
onAccept,
|
|
29
|
+
onDismiss,
|
|
30
|
+
onClear,
|
|
31
|
+
onSetToday,
|
|
32
|
+
okLabel,
|
|
33
|
+
cancelLabel,
|
|
34
|
+
clearLabel,
|
|
35
|
+
todayLabel,
|
|
36
|
+
clearable,
|
|
37
|
+
showTodayButton,
|
|
38
|
+
showTabs,
|
|
39
|
+
wider,
|
|
40
|
+
...other
|
|
41
|
+
}) => (
|
|
42
|
+
<Dialog
|
|
43
|
+
role="dialog"
|
|
44
|
+
onClose={onDismiss}
|
|
45
|
+
classes={{
|
|
46
|
+
paper: clsx(classes.dialogRoot, {
|
|
47
|
+
[classes.dialogRootWider]: wider,
|
|
48
|
+
}),
|
|
49
|
+
}}
|
|
50
|
+
{...other}
|
|
51
|
+
>
|
|
52
|
+
<DialogContent children={children} className={classes.dialog} />
|
|
53
|
+
|
|
54
|
+
<DialogActions
|
|
55
|
+
classes={{
|
|
56
|
+
root: clsx({
|
|
57
|
+
[classes.withAdditionalAction]: clearable || showTodayButton,
|
|
58
|
+
}),
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{clearable && (
|
|
62
|
+
<Button color="primary" onClick={onClear}>
|
|
63
|
+
{clearLabel}
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
{!clearable && showTodayButton && (
|
|
68
|
+
<Button color="primary" onClick={onSetToday}>
|
|
69
|
+
{todayLabel}
|
|
70
|
+
</Button>
|
|
71
|
+
)}
|
|
72
|
+
|
|
73
|
+
{cancelLabel && (
|
|
74
|
+
<Button color="primary" onClick={onDismiss}>
|
|
75
|
+
{cancelLabel}
|
|
76
|
+
</Button>
|
|
77
|
+
)}
|
|
78
|
+
|
|
79
|
+
{okLabel && (
|
|
80
|
+
<Button color="primary" onClick={onAccept}>
|
|
81
|
+
{okLabel}
|
|
82
|
+
</Button>
|
|
83
|
+
)}
|
|
84
|
+
</DialogActions>
|
|
85
|
+
</Dialog>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
ModalDialog.displayName = 'ModalDialog';
|
|
89
|
+
|
|
90
|
+
export const styles = createStyles({
|
|
91
|
+
dialogRoot: {
|
|
92
|
+
minWidth: DIALOG_WIDTH,
|
|
93
|
+
// maxWidth: DIALOG_WIDTH_WIDER,
|
|
94
|
+
},
|
|
95
|
+
dialogRootWider: {
|
|
96
|
+
// minWidth: DIALOG_WIDTH_WIDER,
|
|
97
|
+
},
|
|
98
|
+
dialog: {
|
|
99
|
+
'&:first-child': {
|
|
100
|
+
padding: 0,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
withAdditionalAction: {
|
|
104
|
+
// set justifyContent to default value to fix IE11 layout bug
|
|
105
|
+
// see https://github.com/dmtrKovalenko/material-ui-pickers/pull/267
|
|
106
|
+
justifyContent: 'flex-start',
|
|
107
|
+
|
|
108
|
+
'& > *:first-child': {
|
|
109
|
+
marginRight: 'auto',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export default withStyles(styles, { name: 'MuiPickersModal' })(ModalDialog);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import Toolbar, { ToolbarProps } from '@material-ui/core/Toolbar';
|
|
4
|
+
import { ExtendMui } from '../typings/extendMui';
|
|
5
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
6
|
+
|
|
7
|
+
export const useStyles = makeStyles(
|
|
8
|
+
theme => ({
|
|
9
|
+
toolbar: {
|
|
10
|
+
display: 'flex',
|
|
11
|
+
flexDirection: 'row',
|
|
12
|
+
alignItems: 'center',
|
|
13
|
+
justifyContent: 'center',
|
|
14
|
+
height: 100,
|
|
15
|
+
backgroundColor:
|
|
16
|
+
theme.palette.type === 'light'
|
|
17
|
+
? theme.palette.primary.main
|
|
18
|
+
: theme.palette.background.default,
|
|
19
|
+
},
|
|
20
|
+
toolbarLandscape: {
|
|
21
|
+
height: 'auto',
|
|
22
|
+
maxWidth: 150,
|
|
23
|
+
padding: 8,
|
|
24
|
+
justifyContent: 'flex-start',
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
{ name: 'MuiPickersToolbar' }
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
interface PickerToolbarProps extends ExtendMui<ToolbarProps> {
|
|
31
|
+
isLandscape: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const PickerToolbar: React.SFC<PickerToolbarProps> = ({
|
|
35
|
+
children,
|
|
36
|
+
isLandscape,
|
|
37
|
+
className = null,
|
|
38
|
+
...other
|
|
39
|
+
}) => {
|
|
40
|
+
const classes = useStyles();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Toolbar
|
|
44
|
+
className={clsx(classes.toolbar, { [classes.toolbarLandscape]: isLandscape }, className)}
|
|
45
|
+
{...other}
|
|
46
|
+
>
|
|
47
|
+
{children}
|
|
48
|
+
</Toolbar>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default PickerToolbar;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import TextField, { BaseTextFieldProps, TextFieldProps } from '@material-ui/core/TextField';
|
|
3
|
+
import { ExtendMui } from '../typings/extendMui';
|
|
4
|
+
|
|
5
|
+
export interface PureDateInputProps
|
|
6
|
+
extends ExtendMui<BaseTextFieldProps, 'variant' | 'onError' | 'onChange' | 'value'> {
|
|
7
|
+
/** Pass material-ui text field variant down, bypass internal variant prop */
|
|
8
|
+
inputVariant?: TextFieldProps['variant'];
|
|
9
|
+
/** Override input component */
|
|
10
|
+
TextFieldComponent?: React.ComponentType<TextFieldProps>;
|
|
11
|
+
InputProps?: TextFieldProps['InputProps'];
|
|
12
|
+
inputValue: string;
|
|
13
|
+
validationError?: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const PureDateInput: React.FC<PureDateInputProps> = ({
|
|
17
|
+
inputValue,
|
|
18
|
+
inputVariant,
|
|
19
|
+
validationError,
|
|
20
|
+
InputProps,
|
|
21
|
+
TextFieldComponent = TextField,
|
|
22
|
+
...other
|
|
23
|
+
}) => {
|
|
24
|
+
const PureDateInputProps = React.useMemo(
|
|
25
|
+
() => ({
|
|
26
|
+
...InputProps,
|
|
27
|
+
readOnly: true,
|
|
28
|
+
}),
|
|
29
|
+
[InputProps]
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<TextFieldComponent
|
|
34
|
+
error={Boolean(validationError)}
|
|
35
|
+
helperText={validationError}
|
|
36
|
+
{...other}
|
|
37
|
+
// do not overridable
|
|
38
|
+
value={inputValue}
|
|
39
|
+
variant={inputVariant as any}
|
|
40
|
+
InputProps={PureDateInputProps}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
PureDateInput.displayName = 'PureDateInput';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as PropTypes from 'prop-types';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import ToolbarText from './ToolbarText';
|
|
5
|
+
import Button, { ButtonProps } from '@material-ui/core/Button';
|
|
6
|
+
import { ExtendMui } from '../typings/extendMui';
|
|
7
|
+
import { TypographyProps } from '@material-ui/core/Typography';
|
|
8
|
+
import { createStyles, withStyles, WithStyles } from '@material-ui/core/styles';
|
|
9
|
+
|
|
10
|
+
export interface ToolbarButtonProps
|
|
11
|
+
extends ExtendMui<ButtonProps, 'variant'>,
|
|
12
|
+
WithStyles<typeof styles> {
|
|
13
|
+
variant: TypographyProps['variant'];
|
|
14
|
+
selected: boolean;
|
|
15
|
+
label: string;
|
|
16
|
+
align?: TypographyProps['align'];
|
|
17
|
+
typographyClassName?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const ToolbarButton: React.FunctionComponent<ToolbarButtonProps> = ({
|
|
21
|
+
classes,
|
|
22
|
+
className = null,
|
|
23
|
+
label,
|
|
24
|
+
selected,
|
|
25
|
+
variant,
|
|
26
|
+
align,
|
|
27
|
+
typographyClassName,
|
|
28
|
+
...other
|
|
29
|
+
}) => {
|
|
30
|
+
return (
|
|
31
|
+
<Button variant="text" className={clsx(classes.toolbarBtn, className)} {...other}>
|
|
32
|
+
<ToolbarText
|
|
33
|
+
align={align}
|
|
34
|
+
className={typographyClassName}
|
|
35
|
+
variant={variant}
|
|
36
|
+
label={label}
|
|
37
|
+
selected={selected}
|
|
38
|
+
/>
|
|
39
|
+
</Button>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
(ToolbarButton as any).propTypes = {
|
|
44
|
+
selected: PropTypes.bool.isRequired,
|
|
45
|
+
label: PropTypes.string.isRequired,
|
|
46
|
+
classes: PropTypes.any.isRequired,
|
|
47
|
+
className: PropTypes.string,
|
|
48
|
+
innerRef: PropTypes.any,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
ToolbarButton.defaultProps = {
|
|
52
|
+
className: '',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const styles = createStyles({
|
|
56
|
+
toolbarBtn: {
|
|
57
|
+
padding: 0,
|
|
58
|
+
minWidth: '16px',
|
|
59
|
+
textTransform: 'none',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export default withStyles(styles, { name: 'MuiPickersToolbarButton' })(ToolbarButton);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import Typography, { TypographyProps } from '@material-ui/core/Typography';
|
|
4
|
+
import { ExtendMui } from '../typings/extendMui';
|
|
5
|
+
import { makeStyles, fade } from '@material-ui/core/styles';
|
|
6
|
+
|
|
7
|
+
export interface ToolbarTextProps extends ExtendMui<TypographyProps> {
|
|
8
|
+
selected?: boolean;
|
|
9
|
+
label: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const useStyles = makeStyles(
|
|
13
|
+
theme => {
|
|
14
|
+
const textColor =
|
|
15
|
+
theme.palette.type === 'light'
|
|
16
|
+
? theme.palette.primary.contrastText
|
|
17
|
+
: theme.palette.getContrastText(theme.palette.background.default);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
toolbarTxt: {
|
|
21
|
+
color: fade(textColor, 0.54),
|
|
22
|
+
},
|
|
23
|
+
toolbarBtnSelected: {
|
|
24
|
+
color: textColor,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
{ name: 'MuiPickersToolbarText' }
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const ToolbarText: React.FunctionComponent<ToolbarTextProps> = ({
|
|
32
|
+
selected,
|
|
33
|
+
label,
|
|
34
|
+
className = null,
|
|
35
|
+
...other
|
|
36
|
+
}) => {
|
|
37
|
+
const classes = useStyles();
|
|
38
|
+
return (
|
|
39
|
+
<Typography
|
|
40
|
+
children={label}
|
|
41
|
+
className={clsx(classes.toolbarTxt, className, {
|
|
42
|
+
[classes.toolbarBtnSelected]: selected,
|
|
43
|
+
})}
|
|
44
|
+
{...other}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default ToolbarText;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Omit } from '@material-ui/core';
|
|
3
|
+
import { useUtils } from './hooks/useUtils';
|
|
4
|
+
import { IUtils } from '@date-io/core/IUtils';
|
|
5
|
+
import { MaterialUiPickersDate } from '../typings/date';
|
|
6
|
+
|
|
7
|
+
export interface WithUtilsProps {
|
|
8
|
+
utils: IUtils<MaterialUiPickersDate>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const withUtils = () => <P extends WithUtilsProps>(Component: React.ComponentType<P>) => {
|
|
12
|
+
const WithUtils: React.SFC<Omit<P, keyof WithUtilsProps>> = props => {
|
|
13
|
+
const utils = useUtils();
|
|
14
|
+
return <Component utils={utils} {...(props as any)} />;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
WithUtils.displayName = `WithUtils(${Component.displayName || Component.name})`;
|
|
18
|
+
return WithUtils;
|
|
19
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useIsomorphicEffect } from './useKeyDown';
|
|
3
|
+
import { BasePickerProps } from '../../typings/BasePicker';
|
|
4
|
+
|
|
5
|
+
const getOrientation = () =>
|
|
6
|
+
typeof window !== 'undefined' &&
|
|
7
|
+
window.screen &&
|
|
8
|
+
window.screen.orientation &&
|
|
9
|
+
Math.abs(window.screen.orientation.angle) === 90
|
|
10
|
+
? 'landscape'
|
|
11
|
+
: 'portrait';
|
|
12
|
+
|
|
13
|
+
export function useIsLandscape(customOrientation?: BasePickerProps['orientation']) {
|
|
14
|
+
const [orientation, setOrientation] = React.useState<BasePickerProps['orientation']>(
|
|
15
|
+
getOrientation()
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const eventHandler = React.useCallback(() => setOrientation(getOrientation()), []);
|
|
19
|
+
|
|
20
|
+
useIsomorphicEffect(() => {
|
|
21
|
+
window.addEventListener('orientationchange', eventHandler);
|
|
22
|
+
return () => window.removeEventListener('orientationchange', eventHandler);
|
|
23
|
+
}, [eventHandler]);
|
|
24
|
+
|
|
25
|
+
const orientationToUse = customOrientation || orientation;
|
|
26
|
+
return orientationToUse === 'landscape';
|
|
27
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
export const useIsomorphicEffect =
|
|
4
|
+
typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
|
|
5
|
+
|
|
6
|
+
type KeyHandlers = Record<KeyboardEvent['key'], () => void>;
|
|
7
|
+
|
|
8
|
+
export function runKeyHandler(e: KeyboardEvent, keyHandlers: KeyHandlers) {
|
|
9
|
+
const handler = keyHandlers[e.key];
|
|
10
|
+
if (handler) {
|
|
11
|
+
handler();
|
|
12
|
+
// if event was handled prevent other side effects (e.g. page scroll)
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function useKeyDown(active: boolean, keyHandlers: KeyHandlers) {
|
|
18
|
+
const keyHandlersRef = React.useRef(keyHandlers);
|
|
19
|
+
useIsomorphicEffect(() => {
|
|
20
|
+
keyHandlersRef.current = keyHandlers;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
React.useEffect(() => {
|
|
24
|
+
if (active) {
|
|
25
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
26
|
+
runKeyHandler(event, keyHandlers);
|
|
27
|
+
};
|
|
28
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
29
|
+
return () => {
|
|
30
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}, [active, keyHandlers]);
|
|
34
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useUtils } from './useUtils';
|
|
2
|
+
import { Omit } from '@material-ui/core';
|
|
3
|
+
import { IUtils } from '@date-io/core/IUtils';
|
|
4
|
+
import { BasePickerProps } from '../../typings/BasePicker';
|
|
5
|
+
import { MaterialUiPickersDate } from '../../typings/date';
|
|
6
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import { getDisplayDate } from '../../_helpers/text-field-helper';
|
|
8
|
+
import { StateHookOptions, usePickerState } from './usePickerState';
|
|
9
|
+
|
|
10
|
+
export interface BaseKeyboardPickerProps extends Omit<BasePickerProps, 'onChange'> {
|
|
11
|
+
/** String value for controlling value with pure input string. Overrides value prop */
|
|
12
|
+
inputValue?: string;
|
|
13
|
+
/** Keyboard onChange callback */
|
|
14
|
+
onChange: (date: MaterialUiPickersDate | null, value?: string | null) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function parseInputString(value: string, utils: IUtils<any>, format: string) {
|
|
18
|
+
try {
|
|
19
|
+
return utils.parse(value, format);
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useKeyboardPickerState(props: BaseKeyboardPickerProps, options: StateHookOptions) {
|
|
26
|
+
const { format = options.getDefaultFormat(), inputValue, onChange, value } = props;
|
|
27
|
+
const utils = useUtils();
|
|
28
|
+
|
|
29
|
+
const displayDate = getDisplayDate(value, format, utils, value === null, props);
|
|
30
|
+
const [innerInputValue, setInnerInputValue] = useState(displayDate);
|
|
31
|
+
const dateValue = inputValue ? parseInputString(inputValue, utils, format) : value;
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (value === null || utils.isValid(value)) {
|
|
35
|
+
setInnerInputValue(displayDate);
|
|
36
|
+
}
|
|
37
|
+
}, [displayDate, setInnerInputValue, utils, value]);
|
|
38
|
+
|
|
39
|
+
const handleKeyboardChange = useCallback(
|
|
40
|
+
(date: MaterialUiPickersDate) => {
|
|
41
|
+
onChange(date, date === null ? null : utils.format(date, format));
|
|
42
|
+
},
|
|
43
|
+
[format, onChange, utils]
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const { inputProps: innerInputProps, wrapperProps, pickerProps } = usePickerState(
|
|
47
|
+
// Extend props interface
|
|
48
|
+
{ ...props, value: dateValue, onChange: handleKeyboardChange },
|
|
49
|
+
options
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const inputProps = useMemo(
|
|
53
|
+
() => ({
|
|
54
|
+
...innerInputProps, // reuse validation and open/close logic
|
|
55
|
+
format: wrapperProps.format,
|
|
56
|
+
inputValue: inputValue || innerInputValue,
|
|
57
|
+
onChange: (value: string | null) => {
|
|
58
|
+
setInnerInputValue(value || '');
|
|
59
|
+
const date = value === null ? null : utils.parse(value, wrapperProps.format);
|
|
60
|
+
|
|
61
|
+
onChange(date, value);
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
[innerInputProps, innerInputValue, inputValue, onChange, utils, wrapperProps.format]
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
inputProps,
|
|
69
|
+
wrapperProps,
|
|
70
|
+
pickerProps,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import { BasePickerProps } from '../../typings/BasePicker';
|
|
3
|
+
import { useCallback, useState, Dispatch, SetStateAction } from 'react';
|
|
4
|
+
|
|
5
|
+
export function useOpenState({ open, onOpen, onClose }: BasePickerProps) {
|
|
6
|
+
let setIsOpenState: null | Dispatch<SetStateAction<boolean>> = null;
|
|
7
|
+
if (open === undefined || open === null) {
|
|
8
|
+
// The component is uncontrolled, so we need to give it its own state.
|
|
9
|
+
[open, setIsOpenState] = useState<boolean>(false);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// prettier-ignore
|
|
13
|
+
const setIsOpen = useCallback((newIsOpen: boolean) => {
|
|
14
|
+
setIsOpenState && setIsOpenState(newIsOpen);
|
|
15
|
+
|
|
16
|
+
return newIsOpen
|
|
17
|
+
? onOpen && onOpen()
|
|
18
|
+
: onClose && onClose();
|
|
19
|
+
}, [onOpen, onClose, setIsOpenState]);
|
|
20
|
+
|
|
21
|
+
return { isOpen: open, setIsOpen };
|
|
22
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { useUtils } from './useUtils';
|
|
2
|
+
import { IUtils } from '@date-io/core/IUtils';
|
|
3
|
+
import { MaterialUiPickersDate } from '../..';
|
|
4
|
+
import { useOpenState } from './useOpenState';
|
|
5
|
+
import { BasePickerProps } from '../../typings/BasePicker';
|
|
6
|
+
import { getDisplayDate, validate } from '../../_helpers/text-field-helper';
|
|
7
|
+
import { useCallback, useDebugValue, useEffect, useMemo, useState, useRef } from 'react';
|
|
8
|
+
|
|
9
|
+
export interface StateHookOptions {
|
|
10
|
+
getDefaultFormat: () => string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const useValueToDate = (
|
|
14
|
+
utils: IUtils<MaterialUiPickersDate>,
|
|
15
|
+
{ value, initialFocusedDate }: BasePickerProps
|
|
16
|
+
) => {
|
|
17
|
+
const nowRef = useRef(utils.date());
|
|
18
|
+
const date = utils.date(value || initialFocusedDate || nowRef.current);
|
|
19
|
+
|
|
20
|
+
return date && utils.isValid(date) ? date : nowRef.current;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function useDateValues(props: BasePickerProps, options: StateHookOptions) {
|
|
24
|
+
const utils = useUtils();
|
|
25
|
+
const date = useValueToDate(utils, props);
|
|
26
|
+
const format = props.format || options.getDefaultFormat();
|
|
27
|
+
|
|
28
|
+
return { date, format };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function usePickerState(props: BasePickerProps, options: StateHookOptions) {
|
|
32
|
+
const { autoOk, disabled, onAccept, onChange, onError, value, variant } = props;
|
|
33
|
+
|
|
34
|
+
const utils = useUtils();
|
|
35
|
+
const { isOpen, setIsOpen } = useOpenState(props);
|
|
36
|
+
const { date, format } = useDateValues(props, options);
|
|
37
|
+
const [pickerDate, setPickerDate] = useState(date);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
// if value was changed in closed state - treat it as accepted
|
|
41
|
+
if (!isOpen && !utils.isEqual(pickerDate, date)) {
|
|
42
|
+
setPickerDate(date);
|
|
43
|
+
}
|
|
44
|
+
}, [date, isOpen, pickerDate, utils]);
|
|
45
|
+
|
|
46
|
+
const acceptDate = useCallback(
|
|
47
|
+
(acceptedDate: MaterialUiPickersDate) => {
|
|
48
|
+
setIsOpen(false);
|
|
49
|
+
onChange(acceptedDate);
|
|
50
|
+
|
|
51
|
+
if (onAccept) {
|
|
52
|
+
onAccept(acceptedDate);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
[onAccept, onChange, setIsOpen]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const wrapperProps = useMemo(
|
|
59
|
+
() => ({
|
|
60
|
+
format,
|
|
61
|
+
open: isOpen,
|
|
62
|
+
onClear: () => acceptDate(null),
|
|
63
|
+
onAccept: () => acceptDate(pickerDate),
|
|
64
|
+
onSetToday: () => setPickerDate(utils.date()),
|
|
65
|
+
onDismiss: () => {
|
|
66
|
+
setIsOpen(false);
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
[acceptDate, format, isOpen, pickerDate, setIsOpen, utils]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const pickerProps = useMemo(
|
|
73
|
+
() => ({
|
|
74
|
+
date: pickerDate,
|
|
75
|
+
onChange: (newDate: MaterialUiPickersDate, isFinish = true) => {
|
|
76
|
+
setPickerDate(newDate);
|
|
77
|
+
|
|
78
|
+
if (variant === 'inline' || variant === 'static') {
|
|
79
|
+
onChange(newDate);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (isFinish && autoOk) {
|
|
83
|
+
acceptDate(newDate);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
onSetToday: () => {
|
|
87
|
+
let newDate = utils.date();
|
|
88
|
+
setPickerDate(newDate);
|
|
89
|
+
|
|
90
|
+
if (variant === 'inline' || variant === 'static') {
|
|
91
|
+
onChange(newDate);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (autoOk) {
|
|
95
|
+
acceptDate(newDate);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
onSetShift: (shiftDate: Date) => {
|
|
99
|
+
let newDate = utils.date(shiftDate);
|
|
100
|
+
|
|
101
|
+
if (variant === 'inline' || variant === 'static') {
|
|
102
|
+
onChange(newDate);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (autoOk) {
|
|
106
|
+
acceptDate(newDate);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
[acceptDate, autoOk, onChange, pickerDate, variant]
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const validationError = validate(value, utils, props);
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (validationError && onError) {
|
|
116
|
+
onError(validationError, value);
|
|
117
|
+
}
|
|
118
|
+
}, [onError, validationError, value]);
|
|
119
|
+
|
|
120
|
+
const inputValue = getDisplayDate(date, format, utils, value === null, props);
|
|
121
|
+
const inputProps = useMemo(
|
|
122
|
+
() => ({
|
|
123
|
+
inputValue,
|
|
124
|
+
validationError,
|
|
125
|
+
onClick: () => !disabled && setIsOpen(true),
|
|
126
|
+
}),
|
|
127
|
+
[disabled, inputValue, setIsOpen, validationError]
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const pickerState = { pickerProps, inputProps, wrapperProps };
|
|
131
|
+
|
|
132
|
+
useDebugValue(pickerState);
|
|
133
|
+
return pickerState;
|
|
134
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { IUtils } from '@date-io/core/IUtils';
|
|
3
|
+
import { MaterialUiPickersDate } from '../../typings/date';
|
|
4
|
+
import { MuiPickersContext } from '../../MuiPickersUtilsProvider';
|
|
5
|
+
|
|
6
|
+
export const checkUtils = (utils: IUtils<MaterialUiPickersDate> | null | undefined) => {
|
|
7
|
+
if (!utils) {
|
|
8
|
+
// tslint:disable-next-line
|
|
9
|
+
throw new Error(
|
|
10
|
+
'Can not find utils in context. You either a) forgot to wrap your component tree in MuiPickersUtilsProvider; or b) mixed named and direct file imports. Recommendation: use named imports from the module index.'
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function useUtils() {
|
|
16
|
+
const utils = useContext(MuiPickersContext);
|
|
17
|
+
checkUtils(utils);
|
|
18
|
+
|
|
19
|
+
return utils!;
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { MaterialUiPickersDate } from '../..';
|
|
3
|
+
import { PickerView } from '../../Picker/Picker';
|
|
4
|
+
import { arrayIncludes } from '../../_helpers/utils';
|
|
5
|
+
|
|
6
|
+
export function useViews(
|
|
7
|
+
views: PickerView[],
|
|
8
|
+
openTo: PickerView,
|
|
9
|
+
onChange: (date: MaterialUiPickersDate, isFinish?: boolean) => void
|
|
10
|
+
) {
|
|
11
|
+
const [openView, setOpenView] = React.useState(
|
|
12
|
+
openTo && arrayIncludes(views, openTo) ? openTo : views[0]
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const handleChangeAndOpenNext = React.useCallback(
|
|
16
|
+
(date: MaterialUiPickersDate, isFinish?: boolean) => {
|
|
17
|
+
const nextViewToOpen = views[views.indexOf(openView!) + 1];
|
|
18
|
+
if (isFinish && nextViewToOpen) {
|
|
19
|
+
// do not close picker if needs to show next view
|
|
20
|
+
onChange(date, false);
|
|
21
|
+
setOpenView(nextViewToOpen);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onChange(date, Boolean(isFinish));
|
|
26
|
+
},
|
|
27
|
+
[onChange, openView, views]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return { handleChangeAndOpenNext, openView, setOpenView };
|
|
31
|
+
}
|