From c68683a7bc6e8d75cf255f900ca5e82b277da46a Mon Sep 17 00:00:00 2001 From: Brian Ferry Date: Tue, 10 Oct 2023 13:16:05 -0400 Subject: [PATCH 1/6] feat(core): adding isEmpty, hasSlotted w/ default slot --- core/pfe-core/controllers/slot-controller.ts | 35 +++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/core/pfe-core/controllers/slot-controller.ts b/core/pfe-core/controllers/slot-controller.ts index 7e472ba1e6..d61da0e00f 100644 --- a/core/pfe-core/controllers/slot-controller.ts +++ b/core/pfe-core/controllers/slot-controller.ts @@ -41,15 +41,15 @@ function isObjectConfigSpread(config: ([SlotsConfig] | (string | null)[])): conf * for the default slot, look for direct children not assigned to a slot */ const isSlot = - (n: string | typeof SlotController.anonymous) => + (n: string | typeof SlotController.default) => (child: Element): child is T => - n === SlotController.anonymous ? !child.hasAttribute('slot') + n === SlotController.default ? !child.hasAttribute('slot') : child.getAttribute('slot') === n; export class SlotController implements ReactiveController { - public static anonymous = Symbol('anonymous slot'); + public static default = Symbol('default slot'); - #nodes = new Map(); + #nodes = new Map(); #logger: Logger; @@ -113,8 +113,7 @@ export class SlotController implements ReactiveController { */ hasSlotted(...names: string[]): boolean { if (!names.length) { - this.#logger.warn(`Please provide at least one slot name for which to search.`); - return false; + return this.#nodes.get(SlotController.default)?.hasContent ?? false; } else { return names.some(x => this.#nodes.get(x)?.hasContent ?? false); @@ -142,13 +141,31 @@ export class SlotController implements ReactiveController { */ getSlotted(...slotNames: string[]): T[] { if (!slotNames.length) { - return (this.#nodes.get(SlotController.anonymous)?.elements ?? []) as T[]; + return (this.#nodes.get(SlotController.default)?.elements ?? []) as T[]; } else { return slotNames.flatMap(slotName => this.#nodes.get(slotName)?.elements ?? []) as T[]; } } + /** + * Returns a boolean statement of whether or not the requested slot is empty. + * + * @param {String} slotName The slot name. If no value is provided, it returns the default slot. + * @example this.isEmpty("header"); + * @example this.isEmpty(); + * @returns {Boolean} + */ + + isEmpty(slotName?: string): boolean { + if (!slotName) { + return !this.#nodes.get(SlotController.default)?.hasContent ?? true; + } else { + return !this.#nodes.get(slotName)?.hasContent ?? true; + } + } + + #onSlotChange = (event: Event & { target: HTMLSlotElement }) => { const slotName = event.target.name; this.#initSlot(slotName); @@ -168,13 +185,13 @@ export class SlotController implements ReactiveController { this.host.requestUpdate(); }; - #getChildrenForSlot(name: string | typeof SlotController.anonymous): T[] { + #getChildrenForSlot(name: string | typeof SlotController.default): T[] { const children = Array.from(this.host.children) as T[]; return children.filter(isSlot(name)); } #initSlot = (slotName: string | null) => { - const name = slotName || SlotController.anonymous; + const name = slotName || SlotController.default; const elements = this.#nodes.get(name)?.slot?.assignedElements?.() ?? this.#getChildrenForSlot(name); const selector = slotName ? `slot[name="${slotName}"]` : 'slot:not([name])'; const slot = this.host.shadowRoot?.querySelector?.(selector) ?? null; From da3c8245a82cab0895ebb1d6821ae1ec19fdcabe Mon Sep 17 00:00:00 2001 From: Brian Ferry Date: Tue, 10 Oct 2023 13:30:00 -0400 Subject: [PATCH 2/6] chore: adding changeset --- .changeset/cold-cars-relate.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/cold-cars-relate.md diff --git a/.changeset/cold-cars-relate.md b/.changeset/cold-cars-relate.md new file mode 100644 index 0000000000..99092249cd --- /dev/null +++ b/.changeset/cold-cars-relate.md @@ -0,0 +1,8 @@ +--- +"@patternfly/pfe-core": minor +--- + +`SlotController`: + +- Add `isEmpty` method to check if a slot is empty. If no slot name is provided it will check the default slot. (#2603) +- `hasSlotted` method now returns default slot if no slot name is provided. (#2603) From 9a038517446b69384c1b077b48d8bdb2b6f99893 Mon Sep 17 00:00:00 2001 From: Brian Ferry Date: Wed, 11 Oct 2023 09:11:04 -0400 Subject: [PATCH 3/6] Update core/pfe-core/controllers/slot-controller.ts Co-authored-by: Benny Powers --- core/pfe-core/controllers/slot-controller.ts | 31 +++++++++++++------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/core/pfe-core/controllers/slot-controller.ts b/core/pfe-core/controllers/slot-controller.ts index d61da0e00f..8fee4dc92f 100644 --- a/core/pfe-core/controllers/slot-controller.ts +++ b/core/pfe-core/controllers/slot-controller.ts @@ -149,23 +149,34 @@ export class SlotController implements ReactiveController { } /** - * Returns a boolean statement of whether or not the requested slot is empty. + * Returns a boolean statement of whether or not any of those slots exists in the light DOM. + * + * @param names The slot names to check. + * @example this.hasSlotted('header'); + */ + hasSlotted(...names: (string | null | undefined)[]): boolean { + const { anonymous } = SlotController; + const slotNames = Array.from(names, x => x == null ? anonymous : x); + if (!slotNames.length) { + slotNames.push(anonymous); + } + return slotNames.some(x => this.#nodes.get(x)?.hasContent ?? false); + } + + /** + * Whether or not all the requested slots are empty. * - * @param {String} slotName The slot name. If no value is provided, it returns the default slot. - * @example this.isEmpty("header"); + * @param slots The slot name. If no value is provided, it returns the default slot. + * @example this.isEmpty('header', 'footer'); * @example this.isEmpty(); * @returns {Boolean} */ - - isEmpty(slotName?: string): boolean { - if (!slotName) { - return !this.#nodes.get(SlotController.default)?.hasContent ?? true; - } else { - return !this.#nodes.get(slotName)?.hasContent ?? true; - } + isEmpty(...names: (string | null | undefined)[]): boolean { + return !this.hasSlotted(...names); } + #onSlotChange = (event: Event & { target: HTMLSlotElement }) => { const slotName = event.target.name; this.#initSlot(slotName); From e1cfe1977885fd3b55b5b7c3753a092c8cdc714b Mon Sep 17 00:00:00 2001 From: Brian Ferry Date: Wed, 11 Oct 2023 09:24:29 -0400 Subject: [PATCH 4/6] fix(core): adding anonymous slot back to SlotController --- core/pfe-core/controllers/slot-controller.ts | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/core/pfe-core/controllers/slot-controller.ts b/core/pfe-core/controllers/slot-controller.ts index 8fee4dc92f..bfbc8c7070 100644 --- a/core/pfe-core/controllers/slot-controller.ts +++ b/core/pfe-core/controllers/slot-controller.ts @@ -48,6 +48,7 @@ const isSlot = export class SlotController implements ReactiveController { public static default = Symbol('default slot'); + public static anonymous = this.default; #nodes = new Map(); @@ -105,21 +106,6 @@ export class SlotController implements ReactiveController { this.#mo.disconnect(); } - /** - * Returns a boolean statement of whether or not any of those slots exists in the light DOM. - * - * @param {String|Array} name The slot name. - * @example this.hasSlotted("header"); - */ - hasSlotted(...names: string[]): boolean { - if (!names.length) { - return this.#nodes.get(SlotController.default)?.hasContent ?? false; - } else { - return names.some(x => - this.#nodes.get(x)?.hasContent ?? false); - } - } - /** * Given a slot name or slot names, returns elements assigned to the requested slots as an array. * If no value is provided, it returns all children not assigned to a slot (without a slot attribute). @@ -175,8 +161,6 @@ export class SlotController implements ReactiveController { return !this.hasSlotted(...names); } - - #onSlotChange = (event: Event & { target: HTMLSlotElement }) => { const slotName = event.target.name; this.#initSlot(slotName); From 70bfd0d97b99f632ce8880e26a6994ca62e30293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benny=20Powers=20-=20=D7=A2=D7=9D=20=D7=99=D7=A9=D7=A8?= =?UTF-8?q?=D7=90=D7=9C=20=D7=97=D7=99!?= Date: Mon, 4 Dec 2023 19:44:40 +0200 Subject: [PATCH 5/6] docs: update core/pfe-core/controllers/slot-controller.ts --- core/pfe-core/controllers/slot-controller.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/pfe-core/controllers/slot-controller.ts b/core/pfe-core/controllers/slot-controller.ts index 5ec862e387..2902adf2c3 100644 --- a/core/pfe-core/controllers/slot-controller.ts +++ b/core/pfe-core/controllers/slot-controller.ts @@ -48,6 +48,7 @@ const isSlot = export class SlotController implements ReactiveController { public static default = Symbol('default slot'); + /** @deprecated use `default` */ public static anonymous = this.default; #nodes = new Map(); From 4f862428a25f722e00fea8c1c87765a38e2fc924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benny=20Powers=20-=20=D7=A2=D7=9D=20=D7=99=D7=A9=D7=A8?= =?UTF-8?q?=D7=90=D7=9C=20=D7=97=D7=99!?= Date: Mon, 4 Dec 2023 19:45:19 +0200 Subject: [PATCH 6/6] docs: update .changeset/cold-cars-relate.md --- .changeset/cold-cars-relate.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.changeset/cold-cars-relate.md b/.changeset/cold-cars-relate.md index 99092249cd..21b638d22c 100644 --- a/.changeset/cold-cars-relate.md +++ b/.changeset/cold-cars-relate.md @@ -2,7 +2,5 @@ "@patternfly/pfe-core": minor --- -`SlotController`: - -- Add `isEmpty` method to check if a slot is empty. If no slot name is provided it will check the default slot. (#2603) -- `hasSlotted` method now returns default slot if no slot name is provided. (#2603) +`SlotController`: Add `isEmpty` method to check if a slot is empty. If no slot name is provided it will check the default slot. (#2603) +`SlotController`: `hasSlotted` method now returns default slot if no slot name is provided. (#2603)