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

[core] Adds component prop to OverrideProps type #35924

Merged
merged 24 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 22 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
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,
},
ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved
},
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'>;
ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved

// 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 { PaperBaseProps } 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<PaperBaseProps, '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