import { LightningElement, api } from "lwc"; import { IconSprite, IconSize, IconSymbol } from "typings/custom"; import { toDxColor } from "dxUtils/css"; const fetches = new Map>(); const sizeMap = { xsmall: "xs", small: "sm", medium: "md", large: "lg", xlarge: "xl", "2xlarge": "2xl" }; export default class Icon extends LightningElement { @api sprite: IconSprite = "utility"; @api size: IconSize = "small"; @api symbol!: IconSymbol; @api color?: string; @api alt: string = ""; private node: SVGSymbolElement | undefined; private get hasAlt() { return !!this.alt; } private get style() { let stylestr = ""; if (this.size !== "override" && this.size in sizeMap) { stylestr = `--dx-c-icon-size: var(--dx-g-icon-size-${ sizeMap[this.size] });`; } if (this.color) { stylestr = `${stylestr} fill: ${toDxColor(this.color)};`; } return stylestr; } private get assetUrl() { return `/assets/icons/${this.sprite}-sprite/svg/symbols.svg`; } private get href() { return `${this.assetUrl}#${this.symbol}`; } private get symbolId() { return `dx__${this.sprite}__${this.symbol}`; } private async appendNodes() { if (this.node && this.node.id === this.symbolId) { return; } await this.fetchSprite(this.sprite); const svg = this.template.querySelector("svg")!; // TODO: Validate a better way // eslint-disable-next-line @lwc/lwc/no-document-query const node = document .getElementById(this.symbolId)! .cloneNode(true) as SVGSymbolElement; while (svg.firstChild) { svg.removeChild(svg.firstChild); } for (const n of Array.from(node.childNodes)) { svg.appendChild(n); } svg.setAttribute("viewBox", node.getAttribute("viewBox")!); } private async fetchSprite(sprite: IconSprite) { if (fetches.has(sprite)) { return fetches.get(sprite); } const promise = fetch(this.assetUrl) .then((res) => res.text()) .then((svg) => svg.replace(/id="/g, `id="dx__${sprite}__`)) .then((svg) => { const node = document.createElement("div"); // eslint-disable-next-line @lwc/lwc/no-inner-html node.innerHTML = svg; document.body.appendChild(node); }); fetches.set(sprite, promise); return promise; } }