From 1a3cd67100d69e127815275425070ca9d3dde98b Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 9 Dec 2024 09:11:11 -0800 Subject: [PATCH] refactor(list-item): set displayMode on slotted list (#10965) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Related Issue:** #10949 ## Summary - set displayMode on slotted list - cleanup 🧹 - e2e test --- .../src/components/list-item/list-item.e2e.ts | 32 ++++++++++++++++--- .../src/components/list-item/list-item.tsx | 15 ++++++--- .../src/components/list-item/utils.ts | 16 +++++++--- .../src/components/list/list.e2e.ts | 12 +++---- .../src/components/list/list.tsx | 16 ++++++---- 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/packages/calcite-components/src/components/list-item/list-item.e2e.ts b/packages/calcite-components/src/components/list-item/list-item.e2e.ts index db7985c019e..4676843198a 100755 --- a/packages/calcite-components/src/components/list-item/list-item.e2e.ts +++ b/packages/calcite-components/src/components/list-item/list-item.e2e.ts @@ -59,7 +59,7 @@ describe("calcite-list-item", () => { }, { propertyName: "displayMode", - defaultValue: undefined, + defaultValue: "flat", }, ]); }); @@ -352,17 +352,17 @@ describe("calcite-list-item", () => { it("should fire calciteListItemToggle event when opened and closed", async () => { const page = await newE2EPage({ - html: html``, }); - const listItem = await page.find("calcite-list-item"); + const listItem = await page.find("#test"); const calciteListItemToggle = await page.spyOnEvent("calciteListItemToggle", "window"); expect(await listItem.getProperty("open")).toBe(false); - const openButton = await page.find(`calcite-list-item >>> .${CSS.openContainer}`); + const openButton = await page.find(`#test >>> .${CSS.openContainer}`); await openButton.click(); expect(await listItem.getProperty("open")).toBe(true); @@ -396,6 +396,28 @@ describe("calcite-list-item", () => { expect(calciteListItemToggle).toHaveReceivedEventTimes(0); }); + it("should set displayMode on slotted list", async () => { + const page = await newE2EPage({ + html: html``, + }); + + const listItem = await page.find("calcite-list-item"); + const list = await page.find("calcite-list"); + + expect(await listItem.getProperty("displayMode")).toBe("flat"); + expect(await list.getProperty("displayMode")).toBe("flat"); + + listItem.setProperty("displayMode", "nested"); + await page.waitForChanges(); + + expect(await list.getProperty("displayMode")).toBe("nested"); + + listItem.setProperty("displayMode", "flat"); + await page.waitForChanges(); + + expect(await list.getProperty("displayMode")).toBe("flat"); + }); + it("flat list should not render open container", async () => { const page = await newE2EPage({ html: html`(); -const listSelector = "calcite-list"; - /** * @slot - A slot for adding `calcite-list`, `calcite-list-item` and `calcite-list-item-group` elements. * @slot actions-start - A slot for adding actionable `calcite-action` elements before the content of the component. @@ -168,7 +166,7 @@ export class ListItem * * @private */ - @property({ reflect: true }) displayMode: ListDisplayMode; + @property({ reflect: true }) displayMode: ListDisplayMode = "flat"; /** * Sets the item to display a border. @@ -539,7 +537,14 @@ export class ListItem return; } - this.openable = this.displayMode === "nested" && hasListItemChildren(slotEl); + const children = getListItemChildren(slotEl); + + children.lists.forEach((list) => { + list.displayMode = this.displayMode; + }); + + this.openable = + this.displayMode === "nested" && (children.lists.length > 0 || children.items.length > 0); } private handleDefaultSlotChange(event: Event): void { diff --git a/packages/calcite-components/src/components/list-item/utils.ts b/packages/calcite-components/src/components/list-item/utils.ts index 5574d54c649..4d995e6ca04 100644 --- a/packages/calcite-components/src/components/list-item/utils.ts +++ b/packages/calcite-components/src/components/list-item/utils.ts @@ -3,9 +3,9 @@ import type { List } from "../list/list"; import type { ListItemGroup } from "../list-item-group/list-item-group"; import type { ListItem } from "./list-item"; -const listSelector = "calcite-list"; -const listItemGroupSelector = "calcite-list-item-group"; -const listItemSelector = "calcite-list-item"; +export const listSelector = "calcite-list"; +export const listItemGroupSelector = "calcite-list-item-group"; +export const listItemSelector = "calcite-list-item"; export function openAncestors(el: ListItem["el"]): void { const ancestor = el.parentElement?.closest(listItemSelector); @@ -18,7 +18,10 @@ export function openAncestors(el: ListItem["el"]): void { openAncestors(ancestor); } -export function hasListItemChildren(slotEl: HTMLSlotElement): boolean { +export function getListItemChildren(slotEl: HTMLSlotElement): { + lists: List["el"][]; + items: ListItem["el"][]; +} { const assignedElements = slotEl.assignedElements({ flatten: true }); const groupChildren = assignedElements @@ -30,7 +33,10 @@ export function hasListItemChildren(slotEl: HTMLSlotElement): boolean { const listChildren = assignedElements.filter((el): el is List["el"] => el?.matches(listSelector)); - return [...listChildren, ...groupChildren, ...listItemChildren].length > 0; + return { + lists: listChildren, + items: groupChildren.concat(listItemChildren), + }; } export function updateListItemChildren(slotEl: HTMLSlotElement): void { diff --git a/packages/calcite-components/src/components/list/list.e2e.ts b/packages/calcite-components/src/components/list/list.e2e.ts index 5d6a0c81d3c..8dba5cb1ead 100755 --- a/packages/calcite-components/src/components/list/list.e2e.ts +++ b/packages/calcite-components/src/components/list/list.e2e.ts @@ -195,14 +195,12 @@ describe("calcite-list", () => { await page.waitForChanges(); await page.waitForTimeout(DEBOUNCE.filter); - let modeValues = ["nested", "flat", "nested", "nested", "flat", "nested", "nested"]; - const items = await page.findAll("calcite-list-item"); - expect(items.length).toBe(modeValues.length); + expect(items.length).toBe(7); for (let i = 0; i < items.length; i++) { - expect(await items[i].getProperty("displayMode")).toBe(modeValues[i]); + expect(await items[i].getProperty("displayMode")).toBe("nested"); } const rootList = await page.find("#root"); @@ -211,12 +209,10 @@ describe("calcite-list", () => { await page.waitForChanges(); await page.waitForTimeout(DEBOUNCE.filter); - modeValues = ["flat", "flat", "nested", "nested", "flat", "flat", "flat"]; - - expect(items.length).toBe(modeValues.length); + expect(items.length).toBe(7); for (let i = 0; i < items.length; i++) { - expect(await items[i].getProperty("displayMode")).toBe(modeValues[i]); + expect(await items[i].getProperty("displayMode")).toBe("flat"); } }); diff --git a/packages/calcite-components/src/components/list/list.tsx b/packages/calcite-components/src/components/list/list.tsx index cc145cd5081..324d654ed49 100755 --- a/packages/calcite-components/src/components/list/list.tsx +++ b/packages/calcite-components/src/components/list/list.tsx @@ -11,7 +11,13 @@ import { import { createObserver } from "../../utils/observers"; import { SelectionMode, InteractionMode, Scale } from "../interfaces"; import { ItemData } from "../list-item/interfaces"; -import { openAncestors, updateListItemChildren } from "../list-item/utils"; +import { + listItemGroupSelector, + listItemSelector, + listSelector, + openAncestors, + updateListItemChildren, +} from "../list-item/utils"; import { connectSortableComponent, disconnectSortableComponent, @@ -42,9 +48,7 @@ declare global { } } -const listItemSelector = "calcite-list-item"; -const listItemGroupSelector = "calcite-list-item-group"; -const parentSelector = `${listItemGroupSelector}, calcite-list-item`; +const parentSelector = `${listItemGroupSelector}, ${listItemSelector}`; /** * A general purpose list that enables users to construct list items that conform to Calcite styling. @@ -111,7 +115,7 @@ export class List item.selectionAppearance = selectionAppearance; item.selectionMode = selectionMode; item.interactionMode = interactionMode; - if (item.closest("calcite-list") === el) { + if (item.closest(listSelector) === el) { item.moveToItems = moveToItems.filter( (moveToItem) => moveToItem.element !== el && !item.contains(moveToItem.element), ); @@ -604,7 +608,7 @@ export class List } private setParentList(): void { - this.parentListEl = this.el.parentElement?.closest("calcite-list"); + this.parentListEl = this.el.parentElement?.closest(listSelector); } private handleDefaultSlotChange(event: Event): void {