Browse Source

refactor: Select deprecated showArrow prop (#43520)

* refactor: remove showArrow prop

* fix: optimize iconUtil

* refactor: refactor tree-select&cascader

* docs: update api docs

* test: add test

* fix: update warning

* chore: update dep version

* test: update test
feature
MuxinFeng 1 year ago
committed by GitHub
parent
commit
084f234bc9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      components/auto-complete/index.tsx
  2. 13
      components/cascader/__tests__/index.test.tsx
  3. 18
      components/cascader/index.tsx
  4. 13
      components/select/__tests__/index.test.tsx
  5. 1
      components/select/demo/custom-tag-render.tsx
  6. 2
      components/select/demo/search-box.tsx
  7. 3
      components/select/index.en-US.md
  8. 22
      components/select/index.tsx
  9. 3
      components/select/index.zh-CN.md
  10. 8
      components/select/useShowArrow.ts
  11. 21
      components/select/utils/iconUtil.tsx
  12. 13
      components/tree-select/__tests__/index.test.tsx
  13. 3
      components/tree-select/index.en-US.md
  14. 20
      components/tree-select/index.tsx
  15. 3
      components/tree-select/index.zh-CN.md
  16. 6
      package.json

4
components/auto-complete/index.tsx

@ -32,7 +32,7 @@ export interface AutoCompleteProps<
OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType,
> extends Omit<
InternalSelectProps<ValueType, OptionType>,
'inputIcon' | 'loading' | 'mode' | 'optionLabelProp' | 'labelInValue'
'loading' | 'mode' | 'optionLabelProp' | 'labelInValue'
> {
dataSource?: DataSourceItemType[];
status?: InputStatus;
@ -141,7 +141,7 @@ const AutoComplete: React.ForwardRefRenderFunction<RefSelectProps, AutoCompleteP
return (
<Select
ref={ref}
showArrow={false}
suffixIcon={null}
{...omit(props, ['dataSource', 'dropdownClassName'])}
prefixCls={prefixCls}
popupClassName={popupClassName || dropdownClassName}

13
components/cascader/__tests__/index.test.tsx

@ -715,4 +715,17 @@ describe('Cascader', () => {
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(<Cascader showArrow />);
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();
});
});

18
components/cascader/index.tsx

@ -119,6 +119,11 @@ export type CascaderProps<DataNodeType extends BaseOptionType = any> =
UnionCascaderProps<DataNodeType> & {
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<any>, ref: React.Ref<Cas
'Cascader',
'`dropdownClassName` is deprecated. Please use `popupClassName` instead.',
);
warning(
!('showArrow' in props),
'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.',
);
}
// =================== No Found ====================
@ -267,12 +278,12 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
);
// ===================== Icons =====================
const mergedShowArrow = useShowArrow(showArrow);
const showSuffixIcon = useShowArrow(props.suffixIcon, showArrow);
const { suffixIcon, removeIcon, clearIcon } = getIcons({
...props,
hasFeedback,
feedbackIcon,
showArrow: mergedShowArrow,
showSuffixIcon,
multiple,
prefixCls,
});
@ -317,7 +328,7 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
allowClear={allowClear}
showSearch={mergedShowSearch}
expandIcon={mergedExpandIcon}
inputIcon={suffixIcon}
suffixIcon={suffixIcon}
removeIcon={removeIcon}
clearIcon={clearIcon}
loadingIcon={loadingIcon}
@ -332,7 +343,6 @@ const Cascader = React.forwardRef((props: CascaderProps<any>, ref: React.Ref<Cas
)}
getPopupContainer={getPopupContainer || getContextPopupContainer}
ref={ref}
showArrow={hasFeedback || mergedShowArrow}
/>
);

13
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(<Select showArrow />);
expect(errSpy).toHaveBeenCalledWith(
'Warning: [antd: 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.',
);
expect(container.querySelector('.ant-select-show-arrow')).toBeTruthy();
errSpy.mockRestore();
});
});
});

1
components/select/demo/custom-tag-render.tsx

@ -26,7 +26,6 @@ const tagRender = (props: CustomTagProps) => {
const App: React.FC = () => (
<Select
mode="multiple"
showArrow
tagRender={tagRender}
defaultValue={['gold', 'cyan']}
style={{ width: '100%' }}

2
components/select/demo/search-box.tsx

@ -58,7 +58,7 @@ const SearchInput: React.FC<{ placeholder: string; style: React.CSSProperties }>
placeholder={props.placeholder}
style={props.style}
defaultActiveFirstOption={false}
showArrow={false}
suffixIcon={null}
filterOption={false}
onSearch={handleSearch}
onChange={handleChange}

3
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 | `<DownOutlined />` | |
| 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\[] \| <br />number \| number\[] \| <br />LabeledValue \| LabeledValue\[] | - | |

22
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<ValueType, OptionType>,
'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}
/>,
);

3
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 | `<DownOutlined />` | |
| tagRender | 自定义 tag 内容 render,仅在 `mode``multiple``tags` 时生效 | (props) => ReactNode | - | |
| tokenSeparators | 自动分词的分隔符,仅在 `mode="tags"` 时生效 | string\[] | - | |
| value | 指定当前选中的条目,多选时为一个数组。(value 数组引用未变化时,Select 不会更新) | string \| string\[] \| <br />number \| number\[] \| <br />LabeledValue \| LabeledValue\[] | - | |

8
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;
}

21
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 ?? <CloseCircleFilled />;
// 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;

13
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(<TreeSelect showArrow />);
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();
});
});

3
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 | `<DownOutlined />` | |
| 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 | |

20
components/tree-select/index.tsx

@ -47,7 +47,6 @@ export interface TreeSelectProps<
RcTreeSelectProps<ValueType, OptionType>,
| '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 ? <span className={`${prefixCls}-tree-checkbox-inner`} /> : 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}
/>
);

3
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 | `<DownOutlined />` | |
| switcherIcon | 自定义树节点的展开/折叠图标 | ReactNode \| ((props: AntTreeNodeProps) => ReactNode) | - | renderProps: 4.20.0 |
| tagRender | 自定义 tag 内容,多选时生效 | (props) => ReactNode | - | |
| treeCheckable | 显示 Checkbox | boolean | false | |

6
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",

Loading…
Cancel
Save