From 59b5a8534dd23de04f847ef8cbf2f7fbbfb50bcc Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Thu, 8 Jun 2023 17:32:51 -0500 Subject: [PATCH 01/21] fix(input): no longer remove trailing decimal separator --- .../components/input-number/input-number.e2e.ts | 15 +++++++++++++++ .../src/components/input-number/input-number.tsx | 5 ++++- .../src/components/input/input.e2e.ts | 15 +++++++++++++++ .../src/components/input/input.tsx | 5 ++++- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 74b66aac61d..3be952b09ac 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -715,6 +715,21 @@ describe("calcite-input-number", () => { const input = await page.find("calcite-input-number >>> input"); expect(await input.getProperty("value")).toBe("2"); }); + + it("allows trailing decimal separator", async () => { + const page = await newE2EPage(); + await page.setContent(html``); + const calciteInput = await page.find("calcite-input"); + const inputEventSpy = await calciteInput.spyOnEvent("calciteInputInput"); + + await calciteInput.click(); + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(inputEventSpy).toHaveReceivedEvent(); + const input = await page.find("calcite-input >>> input"); + + expect(await input.getProperty("value")).toBe("1."); + }); }); describe("emits events when value is modified", () => { diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 231564451fa..24e95fd0f39 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -848,7 +848,10 @@ export class InputNumber : sanitizedValue; const newLocalizedValue = numberStringFormatter.localize(newValue); - this.localizedValue = newLocalizedValue; + this.localizedValue = + value.charAt(value.length - 1) === numberStringFormatter.decimal + ? `${newLocalizedValue}${numberStringFormatter.decimal}` + : newLocalizedValue; this.setPreviousNumberValue(previousValue ?? this.value); this.previousValueOrigin = origin; diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index 0d488c59625..12cfcecd88f 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -701,6 +701,21 @@ describe("calcite-input", () => { expect(inputEventSpy).not.toHaveReceivedEvent(); expect(changeEventSpy).not.toHaveReceivedEvent(); }); + + it("allows trailing decimal separator", async () => { + const page = await newE2EPage(); + await page.setContent(html``); + const calciteInput = await page.find("calcite-input"); + const inputEventSpy = await calciteInput.spyOnEvent("calciteInputInput"); + + await calciteInput.click(); + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(inputEventSpy).toHaveReceivedEvent(); + const input = await page.find("calcite-input >>> input"); + + expect(await input.getProperty("value")).toBe("1."); + }); }); describe("emits events when value is modified", () => { diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 033b9ca833a..3eea7ccd5ba 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -984,7 +984,10 @@ export class Input : sanitizedValue; const newLocalizedValue = numberStringFormatter.localize(newValue); - this.localizedValue = newLocalizedValue; + this.localizedValue = + value.charAt(value.length - 1) === numberStringFormatter.decimal + ? `${newLocalizedValue}${numberStringFormatter.decimal}` + : newLocalizedValue; this.userChangedValue = origin === "user" && this.value !== newValue; // don't sanitize the start of negative/decimal numbers, but From 46132123cfcbde7835c26871db9dece1348c3bf5 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Thu, 15 Jun 2023 19:28:29 -0500 Subject: [PATCH 02/21] add localized leading decimal zero values --- .../input-number/input-number.e2e.ts | 49 ++++++++++++++++++- .../components/input-number/input-number.tsx | 36 +++++++++++--- .../src/components/input/input.e2e.ts | 47 ++++++++++++++++++ .../src/components/input/input.tsx | 37 ++++++++++---- .../calcite-components/src/utils/number.ts | 47 +++++++++++++++++- 5 files changed, 196 insertions(+), 20 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 3be952b09ac..c4aecb66777 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -1375,7 +1375,7 @@ describe("calcite-input-number", () => { await page.keyboard.press("Backspace"); await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("1"); + expect(await element.getProperty("value")).toBe("1."); expect(calciteInputNumberInput).toHaveReceivedEventTimes(1); }); @@ -1400,6 +1400,53 @@ describe("calcite-input-number", () => { expect(await element.getProperty("value")).toBe("10000000"); }); + it("should keep leading decimal zeros from value on Backspace", async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + const element = await page.find("calcite-input-number"); + await element.callMethod("setFocus"); + await typeNumberValue(page, "0.0000"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.0000"); + + await page.keyboard.press("Backspace"); + await typeNumberValue(page, "1"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.0001"); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.000101"); + }); + + it("should keep decimal separator zeros from value on Backspace", async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + const element = await page.find("calcite-input-number"); + await element.callMethod("setFocus"); + await typeNumberValue(page, "0.01"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.01"); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.0"); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0."); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.1"); + }); + it("sanitize extra dashes from value", async () => { const page = await newE2EPage(); await page.setContent(``); diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 24e95fd0f39..6ea565fb078 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -44,6 +44,7 @@ import { numberStringFormatter } from "../../utils/locale"; import { + addLocalizedTrailingDecimalZeros, BigDecimal, isValidNumber, parseNumberString, @@ -833,12 +834,19 @@ export class InputNumber useGrouping: this.groupSeparator }; - const sanitizedValue = sanitizeNumberString( - // no need to delocalize a string that ia already in latn numerals - (this.numberingSystem && this.numberingSystem !== "latn") || defaultNumberingSystem !== "latn" - ? numberStringFormatter.delocalize(value) - : value - ); + const isValueDeleted = + this.previousValue?.length > value.length || this.value.length > value.length; + + const sanitizedValue = + value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted + ? value + : sanitizeNumberString( + // no need to delocalize a string that ia already in latn numerals + (this.numberingSystem && this.numberingSystem !== "latn") || + defaultNumberingSystem !== "latn" + ? numberStringFormatter.delocalize(value) + : value + ); const newValue = value && !sanitizedValue @@ -847,9 +855,21 @@ export class InputNumber : "" : sanitizedValue; - const newLocalizedValue = numberStringFormatter.localize(newValue); + let newLocalizedValue = numberStringFormatter.localize(newValue); + + if ( + newLocalizedValue.length !== newValue.length && + numberStringFormatter.delocalize(newLocalizedValue) !== newValue + ) { + newLocalizedValue = addLocalizedTrailingDecimalZeros( + newLocalizedValue, + newValue, + numberStringFormatter + ); + } + this.localizedValue = - value.charAt(value.length - 1) === numberStringFormatter.decimal + value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted ? `${newLocalizedValue}${numberStringFormatter.decimal}` : newLocalizedValue; diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index 12cfcecd88f..397418d7b18 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1578,6 +1578,53 @@ describe("calcite-input", () => { expect(await element.getProperty("value")).toBe("10000000"); }); + it("should keep leading decimal zeros from value on Backspace", async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + const element = await page.find("calcite-input-number"); + await element.callMethod("setFocus"); + await typeNumberValue(page, "0.0000"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.0000"); + + await page.keyboard.press("Backspace"); + await typeNumberValue(page, "1"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.0001"); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.000101"); + }); + + it("should keep decimal separator zeros from value on Backspace", async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + const element = await page.find("calcite-input-number"); + await element.callMethod("setFocus"); + await typeNumberValue(page, "0.01"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.01"); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.0"); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0."); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await element.getProperty("value")).toBe("0.1"); + }); + it("sanitize extra dashes from number input value", async () => { const page = await newE2EPage(); await page.setContent(``); diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 3eea7ccd5ba..1bb070c99a1 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -45,6 +45,7 @@ import { } from "../../utils/locale"; import { + addLocalizedTrailingDecimalZeros, BigDecimal, isValidNumber, parseNumberString, @@ -968,13 +969,19 @@ export class Input signDisplay: "never" }; - const sanitizedValue = sanitizeNumberString( - // no need to delocalize a string that ia already in latn numerals - (this.numberingSystem && this.numberingSystem !== "latn") || - defaultNumberingSystem !== "latn" - ? numberStringFormatter.delocalize(value) - : value - ); + const isValueDeleted = + this.previousValue?.length > value.length || this.value.length > value.length; + + const sanitizedValue = + value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted + ? value + : sanitizeNumberString( + // no need to delocalize a string that ia already in latn numerals + (this.numberingSystem && this.numberingSystem !== "latn") || + defaultNumberingSystem !== "latn" + ? numberStringFormatter.delocalize(value) + : value + ); const newValue = value && !sanitizedValue @@ -983,9 +990,21 @@ export class Input : "" : sanitizedValue; - const newLocalizedValue = numberStringFormatter.localize(newValue); + let newLocalizedValue = numberStringFormatter.localize(newValue); + + if ( + newLocalizedValue.length !== newValue.length && + numberStringFormatter.delocalize(newLocalizedValue) !== newValue + ) { + newLocalizedValue = addLocalizedTrailingDecimalZeros( + newLocalizedValue, + newValue, + numberStringFormatter + ); + } + this.localizedValue = - value.charAt(value.length - 1) === numberStringFormatter.decimal + value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted ? `${newLocalizedValue}${numberStringFormatter.decimal}` : newLocalizedValue; diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 7628b0fd408..495f3aa9968 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -137,14 +137,27 @@ export const sanitizeNumberString = (numberString: string): string => .replace(allHyphensExceptTheStart, "") .replace(decimalOnlyAtEndOfString, "") .replace(allLeadingZerosOptionallyNegative, "$1"); - return isValidNumber(sanitizedValue) ? isNegativeDecimalOnlyZeros.test(sanitizedValue) ? sanitizedValue - : new BigDecimal(sanitizedValue).toString() + : getBigDecimalString(sanitizedValue) : nonExpoNumString; }); +export function getBigDecimalString(sanitizedValue: string): string { + const decimals = sanitizedValue.split(".")[1]; + const newdecimals = new BigDecimal(sanitizedValue).toString().split(".")[1]; + + // adds back trailing deciamls zeros + if (decimals && !newdecimals && BigInt(decimals) === BigInt(0) && decimals !== newdecimals) { + const value = new BigDecimal(sanitizedValue).toString() + "."; + const newvalue = value.padEnd(value.length + decimals.length, "0"); + return newvalue; + } + + return new BigDecimal(sanitizedValue).toString(); +} + export function sanitizeExponentialNumberString(numberString: string, func: (s: string) => string): string { if (!numberString) { return numberString; @@ -217,3 +230,33 @@ export function expandExponentialNumberString(numberString: string): string { function stringContainsNumbers(string: string): boolean { return numberKeys.some((number) => string.includes(number)); } + +/** + * Adds localized trailing decimals zero values to the number string. + * BigInt conversion to string removes the trailing decimal zero values (Ex: 1.000 is returned as 1). This method helps adding them back. + * + * @param {string} localizedValue - localized number string value + * @param {string} value - current value in the input field + * @param {NumberStringFormat} numberStringFormatter - numberStringFormatter instance to localize the number value + * @returns {string} localized number string value + */ +export function addLocalizedTrailingDecimalZeros( + localizedValue: string, + value: string, + formatter: NumberStringFormat +): string { + let localizedDecimals; + const decimalSeparator = formatter.decimal; + if (localizedValue.includes(decimalSeparator)) { + localizedDecimals = localizedValue.split(".")[1]; + } + const decimals = value.split(".")[1]; + + if (localizedDecimals !== decimals) { + localizedValue = decimals && !localizedDecimals ? localizedValue + decimalSeparator : localizedValue; + [...decimals].forEach((decimal) => { + localizedValue += formatter.localize(decimal); + }); + } + return localizedValue; +} From 5d6f50789dafc6a4e6df7bb522738f1aa612f158 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Tue, 20 Jun 2023 16:43:20 -0500 Subject: [PATCH 03/21] fix tests --- .../src/components/input-number/input-number.e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index c4aecb66777..e45a493f4c2 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -1444,7 +1444,7 @@ describe("calcite-input-number", () => { await typeNumberValue(page, "01"); await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.1"); + expect(await element.getProperty("value")).toBe("0.01"); }); it("sanitize extra dashes from value", async () => { From c6a1e7105b64a101d97f69a8916a5ceba531b3f9 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Wed, 21 Jun 2023 12:49:27 -0500 Subject: [PATCH 04/21] fix tests --- .../src/components/input-number/input-number.tsx | 2 +- packages/calcite-components/src/components/input/input.e2e.ts | 4 ++-- packages/calcite-components/src/components/input/input.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index e024a691d6a..ff8b005e476 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -842,7 +842,7 @@ export class InputNumber }; const isValueDeleted = - this.previousValue?.length > value.length || this.value.length > value.length; + this.previousValue?.length > value.length || this.value?.length > value.length; const sanitizedValue = value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index 397418d7b18..ff65860e13e 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1553,7 +1553,7 @@ describe("calcite-input", () => { await page.keyboard.press("Backspace"); await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("1"); + expect(await element.getProperty("value")).toBe("1."); expect(calciteInputInput).toHaveReceivedEventTimes(1); }); @@ -1622,7 +1622,7 @@ describe("calcite-input", () => { await typeNumberValue(page, "01"); await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.1"); + expect(await element.getProperty("value")).toBe("0.01"); }); it("sanitize extra dashes from number input value", async () => { diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index c0540d8d63a..cf03542eb33 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -977,7 +977,7 @@ export class Input }; const isValueDeleted = - this.previousValue?.length > value.length || this.value.length > value.length; + this.previousValue?.length > value.length || this.value?.length > value.length; const sanitizedValue = value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted From 1c60d0741f1ba18355d702e29e74107bc0d85311 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Wed, 21 Jun 2023 16:03:00 -0500 Subject: [PATCH 05/21] cleanup --- .../components/input-number/input-number.e2e.ts | 14 ++++++++++++-- .../src/components/input-number/input-number.tsx | 3 ++- .../src/components/input/input.e2e.ts | 14 ++++++++++++-- .../src/components/input/input.tsx | 3 ++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index e45a493f4c2..216857bdd3e 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -1400,7 +1400,7 @@ describe("calcite-input-number", () => { expect(await element.getProperty("value")).toBe("10000000"); }); - it("should keep leading decimal zeros from value on Backspace", async () => { + it("should be able to append value to zeros in decimal after Backspace", async () => { const page = await newE2EPage(); await page.setContent(` @@ -1422,7 +1422,7 @@ describe("calcite-input-number", () => { expect(await element.getProperty("value")).toBe("0.000101"); }); - it("should keep decimal separator zeros from value on Backspace", async () => { + it("should keep leading decimal separator while input is focused on Backspace", async () => { const page = await newE2EPage(); await page.setContent(` @@ -1447,6 +1447,16 @@ describe("calcite-input-number", () => { expect(await element.getProperty("value")).toBe("0.01"); }); + it("should sanitize leading decimal zeros on initial render", async () => { + const page = await newE2EPage(); + await page.setContent(html``); + const calciteInput = await page.find("calcite-input"); + const input = await page.find("calcite-input >>> input"); + + expect(await input.getProperty("value")).toBe("0"); + expect(await calciteInput.getProperty("value")).toBe("0"); + }); + it("sanitize extra dashes from value", async () => { const page = await newE2EPage(); await page.setContent(``); diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index ff8b005e476..e150e1a5ee3 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -866,7 +866,8 @@ export class InputNumber if ( newLocalizedValue.length !== newValue.length && - numberStringFormatter.delocalize(newLocalizedValue) !== newValue + numberStringFormatter.delocalize(newLocalizedValue) !== newValue && + origin !== "connected" ) { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index ff65860e13e..be8bbab46b4 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1578,7 +1578,7 @@ describe("calcite-input", () => { expect(await element.getProperty("value")).toBe("10000000"); }); - it("should keep leading decimal zeros from value on Backspace", async () => { + it("should be able to append value to zeros in decimal after Backspace", async () => { const page = await newE2EPage(); await page.setContent(` @@ -1600,7 +1600,7 @@ describe("calcite-input", () => { expect(await element.getProperty("value")).toBe("0.000101"); }); - it("should keep decimal separator zeros from value on Backspace", async () => { + it("should keep leading decimal separator while input is focused on Backspace", async () => { const page = await newE2EPage(); await page.setContent(` @@ -1625,6 +1625,16 @@ describe("calcite-input", () => { expect(await element.getProperty("value")).toBe("0.01"); }); + it("should sanitize leading decimal zeros on initial render", async () => { + const page = await newE2EPage(); + await page.setContent(html``); + const calciteInput = await page.find("calcite-input"); + const input = await page.find("calcite-input >>> input"); + + expect(await input.getProperty("value")).toBe("0"); + expect(await calciteInput.getProperty("value")).toBe("0"); + }); + it("sanitize extra dashes from number input value", async () => { const page = await newE2EPage(); await page.setContent(``); diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index cf03542eb33..cba1a5547bf 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -1001,7 +1001,8 @@ export class Input if ( newLocalizedValue.length !== newValue.length && - numberStringFormatter.delocalize(newLocalizedValue) !== newValue + numberStringFormatter.delocalize(newLocalizedValue) !== newValue && + origin !== "connected" ) { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, From c44723927e8cdd684d5378db616a99c2ff85164b Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Wed, 21 Jun 2023 17:21:13 -0500 Subject: [PATCH 06/21] refactor --- .../src/components/input-number/input-number.e2e.ts | 8 ++++---- .../src/components/input-number/input-number.tsx | 6 +----- .../calcite-components/src/components/input/input.e2e.ts | 4 ++-- .../calcite-components/src/components/input/input.tsx | 6 +----- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 216857bdd3e..91e3fd0157d 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -1449,12 +1449,12 @@ describe("calcite-input-number", () => { it("should sanitize leading decimal zeros on initial render", async () => { const page = await newE2EPage(); - await page.setContent(html``); - const calciteInput = await page.find("calcite-input"); - const input = await page.find("calcite-input >>> input"); + await page.setContent(html``); + const calciteInput = await page.find("calcite-input-number"); + const input = await page.find("calcite-input-number >>> input"); expect(await input.getProperty("value")).toBe("0"); - expect(await calciteInput.getProperty("value")).toBe("0"); + expect(await calciteInput.getProperty("value")).toBe("0.0000"); }); it("sanitize extra dashes from value", async () => { diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index e150e1a5ee3..309df3fbac5 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -864,11 +864,7 @@ export class InputNumber let newLocalizedValue = numberStringFormatter.localize(newValue); - if ( - newLocalizedValue.length !== newValue.length && - numberStringFormatter.delocalize(newLocalizedValue) !== newValue && - origin !== "connected" - ) { + if (newLocalizedValue.length !== newValue.length && origin !== "connected") { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, newValue, diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index be8bbab46b4..3df16458855 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1627,12 +1627,12 @@ describe("calcite-input", () => { it("should sanitize leading decimal zeros on initial render", async () => { const page = await newE2EPage(); - await page.setContent(html``); + await page.setContent(html``); const calciteInput = await page.find("calcite-input"); const input = await page.find("calcite-input >>> input"); expect(await input.getProperty("value")).toBe("0"); - expect(await calciteInput.getProperty("value")).toBe("0"); + expect(await calciteInput.getProperty("value")).toBe("0.0000"); }); it("sanitize extra dashes from number input value", async () => { diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index cba1a5547bf..7d6fb5927b5 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -999,11 +999,7 @@ export class Input let newLocalizedValue = numberStringFormatter.localize(newValue); - if ( - newLocalizedValue.length !== newValue.length && - numberStringFormatter.delocalize(newLocalizedValue) !== newValue && - origin !== "connected" - ) { + if (newLocalizedValue.length !== newValue.length && origin !== "connected") { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, newValue, From 7a0480af654e07f928f95d44e718da4cf12cf6e9 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Wed, 21 Jun 2023 17:30:39 -0500 Subject: [PATCH 07/21] refactor util method --- packages/calcite-components/src/utils/number.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 495f3aa9968..dd2a35cd5d5 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -252,8 +252,8 @@ export function addLocalizedTrailingDecimalZeros( } const decimals = value.split(".")[1]; - if (localizedDecimals !== decimals) { - localizedValue = decimals && !localizedDecimals ? localizedValue + decimalSeparator : localizedValue; + if (decimals && localizedDecimals !== decimals) { + localizedValue = localizedValue + decimalSeparator; [...decimals].forEach((decimal) => { localizedValue += formatter.localize(decimal); }); From 87f15d7ccc949e634c62279f8ed8fff492cb1ab1 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Wed, 21 Jun 2023 17:46:51 -0500 Subject: [PATCH 08/21] remove redundant code blocks --- .../components/input-number/input-number.e2e.ts | 8 ++++---- .../src/components/input-number/input-number.tsx | 15 ++++++++++++--- .../src/components/input/input.tsx | 15 ++++++++++++--- packages/calcite-components/src/utils/number.ts | 6 +++--- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 91e3fd0157d..9ecc3580cfc 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -718,15 +718,15 @@ describe("calcite-input-number", () => { it("allows trailing decimal separator", async () => { const page = await newE2EPage(); - await page.setContent(html``); - const calciteInput = await page.find("calcite-input"); - const inputEventSpy = await calciteInput.spyOnEvent("calciteInputInput"); + await page.setContent(html``); + const calciteInput = await page.find("calcite-input-number"); + const inputEventSpy = await calciteInput.spyOnEvent("calciteInputNumberInput"); await calciteInput.click(); await page.keyboard.press("Backspace"); await page.waitForChanges(); expect(inputEventSpy).toHaveReceivedEvent(); - const input = await page.find("calcite-input >>> input"); + const input = await page.find("calcite-input-number >>> input"); expect(await input.getProperty("value")).toBe("1."); }); diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 309df3fbac5..c1b151c342c 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -844,8 +844,11 @@ export class InputNumber const isValueDeleted = this.previousValue?.length > value.length || this.value?.length > value.length; + const hasTrailingDecimalSeparator = + value.charAt(value.length - 1) === numberStringFormatter.decimal; + const sanitizedValue = - value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted + hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString( // no need to delocalize a string that ia already in latn numerals @@ -864,7 +867,12 @@ export class InputNumber let newLocalizedValue = numberStringFormatter.localize(newValue); - if (newLocalizedValue.length !== newValue.length && origin !== "connected") { + // adds localized trailing decimal zero values + if ( + newLocalizedValue.length !== newValue.length && + origin !== "connected" && + !hasTrailingDecimalSeparator + ) { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, newValue, @@ -872,8 +880,9 @@ export class InputNumber ); } + // adds localized trailing decimal separator this.localizedValue = - value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted + hasTrailingDecimalSeparator && isValueDeleted ? `${newLocalizedValue}${numberStringFormatter.decimal}` : newLocalizedValue; diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 7d6fb5927b5..7ac6b99d79b 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -979,8 +979,11 @@ export class Input const isValueDeleted = this.previousValue?.length > value.length || this.value?.length > value.length; + const hasTrailingDecimalSeparator = + value.charAt(value.length - 1) === numberStringFormatter.decimal; + const sanitizedValue = - value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted + hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString( // no need to delocalize a string that ia already in latn numerals @@ -999,7 +1002,12 @@ export class Input let newLocalizedValue = numberStringFormatter.localize(newValue); - if (newLocalizedValue.length !== newValue.length && origin !== "connected") { + // adds localized trailing decimal zero values + if ( + newLocalizedValue.length !== newValue.length && + origin !== "connected" && + !hasTrailingDecimalSeparator + ) { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, newValue, @@ -1007,8 +1015,9 @@ export class Input ); } + // adds localized trailing decimal separator this.localizedValue = - value.charAt(value.length - 1) === numberStringFormatter.decimal && isValueDeleted + hasTrailingDecimalSeparator && isValueDeleted ? `${newLocalizedValue}${numberStringFormatter.decimal}` : newLocalizedValue; diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index dd2a35cd5d5..256def4ec20 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -140,15 +140,15 @@ export const sanitizeNumberString = (numberString: string): string => return isValidNumber(sanitizedValue) ? isNegativeDecimalOnlyZeros.test(sanitizedValue) ? sanitizedValue - : getBigDecimalString(sanitizedValue) + : getBigDecimalAsString(sanitizedValue) : nonExpoNumString; }); -export function getBigDecimalString(sanitizedValue: string): string { +export function getBigDecimalAsString(sanitizedValue: string): string { const decimals = sanitizedValue.split(".")[1]; const newdecimals = new BigDecimal(sanitizedValue).toString().split(".")[1]; - // adds back trailing deciamls zeros + // adds back trailing decimal zeros if (decimals && !newdecimals && BigInt(decimals) === BigInt(0) && decimals !== newdecimals) { const value = new BigDecimal(sanitizedValue).toString() + "."; const newvalue = value.padEnd(value.length + decimals.length, "0"); From 63dff0433c8fd95ffe6079e1da35f5846fd7fbcc Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Fri, 23 Jun 2023 17:56:13 -0500 Subject: [PATCH 09/21] refactor util method to handle comma decimal separator --- .../components/input-number/input-number.tsx | 5 +-- .../src/components/input/input.tsx | 5 +-- .../calcite-components/src/utils/number.ts | 36 ++++++++++++------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index c1b151c342c..0dd413c1098 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -843,10 +843,7 @@ export class InputNumber const isValueDeleted = this.previousValue?.length > value.length || this.value?.length > value.length; - - const hasTrailingDecimalSeparator = - value.charAt(value.length - 1) === numberStringFormatter.decimal; - + const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === "."; const sanitizedValue = hasTrailingDecimalSeparator && isValueDeleted ? value diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 7ac6b99d79b..a66610049d7 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -978,10 +978,7 @@ export class Input const isValueDeleted = this.previousValue?.length > value.length || this.value?.length > value.length; - - const hasTrailingDecimalSeparator = - value.charAt(value.length - 1) === numberStringFormatter.decimal; - + const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === "."; const sanitizedValue = hasTrailingDecimalSeparator && isValueDeleted ? value diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 256def4ec20..156a3e35276 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -145,17 +145,24 @@ export const sanitizeNumberString = (numberString: string): string => }); export function getBigDecimalAsString(sanitizedValue: string): string { - const decimals = sanitizedValue.split(".")[1]; - const newdecimals = new BigDecimal(sanitizedValue).toString().split(".")[1]; + const sanitizedValueDecimals = sanitizedValue.split(".")[1]; + const value = new BigDecimal(sanitizedValue).toString(); + const bigDecimalValueDecimals = value.split(".")[1]; // adds back trailing decimal zeros - if (decimals && !newdecimals && BigInt(decimals) === BigInt(0) && decimals !== newdecimals) { - const value = new BigDecimal(sanitizedValue).toString() + "."; - const newvalue = value.padEnd(value.length + decimals.length, "0"); - return newvalue; + if (sanitizedValueDecimals && bigDecimalValueDecimals) { + let diff = ""; + [...sanitizedValueDecimals].forEach((decimal) => { + if (!bigDecimalValueDecimals.includes(decimal) && decimal === "0") { + diff += "0"; + } + }); + return `${value}${diff}`; + } else if (sanitizedValueDecimals && !bigDecimalValueDecimals) { + return `${value}.${sanitizedValueDecimals}`; } - return new BigDecimal(sanitizedValue).toString(); + return value; } export function sanitizeExponentialNumberString(numberString: string, func: (s: string) => string): string { @@ -247,16 +254,21 @@ export function addLocalizedTrailingDecimalZeros( ): string { let localizedDecimals; const decimalSeparator = formatter.decimal; + const localizedZeroValue = formatter.localize("0"); if (localizedValue.includes(decimalSeparator)) { - localizedDecimals = localizedValue.split(".")[1]; + localizedDecimals = localizedValue.split(decimalSeparator)[1]; } const decimals = value.split(".")[1]; - - if (decimals && localizedDecimals !== decimals) { - localizedValue = localizedValue + decimalSeparator; + if (decimals && localizedDecimals) { + let diff = ""; [...decimals].forEach((decimal) => { - localizedValue += formatter.localize(decimal); + if (!localizedDecimals.includes(decimal) && decimal === localizedZeroValue) { + diff += localizedZeroValue; + } }); + return `${localizedValue}${diff}`; + } else if (decimals && !localizedDecimals) { + return `${localizedValue}${decimalSeparator}${decimals}`; } return localizedValue; } From 6751aaa2d38bb91044d762e3e7ab1ff4655e392b Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Mon, 26 Jun 2023 13:37:58 -0500 Subject: [PATCH 10/21] refactor util methods --- .../calcite-components/src/utils/number.ts | 45 ++++++------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 156a3e35276..7c7608d5eba 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -147,22 +147,11 @@ export const sanitizeNumberString = (numberString: string): string => export function getBigDecimalAsString(sanitizedValue: string): string { const sanitizedValueDecimals = sanitizedValue.split(".")[1]; const value = new BigDecimal(sanitizedValue).toString(); - const bigDecimalValueDecimals = value.split(".")[1]; - - // adds back trailing decimal zeros - if (sanitizedValueDecimals && bigDecimalValueDecimals) { - let diff = ""; - [...sanitizedValueDecimals].forEach((decimal) => { - if (!bigDecimalValueDecimals.includes(decimal) && decimal === "0") { - diff += "0"; - } - }); - return `${value}${diff}`; - } else if (sanitizedValueDecimals && !bigDecimalValueDecimals) { - return `${value}.${sanitizedValueDecimals}`; - } + const [bigDecimalValueInteger, bigDecimalValueDecimals] = value.split("."); - return value; + return sanitizedValueDecimals && bigDecimalValueDecimals !== sanitizedValueDecimals + ? `${bigDecimalValueInteger}.${sanitizedValueDecimals}` + : value; } export function sanitizeExponentialNumberString(numberString: string, func: (s: string) => string): string { @@ -252,23 +241,15 @@ export function addLocalizedTrailingDecimalZeros( value: string, formatter: NumberStringFormat ): string { - let localizedDecimals; const decimalSeparator = formatter.decimal; - const localizedZeroValue = formatter.localize("0"); - if (localizedValue.includes(decimalSeparator)) { - localizedDecimals = localizedValue.split(decimalSeparator)[1]; - } + const localizedIntegers = localizedValue.includes(decimalSeparator) + ? localizedValue.split(decimalSeparator)[0] + : localizedValue; const decimals = value.split(".")[1]; - if (decimals && localizedDecimals) { - let diff = ""; - [...decimals].forEach((decimal) => { - if (!localizedDecimals.includes(decimal) && decimal === localizedZeroValue) { - diff += localizedZeroValue; - } - }); - return `${localizedValue}${diff}`; - } else if (decimals && !localizedDecimals) { - return `${localizedValue}${decimalSeparator}${decimals}`; - } - return localizedValue; + + return decimals + ? `${localizedIntegers}${decimalSeparator}${Array.from(decimals) + .map((d) => formatter.localize(d)) + .join("")}` + : localizedValue; } From 688b98a4650696c7b7233954d007fba3aafc9f18 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Mon, 26 Jun 2023 15:11:37 -0500 Subject: [PATCH 11/21] update tests --- .../input-number/input-number.e2e.ts | 281 +++++++++++++----- .../src/components/input/input.e2e.ts | 146 ++++----- 2 files changed, 284 insertions(+), 143 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index ebf18b14dc8..3116a272ed0 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -717,21 +717,6 @@ describe("calcite-input-number", () => { const input = await page.find("calcite-input-number >>> input"); expect(await input.getProperty("value")).toBe("2"); }); - - it("allows trailing decimal separator", async () => { - const page = await newE2EPage(); - await page.setContent(html``); - const calciteInput = await page.find("calcite-input-number"); - const inputEventSpy = await calciteInput.spyOnEvent("calciteInputNumberInput"); - - await calciteInput.click(); - await page.keyboard.press("Backspace"); - await page.waitForChanges(); - expect(inputEventSpy).toHaveReceivedEvent(); - const input = await page.find("calcite-input-number >>> input"); - - expect(await input.getProperty("value")).toBe("1."); - }); }); describe("emits events when value is modified", () => { @@ -1129,6 +1114,80 @@ describe("calcite-input-number", () => { expect(await calciteInput.getProperty("value")).toBe(assertedValue); expect(await internalLocaleInput.getProperty("value")).toBe(numberStringFormatter.localize(assertedValue)); }); + + it(`should be able to append values after Backspace for ${locale} locale`, async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + numberStringFormatter.numberFormatOptions = { + locale, + numberingSystem: "latn", + useGrouping: false + }; + const decimalSeparator = numberStringFormatter.decimal; + const calciteInput = await page.find("calcite-input-number"); + const input = await page.find("calcite-input-number >>> input"); + await calciteInput.callMethod("setFocus"); + await typeNumberValue(page, `0${decimalSeparator}0000`); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0000`); + + await page.keyboard.press("Backspace"); + await typeNumberValue(page, "1"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0001`); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}000101`); + }); + + it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + numberStringFormatter.numberFormatOptions = { + locale, + numberingSystem: "latn", + useGrouping: false + }; + const decimalSeparator = numberStringFormatter.decimal; + const calciteInput = await page.find("calcite-input-number"); + const input = await page.find("calcite-input-number >>> input"); + await calciteInput.callMethod("setFocus"); + await typeNumberValue(page, `0${decimalSeparator}01`); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0`); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}`); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); + }); + + it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => { + const page = await newE2EPage(); + await page.setContent(html``); + + numberStringFormatter.numberFormatOptions = { + locale, + numberingSystem: "latn", + useGrouping: false + }; + const input = await page.find("calcite-input-number >>> input"); + expect(await input.getProperty("value")).toBe("0"); + }); }); }); @@ -1413,62 +1472,142 @@ describe("calcite-input-number", () => { expect(await element.getProperty("value")).toBe("10000000"); }); - it("should be able to append value to zeros in decimal after Backspace", async () => { - const page = await newE2EPage(); - await page.setContent(` - - `); - - const element = await page.find("calcite-input-number"); - await element.callMethod("setFocus"); - await typeNumberValue(page, "0.0000"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.0000"); - - await page.keyboard.press("Backspace"); - await typeNumberValue(page, "1"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.0001"); - - await typeNumberValue(page, "01"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.000101"); - }); - - it("should keep leading decimal separator while input is focused on Backspace", async () => { - const page = await newE2EPage(); - await page.setContent(` - - `); - - const element = await page.find("calcite-input-number"); - await element.callMethod("setFocus"); - await typeNumberValue(page, "0.01"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.01"); - - await page.keyboard.press("Backspace"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.0"); - - await page.keyboard.press("Backspace"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0."); - - await typeNumberValue(page, "01"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.01"); - }); - - it("should sanitize leading decimal zeros on initial render", async () => { - const page = await newE2EPage(); - await page.setContent(html``); - const calciteInput = await page.find("calcite-input-number"); - const input = await page.find("calcite-input-number >>> input"); - - expect(await input.getProperty("value")).toBe("0"); - expect(await calciteInput.getProperty("value")).toBe("0.0000"); - }); + // describe.only("locale support for trailing decimal separator and zero decimal values", () => { + // const localesWithIssues = ["ar", "bs", "mk", "no", "es-MX"]; + // locales + // .filter((locale) => !localesWithIssues.includes(locale)) + // .forEach((locale) => { + // it(`should be able to append value to zeros in decimal after Backspace for ${locale} locale`, async () => { + // const page = await newE2EPage(); + // await page.setContent(` + // + // `); + + // numberStringFormatter.numberFormatOptions = { + // locale, + // numberingSystem: "latn", + // useGrouping: false + // }; + // const decimalSeparator = numberStringFormatter.decimal; + // const calciteInput = await page.find("calcite-input-number"); + // const input = await page.find("calcite-input-number >>> input"); + // await calciteInput.callMethod("setFocus"); + // await typeNumberValue(page, `0${decimalSeparator}0000`); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0000`); + + // await page.keyboard.press("Backspace"); + // await typeNumberValue(page, "1"); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0001`); + + // await typeNumberValue(page, "01"); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}000101`); + // }); + + // it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => { + // const page = await newE2EPage(); + // await page.setContent(` + // + // `); + + // numberStringFormatter.numberFormatOptions = { + // locale, + // numberingSystem: "latn", + // useGrouping: false + // }; + // const decimalSeparator = numberStringFormatter.decimal; + // const calciteInput = await page.find("calcite-input-number"); + // const input = await page.find("calcite-input-number >>> input"); + // await calciteInput.callMethod("setFocus"); + // await typeNumberValue(page, `0${decimalSeparator}01`); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); + + // await page.keyboard.press("Backspace"); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0`); + + // await page.keyboard.press("Backspace"); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}`); + + // await typeNumberValue(page, "01"); + // await page.waitForChanges(); + // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); + // }); + + // it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => { + // const page = await newE2EPage(); + // await page.setContent(html``); + + // numberStringFormatter.numberFormatOptions = { + // locale, + // numberingSystem: "latn", + // useGrouping: false + // }; + // const input = await page.find("calcite-input-number >>> input"); + // expect(await input.getProperty("value")).toBe("0"); + // }); + // }); + // }); + + // const page = await newE2EPage(); + // await page.setContent(` + // + // `); + + // const element = await page.find("calcite-input-number"); + // await element.callMethod("setFocus"); + // await typeNumberValue(page, "0.0000"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0.0000"); + + // await page.keyboard.press("Backspace"); + // await typeNumberValue(page, "1"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0.0001"); + + // await typeNumberValue(page, "01"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0.000101"); + // }); + + // it("should keep leading decimal separator while input is focused on Backspace", async () => { + // const page = await newE2EPage(); + // await page.setContent(` + // + // `); + + // const element = await page.find("calcite-input-number"); + // await element.callMethod("setFocus"); + // await typeNumberValue(page, "0.01"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0.01"); + + // await page.keyboard.press("Backspace"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0.0"); + + // await page.keyboard.press("Backspace"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0."); + + // await typeNumberValue(page, "01"); + // await page.waitForChanges(); + // expect(await element.getProperty("value")).toBe("0.01"); + // }); + + // it("should sanitize leading decimal zeros on initial render", async () => { + // const page = await newE2EPage(); + // await page.setContent(html``); + // const calciteInput = await page.find("calcite-input-number"); + // const input = await page.find("calcite-input-number >>> input"); + + // expect(await input.getProperty("value")).toBe("0"); + // expect(await calciteInput.getProperty("value")).toBe("0.0000"); + // }); it("sanitize extra dashes from value", async () => { const page = await newE2EPage(); diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index 3ec596ac92f..8af285c3789 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -703,21 +703,6 @@ describe("calcite-input", () => { expect(inputEventSpy).not.toHaveReceivedEvent(); expect(changeEventSpy).not.toHaveReceivedEvent(); }); - - it("allows trailing decimal separator", async () => { - const page = await newE2EPage(); - await page.setContent(html``); - const calciteInput = await page.find("calcite-input"); - const inputEventSpy = await calciteInput.spyOnEvent("calciteInputInput"); - - await calciteInput.click(); - await page.keyboard.press("Backspace"); - await page.waitForChanges(); - expect(inputEventSpy).toHaveReceivedEvent(); - const input = await page.find("calcite-input >>> input"); - - expect(await input.getProperty("value")).toBe("1."); - }); }); describe("emits events when value is modified", () => { @@ -1306,6 +1291,80 @@ describe("calcite-input", () => { expect(await calciteInput.getProperty("value")).toBe(assertedValue); expect(await internalLocaleInput.getProperty("value")).toBe(localizedValue); }); + + it(`should be able to append values after Backspace for ${locale} locale`, async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + numberStringFormatter.numberFormatOptions = { + locale, + numberingSystem: "latn", + useGrouping: false + }; + const decimalSeparator = numberStringFormatter.decimal; + const calciteInput = await page.find("calcite-input"); + const input = await page.find("calcite-input >>> input"); + await calciteInput.callMethod("setFocus"); + await typeNumberValue(page, `0${decimalSeparator}0000`); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0000`); + + await page.keyboard.press("Backspace"); + await typeNumberValue(page, "1"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0001`); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}000101`); + }); + + it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => { + const page = await newE2EPage(); + await page.setContent(` + + `); + + numberStringFormatter.numberFormatOptions = { + locale, + numberingSystem: "latn", + useGrouping: false + }; + const decimalSeparator = numberStringFormatter.decimal; + const calciteInput = await page.find("calcite-input"); + const input = await page.find("calcite-input >>> input"); + await calciteInput.callMethod("setFocus"); + await typeNumberValue(page, `0${decimalSeparator}01`); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0`); + + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}`); + + await typeNumberValue(page, "01"); + await page.waitForChanges(); + expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); + }); + + it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => { + const page = await newE2EPage(); + await page.setContent(html``); + + numberStringFormatter.numberFormatOptions = { + locale, + numberingSystem: "latn", + useGrouping: false + }; + const input = await page.find("calcite-input >>> input"); + expect(await input.getProperty("value")).toBe("0"); + }); }); }); @@ -1591,63 +1650,6 @@ describe("calcite-input", () => { expect(await element.getProperty("value")).toBe("10000000"); }); - it("should be able to append value to zeros in decimal after Backspace", async () => { - const page = await newE2EPage(); - await page.setContent(` - - `); - - const element = await page.find("calcite-input-number"); - await element.callMethod("setFocus"); - await typeNumberValue(page, "0.0000"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.0000"); - - await page.keyboard.press("Backspace"); - await typeNumberValue(page, "1"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.0001"); - - await typeNumberValue(page, "01"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.000101"); - }); - - it("should keep leading decimal separator while input is focused on Backspace", async () => { - const page = await newE2EPage(); - await page.setContent(` - - `); - - const element = await page.find("calcite-input-number"); - await element.callMethod("setFocus"); - await typeNumberValue(page, "0.01"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.01"); - - await page.keyboard.press("Backspace"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.0"); - - await page.keyboard.press("Backspace"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0."); - - await typeNumberValue(page, "01"); - await page.waitForChanges(); - expect(await element.getProperty("value")).toBe("0.01"); - }); - - it("should sanitize leading decimal zeros on initial render", async () => { - const page = await newE2EPage(); - await page.setContent(html``); - const calciteInput = await page.find("calcite-input"); - const input = await page.find("calcite-input >>> input"); - - expect(await input.getProperty("value")).toBe("0"); - expect(await calciteInput.getProperty("value")).toBe("0.0000"); - }); - it("sanitize extra dashes from number input value", async () => { const page = await newE2EPage(); await page.setContent(``); From f7b9f943035c1a0500abb8c799caf883f8411c1b Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Mon, 26 Jun 2023 15:14:36 -0500 Subject: [PATCH 12/21] remove commented code --- .../input-number/input-number.e2e.ts | 137 ------------------ .../components/input-number/input-number.tsx | 1 - .../src/components/input/input.tsx | 1 - 3 files changed, 139 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 3116a272ed0..008f1607498 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -1472,143 +1472,6 @@ describe("calcite-input-number", () => { expect(await element.getProperty("value")).toBe("10000000"); }); - // describe.only("locale support for trailing decimal separator and zero decimal values", () => { - // const localesWithIssues = ["ar", "bs", "mk", "no", "es-MX"]; - // locales - // .filter((locale) => !localesWithIssues.includes(locale)) - // .forEach((locale) => { - // it(`should be able to append value to zeros in decimal after Backspace for ${locale} locale`, async () => { - // const page = await newE2EPage(); - // await page.setContent(` - // - // `); - - // numberStringFormatter.numberFormatOptions = { - // locale, - // numberingSystem: "latn", - // useGrouping: false - // }; - // const decimalSeparator = numberStringFormatter.decimal; - // const calciteInput = await page.find("calcite-input-number"); - // const input = await page.find("calcite-input-number >>> input"); - // await calciteInput.callMethod("setFocus"); - // await typeNumberValue(page, `0${decimalSeparator}0000`); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0000`); - - // await page.keyboard.press("Backspace"); - // await typeNumberValue(page, "1"); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0001`); - - // await typeNumberValue(page, "01"); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}000101`); - // }); - - // it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => { - // const page = await newE2EPage(); - // await page.setContent(` - // - // `); - - // numberStringFormatter.numberFormatOptions = { - // locale, - // numberingSystem: "latn", - // useGrouping: false - // }; - // const decimalSeparator = numberStringFormatter.decimal; - // const calciteInput = await page.find("calcite-input-number"); - // const input = await page.find("calcite-input-number >>> input"); - // await calciteInput.callMethod("setFocus"); - // await typeNumberValue(page, `0${decimalSeparator}01`); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); - - // await page.keyboard.press("Backspace"); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0`); - - // await page.keyboard.press("Backspace"); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}`); - - // await typeNumberValue(page, "01"); - // await page.waitForChanges(); - // expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`); - // }); - - // it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => { - // const page = await newE2EPage(); - // await page.setContent(html``); - - // numberStringFormatter.numberFormatOptions = { - // locale, - // numberingSystem: "latn", - // useGrouping: false - // }; - // const input = await page.find("calcite-input-number >>> input"); - // expect(await input.getProperty("value")).toBe("0"); - // }); - // }); - // }); - - // const page = await newE2EPage(); - // await page.setContent(` - // - // `); - - // const element = await page.find("calcite-input-number"); - // await element.callMethod("setFocus"); - // await typeNumberValue(page, "0.0000"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0.0000"); - - // await page.keyboard.press("Backspace"); - // await typeNumberValue(page, "1"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0.0001"); - - // await typeNumberValue(page, "01"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0.000101"); - // }); - - // it("should keep leading decimal separator while input is focused on Backspace", async () => { - // const page = await newE2EPage(); - // await page.setContent(` - // - // `); - - // const element = await page.find("calcite-input-number"); - // await element.callMethod("setFocus"); - // await typeNumberValue(page, "0.01"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0.01"); - - // await page.keyboard.press("Backspace"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0.0"); - - // await page.keyboard.press("Backspace"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0."); - - // await typeNumberValue(page, "01"); - // await page.waitForChanges(); - // expect(await element.getProperty("value")).toBe("0.01"); - // }); - - // it("should sanitize leading decimal zeros on initial render", async () => { - // const page = await newE2EPage(); - // await page.setContent(html``); - // const calciteInput = await page.find("calcite-input-number"); - // const input = await page.find("calcite-input-number >>> input"); - - // expect(await input.getProperty("value")).toBe("0"); - // expect(await calciteInput.getProperty("value")).toBe("0.0000"); - // }); - it("sanitize extra dashes from value", async () => { const page = await newE2EPage(); await page.setContent(``); diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index afced694e7b..816b201b7fd 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -864,7 +864,6 @@ export class InputNumber let newLocalizedValue = numberStringFormatter.localize(newValue); - // adds localized trailing decimal zero values if ( newLocalizedValue.length !== newValue.length && origin !== "connected" && diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index dbd7e3573d9..a5be3256e77 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -999,7 +999,6 @@ export class Input let newLocalizedValue = numberStringFormatter.localize(newValue); - // adds localized trailing decimal zero values if ( newLocalizedValue.length !== newValue.length && origin !== "connected" && From 43b307529b9c23ca68f8edce25bd96cd41a07351 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Mon, 26 Jun 2023 15:33:46 -0500 Subject: [PATCH 13/21] add missing type for tests --- .../calcite-components/src/components/input/input.e2e.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index 8af285c3789..03857bac1c5 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1295,7 +1295,7 @@ describe("calcite-input", () => { it(`should be able to append values after Backspace for ${locale} locale`, async () => { const page = await newE2EPage(); await page.setContent(` - + `); numberStringFormatter.numberFormatOptions = { @@ -1324,7 +1324,7 @@ describe("calcite-input", () => { it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => { const page = await newE2EPage(); await page.setContent(` - + `); numberStringFormatter.numberFormatOptions = { @@ -1355,7 +1355,7 @@ describe("calcite-input", () => { it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => { const page = await newE2EPage(); - await page.setContent(html``); + await page.setContent(html``); numberStringFormatter.numberFormatOptions = { locale, From cd4a3ac52df52885cb9c388a41a730171ed26adf Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Tue, 27 Jun 2023 11:42:11 -0500 Subject: [PATCH 14/21] fix failing spec tests --- .../components/input-number/input-number.tsx | 2 +- .../src/components/input/input.tsx | 2 +- .../src/utils/number.spec.ts | 32 +++++++++++++++++++ .../calcite-components/src/utils/number.ts | 23 +++++++------ 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 816b201b7fd..2072e4eb66e 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -865,7 +865,7 @@ export class InputNumber let newLocalizedValue = numberStringFormatter.localize(newValue); if ( - newLocalizedValue.length !== newValue.length && + numberStringFormatter.delocalize(newLocalizedValue).length !== newValue.length && origin !== "connected" && !hasTrailingDecimalSeparator ) { diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index a5be3256e77..6c9d6cd2c66 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -1000,7 +1000,7 @@ export class Input let newLocalizedValue = numberStringFormatter.localize(newValue); if ( - newLocalizedValue.length !== newValue.length && + numberStringFormatter.delocalize(newLocalizedValue).length !== newValue.length && origin !== "connected" && !hasTrailingDecimalSeparator ) { diff --git a/packages/calcite-components/src/utils/number.spec.ts b/packages/calcite-components/src/utils/number.spec.ts index 85d10c9cdaa..3a5938f44c7 100644 --- a/packages/calcite-components/src/utils/number.spec.ts +++ b/packages/calcite-components/src/utils/number.spec.ts @@ -1,6 +1,7 @@ import { locales, numberStringFormatter } from "./locale"; import { BigDecimal, + addLocalizedTrailingDecimalZeros, expandExponentialNumberString, isValidNumber, parseNumberString, @@ -169,3 +170,34 @@ describe("expandExponentialNumberString", () => { expect(expandExponentialNumberString("")).toBe(""); }); }); + +describe("addLocalizedTrailingDecimalZeros", () => { + locales.forEach((locale) => { + it(`add back sanitized trailing decimal zero values - ${locale}`, () => { + numberStringFormatter.numberFormatOptions = { + locale, + // the group separator is different in arabic depending on the numberingSystem + numberingSystem: locale === "ar" ? "arab" : "latn", + useGrouping: true + }; + const localizedValue = numberStringFormatter.localize("123456.000"); + const localizedZeroValue = numberStringFormatter.localize("0"); + const result = `${localizedValue}${numberStringFormatter.decimal}`.padEnd( + localizedValue.length + 4, + localizedZeroValue + ); + expect(addLocalizedTrailingDecimalZeros(localizedValue, "123456.000", numberStringFormatter)).toBe(result); + }); + + it(`returns same value if no trailing decimal zero value is removed- ${locale}`, () => { + numberStringFormatter.numberFormatOptions = { + locale, + // the group separator is different in arabic depending on the numberingSystem + numberingSystem: locale === "ar" ? "arab" : "latn", + useGrouping: true + }; + const localizedValue = numberStringFormatter.localize("0.001"); + expect(addLocalizedTrailingDecimalZeros(localizedValue, "0.001", numberStringFormatter)).toBe(localizedValue); + }); + }); +}); diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 7c7608d5eba..729dcd4aa88 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -241,15 +241,18 @@ export function addLocalizedTrailingDecimalZeros( value: string, formatter: NumberStringFormat ): string { - const decimalSeparator = formatter.decimal; - const localizedIntegers = localizedValue.includes(decimalSeparator) - ? localizedValue.split(decimalSeparator)[0] - : localizedValue; const decimals = value.split(".")[1]; - - return decimals - ? `${localizedIntegers}${decimalSeparator}${Array.from(decimals) - .map((d) => formatter.localize(d)) - .join("")}` - : localizedValue; + const lengthOfDecimals = decimals?.length; + const decimalSeparator = formatter.decimal; + const localizedDecimals = localizedValue.split(decimalSeparator)[1]; + + if (decimals) { + const lengthOfTrailingZeros = localizedDecimals ? lengthOfDecimals - localizedDecimals.length : lengthOfDecimals; + localizedValue = + !localizedValue.includes(decimalSeparator) && lengthOfTrailingZeros > 0 + ? `${localizedValue}${decimalSeparator}` + : localizedValue; + return localizedValue.padEnd(localizedValue.length + lengthOfTrailingZeros, formatter.localize("0")); + } + return localizedValue; } From 98c86d476284010d04d858ce3de0a7bbed03771a Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Tue, 27 Jun 2023 16:02:36 -0500 Subject: [PATCH 15/21] use regex --- .../components/input-number/input-number.tsx | 10 +--------- .../src/components/input/input.tsx | 10 +--------- .../calcite-components/src/utils/number.ts | 19 ++++++++----------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 2072e4eb66e..1d0411f61af 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -845,15 +845,7 @@ export class InputNumber this.previousValue?.length > value.length || this.value?.length > value.length; const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === "."; const sanitizedValue = - hasTrailingDecimalSeparator && isValueDeleted - ? value - : sanitizeNumberString( - // no need to delocalize a string that ia already in latn numerals - (this.numberingSystem && this.numberingSystem !== "latn") || - defaultNumberingSystem !== "latn" - ? numberStringFormatter.delocalize(value) - : value - ); + hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString(value); const newValue = value && !sanitizedValue diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 6c9d6cd2c66..6785dc98e2a 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -980,15 +980,7 @@ export class Input this.previousValue?.length > value.length || this.value?.length > value.length; const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === "."; const sanitizedValue = - hasTrailingDecimalSeparator && isValueDeleted - ? value - : sanitizeNumberString( - // no need to delocalize a string that ia already in latn numerals - (this.numberingSystem && this.numberingSystem !== "latn") || - defaultNumberingSystem !== "latn" - ? numberStringFormatter.delocalize(value) - : value - ); + hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString(value); const newValue = value && !sanitizedValue diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 729dcd4aa88..af537d23f63 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -130,6 +130,7 @@ const allLeadingZerosOptionallyNegative = /^([-0])0+(?=\d)/; const decimalOnlyAtEndOfString = /(?!^\.)\.$/; const allHyphensExceptTheStart = /(?!^-)-/g; const isNegativeDecimalOnlyZeros = /^-\b0\b\.?0*$/; +const hasTrailingDecimalZeros = /0*$/; export const sanitizeNumberString = (numberString: string): string => sanitizeExponentialNumberString(numberString, (nonExpoNumString) => { @@ -241,18 +242,14 @@ export function addLocalizedTrailingDecimalZeros( value: string, formatter: NumberStringFormat ): string { - const decimals = value.split(".")[1]; - const lengthOfDecimals = decimals?.length; + const trailingDecimalZeros = value.match(hasTrailingDecimalZeros); const decimalSeparator = formatter.decimal; - const localizedDecimals = localizedValue.split(decimalSeparator)[1]; - - if (decimals) { - const lengthOfTrailingZeros = localizedDecimals ? lengthOfDecimals - localizedDecimals.length : lengthOfDecimals; - localizedValue = - !localizedValue.includes(decimalSeparator) && lengthOfTrailingZeros > 0 - ? `${localizedValue}${decimalSeparator}` - : localizedValue; - return localizedValue.padEnd(localizedValue.length + lengthOfTrailingZeros, formatter.localize("0")); + + if (trailingDecimalZeros[0] && value.includes(".")) { + localizedValue = !localizedValue.includes(decimalSeparator) + ? `${localizedValue}${decimalSeparator}` + : localizedValue; + return localizedValue.padEnd(localizedValue.length + trailingDecimalZeros[0].length, formatter.localize("0")); } return localizedValue; } From ce04bab96f06bbc254f4b797f6433bbd5f7550ea Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Tue, 27 Jun 2023 17:01:49 -0500 Subject: [PATCH 16/21] add more spec tests --- packages/calcite-components/src/utils/number.spec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/calcite-components/src/utils/number.spec.ts b/packages/calcite-components/src/utils/number.spec.ts index 3a5938f44c7..d0bedfc482f 100644 --- a/packages/calcite-components/src/utils/number.spec.ts +++ b/packages/calcite-components/src/utils/number.spec.ts @@ -3,6 +3,7 @@ import { BigDecimal, addLocalizedTrailingDecimalZeros, expandExponentialNumberString, + getBigDecimalAsString, isValidNumber, parseNumberString, sanitizeNumberString @@ -83,6 +84,7 @@ describe("sanitizeNumberString", () => { const nonLeadingZeroExponentialString = "500000e00600"; const multiDecimalExponentialString = "1.2e2.1"; const crazyExponentialString = "-2-.-1ee.5-3e.1..e--09"; + const trailingDecimalZeros = "0.110000"; expect(sanitizeNumberString(stringWithMultipleDashes)).toBe("1234"); expect(sanitizeNumberString(negativeStringWithMultipleDashes)).toBe("-1234"); @@ -103,6 +105,7 @@ describe("sanitizeNumberString", () => { expect(sanitizeNumberString(nonLeadingZeroExponentialString)).toBe("500000e600"); expect(sanitizeNumberString(multiDecimalExponentialString)).toBe("1.2e21"); expect(sanitizeNumberString(crazyExponentialString)).toBe("-2.1e53109"); + expect(sanitizeNumberString(trailingDecimalZeros)).toBe("0.110000"); }); }); From ecbc6970c214fe2ae2854d450807ecd4ccb774ea Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Tue, 27 Jun 2023 17:31:30 -0500 Subject: [PATCH 17/21] remove unused imports --- .../src/components/input-number/input-number.tsx | 1 - packages/calcite-components/src/components/input/input.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 1d0411f61af..559b667fec5 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -42,7 +42,6 @@ import { } from "../../utils/loadable"; import { connectLocalized, - defaultNumberingSystem, disconnectLocalized, LocalizedComponent, NumberingSystem, diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 6785dc98e2a..afde20cb850 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -42,7 +42,6 @@ import { } from "../../utils/loadable"; import { connectLocalized, - defaultNumberingSystem, disconnectLocalized, LocalizedComponent, NumberingSystem, From de31f7cc14bd57f595bd8b0e568043bbcea8dc27 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Wed, 28 Jun 2023 11:09:14 -0500 Subject: [PATCH 18/21] simplify util method logic --- packages/calcite-components/src/utils/number.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index af537d23f63..2b97557a16b 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -242,14 +242,14 @@ export function addLocalizedTrailingDecimalZeros( value: string, formatter: NumberStringFormat ): string { - const trailingDecimalZeros = value.match(hasTrailingDecimalZeros); + const trailingDecimalZeros = value.match(hasTrailingDecimalZeros)[0]; const decimalSeparator = formatter.decimal; - if (trailingDecimalZeros[0] && value.includes(".")) { + if (trailingDecimalZeros && value.includes(".")) { localizedValue = !localizedValue.includes(decimalSeparator) ? `${localizedValue}${decimalSeparator}` : localizedValue; - return localizedValue.padEnd(localizedValue.length + trailingDecimalZeros[0].length, formatter.localize("0")); + return localizedValue.padEnd(localizedValue.length + trailingDecimalZeros.length, formatter.localize("0")); } return localizedValue; } From c50740079b7699064616a1a90e69c9eba58e4dd4 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Thu, 29 Jun 2023 15:43:18 -0500 Subject: [PATCH 19/21] feedback changes and more e2e tests added --- .../input-number/input-number.e2e.ts | 26 ++++++++++++ .../components/input-number/input-number.tsx | 6 +-- .../src/components/input/input.e2e.ts | 26 ++++++++++++ .../src/components/input/input.tsx | 6 +-- .../src/utils/number.spec.ts | 42 +++++++++++++++---- .../calcite-components/src/utils/number.ts | 22 ++++++---- 6 files changed, 102 insertions(+), 26 deletions(-) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 008f1607498..563f3853736 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -899,6 +899,32 @@ describe("calcite-input-number", () => { expect(Number(await element.getProperty("value"))).toBe(195); }); + it("allows deleting exponentail number from decimal and adding trailing zeros", async () => { + const page = await newE2EPage(); + await page.setContent(html``); + + const calciteInput = await page.find("calcite-input-number"); + const input = await page.find("calcite-input-number >>> input"); + await calciteInput.callMethod("setFocus"); + await page.waitForChanges(); + await typeNumberValue(page, "2.100e10"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1e10"); + expect(await input.getProperty("value")).toBe("2.1e10"); + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1e1"); + expect(await input.getProperty("value")).toBe("2.1e1"); + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1"); + expect(await input.getProperty("value")).toBe("2.1"); + await page.keyboard.type("000"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1000"); + expect(await input.getProperty("value")).toBe("2.1000"); + }); + it("disallows typing non-numeric characters with shift modifier key down", async () => { const page = await newE2EPage(); await page.setContent(html``); diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 559b667fec5..356b325c3c4 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -855,11 +855,7 @@ export class InputNumber let newLocalizedValue = numberStringFormatter.localize(newValue); - if ( - numberStringFormatter.delocalize(newLocalizedValue).length !== newValue.length && - origin !== "connected" && - !hasTrailingDecimalSeparator - ) { + if (origin !== "connected" && !hasTrailingDecimalSeparator) { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, newValue, diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index 03857bac1c5..d9d913c3bad 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1055,6 +1055,32 @@ describe("calcite-input", () => { expect(Number(await element.getProperty("value"))).toBe(195); }); + it("allows deleting exponentail number from decimal and adding trailing zeros", async () => { + const page = await newE2EPage(); + await page.setContent(html``); + + const calciteInput = await page.find("calcite-input"); + const input = await page.find("calcite-input >>> input"); + await calciteInput.callMethod("setFocus"); + await page.waitForChanges(); + await typeNumberValue(page, "2.100e10"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1e10"); + expect(await input.getProperty("value")).toBe("2.1e10"); + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1e1"); + expect(await input.getProperty("value")).toBe("2.1e1"); + await page.keyboard.press("Backspace"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1"); + expect(await input.getProperty("value")).toBe("2.1"); + await page.keyboard.type("000"); + await page.waitForChanges(); + expect(await calciteInput.getProperty("value")).toBe("2.1000"); + expect(await input.getProperty("value")).toBe("2.1000"); + }); + it("disallows typing any non-numeric characters with shift modifier key down", async () => { const page = await newE2EPage(); await page.setContent(html``); diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index afde20cb850..3e63f670163 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -990,11 +990,7 @@ export class Input let newLocalizedValue = numberStringFormatter.localize(newValue); - if ( - numberStringFormatter.delocalize(newLocalizedValue).length !== newValue.length && - origin !== "connected" && - !hasTrailingDecimalSeparator - ) { + if (origin !== "connected" && !hasTrailingDecimalSeparator) { newLocalizedValue = addLocalizedTrailingDecimalZeros( newLocalizedValue, newValue, diff --git a/packages/calcite-components/src/utils/number.spec.ts b/packages/calcite-components/src/utils/number.spec.ts index d0bedfc482f..8e4fd5088b8 100644 --- a/packages/calcite-components/src/utils/number.spec.ts +++ b/packages/calcite-components/src/utils/number.spec.ts @@ -175,6 +175,12 @@ describe("expandExponentialNumberString", () => { }); describe("addLocalizedTrailingDecimalZeros", () => { + function getLocalizedDeimalValue(value: string, trailingZeros: number): String { + const localizedValue = numberStringFormatter.localize(value); + const localizedZeroValue = numberStringFormatter.localize("0"); + return `${localizedValue}`.padEnd(localizedValue.length + trailingZeros, localizedZeroValue); + } + locales.forEach((locale) => { it(`add back sanitized trailing decimal zero values - ${locale}`, () => { numberStringFormatter.numberFormatOptions = { @@ -183,16 +189,36 @@ describe("addLocalizedTrailingDecimalZeros", () => { numberingSystem: locale === "ar" ? "arab" : "latn", useGrouping: true }; - const localizedValue = numberStringFormatter.localize("123456.000"); - const localizedZeroValue = numberStringFormatter.localize("0"); - const result = `${localizedValue}${numberStringFormatter.decimal}`.padEnd( - localizedValue.length + 4, - localizedZeroValue - ); - expect(addLocalizedTrailingDecimalZeros(localizedValue, "123456.000", numberStringFormatter)).toBe(result); + + const stringWithTrailingZeros = "123456.1000"; + const bigDecimalWithTrailingZeros = + "1230000000000000000000000000000.00000000000000000000045000000000000000000000000"; + const negativeExponentialString = "-10.021e10000"; + + expect( + addLocalizedTrailingDecimalZeros( + numberStringFormatter.localize(stringWithTrailingZeros), + stringWithTrailingZeros, + numberStringFormatter + ) + ).toBe(getLocalizedDeimalValue(stringWithTrailingZeros, 3)); + expect( + addLocalizedTrailingDecimalZeros( + numberStringFormatter.localize(bigDecimalWithTrailingZeros), + bigDecimalWithTrailingZeros, + numberStringFormatter + ) + ).toBe(getLocalizedDeimalValue(bigDecimalWithTrailingZeros, 24)); + expect( + addLocalizedTrailingDecimalZeros( + numberStringFormatter.localize(negativeExponentialString), + negativeExponentialString, + numberStringFormatter + ) + ).toBe(numberStringFormatter.localize(negativeExponentialString)); }); - it(`returns same value if no trailing decimal zero value is removed- ${locale}`, () => { + it(`returns same value if no trailing decimal zero value is removed - ${locale}`, () => { numberStringFormatter.numberFormatOptions = { locale, // the group separator is different in arabic depending on the numberingSystem diff --git a/packages/calcite-components/src/utils/number.ts b/packages/calcite-components/src/utils/number.ts index 2b97557a16b..e4ab0a4d6d5 100644 --- a/packages/calcite-components/src/utils/number.ts +++ b/packages/calcite-components/src/utils/number.ts @@ -242,14 +242,20 @@ export function addLocalizedTrailingDecimalZeros( value: string, formatter: NumberStringFormat ): string { - const trailingDecimalZeros = value.match(hasTrailingDecimalZeros)[0]; - const decimalSeparator = formatter.decimal; - - if (trailingDecimalZeros && value.includes(".")) { - localizedValue = !localizedValue.includes(decimalSeparator) - ? `${localizedValue}${decimalSeparator}` - : localizedValue; - return localizedValue.padEnd(localizedValue.length + trailingDecimalZeros.length, formatter.localize("0")); + const decimals = value.split(".")[1]; + if (decimals) { + const trailingDecimalZeros = decimals.match(hasTrailingDecimalZeros)[0]; + if ( + trailingDecimalZeros && + formatter.delocalize(localizedValue).length !== value.length && + decimals.indexOf("e") === -1 + ) { + const decimalSeparator = formatter.decimal; + localizedValue = !localizedValue.includes(decimalSeparator) + ? `${localizedValue}${decimalSeparator}` + : localizedValue; + return localizedValue.padEnd(localizedValue.length + trailingDecimalZeros.length, formatter.localize("0")); + } } return localizedValue; } From 4a5713083f4b641c6cddb31834d1b5704623f4b0 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Thu, 29 Jun 2023 15:48:07 -0500 Subject: [PATCH 20/21] remove unused methods in number spec test --- packages/calcite-components/src/utils/number.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/calcite-components/src/utils/number.spec.ts b/packages/calcite-components/src/utils/number.spec.ts index 8e4fd5088b8..bfd82119f6b 100644 --- a/packages/calcite-components/src/utils/number.spec.ts +++ b/packages/calcite-components/src/utils/number.spec.ts @@ -3,7 +3,6 @@ import { BigDecimal, addLocalizedTrailingDecimalZeros, expandExponentialNumberString, - getBigDecimalAsString, isValidNumber, parseNumberString, sanitizeNumberString From dfc931101105e0a1c403bb460b024b404d98c3df Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Thu, 29 Jun 2023 17:05:42 -0500 Subject: [PATCH 21/21] add new lines in test --- .../src/components/input-number/input-number.e2e.ts | 3 +++ packages/calcite-components/src/components/input/input.e2e.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packages/calcite-components/src/components/input-number/input-number.e2e.ts b/packages/calcite-components/src/components/input-number/input-number.e2e.ts index 563f3853736..834372447af 100644 --- a/packages/calcite-components/src/components/input-number/input-number.e2e.ts +++ b/packages/calcite-components/src/components/input-number/input-number.e2e.ts @@ -911,14 +911,17 @@ describe("calcite-input-number", () => { await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1e10"); expect(await input.getProperty("value")).toBe("2.1e10"); + await page.keyboard.press("Backspace"); await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1e1"); expect(await input.getProperty("value")).toBe("2.1e1"); + await page.keyboard.press("Backspace"); await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1"); expect(await input.getProperty("value")).toBe("2.1"); + await page.keyboard.type("000"); await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1000"); diff --git a/packages/calcite-components/src/components/input/input.e2e.ts b/packages/calcite-components/src/components/input/input.e2e.ts index d9d913c3bad..7ca4e0a3302 100644 --- a/packages/calcite-components/src/components/input/input.e2e.ts +++ b/packages/calcite-components/src/components/input/input.e2e.ts @@ -1067,14 +1067,17 @@ describe("calcite-input", () => { await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1e10"); expect(await input.getProperty("value")).toBe("2.1e10"); + await page.keyboard.press("Backspace"); await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1e1"); expect(await input.getProperty("value")).toBe("2.1e1"); + await page.keyboard.press("Backspace"); await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1"); expect(await input.getProperty("value")).toBe("2.1"); + await page.keyboard.type("000"); await page.waitForChanges(); expect(await calciteInput.getProperty("value")).toBe("2.1000");