From ebf59b4d326d4ff623b6688c24724c7f2ee9a17d Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 8 Jan 2025 08:57:30 -0800 Subject: [PATCH 1/4] fix(autocomplete, dom): fix default icon types --- .../autocomplete/autocomplete.e2e.ts | 15 ++++++++++++++ .../autocomplete/autocomplete.stories.ts | 15 ++++++++++++++ .../components/autocomplete/autocomplete.tsx | 10 ++-------- .../src/components/autocomplete/resources.ts | 4 ---- .../calcite-components/src/utils/dom.spec.ts | 20 ++++++++++++++++++- packages/calcite-components/src/utils/dom.ts | 12 +++++++---- 6 files changed, 59 insertions(+), 17 deletions(-) diff --git a/packages/calcite-components/src/components/autocomplete/autocomplete.e2e.ts b/packages/calcite-components/src/components/autocomplete/autocomplete.e2e.ts index 7281ae03d5f..344d2a62e81 100644 --- a/packages/calcite-components/src/components/autocomplete/autocomplete.e2e.ts +++ b/packages/calcite-components/src/components/autocomplete/autocomplete.e2e.ts @@ -433,6 +433,21 @@ describe("calcite-autocomplete", () => { await page.setContent(simpleHTML); }); + it("should be able to remove icon", async () => { + const page = await newE2EPage(); + await page.setContent(simpleHTML); + + const autocomplete = await page.find("calcite-autocomplete"); + const input = await page.find("calcite-autocomplete >>> calcite-input"); + + expect(await input.getProperty("icon")).toBe(undefined); + + autocomplete.setProperty("icon", false); + await page.waitForChanges(); + + expect(await input.getProperty("icon")).toBe(false); + }); + it("should open on focus", async () => { const page = await newE2EPage(); await page.setContent(simpleHTML); diff --git a/packages/calcite-components/src/components/autocomplete/autocomplete.stories.ts b/packages/calcite-components/src/components/autocomplete/autocomplete.stories.ts index ffb05ad5dad..513c2f041dc 100644 --- a/packages/calcite-components/src/components/autocomplete/autocomplete.stories.ts +++ b/packages/calcite-components/src/components/autocomplete/autocomplete.stories.ts @@ -134,6 +134,21 @@ export const simple = (args: AutocompleteStoryArgs): string => html` `; +export const customIcon = (): string => html` +
+ +
+`; + +export const noIcon = (): string => html` +
+ +
+ +`; + export const matchResults = (): string => html`
diff --git a/packages/calcite-components/src/components/autocomplete/autocomplete.tsx b/packages/calcite-components/src/components/autocomplete/autocomplete.tsx index 51849faa3d0..a78ba4155f4 100644 --- a/packages/calcite-components/src/components/autocomplete/autocomplete.tsx +++ b/packages/calcite-components/src/components/autocomplete/autocomplete.tsx @@ -60,7 +60,7 @@ import { Validation } from "../functional/Validation"; import { createObserver } from "../../utils/observers"; import { styles } from "./autocomplete.scss"; import T9nStrings from "./assets/t9n/messages.en.json"; -import { CSS, ICONS, IDS, SLOTS } from "./resources"; +import { CSS, IDS, SLOTS } from "./resources"; const groupItemSelector = "calcite-autocomplete-item-group"; const itemSelector = "calcite-autocomplete-item"; @@ -654,12 +654,6 @@ export class Autocomplete this.updateGroups(); } - private getIcon(): IconNameOrString { - const { icon } = this; - - return icon === true ? ICONS.search : icon || ICONS.search; - } - private setReferenceEl(el: Input["el"]): void { this.referenceEl = el; @@ -794,7 +788,7 @@ export class Autocomplete disabled={disabled} enterKeyHint={enterKeyHint} form={this.form} - icon={this.getIcon()} + icon={this.icon} iconFlipRtl={this.iconFlipRtl} id={inputId} inputMode={inputMode} diff --git a/packages/calcite-components/src/components/autocomplete/resources.ts b/packages/calcite-components/src/components/autocomplete/resources.ts index 9500200e205..7fb20c5b668 100644 --- a/packages/calcite-components/src/components/autocomplete/resources.ts +++ b/packages/calcite-components/src/components/autocomplete/resources.ts @@ -3,10 +3,6 @@ export const SLOTS = { contentTop: "content-top", } as const; -export const ICONS = { - search: "search", -} as const; - export const CSS = { inputContainer: "input-container", input: "input", diff --git a/packages/calcite-components/src/utils/dom.spec.ts b/packages/calcite-components/src/utils/dom.spec.ts index 79ade958c28..9ed8bd625a6 100644 --- a/packages/calcite-components/src/utils/dom.spec.ts +++ b/packages/calcite-components/src/utils/dom.spec.ts @@ -63,10 +63,28 @@ describe("dom", () => { "myCustomValue", )); - it("returns the pre-defined icon name if custom value is not passed", () => + it("returns the pre-defined icon name if custom value is empty string", () => expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, "", "exampleValue")).toBe( "exampleReturnedValue", )); + + it("returns the pre-defined icon name if custom value is undefined", () => + expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, undefined, "exampleValue")).toBe( + "exampleReturnedValue", + )); + + it("returns the pre-defined icon name if custom value is null", () => + expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, null, "exampleValue")).toBe( + "exampleReturnedValue", + )); + + it("returns the pre-defined icon name if custom value is true", () => + expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, true, "exampleValue")).toBe( + "exampleReturnedValue", + )); + + it("returns no icon if custom value is false", () => + expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, false, "exampleValue")).toBe(undefined)); }); describe("uniqueId", () => { diff --git a/packages/calcite-components/src/utils/dom.ts b/packages/calcite-components/src/utils/dom.ts index 48a0e4ec543..9d12aecf6c5 100644 --- a/packages/calcite-components/src/utils/dom.ts +++ b/packages/calcite-components/src/utils/dom.ts @@ -327,14 +327,18 @@ export function filterElementsBySelector(elements: Element[], */ export function setRequestedIcon( iconObject: Record, - iconValue: IconNameOrString | boolean | "", + iconValue: IconNameOrString | boolean, matchedValue: string, ): IconNameOrString | undefined { - if (typeof iconValue === "string" && iconValue !== "") { - return iconValue; - } else if (iconValue === "" || iconValue === true) { + console.log(iconValue, matchedValue); + + if (iconValue === false) { + return undefined; + } else if (iconValue === true || !iconValue) { return iconObject[matchedValue]; } + + return iconValue; } /** From 24ec9abf82d73e2aaad69369f649ee9dab178e72 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 8 Jan 2025 12:49:56 -0800 Subject: [PATCH 2/4] fix(autocomplete, dom): fix default icon types #11224 --- .../src/components/alert/alert.tsx | 2 +- .../input-message/input-message.tsx | 4 +-- .../components/input-number/input-number.tsx | 4 +-- .../src/components/input-text/input-text.tsx | 4 +-- .../src/components/input/input.tsx | 4 +-- .../src/components/notice/notice.tsx | 4 +-- .../calcite-components/src/utils/dom.spec.ts | 28 ++++++------------- packages/calcite-components/src/utils/dom.ts | 16 ++++------- 8 files changed, 26 insertions(+), 40 deletions(-) diff --git a/packages/calcite-components/src/components/alert/alert.tsx b/packages/calcite-components/src/components/alert/alert.tsx index a34b7ec6a7d..6eae60f18cc 100644 --- a/packages/calcite-components/src/components/alert/alert.tsx +++ b/packages/calcite-components/src/components/alert/alert.tsx @@ -405,7 +405,7 @@ export class Alert extends LitElement implements OpenCloseComponent, LoadableCom const { open, autoClose, label, placement, active, openAlertCount } = this; const role = autoClose ? "alert" : "alertdialog"; const hidden = !open; - const effectiveIcon = setRequestedIcon(KindIcons, this.icon, this.kind); + const effectiveIcon = setRequestedIcon(KindIcons, this.kind, this.icon); const hasQueuedAlerts = openAlertCount > 1; /* TODO: [MIGRATION] This used before. In Stencil, props overwrite user-provided props. If you don't wish to overwrite user-values, replace "=" here with "??=" */ this.el.inert = hidden; diff --git a/packages/calcite-components/src/components/input-message/input-message.tsx b/packages/calcite-components/src/components/input-message/input-message.tsx index be873a47cda..725710afad5 100644 --- a/packages/calcite-components/src/components/input-message/input-message.tsx +++ b/packages/calcite-components/src/components/input-message/input-message.tsx @@ -55,7 +55,7 @@ export class InputMessage extends LitElement { // #region Lifecycle override connectedCallback(): void { - this.requestedIcon = setRequestedIcon(StatusIconDefaults, this.icon, this.status); + this.requestedIcon = setRequestedIcon(StatusIconDefaults, this.status, this.icon); } override willUpdate(changes: PropertyValues): void { @@ -67,7 +67,7 @@ export class InputMessage extends LitElement { (changes.has("status") && (this.hasUpdated || this.status !== "idle")) || changes.has("icon") ) { - this.requestedIcon = setRequestedIcon(StatusIconDefaults, this.icon, this.status); + this.requestedIcon = setRequestedIcon(StatusIconDefaults, this.status, this.icon); } } 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 10038f090e7..a45ab45802a 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -413,7 +413,7 @@ export class InputNumber setUpLoadableComponent(this); this.maxString = this.max?.toString(); this.minString = this.min?.toString(); - this.requestedIcon = setRequestedIcon({}, this.icon, "number"); + this.requestedIcon = setRequestedIcon({}, "number", this.icon); this.setPreviousEmittedNumberValue(this.value); this.setPreviousNumberValue(this.value); @@ -440,7 +440,7 @@ export class InputNumber } if (changes.has("icon")) { - this.requestedIcon = setRequestedIcon({}, this.icon, "number"); + this.requestedIcon = setRequestedIcon({}, "number", this.icon); } if (changes.has("messages")) { 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 d1f48e82064..e90351528e8 100644 --- a/packages/calcite-components/src/components/input-text/input-text.tsx +++ b/packages/calcite-components/src/components/input-text/input-text.tsx @@ -353,14 +353,14 @@ export class InputText async load(): Promise { setUpLoadableComponent(this); - this.requestedIcon = setRequestedIcon({}, this.icon, "text"); + this.requestedIcon = setRequestedIcon({}, "text", this.icon); this.setPreviousEmittedValue(this.value); this.setPreviousValue(this.value); } override willUpdate(changes: PropertyValues): void { if (changes.has("icon")) { - this.requestedIcon = setRequestedIcon({}, this.icon, "text"); + this.requestedIcon = setRequestedIcon({}, "text", this.icon); } } diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 01ca297e9f4..5d73f40c901 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -479,7 +479,7 @@ export class Input this.childElType = this.type === "textarea" ? "textarea" : "input"; this.maxString = this.max?.toString(); this.minString = this.min?.toString(); - this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.icon, this.type); + this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.type, this.icon); this.setPreviousEmittedValue(this.value); this.setPreviousValue(this.value); @@ -511,7 +511,7 @@ export class Input } if (changes.has("icon") || (changes.has("type") && (this.hasUpdated || this.type !== "text"))) { - this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.icon, this.type); + this.requestedIcon = setRequestedIcon(INPUT_TYPE_ICONS, this.type, this.icon); } } diff --git a/packages/calcite-components/src/components/notice/notice.tsx b/packages/calcite-components/src/components/notice/notice.tsx index ff20f21095a..06bfbddc8ae 100644 --- a/packages/calcite-components/src/components/notice/notice.tsx +++ b/packages/calcite-components/src/components/notice/notice.tsx @@ -151,7 +151,7 @@ export class Notice extends LitElement implements LoadableComponent, OpenCloseCo async load(): Promise { setUpLoadableComponent(this); - this.requestedIcon = setRequestedIcon(KindIcons, this.icon, this.kind); + this.requestedIcon = setRequestedIcon(KindIcons, this.kind, this.icon); if (this.open) { onToggleOpenCloseComponent(this); } @@ -170,7 +170,7 @@ export class Notice extends LitElement implements LoadableComponent, OpenCloseCo changes.has("icon") || (changes.has("kind") && (this.hasUpdated || this.kind !== "brand")) ) { - this.requestedIcon = setRequestedIcon(KindIcons, this.icon, this.kind); + this.requestedIcon = setRequestedIcon(KindIcons, this.kind, this.icon); } } diff --git a/packages/calcite-components/src/utils/dom.spec.ts b/packages/calcite-components/src/utils/dom.spec.ts index 9ed8bd625a6..3a82a1fd7c3 100644 --- a/packages/calcite-components/src/utils/dom.spec.ts +++ b/packages/calcite-components/src/utils/dom.spec.ts @@ -58,33 +58,23 @@ describe("dom", () => { } describe("setRequestedIcon()", () => { + const iconObject = { exampleValue: "exampleReturnedValue" }; + const matchedValue = "exampleValue"; + it("returns the custom icon name if custom value is passed", () => - expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, "myCustomValue", "exampleValue")).toBe( - "myCustomValue", - )); + expect(setRequestedIcon(iconObject, matchedValue, "myCustomValue")).toBe("myCustomValue")); it("returns the pre-defined icon name if custom value is empty string", () => - expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, "", "exampleValue")).toBe( - "exampleReturnedValue", - )); + expect(setRequestedIcon(iconObject, matchedValue, "")).toBe(iconObject[matchedValue])); it("returns the pre-defined icon name if custom value is undefined", () => - expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, undefined, "exampleValue")).toBe( - "exampleReturnedValue", - )); - - it("returns the pre-defined icon name if custom value is null", () => - expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, null, "exampleValue")).toBe( - "exampleReturnedValue", - )); + expect(setRequestedIcon(iconObject, matchedValue, undefined)).toBe(iconObject[matchedValue])); it("returns the pre-defined icon name if custom value is true", () => - expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, true, "exampleValue")).toBe( - "exampleReturnedValue", - )); + expect(setRequestedIcon(iconObject, matchedValue, true)).toBe(iconObject[matchedValue])); - it("returns no icon if custom value is false", () => - expect(setRequestedIcon({ exampleValue: "exampleReturnedValue" }, false, "exampleValue")).toBe(undefined)); + it("returns no icon name if custom value is false", () => + expect(setRequestedIcon(iconObject, matchedValue, false)).toBe(undefined)); }); describe("uniqueId", () => { diff --git a/packages/calcite-components/src/utils/dom.ts b/packages/calcite-components/src/utils/dom.ts index 9d12aecf6c5..5ef19a3f1c7 100644 --- a/packages/calcite-components/src/utils/dom.ts +++ b/packages/calcite-components/src/utils/dom.ts @@ -321,24 +321,20 @@ export function filterElementsBySelector(elements: Element[], * Set a default icon from a defined set or allow an override with an icon name string * * @param {Record} iconObject The icon object. - * @param {string | boolean} iconValue The icon value. * @param {string} matchedValue The matched value. + * @param {string|boolean|undefined} iconValue The icon value. * @returns {string|undefined} The resulting icon value. */ export function setRequestedIcon( iconObject: Record, - iconValue: IconNameOrString | boolean, matchedValue: string, + iconValue: IconNameOrString | boolean | undefined, ): IconNameOrString | undefined { - console.log(iconValue, matchedValue); - - if (iconValue === false) { - return undefined; - } else if (iconValue === true || !iconValue) { - return iconObject[matchedValue]; + if (typeof iconValue === "boolean") { + return iconValue ? iconObject[matchedValue] : undefined; + } else if (typeof iconValue === "string") { + return iconValue || iconObject[matchedValue]; } - - return iconValue; } /** From 43265b1b029c96484453cc4abc3b633d7fc9a49b Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 8 Jan 2025 13:21:51 -0800 Subject: [PATCH 3/4] fix test --- packages/calcite-components/src/utils/dom.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/calcite-components/src/utils/dom.ts b/packages/calcite-components/src/utils/dom.ts index 5ef19a3f1c7..c34e1d8dcd8 100644 --- a/packages/calcite-components/src/utils/dom.ts +++ b/packages/calcite-components/src/utils/dom.ts @@ -335,6 +335,7 @@ export function setRequestedIcon( } else if (typeof iconValue === "string") { return iconValue || iconObject[matchedValue]; } + return iconObject[matchedValue]; } /** From 383eb41941e7777e7953f9bb4740e6f1234637db Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 8 Jan 2025 15:28:00 -0800 Subject: [PATCH 4/4] review fixes --- packages/calcite-components/src/utils/dom.spec.ts | 14 +++++++------- packages/calcite-components/src/utils/dom.ts | 5 ++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/calcite-components/src/utils/dom.spec.ts b/packages/calcite-components/src/utils/dom.spec.ts index 3a82a1fd7c3..cccab2a11f5 100644 --- a/packages/calcite-components/src/utils/dom.spec.ts +++ b/packages/calcite-components/src/utils/dom.spec.ts @@ -64,16 +64,16 @@ describe("dom", () => { it("returns the custom icon name if custom value is passed", () => expect(setRequestedIcon(iconObject, matchedValue, "myCustomValue")).toBe("myCustomValue")); - it("returns the pre-defined icon name if custom value is empty string", () => - expect(setRequestedIcon(iconObject, matchedValue, "")).toBe(iconObject[matchedValue])); - - it("returns the pre-defined icon name if custom value is undefined", () => - expect(setRequestedIcon(iconObject, matchedValue, undefined)).toBe(iconObject[matchedValue])); - it("returns the pre-defined icon name if custom value is true", () => expect(setRequestedIcon(iconObject, matchedValue, true)).toBe(iconObject[matchedValue])); - it("returns no icon name if custom value is false", () => + it("returns undefined if custom value is an empty string", () => + expect(setRequestedIcon(iconObject, matchedValue, "")).toBe(undefined)); + + it("returns undefined if custom value is undefined", () => + expect(setRequestedIcon(iconObject, matchedValue, undefined)).toBe(undefined)); + + it("returns undefined if custom value is false", () => expect(setRequestedIcon(iconObject, matchedValue, false)).toBe(undefined)); }); diff --git a/packages/calcite-components/src/utils/dom.ts b/packages/calcite-components/src/utils/dom.ts index c34e1d8dcd8..4db7ae8dd38 100644 --- a/packages/calcite-components/src/utils/dom.ts +++ b/packages/calcite-components/src/utils/dom.ts @@ -332,10 +332,9 @@ export function setRequestedIcon( ): IconNameOrString | undefined { if (typeof iconValue === "boolean") { return iconValue ? iconObject[matchedValue] : undefined; - } else if (typeof iconValue === "string") { - return iconValue || iconObject[matchedValue]; + } else if (typeof iconValue === "string" && !!iconValue) { + return iconValue; } - return iconObject[matchedValue]; } /**