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

[TimePicker] Migrate ClockPicker to emotion #26389

Merged
merged 15 commits into from
May 21, 2021
3 changes: 2 additions & 1 deletion docs/pages/api-docs/clock-picker.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"ampm": { "type": { "name": "bool" } },
"ampmInClock": { "type": { "name": "bool" } },
"autoFocus": { "type": { "name": "bool" } },
"classes": { "type": { "name": "object" } },
"components": {
"type": {
"name": "shape",
Expand Down Expand Up @@ -43,6 +44,6 @@
"filename": "/packages/material-ui-lab/src/ClockPicker/ClockPicker.tsx",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/time-picker/\">Time Picker</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
8 changes: 7 additions & 1 deletion docs/translations/api-docs/clock-picker/clock-picker.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"ampm": "12h/24h view for hour selection clock.",
"ampmInClock": "Display ampm controls under the clock (instead of in the toolbar).",
"autoFocus": "Set to <code>true</code> if focus should be moved to clock picker.",
"classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details.",
"components": "The components used for each slot. Either a string to use a HTML element or a component.",
"componentsProps": "The props used for each slot inside.",
"date": "Selected date @DateIOType.",
Expand All @@ -20,5 +21,10 @@
"rightArrowButtonText": "Right arrow icon aria-label text.",
"shouldDisableTime": "Dynamically check if time is disabled or not. If returns <code>false</code> appropriate time point will ot be acceptable."
},
"classDescriptions": {}
"classDescriptions": {
"arrowSwitcher": {
"description": "Styles applied to {{nodeName}}.",
"nodeName": "the arrowSwticher element"
}
}
}
34 changes: 24 additions & 10 deletions packages/material-ui-lab/src/ClockPicker/ClockPicker.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { describeConformance, fireEvent, fireTouchChangedEvent, screen } from 'test/utils';
import ClockPicker from '@material-ui/lab/ClockPicker';
import { describeConformanceV5, fireEvent, fireTouchChangedEvent, screen } from 'test/utils';
import ClockPicker, { clockPickerClasses as classes } from '@material-ui/lab/ClockPicker';
import {
adapterToUse,
createPickerMount,
Expand All @@ -14,14 +14,28 @@ describe('<ClockPicker />', () => {
const mount = createPickerMount();
const render = createPickerRender();

describeConformance(<ClockPicker date={adapterToUse.date()} onChange={() => {}} />, () => ({
classes: {},
inheritComponent: 'div',
mount,
refInstanceof: window.HTMLDivElement,
// cannot test reactTestRenderer because of required context
skip: ['componentProp', 'propsSpread', 'reactTestRenderer'],
}));
describeConformanceV5(
<ClockPicker date={adapterToUse.date()} showViewSwitcher onChange={() => {}} />,
() => ({
classes,
inheritComponent: 'div',
mount,
render,
refInstanceof: window.HTMLDivElement,
muiName: 'MuiClockPicker',
skip: [
'componentProp',
'componentsProp',
'propsSpread',
'reactTestRenderer',
// TODO: fix ClockPicker to spread props to root
'themeDefaultProps',
// TODO: fix ClockPicker not having root element
'themeStyleOverrides',
'themeVariants',
],
}),
);

it('renders a listbox with a name', () => {
render(<ClockPicker date={null} onChange={() => {}} />);
Expand Down
78 changes: 62 additions & 16 deletions packages/material-ui-lab/src/ClockPicker/ClockPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { MuiStyles, WithStyles, withStyles } from '@material-ui/core/styles';
import {
experimentalStyled as styled,
Theme,
unstable_useThemeProps as useThemeProps,
} from '@material-ui/core/styles';
import {
unstable_composeClasses as composeClasses,
generateUtilityClass,
generateUtilityClasses,
} from '@material-ui/unstyled';
import Clock from './Clock';
import { pipe } from '../internal/pickers/utils';
import { useUtils, useNow, MuiPickersAdapter } from '../internal/pickers/hooks/useUtils';
Expand All @@ -16,6 +25,30 @@ import { PickerSelectionState } from '../internal/pickers/hooks/usePickerState';
import { useMeridiemMode } from '../internal/pickers/hooks/date-helpers-hooks';
import { ClockView } from './shared';

export interface ClockPickerClasses {
/** Styles applied to the arrowSwticher element. */
arrowSwitcher: string;
}

export type ClockPickerClassKey = keyof ClockPickerClasses;

export function getClockPickerUtilityClass(slot: string) {
return generateUtilityClass('MuiClockPicker', slot);
}

export const clockPickerClasses: ClockPickerClasses = generateUtilityClasses('MuiClockPicker', [
'arrowSwitcher',
]);

const useUtilityClasses = (styleProps: ClockPickerProps<any>) => {
const { classes } = styleProps;
const slots = {
arrowSwitcher: ['arrowSwitcher'],
};

return composeClasses(slots, getClockPickerUtilityClass, classes);
};

export interface ExportedClockPickerProps<TDate> extends TimeValidationProps<TDate> {
/**
* 12h/24h view for hour selection clock.
Expand Down Expand Up @@ -55,6 +88,10 @@ export interface ClockPickerProps<TDate> extends ExportedClockPickerProps<TDate>
* Set to `true` if focus should be moved to clock picker.
*/
autoFocus?: boolean;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<ClockPickerClasses>;
/**
* The components used for each slot.
* Either a string to use a HTML element or a component.
Expand Down Expand Up @@ -115,13 +152,15 @@ export interface ClockPickerProps<TDate> extends ExportedClockPickerProps<TDate>
view: ClockView;
}

export const styles: MuiStyles<'arrowSwitcher'> = {
arrowSwitcher: {
position: 'absolute',
right: 12,
top: 15,
},
};
const ClockPickerArrowSwitcher = styled(PickersArrowSwitcher, {
name: 'MuiClockPicker',
slot: 'ArrowSwticher',
overridesResolver: (props, styles) => styles.arrowSwitcher,
})({
position: 'absolute',
right: 12,
top: 15,
});

const defaultGetClockLabelText = <TDate extends any>(
view: ClockView,
Expand All @@ -144,12 +183,16 @@ const defaultGetSecondsClockNumberText = (seconds: string) => `${seconds} second
*
* - [ClockPicker API](https://material-ui.com/api/clock-picker/)
*/
function ClockPicker<TDate>(props: ClockPickerProps<TDate> & WithStyles<typeof styles>) {
function ClockPicker<TDate>(inProps: ClockPickerProps<TDate>) {
const props = useThemeProps<Theme, ClockPickerProps<TDate>, 'MuiClockPicker'>({
props: inProps,
name: 'MuiClockPicker',
});

const {
ampm = false,
ampmInClock = false,
autoFocus,
classes,
components,
componentsProps,
date,
Expand Down Expand Up @@ -314,10 +357,14 @@ function ClockPicker<TDate>(props: ClockPickerProps<TDate> & WithStyles<typeof s
isTimeDisabled,
]);

// TODO: convert to simple assignment after the type error in defaultPropsHandler.js:60:6 is fixed
const styleProps = { ...props };
const classes = useUtilityClasses(styleProps);

return (
<React.Fragment>
{showViewSwitcher && (
<PickersArrowSwitcher
<ClockPickerArrowSwitcher
className={classes.arrowSwitcher}
leftArrowButtonText={leftArrowButtonText}
rightArrowButtonText={rightArrowButtonText}
Expand All @@ -327,6 +374,7 @@ function ClockPicker<TDate>(props: ClockPickerProps<TDate> & WithStyles<typeof s
onRightClick={openNextView}
isLeftDisabled={previousViewAvailable}
isRightDisabled={nextViewAvailable}
styleProps={styleProps}
/>
)}

Expand Down Expand Up @@ -367,9 +415,9 @@ ClockPicker.propTypes /* remove-proptypes */ = {
*/
autoFocus: PropTypes.bool,
/**
* @ignore
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object.isRequired,
classes: PropTypes.object,
/**
* The components used for each slot.
* Either a string to use a HTML element or a component.
Expand Down Expand Up @@ -490,6 +538,4 @@ ClockPicker.propTypes /* remove-proptypes */ = {
*
* - [ClockPicker API](https://material-ui.com/api/clock-picker/)
*/
export default withStyles(styles, { name: 'MuiClockPicker' })(ClockPicker) as <TDate>(
props: ClockPickerProps<TDate>,
) => JSX.Element;
export default ClockPicker as <TDate>(props: ClockPickerProps<TDate>) => JSX.Element;
2 changes: 2 additions & 0 deletions packages/material-ui-lab/src/ClockPicker/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { default } from './ClockPickerStandalone';
export { clockPickerClasses } from './ClockPicker';
export type { ClockPickerClasses, ClockPickerClassKey } from './ClockPicker';

export type ClockPickerProps<TDate> =
import('./ClockPickerStandalone').ClockPickerStandaloneProps<TDate>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CalendarPickerClassKey } from '../CalendarPicker';
import { CalendarPickerSkeletonClassKey } from '../CalendarPickerSkeleton';
import { ClockPickerClassKey } from '../ClockPicker/ClockPicker';
import { DateRangePickerDayClassKey } from '../DateRangePickerDay/DateRangePickerDay';
import { LoadingButtonClassKey } from '../LoadingButton';
import { MonthPickerClassKey } from '../MonthPicker';
Expand Down