papayaui 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -91,7 +91,7 @@ const onInput = (e: Event) => {
91
91
  let value = (e as unknown as EventDetail<{ value: string }>).detail.value
92
92
  // 数值类型处理,整数或小数
93
93
  if (props.type === 'number') {
94
- value = formatNumericTypeString(value, props.intLength, props.decimalLength)
94
+ value = formatNumericTypeString(value, props.intLength, props.decimalLength, props.allowNegative)
95
95
  }
96
96
  // 格式化函数处理
97
97
  if (typeof props.formatter === 'function') {
@@ -22,6 +22,10 @@ const inputNumberProps = {
22
22
  * 小数位长度
23
23
  */
24
24
  decimalLength: Number,
25
+ /**
26
+ * 是否允许输入负数
27
+ */
28
+ allowNegative: Boolean,
25
29
  }
26
30
 
27
31
  export const inputProps = {
@@ -0,0 +1,306 @@
1
+ import { describe, test, expect } from 'vitest'
2
+ import { formatNumericTypeString, minAndMax, useInputNumber } from '.'
3
+
4
+ describe('formatNumericTypeString', () => {
5
+ test('should format basic numbers correctly', () => {
6
+ expect(formatNumericTypeString('123')).toBe('123')
7
+ expect(formatNumericTypeString('123.45')).toBe('123')
8
+ expect(formatNumericTypeString('abc123')).toBe('123')
9
+ expect(formatNumericTypeString('12.34.56', Number.MAX_SAFE_INTEGER.toString().length, 2)).toBe(
10
+ '12.34',
11
+ )
12
+ })
13
+
14
+ test('should format numbers with decimal length', () => {
15
+ expect(formatNumericTypeString('123.456', Number.MAX_SAFE_INTEGER.toString().length, 2)).toBe(
16
+ '123.45',
17
+ )
18
+ expect(formatNumericTypeString('123.4', Number.MAX_SAFE_INTEGER.toString().length, 2)).toBe(
19
+ '123.4',
20
+ )
21
+ expect(formatNumericTypeString('123', Number.MAX_SAFE_INTEGER.toString().length, 2)).toBe('123')
22
+ expect(
23
+ formatNumericTypeString('123.123456', Number.MAX_SAFE_INTEGER.toString().length, 3),
24
+ ).toBe('123.123')
25
+ })
26
+
27
+ test('should format numbers with integer length limit', () => {
28
+ expect(formatNumericTypeString('123456', 3)).toBe('123')
29
+ expect(formatNumericTypeString('12', 3)).toBe('12')
30
+ expect(formatNumericTypeString('1234.56', 3, 2)).toBe('123.56')
31
+ })
32
+
33
+ test('should remove leading dot', () => {
34
+ expect(formatNumericTypeString('.123')).toBe('123')
35
+ expect(formatNumericTypeString('.123', Number.MAX_SAFE_INTEGER.toString().length, 2)).toBe(
36
+ '123',
37
+ )
38
+ })
39
+
40
+ test('should handle negative numbers when allowNegative is true', () => {
41
+ expect(
42
+ formatNumericTypeString('-123', Number.MAX_SAFE_INTEGER.toString().length, 0, true),
43
+ ).toBe('-123')
44
+ expect(
45
+ formatNumericTypeString('-123.45', Number.MAX_SAFE_INTEGER.toString().length, 2, true),
46
+ ).toBe('-123.45')
47
+ expect(
48
+ formatNumericTypeString('-123.456', Number.MAX_SAFE_INTEGER.toString().length, 2, true),
49
+ ).toBe('-123.45')
50
+ expect(
51
+ formatNumericTypeString('-0.5', Number.MAX_SAFE_INTEGER.toString().length, 2, true),
52
+ ).toBe('-0.5')
53
+ })
54
+
55
+ test('should remove negative sign when allowNegative is false', () => {
56
+ expect(
57
+ formatNumericTypeString('-123', Number.MAX_SAFE_INTEGER.toString().length, 0, false),
58
+ ).toBe('123')
59
+ expect(
60
+ formatNumericTypeString('-123.45', Number.MAX_SAFE_INTEGER.toString().length, 2, false),
61
+ ).toBe('123.45')
62
+ })
63
+
64
+ test('should handle negative numbers with integer length limit', () => {
65
+ expect(formatNumericTypeString('-123456', 3, 0, true)).toBe('-123')
66
+ expect(formatNumericTypeString('-12', 3, 0, true)).toBe('-12')
67
+ expect(formatNumericTypeString('-1234.56', 3, 2, true)).toBe('-123.56')
68
+ })
69
+
70
+ test('should handle multiple negative signs correctly', () => {
71
+ expect(
72
+ formatNumericTypeString('--123', Number.MAX_SAFE_INTEGER.toString().length, 0, true),
73
+ ).toBe('-123')
74
+ expect(
75
+ formatNumericTypeString('-12-3', Number.MAX_SAFE_INTEGER.toString().length, 0, true),
76
+ ).toBe('-123')
77
+ expect(
78
+ formatNumericTypeString('1-23', Number.MAX_SAFE_INTEGER.toString().length, 0, true),
79
+ ).toBe('123')
80
+ })
81
+
82
+ test('should handle edge cases', () => {
83
+ expect(formatNumericTypeString('')).toBe('')
84
+ expect(formatNumericTypeString('0')).toBe('0')
85
+ expect(formatNumericTypeString('-0', Number.MAX_SAFE_INTEGER.toString().length, 0, true)).toBe(
86
+ '-0',
87
+ )
88
+ expect(formatNumericTypeString('abc')).toBe('')
89
+ expect(formatNumericTypeString('-', Number.MAX_SAFE_INTEGER.toString().length, 0, true)).toBe(
90
+ '-',
91
+ )
92
+ })
93
+ })
94
+
95
+ describe('minAndMax', () => {
96
+ test('should limit value by min', () => {
97
+ expect(minAndMax(5, 10)).toBe(10)
98
+ expect(minAndMax(10, 10)).toBe(10)
99
+ expect(minAndMax(15, 10)).toBe(15)
100
+ })
101
+
102
+ test('should limit value by max', () => {
103
+ expect(minAndMax(5, undefined, 10)).toBe(5)
104
+ expect(minAndMax(10, undefined, 10)).toBe(10)
105
+ expect(minAndMax(15, undefined, 10)).toBe(10)
106
+ })
107
+
108
+ test('should limit value by both min and max', () => {
109
+ expect(minAndMax(5, 10, 20)).toBe(10)
110
+ expect(minAndMax(15, 10, 20)).toBe(15)
111
+ expect(minAndMax(25, 10, 20)).toBe(20)
112
+ })
113
+
114
+ test('should handle negative min and max', () => {
115
+ expect(minAndMax(-15, -10, 10)).toBe(-10)
116
+ expect(minAndMax(-5, -10, 10)).toBe(-5)
117
+ expect(minAndMax(15, -10, 10)).toBe(10)
118
+ expect(minAndMax(-20, -10)).toBe(-10)
119
+ })
120
+
121
+ test('should return value when no limits provided', () => {
122
+ expect(minAndMax(5)).toBe(5)
123
+ expect(minAndMax(-5)).toBe(-5)
124
+ expect(minAndMax(0)).toBe(0)
125
+ })
126
+ })
127
+
128
+ describe('useInputNumber', () => {
129
+ test('should initialize with default values', () => {
130
+ const { numberVal, safeNumberVal } = useInputNumber({})
131
+
132
+ expect(numberVal.value).toBe(0)
133
+ expect(safeNumberVal.value).toBe(0)
134
+ })
135
+
136
+ test('should initialize with provided modelValue', () => {
137
+ const { numberVal, safeNumberVal } = useInputNumber({ modelValue: 10 })
138
+
139
+ expect(numberVal.value).toBe(10)
140
+ expect(safeNumberVal.value).toBe(10)
141
+ })
142
+
143
+ test('should initialize with string modelValue', () => {
144
+ const { numberVal, safeNumberVal } = useInputNumber({ modelValue: '25' })
145
+
146
+ expect(numberVal.value).toBe(25)
147
+ expect(safeNumberVal.value).toBe(25)
148
+ })
149
+
150
+ test('should handle negative modelValue', () => {
151
+ const { numberVal, safeNumberVal } = useInputNumber({ modelValue: -10, allowNegative: true })
152
+
153
+ expect(numberVal.value).toBe(-10)
154
+ expect(safeNumberVal.value).toBe(-10)
155
+ })
156
+
157
+ test('should add value correctly', () => {
158
+ const { numberVal, onAdd } = useInputNumber({ modelValue: 5, step: 2 })
159
+
160
+ expect(numberVal.value).toBe(5)
161
+ const newVal = onAdd()
162
+ expect(newVal).toBe(7)
163
+ expect(numberVal.value).toBe(7)
164
+ })
165
+
166
+ test('should reduce value correctly', () => {
167
+ const { numberVal, onReduce } = useInputNumber({ modelValue: 10, step: 3 })
168
+
169
+ expect(numberVal.value).toBe(10)
170
+ const newVal = onReduce()
171
+ expect(newVal).toBe(7)
172
+ expect(numberVal.value).toBe(7)
173
+ })
174
+
175
+ test('should reduce to negative value when allowNegative is true', () => {
176
+ const { numberVal, onReduce } = useInputNumber({
177
+ modelValue: 5,
178
+ step: 10,
179
+ min: -20,
180
+ allowNegative: true,
181
+ })
182
+
183
+ expect(numberVal.value).toBe(5)
184
+ const newVal = onReduce()
185
+ expect(newVal).toBe(-5)
186
+ expect(numberVal.value).toBe(-5)
187
+ })
188
+
189
+ test('should respect min limit', () => {
190
+ const { numberVal, onReduce } = useInputNumber({ modelValue: 5, step: 10, min: 0 })
191
+
192
+ expect(numberVal.value).toBe(5)
193
+ const newVal = onReduce()
194
+ expect(newVal).toBe(0)
195
+ expect(numberVal.value).toBe(0)
196
+ })
197
+
198
+ test('should respect max limit', () => {
199
+ const { numberVal, onAdd } = useInputNumber({ modelValue: 15, step: 10, max: 20 })
200
+
201
+ expect(numberVal.value).toBe(15)
202
+ const newVal = onAdd()
203
+ expect(newVal).toBe(20)
204
+ expect(numberVal.value).toBe(20)
205
+ })
206
+
207
+ test('should format decimal correctly', () => {
208
+ const { numberVal, onAdd } = useInputNumber({
209
+ modelValue: 0,
210
+ step: 0.1,
211
+ decimalLength: 2,
212
+ min: 0,
213
+ })
214
+
215
+ expect(numberVal.value).toBe(0)
216
+ onAdd()
217
+ expect(numberVal.value).toBe(0.1)
218
+ onAdd()
219
+ expect(numberVal.value).toBe(0.2)
220
+ })
221
+
222
+ test('should format value string correctly', () => {
223
+ const { getFormatVal } = useInputNumber({ intLength: 3, decimalLength: 2 })
224
+
225
+ expect(getFormatVal('123.456')).toBe('123.45')
226
+ expect(getFormatVal('1234.56')).toBe('123.56')
227
+ expect(getFormatVal('12.3')).toBe('12.3')
228
+ })
229
+
230
+ test('should format negative value string when allowNegative is true', () => {
231
+ const { getFormatVal } = useInputNumber({
232
+ intLength: 3,
233
+ decimalLength: 2,
234
+ allowNegative: true,
235
+ })
236
+
237
+ expect(getFormatVal('-123.456')).toBe('-123.45')
238
+ expect(getFormatVal('-1234.56')).toBe('-123.56')
239
+ expect(getFormatVal('-12.3')).toBe('-12.3')
240
+ })
241
+
242
+ test('should not format negative value string when allowNegative is false', () => {
243
+ const { getFormatVal } = useInputNumber({
244
+ intLength: 3,
245
+ decimalLength: 2,
246
+ allowNegative: false,
247
+ })
248
+
249
+ expect(getFormatVal('-123.456')).toBe('123.45')
250
+ expect(getFormatVal('-1234.56')).toBe('123.56')
251
+ })
252
+
253
+ test('should not update value when updateValue is false', () => {
254
+ const { numberVal, onAdd } = useInputNumber({ modelValue: 5, step: 2 })
255
+
256
+ expect(numberVal.value).toBe(5)
257
+ const newVal = onAdd(false)
258
+ expect(newVal).toBe(7)
259
+ expect(numberVal.value).toBe(5) // value should not be updated
260
+ })
261
+
262
+ test('should handle complex scenario with negative numbers', () => {
263
+ const { numberVal, onAdd, onReduce } = useInputNumber({
264
+ modelValue: 0,
265
+ step: 5,
266
+ min: -20,
267
+ max: 20,
268
+ allowNegative: true,
269
+ })
270
+
271
+ expect(numberVal.value).toBe(0)
272
+
273
+ // Add to positive
274
+ onAdd()
275
+ expect(numberVal.value).toBe(5)
276
+ onAdd()
277
+ expect(numberVal.value).toBe(10)
278
+ onAdd()
279
+ expect(numberVal.value).toBe(15)
280
+
281
+ // Try to exceed max
282
+ onAdd()
283
+ expect(numberVal.value).toBe(20)
284
+ onAdd()
285
+ expect(numberVal.value).toBe(20) // capped at max
286
+
287
+ // Reduce to negative
288
+ onReduce()
289
+ onReduce()
290
+ onReduce()
291
+ onReduce()
292
+ expect(numberVal.value).toBe(0)
293
+ onReduce()
294
+ expect(numberVal.value).toBe(-5)
295
+ onReduce()
296
+ expect(numberVal.value).toBe(-10)
297
+
298
+ // Try to exceed min
299
+ onReduce()
300
+ onReduce()
301
+ onReduce()
302
+ expect(numberVal.value).toBe(-20)
303
+ onReduce()
304
+ expect(numberVal.value).toBe(-20) // capped at min
305
+ })
306
+ })
@@ -16,6 +16,8 @@ export interface UseInputNumberProps {
16
16
  intLength?: number
17
17
  /** 小数位长度 */
18
18
  decimalLength?: number
19
+ /** 是否允许输入负数 */
20
+ allowNegative?: boolean
19
21
  }
20
22
 
21
23
  export function useInputNumber(props: IncludeRefs<UseInputNumberProps>) {
@@ -28,6 +30,7 @@ export function useInputNumber(props: IncludeRefs<UseInputNumberProps>) {
28
30
  step: _props.step ?? 1,
29
31
  intLength: _props.intLength ?? Number.MAX_SAFE_INTEGER.toString().length,
30
32
  decimalLength: _props.decimalLength ?? 0,
33
+ allowNegative: _props.allowNegative ?? false,
31
34
  })
32
35
 
33
36
  const numberVal = ref<number | null>(
@@ -52,7 +55,7 @@ export function useInputNumber(props: IncludeRefs<UseInputNumberProps>) {
52
55
  )
53
56
 
54
57
  const getFormatVal = (text: InputNumberValue) => {
55
- return formatNumericTypeString(text, state.intLength, state.decimalLength)
58
+ return formatNumericTypeString(text, state.intLength, state.decimalLength, state.allowNegative)
56
59
  }
57
60
 
58
61
  const onUpdate = (type: 'add' | 'reduce', updateValue = true) => {
@@ -96,13 +99,25 @@ export const formatNumericTypeString = (
96
99
  value: InputNumberValue,
97
100
  intLength = Number.MAX_SAFE_INTEGER.toString().length,
98
101
  decimalLength = 0,
102
+ allowNegative = false,
99
103
  ) => {
100
104
  // 根据整数位和小数位处理值
101
- value = String(value)
105
+ const strValue = String(value)
106
+
107
+ // 移除所有非数字和点的字符
108
+ value = strValue
102
109
  .replace(/^\./, '')
103
- .replace(/[^0-9.]/g, '')
110
+ .replace(allowNegative ? /[^0-9.-]/g : /[^0-9.]/g, '')
111
+ // 如果允许负数,只保留第一个负号,且只能在开头
112
+ .replace(allowNegative ? /(?!^)-/g : /-/g, '')
113
+
104
114
  const valSplit = value.split('.').slice(0, 2)
105
- valSplit[0] = valSplit[0].slice(0, intLength)
115
+ // 处理整数部分(保留负号)
116
+ const intPart = valSplit[0]
117
+ const hasNegativeSign = intPart.startsWith('-')
118
+ const intDigits = intPart.replace('-', '')
119
+ valSplit[0] = (hasNegativeSign ? '-' : '') + intDigits.slice(0, intLength)
120
+
106
121
  if (typeof valSplit[1] !== 'undefined' && decimalLength) {
107
122
  valSplit[1] = valSplit[1].slice(0, decimalLength)
108
123
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "papayaui",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "适用于uniapp的ui扩展库",
5
5
  "main": "index.ts",
6
6
  "module": "index.ts",