diff --git a/packages/calcite-components/src/components/autocomplete/autocomplete.tsx b/packages/calcite-components/src/components/autocomplete/autocomplete.tsx index 73ae316fe96..c0d22a02066 100644 --- a/packages/calcite-components/src/components/autocomplete/autocomplete.tsx +++ b/packages/calcite-components/src/components/autocomplete/autocomplete.tsx @@ -8,6 +8,7 @@ import { state, JsxNode, stringOrBoolean, + LuminaJsx, } from "@arcgis/lumina"; import { useWatchAttributes } from "@arcgis/components-controllers"; import { debounce } from "lodash-es"; @@ -166,9 +167,9 @@ export class Autocomplete * Specifies the type of content to autocomplete, for use in forms. * Read the native attribute's documentation on MDN for more info. * - * @mdn [step](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) + * @mdn [autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) */ - @property() autocomplete: string; + @property() autocomplete: AutoFill; /** When `true`, interaction is prevented and the component is displayed with lower opacity. */ @property({ reflect: true }) disabled = false; @@ -727,17 +728,9 @@ export class Autocomplete override render(): JsxNode { const { disabled, listId, inputId, isOpen } = this; - const autofocus = this.el.autofocus || this.el.hasAttribute("autofocus") ? true : null; - const enterKeyHint = this.el.getAttribute("enterkeyhint"); - const inputMode = this.el.getAttribute("inputmode") as - | "none" - | "text" - | "search" - | "email" - | "tel" - | "url" - | "numeric" - | "decimal"; + const autofocus = this.el.autofocus; + const enterKeyHint = this.el.enterKeyHint as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"]; + const inputMode = this.el.inputMode as LuminaJsx.HTMLElementTags["input"]["inputMode"]; return ( 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 0ca19b4e048..0d7ec650112 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -159,9 +159,9 @@ export class InputNumber * Specifies the type of content to autocomplete, for use in forms. * Read the native attribute's documentation on MDN for more info. * - * @mdn [step](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) + * @mdn [autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) */ - @property() autocomplete: string; + @property() autocomplete: AutoFill; /** When `true`, a clear button is displayed when the component has a value. */ @property({ reflect: true }) clearable = false; @@ -976,20 +976,13 @@ export class InputNumber aria-errormessage={IDS.validationMessage} ariaInvalid={this.status === "invalid"} ariaLabel={getLabelText(this)} - autocomplete={this.autocomplete as LuminaJsx.HTMLElementTags["input"]["autocomplete"]} - autofocus={this.el.autofocus ? true : null} + autocomplete={this.autocomplete} + autofocus={this.el.autofocus} defaultValue={this.defaultValue} - disabled={this.disabled ? true : null} - enterKeyHint={ - (this.el.enterKeyHint || - this.el.getAttribute( - "enterkeyhint", - )) as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"] - } + disabled={this.disabled} + enterKeyHint={this.el.enterKeyHint as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"]} inputMode={ - (this.el.inputMode || - this.el.getAttribute("inputmode") || - "decimal") as LuminaJsx.HTMLElementTags["input"]["inputMode"] + (this.el.inputMode as LuminaJsx.HTMLElementTags["input"]["inputMode"]) || "decimal" } key="localized-input" maxLength={this.maxLength} diff --git a/packages/calcite-components/src/components/input-text/input-text.tsx b/packages/calcite-components/src/components/input-text/input-text.tsx index 4f36e86102b..de33abd023d 100644 --- a/packages/calcite-components/src/components/input-text/input-text.tsx +++ b/packages/calcite-components/src/components/input-text/input-text.tsx @@ -137,9 +137,9 @@ export class InputText * Specifies the type of content to autocomplete, for use in forms. * Read the native attribute's documentation on MDN for more info. * - * @mdn [step](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) + * @mdn [autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) */ - @property() autocomplete: string; + @property() autocomplete: AutoFill; /** When `true`, a clear button is displayed when the component has a value. */ @property({ reflect: true }) clearable = false; @@ -585,24 +585,16 @@ export class InputText aria-errormessage={IDS.validationMessage} ariaInvalid={this.status === "invalid"} ariaLabel={getLabelText(this)} - autocomplete={this.autocomplete as LuminaJsx.HTMLElementTags["input"]["autocomplete"]} - autofocus={this.el.autofocus ? true : null} + autocomplete={this.autocomplete} + autofocus={this.el.autofocus} class={{ [CSS.editingEnabled]: this.editingEnabled, [CSS.inlineChild]: !!this.inlineEditableEl, }} defaultValue={this.defaultValue} disabled={this.disabled ? true : null} - enterKeyHint={ - (this.el.enterKeyHint || - this.el.getAttribute( - "enterkeyhint", - )) as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"] - } - inputMode={ - (this.el.inputMode || - this.el.getAttribute("inputmode")) as LuminaJsx.HTMLElementTags["input"]["inputMode"] - } + enterKeyHint={this.el.enterKeyHint as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"]} + inputMode={this.el.inputMode as LuminaJsx.HTMLElementTags["input"]["inputMode"]} maxLength={this.maxLength} minLength={this.minLength} name={this.name} diff --git a/packages/calcite-components/src/components/input/common/tests.ts b/packages/calcite-components/src/components/input/common/tests.ts index b0c437ebd0b..8d9de052b28 100644 --- a/packages/calcite-components/src/components/input/common/tests.ts +++ b/packages/calcite-components/src/components/input/common/tests.ts @@ -1,6 +1,6 @@ /* eslint-disable jest/no-conditional-expect -- Using conditional logic in a confined test helper to handle specific scenarios, reducing duplication, balancing test readability and maintainability. **/ import { LuminaJsx } from "@arcgis/lumina"; -import { newE2EPage } from "@arcgis/lumina-compiler/puppeteerTesting"; +import { E2EElement, newE2EPage } from "@arcgis/lumina-compiler/puppeteerTesting"; import { expect, it } from "vitest"; import { hiddenFormInputSlotName } from "../../../utils/form"; import { isElementFocused } from "../../../tests/utils"; @@ -136,9 +136,18 @@ export function testWorkaroundForGlobalPropRemoval( const input = await page.find(inputTag); + // we intentionally test each one to avoid renders caused by unrelated props affecting result await input.removeAttribute("autofocus"); await page.waitForChanges(); expect(internalInput.getAttribute("autofocus")).toBe(null); + + await input.removeAttribute("inputmode"); + await page.waitForChanges(); + expect(internalInput.getAttribute("inputmode")).toBe(getExpectedDefaultInputMode(input)); + + await input.removeAttribute("enterkeyhint"); + await page.waitForChanges(); + expect(internalInput.getAttribute("enterkeyhint")).toBe(""); }); it("supports global props", async () => { @@ -157,8 +166,21 @@ export function testWorkaroundForGlobalPropRemoval( expect(internalInput.getAttribute("inputmode")).toBe(testInputMode); expect(internalInput.getAttribute("enterkeyhint")).toBe(testEnterKeyHint); + // we intentionally test each one to avoid renders caused by unrelated props affecting result input.setProperty("autofocus", false); await page.waitForChanges(); expect(internalInput.getAttribute("autofocus")).toBe(null); + + input.setProperty("inputMode", null); + await page.waitForChanges(); + expect(internalInput.getAttribute("inputmode")).toBe(getExpectedDefaultInputMode(input)); + + input.setProperty("enterKeyHint", null); + await page.waitForChanges(); + expect(internalInput.getAttribute("enterkeyhint")).toBe(""); }); + + function getExpectedDefaultInputMode(input: E2EElement): string { + return input.tagName === "CALCITE-INPUT-NUMBER" ? "decimal" : ""; + } } diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index f84fa05c91c..06dbfc8300b 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -180,9 +180,9 @@ export class Input * Specifies the type of content to autocomplete, for use in forms. * Read the native attribute's documentation on MDN for more info. * - * @mdn [step](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) + * @mdn [autocomplete](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) */ - @property() autocomplete: string; + @property() autocomplete: AutoFill; /** When `true`, a clear button is displayed when the component has a value. The clear button shows by default for `"search"`, `"time"`, and `"date"` types, and will not display for the `"textarea"` type. */ @property({ reflect: true }) clearable = false; @@ -1055,9 +1055,9 @@ export class Input const prefixText =
{this.prefixText}
; const suffixText =
{this.suffixText}
; - const autofocus = this.el.autofocus || this.el.hasAttribute("autofocus") ? true : null; - const enterKeyHint = this.el.enterKeyHint || this.el.getAttribute("enterkeyhint"); - const inputMode = this.el.inputMode || this.el.getAttribute("inputmode"); + const autofocus = this.el.autofocus; + const enterKeyHint = this.el.enterKeyHint as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"]; + const inputMode = this.el.inputMode as LuminaJsx.HTMLElementTags["input"]["inputMode"]; const localeNumberInput = this.type === "number" ? ( @@ -1066,12 +1066,12 @@ export class Input aria-errormessage={IDS.validationMessage} ariaInvalid={this.status === "invalid"} ariaLabel={getLabelText(this)} - autocomplete={this.autocomplete as LuminaJsx.HTMLElementTags["input"]["autocomplete"]} + autocomplete={this.autocomplete} autofocus={autofocus} defaultValue={this.defaultValue} disabled={this.disabled ? true : null} - enterKeyHint={enterKeyHint as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"]} - inputMode={inputMode as LuminaJsx.HTMLElementTags["input"]["inputMode"]} + enterKeyHint={enterKeyHint} + inputMode={inputMode} key="localized-input" maxLength={this.maxLength} minLength={this.minLength} @@ -1102,7 +1102,7 @@ export class Input aria-errormessage={IDS.validationMessage} ariaInvalid={this.status === "invalid"} ariaLabel={getLabelText(this)} - autocomplete={this.autocomplete as LuminaJsx.HTMLElementTags["input"]["autocomplete"]} + autocomplete={this.autocomplete} autofocus={autofocus} class={{ [CSS.editingEnabled]: this.editingEnabled, @@ -1110,8 +1110,8 @@ export class Input }} defaultValue={this.defaultValue} disabled={this.disabled ? true : null} - enterKeyHint={enterKeyHint as LuminaJsx.HTMLElementTags["input"]["enterKeyHint"]} - inputMode={inputMode as LuminaJsx.HTMLElementTags["input"]["inputMode"]} + enterKeyHint={enterKeyHint} + inputMode={inputMode} max={this.maxString} maxLength={this.maxLength} min={this.minString}