ba-web-components/src/components/spinner/spinner.mjs
Alan Bridgeman d95bdda9ec
All checks were successful
Build, Test, and Publish (to Private NPM Registry) UI Components Library / publish (push) Successful in 1m2s
Slight adjustment to tab styles + added spinner component
2026-05-19 21:36:00 -05:00

96 lines
No EOL
4 KiB
JavaScript

import { ComposableElement } from '../ComposableElement.mjs';
/**
* Spinner Web Component
*
* A simple spinner component that indicates loading or processing state.
* This component uses the `aria-busy` attribute in combination with CSS tricks to create a spinner that is accessible, modern, and easy to manage.
*/
export class Spinner extends ComposableElement {
constructor() {
super();
}
// -------------------------------
// Web Component Lifecycle Methods
// -------------------------------
/**
* Does initial setup and adds event listeners for interactivity
*
* `connectedCallback` is a lifecycle method in web components that runs when the custom element is inserted into the document's Document Object Model (DOM).
* It can be invoked multiple times if the element is removed and then re-inserted into the DOM.
*
* Timing: It is called after the element's constructor() but before the element's children are necessarily connected or fully rendered.
* Purpose: It is the ideal place to set up tasks that should only occur when the element is actually present in the live document. Common uses include:
*/
connectedCallback() {
const internals = this.attachInternals();
this.shadow = this.shadowRoot;
if (!this.shadow) {
this.shadow = this.attachShadow({ mode: 'open' });
// Defer execution until the browser finishes parsing the children
setTimeout(() => {
// Recreate the template using the shadow DOM that is only available through JavaScript
this.createTemplateInJS(this.shadow);
}, 0);
}
}
/**
* Cleans up event listeners when the component is removed from the DOM
*
* `disconnectedCallback` is a lifecycle method in web components that runs when the custom element is removed from the document's DOM.
* It can be invoked multiple times if the element is removed and then re-inserted into the DOM.
*
* Timing: It is called after the element is removed from the DOM but before it is garbage collected.
* Purpose: It is the ideal place to clean up any resources or event listeners that were set up in `connectedCallback`.
*
* Common uses include:
* - Removing event listeners to prevent memory leaks
* - Clearing timers or intervals
* - Disconnecting from external data sources or APIs
*/
disconnectedCallback() {}
/**
* Recreate the template in the shadow DOM through JavaScript instead of relying on the `shadowrootmode` attribute
*
* @param {ShadowRoot} shadow The shadow DOM to attach the template to
*/
createTemplateInJS(shadow) {
const config = this.initializeComponent('spinner', shadow);
if(config == null) {
throw new Error('Spinner configuration not found. Please ensure you have a script tag with the appropriate data-spinner-config attribute containing the necessary JSON configuration for the spinner component.');
}
// Create the container div for the spinner component
const spinnerSpan = document.createElement('span');
spinnerSpan.id = config.spinnerId || 'spinner';
spinnerSpan.setAttribute('aria-busy', 'true');
if(config.inline) {
spinnerSpan.classList.add('inline');
}
if(typeof config.speed !== 'undefined' && (config.speed === 'slow' || config.speed === 'fast')) {
spinnerSpan.classList.add(config.speed);
}
const spinnerSlot = document.createElement('slot');
spinnerSlot.name = 'spinner-content';
spinnerSpan.appendChild(spinnerSlot);
// Finally, append the entire spinner span to the shadow DOM of the component
shadow.appendChild(spinnerSpan);
}
}
document.addEventListener('DOMContentLoaded', () => {
if (!customElements.get('ba-spinner')) {
customElements.define('ba-spinner', Spinner);
}
});