From e304b8bdb9c834c6e18d9f701bb48363f8621e5d Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 27 Dec 2021 16:25:31 -0800 Subject: [PATCH 01/12] refactor(dom): Update getSlotted utility to handle querying for item(s) in the default slot. --- src/utils/dom.spec.ts | 10 +++++++++- src/utils/dom.ts | 12 ++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/utils/dom.spec.ts b/src/utils/dom.spec.ts index e1bc69329ae..293e4d8c82d 100644 --- a/src/utils/dom.spec.ts +++ b/src/utils/dom.spec.ts @@ -1,3 +1,4 @@ +import { html } from "../tests/utils"; import { getElementProp, getSlotted, setRequestedIcon, ensureId } from "./dom"; import { guidPattern } from "./guid.spec"; @@ -98,7 +99,10 @@ describe("dom", () => { } connectedCallback(): void { - this.shadowRoot.innerHTML = ``; + this.shadowRoot.innerHTML = html` + + + `; } } @@ -115,6 +119,7 @@ describe("dom", () => { 🙂

😂

+

Hello world

`; }); @@ -126,6 +131,9 @@ describe("dom", () => { it("returns null when no results", () => expect(getSlotted(getTestComponent(), "non-existent-slot")).toBeNull()); describe("scoped selector", () => { + it("returns element with matching default selector", () => + expect(getSlotted(getTestComponent(), null, { selector: "p" })).toBeTruthy()); + it("returns element with matching nested selector", () => expect(getSlotted(getTestComponent(), testSlotName, { selector: "span" })).toBeTruthy()); diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 69180044eac..43593cd25f7 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -137,20 +137,20 @@ interface GetSlottedOptions { export function getSlotted( element: Element, - slotName: string, - options: GetSlottedOptions & { all: true } + slotName?: string, + options?: GetSlottedOptions & { all: true } ): T[]; export function getSlotted( element: Element, - slotName: string, + slotName?: string, options?: GetSlottedOptions ): T | null; export function getSlotted( element: Element, - slotName: string, + slotName?: string, options?: GetSlottedOptions ): (T | null) | T[] { - const slotSelector = `[slot="${slotName}"]`; + const slotSelector = !!slotName ? `[slot="${slotName}"]` : ":not([slot])"; if (options?.all) { return queryMultiple(element, slotSelector, options); @@ -185,7 +185,7 @@ function querySingle( match = options && options.direct === false ? match : match?.parentElement === element ? match : null; const selector = options?.selector; - return selector ? match.querySelector(selector) : match; + return selector ? match?.querySelector(selector) : match; } export function filterDirectChildren(el: Element, selector: string): T[] { From a544156f70fc91c32813f34ef2a42ff2374ca0bc Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 27 Dec 2021 16:38:19 -0800 Subject: [PATCH 02/12] cleanup --- src/utils/dom.spec.ts | 2 ++ src/utils/dom.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/dom.spec.ts b/src/utils/dom.spec.ts index 293e4d8c82d..bb39067d705 100644 --- a/src/utils/dom.spec.ts +++ b/src/utils/dom.spec.ts @@ -125,6 +125,8 @@ describe("dom", () => { }); describe("single slotted", () => { + it("returns elements with matching default slot", () => expect(getSlotted(getTestComponent())).toBeTruthy()); + it("returns elements with matching slot name", () => expect(getSlotted(getTestComponent(), testSlotName)).toBeTruthy()); diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 43593cd25f7..0922519bbe6 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -150,7 +150,7 @@ export function getSlotted( slotName?: string, options?: GetSlottedOptions ): (T | null) | T[] { - const slotSelector = !!slotName ? `[slot="${slotName}"]` : ":not([slot])"; + const slotSelector = slotName ? `[slot="${slotName}"]` : ":not([slot])"; if (options?.all) { return queryMultiple(element, slotSelector, options); From 4412bcb1b853a865f2b1a9ddebbb2643af1349bf Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Tue, 28 Dec 2021 10:38:34 -0800 Subject: [PATCH 03/12] fix tests --- src/utils/dom.spec.ts | 10 +++------- src/utils/dom.ts | 4 +++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/utils/dom.spec.ts b/src/utils/dom.spec.ts index bb39067d705..c751077201b 100644 --- a/src/utils/dom.spec.ts +++ b/src/utils/dom.spec.ts @@ -1,4 +1,3 @@ -import { html } from "../tests/utils"; import { getElementProp, getSlotted, setRequestedIcon, ensureId } from "./dom"; import { guidPattern } from "./guid.spec"; @@ -99,10 +98,7 @@ describe("dom", () => { } connectedCallback(): void { - this.shadowRoot.innerHTML = html` - - - `; + this.shadowRoot.innerHTML = ``; } } @@ -119,7 +115,7 @@ describe("dom", () => { 🙂

😂

-

Hello world

+

🙂

`; }); @@ -133,7 +129,7 @@ describe("dom", () => { it("returns null when no results", () => expect(getSlotted(getTestComponent(), "non-existent-slot")).toBeNull()); describe("scoped selector", () => { - it("returns element with matching default selector", () => + it("returns element with matching default slot", () => expect(getSlotted(getTestComponent(), null, { selector: "p" })).toBeTruthy()); it("returns element with matching nested selector", () => diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 0922519bbe6..0a1a5a38981 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -135,6 +135,8 @@ interface GetSlottedOptions { selector?: string; } +const defaultSlotSelector = "> :not([slot])"; + export function getSlotted( element: Element, slotName?: string, @@ -150,7 +152,7 @@ export function getSlotted( slotName?: string, options?: GetSlottedOptions ): (T | null) | T[] { - const slotSelector = slotName ? `[slot="${slotName}"]` : ":not([slot])"; + const slotSelector = slotName ? `[slot="${slotName}"]` : defaultSlotSelector; if (options?.all) { return queryMultiple(element, slotSelector, options); From 01780f451a4a8a8bfa79c834e73c2a22cd9439c3 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Tue, 28 Dec 2021 11:02:21 -0800 Subject: [PATCH 04/12] fix typing --- src/utils/dom.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 0a1a5a38981..d7fe43e7896 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -139,8 +139,8 @@ const defaultSlotSelector = "> :not([slot])"; export function getSlotted( element: Element, - slotName?: string, - options?: GetSlottedOptions & { all: true } + slotName: string, + options: GetSlottedOptions & { all: true } ): T[]; export function getSlotted( element: Element, From 9cb29d18a3c531498843923d4b2a8b60cf811144 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 29 Dec 2021 12:24:56 -0800 Subject: [PATCH 05/12] add test --- src/utils/dom.spec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/dom.spec.ts b/src/utils/dom.spec.ts index ec7f7651b3c..8b848db6a7a 100644 --- a/src/utils/dom.spec.ts +++ b/src/utils/dom.spec.ts @@ -192,6 +192,9 @@ describe("dom", () => { }); describe("multiple slotted", () => { + it("returns element with default slot name", () => + expect(getSlotted(getTestComponent(), null, { all: true })).toHaveLength(1)); + it("returns elements with matching slot name", () => expect(getSlotted(getTestComponent(), testSlotName, { all: true })).toHaveLength(2)); From ee92c3fa44dcf2ce6ee7cd182e8f7cc7a0379c9b Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 29 Dec 2021 14:24:11 -0800 Subject: [PATCH 06/12] review fixes --- src/utils/dom.spec.ts | 4 ++-- src/utils/dom.ts | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/utils/dom.spec.ts b/src/utils/dom.spec.ts index 8b848db6a7a..68ce1563525 100644 --- a/src/utils/dom.spec.ts +++ b/src/utils/dom.spec.ts @@ -141,7 +141,7 @@ describe("dom", () => { describe("scoped selector", () => { it("returns element with matching default slot", () => - expect(getSlotted(getTestComponent(), null, { selector: "p" })).toBeTruthy()); + expect(getSlotted(getTestComponent(), { selector: "p" })).toBeTruthy()); it("returns element with matching nested selector", () => expect(getSlotted(getTestComponent(), testSlotName, { selector: "span" })).toBeTruthy()); @@ -193,7 +193,7 @@ describe("dom", () => { describe("multiple slotted", () => { it("returns element with default slot name", () => - expect(getSlotted(getTestComponent(), null, { all: true })).toHaveLength(1)); + expect(getSlotted(getTestComponent(), { all: true })).toHaveLength(1)); it("returns elements with matching slot name", () => expect(getSlotted(getTestComponent(), testSlotName, { all: true })).toHaveLength(2)); diff --git a/src/utils/dom.ts b/src/utils/dom.ts index e652051a513..15839970009 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -166,19 +166,24 @@ const defaultSlotSelector = "> :not([slot])"; export function getSlotted( element: Element, - slotName: string | string[], + slotName: string | string[] | (GetSlottedOptions & { all: true }), options: GetSlottedOptions & { all: true } ): T[]; export function getSlotted( element: Element, - slotName?: string | string[], + slotName?: string | string[] | GetSlottedOptions, options?: GetSlottedOptions ): T | null; export function getSlotted( element: Element, - slotName?: string | string[], + slotName?: string | string[] | GetSlottedOptions, options?: GetSlottedOptions ): (T | null) | T[] { + if (!Array.isArray(slotName) && typeof slotName !== "string") { + options = slotName; + slotName = null; + } + const slotSelector = slotName ? Array.isArray(slotName) ? slotName.map((name) => `[slot="${name}"]`).join(",") From 2b51a404b9cafdc73de2f867e1d7f844752a7ce6 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 29 Dec 2021 15:24:18 -0800 Subject: [PATCH 07/12] check assigned slot if browser --- src/utils/dom.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 15839970009..2018646b24c 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -1,5 +1,6 @@ import { CSS_UTILITY } from "./resources"; import { guid } from "./guid"; +import { Build } from "@stencil/core"; /** * This helper will guarantee an ID on the provided element. @@ -203,6 +204,7 @@ function queryMultiple( options?: GetSlottedOptions ): T[] { let matches = Array.from(element.querySelectorAll(slotSelector)); + matches = matches.filter((match) => !Build.isBrowser || !!match?.assignedSlot); matches = options && options.direct === false ? matches : matches.filter((el) => el.parentElement === element); const selector = options?.selector; @@ -220,6 +222,11 @@ function querySingle( options?: GetSlottedOptions ): T | null { let match = element.querySelector(slotSelector); + + if (Build.isBrowser && !match?.assignedSlot) { + return null; + } + match = options && options.direct === false ? match : match?.parentElement === element ? match : null; const selector = options?.selector; From f9f8cdf518186e1ac3c9e46ccad605de7d51c521 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Wed, 29 Dec 2021 16:26:40 -0800 Subject: [PATCH 08/12] revert --- src/utils/dom.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 2018646b24c..685ba2019f1 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -1,6 +1,5 @@ import { CSS_UTILITY } from "./resources"; import { guid } from "./guid"; -import { Build } from "@stencil/core"; /** * This helper will guarantee an ID on the provided element. @@ -204,7 +203,6 @@ function queryMultiple( options?: GetSlottedOptions ): T[] { let matches = Array.from(element.querySelectorAll(slotSelector)); - matches = matches.filter((match) => !Build.isBrowser || !!match?.assignedSlot); matches = options && options.direct === false ? matches : matches.filter((el) => el.parentElement === element); const selector = options?.selector; @@ -223,10 +221,6 @@ function querySingle( ): T | null { let match = element.querySelector(slotSelector); - if (Build.isBrowser && !match?.assignedSlot) { - return null; - } - match = options && options.direct === false ? match : match?.parentElement === element ? match : null; const selector = options?.selector; From 1c547a0194231840f48050af966ceba6288f9f4b Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Thu, 30 Dec 2021 15:28:13 -0800 Subject: [PATCH 09/12] test single slot --- src/utils/dom.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 685ba2019f1..8b6a94b314f 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -202,7 +202,7 @@ function queryMultiple( slotSelector: string, options?: GetSlottedOptions ): T[] { - let matches = Array.from(element.querySelectorAll(slotSelector)); + let matches = Array.from(element.querySelectorAll(slotSelector)).filter((match) => match?.assignedSlot); matches = options && options.direct === false ? matches : matches.filter((el) => el.parentElement === element); const selector = options?.selector; @@ -221,7 +221,13 @@ function querySingle( ): T | null { let match = element.querySelector(slotSelector); - match = options && options.direct === false ? match : match?.parentElement === element ? match : null; + match = match?.assignedSlot + ? options && options.direct === false + ? match + : match?.parentElement === element + ? match + : null + : null; const selector = options?.selector; return selector ? match?.querySelector(selector) : match; From 5b8fcbae5fc88f6dcdb44c15f12da5ac25a24185 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Thu, 30 Dec 2021 15:51:24 -0800 Subject: [PATCH 10/12] try again --- src/utils/dom.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 8b6a94b314f..4ea2be639a3 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -202,9 +202,13 @@ function queryMultiple( slotSelector: string, options?: GetSlottedOptions ): T[] { - let matches = Array.from(element.querySelectorAll(slotSelector)).filter((match) => match?.assignedSlot); + let matches = Array.from(element.querySelectorAll(slotSelector)); matches = options && options.direct === false ? matches : matches.filter((el) => el.parentElement === element); + if (slotSelector === defaultSlotSelector) { + matches = matches.filter((match) => match?.assignedSlot); + } + const selector = options?.selector; return selector ? matches @@ -221,13 +225,11 @@ function querySingle( ): T | null { let match = element.querySelector(slotSelector); - match = match?.assignedSlot - ? options && options.direct === false - ? match - : match?.parentElement === element - ? match - : null - : null; + if (slotSelector === defaultSlotSelector) { + match = match?.assignedSlot ? match : null; + } + + match = options && options.direct === false ? match : match?.parentElement === element ? match : null; const selector = options?.selector; return selector ? match?.querySelector(selector) : match; From f16e6014b822917b4f4bb32888bbf56ae8fab6bd Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Fri, 7 Jan 2022 12:54:20 -0800 Subject: [PATCH 11/12] fix test --- src/utils/dom.spec.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utils/dom.spec.ts b/src/utils/dom.spec.ts index 68ce1563525..01e2399a416 100644 --- a/src/utils/dom.spec.ts +++ b/src/utils/dom.spec.ts @@ -123,9 +123,12 @@ describe("dom", () => {

😂

😂

-

🙂

+

🙂

`; + + const assignedSlot = document.querySelector("slot-test").shadowRoot.querySelector(`slot:not([name])`); + (document.getElementById("default-slot-el") as any).assignedSlot = assignedSlot; }); describe("single slotted", () => { From 8b9b31d45ff6d4c704812e23b80d52850b905689 Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Fri, 7 Jan 2022 15:05:54 -0800 Subject: [PATCH 12/12] fix test? --- .../calcite-dropdown/calcite-dropdown.e2e.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/calcite-dropdown/calcite-dropdown.e2e.ts b/src/components/calcite-dropdown/calcite-dropdown.e2e.ts index 27b6a15205f..d5130a62b23 100644 --- a/src/components/calcite-dropdown/calcite-dropdown.e2e.ts +++ b/src/components/calcite-dropdown/calcite-dropdown.e2e.ts @@ -756,7 +756,7 @@ describe("calcite-dropdown", () => { describe("opens the dropdown with click, enter, or space", () => { it("opens when dropdown-trigger is a button", async () => { const page = await newE2EPage(); - await page.setContent(html` + await page.setContent(html` Open dropdown @@ -768,7 +768,7 @@ describe("calcite-dropdown", () => { - + `); const element = await page.find("calcite-dropdown"); const trigger = await element.find("calcite-button[slot='dropdown-trigger']"); @@ -794,9 +794,9 @@ describe("calcite-dropdown", () => { it("opens when dropdown-trigger is an action", async () => { const page = await newE2EPage(); - await page.setContent(html` + await page.setContent(html` - Open dropdown + Open dropdown Dropdown Item Content @@ -806,7 +806,7 @@ describe("calcite-dropdown", () => { - + `); const element = await page.find("calcite-dropdown"); const trigger = await element.find("calcite-action[slot='dropdown-trigger'] >>> button");