From 93a46a091f3c79e4d3d34e9632a199127dac22e8 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 8 Aug 2022 18:06:49 +0200 Subject: [PATCH] Add method `setIcon` to change the icon on runtime --- ts/WoltLabSuite/WebComponent/fa-icon.ts | 79 ++++++++++++++++--- .../js/WoltLabSuite/WebComponent/fa-icon.js | 67 +++++++++++++--- 2 files changed, 122 insertions(+), 24 deletions(-) diff --git a/ts/WoltLabSuite/WebComponent/fa-icon.ts b/ts/WoltLabSuite/WebComponent/fa-icon.ts index 8fe515e161..c61b8b7556 100644 --- a/ts/WoltLabSuite/WebComponent/fa-icon.ts +++ b/ts/WoltLabSuite/WebComponent/fa-icon.ts @@ -20,7 +20,7 @@ slot.name = "svg"; root.append(slot); } else { - const [codepoint] = window.getFontAwesome6Styles(this.name!)!; + const [codepoint] = window.getFontAwesome6Styles(this.name)!; root.append(codepoint); // TODO: Add style @@ -35,47 +35,100 @@ } if (this.brand) { - if (this.name !== null) { + if (this.name !== "") { throw new TypeError("Cannot provide a name for brand icons."); } } else { - if (this.name === null) { + if (this.name === "") { throw new TypeError("Must provide the name of the icon."); } const styles = window.getFontAwesome6Styles(this.name); if (styles === undefined) { - throw new TypeError(`The icon '${name}' is unknown or unsupported.`); + throw new TypeError(`The icon '${this.name}' is unknown or unsupported.`); } } } private prepareRoot(): ShadowRoot { - const root = this.attachShadow({ mode: "closed" }); + const root = this.attachShadow({ mode: "open" }); if (this.brand) { const iconHeight = HeightMap.get(this.size)!; const style = document.createElement("style"); style.textContent = ` - ::slotted(svg) { - fill: currentColor; - height: ${iconHeight}px; - shape-rendering: geometricprecision; - } - `; + ::slotted(svg) { + fill: currentColor; + height: ${iconHeight}px; + shape-rendering: geometricprecision; + } + `; root.append(style); } return root; } + setIcon(name: string, type: "regular" | "solid"): void { + if (this.brand) { + throw new Error("Cannot change the icon of a brand icon."); + } + + const metadata = window.getFontAwesome6Styles(name); + if (metadata === undefined) { + throw new TypeError(`The icon '${name}' is unknown or unsupported.`); + } + + const [codepoint, styles] = metadata; + if (!styles.includes(type)) { + throw new Error(`The icon '${name}' does not support the style '${type}'.`); + } + + this.solid = type === "solid"; + this.regular = type === "regular"; + this.name = name; + + const root = this.shadowRoot!; + root.childNodes[0]?.remove(); + + root.append(codepoint); + } + + get solid(): boolean { + return this.hasAttribute("solid"); + } + + set solid(solid: boolean) { + if (solid) { + this.setAttribute("solid", ""); + } else { + this.removeAttribute("solid"); + } + } + + get regular(): boolean { + return this.hasAttribute("regular"); + } + + set regular(regular: boolean) { + if (regular) { + this.setAttribute("regular", ""); + } else { + this.removeAttribute("regular"); + } + } + get brand(): boolean { return this.hasAttribute("brand"); } - get name(): string | null { - return this.getAttribute("name"); + get name(): string { + return this.getAttribute("name") || ""; + } + + set name(name: string) { + this.setAttribute("name", name); } get size(): number { diff --git a/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js b/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js index fa582e3edc..f1d8639649 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js +++ b/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js @@ -32,41 +32,86 @@ throw new TypeError("Must provide a valid icon size."); } if (this.brand) { - if (this.name !== null) { + if (this.name !== "") { throw new TypeError("Cannot provide a name for brand icons."); } } else { - if (this.name === null) { + if (this.name === "") { throw new TypeError("Must provide the name of the icon."); } const styles = window.getFontAwesome6Styles(this.name); if (styles === undefined) { - throw new TypeError(`The icon '${name}' is unknown or unsupported.`); + throw new TypeError(`The icon '${this.name}' is unknown or unsupported.`); } } } prepareRoot() { - const root = this.attachShadow({ mode: "closed" }); + const root = this.attachShadow({ mode: "open" }); if (this.brand) { const iconHeight = HeightMap.get(this.size); const style = document.createElement("style"); style.textContent = ` - ::slotted(svg) { - fill: currentColor; - height: ${iconHeight}px; - shape-rendering: geometricprecision; - } - `; + ::slotted(svg) { + fill: currentColor; + height: ${iconHeight}px; + shape-rendering: geometricprecision; + } + `; root.append(style); } return root; } + setIcon(name, type) { + var _a; + if (this.brand) { + throw new Error("Cannot change the icon of a brand icon."); + } + const metadata = window.getFontAwesome6Styles(name); + if (metadata === undefined) { + throw new TypeError(`The icon '${name}' is unknown or unsupported.`); + } + const [codepoint, styles] = metadata; + if (!styles.includes(type)) { + throw new Error(`The icon '${name}' does not support the style '${type}'.`); + } + this.solid = type === "solid"; + this.regular = type === "regular"; + this.name = name; + const root = this.shadowRoot; + (_a = root.childNodes[0]) === null || _a === void 0 ? void 0 : _a.remove(); + root.append(codepoint); + } + get solid() { + return this.hasAttribute("solid"); + } + set solid(solid) { + if (solid) { + this.setAttribute("solid", ""); + } + else { + this.removeAttribute("solid"); + } + } + get regular() { + return this.hasAttribute("regular"); + } + set regular(regular) { + if (regular) { + this.setAttribute("regular", ""); + } + else { + this.removeAttribute("regular"); + } + } get brand() { return this.hasAttribute("brand"); } get name() { - return this.getAttribute("name"); + return this.getAttribute("name") || ""; + } + set name(name) { + this.setAttribute("name", name); } get size() { const size = this.getAttribute("size"); -- 2.20.1