Skip to content

Commit

Permalink
[core] Adds component prop to OverrideProps type (mui#35924)
Browse files Browse the repository at this point in the history
  • Loading branch information
sai6855 committed Jul 18, 2023
1 parent db2968e commit 1b9c8ab
Show file tree
Hide file tree
Showing 29 changed files with 540 additions and 129 deletions.
4 changes: 2 additions & 2 deletions docs/data/material/guides/routing/LinkRouterWithTheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { StaticRouter } from 'react-router-dom/server';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';
import Link, { LinkProps } from '@mui/material/Link';
import Link from '@mui/material/Link';

const LinkBehavior = React.forwardRef<
HTMLAnchorElement,
Expand All @@ -33,7 +33,7 @@ const theme = createTheme({
MuiLink: {
defaultProps: {
component: LinkBehavior,
} as LinkProps,
},
},
MuiButtonBase: {
defaultProps: {
Expand Down
2 changes: 1 addition & 1 deletion docs/data/material/guides/routing/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const theme = createTheme({
MuiLink: {
defaultProps: {
component: LinkBehavior,
} as LinkProps,
},
},
MuiButtonBase: {
defaultProps: {
Expand Down
2 changes: 1 addition & 1 deletion docs/src/modules/components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export type LinkProps = {
linkAs?: NextLinkProps['as']; // Useful when the as prop is shallow by styled().
noLinkStyle?: boolean;
} & Omit<NextLinkComposedProps, 'to' | 'linkAs' | 'href'> &
Omit<MuiLinkProps, 'href'>;
Omit<MuiLinkProps, 'href' | 'component'>;

// A styled version of the Next.js Link component:
// https://nextjs.org/docs/api-reference/next/link
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-material/src/Button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ Button.propTypes /* remove-proptypes */ = {
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
component: PropTypes /* @typescript-to-proptypes-ignore */.elementType,
/**
* If `true`, the component is disabled.
* @default false
Expand Down
33 changes: 33 additions & 0 deletions packages/mui-material/src/Button/Button.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,39 @@ function FakeIcon() {
return <div>Icon</div>;
}

const props1: ButtonProps<'div'> = {
component: 'div',
onChange: (event) => {
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
},
};

const props2: ButtonProps = {
onChange: (event) => {
expectType<React.FormEvent<HTMLButtonElement>, typeof event>(event);
},
};

const props3: ButtonProps<'span'> = {
// @ts-expect-error
component: 'div',
};

const props4: ButtonProps<typeof TestOverride> = {
component: TestOverride,
x: 2,
};

const props5: ButtonProps<typeof TestOverride> = {
component: TestOverride,
// @ts-expect-error
inCorrectProp: 3,
};

const props6: ButtonProps<typeof TestOverride> = {
component: TestOverride,
};

const buttonTest = () => (
<div>
<Button>I am a button!</Button>
Expand Down
4 changes: 2 additions & 2 deletions packages/mui-material/src/Card/Card.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { SxProps } from '@mui/system';
import { DistributiveOmit } from '@mui/types';
import { OverridableComponent, OverrideProps } from '@mui/material/OverridableComponent';
import { Theme } from '..';
import { PaperProps } from '../Paper';
import { PaperOwnProps } from '../Paper';
import { CardClasses } from './cardClasses';

// TODO: v6 remove this interface, it is not used
export interface CardPropsColorOverrides {}

export interface CardTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P &
DistributiveOmit<PaperProps, 'classes'> & {
DistributiveOmit<PaperOwnProps, 'classes'> & {
/**
* Override or extend the styles applied to the component.
*/
Expand Down
33 changes: 33 additions & 0 deletions packages/mui-material/src/Card/Card.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import Card from '@mui/material/Card';
import { expectType } from '@mui/types';

const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
function CustomComponent() {
return <div />;
};

function CardTest() {
return (
<div>
<Card />
<Card elevation={4} />
<Card
onClick={(event) => {
expectType<React.MouseEvent<HTMLDivElement, MouseEvent>, typeof event>(event);
}}
/>
<Card
component="a"
href="test"
onClick={(event) => {
expectType<React.MouseEvent<HTMLAnchorElement, MouseEvent>, typeof event>(event);
}}
/>

<Card component={CustomComponent} stringProp="test" numberProp={0} />
{/* @ts-expect-error missing stringProp and numberProp */}
<Card component={CustomComponent} />
</div>
);
}
13 changes: 9 additions & 4 deletions packages/mui-material/src/CardHeader/CardHeader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@ interface ComponentProp {
component?: React.ElementType;
}

<CardHeader component={CustomComponent} stringProp="s" numberProp={2} />;

function createElementBasePropMixedTest() {
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader);
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
component: 'div',
});
// ExpectError: type system should be demanding the required props of "CustomComponent"
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
// @ts-expect-error
React.createElement<CardHeaderProps<typeof CustomComponent>>(CardHeader, {
component: CustomComponent,
stringProp: '2',
numberProp: 3,
incorrectProp: 3,
});
// @ts-expect-error
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
// This test shouldn't fail but does; stringProp & numberProp are required props of CustomComponent

React.createElement<CardHeaderProps<typeof CustomComponent>>(CardHeader, {
component: CustomComponent,
stringProp: '',
numberProp: 0,
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-material/src/Dialog/Dialog.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export interface DialogProps extends StandardProps<ModalProps, 'children'> {
* Props applied to the [`Paper`](/material-ui/api/paper/) element.
* @default {}
*/
PaperProps?: Partial<PaperProps>;
PaperProps?: Partial<PaperProps<React.ElementType>>;
/**
* Determine the container for scrolling the dialog.
* @default 'paper'
Expand Down
19 changes: 16 additions & 3 deletions packages/mui-material/src/Dialog/Dialog.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import * as React from 'react';
import { Dialog } from '@mui/material';
import Dialog from '@mui/material/Dialog';
import { PaperProps } from '@mui/material/Paper';
import { expectType } from '@mui/types';

function optionalChildrenTest() {
<Dialog open />;
const paperProps: PaperProps<'span'> = {
component: 'span',
onClick: (event) => {
expectType<React.MouseEvent<HTMLSpanElement, MouseEvent>, typeof event>(event);
},
};
function Test() {
return (
<React.Fragment>
<Dialog open />;
<Dialog open PaperProps={paperProps} />;
</React.Fragment>
);
}
2 changes: 1 addition & 1 deletion packages/mui-material/src/Drawer/Drawer.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export interface DrawerProps extends StandardProps<ModalProps, 'open' | 'childre
* Props applied to the [`Paper`](/material-ui/api/paper/) element.
* @default {}
*/
PaperProps?: Partial<PaperProps>;
PaperProps?: Partial<PaperProps<React.ElementType>>;
/**
* Props applied to the [`Slide`](/material-ui/api/slide/) element.
*/
Expand Down
19 changes: 19 additions & 0 deletions packages/mui-material/src/Drawer/Drawer.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import Drawer from '@mui/material/Drawer';
import { PaperProps } from '@mui/material/Paper';
import { expectType } from '@mui/types';

const paperProps: PaperProps<'span'> = {
component: 'span',
onClick: (event) => {
expectType<React.MouseEvent<HTMLSpanElement, MouseEvent>, typeof event>(event);
},
};
function Test() {
return (
<React.Fragment>
<Drawer open />;
<Drawer open PaperProps={paperProps} />;
</React.Fragment>
);
}
2 changes: 1 addition & 1 deletion packages/mui-material/src/Fab/Fab.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ Fab.propTypes /* remove-proptypes */ = {
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
component: PropTypes /* @typescript-to-proptypes-ignore */.elementType,
/**
* If `true`, the component is disabled.
* @default false
Expand Down
66 changes: 66 additions & 0 deletions packages/mui-material/src/FormHelperText/FormHelperText.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as React from 'react';
import FormHelperText, { FormHelperTextProps } from '@mui/material/FormHelperText';
import { expectType } from '@mui/types';

const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
function CustomComponent() {
return <div />;
};

const props: FormHelperTextProps<'div'> = {
component: 'div',
onChange: (event) => {
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
},
};

const props2: FormHelperTextProps = {
onChange: (event) => {
expectType<React.FormEvent<HTMLParagraphElement>, typeof event>(event);
},
};

const props3: FormHelperTextProps<'span'> = {
// @ts-expect-error
component: 'div',
};

const props4: FormHelperTextProps<typeof CustomComponent> = {
component: CustomComponent,
stringProp: '2',
numberProp: 2,
};

const props5: FormHelperTextProps<typeof CustomComponent> = {
component: CustomComponent,
stringProp: '2',
numberProp: 2,
// @ts-expect-error
inCorrectProp: 3,
};

// @ts-expect-error
const props6: FormHelperTextProps<typeof CustomComponent> = {
component: CustomComponent,
};

const TestComponent = () => {
return (
<React.Fragment>
<FormHelperText />
<FormHelperText component={'a'} href="/test" />

<FormHelperText component={CustomComponent} stringProp="s" numberProp={1} />
{
// @ts-expect-error
<FormHelperText component={CustomComponent} />
}
<FormHelperText
component="span"
onChange={(event) => {
expectType<React.FormEvent<HTMLSpanElement>, typeof event>(event);
}}
/>
</React.Fragment>
);
};
65 changes: 63 additions & 2 deletions packages/mui-material/src/Grid/Grid.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,68 @@
import * as React from 'react';
import Paper from '@mui/material/Paper';
import Grid from '@mui/material/Grid';
import Grid, { GridProps } from '@mui/material/Grid';
import { expectType } from '@mui/types';

const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
function CustomComponent() {
return <div />;
};

const props: GridProps<'span'> = {
component: 'span',
onChange: (event) => {
expectType<React.FormEvent<HTMLSpanElement>, typeof event>(event);
},
};

const props2: GridProps = {
onChange: (event) => {
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
},
};

const props3: GridProps<'span'> = {
// @ts-expect-error
component: 'div',
};

const props4: GridProps<typeof CustomComponent> = {
component: CustomComponent,
stringProp: '2',
numberProp: 2,
};

const props5: GridProps<typeof CustomComponent> = {
component: CustomComponent,
stringProp: '2',
numberProp: 2,
// @ts-expect-error
inCorrectProp: 3,
};

// @ts-expect-error
const props6: GridProps<typeof CustomComponent> = {
component: CustomComponent,
};

function ResponsiveTest() {
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square />;
return (
<React.Fragment>
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square />
<Grid item component={'a'} href="/test" />

<Grid item component={CustomComponent} stringProp="s" numberProp={1} />
{
// @ts-expect-error
<Grid item component={CustomComponent} />
}
<Grid
item
component="span"
onChange={(event) => {
expectType<React.FormEvent<HTMLSpanElement>, typeof event>(event);
}}
/>
</React.Fragment>
);
}
Loading

0 comments on commit 1b9c8ab

Please sign in to comment.