diff --git a/packages/ui/src/composables/useInputMask/masks/numeral.ts b/packages/ui/src/composables/useInputMask/masks/numeral.ts index e33b563f13..9657cc0cc8 100644 --- a/packages/ui/src/composables/useInputMask/masks/numeral.ts +++ b/packages/ui/src/composables/useInputMask/masks/numeral.ts @@ -1,31 +1,41 @@ +import { StringWithAutocomplete } from '../../../utils/types/prop-type' import { Mask, MaskToken } from '../mask' import { createRegexMask, RegexToken } from './regex' -const DELIMITER = ' ' -const DECIMAL = '.' - type NumeralToken = RegexToken & { isDecimal?: boolean} -export const createNumeralMask = (): Mask => { +export const createNumeralMask = (options: { + decimal?: boolean, + decimalChar?: StringWithAutocomplete<'.' | ','>, +} = {}): Mask => { const intMask = createRegexMask(/(\d{3} )*(\d{3})/, { reverse: true }) + + const { decimal = true, decimalChar = '.' } = options + + const decimalRegex = new RegExp(`[.|,|${decimalChar}]`, 'g') + + if (!decimal) { + return intMask + } + const decimalMask = createRegexMask(/(\d{3} )*(\d{3})/, { reverse: false }) return { format: (text: string) => { - const hasDecimal = text.includes(DECIMAL) + const foundDecimal = text.match(decimalRegex) - if (!hasDecimal) { + if (!foundDecimal) { return intMask.format(text) } - const [int = '', decimal = '', ...rest] = text.split(DECIMAL) + const [int = '', decimal = '', ...rest] = text.split(foundDecimal[0]) const intResult = intMask.format(int) const decimalResult = decimalMask.format(decimal + rest.join('')) return { - text: intResult.text + DECIMAL + decimalResult.text, - tokens: [...intResult.tokens, { type: 'char', static: false, expect: DECIMAL, isDecimal: true }, ...decimalResult.tokens] as NumeralToken[], + text: intResult.text + decimalChar + decimalResult.text, + tokens: [...intResult.tokens, { type: 'char', static: false, expect: decimalChar, isDecimal: true }, ...decimalResult.tokens] as NumeralToken[], } }, handleCursor (selectionStart, selectionEnd, oldTokens, newTokens, data) { @@ -42,7 +52,9 @@ export const createNumeralMask = (): Mask => { } }, unformat: (text: string, tokens: MaskToken[]) => { - return parseFloat(text.replace(/ /g, '')).toString() + const [int = 0, decimal = 0] = text.replace(/ /g, '').split(decimalChar) + + return parseFloat(int + '.' + decimal).toString() }, } } diff --git a/packages/ui/src/composables/useInputMask/useInputMask.stories.ts b/packages/ui/src/composables/useInputMask/useInputMask.stories.ts index 9ee4cba0e3..acb6ec0e1c 100644 --- a/packages/ui/src/composables/useInputMask/useInputMask.stories.ts +++ b/packages/ui/src/composables/useInputMask/useInputMask.stories.ts @@ -1,6 +1,7 @@ import { computed, ref } from 'vue' import { defineStory } from '../../../.storybook/types' import { useInputMask } from './useInputMask' +import { VaInput } from '../../components' import TokensRenderer from './tests/Tokens.vue' import PossibleTokens from './tests/PossibleTokens.vue' import { createRegexMask } from './masks/regex' @@ -259,6 +260,50 @@ export const NumeralWithDecimal = defineStory({ }), }) +export const NumeralWithDecimalCustomChar = defineStory({ + story: () => ({ + setup () { + const value = ref('123456') + const input = ref() + + const numeralRegex = createNumeralMask({ + decimalChar: ',', + }) + const { masked, unmasked } = useInputMask(numeralRegex, input) + + return { value, input, masked, unmasked } + }, + template: ` + + +

masked: {{ masked }}

+

unmasked: {{ unmasked }}

+ `, + }), +}) + +export const NumeralMaskWithoutDecimal = defineStory({ + story: () => ({ + setup () { + const value = ref('123456') + const input = ref() + + const numeralRegex = createNumeralMask({ + decimal: false, + }) + const { masked, unmasked } = useInputMask(numeralRegex, input) + + return { value, input, masked, unmasked } + }, + template: ` + + +

masked: {{ masked }}

+

unmasked: {{ unmasked }}

+ `, + }), +}) + export const CustomMask = defineStory({ story: () => ({ setup () { @@ -310,3 +355,30 @@ export const CustomMask = defineStory({ `, }), }) + +export const WithVueComponent = defineStory({ + story: () => ({ + components: { VaInput }, + setup () { + const value = ref('123456') + const input = ref() + + const numeralRegex = createNumeralMask({ + decimal: false, + }) + const { masked, unmasked } = useInputMask(numeralRegex, input) + + return { value, input, masked, unmasked } + }, + template: ` + + +

masked: {{ masked }}

+

unmasked: {{ unmasked }}

+ `, + }), +}) diff --git a/packages/ui/src/composables/useInputMask/useInputMask.ts b/packages/ui/src/composables/useInputMask/useInputMask.ts index 616c33f684..f8e3a7b668 100644 --- a/packages/ui/src/composables/useInputMask/useInputMask.ts +++ b/packages/ui/src/composables/useInputMask/useInputMask.ts @@ -33,6 +33,9 @@ export const useInputMask = (mask: MaybeRef const input = computed(() => extractInput(el.value)) const setInputValue = (value: string, options?: InputEventInit) => { + if (input.value!.value === value) { + return + } input.value!.value = value input.value!.dispatchEvent(new InputEvent('input', options)) }