diff --git a/packages/calcite-components/src/components/combobox/combobox.e2e.ts b/packages/calcite-components/src/components/combobox/combobox.e2e.ts index 14b57d9fc42..e5b1c0b2898 100644 --- a/packages/calcite-components/src/components/combobox/combobox.e2e.ts +++ b/packages/calcite-components/src/components/combobox/combobox.e2e.ts @@ -1087,6 +1087,31 @@ describe("calcite-combobox", () => { expect(eventSpy).toHaveReceivedEventTimes(2); }); + it("should clear the input on blur when filtered items are empty", async () => { + await page.waitForChanges(); + const combobox = await page.find("calcite-combobox"); + const inputEl = await page.find(`#myCombobox >>> input`); + + await inputEl.focus(); + await page.waitForChanges(); + expect(await page.evaluate(() => document.activeElement.id)).toBe("myCombobox"); + await page.keyboard.type("asdf"); + await page.waitForChanges(); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + expect(await combobox.getProperty("value")).toBe(""); + + combobox.setProperty("selectionMode", "single"); + await inputEl.focus(); + await page.waitForChanges(); + expect(await page.evaluate(() => document.activeElement.id)).toBe("myCombobox"); + await page.keyboard.type("asdf"); + await page.waitForChanges(); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + expect(await combobox.getProperty("value")).toBe(""); + }); + describe("keyboard interaction with chips", () => { let element; let chips; @@ -1810,4 +1835,64 @@ describe("calcite-combobox", () => { expect(await item.getProperty("scale")).toBe("l"); }); }); + + describe("clicked outside", () => { + let page: E2EPage; + + beforeEach(async () => { + page = await newE2EPage(); + await page.setContent( + html` + + + + + click me + ` + ); + }); + + async function assertClickOutside(selectionMode = "multiple", allowCustomValues = false): Promise { + const combobox = await page.find("calcite-combobox"); + combobox.setProperty("selectionMode", selectionMode); + combobox.setProperty("allowCustomValues", allowCustomValues); + const inputEl = await page.find(`#myCombobox >>> input`); + const buttonEl = await page.find("calcite-button"); + + await inputEl.focus(); + await page.waitForChanges(); + expect(await page.evaluate(() => document.activeElement.id)).toBe("myCombobox"); + await inputEl.type("asdf"); + await page.waitForChanges(); + + if (allowCustomValues) { + await inputEl.press("Enter"); + await buttonEl.click(); + await page.waitForChanges(); + expect(await page.evaluate(() => document.activeElement.id)).toBe("button"); + expect(await combobox.getProperty("value")).toBe("asdf"); + } else { + await buttonEl.click(); + await page.waitForChanges(); + expect(await page.evaluate(() => document.activeElement.id)).toBe("button"); + expect(await combobox.getProperty("value")).toBe(""); + } + } + + it("should clear input value in single selectionMode", async () => { + await assertClickOutside("single"); + }); + + it("should not clear input value in single selectionMode with allowCustomValues", async () => { + await assertClickOutside("single", true); + }); + + it("should clear input value in multiple selectionMode", async () => { + await assertClickOutside(); + }); + + it("should not clear input value in multiple selectionMode with allowCustomValues", async () => { + await assertClickOutside("multiple", true); + }); + }); }); diff --git a/packages/calcite-components/src/components/combobox/combobox.tsx b/packages/calcite-components/src/components/combobox/combobox.tsx index 60b0a1cba8f..be4f5a0cb5d 100644 --- a/packages/calcite-components/src/components/combobox/combobox.tsx +++ b/packages/calcite-components/src/components/combobox/combobox.tsx @@ -535,6 +535,11 @@ export class Combobox this.setFocus(); } + private clearInputValue(): void { + this.textInput.value = ""; + this.text = ""; + } + setFilteredPlacements = (): void => { const { el, flipPlacements } = this; @@ -759,6 +764,12 @@ export class Combobox setInactiveIfNotContained = (event: Event): void => { const composedPath = event.composedPath(); + if (!this.allowCustomValues && this.textInput.value) { + this.clearInputValue(); + this.filterItems(""); + this.updateActiveItemIndex(-1); + } + if (!this.open || composedPath.includes(this.el) || composedPath.includes(this.referenceEl)) { return; } @@ -767,15 +778,6 @@ export class Combobox this.addCustomChip(this.text); } - if (isSingleLike(this.selectionMode)) { - if (this.textInput) { - this.textInput.value = ""; - } - this.text = ""; - this.filterItems(""); - this.updateActiveItemIndex(-1); - } - this.open = false; };