diff --git a/src/packages/inputnumber/demo.scss b/src/packages/inputnumber/demo.scss
new file mode 100644
index 0000000000..870bd6de47
--- /dev/null
+++ b/src/packages/inputnumber/demo.scss
@@ -0,0 +1,6 @@
+.format-width {
+ input,
+ .nut-number-input {
+ --nutui-inputnumber-input-width: 60px;
+ }
+}
diff --git a/src/packages/inputnumber/demo.tsx b/src/packages/inputnumber/demo.tsx
index 5cfac27a54..4f21636843 100644
--- a/src/packages/inputnumber/demo.tsx
+++ b/src/packages/inputnumber/demo.tsx
@@ -4,6 +4,7 @@ import { InputNumber } from './inputnumber'
import ConfigProvider from '@/packages/configprovider'
import Cell from '@/packages/cell'
import Toast from '@/packages/toast'
+import './demo.scss'
interface ValState {
val1: number | string
@@ -29,6 +30,7 @@ interface T {
'3a42134b': string
'65bafb1d': string
'7e2394ae': string
+ '7e2394be': string
}
const customTheme = {
@@ -63,6 +65,7 @@ const InputNumberDemo = () => {
'3a42134b': '支持小数点',
'65bafb1d': '支持异步修改',
'7e2394ae': '自定义按钮大小',
+ '7e2394be': '支持formatter',
},
'zh-TW': {
'6333c786': '超出限制事件觸發',
@@ -77,6 +80,7 @@ const InputNumberDemo = () => {
'3a42134b': '支持小數點',
'65bafb1d': '支持異步修改',
'7e2394ae': '自定義按鈕大小',
+ '7e2394be': '支持formatter',
},
'en-US': {
'6333c786': 'Exceeded limit event triggered',
@@ -91,6 +95,7 @@ const InputNumberDemo = () => {
'3a42134b': 'support decimal point',
'65bafb1d': 'Support for asynchronous modification',
'7e2394ae': 'custom button size',
+ '7e2394be': 'support formatter',
},
})
@@ -181,6 +186,28 @@ const InputNumberDemo = () => {
inputWidth="50"
/>
+
+
支持formatter
+
+
+ `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
+ }
+ />
+ |
+
+ `${value}%`}
+ />
+ |
>
)
diff --git a/src/packages/inputnumber/doc.en-US.md b/src/packages/inputnumber/doc.en-US.md
index 6a4af959ec..4d4c056ce4 100644
--- a/src/packages/inputnumber/doc.en-US.md
+++ b/src/packages/inputnumber/doc.en-US.md
@@ -204,6 +204,39 @@ export default App;
```
:::
+### support formatter
+
+:::demo
+```tsx
+import React from "react";
+import { InputNumber } from '@nutui/nutui-react';
+
+const App = () => {
+ return (
+ <>
+
+ `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
+ }
+ />
+ `${value}%`}
+ />
+ >
+ )
+}
+export default App;
+```
+:::
+
## API
### Props
@@ -220,6 +253,7 @@ export default App;
| disabled | Disable all features | boolean | `false` |
| readonly | Read only status disables input box operation behavior | boolean | `false` |
| isAsync | Support for asynchronous modification | boolean | `false` |
+| formatter`v1.4.14` | Specifies the format of the value displayed in the input box | function(value: number | string): string | - |
### Events
diff --git a/src/packages/inputnumber/doc.md b/src/packages/inputnumber/doc.md
index 6f25f5c051..4f8f456eba 100644
--- a/src/packages/inputnumber/doc.md
+++ b/src/packages/inputnumber/doc.md
@@ -249,6 +249,39 @@ export default App;
```
:::
+### 支持formatter
+
+:::demo
+```tsx
+import React from "react";
+import { InputNumber } from '@nutui/nutui-react';
+
+const App = () => {
+ return (
+ <>
+
+ `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
+ }
+ />
+ `${value}%`}
+ />
+ >
+ )
+}
+export default App;
+```
+:::
+
## API
### Props
@@ -265,6 +298,7 @@ export default App;
| disabled | 禁用所有功能 | boolean | `false` |
| readonly | 只读状态禁用输入框操作行为 | boolean | `false` |
| isAsync | 支持异步修改 | boolean | `false` |
+| formatter`v1.4.14` | 指定输入框展示值的格式 | function(value: number | string): string | - |
### Events
diff --git a/src/packages/inputnumber/inputnumber.tsx b/src/packages/inputnumber/inputnumber.tsx
index 6ac1f9f4f8..b034247495 100644
--- a/src/packages/inputnumber/inputnumber.tsx
+++ b/src/packages/inputnumber/inputnumber.tsx
@@ -1,6 +1,7 @@
import React, {
useState,
useEffect,
+ useRef,
FunctionComponent,
ChangeEvent,
FocusEvent,
@@ -24,6 +25,7 @@ export interface InputNumberProps extends BasicComponent {
isAsync: boolean
className: string
style: React.CSSProperties
+ formatter?: (displayValue: string | number) => string
add: (e: MouseEvent) => void
reduce: (e: MouseEvent) => void
overlimit: (e: MouseEvent) => void
@@ -77,6 +79,7 @@ export const InputNumber: FunctionComponent<
isAsync,
className,
style,
+ formatter,
add,
reduce,
change,
@@ -97,9 +100,15 @@ export const InputNumber: FunctionComponent<
...props,
}
const [inputValue, setInputValue] = useState(modelValue)
+ const inputRef = useRef('')
useEffect(() => {
- setInputValue(modelValue)
- }, [modelValue])
+ if (formatter) {
+ inputRef.current = formatter(modelValue)
+ setInputValue(formatter(modelValue))
+ } else {
+ setInputValue(modelValue)
+ }
+ }, [modelValue, formatter])
const b = bem('inputnumber')
const classes = classNames(
@@ -114,6 +123,10 @@ export const InputNumber: FunctionComponent<
...style,
}
const addAllow = (value = inputValue) => {
+ if (formatter) {
+ const numValue = String(value).replace(/[^0-9|\.]/gi, '')
+ return Number(numValue) < Number(max) && !disabled
+ }
if (value || typeof value === 'number') {
return value < Number(max) && !disabled
}
@@ -121,6 +134,10 @@ export const InputNumber: FunctionComponent<
}
const reduceAllow = (value = inputValue) => {
+ if (formatter) {
+ const numValue = String(value).replace(/[^0-9|\.]/gi, '')
+ return Number(numValue) > Number(min) && !disabled
+ }
if (value || typeof value === 'number') {
return value > Number(min) && !disabled
}
@@ -148,11 +165,17 @@ export const InputNumber: FunctionComponent<
change && change(outputValue, e)
if (!isAsync) {
if (Number(outputValue) < Number(min)) {
- setInputValue(Number(min))
+ formatter
+ ? setInputValue(formatter(Number(min)))
+ : setInputValue(Number(min))
} else if (Number(outputValue) > Number(max)) {
- setInputValue(Number(max))
+ formatter
+ ? setInputValue(formatter(Number(max)))
+ : setInputValue(Number(max))
} else {
- setInputValue(outputValue)
+ formatter
+ ? setInputValue(formatter(outputValue))
+ : setInputValue(outputValue)
}
}
}
@@ -161,8 +184,15 @@ export const InputNumber: FunctionComponent<
onReduce && onReduce(e)
reduce && reduce(e)
if (reduceAllow()) {
- const outputValue = Number(inputValue) - Number(step)
- emitChange(outputValue, e)
+ if (formatter) {
+ const numValue = String(inputValue).replace(/[^0-9|\.]/gi, '')
+ const outputValue = Number(numValue) - Number(step)
+ inputRef.current = formatter(outputValue)
+ emitChange(outputValue, e)
+ } else {
+ const outputValue = Number(inputValue) - Number(step)
+ emitChange(outputValue, e)
+ }
} else {
onOverlimit && onOverlimit(e)
overlimit && overlimit(e)
@@ -173,8 +203,15 @@ export const InputNumber: FunctionComponent<
onAdd && onAdd(e)
add && add(e)
if (addAllow()) {
- const outputValue = Number(inputValue) + Number(step)
- emitChange(outputValue, e)
+ if (formatter) {
+ const numValue = String(inputValue).replace(/[^0-9|\.]/gi, '')
+ const outputValue = Number(numValue) + Number(step)
+ inputRef.current = formatter(outputValue)
+ emitChange(outputValue, e)
+ } else {
+ const outputValue = Number(inputValue) + Number(step)
+ emitChange(outputValue, e)
+ }
} else {
onOverlimit && onOverlimit(e)
overlimit && overlimit(e)
@@ -194,6 +231,48 @@ export const InputNumber: FunctionComponent<
}
}
+ const changeFormatValue = (e: ChangeEvent) => {
+ const input = e.target.value
+
+ const numReg = new RegExp('^[0-9]*$')
+ const numValue = input.replace(/[^0-9|\.]/gi, '')
+
+ if (formatter) {
+ if (!numReg.test(input[0]) && numValue) {
+ setInputValue(formatter(numValue))
+ } else if (!numReg.test(input[0]) && !numValue) {
+ setInputValue(input)
+ } else if (numReg.test(input[0])) {
+ console.log('inputRef.current', inputRef.current)
+ console.log('formatter(numValue)', formatter(numValue))
+
+ // 针对于100%这种尾字符例子,直接删除会进行匹配
+ if (formatter(numValue) === inputRef.current) {
+ setInputValue(numValue)
+ } else {
+ setInputValue(formatter(numValue))
+ inputRef.current = formatter(numValue)
+ }
+ }
+ }
+ }
+
+ const burFormatValue = (e: ChangeEvent) => {
+ const input = e.target.value
+
+ const numReg = new RegExp('^[0-9]*$')
+ const numValue = input.replace(/[^0-9|\.]/gi, '')
+ if (formatter) {
+ if (formatter(numValue) === input) {
+ emitChange(numValue, e)
+ return
+ }
+ if (!numReg.test(input) || !input) {
+ setInputValue(formatter(''))
+ }
+ }
+ }
+
const focusValue = (e: FocusEvent) => {
if (disabled) return
if (readonly) return
@@ -227,18 +306,35 @@ export const InputNumber: FunctionComponent<
onClick={reduceNumber}
/>
-
+ <>
+ {formatter ? (
+
+ ) : (
+
+ )}
+ >