From 22da155ab9f633b971e6c0d848ff9f7ee4c8476a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Sat, 16 Sep 2023 00:47:48 +0800 Subject: [PATCH 01/18] Convert to typescript --- packages/mui-base/src/FormControl/index.ts | 2 + .../src/FormControl/FormControl.d.ts | 133 ------------------ .../src/FormControl/FormControl.test.js | 3 +- .../{FormControl.js => FormControl.tsx} | 36 +++-- .../src/FormControl/FormControl.types.ts | 90 ++++++++++++ .../src/FormControl/FormControlContext.ts | 14 +- .../src/FormControl/index.d.ts | 9 -- .../src/FormControl/{index.js => index.ts} | 0 .../src/FormControl/useFormControl.ts | 4 +- 9 files changed, 125 insertions(+), 166 deletions(-) delete mode 100644 packages/mui-material-next/src/FormControl/FormControl.d.ts rename packages/mui-material-next/src/FormControl/{FormControl.js => FormControl.tsx} (88%) create mode 100644 packages/mui-material-next/src/FormControl/FormControl.types.ts delete mode 100644 packages/mui-material-next/src/FormControl/index.d.ts rename packages/mui-material-next/src/FormControl/{index.js => index.ts} (100%) diff --git a/packages/mui-base/src/FormControl/index.ts b/packages/mui-base/src/FormControl/index.ts index 8af0c5ba618fe1..1f758f2bf48b04 100644 --- a/packages/mui-base/src/FormControl/index.ts +++ b/packages/mui-base/src/FormControl/index.ts @@ -8,6 +8,8 @@ export type { FormControlRootSlotPropsOverrides, FormControlState, UseFormControlContextReturnValue, + // for material-next + FormControlOwnProps, } from './FormControl.types'; export * from './formControlClasses'; diff --git a/packages/mui-material-next/src/FormControl/FormControl.d.ts b/packages/mui-material-next/src/FormControl/FormControl.d.ts deleted file mode 100644 index 6c23df2da656ba..00000000000000 --- a/packages/mui-material-next/src/FormControl/FormControl.d.ts +++ /dev/null @@ -1,133 +0,0 @@ -import * as React from 'react'; -import { SxProps } from '@mui/system'; -import { OverridableStringUnion, OverridableComponent, OverrideProps } from '@mui/types'; -import { Theme } from '../styles'; -import { FormControlClasses } from './formControlClasses'; - -export interface FormControlPropsSizeOverrides {} -export interface FormControlPropsColorOverrides {} - -export interface FormControlOwnProps { - /** - * The content of the component. - */ - children?: React.ReactNode; - /** - * Override or extend the styles applied to the component. - */ - classes?: Partial; - /** - * The color of the component. - * It supports both default and custom theme colors, which can be added as shown in the - * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors). - * @default 'primary' - */ - color?: OverridableStringUnion< - 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning', - FormControlPropsColorOverrides - >; - /** - * If `true`, the label, input and helper text should be displayed in a disabled state. - * @default false - */ - disabled?: boolean; - /** - * If `true`, the label is displayed in an error state. - * @default false - */ - error?: boolean; - /** - * If `true`, the component will take up the full width of its container. - * @default false - */ - fullWidth?: boolean; - /** - * If `true`, the component is displayed in focused state. - */ - focused?: boolean; - /** - * If `true`, the label is hidden. - * This is used to increase density for a `FilledInput`. - * Be sure to add `aria-label` to the `input` element. - * @default false - */ - hiddenLabel?: boolean; - /** - * If `dense` or `normal`, will adjust vertical spacing of this and contained components. - * @default 'none' - */ - margin?: 'dense' | 'normal' | 'none'; - /** - * If `true`, the label will indicate that the `input` is required. - * @default false - */ - required?: boolean; - /** - * The size of the component. - * @default 'medium' - */ - size?: OverridableStringUnion<'small' | 'medium', FormControlPropsSizeOverrides>; - /** - * The system prop that allows defining system overrides as well as additional CSS styles. - */ - sx?: SxProps; - /** - * The variant to use. - * @default 'outlined' - */ - variant?: 'standard' | 'outlined' | 'filled'; -} - -export interface FormControlTypeMap< - AdditionalProps = {}, - RootComponent extends React.ElementType = 'div', -> { - props: AdditionalProps & FormControlOwnProps; - defaultComponent: RootComponent; -} - -/** - * Provides context such as filled/focused/error/required for form inputs. - * Relying on the context provides high flexibility and ensures that the state always stays - * consistent across the children of the `FormControl`. - * This context is used by the following components: - * - * * FormLabel - * * FormHelperText - * * Input - * * InputLabel - * - * You can find one composition example below and more going to [the demos](https://mui.com/material-ui/react-text-field/#components). - * - * ```jsx - * - * Email address - * - * We'll never share your email. - * - * ``` - * - * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies. - * For instance, only one input can be focused at the same time, the state shouldn't be shared. - * - * Demos: - * - * - [Checkbox](https://mui.com/material-ui/react-checkbox/) - * - [Radio Group](https://mui.com/material-ui/react-radio-button/) - * - [Switch](https://mui.com/material-ui/react-switch/) - * - [Text Field](https://mui.com/material-ui/react-text-field/) - * - * API: - * - * - [FormControl API](https://mui.com/material-ui/api/form-control/) - */ -declare const FormControl: OverridableComponent; - -export type FormControlProps< - RootComponent extends React.ElementType = FormControlTypeMap['defaultComponent'], - AdditionalProps = {}, -> = OverrideProps, RootComponent> & { - component?: React.ElementType; -}; - -export default FormControl; diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index 0027766b0f3a8e..8f54d9b98db7b6 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -26,10 +26,9 @@ describe('', () => { inheritComponent: 'div', render, refInstanceof: window.HTMLDivElement, - testComponentPropWith: 'fieldset', muiName: 'MuiFormControl', testVariantProps: { margin: 'dense' }, - skip: ['componentsProp'], + skip: ['componentProp', 'componentsProp'], })); describe('initial state', () => { diff --git a/packages/mui-material-next/src/FormControl/FormControl.js b/packages/mui-material-next/src/FormControl/FormControl.tsx similarity index 88% rename from packages/mui-material-next/src/FormControl/FormControl.js rename to packages/mui-material-next/src/FormControl/FormControl.tsx index b7e291351e38fb..bc614529bcb9a1 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.js +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; import { unstable_composeClasses as composeClasses } from '@mui/base/composeClasses'; +import { OverridableComponent } from '@mui/types'; import { unstable_capitalize as capitalize, unstable_isMuiElement as isMuiElement, @@ -11,9 +12,10 @@ import useThemeProps from '../styles/useThemeProps'; import styled from '../styles/styled'; import { isFilled, isAdornedStart } from '../InputBase/utils'; import FormControlContext from './FormControlContext'; +import { FormControlTypeMap, FormControlOwnerState, FormControlProps } from './FormControl.types'; import { getFormControlUtilityClasses } from './formControlClasses'; -const useUtilityClasses = (ownerState) => { +const useUtilityClasses = (ownerState: FormControlOwnerState) => { const { classes, margin, fullWidth } = ownerState; const slots = { root: ['root', margin !== 'none' && `margin${capitalize(margin)}`, fullWidth && 'fullWidth'], @@ -27,12 +29,12 @@ const FormControlRoot = styled('div', { slot: 'Root', overridesResolver: ({ ownerState }, styles) => { return { - ...styles.root, - ...styles[`margin${capitalize(ownerState.margin)}`], + ...(styles.root as Record), + ...(styles[`margin${capitalize(ownerState.margin)}`] as Record), ...(ownerState.fullWidth && styles.fullWidth), }; }, -})(({ ownerState }) => ({ +})<{ ownerState: FormControlOwnerState }>(({ ownerState }) => ({ display: 'inline-flex', flexDirection: 'column', position: 'relative', @@ -79,13 +81,15 @@ const FormControlRoot = styled('div', { * ⚠️ Only one `InputBase` can be used within a FormControl because it creates visual inconsistencies. * For instance, only one input can be focused at the same time, the state shouldn't be shared. */ -const FormControl = React.forwardRef(function FormControl(inProps, ref) { +const FormControl = React.forwardRef(function FormControl< + RootComponentType extends React.ElementType = FormControlTypeMap['defaultComponent'], +>(inProps: FormControlProps, ref: React.ForwardedRef) { const props = useThemeProps({ props: inProps, name: 'MuiFormControl' }); const { children, className, color = 'primary', - component = 'div', + // component = 'div', disabled = false, error = false, focused: visuallyFocused, @@ -98,10 +102,11 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) { ...other } = props; - const ownerState = { + const ownerState: FormControlOwnerState = { ...props, + classes: props.classes ?? {}, color, - component, + // component, disabled, error, fullWidth, @@ -125,7 +130,10 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) { return; } - const input = isMuiElement(child, ['Select']) ? child.props.input : child; + const input = + React.isValidElement(child) && isMuiElement(child, ['Select']) + ? child.props.input + : child; if (input && isAdornedStart(input.props)) { initialAdornedStart = true; @@ -146,7 +154,10 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) { return; } - if (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) { + if ( + React.isValidElement(child) && + (isFilled(child.props, true) || isFilled(child.props.inputProps, true)) + ) { initialFilled = true; } }); @@ -162,7 +173,7 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) { const focused = visuallyFocused !== undefined && !disabled ? visuallyFocused : focusedState; - let registerEffect; + let registerEffect: undefined | (() => () => void); if (process.env.NODE_ENV !== 'production') { // eslint-disable-next-line react-hooks/rules-of-hooks const registeredInput = React.useRef(false); @@ -229,7 +240,6 @@ const FormControl = React.forwardRef(function FormControl(inProps, ref) { return ( ); -}); +}) as OverridableComponent; FormControl.propTypes /* remove-proptypes */ = { // ----------------------------- Warning -------------------------------- diff --git a/packages/mui-material-next/src/FormControl/FormControl.types.ts b/packages/mui-material-next/src/FormControl/FormControl.types.ts new file mode 100644 index 00000000000000..38e85dc2c1adad --- /dev/null +++ b/packages/mui-material-next/src/FormControl/FormControl.types.ts @@ -0,0 +1,90 @@ +import * as React from 'react'; +import { SxProps } from '@mui/system'; +import { FormControlOwnProps as BaseFormControlOwnProps } from '@mui/base/FormControl'; +import { OverridableStringUnion, OverrideProps } from '@mui/types'; +import { Theme } from '../styles'; +import { FormControlClasses } from './formControlClasses'; + +export interface FormControlPropsSizeOverrides {} +export interface FormControlPropsColorOverrides {} + +export interface FormControlOwnProps extends BaseFormControlOwnProps { + /** + * The content of the component. + */ + children?: React.ReactNode; + /** + * Override or extend the styles applied to the component. + */ + classes?: Partial; + /** + * The color of the component. + * It supports both default and custom theme colors, which can be added as shown in the + * [palette customization guide](https://mui.com/material-ui/customization/palette/#adding-new-colors). + * @default 'primary' + */ + color?: OverridableStringUnion< + 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning', + FormControlPropsColorOverrides + >; + /** + * If `true`, the component will take up the full width of its container. + * @default false + */ + fullWidth?: boolean; + /** + * If `true`, the component is displayed in focused state. + */ + focused?: boolean; + /** + * If `true`, the label is hidden. + * This is used to increase density for a `FilledInput`. + * Be sure to add `aria-label` to the `input` element. + * @default false + */ + hiddenLabel?: boolean; + /** + * If `dense` or `normal`, will adjust vertical spacing of this and contained components. + * @default 'none' + */ + margin?: 'dense' | 'normal' | 'none'; + /** + * The size of the component. + * @default 'medium' + */ + size?: OverridableStringUnion<'small' | 'medium', FormControlPropsSizeOverrides>; + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx?: SxProps; + /** + * The variant to use. + * @default 'outlined' + */ + variant?: 'outlined' | 'filled'; +} + +export interface FormControlTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: FormControlOwnProps & AdditionalProps; + defaultComponent: RootComponentType; +} + +export type FormControlProps< + RootComponentType extends React.ElementType = FormControlTypeMap['defaultComponent'], + AdditionalProps = {}, +> = OverrideProps, RootComponentType>; + +type MaterialYouOwnerStateKeys = + | 'classes' + | 'color' + | 'margin' + | 'size' + | 'fullWidth' + | 'hiddenLabel' + | 'variant'; + +export type FormControlOwnerState = Required> & + FormControlProps; diff --git a/packages/mui-material-next/src/FormControl/FormControlContext.ts b/packages/mui-material-next/src/FormControl/FormControlContext.ts index 606057104b1457..9a29262072a0d6 100644 --- a/packages/mui-material-next/src/FormControl/FormControlContext.ts +++ b/packages/mui-material-next/src/FormControl/FormControlContext.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import type { FormControlProps } from './FormControl'; +import { FormControlProps } from './FormControl.types'; type ContextFromPropsKey = | 'color' @@ -8,26 +8,26 @@ type ContextFromPropsKey = | 'fullWidth' | 'hiddenLabel' | 'margin' - | 'onBlur' - | 'onFocus' | 'required' | 'size' | 'variant'; -export interface FormControlState extends Pick { +export interface FormControlContextValue extends Pick { adornedStart: boolean; filled: boolean; focused: boolean; + onBlur: () => void; + onFocus: () => void; onEmpty: () => void; onFilled: () => void; - registerEffect: () => void; + registerEffect: undefined | (() => () => void); setAdornedStart: React.Dispatch>; } /** - * @ignore - internal component. + * @internal */ -const FormControlContext = React.createContext(undefined); +const FormControlContext = React.createContext(undefined); if (process.env.NODE_ENV !== 'production') { FormControlContext.displayName = 'FormControlContext'; diff --git a/packages/mui-material-next/src/FormControl/index.d.ts b/packages/mui-material-next/src/FormControl/index.d.ts deleted file mode 100644 index 7eaec9a8312087..00000000000000 --- a/packages/mui-material-next/src/FormControl/index.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export { default } from './FormControl'; -export * from './FormControl'; - -export { default as useFormControl } from './useFormControl'; - -export { FormControlState } from './FormControlContext'; - -export { default as formControlClasses } from './formControlClasses'; -export * from './formControlClasses'; diff --git a/packages/mui-material-next/src/FormControl/index.js b/packages/mui-material-next/src/FormControl/index.ts similarity index 100% rename from packages/mui-material-next/src/FormControl/index.js rename to packages/mui-material-next/src/FormControl/index.ts diff --git a/packages/mui-material-next/src/FormControl/useFormControl.ts b/packages/mui-material-next/src/FormControl/useFormControl.ts index cf24c6cad1ffe8..8cf6ac69fbce7f 100644 --- a/packages/mui-material-next/src/FormControl/useFormControl.ts +++ b/packages/mui-material-next/src/FormControl/useFormControl.ts @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; -import FormControlContext, { FormControlState } from './FormControlContext'; +import FormControlContext, { FormControlContextValue } from './FormControlContext'; -export default function useFormControl(): FormControlState | undefined { +export default function useFormControl(): FormControlContextValue | undefined { return React.useContext(FormControlContext); } From ae76f2907559db17bc3c8aac8a4627bb7cd338ce Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Sat, 16 Sep 2023 01:14:15 +0800 Subject: [PATCH 02/18] Implement slots --- .../src/FormControl/FormControl.test.js | 6 ++ .../src/FormControl/FormControl.tsx | 63 ++++++++++--------- .../src/FormControl/FormControl.types.ts | 7 ++- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index 8f54d9b98db7b6..5d44bc138ee1d3 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -28,6 +28,12 @@ describe('', () => { refInstanceof: window.HTMLDivElement, muiName: 'MuiFormControl', testVariantProps: { margin: 'dense' }, + slots: { + root: { + expectedClassName: classes.root, + testWithElement: 'fieldset', + }, + }, skip: ['componentProp', 'componentsProp'], })); diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index bc614529bcb9a1..2ddf4378452e0c 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; import { unstable_composeClasses as composeClasses } from '@mui/base/composeClasses'; +import { useSlotProps } from '@mui/base'; import { OverridableComponent } from '@mui/types'; import { unstable_capitalize as capitalize, @@ -83,13 +83,12 @@ const FormControlRoot = styled('div', { */ const FormControl = React.forwardRef(function FormControl< RootComponentType extends React.ElementType = FormControlTypeMap['defaultComponent'], ->(inProps: FormControlProps, ref: React.ForwardedRef) { +>(inProps: FormControlProps, forwardedRef: React.ForwardedRef) { const props = useThemeProps({ props: inProps, name: 'MuiFormControl' }); const { children, className, color = 'primary', - // component = 'div', disabled = false, error = false, focused: visuallyFocused, @@ -98,27 +97,12 @@ const FormControl = React.forwardRef(function FormControl< margin = 'none', required = false, size = 'medium', + slotProps = {}, + slots = {}, variant = 'outlined', ...other } = props; - const ownerState: FormControlOwnerState = { - ...props, - classes: props.classes ?? {}, - color, - // component, - disabled, - error, - fullWidth, - hiddenLabel, - margin, - required, - size, - variant, - }; - - const classes = useUtilityClasses(ownerState); - const [adornedStart, setAdornedStart] = React.useState(() => { // We need to iterate through the children and find the Input in order // to fully support server-side rendering. @@ -194,6 +178,24 @@ const FormControl = React.forwardRef(function FormControl< }; } + const ownerState = { + ...props, + classes: props.classes ?? {}, + color, + disabled, + error, + filled, + focused, + fullWidth, + hiddenLabel, + margin, + required, + size, + variant, + }; + + const classes = useUtilityClasses(ownerState); + const childContext = React.useMemo(() => { return { adornedStart, @@ -237,16 +239,21 @@ const FormControl = React.forwardRef(function FormControl< variant, ]); + const Root = slots.root || FormControlRoot; + const rootProps = useSlotProps({ + elementType: Root, + externalSlotProps: slotProps.root, + externalForwardedProps: other, + additionalProps: { + ref: forwardedRef, + }, + ownerState, + className: [classes.root, className], + }); + return ( - - {children} - + {children} ); }) as OverridableComponent; diff --git a/packages/mui-material-next/src/FormControl/FormControl.types.ts b/packages/mui-material-next/src/FormControl/FormControl.types.ts index 38e85dc2c1adad..09bb1aa0cc97eb 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.types.ts +++ b/packages/mui-material-next/src/FormControl/FormControl.types.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { SxProps } from '@mui/system'; import { FormControlOwnProps as BaseFormControlOwnProps } from '@mui/base/FormControl'; -import { OverridableStringUnion, OverrideProps } from '@mui/types'; +import { OverridableStringUnion, OverrideProps, Simplify } from '@mui/types'; import { Theme } from '../styles'; import { FormControlClasses } from './formControlClasses'; @@ -86,5 +86,6 @@ type MaterialYouOwnerStateKeys = | 'hiddenLabel' | 'variant'; -export type FormControlOwnerState = Required> & - FormControlProps; +export type FormControlOwnerState = Simplify< + Required> & FormControlProps +>; From cd3e5f2b970acb05d52dd0283721e8222d059c64 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 18 Sep 2023 13:10:28 +0800 Subject: [PATCH 03/18] Integrate with InputBase --- .../src/FormControl/FormControlContext.ts | 4 +- .../src/InputBase/InputBase.tsx | 52 ++++++++++--------- .../src/InputBase/InputBase.types.ts | 4 +- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControlContext.ts b/packages/mui-material-next/src/FormControl/FormControlContext.ts index 9a29262072a0d6..16cb4e9c83ca55 100644 --- a/packages/mui-material-next/src/FormControl/FormControlContext.ts +++ b/packages/mui-material-next/src/FormControl/FormControlContext.ts @@ -16,8 +16,8 @@ export interface FormControlContextValue extends Pick void; - onFocus: () => void; + onBlur: (event?: React.FocusEvent) => void; + onFocus: (event: React.FocusEvent) => void; onEmpty: () => void; onFilled: () => void; registerEffect: undefined | (() => () => void); diff --git a/packages/mui-material-next/src/InputBase/InputBase.tsx b/packages/mui-material-next/src/InputBase/InputBase.tsx index 3b162a71ebe9f6..cc70b7217c7d89 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.tsx +++ b/packages/mui-material-next/src/InputBase/InputBase.tsx @@ -18,8 +18,8 @@ import { } from '@mui/utils'; import { OverridableComponent } from '@mui/types'; // import formControlState from '@mui/material/FormControl/formControlState'; -import FormControlContext from '@mui/material/FormControl/FormControlContext'; -import useFormControl from '@mui/material/FormControl/useFormControl'; +import FormControlContext from '@mui/material-next/FormControl/FormControlContext'; +import useFormControl from '@mui/material-next/FormControl/useFormControl'; import styled from '../styles/styled'; import useThemeProps from '../styles/useThemeProps'; import { isFilled } from './utils'; @@ -262,7 +262,7 @@ const InputBase = React.forwardRef(function InputBase< disabled: disabledProp, disableInjectingGlobalStyles, endAdornment, - error, + error: errorProp, fullWidth = false, id, inputRef: inputRefProp, @@ -280,7 +280,7 @@ const InputBase = React.forwardRef(function InputBase< placeholder, readOnly, renderSuffix, - required, + required: requiredProp, rows, size: sizeProp, slotProps = {}, @@ -293,19 +293,20 @@ const InputBase = React.forwardRef(function InputBase< const { current: isControlled } = React.useRef(value != null); - // TODO: integrate material-next/FormControl const muiFormControl = useFormControl(); - /* if (process.env.NODE_ENV !== 'production') { // eslint-disable-next-line react-hooks/rules-of-hooks React.useEffect(() => { - if (muiFormControl) { + if (muiFormControl && muiFormControl.registerEffect) { return muiFormControl.registerEffect(); } - return undefined; + return undefined; }, [muiFormControl]); } + + // TODO: what is this actually doing ?! + /* const fcs = formControlState({ props, muiFormControl, @@ -342,9 +343,9 @@ const InputBase = React.forwardRef(function InputBase< onFocus(event); } - // if (muiFormControl && muiFormControl.onFocus) { - // muiFormControl.onFocus(event); - // } + if (muiFormControl && muiFormControl.onFocus) { + muiFormControl.onFocus(event); + } }; const handleBlur = (event?: React.FocusEvent) => { @@ -352,9 +353,9 @@ const InputBase = React.forwardRef(function InputBase< onBlur(event); } - // if (muiFormControl && muiFormControl.onBlur) { - // muiFormControl.onBlur(event); - // } + if (muiFormControl && muiFormControl.onBlur) { + muiFormControl.onBlur(event); + } }; const handleChange = ( @@ -375,7 +376,7 @@ const InputBase = React.forwardRef(function InputBase< }; const handleClick = (event: React.PointerEvent) => { - if (onClick /* && !fcs.disabled */) { + if (onClick) { onClick(event); } }; @@ -386,19 +387,20 @@ const InputBase = React.forwardRef(function InputBase< } }, [muiFormControl, startAdornment]); + const required = muiFormControl?.required ?? requiredProp; + const { getRootProps, getInputProps, focused: focusedState, - // TODO: what if this `formControlContext` is completely ignored and the component uses a completely separate one similar to Joy - // formControlContext, error: errorState, disabled: disabledState, inputRef, + // ignore Base UI's formControlContext } = useInput({ - disabled: disabledProp, + disabled: muiFormControl?.disabled ?? disabledProp, defaultValue, - error, + error: muiFormControl?.error ?? errorProp, onBlur: handleBlur, onClick: handleClick, onChange: handleChange, @@ -408,19 +410,19 @@ const InputBase = React.forwardRef(function InputBase< inputRef: inputRefProp, }); - // TODO: integrate ownerState properties with material-next/FormControl: color, disabled, error, focused, hiddenLabel, size const ownerState = { ...props, - color: colorProp || 'primary', + color: muiFormControl?.color ?? colorProp ?? 'primary', disabled: disabledState, endAdornment, error: errorState, - focused: focusedState, + focused: muiFormControl?.focused ?? focusedState, formControl: muiFormControl, fullWidth, - hiddenLabel: false, // TODO: material-next/FormControl integration + hiddenLabel: muiFormControl?.hiddenLabel ?? false, multiline, - size: sizeProp, + required, + size: muiFormControl?.size ?? sizeProp, startAdornment, type, }; @@ -518,7 +520,7 @@ const InputBase = React.forwardRef(function InputBase< {endAdornment} {renderSuffix ? renderSuffix({ - // ...fcs, + ...muiFormControl, startAdornment, }) : null} diff --git a/packages/mui-material-next/src/InputBase/InputBase.types.ts b/packages/mui-material-next/src/InputBase/InputBase.types.ts index 50880175c1e740..65813b08fa8f34 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.types.ts +++ b/packages/mui-material-next/src/InputBase/InputBase.types.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { SlotComponentProps } from '@mui/base'; -import { FormControlState } from '@mui/material/FormControl'; +import { FormControlContextValue } from '@mui/material-next/FormControl/FormControlContext'; import { UseInputRootSlotProps } from '@mui/base/useInput'; import { SxProps } from '@mui/system'; import { OverridableStringUnion, OverrideProps, Simplify } from '@mui/types'; @@ -265,7 +265,7 @@ export type InputBaseProps< export type InputBaseOwnerState = Simplify< InputBaseOwnProps & { - formControl: FormControlState | undefined; + formControl: FormControlContextValue | undefined; hiddenLabel?: boolean; focused: boolean; type: React.InputHTMLAttributes['type'] | undefined; From 9bec34cb032c76f2250d186bfb4347a0e0425a16 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 18 Sep 2023 14:04:34 +0800 Subject: [PATCH 04/18] Update InputBase tests --- .../src/InputBase/InputBase.test.js | 40 ++++++++++++------- .../src/InputBase/InputBase.tsx | 24 ++++------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/mui-material-next/src/InputBase/InputBase.test.js b/packages/mui-material-next/src/InputBase/InputBase.test.js index 3774b529c76751..598aa385f3ed6f 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.test.js +++ b/packages/mui-material-next/src/InputBase/InputBase.test.js @@ -1,4 +1,3 @@ -/* eslint-disable mocha/no-skipped-tests */ import * as React from 'react'; import PropTypes from 'prop-types'; import { expect } from 'chai'; @@ -11,7 +10,7 @@ import { screen, } from '@mui-internal/test-utils'; import { ThemeProvider } from '@emotion/react'; -import FormControl, { useFormControl } from '@mui/material/FormControl'; +import FormControl, { useFormControl } from '@mui/material-next/FormControl'; import InputAdornment from '@mui/material/InputAdornment'; import TextField from '@mui/material/TextField'; import { createTheme } from '@mui/material/styles'; @@ -112,7 +111,7 @@ describe('', () => { setProps({ disabled: true }); expect(handleBlur.callCount).to.equal(1); - // // check if focus not initiated again + // check if focus not initiated again expect(handleFocus.callCount).to.equal(1); }); }); @@ -144,8 +143,8 @@ describe('', () => { ); const input = getByRole('textbox'); + // TODO: refactor this test with @testing-library/user-event // simulating user input: gain focus, key input (keydown, (input), change, keyup), blur - act(() => { input.focus(); }); @@ -222,10 +221,13 @@ describe('', () => { }); describe('prop: slots', () => { - // TODO: delete, covered by describeConformance - xit('should accept any html component', () => { + // TODO: figure out if this is covered by describeConformance + it('should accept any html component', () => { const { getByTestId } = render( - , + , ); expect(getByTestId('input-component')).to.have.property('nodeName', 'SPAN'); }); @@ -244,8 +246,7 @@ describe('', () => { expect(typeof injectedProps.onFocus).to.equal('function'); }); - // TODO: requires material-next/FormControl - describe.skip('target mock implementations', () => { + describe('target mock implementations', () => { it('can just mock the value', () => { const MockedValue = React.forwardRef(function MockedValue(props, ref) { const { onChange } = props; @@ -266,7 +267,11 @@ describe('', () => { const { getByRole, getByTestId } = render( - + , ); expect(getByTestId('filled')).to.have.text('filled: false'); @@ -277,7 +282,8 @@ describe('', () => { it("can expose the input component's ref through the inputComponent prop", () => { const FullTarget = React.forwardRef(function FullTarget(props, ref) { - return ; + const { ownerState, ...otherProps } = props; + return ; }); function FilledState(props) { @@ -288,7 +294,11 @@ describe('', () => { const { getByRole, getByTestId } = render( - + , ); expect(getByTestId('filled')).to.have.text('filled: false'); @@ -299,9 +309,7 @@ describe('', () => { }); }); - // TODO: unskip and refactor when integrating material-next/FormControl - - describe.skip('with FormControl', () => { + describe('with FormControl', () => { it('should have the formControl class', () => { const { getByTestId } = render( @@ -668,6 +676,8 @@ describe('', () => { }); describe('prop: focused', () => { + // TODO: use material-next/TextField + // eslint-disable-next-line mocha/no-skipped-tests it.skip('should render correct border color with `ThemeProvider` imported from `@emotion/react`', function test() { if (/jsdom/.test(window.navigator.userAgent)) { this.skip(); diff --git a/packages/mui-material-next/src/InputBase/InputBase.tsx b/packages/mui-material-next/src/InputBase/InputBase.tsx index cc70b7217c7d89..920a8904a5e905 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.tsx +++ b/packages/mui-material-next/src/InputBase/InputBase.tsx @@ -17,7 +17,6 @@ import { unstable_useEnhancedEffect as useEnhancedEffect, } from '@mui/utils'; import { OverridableComponent } from '@mui/types'; -// import formControlState from '@mui/material/FormControl/formControlState'; import FormControlContext from '@mui/material-next/FormControl/FormControlContext'; import useFormControl from '@mui/material-next/FormControl/useFormControl'; import styled from '../styles/styled'; @@ -305,20 +304,10 @@ const InputBase = React.forwardRef(function InputBase< }, [muiFormControl]); } - // TODO: what is this actually doing ?! - /* - const fcs = formControlState({ - props, - muiFormControl, - states: ['color', 'disabled', 'error', 'hiddenLabel', 'size', 'required', 'filled'], - }); - fcs.focused = muiFormControl ? muiFormControl.focused : focused; - */ - const onFilled = muiFormControl && muiFormControl.onFilled; const onEmpty = muiFormControl && muiFormControl.onEmpty; - // TODO: needs material-next/FormControl & material-next/Outlined|FilledInput + // TODO: needs material-next/Outlined|FilledInput const checkDirty = React.useCallback( (obj: any) => { if (isFilled(obj)) { @@ -387,7 +376,7 @@ const InputBase = React.forwardRef(function InputBase< } }, [muiFormControl, startAdornment]); - const required = muiFormControl?.required ?? requiredProp; + const required = requiredProp ?? muiFormControl?.required; const { getRootProps, @@ -398,9 +387,9 @@ const InputBase = React.forwardRef(function InputBase< inputRef, // ignore Base UI's formControlContext } = useInput({ - disabled: muiFormControl?.disabled ?? disabledProp, + disabled: disabledProp ?? muiFormControl?.disabled, defaultValue, - error: muiFormControl?.error ?? errorProp, + error: errorProp ?? muiFormControl?.error, onBlur: handleBlur, onClick: handleClick, onChange: handleChange, @@ -412,7 +401,7 @@ const InputBase = React.forwardRef(function InputBase< const ownerState = { ...props, - color: muiFormControl?.color ?? colorProp ?? 'primary', + color: colorProp ?? muiFormControl?.color ?? 'primary', disabled: disabledState, endAdornment, error: errorState, @@ -422,7 +411,7 @@ const InputBase = React.forwardRef(function InputBase< hiddenLabel: muiFormControl?.hiddenLabel ?? false, multiline, required, - size: muiFormControl?.size ?? sizeProp, + size: sizeProp ?? muiFormControl?.size, startAdornment, type, }; @@ -520,6 +509,7 @@ const InputBase = React.forwardRef(function InputBase< {endAdornment} {renderSuffix ? renderSuffix({ + // TODO: make sure ['color', 'disabled', 'error', 'hiddenLabel', 'size', 'required', 'filled'] are all passed to renderSuffix ...muiFormControl, startAdornment, }) From f7e7e525bf0cd8d905708b0f4a135735f27b99e1 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 18 Sep 2023 15:35:23 +0800 Subject: [PATCH 05/18] Update FormControl tests --- .../src/FormControl/FormControl.test.js | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index 5d44bc138ee1d3..2eabbe415fe2e4 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -1,4 +1,3 @@ -/* eslint-disable mocha/no-skipped-tests */ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; @@ -90,8 +89,7 @@ describe('', () => { }); }); - // TODO: needs InputBase + FormControl integrated - describe.skip('prop: disabled', () => { + describe('prop: disabled', () => { it('will be unfocused if it gets disabled', () => { const readContext = spy(); const { container, setProps } = render( @@ -139,12 +137,14 @@ describe('', () => { }); }); - describe('input', () => { - // TODO: needs InputBase + FormControl integrated - it.skip('should be filled when a value is set', () => { + // TODO: needs Outlined|FilledInput + FormControl integrated + // eslint-disable-next-line mocha/no-skipped-tests + describe.skip('input', () => { + it('should be filled when a value is set', () => { const readContext = spy(); render( + {/* TODO: use material-next/OutlinedInput */} , @@ -152,11 +152,11 @@ describe('', () => { expect(readContext.args[0][0]).to.have.property('filled', true); }); - // TODO: needs InputBase + FormControl integrated - it.skip('should be filled when a value is set through inputProps', () => { + it('should be filled when a value is set through inputProps', () => { const readContext = spy(); render( + {/* TODO: use material-next/OutlinedInput */} , @@ -164,11 +164,11 @@ describe('', () => { expect(readContext.args[0][0]).to.have.property('filled', true); }); - // TODO: needs InputBase + FormControl integrated - it.skip('should be filled when a defaultValue is set', () => { + it('should be filled when a defaultValue is set', () => { const readContext = spy(); render( + {/* TODO: use material-next/OutlinedInput */} , @@ -180,6 +180,7 @@ describe('', () => { const readContext = spy(); render( + {/* TODO: use material-next/OutlinedInput */} } /> , @@ -187,11 +188,11 @@ describe('', () => { expect(readContext.args[0][0]).to.have.property('adornedStart', false); }); - // TODO: needs InputBase + FormControl integrated - it.skip('should be adornedStart with a startAdornment', () => { + it('should be adornedStart with a startAdornment', () => { const readContext = spy(); render( + {/* TODO: use material-next/OutlinedInput */} } /> , @@ -200,7 +201,8 @@ describe('', () => { }); }); - // TODO: unskip and refactor when integrating material-next/Select + // TODO: needs material-next/Select + FormControl integrated + // eslint-disable-next-line mocha/no-skipped-tests describe.skip('select', () => { it('should not be adorned without a startAdornment', () => { const readContext = spy(); From fed7cfbbb8726c7626f88e4548a70117563c532a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 18 Sep 2023 15:41:19 +0800 Subject: [PATCH 06/18] Update proptypes --- .../src/FormControl/FormControl.tsx | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index 2ddf4378452e0c..8ff9a8ed83f54d 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -261,7 +261,7 @@ const FormControl = React.forwardRef(function FormControl< FormControl.propTypes /* remove-proptypes */ = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the d.ts file and run "yarn proptypes" | + // | To update them edit TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- /** * The content of the component. @@ -272,7 +272,7 @@ FormControl.propTypes /* remove-proptypes */ = { */ classes: PropTypes.object, /** - * @ignore + * Class name applied to the root element. */ className: PropTypes.string, /** @@ -285,11 +285,6 @@ FormControl.propTypes /* remove-proptypes */ = { PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string, ]), - /** - * The component used for the root node. - * Either a string to use a HTML element or a component. - */ - component: PropTypes.elementType, /** * If `true`, the label, input and helper text should be displayed in a disabled state. * @default false @@ -334,6 +329,21 @@ FormControl.propTypes /* remove-proptypes */ = { PropTypes.oneOf(['medium', 'small']), PropTypes.string, ]), + /** + * The props used for each slot inside the FormControl. + * @default {} + */ + slotProps: PropTypes.shape({ + root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + }), + /** + * The components used for each slot inside the FormControl. + * Either a string to use a HTML element or a component. + * @default {} + */ + slots: PropTypes.shape({ + root: PropTypes.elementType, + }), /** * The system prop that allows defining system overrides as well as additional CSS styles. */ @@ -346,7 +356,7 @@ FormControl.propTypes /* remove-proptypes */ = { * The variant to use. * @default 'outlined' */ - variant: PropTypes.oneOf(['filled', 'outlined', 'standard']), -}; + variant: PropTypes.oneOf(['filled', 'outlined']), +} as any; export default FormControl; From 92ac592c49299183b041a9b05b52216366fb8fe4 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 18 Sep 2023 16:19:23 +0800 Subject: [PATCH 07/18] Add back registering input tests --- .../src/FormControl/FormControl.test.js | 61 ++++++++++++++++++- .../src/InputBase/InputBase.tsx | 2 +- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index 2eabbe415fe2e4..a90045f7090cc5 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; -import { describeConformance, act, createRenderer } from '@mui-internal/test-utils'; +import { describeConformance, act, createRenderer, fireEvent } from '@mui-internal/test-utils'; import FormControl, { formControlClasses as classes } from '@mui/material-next/FormControl'; // TODO: replace with material-next/OutlinedInput import InputBase from '@mui/material-next/InputBase'; @@ -137,6 +137,65 @@ describe('', () => { }); }); + describe('registering input', () => { + it("should warn if more than one input is rendered regardless how it's nested", () => { + expect(() => { + render( + + +
+ {/* should work regardless how it's nested */} + +
+
, + ); + }).toErrorDev([ + 'MUI: There are multiple `InputBase` components inside a FormControl.\nThis creates visual inconsistencies, only use one `InputBase`.', + // React 18 Strict Effects run mount effects twice + React.version.startsWith('18') && + 'MUI: There are multiple `InputBase` components inside a FormControl.\nThis creates visual inconsistencies, only use one `InputBase`.', + ]); + }); + + it('should not warn if only one input is rendered', () => { + expect(() => { + render( + + + , + ); + }).not.toErrorDev(); + }); + + it('should not warn when toggling between inputs', () => { + // this will ensure that deregistering was called during unmount + function ToggleFormInputs() { + const [flag, setFlag] = React.useState(true); + + return ( + + {flag ? ( + + ) : ( + // TODO: use material-next/Select + + )} + + + ); + } + + const { getByText } = render(); + expect(() => { + fireEvent.click(getByText('toggle')); + }).not.toErrorDev(); + }); + }); + // TODO: needs Outlined|FilledInput + FormControl integrated // eslint-disable-next-line mocha/no-skipped-tests describe.skip('input', () => { diff --git a/packages/mui-material-next/src/InputBase/InputBase.tsx b/packages/mui-material-next/src/InputBase/InputBase.tsx index 920a8904a5e905..6fb80f25ea2065 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.tsx +++ b/packages/mui-material-next/src/InputBase/InputBase.tsx @@ -509,7 +509,7 @@ const InputBase = React.forwardRef(function InputBase< {endAdornment} {renderSuffix ? renderSuffix({ - // TODO: make sure ['color', 'disabled', 'error', 'hiddenLabel', 'size', 'required', 'filled'] are all passed to renderSuffix + // TODO: make sure ['color', 'disabled', 'error', 'hiddenLabel', 'size', 'required', 'filled'] are all passed to renderSuffix when integrating OutlinedInput ...muiFormControl, startAdornment, }) From 23a97971c5960e1f2d0cefdac058c011d20f6669 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Mon, 18 Sep 2023 16:44:45 +0800 Subject: [PATCH 08/18] Update comments --- .../src/FormControl/FormControl.test.js | 20 +++++++++---------- .../src/FormControl/formControlState.js | 2 ++ .../src/InputBase/InputBase.test.js | 8 ++++---- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index a90045f7090cc5..63e0d47296f395 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -3,9 +3,9 @@ import { expect } from 'chai'; import { spy } from 'sinon'; import { describeConformance, act, createRenderer, fireEvent } from '@mui-internal/test-utils'; import FormControl, { formControlClasses as classes } from '@mui/material-next/FormControl'; -// TODO: replace with material-next/OutlinedInput +// TODO v6: replace with material-next/FilledInput import InputBase from '@mui/material-next/InputBase'; -// TODO: replace with material-next/Select +// TODO v6: replace with material-next/Select import Select from '@mui/material/Select'; import useFormControl from './useFormControl'; @@ -177,7 +177,7 @@ describe('', () => { {flag ? ( ) : ( - // TODO: use material-next/Select + // TODO v6: use material-next/Select @@ -196,14 +196,14 @@ describe('', () => { }); }); - // TODO: needs Outlined|FilledInput + FormControl integrated + // TODO v6: needs FilledInput + FormControl integrated // eslint-disable-next-line mocha/no-skipped-tests describe.skip('input', () => { it('should be filled when a value is set', () => { const readContext = spy(); render( - {/* TODO: use material-next/OutlinedInput */} + {/* TODO v6: use material-next/FilledInput */} , @@ -215,7 +215,7 @@ describe('', () => { const readContext = spy(); render( - {/* TODO: use material-next/OutlinedInput */} + {/* TODO v6: use material-next/FilledInput */} , @@ -227,7 +227,7 @@ describe('', () => { const readContext = spy(); render( - {/* TODO: use material-next/OutlinedInput */} + {/* TODO v6: use material-next/FilledInput */} , @@ -239,7 +239,7 @@ describe('', () => { const readContext = spy(); render( - {/* TODO: use material-next/OutlinedInput */} + {/* TODO v6: use material-next/FilledInput */} } /> , @@ -251,7 +251,7 @@ describe('', () => { const readContext = spy(); render( - {/* TODO: use material-next/OutlinedInput */} + {/* TODO v6: use material-next/FilledInput */} } /> , @@ -260,7 +260,7 @@ describe('', () => { }); }); - // TODO: needs material-next/Select + FormControl integrated + // TODO v6: needs material-next/Select + FormControl integrated // eslint-disable-next-line mocha/no-skipped-tests describe.skip('select', () => { it('should not be adorned without a startAdornment', () => { diff --git a/packages/mui-material-next/src/FormControl/formControlState.js b/packages/mui-material-next/src/FormControl/formControlState.js index eb46904ff6cc0a..86c999f26e24c6 100644 --- a/packages/mui-material-next/src/FormControl/formControlState.js +++ b/packages/mui-material-next/src/FormControl/formControlState.js @@ -1,4 +1,6 @@ +// TODO v6: decide whether to update/refactor this, keep as-is, or drop it export default function formControlState({ props, states, muiFormControl }) { + // for every prop in `states` that is undefined, set it with the value from formControlContext return states.reduce((acc, state) => { acc[state] = props[state]; diff --git a/packages/mui-material-next/src/InputBase/InputBase.test.js b/packages/mui-material-next/src/InputBase/InputBase.test.js index 598aa385f3ed6f..a1c6f3f170f783 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.test.js +++ b/packages/mui-material-next/src/InputBase/InputBase.test.js @@ -143,7 +143,7 @@ describe('', () => { ); const input = getByRole('textbox'); - // TODO: refactor this test with @testing-library/user-event + // TODO v6: refactor this test with @testing-library/user-event // simulating user input: gain focus, key input (keydown, (input), change, keyup), blur act(() => { input.focus(); @@ -221,7 +221,7 @@ describe('', () => { }); describe('prop: slots', () => { - // TODO: figure out if this is covered by describeConformance + // TODO v6: figure out if this is covered by describeConformance it('should accept any html component', () => { const { getByTestId } = render( ', () => { expect(getByTestId('adornment')).not.to.equal(null); }); - // TODO: use material-next/Select + // TODO v6: use material-next/Select it('should allow a Select as an adornment', () => { render( ', () => { }); describe('prop: focused', () => { - // TODO: use material-next/TextField + // TODO v6: use material-next/TextField // eslint-disable-next-line mocha/no-skipped-tests it.skip('should render correct border color with `ThemeProvider` imported from `@emotion/react`', function test() { if (/jsdom/.test(window.navigator.userAgent)) { From 97ae8dbca3062ccb12f207bb6d7b1bcbb9634323 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 21 Sep 2023 13:43:19 +0800 Subject: [PATCH 09/18] Add back component prop --- .../mui-material-next/src/FormControl/FormControl.test.js | 5 +++-- packages/mui-material-next/src/FormControl/FormControl.tsx | 5 ++++- .../mui-material-next/src/FormControl/FormControl.types.ts | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index 63e0d47296f395..2e942b4f3913f2 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -26,14 +26,15 @@ describe('', () => { render, refInstanceof: window.HTMLDivElement, muiName: 'MuiFormControl', - testVariantProps: { margin: 'dense' }, slots: { root: { expectedClassName: classes.root, testWithElement: 'fieldset', }, }, - skip: ['componentProp', 'componentsProp'], + testComponentPropWith: 'fieldset', + testVariantProps: { margin: 'dense' }, + skip: ['componentsProp'], })); describe('initial state', () => { diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index 8ff9a8ed83f54d..2e9a81c6567ff8 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -88,7 +88,9 @@ const FormControl = React.forwardRef(function FormControl< const { children, className, + classes: classesProp, color = 'primary', + component: ComponentProp = 'div', disabled = false, error = false, focused: visuallyFocused, @@ -182,6 +184,7 @@ const FormControl = React.forwardRef(function FormControl< ...props, classes: props.classes ?? {}, color, + component: ComponentProp, disabled, error, filled, @@ -239,7 +242,7 @@ const FormControl = React.forwardRef(function FormControl< variant, ]); - const Root = slots.root || FormControlRoot; + const Root = slots.root ?? ComponentProp ?? FormControlRoot; const rootProps = useSlotProps({ elementType: Root, externalSlotProps: slotProps.root, diff --git a/packages/mui-material-next/src/FormControl/FormControl.types.ts b/packages/mui-material-next/src/FormControl/FormControl.types.ts index 09bb1aa0cc97eb..848054e6ad7577 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.types.ts +++ b/packages/mui-material-next/src/FormControl/FormControl.types.ts @@ -75,7 +75,9 @@ export interface FormControlTypeMap< export type FormControlProps< RootComponentType extends React.ElementType = FormControlTypeMap['defaultComponent'], AdditionalProps = {}, -> = OverrideProps, RootComponentType>; +> = OverrideProps, RootComponentType> & { + component?: React.ElementType; +}; type MaterialYouOwnerStateKeys = | 'classes' From 1f4d0573c5406e5e062fa3c8a1cf1691b18eca86 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 21 Sep 2023 15:25:44 +0800 Subject: [PATCH 10/18] Update proptypes --- packages/mui-material-next/src/FormControl/FormControl.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index 2e9a81c6567ff8..8af2890f074d37 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -288,6 +288,11 @@ FormControl.propTypes /* remove-proptypes */ = { PropTypes.oneOf(['primary', 'secondary', 'error', 'info', 'success', 'warning']), PropTypes.string, ]), + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, /** * If `true`, the label, input and helper text should be displayed in a disabled state. * @default false From 4a362917d74d0050b236cc6461c460f99f690f27 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 21 Sep 2023 16:40:42 +0800 Subject: [PATCH 11/18] Update comments --- .../src/InputBase/InputBase.test.js | 29 ++++++++++++------- .../src/InputBase/InputBase.tsx | 7 ++++- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/packages/mui-material-next/src/InputBase/InputBase.test.js b/packages/mui-material-next/src/InputBase/InputBase.test.js index a1c6f3f170f783..12cba3da33daae 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.test.js +++ b/packages/mui-material-next/src/InputBase/InputBase.test.js @@ -9,11 +9,12 @@ import { fireEvent, screen, } from '@mui-internal/test-utils'; -import { ThemeProvider } from '@emotion/react'; import FormControl, { useFormControl } from '@mui/material-next/FormControl'; +// TODO v6: replace with material-next/InputAdornment import InputAdornment from '@mui/material/InputAdornment'; +// TODO v6: replace with material-next/TextField import TextField from '@mui/material/TextField'; -import { createTheme } from '@mui/material/styles'; +// TODO v6: replace with material-next/Select import Select from '@mui/material/Select'; import InputBase, { inputBaseClasses as classes } from '@mui/material-next/InputBase'; import { CssVarsProvider, extendTheme } from '@mui/material-next/styles'; @@ -676,25 +677,31 @@ describe('', () => { }); describe('prop: focused', () => { - // TODO v6: use material-next/TextField + // TODO v6: requires material-next/OutlinedInput // eslint-disable-next-line mocha/no-skipped-tests - it.skip('should render correct border color with `ThemeProvider` imported from `@emotion/react`', function test() { + it.skip('should render correct border color with a customized primary color supplied to CssVarsProvider', function test() { if (/jsdom/.test(window.navigator.userAgent)) { this.skip(); } - const theme = createTheme({ - palette: { - mode: 'light', - primary: { - main: 'rgb(0, 191, 165)', + const theme = extendTheme({ + colorSchemes: { + light: { + palette: { + primary: { + main: 'rgb(0, 191, 165)', + }, + }, }, }, }); const { getByRole } = render( - + + {/* TODO v6: use material-next/TextField or OutlinedInput */} - , + , ); + + // this `fieldset` is the (internal) NotchedOutline component const fieldset = getByRole('textbox').nextSibling; expect(fieldset).toHaveComputedStyle({ borderTopColor: 'rgb(0, 191, 165)', diff --git a/packages/mui-material-next/src/InputBase/InputBase.tsx b/packages/mui-material-next/src/InputBase/InputBase.tsx index 6fb80f25ea2065..2a879e6aa82959 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.tsx +++ b/packages/mui-material-next/src/InputBase/InputBase.tsx @@ -509,7 +509,12 @@ const InputBase = React.forwardRef(function InputBase< {endAdornment} {renderSuffix ? renderSuffix({ - // TODO: make sure ['color', 'disabled', 'error', 'hiddenLabel', 'size', 'required', 'filled'] are all passed to renderSuffix when integrating OutlinedInput + // TODO: requires integrating with OutlinedInput + // ...formControlState({ + // props, + // muiFormControl, + // states: ['color', 'disabled', 'error', 'hiddenLabel', 'size', 'required', 'filled'] + // }), ...muiFormControl, startAdornment, }) From 50c04aa35a8fc097a0409bb1c2d1f717f28879c2 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 21 Sep 2023 17:13:03 +0800 Subject: [PATCH 12/18] Remove redundant test --- .../mui-material-next/src/InputBase/InputBase.test.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/mui-material-next/src/InputBase/InputBase.test.js b/packages/mui-material-next/src/InputBase/InputBase.test.js index 12cba3da33daae..781ea292c7cf82 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.test.js +++ b/packages/mui-material-next/src/InputBase/InputBase.test.js @@ -222,17 +222,6 @@ describe('', () => { }); describe('prop: slots', () => { - // TODO v6: figure out if this is covered by describeConformance - it('should accept any html component', () => { - const { getByTestId } = render( - , - ); - expect(getByTestId('input-component')).to.have.property('nodeName', 'SPAN'); - }); - it('should inject onBlur and onFocus', () => { let injectedProps; const MyInputBase = React.forwardRef(function MyInputBase(props, ref) { From 2d2905d4a120c450b2225c65553d771c33ccb3f1 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 21 Sep 2023 17:45:41 +0800 Subject: [PATCH 13/18] Fix component prop and tests --- .../mui-material-next/src/FormControl/FormControl.test.js | 4 ++++ packages/mui-material-next/src/FormControl/FormControl.tsx | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.test.js b/packages/mui-material-next/src/FormControl/FormControl.test.js index 2e942b4f3913f2..ed22b74a058d50 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.test.js +++ b/packages/mui-material-next/src/FormControl/FormControl.test.js @@ -5,6 +5,7 @@ import { describeConformance, act, createRenderer, fireEvent } from '@mui-intern import FormControl, { formControlClasses as classes } from '@mui/material-next/FormControl'; // TODO v6: replace with material-next/FilledInput import InputBase from '@mui/material-next/InputBase'; +import { CssVarsProvider, extendTheme } from '@mui/material-next/styles'; // TODO v6: replace with material-next/Select import Select from '@mui/material/Select'; import useFormControl from './useFormControl'; @@ -23,6 +24,8 @@ describe('', () => { describeConformance(, () => ({ classes, inheritComponent: 'div', + ThemeProvider: CssVarsProvider, + createTheme: extendTheme, render, refInstanceof: window.HTMLDivElement, muiName: 'MuiFormControl', @@ -32,6 +35,7 @@ describe('', () => { testWithElement: 'fieldset', }, }, + testRootOverrides: { slotName: 'root', slotClassName: classes.root }, testComponentPropWith: 'fieldset', testVariantProps: { margin: 'dense' }, skip: ['componentsProp'], diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index 8af2890f074d37..5f63f81147b7e1 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -90,7 +90,7 @@ const FormControl = React.forwardRef(function FormControl< className, classes: classesProp, color = 'primary', - component: ComponentProp = 'div', + component: componentProp, disabled = false, error = false, focused: visuallyFocused, @@ -184,7 +184,7 @@ const FormControl = React.forwardRef(function FormControl< ...props, classes: props.classes ?? {}, color, - component: ComponentProp, + component: componentProp, disabled, error, filled, @@ -242,13 +242,14 @@ const FormControl = React.forwardRef(function FormControl< variant, ]); - const Root = slots.root ?? ComponentProp ?? FormControlRoot; + const Root = slots.root ?? FormControlRoot; const rootProps = useSlotProps({ elementType: Root, externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { ref: forwardedRef, + as: componentProp, }, ownerState, className: [classes.root, className], From 6ce9f789572e34ff88831738cee5897defc5312a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 27 Sep 2023 15:24:11 +0800 Subject: [PATCH 14/18] Add back inputComponent prop --- packages/mui-material-next/migration.md | 11 ------ .../src/InputBase/InputBase.test.js | 26 +++++++------- .../src/InputBase/InputBase.tsx | 34 ++++++++++++++----- .../src/InputBase/InputBase.types.ts | 4 ++- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/packages/mui-material-next/migration.md b/packages/mui-material-next/migration.md index 8c0392f6968044..f027c255db15e3 100644 --- a/packages/mui-material-next/migration.md +++ b/packages/mui-material-next/migration.md @@ -134,17 +134,6 @@ This is to ensure that default is prevented when the `ButtonBase` root is not a ## InputBase -### Removed the `inputComponent` prop - -The `inputComponent` is deprecated in favor of `slots.input`: - -```diff - -``` - ### Removed `inputProps` `inputProps` are deprecated in favor of `slotProps.input`: diff --git a/packages/mui-material-next/src/InputBase/InputBase.test.js b/packages/mui-material-next/src/InputBase/InputBase.test.js index 781ea292c7cf82..1bf9a01ecf6e50 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.test.js +++ b/packages/mui-material-next/src/InputBase/InputBase.test.js @@ -221,7 +221,17 @@ describe('', () => { }); }); - describe('prop: slots', () => { + describe('prop: inputComponent', () => { + it('should accept any html component', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('input-component')).to.have.property('nodeName', 'SPAN'); + }); + it('should inject onBlur and onFocus', () => { let injectedProps; const MyInputBase = React.forwardRef(function MyInputBase(props, ref) { @@ -230,7 +240,7 @@ describe('', () => { return ; }); - render(); + render(); expect(typeof injectedProps.onBlur).to.equal('function'); expect(typeof injectedProps.onFocus).to.equal('function'); @@ -257,11 +267,7 @@ describe('', () => { const { getByRole, getByTestId } = render( - + , ); expect(getByTestId('filled')).to.have.text('filled: false'); @@ -284,11 +290,7 @@ describe('', () => { const { getByRole, getByTestId } = render( - + , ); expect(getByTestId('filled')).to.have.text('filled: false'); diff --git a/packages/mui-material-next/src/InputBase/InputBase.tsx b/packages/mui-material-next/src/InputBase/InputBase.tsx index 2a879e6aa82959..27ef24356e9025 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.tsx +++ b/packages/mui-material-next/src/InputBase/InputBase.tsx @@ -16,7 +16,7 @@ import { unstable_capitalize as capitalize, unstable_useEnhancedEffect as useEnhancedEffect, } from '@mui/utils'; -import { OverridableComponent } from '@mui/types'; +import { OverrideProps } from '@mui/types'; import FormControlContext from '@mui/material-next/FormControl/FormControlContext'; import useFormControl from '@mui/material-next/FormControl/useFormControl'; import styled from '../styles/styled'; @@ -264,6 +264,7 @@ const InputBase = React.forwardRef(function InputBase< error: errorProp, fullWidth = false, id, + inputComponent: inputComponentProp = 'input', inputRef: inputRefProp, margin, maxRows, @@ -433,6 +434,11 @@ const InputBase = React.forwardRef(function InputBase< type, }; + let InputComponent = inputComponentProp; + if (multiline && InputComponent === 'input') { + InputComponent = TextareaAutosize; + } + const Root = slots.root || InputBaseRoot; const rootProps: WithOptionalOwnerState = useSlotProps({ elementType: Root, @@ -446,15 +452,13 @@ const InputBase = React.forwardRef(function InputBase< className: [classes.root, className], }); - const InputComponent = multiline - ? slots.textarea ?? TextareaAutosize - : slots.input ?? InputBaseInput; + const Input = multiline ? slots.textarea ?? TextareaAutosize : slots.input ?? InputBaseInput; const inputProps: WithOptionalOwnerState = useSlotProps({ // TextareaAutosize doesn't support ownerState, we manually change the // elementType so ownerState is excluded from the return value (this doesn't // affect other returned props) - elementType: InputComponent === TextareaAutosize ? 'textarea' : InputComponent, + elementType: Input === TextareaAutosize ? 'textarea' : Input, getSlotProps: (otherHandlers: EventHandlers) => { return getInputProps({ ...propsToForwardToInputSlot, @@ -463,9 +467,10 @@ const InputBase = React.forwardRef(function InputBase< }, externalSlotProps: slotProps.input, additionalProps: { + as: InputComponent, rows: multiline ? rows : undefined, ...(multiline && - !isHostComponent(InputComponent) && { + !isHostComponent(Input) && { minRows: rows || minRows, maxRows: rows || maxRows, }), @@ -504,7 +509,7 @@ const InputBase = React.forwardRef(function InputBase< {startAdornment} - + {endAdornment} {renderSuffix @@ -522,7 +527,20 @@ const InputBase = React.forwardRef(function InputBase< ); -}) as OverridableComponent; +}) as InputBaseComponent; + +interface InputBaseComponent { + ( + props: { + /** + * The component used for the input node. + * Either a string to use a HTML element or a component. + */ + inputComponent?: C; + } & OverrideProps, + ): JSX.Element | null; + propTypes?: any; +} InputBase.propTypes /* remove-proptypes */ = { // ----------------------------- Warning -------------------------------- diff --git a/packages/mui-material-next/src/InputBase/InputBase.types.ts b/packages/mui-material-next/src/InputBase/InputBase.types.ts index 65813b08fa8f34..086ee8a62846f0 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.types.ts +++ b/packages/mui-material-next/src/InputBase/InputBase.types.ts @@ -261,7 +261,9 @@ export interface InputBaseTypeMap< export type InputBaseProps< RootComponentType extends React.ElementType = InputBaseTypeMap['defaultComponent'], AdditionalProps = {}, -> = OverrideProps, RootComponentType>; +> = OverrideProps, RootComponentType> & { + inputComponent?: React.ElementType; +}; export type InputBaseOwnerState = Simplify< InputBaseOwnProps & { From c91f973f9097ba710bbc92484dc632302196cca7 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 27 Sep 2023 15:59:09 +0800 Subject: [PATCH 15/18] Fix review comments --- packages/mui-base/src/FormControl/index.ts | 1 - packages/mui-material-next/migration.md | 11 +++++++++++ .../src/FormControl/FormControl.tsx | 17 ++++++++--------- .../src/FormControl/FormControl.types.ts | 4 ++-- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/packages/mui-base/src/FormControl/index.ts b/packages/mui-base/src/FormControl/index.ts index 1f758f2bf48b04..36bffd4e36536c 100644 --- a/packages/mui-base/src/FormControl/index.ts +++ b/packages/mui-base/src/FormControl/index.ts @@ -8,7 +8,6 @@ export type { FormControlRootSlotPropsOverrides, FormControlState, UseFormControlContextReturnValue, - // for material-next FormControlOwnProps, } from './FormControl.types'; diff --git a/packages/mui-material-next/migration.md b/packages/mui-material-next/migration.md index f027c255db15e3..dee387220c4c9a 100644 --- a/packages/mui-material-next/migration.md +++ b/packages/mui-material-next/migration.md @@ -132,6 +132,17 @@ If you need to prevent default on a `key-up` and/or `key-down` event, then besid This is to ensure that default is prevented when the `ButtonBase` root is not a native button, for example, when the root element used is a `span`. +## FormControl + +### Renamed `FormControlState` + +The `FormControlState` interface was renamed to `FormControlContextValue`: + +```diff +-import { FormControlState } from '@mui/material'; ++import { FormControlContextValue } from '@mui/material-next'; +``` + ## InputBase ### Removed `inputProps` diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index 5f63f81147b7e1..32eed461d78314 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -28,11 +28,11 @@ const FormControlRoot = styled('div', { name: 'MuiFormControl', slot: 'Root', overridesResolver: ({ ownerState }, styles) => { - return { - ...(styles.root as Record), - ...(styles[`margin${capitalize(ownerState.margin)}`] as Record), - ...(ownerState.fullWidth && styles.fullWidth), - }; + return [ + styles.root, + styles[`margin${capitalize(ownerState.margin)}`], + ownerState.fullWidth && styles.fullWidth, + ]; }, })<{ ownerState: FormControlOwnerState }>(({ ownerState }) => ({ display: 'inline-flex', @@ -87,8 +87,7 @@ const FormControl = React.forwardRef(function FormControl< const props = useThemeProps({ props: inProps, name: 'MuiFormControl' }); const { children, - className, - classes: classesProp, + classes: classesProp = {}, color = 'primary', component: componentProp, disabled = false, @@ -182,7 +181,7 @@ const FormControl = React.forwardRef(function FormControl< const ownerState = { ...props, - classes: props.classes ?? {}, + classes: classesProp, color, component: componentProp, disabled, @@ -252,7 +251,7 @@ const FormControl = React.forwardRef(function FormControl< as: componentProp, }, ownerState, - className: [classes.root, className], + className: classes.root, }); return ( diff --git a/packages/mui-material-next/src/FormControl/FormControl.types.ts b/packages/mui-material-next/src/FormControl/FormControl.types.ts index 848054e6ad7577..9c7b27a5df8b03 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.types.ts +++ b/packages/mui-material-next/src/FormControl/FormControl.types.ts @@ -79,7 +79,7 @@ export type FormControlProps< component?: React.ElementType; }; -type MaterialYouOwnerStateKeys = +type MaterialDesignOwnerStateKeys = | 'classes' | 'color' | 'margin' @@ -89,5 +89,5 @@ type MaterialYouOwnerStateKeys = | 'variant'; export type FormControlOwnerState = Simplify< - Required> & FormControlProps + Required> & FormControlProps >; From cfa76e2daaa2c3ca6ec3a7eaa0079c98266d9568 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 27 Sep 2023 21:23:07 +0800 Subject: [PATCH 16/18] Update migration.md --- packages/mui-material-next/migration.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/mui-material-next/migration.md b/packages/mui-material-next/migration.md index dee387220c4c9a..7ede7be08fc344 100644 --- a/packages/mui-material-next/migration.md +++ b/packages/mui-material-next/migration.md @@ -143,6 +143,10 @@ The `FormControlState` interface was renamed to `FormControlContextValue`: +import { FormControlContextValue } from '@mui/material-next'; ``` +### Removed the `standard` variant + +The standard variant is no longer supported in Material You, use the `filled` or `outlined` variants instead. + ## InputBase ### Removed `inputProps` From 76db9998922e3b093be6d197ec7a1784aa26f9bd Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 27 Sep 2023 21:28:05 +0800 Subject: [PATCH 17/18] Update proptypes --- .../src/FormControl/FormControl.tsx | 4 --- .../src/InputBase/InputBase.tsx | 27 ++++--------------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/packages/mui-material-next/src/FormControl/FormControl.tsx b/packages/mui-material-next/src/FormControl/FormControl.tsx index 32eed461d78314..01968d28bc303f 100644 --- a/packages/mui-material-next/src/FormControl/FormControl.tsx +++ b/packages/mui-material-next/src/FormControl/FormControl.tsx @@ -274,10 +274,6 @@ FormControl.propTypes /* remove-proptypes */ = { * Override or extend the styles applied to the component. */ classes: PropTypes.object, - /** - * Class name applied to the root element. - */ - className: PropTypes.string, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the diff --git a/packages/mui-material-next/src/InputBase/InputBase.tsx b/packages/mui-material-next/src/InputBase/InputBase.tsx index 27ef24356e9025..02d5b103cfa521 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.tsx +++ b/packages/mui-material-next/src/InputBase/InputBase.tsx @@ -551,16 +551,6 @@ InputBase.propTypes /* remove-proptypes */ = { * @ignore */ 'aria-describedby': PropTypes.string, - /** - * Defines a string value that labels the current element. - * @see aria-labelledby. - */ - 'aria-label': PropTypes.string, - /** - * Identifies the element (or elements) that labels the current element. - * @see aria-describedby. - */ - 'aria-labelledby': PropTypes.string, /** * This prop helps users to fill forms faster, especially on mobile devices. * The name can be confusing, as it's more like an autofill. @@ -571,18 +561,10 @@ InputBase.propTypes /* remove-proptypes */ = { * If `true`, the `input` element is focused during the first mount. */ autoFocus: PropTypes.bool, - /** - * @ignore - */ - children: PropTypes.node, /** * Override or extend the styles applied to the component. */ classes: PropTypes.object, - /** - * @ignore - */ - className: PropTypes.string, /** * The color of the component. * It supports both default and custom theme colors, which can be added as shown in the @@ -623,6 +605,11 @@ InputBase.propTypes /* remove-proptypes */ = { * The id of the `input` element. */ id: PropTypes.string, + /** + * The component used for the input node. + * Either a string to use a HTML element or a component. + */ + inputComponent: PropTypes.elementType, /** * Pass a ref to the `input` element. */ @@ -663,10 +650,6 @@ InputBase.propTypes /* remove-proptypes */ = { * You can pull out the new value by accessing `event.target.value` (string). */ onChange: PropTypes.func, - /** - * @ignore - */ - onClick: PropTypes.func, /** * @ignore */ From d2955f8a526b22603cbbe6c4131ef0672e153d31 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 27 Sep 2023 22:25:01 +0800 Subject: [PATCH 18/18] Update comments --- packages/mui-material-next/src/InputBase/InputBase.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/mui-material-next/src/InputBase/InputBase.test.js b/packages/mui-material-next/src/InputBase/InputBase.test.js index 1bf9a01ecf6e50..96eb55612ed2ca 100644 --- a/packages/mui-material-next/src/InputBase/InputBase.test.js +++ b/packages/mui-material-next/src/InputBase/InputBase.test.js @@ -221,6 +221,8 @@ describe('', () => { }); }); + // for InputBase, the `component` prop is called `inputComponent` so it's skipped + // in describeConformance and manually tested here describe('prop: inputComponent', () => { it('should accept any html component', () => { const { getByTestId } = render(