UNPKG

@exadel/esl

Version:

Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components

125 lines (124 loc) 4.94 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { setAttr } from '../../esl-utils/dom/attr'; import { prop } from '../../esl-utils/decorators'; import { ESLEventUtils } from '../../esl-utils/dom/events'; import { CSSClassUtils } from '../../esl-utils/dom/class'; /** Finalize tag name (`is`) for passed ESLBaseElement-based class */ const finalize = (type, tagName) => { Object.defineProperty(type, 'is', { get: () => tagName, set(value) { if (this === type) throw Error(`[ESL]: Cannot override ${type.name}.is property, the class is already registered`); Object.defineProperty(this, 'is', { value, writable: true, configurable: true }); } }); }; /** * Base class for ESL custom elements * Allows defining custom element with the optional custom tag name */ export class ESLBaseElement extends HTMLElement { constructor() { super(...arguments); this._connected = false; } /** @returns custom element tag name */ get baseTagName() { return this.constructor.is; } connectedCallback() { this._connected = true; this.classList.add(this.baseTagName); // Automatic subscription happens only if the element is currently in the DOM if (this.isConnected) ESLEventUtils.subscribe(this); } disconnectedCallback() { this._connected = false; ESLEventUtils.unsubscribe(this); } /** * Callback to handle changing of element attributes. * Happens when attribute accessed for writing independently of the actual value change */ attributeChangedCallback(name, oldValue, newValue) { } /** Checks that the element's `connectedCallback` has been executed */ get connected() { return this._connected; } $$on(event, handler) { return ESLEventUtils.subscribe(this, event, handler); } /** Unsubscribes event listener */ $$off(...condition) { return ESLEventUtils.unsubscribe(this, ...condition); } /** * Gets or sets CSS classes for the current element. * @param cls - CSS classes query {@link CSSClassUtils} * @param value - boolean to set CSS class(es) state or undefined to skip mutation * @returns current classes state or passed state */ $$cls(cls, value) { if (value === undefined) return CSSClassUtils.has(this, cls); CSSClassUtils.toggle(this, cls, value); return value; } /** * Gets or sets an attribute for the current element. * If the `value` param is undefined then skips mutation. * @param name - attribute name * @param value - string attribute value, boolean attribute state or `null` to delete attribute * @returns the current attribute value or previous value for mutation */ $$attr(name, value) { const prevValue = this.getAttribute(name); if (value !== undefined) setAttr(this, name, value); return prevValue; } /** * Dispatches component custom event. * @param eventName - event name * @param eventInit - custom event init. See {@link CustomEventInit} */ $$fire(eventName, eventInit) { return ESLEventUtils.dispatch(this, eventName, eventInit); } /** * Register component in the {@link customElements} registry * @param tagName - custom tag name to register custom element */ static register(tagName) { tagName = tagName || this.is; if (!tagName) throw new DOMException('[ESL]: Incorrect tag name', 'NotSupportedError'); const constructor = customElements.get(tagName); if (constructor && (constructor !== this || constructor.is !== tagName)) { throw new DOMException('[ESL]: Element tag already occupied or inconsistent', 'NotSupportedError'); } if (constructor) return; finalize(this, tagName); customElements.define(tagName, this); } /** Shortcut for `customElements.whenDefined(currentCustomElement)` */ static get registered() { return customElements.whenDefined(this.is); } static create() { return document.createElement(this.is); } } /** Custom element tag name */ ESLBaseElement.is = ''; __decorate([ prop('esl:refresh') ], ESLBaseElement.prototype, "REFRESH_EVENT", void 0);