Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,29 @@
.handler-disabled();
}
}

&-type-spinner {
display: inline-flex;
align-items: center;
}

&-type-spinner &-handler-wrap {
flex: 0 0 20px;
border-left: 0;
}

&-type-spinner &-handler {
line-height: 26px;
}

&-type-spinner &-handler-up {
border-bottom: 0;
border-left: 1px solid #d9d9d9;
height: 100%;
}
&-type-spinner &-handler-down {
border-top: 0;
border-right: 1px solid #d9d9d9;
height: 100%;
}
}
78 changes: 78 additions & 0 deletions docs/demo/spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* eslint no-console:0 */
import InputNumber from '@rc-component/input-number';
import React from 'react';
import '../../assets/index.less';

export default () => {
const [disabled, setDisabled] = React.useState(false);
const [readOnly, setReadOnly] = React.useState(false);
const [keyboard, setKeyboard] = React.useState(true);
const [wheel, setWheel] = React.useState(true);
const [stringMode, setStringMode] = React.useState(false);
const [value, setValue] = React.useState<string | number>(93);

const onChange = (val: number) => {
console.warn('onChange:', val, typeof val);
setValue(val);
};

return (
<div style={{ margin: 10 }}>
<h3>Controlled</h3>
<InputNumber
type="spinner"
aria-label="Simple number input example"
min={-8}
max={10}
style={{ width: 100 }}
value={value}
onChange={onChange}
readOnly={readOnly}
disabled={disabled}
keyboard={keyboard}
changeOnWheel={wheel}
stringMode={stringMode}
/>
<p>
<button type="button" onClick={() => setDisabled(!disabled)}>
toggle Disabled ({String(disabled)})
</button>
<button type="button" onClick={() => setReadOnly(!readOnly)}>
toggle readOnly ({String(readOnly)})
</button>
<button type="button" onClick={() => setKeyboard(!keyboard)}>
toggle keyboard ({String(keyboard)})
</button>
<button type="button" onClick={() => setStringMode(!stringMode)}>
toggle stringMode ({String(stringMode)})
</button>
<button type="button" onClick={() => setWheel(!wheel)}>
toggle wheel ({String(wheel)})
</button>
</p>

<hr />
<h3>Uncontrolled</h3>
<InputNumber
type="spinner"
style={{ width: 100 }}
onChange={onChange}
min={-99}
max={99}
defaultValue={33}
/>

<hr />
<h3>!changeOnBlur</h3>
<InputNumber
type="spinner"
style={{ width: 100 }}
min={-9}
max={9}
defaultValue={10}
onChange={onChange}
changeOnBlur={false}
/>
</div>
);
};
4 changes: 4 additions & 0 deletions docs/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ nav:
## focus

<code src="./demo/focus.tsx"></code>

## spinner

<code src="./demo/spinner.tsx"></code>
30 changes: 28 additions & 2 deletions src/InputNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export interface InputNumberProps<T extends ValueType = ValueType>
/** value will show as string */
stringMode?: boolean;

type?: 'input' | 'spinner';

defaultValue?: T;
value?: T | null;

