/** * Icon Link Button Component * A text link with an icon on the left * Used for actions like "Add to wishlist", "Write a review" */ import { wishlistIcon } from "../icons/wishlist-icon.js"; import { reviewIcon } from "../icons/review-icon.js"; class IconLinkButton extends HTMLElement { static get observedAttributes() { return ["href", "icon"]; } constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.render(); this.setupEventListeners(); } attributeChangedCallback() { if (this.shadowRoot) { this.render(); this.setupEventListeners(); } } setupEventListeners() { const button = this.shadowRoot?.querySelector(".icon-link-button"); if (button && !this.hasAttribute("href")) { button.addEventListener("click", () => { this.dispatchEvent( new CustomEvent("link-click", { bubbles: true, composed: true, }) ); }); } } get href() { return this.getAttribute("href") || ""; } get icon() { return this.getAttribute("icon") || ""; } getIconHtml() { switch (this.icon) { case "wishlist": return wishlistIcon({ size: 24, color: "currentColor" }); case "review": return reviewIcon({ size: 24, color: "currentColor" }); default: return ""; } } render() { const isLink = this.hasAttribute("href") && this.href; const tag = isLink ? "a" : "button"; const hrefAttr = isLink ? `href="${this.href}"` : ""; const typeAttr = isLink ? "" : 'type="button"'; const iconHtml = this.getIconHtml(); this.shadowRoot.innerHTML = ` <${tag} class="icon-link-button" ${hrefAttr} ${typeAttr} > ${iconHtml ? `${iconHtml}` : ""} `; } } customElements.define("icon-link-button", IconLinkButton);