Skip to content

Commit

Permalink
[Input][material-next] Add InputBase component (#38392)
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert authored Aug 22, 2023
1 parent 81090a6 commit ab8f160
Show file tree
Hide file tree
Showing 14 changed files with 1,981 additions and 18 deletions.
22 changes: 14 additions & 8 deletions docs/pages/base-ui/api/use-input.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,30 @@
"error": { "type": { "name": "boolean", "description": "boolean" } },
"inputRef": {
"type": {
"name": "React.Ref<HTMLInputElement>",
"description": "React.Ref<HTMLInputElement>"
"name": "React.Ref<HTMLInputElement | HTMLTextAreaElement>",
"description": "React.Ref<HTMLInputElement | HTMLTextAreaElement>"
}
},
"onBlur": {
"type": { "name": "React.FocusEventHandler", "description": "React.FocusEventHandler" }
"type": {
"name": "React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>",
"description": "React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>"
}
},
"onChange": {
"type": {
"name": "React.ChangeEventHandler<HTMLInputElement>",
"description": "React.ChangeEventHandler<HTMLInputElement>"
"name": "React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>",
"description": "React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>"
}
},
"onClick": {
"type": { "name": "React.MouseEventHandler", "description": "React.MouseEventHandler" }
},
"onFocus": {
"type": { "name": "React.FocusEventHandler", "description": "React.FocusEventHandler" }
"type": {
"name": "React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>",
"description": "React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>"
}
},
"required": { "type": { "name": "boolean", "description": "boolean" } },
"value": { "type": { "name": "unknown", "description": "unknown" } }
Expand Down Expand Up @@ -54,8 +60,8 @@
},
"inputRef": {
"type": {
"name": "React.RefCallback<HTMLInputElement> | null",
"description": "React.RefCallback<HTMLInputElement> | null"
"name": "React.RefCallback<HTMLInputElement | HTMLTextAreaElement> | null",
"description": "React.RefCallback<HTMLInputElement | HTMLTextAreaElement> | null"
},
"required": true
},
Expand Down
29 changes: 28 additions & 1 deletion packages/mui-base/src/useInput/useInput.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as React from 'react';
import { createRenderer } from 'test/utils';
import { act, createRenderer } from 'test/utils';
import { expect } from 'chai';
import { spy } from 'sinon';
import { useInput } from './useInput';
import { UseInputParameters } from './useInput.types';

describe('useInput', () => {
const { render } = createRenderer();
Expand All @@ -20,4 +22,29 @@ describe('useInput', () => {
expect(inputRef.current).to.deep.equal(getByRole('textbox'));
});
});

describe('prop: disabled', () => {
it('should reset the focused state if getting disabled', () => {
const handleBlur = spy();
const handleFocus = spy();

function Input(props: UseInputParameters) {
const { getInputProps } = useInput(props);

return <input {...getInputProps()} />;
}
const { getByRole, setProps } = render(<Input onBlur={handleBlur} onFocus={handleFocus} />);

act(() => {
getByRole('textbox').focus();
});
expect(handleFocus.callCount).to.equal(1);

setProps({ disabled: true });

expect(handleBlur.callCount).to.equal(1);
// check if focus not initiated again
expect(handleFocus.callCount).to.equal(1);
});
});
});
18 changes: 9 additions & 9 deletions packages/mui-base/src/useInput/useInput.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ export interface UseInputParameters {
* The prop defaults to the value (`false`) inherited from the parent FormControl component.
*/
error?: boolean;
onBlur?: React.FocusEventHandler;
onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onClick?: React.MouseEventHandler;
onChange?: React.ChangeEventHandler<HTMLInputElement>;
onFocus?: React.FocusEventHandler;
inputRef?: React.Ref<HTMLInputElement>;
onChange?: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onFocus?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
inputRef?: React.Ref<HTMLInputElement | HTMLTextAreaElement>;
/**
* If `true`, the `input` element is required.
* The prop defaults to the value (`false`) inherited from the parent FormControl component.
Expand All @@ -42,11 +42,11 @@ export type UseInputRootSlotProps<TOther = {}> = Omit<
export interface UseInputInputSlotOwnProps {
'aria-invalid': React.AriaAttributes['aria-invalid'];
defaultValue: string | number | readonly string[] | undefined;
ref: React.RefCallback<HTMLInputElement> | null;
ref: React.RefCallback<HTMLInputElement | HTMLTextAreaElement> | null;
value: string | number | readonly string[] | undefined;
onBlur: React.FocusEventHandler;
onChange: React.ChangeEventHandler<HTMLInputElement>;
onFocus: React.FocusEventHandler;
onBlur: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onFocus: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
required: boolean;
disabled: boolean;
}
Expand Down Expand Up @@ -87,7 +87,7 @@ export interface UseInputReturnValue {
getRootProps: <TOther extends Record<string, any> = {}>(
externalProps?: TOther,
) => UseInputRootSlotProps<TOther>;
inputRef: React.RefCallback<HTMLInputElement> | null;
inputRef: React.RefCallback<HTMLInputElement | HTMLTextAreaElement> | null;
/**
* If `true`, the `input` will indicate that it's required.
*/
Expand Down
24 changes: 24 additions & 0 deletions packages/mui-material-next/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,30 @@ 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`.

## InputBase

### Removed the `inputComponent` prop

The `inputComponent` is deprecated in favor of `slots.input`:

```diff
<InputBase
- inputComponent="textarea"
+ slots={{ input: 'textarea' }}
/>
```

### Removed `inputProps`

`inputProps` are deprecated in favor of `slotProps.input`:

```diff
<InputBase
- inputProps={{ className: 'my-input' }}
+ slotProps={{ input: { className: 'my-input' } }}
/>
```

## Slider

### Thumb and Value Label slots must accept refs
Expand Down
9 changes: 9 additions & 0 deletions packages/mui-material-next/src/InputBase/InputBase.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as React from 'react';
import { expectType } from '@mui/types';
import InputBase from '@mui/material-next/InputBase';

<InputBase
onInvalid={(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) => {
expectType<React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, typeof event>(event);
}}
/>;
Loading

0 comments on commit ab8f160

Please sign in to comment.