Expand Down Expand Up @@ -119,6 +121,7 @@ type InternalInputNumberProps = Omit<InputNumberProps, 'prefix' | 'suffix'> & {
const InternalInputNumber = React.forwardRef(
(props: InternalInputNumberProps, ref: React.Ref<HTMLInputElement>) => {
const {
type,
prefixCls,
className,
style,
Expand Down Expand Up @@ -607,7 +610,7 @@ const InternalInputNumber = React.forwardRef(
onCompositionEnd={onCompositionEnd}
onBeforeInput={onBeforeInput}
>
{controls && (
{type === 'input' && controls && (
<StepHandler
prefixCls={prefixCls}
upNode={upHandler}
Expand All @@ -617,6 +620,17 @@ const InternalInputNumber = React.forwardRef(
onStep={onInternalStep}
/>
)}

{type === 'spinner' && controls && (
<StepHandler
prefixCls={prefixCls}
downNode={downHandler}
downDisabled={downDisabled}
upHidden
onStep={onInternalStep}
/>
)}

<div className={`${inputClassName}-wrap`}>
<input
autoComplete="off"
Expand All @@ -634,13 +648,24 @@ const InternalInputNumber = React.forwardRef(
readOnly={readOnly}
/>
</div>

{type === 'spinner' && controls && (
<StepHandler
prefixCls={prefixCls}
upNode={upHandler}
upDisabled={upDisabled}
downHidden
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

耦合度有点太高了,StepHandler 单独拆一个子组件出来消费吧

onStep={onInternalStep}
/>
)}
</div>
);
},
);

const InputNumber = React.forwardRef<InputNumberRef, InputNumberProps>((props, ref) => {
const {
type = 'input',
disabled,
style,
prefixCls = 'rc-input-number',
Expand Down Expand Up @@ -675,7 +700,7 @@ const InputNumber = React.forwardRef<InputNumberRef, InputNumberProps>((props, r
return (
<SemanticContext.Provider value={memoizedValue}>
<BaseInput
className={className}
className={clsx(`${prefixCls}-type-${type}`, className)}
triggerFocus={focus}
prefixCls={prefixCls}
value={value}
Expand All @@ -696,6 +721,7 @@ const InputNumber = React.forwardRef<InputNumberRef, InputNumberProps>((props, r
ref={holderRef}
>
<InternalInputNumber
type={type}
prefixCls={prefixCls}
disabled={disabled}
ref={inputFocusRef}
Expand Down
53 changes: 31 additions & 22 deletions src/StepHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export interface StepHandlerProps {
upNode?: React.ReactNode;
downNode?: React.ReactNode;
upDisabled?: boolean;
upHidden?: boolean;
downDisabled?: boolean;
downHidden?: boolean;
onStep: (up: boolean, emitter: 'handler' | 'keyboard' | 'wheel') => void;
}

Expand All @@ -29,6 +31,8 @@ export default function StepHandler({
downNode,
upDisabled,
downDisabled,
upHidden,
downHidden,
onStep,
}: StepHandlerProps) {
// ======================== Step ========================
Expand Down Expand Up @@ -98,28 +102,33 @@ export default function StepHandler({

return (
<div className={clsx(`${handlerClassName}-wrap`, classNames?.actions)} style={styles?.actions}>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, true);
}}
aria-label="Increase Value"
aria-disabled={upDisabled}
className={upClassName}
>
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
</span>
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, false);
}}
aria-label="Decrease Value"
aria-disabled={downDisabled}
className={downClassName}
>
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
</span>
{!upHidden && (
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, true);
}}
aria-label="Increase Value"
aria-disabled={upDisabled}
className={upClassName}
>
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
</span>
)}

{!downHidden && (
<span
{...sharedHandlerProps}
onMouseDown={(e) => {
onStepMouseDown(e, false);
}}
aria-label="Decrease Value"
aria-disabled={downDisabled}
className={downClassName}
>
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
</span>
)}
</div>
);
}
6 changes: 3 additions & 3 deletions tests/__snapshots__/baseInput.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports[`baseInput addon should render properly 1`] = `
<div>
<div>
<div
class="rc-input-group-wrapper"
class="rc-input-group-wrapper rc-input-type-input"
>
<div
class="rc-input-wrapper rc-input-group"
Expand Down Expand Up @@ -64,7 +64,7 @@ exports[`baseInput addon should render properly 1`] = `
<br />
<br />
<div
class="rc-input-group-wrapper"
class="rc-input-group-wrapper rc-input-type-input"
>
<div
class="rc-input-wrapper rc-input-group"
Expand Down Expand Up @@ -128,7 +128,7 @@ exports[`baseInput addon should render properly 1`] = `
exports[`baseInput prefix should render properly 1`] = `
<div>
<div
class="rc-input-affix-wrapper"
class="rc-input-affix-wrapper rc-input-type-input"
>
<span
class="rc-input-prefix"
Expand Down