diff --git a/.size-limit.js b/.size-limit.js index ac662de364d6d8..abd3066a57eddc 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -27,7 +27,7 @@ module.exports = [ name: 'The size of all the modules of material-ui.', webpack: true, path: 'packages/material-ui/build/index.js', - limit: '94.6 KB', + limit: '94.7 KB', }, { name: 'The main bundle of the docs', diff --git a/packages/material-ui/src/Checkbox/Checkbox.js b/packages/material-ui/src/Checkbox/Checkbox.js index 3a892075f2d991..abb53cc99c0594 100644 --- a/packages/material-ui/src/Checkbox/Checkbox.js +++ b/packages/material-ui/src/Checkbox/Checkbox.js @@ -98,7 +98,7 @@ Checkbox.propTypes = { /** * Use that property to pass a ref callback to the native input component. */ - inputRef: PropTypes.func, + inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), /** * Callback fired when the state is changed. * diff --git a/packages/material-ui/src/FormControlLabel/FormControlLabel.js b/packages/material-ui/src/FormControlLabel/FormControlLabel.js index 5d2f8ae0a7143f..da5db998b6e7fd 100644 --- a/packages/material-ui/src/FormControlLabel/FormControlLabel.js +++ b/packages/material-ui/src/FormControlLabel/FormControlLabel.js @@ -116,7 +116,7 @@ FormControlLabel.propTypes = { /** * Use that property to pass a ref callback to the native input component. */ - inputRef: PropTypes.func, + inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), /** * The text to be used in an enclosing label element. */ diff --git a/packages/material-ui/src/Input/Input.d.ts b/packages/material-ui/src/Input/Input.d.ts index 2481d86255cc7c..0cb45b5e29dbc6 100644 --- a/packages/material-ui/src/Input/Input.d.ts +++ b/packages/material-ui/src/Input/Input.d.ts @@ -18,7 +18,7 @@ export interface InputProps id?: string; inputComponent?: React.ReactType; inputProps?: { [arbitrary: string]: any }; - inputRef?: React.Ref; + inputRef?: React.Ref | React.RefObject; margin?: 'dense'; multiline?: boolean; name?: string; diff --git a/packages/material-ui/src/Input/Input.js b/packages/material-ui/src/Input/Input.js index 28d15859d25855..074a8b42aa5bfe 100644 --- a/packages/material-ui/src/Input/Input.js +++ b/packages/material-ui/src/Input/Input.js @@ -323,10 +323,20 @@ class Input extends React.Component { handleRefInput = node => { this.input = node; + let ref; + if (this.props.inputRef) { - this.props.inputRef(node); + ref = this.props.inputRef; } else if (this.props.inputProps && this.props.inputProps.ref) { - this.props.inputProps.ref(node); + ref = this.props.inputProps.ref; + } + + if (ref) { + if (typeof ref === 'function') { + ref(node); + } else { + ref.current = node; + } } }; @@ -541,7 +551,7 @@ Input.propTypes = { /** * Use that property to pass a ref callback to the native input component. */ - inputRef: PropTypes.func, + inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), /** * If `dense`, will adjust vertical spacing. This is normally obtained via context from * FormControl. diff --git a/packages/material-ui/src/Input/Input.test.js b/packages/material-ui/src/Input/Input.test.js index 38df091d39f4a3..ceacbec735343b 100644 --- a/packages/material-ui/src/Input/Input.test.js +++ b/packages/material-ui/src/Input/Input.test.js @@ -471,4 +471,18 @@ describe('', () => { assert.strictEqual(wrapper.childAt(1).type(), InputAdornment); }); }); + + describe('prop: inputRef', () => { + it('should be able to return the input node via a ref object', () => { + const ref = React.createRef(); + mount(); + assert.strictEqual(ref.current.tagName, 'INPUT'); + }); + + it('should be able to return the textarea node via a ref object', () => { + const ref = React.createRef(); + mount(); + assert.strictEqual(ref.current.tagName, 'TEXTAREA'); + }); + }); }); diff --git a/packages/material-ui/src/Input/Textarea.d.ts b/packages/material-ui/src/Input/Textarea.d.ts index 25411b272077f6..9029b97da16cb3 100644 --- a/packages/material-ui/src/Input/Textarea.d.ts +++ b/packages/material-ui/src/Input/Textarea.d.ts @@ -11,7 +11,7 @@ export interface TextareaProps disabled?: boolean; rows?: string | number; rowsMax?: string | number; - textareaRef?: React.Ref; + textareaRef?: React.Ref | React.RefObject; value?: string; } diff --git a/packages/material-ui/src/Input/Textarea.js b/packages/material-ui/src/Input/Textarea.js index 06f867287dc334..9ec321ed76ff06 100644 --- a/packages/material-ui/src/Input/Textarea.js +++ b/packages/material-ui/src/Input/Textarea.js @@ -115,8 +115,14 @@ class Textarea extends React.Component { handleRefInput = node => { this.input = node; - if (this.props.textareaRef) { - this.props.textareaRef(node); + + const { textareaRef } = this.props; + if (textareaRef) { + if (typeof textareaRef === 'function') { + textareaRef(node); + } else { + textareaRef.current = node; + } } }; @@ -224,7 +230,7 @@ Textarea.propTypes = { /** * Use that property to pass a ref callback to the native textarea element. */ - textareaRef: PropTypes.func, + textareaRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), /** * @ignore */ diff --git a/packages/material-ui/src/Input/Textarea.test.js b/packages/material-ui/src/Input/Textarea.test.js index 5ab8ad26ebdad8..6e6f6a4023b630 100644 --- a/packages/material-ui/src/Input/Textarea.test.js +++ b/packages/material-ui/src/Input/Textarea.test.js @@ -1,5 +1,3 @@ -// @flow - import React from 'react'; import { assert } from 'chai'; import { spy, useFakeTimers } from 'sinon'; @@ -156,4 +154,12 @@ describe('