From 0b6a663a5826a15e3d2e1012632085b0f346f52a Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Tue, 9 Aug 2022 17:33:26 +0200 Subject: [PATCH] Add support for changes to the icon name and FA6 Pro --- ts/WoltLabSuite/WebComponent/fa-icon.ts | 80 +++++++++++++++---- .../js/WoltLabSuite/WebComponent/fa-icon.js | 68 ++++++++++++---- 2 files changed, 118 insertions(+), 30 deletions(-) diff --git a/ts/WoltLabSuite/WebComponent/fa-icon.ts b/ts/WoltLabSuite/WebComponent/fa-icon.ts index 3bcfeda113..913e5b7f24 100644 --- a/ts/WoltLabSuite/WebComponent/fa-icon.ts +++ b/ts/WoltLabSuite/WebComponent/fa-icon.ts @@ -1,4 +1,18 @@ (() => { + let isFA6Free: boolean; + function isFontAwesome6Free(): boolean { + if (isFA6Free === undefined) { + isFA6Free = true; + + const iconFont = window.getComputedStyle(document.documentElement).getPropertyValue("--fa-font-family"); + if (iconFont === "Font Awesome 6 Pro") { + isFA6Free = false; + } + } + + return isFA6Free; + } + const HeightMap = new Map([ [16, 14], [24, 18], @@ -13,10 +27,7 @@ class FaIcon extends HTMLElement { connectedCallback() { this.validate(); - - const root = this.attachShadow({ mode: "open" }); - const [codepoint] = window.getFontAwesome6IconMetadata(this.name)!; - root.append(codepoint); + this.setIcon(this.name, this.solid); } private validate(): void { @@ -28,34 +39,67 @@ if (this.name === "") { throw new TypeError("Must provide the name of the icon."); - } - - const styles = window.getFontAwesome6IconMetadata(this.name); - if (styles === undefined) { + } else if (!this.isValidIconName(this.name)) { throw new TypeError(`The icon '${this.name}' is unknown or unsupported.`); } } - setIcon(name: string, type: "" | "solid"): void { - const metadata = window.getFontAwesome6IconMetadata(name); - if (metadata === undefined) { + setIcon(name: string, isSolid: boolean): void { + if (!this.isValidIconName(name)) { 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}'.`); + if (!this.isValidIconStyle(name, isSolid)) { + throw new Error(`The icon '${name}' only supports the 'solid' style.`); } - this.solid = type === "solid"; + this.solid = isSolid; this.name = name; - const root = this.shadowRoot!; + this.updateIcon(); + } + + private isValidIconName(name: string | null): boolean { + return name !== null && window.getFontAwesome6IconMetadata(name) !== undefined; + } + + private isValidIconStyle(name: string, isSolid: boolean): boolean { + if (!isSolid && isFontAwesome6Free()) { + const [, styles] = window.getFontAwesome6IconMetadata(name)!; + if (!styles.includes("regular")) { + return false; + } + } + + return true; + } + + private getShadowRoot(): ShadowRoot { + if (this.shadowRoot === null) { + return this.attachShadow({ mode: "open" }); + } + + return this.shadowRoot; + } + + private updateIcon(): void { + const root = this.getShadowRoot(); root.childNodes[0]?.remove(); + const [codepoint] = window.getFontAwesome6IconMetadata(this.name)!; root.append(codepoint); } + attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void { + switch (name) { + case "name": + if (newValue !== null && this.isValidIconName(newValue)) { + this.updateIcon(); + } + break; + } + } + get solid(): boolean { return this.hasAttribute("solid"); } @@ -84,6 +128,10 @@ return parseInt(size); } + + static get observedAttributes() { + return ["name"]; + } } window.customElements.define("fa-icon", FaIcon); diff --git a/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js b/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js index 32414f26fd..e6e379f8c8 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js +++ b/wcfsetup/install/files/js/WoltLabSuite/WebComponent/fa-icon.js @@ -1,5 +1,16 @@ "use strict"; (() => { + let isFA6Free; + function isFontAwesome6Free() { + if (isFA6Free === undefined) { + isFA6Free = true; + const iconFont = window.getComputedStyle(document.documentElement).getPropertyValue("--fa-font-family"); + if (iconFont === "Font Awesome 6 Pro") { + isFA6Free = false; + } + } + return isFA6Free; + } const HeightMap = new Map([ [16, 14], [24, 18], @@ -13,9 +24,7 @@ class FaIcon extends HTMLElement { connectedCallback() { this.validate(); - const root = this.attachShadow({ mode: "open" }); - const [codepoint] = window.getFontAwesome6IconMetadata(this.name); - root.append(codepoint); + this.setIcon(this.name, this.solid); } validate() { if (this.size === 0) { @@ -27,27 +36,55 @@ if (this.name === "") { throw new TypeError("Must provide the name of the icon."); } - const styles = window.getFontAwesome6IconMetadata(this.name); - if (styles === undefined) { + else if (!this.isValidIconName(this.name)) { throw new TypeError(`The icon '${this.name}' is unknown or unsupported.`); } } - setIcon(name, type) { - var _a; - const metadata = window.getFontAwesome6IconMetadata(name); - if (metadata === undefined) { + setIcon(name, isSolid) { + if (!this.isValidIconName(name)) { 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}'.`); + if (!this.isValidIconStyle(name, isSolid)) { + throw new Error(`The icon '${name}' only supports the 'solid' style.`); } - this.solid = type === "solid"; + this.solid = isSolid; this.name = name; - const root = this.shadowRoot; + this.updateIcon(); + } + isValidIconName(name) { + return name !== null && window.getFontAwesome6IconMetadata(name) !== undefined; + } + isValidIconStyle(name, isSolid) { + if (!isSolid && isFontAwesome6Free()) { + const [, styles] = window.getFontAwesome6IconMetadata(name); + if (!styles.includes("regular")) { + return false; + } + } + return true; + } + getShadowRoot() { + if (this.shadowRoot === null) { + return this.attachShadow({ mode: "open" }); + } + return this.shadowRoot; + } + updateIcon() { + var _a; + const root = this.getShadowRoot(); (_a = root.childNodes[0]) === null || _a === void 0 ? void 0 : _a.remove(); + const [codepoint] = window.getFontAwesome6IconMetadata(this.name); root.append(codepoint); } + attributeChangedCallback(name, oldValue, newValue) { + switch (name) { + case "name": + if (newValue !== null && this.isValidIconName(newValue)) { + this.updateIcon(); + } + break; + } + } get solid() { return this.hasAttribute("solid"); } @@ -72,6 +109,9 @@ } return parseInt(size); } + static get observedAttributes() { + return ["name"]; + } } window.customElements.define("fa-icon", FaIcon); })(); -- 2.20.1