diff --git a/components/auto-complete/index.tsx b/components/auto-complete/index.tsx index a4a618e223..5bf552b9c8 100755 --- a/components/auto-complete/index.tsx +++ b/components/auto-complete/index.tsx @@ -32,7 +32,7 @@ export interface AutoCompleteProps< OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, > extends Omit< InternalSelectProps, - 'inputIcon' | 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue' + 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue' > { dataSource?: DataSourceItemType[]; status?: InputStatus; @@ -141,7 +141,7 @@ const AutoComplete: React.ForwardRefRenderFunction { fireEvent.click(container.querySelector('.ant-cascader-checkbox')!); expect(container.querySelectorAll('.ant-cascader-checkbox-checked')).toHaveLength(3); }); + + it('deprecate showArrow', () => { + resetWarned(); + + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const { container } = render(); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: Cascader] `showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.', + ); + expect(container.querySelector('.ant-select-show-arrow')).toBeTruthy(); + + errSpy.mockRestore(); + }); }); diff --git a/components/cascader/index.tsx b/components/cascader/index.tsx index 33794723f7..e6e02cb9ab 100644 --- a/components/cascader/index.tsx +++ b/components/cascader/index.tsx @@ -119,6 +119,11 @@ export type CascaderProps = UnionCascaderProps & { multiple?: boolean; size?: SizeType; + /** + * @deprecated `showArrow` is deprecated which will be removed in next major version. It will be a + * default behavior, you can hide it by setting `suffixIcon` to null. + */ + showArrow?: boolean; disabled?: boolean; bordered?: boolean; placement?: SelectCommonPlacement; @@ -194,6 +199,12 @@ const Cascader = React.forwardRef((props: CascaderProps, ref: React.Ref, ref: React.Ref, ref: React.Ref, ref: React.Ref ); diff --git a/components/select/__tests__/index.test.tsx b/components/select/__tests__/index.test.tsx index 7013db534f..93157888cd 100644 --- a/components/select/__tests__/index.test.tsx +++ b/components/select/__tests__/index.test.tsx @@ -159,5 +159,18 @@ describe('Select', () => { errSpy.mockRestore(); }); + + it('deprecate showArrow', () => { + resetWarned(); + + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const { container } = render( placeholder={props.placeholder} style={props.style} defaultActiveFirstOption={false} - showArrow={false} + suffixIcon={null} filterOption={false} onSearch={handleSearch} onChange={handleChange} diff --git a/components/select/index.en-US.md b/components/select/index.en-US.md index b495ff27dd..356b9c5a95 100644 --- a/components/select/index.en-US.md +++ b/components/select/index.en-US.md @@ -86,11 +86,10 @@ Select component to select value from options. | placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | | | removeIcon | The custom remove icon | ReactNode | - | | | searchValue | The current input "search" text | string | - | | -| showArrow | Whether to show the drop-down arrow | boolean | `true` | | | showSearch | Whether select is searchable | boolean | single: false, multiple: true | | | size | Size of Select input | `large` \| `middle` \| `small` | `middle` | | | status | Set validation status | 'error' \| 'warning' | - | 4.19.0 | -| suffixIcon | The custom suffix icon. Customize icon will not response click open to avoid icon designed to do other interactive. You can use `pointer-events: none` style to bypass | ReactNode | - | | +| suffixIcon | The custom suffix icon. Customize icon will not response click open to avoid icon designed to do other interactive. You can use `pointer-events: none` style to bypass | ReactNode | `` | | | tagRender | Customize tag render, only applies when `mode` is set to `multiple` or `tags` | (props) => ReactNode | - | | | tokenSeparators | Separator used to tokenize, only applies when `mode="tags"` | string\[] | - | | | value | Current selected option (considered as a immutable array) | string \| string\[] \|
number \| number\[] \|
LabeledValue \| LabeledValue\[] | - | | diff --git a/components/select/index.tsx b/components/select/index.tsx index 5f3f1b7367..b79085df0d 100755 --- a/components/select/index.tsx +++ b/components/select/index.tsx @@ -47,6 +47,11 @@ export interface InternalSelectProps< disabled?: boolean; mode?: 'multiple' | 'tags' | 'SECRET_COMBOBOX_MODE_DO_NOT_USE' | 'combobox'; bordered?: boolean; + /** + * @deprecated `showArrow` is deprecated which will be removed in next major version. It will be a + * default behavior, you can hide it by setting `suffixIcon` to null. + */ + showArrow?: boolean; } export interface SelectProps< @@ -54,7 +59,7 @@ export interface SelectProps< OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, > extends Omit< InternalSelectProps, - 'inputIcon' | 'mode' | 'getInputElement' | 'getRawInputElement' | 'backfill' | 'placement' + 'mode' | 'getInputElement' | 'getRawInputElement' | 'backfill' | 'placement' > { placement?: SelectCommonPlacement; mode?: 'multiple' | 'tags'; @@ -89,7 +94,6 @@ const InternalSelect = < disabled: customDisabled, notFoundContent, status: customStatus, - showArrow, builtinPlacements, dropdownMatchSelectWidth, popupMatchSelectWidth, @@ -133,7 +137,7 @@ const InternalSelect = < }, [props.mode]); const isMultiple = mode === 'multiple' || mode === 'tags'; - const mergedShowArrow = useShowArrow(showArrow); + const showSuffixIcon = useShowArrow(props.suffixIcon, props.showArrow); const mergedPopupMatchSelectWidth = popupMatchSelectWidth ?? dropdownMatchSelectWidth ?? contextPopupMatchSelectWidth; @@ -163,8 +167,9 @@ const InternalSelect = < multiple: isMultiple, hasFeedback, feedbackIcon, - showArrow: mergedShowArrow, + showSuffixIcon, prefixCls, + showArrow: props.showArrow, }); const selectProps = omit(props as typeof props & { itemIcon: React.ReactNode }, [ @@ -226,6 +231,12 @@ const InternalSelect = < 'Select', '`dropdownMatchSelectWidth` is deprecated. Please use `popupMatchSelectWidth` instead.', ); + + warning( + !('showArrow' in props), + 'Select', + '`showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.', + ); } // ====================== Render ======================= @@ -249,7 +260,7 @@ const InternalSelect = < prefixCls={prefixCls} placement={memoPlacement} direction={direction} - inputIcon={suffixIcon} + suffixIcon={suffixIcon} menuItemSelectedIcon={itemIcon} removeIcon={removeIcon} clearIcon={clearIcon} @@ -257,7 +268,6 @@ const InternalSelect = < className={mergedClassName} getPopupContainer={getPopupContainer || getContextPopupContainer} dropdownClassName={rcSelectRtlDropdownClassName} - showArrow={hasFeedback || mergedShowArrow} disabled={mergedDisabled} />, ); diff --git a/components/select/index.zh-CN.md b/components/select/index.zh-CN.md index 37c12c7002..cf5e5accfb 100644 --- a/components/select/index.zh-CN.md +++ b/components/select/index.zh-CN.md @@ -87,11 +87,10 @@ demo: | placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | | | removeIcon | 自定义的多选框清除图标 | ReactNode | - | | | searchValue | 控制搜索文本 | string | - | | -| showArrow | 是否显示下拉小箭头 | boolean | `true` | | | showSearch | 配置是否可搜索 | boolean | 单选为 false,多选为 true | | | size | 选择框大小 | `large` \| `middle` \| `small` | `middle` | | | status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 | -| suffixIcon | 自定义的选择框后缀图标。以防止图标被用于其他交互,替换的图标默认不会响应展开、收缩事件,可以通过添加 `pointer-events: none` 样式透传。 | ReactNode | - | | +| suffixIcon | 自定义的选择框后缀图标。以防止图标被用于其他交互,替换的图标默认不会响应展开、收缩事件,可以通过添加 `pointer-events: none` 样式透传。 | ReactNode | `` | | | tagRender | 自定义 tag 内容 render,仅在 `mode` 为 `multiple` 或 `tags` 时生效 | (props) => ReactNode | - | | | tokenSeparators | 自动分词的分隔符,仅在 `mode="tags"` 时生效 | string\[] | - | | | value | 指定当前选中的条目,多选时为一个数组。(value 数组引用未变化时,Select 不会更新) | string \| string\[] \|
number \| number\[] \|
LabeledValue \| LabeledValue\[] | - | | diff --git a/components/select/useShowArrow.ts b/components/select/useShowArrow.ts index 3c157f0d39..0f344cb1ac 100644 --- a/components/select/useShowArrow.ts +++ b/components/select/useShowArrow.ts @@ -1,9 +1,11 @@ +import type { ReactNode } from 'react'; + /** * Since Select, TreeSelect, Cascader is same Select like component. * We just use same hook to handle this logic. * - * If `showArrow` not configured, always show it. + * If `suffixIcon` is not equal to `null`, always show it. */ -export default function useShowArrow(showArrow?: boolean) { - return showArrow ?? true; +export default function useShowArrow(suffixIcon?: ReactNode, showArrow?: boolean) { + return showArrow !== undefined ? showArrow : suffixIcon !== null; } diff --git a/components/select/utils/iconUtil.tsx b/components/select/utils/iconUtil.tsx index 45df8e1072..a5718b8a23 100644 --- a/components/select/utils/iconUtil.tsx +++ b/components/select/utils/iconUtil.tsx @@ -18,8 +18,9 @@ export default function getIcons({ multiple, hasFeedback, prefixCls, - showArrow, + showSuffixIcon, feedbackIcon, + showArrow, }: { suffixIcon?: React.ReactNode; clearIcon?: RenderNode; @@ -30,18 +31,24 @@ export default function getIcons({ hasFeedback?: boolean; feedbackIcon?: ReactNode; prefixCls: string; + showSuffixIcon?: boolean; showArrow?: boolean; }) { // Clear Icon const mergedClearIcon = clearIcon ?? ; // Validation Feedback Icon - const getSuffixIconNode = (arrowIcon?: ReactNode) => ( - <> - {showArrow !== false && arrowIcon} - {hasFeedback && feedbackIcon} - - ); + const getSuffixIconNode = (arrowIcon?: ReactNode) => { + if (suffixIcon === null && !hasFeedback && !showArrow) { + return null; + } + return ( + <> + {showSuffixIcon !== false && arrowIcon} + {hasFeedback && feedbackIcon} + + ); + }; // Arrow item icon let mergedSuffixIcon = null; diff --git a/components/tree-select/__tests__/index.test.tsx b/components/tree-select/__tests__/index.test.tsx index 45cf756d57..c5a626a152 100644 --- a/components/tree-select/__tests__/index.test.tsx +++ b/components/tree-select/__tests__/index.test.tsx @@ -89,4 +89,17 @@ describe('TreeSelect', () => { container.querySelector('.ant-select-tree-treenode-leaf-last')?.getAttribute('aria-label'), ).toBe('label'); }); + + it('deprecate showArrow', () => { + resetWarned(); + + const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const { container } = render(); + expect(errSpy).toHaveBeenCalledWith( + 'Warning: [antd: TreeSelect] `showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.', + ); + expect(container.querySelector('.ant-select-show-arrow')).toBeTruthy(); + + errSpy.mockRestore(); + }); }); diff --git a/components/tree-select/index.en-US.md b/components/tree-select/index.en-US.md index 3972199c85..12d91ce8ab 100644 --- a/components/tree-select/index.en-US.md +++ b/components/tree-select/index.en-US.md @@ -57,12 +57,11 @@ Tree selection control. | placeholder | Placeholder of the select input | string | - | | | placement | The position where the selection box pops up | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | | | searchValue | Work with `onSearch` to make search value controlled | string | - | | -| showArrow | Whether to show the `suffixIcon` | boolean | `true` | | | showCheckedStrategy | The way show selected item in box when `treeCheckable` set. **Default:** just show child nodes. **`TreeSelect.SHOW_ALL`:** show all checked treeNodes (include parent treeNode). **`TreeSelect.SHOW_PARENT`:** show checked treeNodes (just show parent treeNode) | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | | | showSearch | Support search or not | boolean | single: false \| multiple: true | | | size | To set the size of the select input | `large` \| `middle` \| `small` | - | | | status | Set validation status | 'error' \| 'warning' | - | 4.19.0 | -| suffixIcon | The custom suffix icon,you must set `showArrow` to `true` manually in multiple selection mode | ReactNode | - | | +| suffixIcon | The custom suffix icon | ReactNode | `` | | | switcherIcon | Customize collapse/expand icon of tree node | ReactNode \| ((props: AntTreeNodeProps) => ReactNode) | - | renderProps: 4.20.0 | | tagRender | Customize tag render when `multiple` | (props) => ReactNode | - | | | treeCheckable | Whether to show checkbox on the treeNodes | boolean | false | | diff --git a/components/tree-select/index.tsx b/components/tree-select/index.tsx index 017494a1cd..f0072b0c5d 100644 --- a/components/tree-select/index.tsx +++ b/components/tree-select/index.tsx @@ -47,7 +47,6 @@ export interface TreeSelectProps< RcTreeSelectProps, | 'showTreeIcon' | 'treeMotion' - | 'inputIcon' | 'mode' | 'getInputElement' | 'backfill' @@ -70,6 +69,11 @@ export interface TreeSelectProps< /** @deprecated Please use `popupMatchSelectWidth` instead */ dropdownMatchSelectWidth?: boolean | number; popupMatchSelectWidth?: boolean | number; + /** + * @deprecated `showArrow` is deprecated which will be removed in next major version. It will be a + * default behavior, you can hide it by setting `suffixIcon` to null. + */ + showArrow?: boolean; } const InternalTreeSelect = < @@ -98,7 +102,6 @@ const InternalTreeSelect = < transitionName, choiceTransitionName = '', status: customStatus, - showArrow, treeExpandAction, builtinPlacements, dropdownMatchSelectWidth, @@ -135,6 +138,12 @@ const InternalTreeSelect = < 'Select', '`dropdownMatchSelectWidth` is deprecated. Please use `popupMatchSelectWidth` instead.', ); + + warning( + !('showArrow' in props), + 'TreeSelect', + '`showArrow` is deprecated which will be removed in next major version. It will be a default behavior, you can hide it by setting `suffixIcon` to null.', + ); } const rootPrefixCls = getPrefixCls(); @@ -157,7 +166,7 @@ const InternalTreeSelect = < ); const isMultiple = !!(treeCheckable || multiple); - const mergedShowArrow = useShowArrow(showArrow); + const showSuffixIcon = useShowArrow(props.suffixIcon, props.showArrow); const mergedPopupMatchSelectWidth = popupMatchSelectWidth ?? dropdownMatchSelectWidth ?? contextPopupMatchSelectWidth; @@ -175,7 +184,7 @@ const InternalTreeSelect = < const { suffixIcon, removeIcon, clearIcon } = getIcons({ ...props, multiple: isMultiple, - showArrow: mergedShowArrow, + showSuffixIcon, hasFeedback, feedbackIcon, prefixCls, @@ -255,7 +264,7 @@ const InternalTreeSelect = < treeCheckable ? : treeCheckable } treeLine={!!treeLine} - inputIcon={suffixIcon} + suffixIcon={suffixIcon} multiple={isMultiple} placement={memoizedPlacement} removeIcon={removeIcon} @@ -272,7 +281,6 @@ const InternalTreeSelect = < getTransitionDirection(placement), transitionName, )} - showArrow={hasFeedback || mergedShowArrow} treeExpandAction={treeExpandAction} /> ); diff --git a/components/tree-select/index.zh-CN.md b/components/tree-select/index.zh-CN.md index c2341d59a9..a3fccc3286 100644 --- a/components/tree-select/index.zh-CN.md +++ b/components/tree-select/index.zh-CN.md @@ -58,12 +58,11 @@ demo: | placeholder | 选择框默认文字 | string | - | | | placement | 选择框弹出的位置 | `bottomLeft` `bottomRight` `topLeft` `topRight` | bottomLeft | | | searchValue | 搜索框的值,可以通过 `onSearch` 获取用户输入 | string | - | | -| showArrow | 是否显示 `suffixIcon` | boolean | `true` | | | showCheckedStrategy | 配置 `treeCheckable` 时,定义选中项回填的方式。`TreeSelect.SHOW_ALL`: 显示所有选中节点(包括父节点)。`TreeSelect.SHOW_PARENT`: 只显示父节点(当父节点下所有子节点都选中时)。 默认只显示子节点 | `TreeSelect.SHOW_ALL` \| `TreeSelect.SHOW_PARENT` \| `TreeSelect.SHOW_CHILD` | `TreeSelect.SHOW_CHILD` | | | showSearch | 是否支持搜索框 | boolean | 单选:false \| 多选:true | | | size | 选择框大小 | `large` \| `middle` \| `small` | - | | | status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 | -| suffixIcon | 自定义的选择框后缀图标, 多选模式下必须同时设置 `showArrow` 为 true | ReactNode | - | | +| suffixIcon | 自定义的选择框后缀图标 | ReactNode | `` | | | switcherIcon | 自定义树节点的展开/折叠图标 | ReactNode \| ((props: AntTreeNodeProps) => ReactNode) | - | renderProps: 4.20.0 | | tagRender | 自定义 tag 内容,多选时生效 | (props) => ReactNode | - | | | treeCheckable | 显示 Checkbox | boolean | false | | diff --git a/package.json b/package.json index d36523acde..aea16c50b9 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "copy-to-clipboard": "^3.2.0", "dayjs": "^1.11.1", "qrcode.react": "^3.1.0", - "rc-cascader": "~3.12.0", + "rc-cascader": "~3.13.0", "rc-checkbox": "~3.1.0", "rc-collapse": "~3.7.0", "rc-dialog": "~9.1.0", @@ -142,7 +142,7 @@ "rc-rate": "~2.12.0", "rc-resize-observer": "^1.2.0", "rc-segmented": "~2.2.0", - "rc-select": "~14.5.0", + "rc-select": "~14.6.0", "rc-slider": "~10.1.0", "rc-steps": "~6.0.0", "rc-switch": "~4.1.0", @@ -151,7 +151,7 @@ "rc-textarea": "~1.3.2", "rc-tooltip": "~6.0.0", "rc-tree": "~5.7.6", - "rc-tree-select": "~5.9.0", + "rc-tree-select": "~5.10.0", "rc-upload": "~4.3.0", "rc-util": "^5.32.0", "scroll-into-view-if-needed": "^3.0.3",