Skip to content

Commit 862c9bb

Browse files
committed
feat(spinner): support spinner type
1 parent 195463e commit 862c9bb

File tree

5 files changed

+166
-24
lines changed

5 files changed

+166
-24
lines changed

assets/index.less

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,29 @@
133133
.handler-disabled();
134134
}
135135
}
136+
137+
&-type-spinner {
138+
display: inline-flex;
139+
align-items: center;
140+
}
141+
142+
&-type-spinner &-handler-wrap {
143+
flex: 0 0 20px;
144+
border-left: 0;
145+
}
146+
147+
&-type-spinner &-handler {
148+
line-height: 26px;
149+
}
150+
151+
&-type-spinner &-handler-up {
152+
border-bottom: 0;
153+
border-left: 1px solid #d9d9d9;
154+
height: 100%;
155+
}
156+
&-type-spinner &-handler-down {
157+
border-top: 0;
158+
border-right: 1px solid #d9d9d9;
159+
height: 100%;
160+
}
136161
}

docs/demo/spinner.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* eslint no-console:0 */
2+
import InputNumber from '@rc-component/input-number';
3+
import React from 'react';
4+
import '../../assets/index.less';
5+
6+
export default () => {
7+
const [disabled, setDisabled] = React.useState(false);
8+
const [readOnly, setReadOnly] = React.useState(false);
9+
const [keyboard, setKeyboard] = React.useState(true);
10+
const [wheel, setWheel] = React.useState(true);
11+
const [stringMode, setStringMode] = React.useState(false);
12+
const [value, setValue] = React.useState<string | number>(93);
13+
14+
const onChange = (val: number) => {
15+
console.warn('onChange:', val, typeof val);
16+
setValue(val);
17+
};
18+
19+
return (
20+
<div style={{ margin: 10 }}>
21+
<h3>Controlled</h3>
22+
<InputNumber
23+
type="spinner"
24+
aria-label="Simple number input example"
25+
min={-8}
26+
max={10}
27+
style={{ width: 100 }}
28+
value={value}
29+
onChange={onChange}
30+
readOnly={readOnly}
31+
disabled={disabled}
32+
keyboard={keyboard}
33+
changeOnWheel={wheel}
34+
stringMode={stringMode}
35+
/>
36+
<p>
37+
<button type="button" onClick={() => setDisabled(!disabled)}>
38+
toggle Disabled ({String(disabled)})
39+
</button>
40+
<button type="button" onClick={() => setReadOnly(!readOnly)}>
41+
toggle readOnly ({String(readOnly)})
42+
</button>
43+
<button type="button" onClick={() => setKeyboard(!keyboard)}>
44+
toggle keyboard ({String(keyboard)})
45+
</button>
46+
<button type="button" onClick={() => setStringMode(!stringMode)}>
47+
toggle stringMode ({String(stringMode)})
48+
</button>
49+
<button type="button" onClick={() => setWheel(!wheel)}>
50+
toggle wheel ({String(wheel)})
51+
</button>
52+
</p>
53+
54+
<hr />
55+
<h3>Uncontrolled</h3>
56+
<InputNumber
57+
type="spinner"
58+
style={{ width: 100 }}
59+
onChange={onChange}
60+
min={-99}
61+
max={99}
62+
defaultValue={33}
63+
/>
64+
65+
<hr />
66+
<h3>!changeOnBlur</h3>
67+
<InputNumber
68+
type="spinner"
69+
style={{ width: 100 }}
70+
min={-9}
71+
max={9}
72+
defaultValue={10}
73+
onChange={onChange}
74+
changeOnBlur={false}
75+
/>
76+
</div>
77+
);
78+
};

docs/example.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,7 @@ nav:
5252
## focus
5353

5454
<code src="./demo/focus.tsx"></code>
55+
56+
## spinner
57+
58+
<code src="./demo/spinner.tsx"></code>

src/InputNumber.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export interface InputNumberProps<T extends ValueType = ValueType>
6363
/** value will show as string */
6464
stringMode?: boolean;
6565

66+
type?: 'input' | 'spinner';
67+
6668
defaultValue?: T;
6769
value?: T | null;
6870

