Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace existing timepicker with MUI timepicker #29

Merged
merged 1 commit into from
Mar 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 20 additions & 133 deletions src/components/TimePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,144 +1,31 @@
import Autocomplete, { AutocompleteProps } from './Autocomplete';
import { SizeTypes } from './TextField';
import { Clock } from '../icons';
import MuiTimePicker, { TimePickerProps as MuiTimePickerProps } from '@mui/lab/TimePicker';
import TextField, { TextFieldProps } from './TextField';

const twentyFourHourTimes = [
{ id: '00:00', value: '00:00' },
{ id: '00:30', value: '00:30' },
{ id: '01:00', value: '01:00' },
{ id: '01:30', value: '01:30' },
{ id: '02:00', value: '02:00' },
{ id: '02:30', value: '02:30' },
{ id: '03:00', value: '03:00' },
{ id: '03:30', value: '03:30' },
{ id: '04:00', value: '04:00' },
{ id: '04:30', value: '04:30' },
{ id: '05:00', value: '05:00' },
{ id: '05:30', value: '05:30' },
{ id: '06:00', value: '06:00' },
{ id: '07:00', value: '07:00' },
{ id: '07:30', value: '07:30' },
{ id: '08:00', value: '08:00' },
{ id: '08:30', value: '08:30' },
{ id: '09:00', value: '09:00' },
{ id: '09:30', value: '09:30' },
{ id: '10:00', value: '10:00' },
{ id: '10:30', value: '10:30' },
{ id: '11:00', value: '11:00' },
{ id: '11:30', value: '11:30' },
{ id: '12:00', value: '12:00' },
{ id: '12:30', value: '12:30' },
{ id: '13:00', value: '13:00' },
{ id: '13:30', value: '13:30' },
{ id: '14:00', value: '14:00' },
{ id: '14:30', value: '14:30' },
{ id: '15:00', value: '15:00' },
{ id: '15:30', value: '15:30' },
{ id: '16:00', value: '16:00' },
{ id: '16:30', value: '16:30' },
{ id: '17:00', value: '17:00' },
{ id: '17:30', value: '17:30' },
{ id: '18:00', value: '18:00' },
{ id: '18:30', value: '18:30' },
{ id: '19:00', value: '19:00' },
{ id: '19:30', value: '19:30' },
{ id: '20:00', value: '20:00' },
{ id: '20:30', value: '20:30' },
{ id: '21:00', value: '21:00' },
{ id: '21:30', value: '21:30' },
{ id: '22:00', value: '22:00' },
{ id: '22:30', value: '22:30' },
{ id: '23:00', value: '23:00' },
{ id: '23:30', value: '23:30' },
];

const twelveHourTimes = [
{ id: '12:00 AM', value: '12:00 AM' },
{ id: '12:30 AM', value: '12:30 AM' },
{ id: '01:00 AM', value: '01:00 AM' },
{ id: '01:30 AM', value: '01:30 AM' },
{ id: '02:00 AM', value: '02:00 AM' },
{ id: '02:30 AM', value: '02:30 AM' },
{ id: '03:00 AM', value: '03:00 AM' },
{ id: '03:30 AM', value: '03:30 AM' },
{ id: '04:00 AM', value: '04:00 AM' },
{ id: '04:30 AM', value: '04:30 AM' },
{ id: '05:00 AM', value: '05:00 AM' },
{ id: '05:30 AM', value: '05:30 AM' },
{ id: '06:00 AM', value: '06:00 AM' },
{ id: '07:00 AM', value: '07:00 AM' },
{ id: '07:30 AM', value: '07:30 AM' },
{ id: '08:00 AM', value: '08:00 AM' },
{ id: '08:30 AM', value: '08:30 AM' },
{ id: '09:00 AM', value: '09:00 AM' },
{ id: '09:30 AM', value: '09:30 AM' },
{ id: '10:00 AM', value: '10:00 AM' },
{ id: '10:30 AM', value: '10:30 AM' },
{ id: '11:00 AM', value: '11:00 AM' },
{ id: '11:30 AM', value: '11:30 AM' },
{ id: '12:00 PM', value: '12:00 PM' },
{ id: '12:30 PM', value: '12:30 PM' },
{ id: '01:00 PM', value: '01:00 PM' },
{ id: '01:30 PM', value: '01:30 PM' },
{ id: '02:00 PM', value: '02:00 PM' },
{ id: '02:30 PM', value: '02:30 PM' },
{ id: '03:00 PM', value: '03:00 PM' },
{ id: '03:30 PM', value: '03:30 PM' },
{ id: '04:00 PM', value: '04:00 PM' },
{ id: '04:30 PM', value: '04:30 PM' },
{ id: '05:00 PM', value: '05:00 PM' },
{ id: '05:30 PM', value: '05:30 PM' },
{ id: '06:00 PM', value: '06:00 PM' },
{ id: '07:00 PM', value: '07:00 PM' },
{ id: '07:30 PM', value: '07:30 PM' },
{ id: '08:00 PM', value: '08:00 PM' },
{ id: '08:30 PM', value: '08:30 PM' },
{ id: '09:00 PM', value: '09:00 PM' },
{ id: '09:30 PM', value: '09:30 PM' },
{ id: '10:00 PM', value: '10:00 PM' },
{ id: '10:30 PM', value: '10:30 PM' },
{ id: '11:00 PM', value: '11:00 PM' },
{ id: '11:30 PM', value: '11:30 PM' },
];

