diff --git a/docs/data/joy/components/select/SelectMultiple.js b/docs/data/joy/components/select/SelectMultiple.js new file mode 100644 index 00000000000000..85e43ba38cb004 --- /dev/null +++ b/docs/data/joy/components/select/SelectMultiple.js @@ -0,0 +1,31 @@ +import * as React from 'react'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; + +export default function SelectMultiple() { + const handleChange = (event, newValue) => { + console.log(`You have choosen "${newValue}"`); + }; + return ( + + ); +} diff --git a/docs/data/joy/components/select/SelectMultiple.tsx b/docs/data/joy/components/select/SelectMultiple.tsx new file mode 100644 index 00000000000000..2f576ef505201c --- /dev/null +++ b/docs/data/joy/components/select/SelectMultiple.tsx @@ -0,0 +1,34 @@ +import * as React from 'react'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; + +export default function SelectMultiple() { + const handleChange = ( + event: React.SyntheticEvent | null, + newValue: Array | null, + ) => { + console.log(`You have choosen "${newValue}"`); + }; + return ( + + ); +} diff --git a/docs/data/joy/components/select/SelectMultipleAppearance.js b/docs/data/joy/components/select/SelectMultipleAppearance.js new file mode 100644 index 00000000000000..cd738b5f59c091 --- /dev/null +++ b/docs/data/joy/components/select/SelectMultipleAppearance.js @@ -0,0 +1,37 @@ +import * as React from 'react'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import { Box, Chip } from '@mui/joy'; + +export default function SelectMultipleAppearance() { + return ( + + ); +} diff --git a/docs/data/joy/components/select/SelectMultipleAppearance.tsx b/docs/data/joy/components/select/SelectMultipleAppearance.tsx new file mode 100644 index 00000000000000..cd738b5f59c091 --- /dev/null +++ b/docs/data/joy/components/select/SelectMultipleAppearance.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import { Box, Chip } from '@mui/joy'; + +export default function SelectMultipleAppearance() { + return ( + + ); +} diff --git a/docs/data/joy/components/select/SelectMultipleFormSubmission.js b/docs/data/joy/components/select/SelectMultipleFormSubmission.js new file mode 100644 index 00000000000000..c08b2a2d6e0c60 --- /dev/null +++ b/docs/data/joy/components/select/SelectMultipleFormSubmission.js @@ -0,0 +1,36 @@ +import * as React from 'react'; +import Button from '@mui/joy/Button'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import Stack from '@mui/joy/Stack'; + +export default function SelectMultipleFormSubmission() { + return ( +
{ + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const formJson = Object.fromEntries(formData.entries()); + const selectedPets = JSON.parse(formJson.pets); + alert(JSON.stringify(selectedPets)); + }} + > + + + + +
+ ); +} diff --git a/docs/data/joy/components/select/SelectMultipleFormSubmission.tsx b/docs/data/joy/components/select/SelectMultipleFormSubmission.tsx new file mode 100644 index 00000000000000..b16c85696fe035 --- /dev/null +++ b/docs/data/joy/components/select/SelectMultipleFormSubmission.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import Button from '@mui/joy/Button'; +import Select from '@mui/joy/Select'; +import Option from '@mui/joy/Option'; +import Stack from '@mui/joy/Stack'; + +export default function SelectMultipleFormSubmission() { + return ( +
{ + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const formJson = Object.fromEntries((formData as any).entries()); + const selectedPets = JSON.parse(formJson.pets); + alert(JSON.stringify(selectedPets)); + }} + > + + + + +
+ ); +} diff --git a/docs/data/joy/components/select/select.md b/docs/data/joy/components/select/select.md index 9007ed7ed01cdd..9ba7298c176184 100644 --- a/docs/data/joy/components/select/select.md +++ b/docs/data/joy/components/select/select.md @@ -123,6 +123,27 @@ const App = () => ( ); ``` +### Multiple selections + +Set the `multiple` prop to let your users select multiple options from the list. +In contrast with single-selection mode, the options popup doesn't close after an item is selected, which enables users to continue choosing more options. + +Note that in multiple selection mode, the `value` prop (and `defaultValue`) is an array. + +{{"demo": "SelectMultiple.js"}} + +#### Selected value appearance + +Use the `renderValue` prop to customize the display of the selected options. + +{{"demo": "SelectMultipleAppearance.js"}} + +#### Form submission + +The `Select` component supports `name` and `required` props that will be used when submitting the form. + +{{"demo": "SelectMultipleFormSubmission.js"}} + ### Listbox #### Maximum height diff --git a/docs/pages/joy-ui/api/select.json b/docs/pages/joy-ui/api/select.json index af8f6611339328..7e2c557988416d 100644 --- a/docs/pages/joy-ui/api/select.json +++ b/docs/pages/joy-ui/api/select.json @@ -23,6 +23,7 @@ "indicator": { "type": { "name": "node" } }, "listboxId": { "type": { "name": "string" } }, "listboxOpen": { "type": { "name": "bool" } }, + "multiple": { "type": { "name": "bool" } }, "name": { "type": { "name": "string" } }, "onChange": { "type": { "name": "func" } }, "onClose": { "type": { "name": "func" } }, @@ -113,6 +114,7 @@ "disabled", "expanded", "focusVisible", + "multiple", "popper", "sizeLg", "sizeMd", diff --git a/docs/translations/api-docs-joy/select/select.json b/docs/translations/api-docs-joy/select/select.json index e3f5399432fec2..248396717d8ae2 100644 --- a/docs/translations/api-docs-joy/select/select.json +++ b/docs/translations/api-docs-joy/select/select.json @@ -31,6 +31,9 @@ "description": "id attribute of the listbox element. Also used to derive the id attributes of options." }, "listboxOpen": { "description": "Controls the open state of the select's listbox." }, + "multiple": { + "description": "If true, selecting multiple values is allowed. This affects the type of the value, defaultValue, and onChange props." + }, "name": { "description": "Name of the element. For example used by the server to identify the fields in form submits. If the name is provided, the component will render a hidden input element that can be submitted to a server." }, @@ -85,6 +88,9 @@ "description": "Class name applied to {{nodeName}}.", "nodeName": "the listbox slot" }, + "multiple": { + "description": "Class name applied to the root slot if multiple=true" + }, "colorPrimary": { "description": "Class name applied to {{nodeName}} if {{conditions}}.", "nodeName": "the root slot", diff --git a/packages/mui-joy/src/Select/Select.spec.tsx b/packages/mui-joy/src/Select/Select.spec.tsx index a5f4084c690a5e..bc3db85409e56d 100644 --- a/packages/mui-joy/src/Select/Select.spec.tsx +++ b/packages/mui-joy/src/Select/Select.spec.tsx @@ -105,40 +105,119 @@ interface Value { ; + value={[10]} onChange={handleMultiChange} />; + value={[10]} component="a" />; +; +; +; + +; + + + value={[10]} + // @ts-expect-error + onChange={handleChange} +/>; + +; + + onChange={handleMultiChange} value={[10]} />; + +; +// @ts-expect-error +; +// @ts-expect-error +; diff --git a/packages/mui-joy/src/Select/Select.test.tsx b/packages/mui-joy/src/Select/Select.test.tsx index 06c7060b14c3ba..550b2e3f53bd35 100644 --- a/packages/mui-joy/src/Select/Select.test.tsx +++ b/packages/mui-joy/src/Select/Select.test.tsx @@ -646,4 +646,32 @@ describe('Joy values.map((v) => `${v.label} (${v.value})`).join(', ')} + > + + + , + ); + + expect(getByRole('combobox')).to.have.text('One (1), Two (2)'); + }); + + it('renders the selected values (multiple) as comma-separated list of labels if renderValue is not provided', () => { + const { getByRole } = render( + , + ); + + expect(getByRole('combobox')).to.have.text('One, Two'); + }); + }); }); diff --git a/packages/mui-joy/src/Select/Select.tsx b/packages/mui-joy/src/Select/Select.tsx index 8d2556846a780c..0bf261300def0d 100644 --- a/packages/mui-joy/src/Select/Select.tsx +++ b/packages/mui-joy/src/Select/Select.tsx @@ -5,7 +5,7 @@ import clsx from 'clsx'; import { OverrideProps, DefaultComponentProps } from '@mui/types'; import { unstable_capitalize as capitalize, unstable_useForkRef as useForkRef } from '@mui/utils'; import { Popper, PopperProps } from '@mui/base/Popper'; -import { useSelect, SelectProvider } from '@mui/base/useSelect'; +import { useSelect, SelectProvider, SelectValue } from '@mui/base/useSelect'; import { SelectOption } from '@mui/base/useOption'; import { unstable_composeClasses as composeClasses } from '@mui/base/composeClasses'; import { StyledList } from '../List/List'; @@ -13,7 +13,12 @@ import ListProvider, { scopedVariables } from '../List/ListProvider'; import GroupListContext from '../List/GroupListContext'; import Unfold from '../internal/svg-icons/Unfold'; import { styled, useThemeProps } from '../styles'; -import { SelectOwnProps, SelectOwnerState, SelectTypeMap } from './SelectProps'; +import { + SelectOwnProps, + SelectOwnerState, + SelectSlotsAndSlotProps, + SelectTypeMap, +} from './SelectProps'; import { resolveSxValue } from '../styles/styleUtils'; import useSlot from '../utils/useSlot'; import selectClasses, { getSelectUtilityClass } from './selectClasses'; @@ -21,10 +26,15 @@ import { ListOwnerState } from '../List'; import FormControlContext from '../FormControl/FormControlContext'; import { VariantColorProvider } from '../styles/variantColorInheritance'; -function defaultRenderSingleValue(selectedOption: SelectOption | null) { - return selectedOption?.label ?? ''; -} +function defaultRenderValue( + selectedOptions: SelectOption | SelectOption[] | null, +) { + if (Array.isArray(selectedOptions)) { + return {selectedOptions.map((o) => o.label).join(', ')}; + } + return selectedOptions?.label ?? ''; +} const defaultModifiers: PopperProps['modifiers'] = [ { name: 'offset', @@ -44,8 +54,8 @@ const defaultModifiers: PopperProps['modifiers'] = [ }, ]; -const useUtilityClasses = (ownerState: SelectOwnerState) => { - const { color, disabled, focusVisible, size, variant, open } = ownerState; +const useUtilityClasses = (ownerState: SelectOwnerState) => { + const { color, disabled, focusVisible, size, variant, open, multiple } = ownerState; const slots = { root: [ @@ -56,6 +66,7 @@ const useUtilityClasses = (ownerState: SelectOwnerState) => { variant && `variant${capitalize(variant)}`, color && `color${capitalize(color)}`, size && `size${capitalize(size)}`, + multiple && 'multiple', ], button: ['button'], startDecorator: ['startDecorator'], @@ -71,7 +82,7 @@ const SelectRoot = styled('div', { name: 'JoySelect', slot: 'Root', overridesResolver: (props, styles) => styles.root, -})<{ ownerState: SelectOwnerState }>(({ theme, ownerState }) => { +})<{ ownerState: SelectOwnerState }>(({ theme, ownerState }) => { const variantStyle = theme.variants[`${ownerState.variant!}`]?.[ownerState.color!]; const { borderRadius } = resolveSxValue({ theme, ownerState }, ['borderRadius']); return [ @@ -181,7 +192,7 @@ const SelectButton = styled('button', { name: 'JoySelect', slot: 'Button', overridesResolver: (props, styles) => styles.button, -})<{ ownerState: SelectOwnerState }>(({ ownerState }) => ({ +})<{ ownerState: SelectOwnerState }>(({ ownerState }) => ({ // reset user-agent button style border: 0, outline: 0, @@ -218,7 +229,7 @@ const SelectListbox = styled(StyledList, { name: 'JoySelect', slot: 'Listbox', overridesResolver: (props, styles) => styles.listbox, -})<{ ownerState: SelectOwnerState }>(({ theme, ownerState }) => { +})<{ ownerState: SelectOwnerState }>(({ theme, ownerState }) => { const variantStyle = theme.variants[ownerState.variant!]?.[ownerState.color!]; return { '--focus-outline-offset': `calc(${theme.vars.focus.thickness} * -1)`, // to prevent the focus outline from being cut by overflow @@ -246,7 +257,7 @@ const SelectStartDecorator = styled('span', { name: 'JoySelect', slot: 'StartDecorator', overridesResolver: (props, styles) => styles.startDecorator, -})<{ ownerState: SelectOwnerState }>({ +})<{ ownerState: SelectOwnerState }>({ '--Button-margin': '0 0 0 calc(var(--Select-decoratorChildOffset) * -1)', '--IconButton-margin': '0 0 0 calc(var(--Select-decoratorChildOffset) * -1)', '--Icon-margin': '0 0 0 calc(var(--Select-paddingInline) / -4)', @@ -260,7 +271,7 @@ const SelectEndDecorator = styled('span', { name: 'JoySelect', slot: 'EndDecorator', overridesResolver: (props, styles) => styles.endDecorator, -})<{ ownerState: SelectOwnerState }>({ +})<{ ownerState: SelectOwnerState }>({ '--Button-margin': '0 calc(var(--Select-decoratorChildOffset) * -1) 0 0', '--IconButton-margin': '0 calc(var(--Select-decoratorChildOffset) * -1) 0 0', '--Icon-margin': '0 calc(var(--Select-paddingInline) / -4) 0 0', @@ -273,7 +284,7 @@ const SelectEndDecorator = styled('span', { const SelectIndicator = styled('span', { name: 'JoySelect', slot: 'Indicator', -})<{ ownerState: SelectOwnerState }>(({ ownerState, theme }) => ({ +})<{ ownerState: SelectOwnerState }>(({ ownerState, theme }) => ({ ...(ownerState.size === 'sm' && { '--Icon-fontSize': theme.vars.fontSize.lg, }), @@ -308,8 +319,8 @@ const SelectIndicator = styled('span', { * * - [Select API](https://mui.com/joy-ui/api/select/) */ -const Select = React.forwardRef(function Select( - inProps: SelectOwnProps, +const Select = React.forwardRef(function Select( + inProps: SelectOwnProps, ref: React.ForwardedRef, ) { const props = useThemeProps({ @@ -346,6 +357,7 @@ const Select = React.forwardRef(function Select( 'aria-labelledby': ariaLabelledby, id, name, + multiple = false as Multiple, slots = {}, slotProps = {}, ...other @@ -376,7 +388,9 @@ const Select = React.forwardRef(function Select( const size = inProps.size ?? formControl?.size ?? sizeProp; const color = inProps.color ?? (formControl?.error ? 'danger' : formControl?.color ?? colorProp); - const renderValue = renderValueProp ?? defaultRenderSingleValue; + const renderValue: (option: SelectValue, Multiple>) => React.ReactNode = + renderValueProp ?? defaultRenderValue; + const [anchorEl, setAnchorEl] = React.useState(null); const rootRef = React.useRef(null); @@ -433,7 +447,7 @@ const Select = React.forwardRef(function Select( disabled: disabledProp, getSerializedValue, listboxId, - multiple: false, + multiple, name, required, onChange, @@ -442,7 +456,7 @@ const Select = React.forwardRef(function Select( value: valueProp, }); - const ownerState = { + const ownerState: SelectOwnerState = { ...props, active: buttonActive, defaultListboxOpen, @@ -457,19 +471,34 @@ const Select = React.forwardRef(function Select( }; const classes = useUtilityClasses(ownerState); - const externalForwardedProps = { ...other, slots, slotProps }; + const externalForwardedProps = { + ...other, + slots, + slotProps, + } as SelectSlotsAndSlotProps & typeof other; + + const selectedOption = React.useMemo(() => { + let selectedOptionsMetadata: SelectValue, Multiple>; + if (multiple) { + selectedOptionsMetadata = (value as OptionValue[]) + .map((v) => getOptionMetadata(v)) + .filter((o) => o !== undefined) as SelectValue, Multiple>; + } else { + selectedOptionsMetadata = (getOptionMetadata(value as OptionValue) ?? null) as SelectValue< + SelectOption, + Multiple + >; + } - const selectedOption = React.useMemo( - () => getOptionMetadata(value as TValue) ?? null, - [getOptionMetadata, value], - ); + return selectedOptionsMetadata; + }, [getOptionMetadata, value, multiple]); const [SlotRoot, rootProps] = useSlot('root', { ref: handleRef, className: classes.root, elementType: SelectRoot, externalForwardedProps, - ownerState, + ownerState: ownerState as SelectOwnerState, }); const [SlotButton, buttonProps] = useSlot('button', { @@ -485,7 +514,7 @@ const Select = React.forwardRef(function Select( elementType: SelectButton, externalForwardedProps, getSlotProps: getButtonProps, - ownerState, + ownerState: ownerState as SelectOwnerState, }); const [SlotListbox, listboxProps] = useSlot('listbox', { @@ -505,7 +534,7 @@ const Select = React.forwardRef(function Select( nesting: false, row: false, wrap: false, - } as SelectOwnerState & ListOwnerState, + } as SelectOwnerState & ListOwnerState, getSlotOwnerState: (mergedProps) => ({ size: mergedProps.size || size, variant: mergedProps.variant || variant, @@ -518,21 +547,21 @@ const Select = React.forwardRef(function Select( className: classes.startDecorator, elementType: SelectStartDecorator, externalForwardedProps, - ownerState, + ownerState: ownerState as SelectOwnerState, }); const [SlotEndDecorator, endDecoratorProps] = useSlot('endDecorator', { className: classes.endDecorator, elementType: SelectEndDecorator, externalForwardedProps, - ownerState, + ownerState: ownerState as SelectOwnerState, }); const [SlotIndicator, indicatorProps] = useSlot('indicator', { className: classes.indicator, elementType: SelectIndicator, externalForwardedProps, - ownerState, + ownerState: ownerState as SelectOwnerState, }); // Wait for `listboxProps` because `slotProps.listbox` could be a function. @@ -582,16 +611,21 @@ const Select = React.forwardRef(function Select( }) as SelectComponent; interface SelectComponent { - ( + ( props: { /** * The component used for the root node. * Either a string to use a HTML element or a component. */ component: C; - } & OverrideProps, C>, + multiple?: Multiple; + } & OverrideProps, C>, + ): JSX.Element | null; + ( + props: { + multiple?: Multiple; + } & DefaultComponentProps>, ): JSX.Element | null; - (props: DefaultComponentProps>): JSX.Element | null; propTypes?: any; } @@ -678,6 +712,11 @@ Select.propTypes /* remove-proptypes */ = { * @default undefined */ listboxOpen: PropTypes.bool, + /** + * If `true`, selecting multiple values is allowed. + * This affects the type of the `value`, `defaultValue`, and `onChange` props. + */ + multiple: PropTypes.bool, /** * Name of the element. For example used by the server to identify the fields in form submits. * If the name is provided, the component will render a hidden input element that can be submitted to a server. diff --git a/packages/mui-joy/src/Select/SelectProps.ts b/packages/mui-joy/src/Select/SelectProps.ts index de93fbe25ae293..b49008f4a3857d 100644 --- a/packages/mui-joy/src/Select/SelectProps.ts +++ b/packages/mui-joy/src/Select/SelectProps.ts @@ -53,14 +53,14 @@ export interface SelectPropsVariantOverrides {} export interface SelectPropsColorOverrides {} export interface SelectPropsSizeOverrides {} -export type SelectSlotsAndSlotProps = CreateSlotsAndSlotProps< +export type SelectSlotsAndSlotProps = CreateSlotsAndSlotProps< SelectSlots, { - root: SlotProps<'div', {}, SelectOwnerState>; - button: SlotProps<'button', {}, SelectOwnerState>; - startDecorator: SlotProps<'span', {}, SelectOwnerState>; - endDecorator: SlotProps<'span', {}, SelectOwnerState>; - indicator: SlotProps<'span', {}, SelectOwnerState>; + root: SlotProps<'div', {}, SelectOwnerState>; + button: SlotProps<'button', {}, SelectOwnerState>; + startDecorator: SlotProps<'span', {}, SelectOwnerState>; + endDecorator: SlotProps<'span', {}, SelectOwnerState>; + indicator: SlotProps<'span', {}, SelectOwnerState>; listbox: SlotProps< 'ul', { @@ -68,7 +68,7 @@ export type SelectSlotsAndSlotProps = CreateSlotsAndSlotProps< variant?: OverridableStringUnion; size?: OverridableStringUnion<'sm' | 'md' | 'lg', SelectPropsSizeOverrides>; } & Omit, - SelectOwnerState + SelectOwnerState >; } >; @@ -165,40 +165,47 @@ export interface SelectStaticProps { variant?: OverridableStringUnion; } -export type SelectOwnProps = SelectStaticProps & - SelectSlotsAndSlotProps & { +export type SelectOwnProps = SelectStaticProps & + SelectSlotsAndSlotProps & { /** * The default selected value. Use when the component is not controlled. */ - defaultValue?: OptionValue | null; + defaultValue?: SelectValue; + /** + * If `true`, selecting multiple values is allowed. + * This affects the type of the `value`, `defaultValue`, and `onChange` props. + * + * @default false + */ + multiple?: Multiple; /** * A function to convert the currently selected value to a string. * Used to set a value of a hidden input associated with the select, * so that the selected value can be posted with a form. */ getSerializedValue?: ( - option: SelectValue, false>, + option: SelectValue, Multiple>, ) => React.InputHTMLAttributes['value']; /** * Callback fired when an option is selected. */ onChange?: ( event: React.MouseEvent | React.KeyboardEvent | React.FocusEvent | null, - value: OptionValue | null, + value: SelectValue, ) => void; /** * Function that customizes the rendering of the selected value. */ - renderValue?: (option: SelectOption | null) => React.ReactNode; + renderValue?: (option: SelectValue, Multiple>) => React.ReactNode; /** * The selected value. * Set to `null` to deselect all options. */ - value?: OptionValue | null; + value?: SelectValue; }; -export interface SelectOwnerState - extends ApplyColorInversion> { +export interface SelectOwnerState + extends ApplyColorInversion> { /** * If `true`, the select button is active. */ @@ -223,16 +230,18 @@ export interface SelectOwnerState export interface SelectTypeMap< OptionValue extends {}, + Multiple extends boolean = false, P = {}, D extends React.ElementType = 'button', > { - props: P & SelectOwnProps; + props: P & SelectOwnProps; defaultComponent: D; } export type SelectProps< OptionValue extends {}, - D extends React.ElementType = SelectTypeMap['defaultComponent'], -> = OverrideProps, D> & { + Multiple extends boolean, + D extends React.ElementType = SelectTypeMap['defaultComponent'], +> = OverrideProps, D> & { component?: D; }; diff --git a/packages/mui-joy/src/Select/selectClasses.ts b/packages/mui-joy/src/Select/selectClasses.ts index 026f859797e5c0..fb6c67bf4a28fb 100644 --- a/packages/mui-joy/src/Select/selectClasses.ts +++ b/packages/mui-joy/src/Select/selectClasses.ts @@ -15,6 +15,8 @@ export interface SelectClasses { popper: string; /** Class name applied to the listbox slot. */ listbox: string; + /** Class name applied to the root slot if `multiple=true` */ + multiple: string; /** Class name applied to the root slot if `color="primary"`. */ colorPrimary: string; /** Class name applied to the root slot if `color="neutral"`. */ @@ -79,6 +81,7 @@ const selectClasses: SelectClasses = generateUtilityClasses('MuiSelect', [ 'focusVisible', 'disabled', 'expanded', + 'multiple', ]); export default selectClasses; diff --git a/packages/mui-joy/src/styles/components.d.ts b/packages/mui-joy/src/styles/components.d.ts index f12a710f7ee8c6..a02018d11bd571 100644 --- a/packages/mui-joy/src/styles/components.d.ts +++ b/packages/mui-joy/src/styles/components.d.ts @@ -431,8 +431,8 @@ export interface Components { styleOverrides?: StyleOverrides; }; JoySelect?: { - defaultProps?: Partial>; - styleOverrides?: StyleOverrides, Theme>; + defaultProps?: Partial>; + styleOverrides?: StyleOverrides, Theme>; }; JoyOption?: { defaultProps?: Partial; diff --git a/packages/mui-joy/src/styles/extendTheme.spec.ts b/packages/mui-joy/src/styles/extendTheme.spec.ts index 38c31364a17de1..4123819575c786 100644 --- a/packages/mui-joy/src/styles/extendTheme.spec.ts +++ b/packages/mui-joy/src/styles/extendTheme.spec.ts @@ -1012,37 +1012,37 @@ extendTheme({ }, styleOverrides: { root: ({ ownerState }) => { - expectType & Record, typeof ownerState>( + expectType & Record, typeof ownerState>( ownerState, ); return {}; }, button: ({ ownerState }) => { - expectType & Record, typeof ownerState>( + expectType & Record, typeof ownerState>( ownerState, ); return {}; }, startDecorator: ({ ownerState }) => { - expectType & Record, typeof ownerState>( + expectType & Record, typeof ownerState>( ownerState, ); return {}; }, endDecorator: ({ ownerState }) => { - expectType & Record, typeof ownerState>( + expectType & Record, typeof ownerState>( ownerState, ); return {}; }, indicator: ({ ownerState }) => { - expectType & Record, typeof ownerState>( + expectType & Record, typeof ownerState>( ownerState, ); return {}; }, listbox: ({ ownerState }) => { - expectType & Record, typeof ownerState>( + expectType & Record, typeof ownerState>( ownerState, ); return {};