From ee3e1fe9eff3534fc6f9f88d491d1a1ec1ab29ae 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 17:04:13 +0800 Subject: [PATCH] feat: unify allowClear configuration --- README.md | 21 ++++- package.json | 4 +- src/Mentions.tsx | 4 +- tests/__snapshots__/AllowClear.spec.tsx.snap | 6 ++ tests/allowClear.test.tsx | 81 ++++++++++++++++++++ 5 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 tests/allowClear.test.tsx diff --git a/README.md b/README.md index cced210..e0c8344 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Then open `http://localhost:8000`. | Property | Type | Default | Description | | ----------------- | ---------------------------------------------------------- | ------------- | ----------------------------------------------- | -| allowClear | `boolean \| { clearIcon?: ReactNode }` | `false` | Show a clear button for the textarea value. | +| allowClear | `boolean \| AllowClearConfig` | `false` | Show a clear button for the textarea value. | | autoFocus | `boolean` | `false` | Focus the textarea when mounted. | | autoSize | `boolean \| { minRows?: number; maxRows?: number }` | - | Auto resize textarea height. | | children | `ReactNode` | - | `Mentions.Option` children. | @@ -169,3 +169,22 @@ The release flow is handled by `@rc-component/np` through the `rc-np` command af ## License @rc-component/mentions 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. + +When no other affix keeps the wrapper mounted, dynamically disabling clearing can recreate the input DOM node and lose focus or selection, just like switching to `allowClear={false}`. The value is preserved. With an existing suffix, the wrapper, focus, and selection remain stable. diff --git a/package.json b/package.json index f1e9855..e783a6e 100644 --- a/package.json +++ b/package.json @@ -44,10 +44,10 @@ "*": "prettier --write --ignore-unknown" }, "dependencies": { - "@rc-component/input": "~1.4.0", + "@rc-component/input": "~1.4.1", "@rc-component/menu": "~1.6.0", "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.13.0", + "@rc-component/util": "^1.14.0", "clsx": "^2.1.1" }, "devDependencies": { diff --git a/src/Mentions.tsx b/src/Mentions.tsx index 1f3ae35..b40106f 100644 --- a/src/Mentions.tsx +++ b/src/Mentions.tsx @@ -11,6 +11,7 @@ import { KeyCode, toArray, useControlledState, + useAllowClear, useId, } from '@rc-component/util'; import React, { @@ -663,7 +664,8 @@ const Mentions = forwardRef( }, ref, ) => { - const hasSuffix = isReactRenderable(suffix) || Boolean(allowClear); + const clearConfig = useAllowClear(allowClear); + const hasSuffix = isReactRenderable(suffix) || !clearConfig.disabled; const suffixNode = isReactRenderable(suffix) ? <>{suffix} : suffix; // =============================== Ref ================================ diff --git a/tests/__snapshots__/AllowClear.spec.tsx.snap b/tests/__snapshots__/AllowClear.spec.tsx.snap index 0c752bd..77663ea 100644 --- a/tests/__snapshots__/AllowClear.spec.tsx.snap +++ b/tests/__snapshots__/AllowClear.spec.tsx.snap @@ -12,6 +12,7 @@ exports[`should support allowClear should not show icon if defaultValue is undef class="rc-mentions-suffix" >