export interface TimePickerProps extends Omit<AutocompleteProps, 'renderInput' | 'options'> {
twelvehour?: boolean;
error?: boolean;
helperText?: string;
size?: SizeTypes;
label?: string;
export interface TimePickerProps extends Omit<MuiTimePickerProps, 'renderInput' | 'InputProps'> {
InputProps?: TextFieldProps;
'data-testid'?: string;
}

const TimePicker = ({
twelvehour,
error,
helperText,
size = 'small',
label,
...props
}: TimePickerProps): JSX.Element => {
const TimePicker = ({ ampm = false, InputProps = {}, ...props }: TimePickerProps): JSX.Element => {
return (
<Autocomplete
freeSolo
forcePopupIcon
popupIcon={<Clock color="inherit" />}
options={twelvehour ? twelveHourTimes : twentyFourHourTimes}
disableClearable={true}
size={size}
label={label}
error={error}
helperText={helperText}
sx={{
'& .MuiAutocomplete-popupIndicatorOpen': { transform: 'none' },
}}
<MuiTimePicker
ampm={ampm}
{...props}
PopperProps={{
// @ts-ignore
sx: {
'& .MuiClockPicker-arrowSwitcher': {
width: '70px',

'& button:hover': {
backgroundColor: 'primary.light',
},
},
},
}}
renderInput={(params) => <TextField {...(params as TextFieldProps)} {...InputProps} />}
/>
);
};

TimePicker.defaultProps = {
twelvehour: false,
};

export default TimePicker;
113 changes: 100 additions & 13 deletions stories/Inputs/TimePicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,116 @@ import { Story, Meta } from '@storybook/react/types-6-0';
import TimePicker, { TimePickerProps } from '../../src/components/TimePicker';
import Box from '../../src/components/Box';
import { modifyExcludedParams } from '../../.storybook/excludedParams';
import { LocalizationProvider } from '../../src';
import AdapterDayjs from '@date-io/dayjs';
import { useState } from 'react';

export default {
title: 'Components/Inputs/TimePicker',
component: TimePicker,
parameters: {
controls: { exclude: modifyExcludedParams(['color']) },
docs: {
source: {
type: 'code',
},
description: {
component: `Date pickers let the user select time.

This component relies on the date management library of your choice. It supports date-fns, luxon, dayjs, moment and any other library via a @date-io adapter interface.

Please install any of these date management libraries, @date-io adapter for it and set up the right date engine by wrapping your root (or the highest level you wish the pickers to be available) with LocalizationProvider and pass the adapter and locale to it. @date-io adapters can be found at https://github.com/dmtrKovalenko/date-io. Usage examples can be found by clicking the "show code" button in the stories.`,
},
},
},
argTypes: {
value: {
control: { type: 'null' },
type: { name: 'string', required: true },
description: 'Type depends on adapter that is being used to wrap picker',
table: {
type: {
summary: 'any | Date | number | string',
},
},
},
onChange: {
control: { type: 'null' },
type: { name: 'string', required: true },
description: 'Callback fired when the value (the selected time) changes to @DateIOType',
table: {
type: {
summary: 'func',
},
},
},
label: {
control: { type: 'text' },
description: 'The label of the picker',
table: {
type: {
summary: 'string',
},
},
},
ampm: {
defaultValue: { summary: false },
control: { type: 'boolean' },
description: '12h/24h view for hour selection clock',
table: {
type: {
summary: 'boolean',
},
},
},
disabled: {
defaultValue: { summary: false },
control: { type: 'boolean' },
description: 'If true, the input element will be disabled',
table: {
type: {
summary: 'boolean',
},
},
},
readOnly: {
defaultValue: { summary: false },
control: { type: 'boolean' },
description: 'If true, the input element will be read only',
table: {
type: {
summary: 'boolean',
},
},
},
},
} as Meta;

const Template: Story<TimePickerProps> = (args) => (
<Box sx={{ width: '125px' }}>
<TimePicker {...args} />
</Box>
);
const Template: Story<TimePickerProps> = (args) => {
const [value, setValue] = useState<unknown>(new Date());

export const Default = Template.bind({});
Default.args = { label: 'Label' };

export const LargeTwelveHour = Template.bind({});
LargeTwelveHour.args = { twelvehour: true, size: 'medium' };
return (
<Box sx={{ width: '150px' }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<TimePicker
{...args}
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
/>
</LocalizationProvider>
</Box>
);
};

export const Disabled = Template.bind({});
Disabled.args = { disabled: true };
export const Default = Template.bind({});
Default.args = { label: 'Label', ampm: false, disabled: false, readOnly: false };

export const Error = Template.bind({});
Error.args = { error: true, helperText: 'The date was bad' };
Error.args = {
label: 'Error',
disabled: false,
ampm: false,
InputProps: { error: true, helperText: 'Invalid time' },
};