From 8c7f94b322747735911c6bb7785045e1be756289 Mon Sep 17 00:00:00 2001 From: Ezequias Antunes Date: Thu, 30 Apr 2026 11:53:42 -0300 Subject: [PATCH 1/5] =?UTF-8?q?Melhora=20usabilidade=20do=20componente=20p?= =?UTF-8?q?ara=20valores=20decimais,=20passa=20a=20utilizar=20apenas=20v?= =?UTF-8?q?=C3=ADrgula=20como=20separador=20decimal,=20limita=20casas=20de?= =?UTF-8?q?cimais,=20permite=20zeros=20ap=C3=B3s=20a=20v=C3=ADrgula?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/NumberInput.vue | 67 ++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/src/components/NumberInput.vue b/src/components/NumberInput.vue index cdfc658a..103f8935 100644 --- a/src/components/NumberInput.vue +++ b/src/components/NumberInput.vue @@ -40,12 +40,14 @@ :floating-label="floatingLabel || mobile" :support-link="supportLink || linkText" :support-link-url="supportLinkUrl || linkUrl" - type="number" + type="text" + inputmode="decimal" @click="emitClick" @change="handleChange" @focus="handleFocus" - @blur="emitBlur" + @blur="handleBlur" @keydown="emitKeydown" + @input="handleDefaultInput" /> @@ -263,6 +265,25 @@ watch(model, (newValue) => { unmaskedValue.value = 0; } } + } else if (!props.mask) { + if (newValue === null || newValue === undefined || newValue === '') { + internalValue.value = ''; + unmaskedValue.value = ''; + return; + } + + const numericValue = typeof newValue === 'string' ? parseFloat(newValue.replace(',', '.')) : newValue; + const currentInternalNumeric = parseFloat(String(internalValue.value).replace(/\./g, '').replace(',', '.')); + + if (numericValue !== currentInternalNumeric) { + const hasFractionalPart = (numericValue % 1 !== 0) || (typeof newValue === 'string' && newValue.includes(',')); + internalValue.value = numericValue.toLocaleString('pt-BR', { + minimumFractionDigits: hasFractionalPart ? 2 : 0, + maximumFractionDigits: hasFractionalPart ? 2 : 0, + useGrouping: false, + }); + } + unmaskedValue.value = numericValue; } else { internalValue.value = newValue ?? ''; } @@ -279,8 +300,9 @@ watch(internalValue, (value) => { } else if (stringifiedInput.length > 15) { internalValue.value = +stringifiedInput.slice(0, 15); } else { - model.value = +stringifiedInput; - unmaskedValue.value = +stringifiedInput; + const numericValue = parseFloat(stringifiedInput.replace(/\./g, '').replace(',', '.')); + model.value = isNaN(numericValue) ? '' : numericValue; + unmaskedValue.value = model.value; } }); @@ -316,6 +338,27 @@ function handleMoneyInput(event) { } } +function handleDefaultInput(event) { + let value = event.target.value; + + // Permitir apenas números e uma vírgula (substituindo ponto por vírgula) + value = value.replace(/\./g, ','); + value = value.replace(/[^\d,]/g, ''); + + // Garantir apenas uma vírgula + const parts = value.split(','); + if (parts.length > 2) { + value = parts[0] + ',' + parts.slice(1).join(''); + } + + // Limitar a 2 casas decimais + if (parts.length === 2 && parts[1].length > 2) { + value = parts[0] + ',' + parts[1].slice(0, 2); + } + + internalValue.value = value; +} + function handleFocus(event) { if (props.money) { internalValue.value = (internalValue.value === '') @@ -329,6 +372,22 @@ function handleFocus(event) { emitFocus(event); } +function handleBlur(event) { + if (!props.money && !props.mask && internalValue.value !== '') { + const stringValue = String(internalValue.value); + const hasComma = stringValue.includes(','); + const numericValue = parseFloat(stringValue.replace(/\./g, '').replace(',', '.')); + if (!isNaN(numericValue)) { + internalValue.value = numericValue.toLocaleString('pt-BR', { + minimumFractionDigits: hasComma ? 2 : 0, + maximumFractionDigits: hasComma ? 2 : 0, + useGrouping: false, + }); + } + } + emitBlur(event); +} + function handleChange() { if (!props.money) { model.value = internalValue.value; From 2fef0c2d1b7fe0909a10662a19b14f173c322ebb Mon Sep 17 00:00:00 2001 From: Ezequias Antunes Date: Thu, 30 Apr 2026 13:24:00 -0300 Subject: [PATCH 2/5] =?UTF-8?q?Corrige=20visualiza=C3=A7=C3=A3o=20de=20um?= =?UTF-8?q?=20n=C3=BAmero=20decimal=20como=20n=C3=BAmero=20inteiro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/NumberInput.vue | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/components/NumberInput.vue b/src/components/NumberInput.vue index 103f8935..c0d1cae5 100644 --- a/src/components/NumberInput.vue +++ b/src/components/NumberInput.vue @@ -273,15 +273,17 @@ watch(model, (newValue) => { } const numericValue = typeof newValue === 'string' ? parseFloat(newValue.replace(',', '.')) : newValue; - const currentInternalNumeric = parseFloat(String(internalValue.value).replace(/\./g, '').replace(',', '.')); + const currentInternalNumeric = parseFloat(String(internalValue.value).replace(',', '.')); - if (numericValue !== currentInternalNumeric) { - const hasFractionalPart = (numericValue % 1 !== 0) || (typeof newValue === 'string' && newValue.includes(',')); - internalValue.value = numericValue.toLocaleString('pt-BR', { - minimumFractionDigits: hasFractionalPart ? 2 : 0, - maximumFractionDigits: hasFractionalPart ? 2 : 0, - useGrouping: false, - }); + const hasDecimalIntent = (numericValue % 1 !== 0) || (typeof newValue === 'string' && (newValue.includes(',') || newValue.includes('.'))); + const formattedValue = numericValue.toLocaleString('pt-BR', { + minimumFractionDigits: hasDecimalIntent ? 2 : 0, + maximumFractionDigits: hasDecimalIntent ? 2 : 0, + useGrouping: false, + }); + + if (formattedValue !== internalValue.value && numericValue !== currentInternalNumeric) { + internalValue.value = formattedValue; } unmaskedValue.value = numericValue; } else { @@ -300,7 +302,7 @@ watch(internalValue, (value) => { } else if (stringifiedInput.length > 15) { internalValue.value = +stringifiedInput.slice(0, 15); } else { - const numericValue = parseFloat(stringifiedInput.replace(/\./g, '').replace(',', '.')); + const numericValue = parseFloat(stringifiedInput.replace(',', '.')); model.value = isNaN(numericValue) ? '' : numericValue; unmaskedValue.value = model.value; } @@ -375,12 +377,12 @@ function handleFocus(event) { function handleBlur(event) { if (!props.money && !props.mask && internalValue.value !== '') { const stringValue = String(internalValue.value); - const hasComma = stringValue.includes(','); - const numericValue = parseFloat(stringValue.replace(/\./g, '').replace(',', '.')); + const hasSeparator = stringValue.includes(',') || stringValue.includes('.'); + const numericValue = parseFloat(stringValue.replace(',', '.')); if (!isNaN(numericValue)) { internalValue.value = numericValue.toLocaleString('pt-BR', { - minimumFractionDigits: hasComma ? 2 : 0, - maximumFractionDigits: hasComma ? 2 : 0, + minimumFractionDigits: hasSeparator ? 2 : 0, + maximumFractionDigits: hasSeparator ? 2 : 0, useGrouping: false, }); } From 9af59630ea9c1ea32ac36780c93f3c4361e17aaa Mon Sep 17 00:00:00 2001 From: Ezequias Antunes Date: Thu, 30 Apr 2026 13:45:26 -0300 Subject: [PATCH 3/5] =?UTF-8?q?Altera=20vers=C3=A3o=20do=20pacote?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 884d246e..557e701e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sysvale/cuida", - "version": "3.157.0", + "version": "3.157.2", "description": "A design system built by Sysvale, using storybook and Vue components", "repository": { "type": "git", @@ -86,4 +86,4 @@ "readme": "ERROR: No README data found!", "homepage": "https://github.com/Sysvale/cuida#readme", "_id": "@sysvale/cuida@3.0.0-alpha.21" -} +} \ No newline at end of file From 81044ea0af956abab3ea38fdb794bffc8ade03fa Mon Sep 17 00:00:00 2001 From: Ezequias Antunes Date: Thu, 30 Apr 2026 15:53:45 -0300 Subject: [PATCH 4/5] =?UTF-8?q?Permite=20que=20os=20valores=20n=C3=BAmeric?= =?UTF-8?q?os,=20quando=20apagados,=20retornam=20nulo=20em=20vez=20de=20st?= =?UTF-8?q?ring=20vazia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/NumberInput.vue | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/NumberInput.vue b/src/components/NumberInput.vue index c0d1cae5..1b0d30e0 100644 --- a/src/components/NumberInput.vue +++ b/src/components/NumberInput.vue @@ -268,7 +268,7 @@ watch(model, (newValue) => { } else if (!props.mask) { if (newValue === null || newValue === undefined || newValue === '') { internalValue.value = ''; - unmaskedValue.value = ''; + unmaskedValue.value = null; return; } @@ -303,7 +303,7 @@ watch(internalValue, (value) => { internalValue.value = +stringifiedInput.slice(0, 15); } else { const numericValue = parseFloat(stringifiedInput.replace(',', '.')); - model.value = isNaN(numericValue) ? '' : numericValue; + model.value = isNaN(numericValue) ? null : numericValue; unmaskedValue.value = model.value; } }); @@ -322,7 +322,7 @@ function handleMoneyInput(event) { const formattedValue = formatDigitsToBRL(digits); - + internalValue.value = formattedValue; unmaskedValue.value = unmaskBRL(formattedValue); model.value = formattedValue; @@ -391,7 +391,10 @@ function handleBlur(event) { } function handleChange() { - if (!props.money) { + if (!props.money && !props.mask) { + const numericValue = parseFloat(String(internalValue.value).replace(',', '.')); + model.value = isNaN(numericValue) ? null : numericValue; + } else if (!props.money) { model.value = internalValue.value; } emitChange(); From 8fd62550aa0058d7fb91b5a08de6bb4fa2228612 Mon Sep 17 00:00:00 2001 From: Ezequias Antunes Date: Thu, 30 Apr 2026 17:14:35 -0300 Subject: [PATCH 5/5] Atualiza snapshot do NumberInput --- src/tests/__snapshots__/NumberInput.spec.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/__snapshots__/NumberInput.spec.js.snap b/src/tests/__snapshots__/NumberInput.spec.js.snap index 120fa73f..aef7170c 100644 --- a/src/tests/__snapshots__/NumberInput.spec.js.snap +++ b/src/tests/__snapshots__/NumberInput.spec.js.snap @@ -2,7 +2,7 @@ exports[`CdsNumberInput > renders correctly 1`] = ` "
-