From fc58141625ecbdc7d804aa382a69b38bf7146fc4 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Thu, 9 Mar 2023 14:12:06 +0300 Subject: [PATCH] feat(kit): new utility `maskitoParseNumber` (#178) --- .../examples/maskito-parse-number-demo.md | 8 ++++ .../kit/number/number-mask-doc.component.ts | 4 ++ .../kit/number/number-mask-doc.module.ts | 9 +---- .../kit/number/number-mask-doc.template.html | 12 ++++++ projects/kit/src/index.ts | 10 ++--- projects/kit/src/lib/masks/number/index.ts | 1 + .../kit/src/lib/masks/number/number-mask.ts | 2 +- .../max-validation-postprocessor.ts | 12 ++---- .../kit/src/lib/masks/number/utils/index.ts | 1 + .../lib/masks/number/utils/parse-number.ts | 10 +++++ .../number/utils/tests/parse-number.spec.ts | 39 +++++++++++++++++++ 11 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 projects/demo/src/pages/kit/number/examples/maskito-parse-number-demo.md create mode 100644 projects/kit/src/lib/masks/number/utils/parse-number.ts create mode 100644 projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts diff --git a/projects/demo/src/pages/kit/number/examples/maskito-parse-number-demo.md b/projects/demo/src/pages/kit/number/examples/maskito-parse-number-demo.md new file mode 100644 index 000000000..24bf0f929 --- /dev/null +++ b/projects/demo/src/pages/kit/number/examples/maskito-parse-number-demo.md @@ -0,0 +1,8 @@ +```ts +import {maskitoParseNumber} from '@maskito/kit'; + +maskitoParseNumber( + '10 000,42', // document.querySelector('input').value + ',', // decimal separator (dot is default) +); // 10000.42 +``` diff --git a/projects/demo/src/pages/kit/number/number-mask-doc.component.ts b/projects/demo/src/pages/kit/number/number-mask-doc.component.ts index aba43cb4c..4b102efce 100644 --- a/projects/demo/src/pages/kit/number/number-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/number/number-mask-doc.component.ts @@ -16,6 +16,10 @@ type GeneratorOptions = Required< changeDetection: ChangeDetectionStrategy.OnPush, }) export class NumberMaskDocComponent implements GeneratorOptions { + readonly maskitoParseNumberDemo = import( + './examples/maskito-parse-number-demo.md?raw' + ); + readonly highPrecisionExample1: TuiDocExample = { MaskitoOptions: import('./examples/1-high-precision/mask.ts?raw'), }; diff --git a/projects/demo/src/pages/kit/number/number-mask-doc.module.ts b/projects/demo/src/pages/kit/number/number-mask-doc.module.ts index 3ca3f606b..2be7862dc 100644 --- a/projects/demo/src/pages/kit/number/number-mask-doc.module.ts +++ b/projects/demo/src/pages/kit/number/number-mask-doc.module.ts @@ -4,12 +4,7 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {RouterModule} from '@angular/router'; import {MaskitoModule} from '@maskito/angular'; import {TuiAddonDocModule, tuiGenerateRoutes} from '@taiga-ui/addon-doc'; -import { - TuiHintModule, - TuiLabelModule, - TuiNotificationModule, - TuiTextfieldControllerModule, -} from '@taiga-ui/core'; +import {TuiNotificationModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/kit'; import {NumberMaskDocExample1} from './examples/1-high-precision/component'; @@ -25,9 +20,7 @@ import {NumberMaskDocComponent} from './number-mask-doc.component'; ReactiveFormsModule, MaskitoModule, TuiAddonDocModule, - TuiHintModule, TuiInputModule, - TuiLabelModule, TuiNotificationModule, TuiTextfieldControllerModule, RouterModule.forChild(tuiGenerateRoutes(NumberMaskDocComponent)), diff --git a/projects/demo/src/pages/kit/number/number-mask-doc.template.html b/projects/demo/src/pages/kit/number/number-mask-doc.template.html index a2511fa2d..ee5ba9e41 100644 --- a/projects/demo/src/pages/kit/number/number-mask-doc.template.html +++ b/projects/demo/src/pages/kit/number/number-mask-doc.template.html @@ -7,6 +7,18 @@ maskitoNumberOptionsGenerator to create a mask for entering a formatted number. + + Despite the name of the mask, element's raw value is still string. + +

+ Use + maskitoParseNumber + to get number-type value. +

+ + +
+ { return ({value, selection}) => { - const parsedValue = Number( - value - .replace(new RegExp(thousandSeparator, 'g'), '') - .replace(decimalSeparator, '.'), - ); - - if (parsedValue > max) { + if (maskitoParseNumber(value, decimalSeparator) > max) { const newValue = `${max}`.replace('.', decimalSeparator); return { diff --git a/projects/kit/src/lib/masks/number/utils/index.ts b/projects/kit/src/lib/masks/number/utils/index.ts index b8f168b23..5d75a66fb 100644 --- a/projects/kit/src/lib/masks/number/utils/index.ts +++ b/projects/kit/src/lib/masks/number/utils/index.ts @@ -1,2 +1,3 @@ export * from './generate-mask-expression'; export * from './get-default-pseudo-separators'; +export * from './parse-number'; diff --git a/projects/kit/src/lib/masks/number/utils/parse-number.ts b/projects/kit/src/lib/masks/number/utils/parse-number.ts new file mode 100644 index 000000000..1745cabdc --- /dev/null +++ b/projects/kit/src/lib/masks/number/utils/parse-number.ts @@ -0,0 +1,10 @@ +export function maskitoParseNumber( + maskedNumber: string, + decimalSeparator: string = '.', +): number { + return Number( + maskedNumber + .replace(new RegExp(`[^\\d\\${decimalSeparator}]`, 'g'), '') + .replace(decimalSeparator, '.'), + ); +} diff --git a/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts b/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts new file mode 100644 index 000000000..70f20d042 --- /dev/null +++ b/projects/kit/src/lib/masks/number/utils/tests/parse-number.spec.ts @@ -0,0 +1,39 @@ +import {maskitoParseNumber} from '../parse-number'; + +describe('maskitoParseNumber', () => { + describe('decimal separator is dot (default one)', () => { + it('thousand separator is space', () => { + expect(maskitoParseNumber('1 000 000.42')).toBe(1000000.42); + }); + + it('thousand separator is hyphen', () => { + expect(maskitoParseNumber('1-000-000.42')).toBe(1000000.42); + }); + + it('thousand separator is empty string', () => { + expect(maskitoParseNumber('1000000.42')).toBe(1000000.42); + }); + + it('empty decimal part & thousand separator is comma', () => { + expect(maskitoParseNumber('1,000,000')).toBe(1000000); + }); + }); + + describe('decimal separator is comma', () => { + it('thousand separator is space', () => { + expect(maskitoParseNumber('42 111,42', ',')).toBe(42111.42); + }); + + it('thousand separator is hyphen', () => { + expect(maskitoParseNumber('42-111,42', ',')).toBe(42111.42); + }); + + it('thousand separator is empty string', () => { + expect(maskitoParseNumber('42111,42', ',')).toBe(42111.42); + }); + + it('empty decimal part & thousand separator is dot', () => { + expect(maskitoParseNumber('42.111', ',')).toBe(42111); + }); + }); +});