UNPKG

rivet-stickers

Version:

Stickers for Indiana University's Rivet Design System

114 lines (98 loc) 2.86 kB
/*! * Copyright (C) 2024 The Trustees of Indiana University * SPDX-License-Identifier: BSD-3-Clause */ import './rivet-sticker-element.css'; const packageName = 'Rivet Stickers'; const elementName = 'rvt-sticker'; const nameAttributeName = 'name'; const registeredEventName = 'rvtStickerRegistered'; const size = 80; const nameToTemplateMap = new Map(); export function registerSticker (name, content) { window.customElements.get(elementName).register?.(name, content); } class RivetStickerElement extends window.HTMLElement { #name; #requestUpdate = throttleRAF(this.#update.bind(this)); static get observedAttributes () { return [nameAttributeName]; } static register (name, content) { if (!name || typeof name !== 'string') { throw new Error(`${packageName}: Name must be a string.`); } const template = document.createElement('template'); template.innerHTML = content; if (template.content.children.length !== 1) { throw new Error(`${packageName} (${name}): Content must contain one SVG element.`); } const svg = template.content.firstChild; if (svg.nodeName.toLowerCase() !== 'svg') { throw new Error(`${packageName} (${name}): Content must be a SVG element.`); } setDefaultAttributes(svg, { 'aria-hidden': 'true', fill: 'currentColor', focusable: 'false', height: '100%', viewBox: `0 0 ${size} ${size}`, width: '100%', xmlns: 'http://www.w3.org/2000/svg' }); nameToTemplateMap.set(name, template); const event = new CustomEvent(registeredEventName, { detail: { name } }); document.dispatchEvent(event); } attributeChangedCallback () { this.#requestUpdate(); } connectedCallback () { document.addEventListener(registeredEventName, this.#requestUpdate); this.#requestUpdate(); } disconnectedCallback () { document.removeEventListener(registeredEventName, this.#requestUpdate); } #update () { const name = this.getAttribute(nameAttributeName); if (!nameToTemplateMap.has(name) || this.#name === name) { return; } const content = nameToTemplateMap.get(name).content.cloneNode(true); this.replaceChildren(content); this.#name = name; } } if (!window.customElements.get(elementName)) { window.customElements.define(elementName, RivetStickerElement); } // // Utilities // function setDefaultAttribute (element, name, value) { if (!element.hasAttribute(name)) { element.setAttribute(name, value); } } function setDefaultAttributes (element, attributes) { Object.entries(attributes).forEach(([name, value]) => { setDefaultAttribute(element, name, value); }); } // Call the function at most once per animation frame. function throttleRAF (fn) { let wait = false; return function (...args) { if (wait) { return; } wait = true; window.requestAnimationFrame(() => { fn.call(this, ...args); wait = false; }); }; }