diff --git a/packages/mui-material/src/InputBase/InputBase.js b/packages/mui-material/src/InputBase/InputBase.js
index 36e7679ca95a4f..f860a081144fe0 100644
--- a/packages/mui-material/src/InputBase/InputBase.js
+++ b/packages/mui-material/src/InputBase/InputBase.js
@@ -455,14 +455,38 @@ const InputBase = React.forwardRef(function InputBase(inProps, ref) {
}, []);
const handleClick = (event) => {
- if (inputRef.current && event.currentTarget === event.target) {
- inputRef.current.focus();
- }
+ const input = inputRef.current;
+
+ if (
+ input &&
+ event.currentTarget === event.target &&
+ (input.nodeName === 'INPUT' || input.nodeName === 'TEXTAREA')
+ ) {
+ const pos =
+ typeof input.selectionStart === 'number'
+ ? input.selectionStart
+ : input.value.length;
+
+ input.focus();
+
+ requestAnimationFrame(() => {
+ const restorePos =
+ pos === 0 && event.target === event.currentTarget
+ ? input.value.length
+ : pos;
+
+ if (typeof input.setSelectionRange === 'function') {
+ input.setSelectionRange(restorePos, restorePos);
+ }
+ });
+ }
+
+ if (onClick) {
+ onClick(event);
+ }
+};
+
- if (onClick) {
- onClick(event);
- }
- };
let InputComponent = inputComponent;
let inputProps = inputPropsProp;
diff --git a/packages/mui-material/src/InputBase/InputBase.test.js b/packages/mui-material/src/InputBase/InputBase.test.js
index d1f047ae040c1f..45635ea1ac89e3 100644
--- a/packages/mui-material/src/InputBase/InputBase.test.js
+++ b/packages/mui-material/src/InputBase/InputBase.test.js
@@ -1,7 +1,7 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { expect } from 'chai';
-import { spy } from 'sinon';
+import sinon, { spy } from 'sinon';
import { act, createRenderer, fireEvent, screen, reactMajor } from '@mui/internal-test-utils';
import { ThemeProvider } from '@emotion/react';
import FormControl, { useFormControl } from '@mui/material/FormControl';
@@ -694,6 +694,32 @@ describe('', () => {
});
});
+ describe('caret behavior', () => {
+ it('should preserve caret position when clicking on the Root wrapper', () => {
+ const clock = sinon.useFakeTimers();
+
+ const { container } = render();
+ const input = container.querySelector('input');
+
+ act(() => {
+ input.setSelectionRange(2, 2);
+ });
+
+ const wrapper = input.parentElement;
+
+ fireEvent.click(wrapper);
+
+ act(() => {
+ clock.runAll();
+ });
+
+ expect(input.selectionStart).to.equal(2);
+ expect(input.selectionEnd).to.equal(2);
+
+ clock.restore();
+ });
+ });
+
describe('prop: focused', () => {
it('should render correct border color with `ThemeProvider` imported from `@emotion/react`', function test() {
if (window.navigator.userAgent.includes('jsdom')) {