From e71eb3de7e44a6309a4346e4c29a7f1c067b5cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E8=89=B3=E5=85=B5?= Date: Tue, 13 Oct 2026 15:41:48 +0800 Subject: [PATCH] feat: unify allowClear configuration --- README.md | 17 +++++++ package.json | 2 +- src/BaseSelect/index.tsx | 6 ++- src/SelectInput/index.tsx | 3 ++ src/hooks/useAllowClear.tsx | 26 +++++------ src/utils/warningPropsUtil.ts | 6 ++- tests/allowClear.test.tsx | 86 +++++++++++++++++++++++++++++++++++ 7 files changed, 127 insertions(+), 19 deletions(-) create mode 100644 tests/allowClear.test.tsx diff --git a/README.md b/README.md index 6da84ebf..0363bd2e 100644 --- a/README.md +++ b/README.md @@ -167,3 +167,20 @@ The release flow is handled by `@rc-component/np` through the `rc-np` command af ## License @rc-component/select is released under the [MIT](./LICENSE) license. + +### Clear configuration + +`allowClear` accepts a boolean or an `AllowClearConfig` object from `@rc-component/util`: + +```ts +interface AllowClearConfig { + clearIcon?: React.ReactNode; + disabled?: boolean; + tabIndex?: number; + label?: string; +} +``` + +All fields are optional. `disabled: true` behaves like `allowClear={false}`: the clear button and space reserved solely for it are removed; the input remains editable. Existing suffixes and other content are preserved. This changes the previous hidden-button spacing behavior where applicable. + +`tabIndex` affects only the clear button; `-1` removes it from Tab navigation while retaining mouse activation. `label` supplies its accessible name through `aria-label`. Defaults, clear values, callbacks, and component state restrictions are unchanged. diff --git a/package.json b/package.json index 14b6d995..cb18d197 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "dependencies": { "@rc-component/overflow": "^1.0.0", "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.13.0", + "@rc-component/util": "^1.14.0", "@rc-component/virtual-list": "^1.2.0", "clsx": "^2.1.1" }, diff --git a/src/BaseSelect/index.tsx b/src/BaseSelect/index.tsx index 0389f623..c2dea864 100644 --- a/src/BaseSelect/index.tsx +++ b/src/BaseSelect/index.tsx @@ -1,6 +1,6 @@ import type { AlignType, BuildInPlacements } from '@rc-component/trigger'; import { clsx } from 'clsx'; -import { getDOM, isNonNullable, useEvent } from '@rc-component/util'; +import { type AllowClearConfig, getDOM, isNonNullable, useEvent } from '@rc-component/util'; import type { ScrollConfig, ScrollTo } from '@rc-component/virtual-list'; import * as React from 'react'; import { useAllowClear } from '../hooks/useAllowClear'; @@ -185,7 +185,7 @@ export interface BaseSelectProps tokenSeparators?: string[] | ((input: string) => string[]); // >>> Icons - allowClear?: boolean | { clearIcon?: React.ReactNode; label?: string }; + allowClear?: boolean | AllowClearConfig; prefix?: React.ReactNode; /** @deprecated Please use `suffix` instead. */ suffixIcon?: RenderNode; @@ -725,6 +725,7 @@ const BaseSelect = React.forwardRef((props, ref) allowClear: mergedAllowClear, clearIcon: clearNode, label: clearLabel, + tabIndex: clearTabIndex, } = useAllowClear( prefixCls, displayValues, @@ -768,6 +769,7 @@ const BaseSelect = React.forwardRef((props, ref) suffix={mergedSuffixIcon} clearIcon={clearNode} clearLabel={clearLabel} + clearTabIndex={clearTabIndex} // Type or mode multiple={multiple} mode={mode} diff --git a/src/SelectInput/index.tsx b/src/SelectInput/index.tsx index 0035803a..55da4919 100644 --- a/src/SelectInput/index.tsx +++ b/src/SelectInput/index.tsx @@ -29,6 +29,7 @@ export interface SelectInputProps extends Omit(function Selec suffix, clearIcon, clearLabel, + clearTabIndex, children, // Data @@ -310,6 +312,7 @@ export default React.forwardRef(function Selec