Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/ResizableTextArea.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import classNames from 'classnames';
import ResizeObserver from '@rc-component/resize-observer';
import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect';
import useMergedState from '@rc-component/util/lib/hooks/useMergedState';
import raf from '@rc-component/util/lib/raf';
import classNames from 'classnames';
import * as React from 'react';
import type { TextAreaProps } from '.';
import calculateAutoSizeStyle from './calculateNodeHeight';
Expand Down Expand Up @@ -66,9 +66,10 @@ const ResizableTextArea = React.forwardRef<ResizableTextAreaRef, TextAreaProps>(
// https://github.com/ant-design/ant-design/issues/21870
const fixFirefoxAutoScroll = () => {
try {
const isFirefox = navigator.userAgent.includes('Firefox');
// FF has bug with jump of scroll to top. We force back here.
if (document.activeElement === textareaRef.current) {
const { selectionStart, selectionEnd, scrollTop } =
if (isFirefox && document.activeElement === textareaRef.current) {
const { scrollTop, selectionStart, selectionEnd } =
textareaRef.current;

// Fix Safari bug which not rollback when break line
Expand Down
51 changes: 46 additions & 5 deletions tests/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,42 @@ describe('TextArea', () => {
jest.useRealTimers();
});

it('paste text should change cursor position', async () => {
const { container } = render(
<TextArea autoSize={{ minRows: 2, maxRows: 6 }} />,
);
const textArea = container.querySelector('textarea') as HTMLTextAreaElement;
// ็›‘ๅฌไบ‹ไปถ็ป‘ๅฎšๅ’Œ็งป้™ค
const pasteData = 'pasted text\n'.repeat(10);
const clipboardData = {
getData: jest.fn().mockReturnValue(pasteData),
};

const pasteEvent = async () => {
fireEvent.focus(textArea);

fireEvent.paste(textArea, {
clipboardData,
types: ['text/plain'],
items: [],
});

fireEvent.change(textArea, { target: { value: pasteData } });
textArea.setSelectionRange(pasteData.length, pasteData.length);

await wait();
expect(textArea.selectionStart).toBe(pasteData.length);
expect(textArea.selectionEnd).toBe(pasteData.length);
fireEvent.change(textArea, { target: { value: '' } });
await wait();
expect(textArea.selectionStart).toBe(0);
expect(textArea.selectionEnd).toBe(0);
};

await pasteEvent();
await pasteEvent();
});

it('should work correctly on controlled mode', () => {
const Demo = () => {
const [value, setValue] = React.useState('111');
Expand Down Expand Up @@ -235,18 +271,23 @@ describe('TextArea', () => {
container.querySelector('textarea').focus();
expect(document.activeElement).toBe(container.querySelector('textarea'));

const setSelectionRangeFn = jest.spyOn(
container.querySelector('textarea'),
'setSelectionRange',
);
// https://github.com/ant-design/ant-design/issues/54444
// Other browsers may have cursor position issues when calling setSelectionRange, so we do not call it here.
// const setSelectionRangeFn = jest.spyOn(
// container.querySelector('textarea'),
// 'setSelectionRange',
// );

fireEvent.change(container.querySelector('textarea'), {
target: { value: '\n1' },
});

await wait();

expect(setSelectionRangeFn).toHaveBeenCalled();
// expect(setSelectionRangeFn).toHaveBeenCalled();
expect(container.querySelector('textarea').scrollTop).toBe(
container.querySelector('textarea').scrollHeight,
);
unmount();
});

Expand Down