@@ -119,6 +121,7 @@ type InternalInputNumberProps = Omit<InputNumberProps, 'prefix' | 'suffix'> & {
119121
const InternalInputNumber = React.forwardRef(
120122
(props: InternalInputNumberProps, ref: React.Ref<HTMLInputElement>) => {
121123
const {
124+
type,
122125
prefixCls,
123126
className,
124127
style,
@@ -607,7 +610,7 @@ const InternalInputNumber = React.forwardRef(
607610
onCompositionEnd={onCompositionEnd}
608611
onBeforeInput={onBeforeInput}
609612
>
610-
{controls && (
613+
{type === 'input' && controls && (
611614
<StepHandler
612615
prefixCls={prefixCls}
613616
upNode={upHandler}
@@ -617,6 +620,17 @@ const InternalInputNumber = React.forwardRef(
617620
onStep={onInternalStep}
618621
/>
619622
)}
623+
624+
{type === 'spinner' && (
625+
<StepHandler
626+
prefixCls={prefixCls}
627+
downNode={downHandler}
628+
downDisabled={downDisabled}
629+
upHidden
630+
onStep={onInternalStep}
631+
/>
632+
)}
633+
620634
<div className={`${inputClassName}-wrap`}>
621635
<input
622636
autoComplete="off"
@@ -634,13 +648,24 @@ const InternalInputNumber = React.forwardRef(
634648
readOnly={readOnly}
635649
/>
636650
</div>
651+
652+
{type === 'spinner' && (
653+
<StepHandler
654+
prefixCls={prefixCls}
655+
upNode={upHandler}
656+
upDisabled={upDisabled}
657+
downHidden
658+
onStep={onInternalStep}
659+
/>
660+
)}
637661
</div>
638662
);
639663
},
640664
);
641665

642666
const InputNumber = React.forwardRef<InputNumberRef, InputNumberProps>((props, ref) => {
643667
const {
668+
type = 'input',
644669
disabled,
645670
style,
646671
prefixCls = 'rc-input-number',
@@ -675,7 +700,7 @@ const InputNumber = React.forwardRef<InputNumberRef, InputNumberProps>((props, r
675700
return (
676701
<SemanticContext.Provider value={memoizedValue}>
677702
<BaseInput
678-
className={className}
703+
className={clsx(`${prefixCls}-type-${type}`, className)}
679704
triggerFocus={focus}
680705
prefixCls={prefixCls}
681706
value={value}
@@ -696,6 +721,7 @@ const InputNumber = React.forwardRef<InputNumberRef, InputNumberProps>((props, r
696721
ref={holderRef}
697722
>
698723
<InternalInputNumber
724+
type={type}
699725
prefixCls={prefixCls}
700726
disabled={disabled}
701727
ref={inputFocusRef}

src/StepHandler.tsx

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ export interface StepHandlerProps {
1919
upNode?: React.ReactNode;
2020
downNode?: React.ReactNode;
2121
upDisabled?: boolean;
22+
upHidden?: boolean;
2223
downDisabled?: boolean;
24+
downHidden?: boolean;
2325
onStep: (up: boolean, emitter: 'handler' | 'keyboard' | 'wheel') => void;
2426
}
2527

@@ -29,6 +31,8 @@ export default function StepHandler({
2931
downNode,
3032
upDisabled,
3133
downDisabled,
34+
upHidden,
35+
downHidden,
3236
onStep,
3337
}: StepHandlerProps) {
3438
// ======================== Step ========================
@@ -98,28 +102,33 @@ export default function StepHandler({
98102

99103
return (
100104
<div className={clsx(`${handlerClassName}-wrap`, classNames?.actions)} style={styles?.actions}>
101-
<span
102-
{...sharedHandlerProps}
103-
onMouseDown={(e) => {
104-
onStepMouseDown(e, true);
105-
}}
106-
aria-label="Increase Value"
107-
aria-disabled={upDisabled}
108-
className={upClassName}
109-
>
110-
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
111-
</span>
112-
<span
113-
{...sharedHandlerProps}
114-
onMouseDown={(e) => {
115-
onStepMouseDown(e, false);
116-
}}
117-
aria-label="Decrease Value"
118-
aria-disabled={downDisabled}
119-
className={downClassName}
120-
>
121-
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
122-
</span>
105+
{!upHidden && (
106+
<span
107+
{...sharedHandlerProps}
108+
onMouseDown={(e) => {
109+
onStepMouseDown(e, true);
110+
}}
111+
aria-label="Increase Value"
112+
aria-disabled={upDisabled}
113+
className={upClassName}
114+
>
115+
{upNode || <span unselectable="on" className={`${prefixCls}-handler-up-inner`} />}
116+
</span>
117+
)}
118+
119+
{!downHidden && (
120+
<span
121+
{...sharedHandlerProps}
122+
onMouseDown={(e) => {
123+
onStepMouseDown(e, false);
124+
}}
125+
aria-label="Decrease Value"
126+
aria-disabled={downDisabled}
127+
className={downClassName}
128+
>
129+
{downNode || <span unselectable="on" className={`${prefixCls}-handler-down-inner`} />}
130+
</span>
131+
)}
123132
</div>
124133
);
125134
}

0 commit comments

Comments
 (0)