Skip to content

Commit

Permalink
feat: add percent format style (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
dm4t2 committed Oct 16, 2021
1 parent da183a4 commit 3035d1e
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/api.ts
Expand Up @@ -19,7 +19,8 @@ export interface NumberRange {
export enum NumberFormatStyle {
Decimal = 'decimal',
Currency = 'currency',
Unit = 'unit'
Unit = 'unit',
Percent = 'percent'
}

export interface NumberInputOptions {
Expand Down
11 changes: 9 additions & 2 deletions src/numberFormat.ts
Expand Up @@ -58,14 +58,21 @@ export class NumberFormat {
const fraction = this.decimalSymbol ? `(?:${escapeRegExp(this.decimalSymbol)}(\\d*))?` : ''
const match = this.stripGroupingSeparator(str).match(new RegExp(`^${INTEGER_PATTERN}${fraction}$`))
if (match && this.isValidIntegerFormat(this.decimalSymbol ? str.split(this.decimalSymbol)[0] : str, Number(match[1]))) {
return Number(`${negative ? '-' : ''}${this.onlyDigits(match[1])}.${this.onlyDigits(match[2] || '')}`)
let number = Number(`${negative ? '-' : ''}${this.onlyDigits(match[1])}.${this.onlyDigits(match[2] || '')}`)
if (this.style === NumberFormatStyle.Percent) {
number /= 100
}
return number
}
}
return null
}

isValidIntegerFormat(formattedNumber: string, integerNumber: number): boolean {
const options = { style: this.style, currency: this.currency, unit: this.unit, minimumFractionDigits: 0 }
if (this.style === NumberFormatStyle.Percent) {
integerNumber /= 100
}
return [
this.stripPrefixOrSuffix(this.normalizeDigits(integerNumber.toLocaleString(this.locale, { ...options, useGrouping: true }))),
this.stripPrefixOrSuffix(this.normalizeDigits(integerNumber.toLocaleString(this.locale, { ...options, useGrouping: false })))
Expand All @@ -85,7 +92,7 @@ export class NumberFormat {
currency: this.currency,
unit: this.unit,
...options
}).format(value)
}).format(this.style === NumberFormatStyle.Percent ? value / 100 : value)
: ''
}

Expand Down
18 changes: 12 additions & 6 deletions src/numberInput.ts
@@ -1,6 +1,6 @@
import { DECIMAL_SEPARATORS, NumberFormat } from './numberFormat'
import { AutoDecimalModeNumberMask, DefaultNumberMask, NumberMask } from './numberMask'
import { NumberInputConstructorArgs, NumberInputOptions, NumberInputValue } from './api'
import { NumberFormatStyle, NumberInputConstructorArgs, NumberInputOptions, NumberInputValue } from './api'
import { count } from './utils'

export class NumberInput {
Expand Down Expand Up @@ -96,8 +96,8 @@ export class NumberInput {
return max
}

private validateStep(value: number | null): number | null {
return value != null && this.toInteger(value) % this.toInteger(this.step) !== 0 ? this.getNextStep(value) : value
private validateStep(value: number): number {
return this.toInteger(value) % this.toInteger(this.step) !== 0 ? this.getNextStep(value) : value
}

private getNextStep(value: number): number {
Expand All @@ -112,12 +112,18 @@ export class NumberInput {
return Number(value.toFixed(this.numberFormat.maximumFractionDigits).split('.').join(''))
}

private validateValueRange(value: number | null): number | null {
return value != null ? Math.min(Math.max(value, this.minValue), this.maxValue) : value
private validateValueRange(value: number): number {
return Math.min(Math.max(value, this.minValue), this.maxValue)
}

private applyFixedFractionFormat(number: number | null, forcedChange = false) {
this.format(this.numberFormat.format(this.validateStep(this.validateValueRange(number))))
if (number != null) {
number = this.validateStep(this.validateValueRange(number))
if (this.options.formatStyle === NumberFormatStyle.Percent) {
number *= 100
}
}
this.format(this.numberFormat.format(number))
if (number !== this.numberValue || forcedChange) {
this.onChange?.(this.getValue())
}
Expand Down

0 comments on commit 3035d1e

Please sign in to comment.