From 23a89406d81afe8434094cbfb8a66c43c86b2bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 10 Nov 2025 16:56:33 +0800 Subject: [PATCH] feat: triggerFocus support --- src/Dom/focus.ts | 40 ++++++++++++++++++++++++++++++++++++++++ tests/focus.test.ts | 27 ++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/Dom/focus.ts b/src/Dom/focus.ts index a6654841..6b182463 100644 --- a/src/Dom/focus.ts +++ b/src/Dom/focus.ts @@ -97,3 +97,43 @@ export function limitTabRange(node: HTMLElement, e: KeyboardEvent) { } } } + +export interface InputFocusOptions extends FocusOptions { + cursor?: 'start' | 'end' | 'all'; +} + +// Used for `rc-input` `rc-textarea` `rc-input-number` +/** + * Focus element and set cursor position for input/textarea elements. + */ +export function triggerFocus( + element?: HTMLElement, + option?: InputFocusOptions, +) { + if (!element) return; + + element.focus(option); + + // Selection content + const { cursor } = option || {}; + if ( + cursor && + (element instanceof HTMLInputElement || + element instanceof HTMLTextAreaElement) + ) { + const len = element.value.length; + + switch (cursor) { + case 'start': + element.setSelectionRange(0, 0); + break; + + case 'end': + element.setSelectionRange(len, len); + break; + + default: + element.setSelectionRange(0, len); + } + } +} diff --git a/tests/focus.test.ts b/tests/focus.test.ts index 795e2e71..1c835bf9 100644 --- a/tests/focus.test.ts +++ b/tests/focus.test.ts @@ -1,6 +1,6 @@ /* eslint-disable class-methods-use-this */ import { spyElementPrototype } from '../src/test/domHook'; -import { getFocusNodeList } from '../src/Dom/focus'; +import { getFocusNodeList, triggerFocus } from '../src/Dom/focus'; describe('focus', () => { beforeAll(() => { @@ -31,4 +31,29 @@ describe('focus', () => { const tabFocusList = getFocusNodeList(div, true); expect(tabFocusList).toHaveLength(5); }); + + it('triggerFocus should set cursor position for textarea', () => { + const textarea = document.createElement('textarea'); + textarea.value = 'test content'; + + const focusSpy = jest.spyOn(textarea, 'focus'); + const setSelectionRangeSpy = jest.spyOn(textarea, 'setSelectionRange'); + + // Test cursor: 'start' + triggerFocus(textarea, { cursor: 'start' }); + expect(setSelectionRangeSpy).toHaveBeenCalledWith(0, 0); + + // Test cursor: 'end' + triggerFocus(textarea, { cursor: 'end' }); + expect(setSelectionRangeSpy).toHaveBeenCalledWith(12, 12); // 'test content'.length = 12 + + // Test cursor: 'all' + triggerFocus(textarea, { cursor: 'all' }); + expect(setSelectionRangeSpy).toHaveBeenCalledWith(0, 12); // select all text + + expect(focusSpy).toHaveBeenCalledTimes(3); + + focusSpy.mockRestore(); + setSelectionRangeSpy.mockRestore(); + }); });