Skip to content

Commit

Permalink
[material-ui][Select] Fix variant type (#41405)
Browse files Browse the repository at this point in the history
  • Loading branch information
sai6855 committed Mar 14, 2024
1 parent 65408b1 commit c25839e
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 21 deletions.
28 changes: 8 additions & 20 deletions packages/mui-material/src/Select/Select.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export interface BaseSelectProps<Value = unknown>
* The variant to use.
* @default 'outlined'
*/
variant?: 'filled' | 'standard' | 'outlined';
variant?: SelectVariants;
}

export interface FilledSelectProps extends Omit<FilledInputProps, 'value' | 'onChange'> {
Expand All @@ -172,20 +172,15 @@ export interface OutlinedSelectProps extends Omit<OutlinedInputProps, 'value' |
* The variant to use.
* @default 'outlined'
*/
variant: 'outlined';
variant?: 'outlined';
}

export type SelectVariants = 'outlined' | 'standard' | 'filled';

export type SelectProps<
Value = unknown,
Variant extends SelectVariants = SelectVariants,
> = BaseSelectProps<Value> &
(Variant extends 'filled'
? FilledSelectProps
: Variant extends 'standard'
? StandardSelectProps
: OutlinedSelectProps);
export type SelectProps<Value = unknown> =
| (FilledSelectProps & BaseSelectProps<Value>)
| (StandardSelectProps & BaseSelectProps<Value>)
| (OutlinedSelectProps & BaseSelectProps<Value>);

/**
*
Expand All @@ -198,15 +193,8 @@ export type SelectProps<
* - [Select API](https://mui.com/material-ui/api/select/)
* - inherits [OutlinedInput API](https://mui.com/material-ui/api/outlined-input/)
*/

export default function Select<Value = unknown, Variant extends SelectVariants = 'outlined'>(
props: {
/**
* The variant to use.
* @default 'outlined'
*/
variant?: Variant;
} & Omit<SelectProps<Value, Variant>, 'variant'>,
export default function Select<Value = unknown>(
props: SelectProps<Value>,
): JSX.Element & {
muiName: string;
};
122 changes: 121 additions & 1 deletion packages/mui-material/src/Select/Select.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import Select, { SelectChangeEvent } from '@mui/material/Select';
import Select, { SelectChangeEvent, SelectProps } from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import { createTheme } from '@mui/material/styles';

Expand Down Expand Up @@ -75,4 +75,124 @@ function genericValueTest() {
},
}}
/>;

<Select variant="filled" />;
<Select variant="standard" />;
<Select variant="outlined" />;
<Select />;

<Select variant="filled" hiddenLabel />;
// @ts-expect-error hiddenLabel is not present in standard variant
<Select variant="standard" hiddenLabel />;
// @ts-expect-error hiddenLabel is not present in outlined variant
<Select variant="outlined" hiddenLabel />;
// @ts-expect-error hiddenLabel is not present in outlined variant
<Select hiddenLabel />;

const defaultProps: SelectProps<number> = {};
const outlinedProps: SelectProps<number> = {
variant: 'outlined',
};
const filledProps: SelectProps<number> = {
variant: 'filled',
};
const standardProps: SelectProps<number> = {
variant: 'standard',
};

<Select {...defaultProps} />;
<Select {...outlinedProps} />;
<Select {...filledProps} />;
<Select {...standardProps} />;
<Select<number> {...outlinedProps} />;
<Select<number> {...defaultProps} />;
<Select<number> {...filledProps} />;

const rawDefaultProps: SelectProps = {};
const rawOutlinedProps: SelectProps = {
variant: 'outlined',
};
const rawFilledProps: SelectProps = {
variant: 'filled',
};

<Select {...rawDefaultProps} />;
<Select {...rawOutlinedProps} />;
<Select {...rawFilledProps} />;

// @ts-expect-error hiddenLabel is not present in outlined variant
<Select {...defaultProps} hiddenLabel />;
// @ts-expect-error hiddenLabel is not present in outlined variant
<Select {...outlinedProps} hiddenLabel />;
<Select {...filledProps} hiddenLabel />;
// @ts-expect-error hiddenLabel is not present in standard variant
<Select {...standardProps} hiddenLabel />;

interface OtherProps {
otherProp?: number;
}

const SelectWrapper1 = <Value,>(props: SelectProps<Value> & OtherProps) => {
const { otherProp, ...materialSelectProps } = props;

return <Select<Value> {...materialSelectProps} />;
};

<SelectWrapper1 />;
<SelectWrapper1<number> variant="filled" hiddenLabel />;
<SelectWrapper1 variant="filled" hiddenLabel />;
}

type Options<T> = { text: string; value: T } | T;

type Props<T> = (
| {
value: T;
multiple?: false;
onChange: (value: T) => void;
}
| {
value: T[];
multiple: true;
onChange: (value: T[]) => void;
}
) & {
options: Options<T>[];
};

// test for https://github.com/mui/material-ui/issues/41375
const AppSelect = <T extends string>(props: Props<T>) => {
const getOptionText = (option: Options<T>) => {
if (typeof option === 'object') {
return option.text;
}
return option;
};

const getOptionValue = (option: Options<T>) => {
if (typeof option === 'object') {
return option.value;
}
return option;
};

return (
<Select
value={props.value}
multiple={props.multiple}
onChange={(event) => {
if (props.multiple) {
props.onChange(event.target.value as T[]);
} else {
props.onChange(event.target.value as T);
}
}}
>
{props.options.map((option, index) => (
<MenuItem key={index} value={getOptionValue(option)}>
{getOptionText(option)}
</MenuItem>
))}
</Select>
);
};

0 comments on commit c25839e

Please sign in to comment.