mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
feat(input-number): add suffix prop & change controls animation (#49674)
* feat: add suffix prop & change controls animation * feat: add opacity * refactor: calc * refactor: change file * test: change text --------- Co-authored-by: afc163 <afc163@gmail.com>
This commit is contained in:
parent
09e6ed7278
commit
10e46c107e
@ -3203,7 +3203,7 @@ exports[`renders components/input-number/demo/out-of-range.tsx extend context co
|
||||
|
||||
exports[`renders components/input-number/demo/out-of-range.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/input-number/demo/prefix.tsx extend context correctly 1`] = `
|
||||
exports[`renders components/input-number/demo/presuffix.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-input-number-affix-wrapper ant-input-number-outlined"
|
||||
@ -3490,10 +3490,95 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-input-number-affix-wrapper ant-input-number-outlined"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="ant-input-number-suffix"
|
||||
>
|
||||
RMB
|
||||
</span>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/input-number/demo/prefix.tsx extend context correctly 2`] = `[]`;
|
||||
exports[`renders components/input-number/demo/presuffix.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/input-number/demo/render-panel.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
|
@ -2911,7 +2911,7 @@ exports[`renders components/input-number/demo/out-of-range.tsx correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/input-number/demo/prefix.tsx correctly 1`] = `
|
||||
exports[`renders components/input-number/demo/presuffix.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-input-number-affix-wrapper ant-input-number-outlined"
|
||||
@ -3198,6 +3198,91 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
<br />,
|
||||
<br />,
|
||||
<div
|
||||
class="ant-input-number-affix-wrapper ant-input-number-outlined"
|
||||
style="width:100%"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="ant-input-number-suffix"
|
||||
>
|
||||
RMB
|
||||
</span>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
|
19
components/input-number/__tests__/suffix.test.tsx
Normal file
19
components/input-number/__tests__/suffix.test.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
|
||||
import InputNumber from '..';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
|
||||
describe('suffix', () => {
|
||||
it('should support suffix prop', () => {
|
||||
const { container } = render(<InputNumber suffix={<i>hello</i>} />);
|
||||
expect(container.querySelector('.ant-input-number-suffix')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should trigger focus when suffix is clicked', () => {
|
||||
const { container } = render(<InputNumber suffix={<i>antd</i>} />);
|
||||
|
||||
const mockFocus = jest.spyOn(container.querySelector('input')!, 'focus');
|
||||
fireEvent.click(container.querySelector('i')!);
|
||||
expect(mockFocus).toHaveBeenCalled();
|
||||
});
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
## zh-CN
|
||||
|
||||
在输入框上添加前缀图标。
|
||||
|
||||
## en-US
|
||||
|
||||
Add a prefix inside input.
|
7
components/input-number/demo/presuffix.md
Normal file
7
components/input-number/demo/presuffix.md
Normal file
@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
在输入框上添加前缀或后缀图标。
|
||||
|
||||
## en-US
|
||||
|
||||
Add a prefix or suffix inside input.
|
@ -11,6 +11,9 @@ const App: React.FC = () => (
|
||||
<br />
|
||||
<br />
|
||||
<InputNumber prefix="¥" disabled style={{ width: '100%' }} />
|
||||
<br />
|
||||
<br />
|
||||
<InputNumber suffix="RMB" style={{ width: '100%' }} />
|
||||
</>
|
||||
);
|
||||
|
@ -27,7 +27,7 @@ When a numeric value needs to be provided.
|
||||
<code src="./demo/variant.tsx" version="5.13.0">Variants</code>
|
||||
<code src="./demo/filled-debug.tsx" debug>Filled Debug</code>
|
||||
<code src="./demo/out-of-range.tsx">Out of range</code>
|
||||
<code src="./demo/prefix.tsx">Prefix</code>
|
||||
<code src="./demo/presuffix.tsx">Prefix / Suffix</code>
|
||||
<code src="./demo/status.tsx">Status</code>
|
||||
<code src="./demo/controls.tsx" debug>Icon</code>
|
||||
<code src="./demo/render-panel.tsx" debug>_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||
@ -58,6 +58,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| readOnly | If readonly the input | boolean | false | - |
|
||||
| status | Set validation status | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| prefix | The prefix icon for the Input | ReactNode | - | 4.17.0 |
|
||||
| suffix | The suffix icon for the Input | ReactNode | - | 5.20.0 |
|
||||
| size | The height of input box | `large` \| `middle` \| `small` | - | - |
|
||||
| step | The number to which the current value is increased or decreased. It can be an integer or decimal | number \| string | 1 | - |
|
||||
| stringMode | Set value as string to support high precision decimals. Will return string value by `onChange` | boolean | false | 4.13.0 |
|
||||
|
@ -27,6 +27,7 @@ export interface InputNumberProps<T extends ValueType = ValueType>
|
||||
addonBefore?: React.ReactNode;
|
||||
addonAfter?: React.ReactNode;
|
||||
prefix?: React.ReactNode;
|
||||
suffix?: React.ReactNode;
|
||||
size?: SizeType;
|
||||
disabled?: boolean;
|
||||
/** @deprecated Use `variant` instead. */
|
||||
@ -66,6 +67,7 @@ const InputNumber = React.forwardRef<HTMLInputElement, InputNumberProps>((props,
|
||||
addonBefore,
|
||||
addonAfter,
|
||||
prefix,
|
||||
suffix,
|
||||
bordered,
|
||||
readOnly,
|
||||
status: customStatus,
|
||||
@ -141,7 +143,7 @@ const InputNumber = React.forwardRef<HTMLInputElement, InputNumberProps>((props,
|
||||
readOnly={readOnly}
|
||||
controls={controlsTemp}
|
||||
prefix={prefix}
|
||||
suffix={suffixNode}
|
||||
suffix={suffixNode || suffix}
|
||||
addonBefore={
|
||||
addonBefore && (
|
||||
<ContextIsolator form space>
|
||||
|
@ -28,7 +28,7 @@ demo:
|
||||
<code src="./demo/variant.tsx" version="5.13.0">形态变体</code>
|
||||
<code src="./demo/filled-debug.tsx" debug>Filled Debug</code>
|
||||
<code src="./demo/out-of-range.tsx">超出边界</code>
|
||||
<code src="./demo/prefix.tsx">前缀</code>
|
||||
<code src="./demo/presuffix.tsx">前缀/后缀</code>
|
||||
<code src="./demo/status.tsx">自定义状态</code>
|
||||
<code src="./demo/controls.tsx" debug>图标按钮</code>
|
||||
<code src="./demo/render-panel.tsx" debug>_InternalPanelDoNotUseOrYouWillBeFired</code>
|
||||
@ -59,6 +59,7 @@ demo:
|
||||
| readOnly | 只读 | boolean | false | - |
|
||||
| status | 设置校验状态 | 'error' \| 'warning' | - | 4.19.0 |
|
||||
| prefix | 带有前缀图标的 input | ReactNode | - | 4.17.0 |
|
||||
| suffix | 带有后缀图标的 input | ReactNode | - | 5.20.0 |
|
||||
| size | 输入框大小 | `large` \| `middle` \| `small` | - | - |
|
||||
| step | 每次改变步数,可以为小数 | number \| string | 1 | - |
|
||||
| stringMode | 字符值模式,开启后支持高精度小数。同时 `onChange` 将返回 string 类型 | boolean | false | 4.13.0 |
|
||||
|
@ -61,6 +61,7 @@ const genInputNumberStyles: GenerateStyle<InputNumberToken> = (token: InputNumbe
|
||||
colorTextDescription,
|
||||
motionDurationMid,
|
||||
handleHoverColor,
|
||||
handleOpacity,
|
||||
paddingInline,
|
||||
paddingBlock,
|
||||
handleBg,
|
||||
@ -69,7 +70,6 @@ const genInputNumberStyles: GenerateStyle<InputNumberToken> = (token: InputNumbe
|
||||
borderRadiusSM,
|
||||
borderRadiusLG,
|
||||
controlWidth,
|
||||
handleOpacity,
|
||||
handleBorderColor,
|
||||
filledHandleBg,
|
||||
lineHeightLG,
|
||||
@ -236,31 +236,32 @@ const genInputNumberStyles: GenerateStyle<InputNumberToken> = (token: InputNumbe
|
||||
},
|
||||
},
|
||||
},
|
||||
[`&:hover ${componentCls}-handler-wrap, &-focused ${componentCls}-handler-wrap`]: {
|
||||
width: token.handleWidth,
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Handler
|
||||
{
|
||||
[componentCls]: {
|
||||
[`&:hover ${componentCls}-handler-wrap, &-focused ${componentCls}-handler-wrap`]: {
|
||||
opacity: 1,
|
||||
},
|
||||
|
||||
[`${componentCls}-handler-wrap`]: {
|
||||
position: 'absolute',
|
||||
insetBlockStart: 0,
|
||||
insetInlineEnd: 0,
|
||||
width: token.handleWidth,
|
||||
width: 0,
|
||||
opacity: handleOpacity,
|
||||
height: '100%',
|
||||
borderStartStartRadius: 0,
|
||||
borderStartEndRadius: borderRadius,
|
||||
borderEndEndRadius: borderRadius,
|
||||
borderEndStartRadius: 0,
|
||||
opacity: handleOpacity,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'stretch',
|
||||
transition: `opacity ${motionDurationMid} linear ${motionDurationMid}`,
|
||||
transition: `all ${motionDurationMid}`,
|
||||
overflow: 'hidden',
|
||||
|
||||
// Fix input number inside Menu makes icon too large
|
||||
// We arise the selector priority by nest selector here
|
||||
@ -370,6 +371,7 @@ const genAffixWrapperStyles: GenerateStyle<InputNumberToken> = (token: InputNumb
|
||||
paddingInlineSM,
|
||||
paddingBlockLG,
|
||||
paddingBlockSM,
|
||||
motionDurationMid,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
@ -382,6 +384,7 @@ const genAffixWrapperStyles: GenerateStyle<InputNumberToken> = (token: InputNumb
|
||||
// or number handler will cover form status
|
||||
position: 'relative',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
width: controlWidth,
|
||||
padding: 0,
|
||||
paddingInlineStart: paddingInline,
|
||||
@ -438,6 +441,7 @@ const genAffixWrapperStyles: GenerateStyle<InputNumberToken> = (token: InputNumb
|
||||
},
|
||||
|
||||
[componentCls]: {
|
||||
position: 'static',
|
||||
color: 'inherit',
|
||||
|
||||
'&-prefix, &-suffix': {
|
||||
@ -452,15 +456,22 @@ const genAffixWrapperStyles: GenerateStyle<InputNumberToken> = (token: InputNumb
|
||||
},
|
||||
|
||||
'&-suffix': {
|
||||
position: 'absolute',
|
||||
insetBlockStart: 0,
|
||||
insetInlineEnd: 0,
|
||||
zIndex: 1,
|
||||
height: '100%',
|
||||
marginInlineEnd: paddingInline,
|
||||
marginInlineStart: inputAffixPadding,
|
||||
transition: `margin ${motionDurationMid}`,
|
||||
},
|
||||
},
|
||||
|
||||
[`&:hover ${componentCls}-handler-wrap, &-focused ${componentCls}-handler-wrap`]: {
|
||||
width: token.handleWidth,
|
||||
opacity: 1,
|
||||
},
|
||||
[`&:hover ${componentCls}-suffix`]: {
|
||||
marginInlineEnd: token.calc(token.handleWidth).add(paddingInline).equal(),
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user