UNPKG

@exadel/esl

Version:

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

140 lines (139 loc) 4.99 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 { ESLBaseElement } from '../../../esl-base-element/core'; import { format } from '../../../esl-utils/misc/format'; import { rafDecorator } from '../../../esl-utils/async/raf'; import { attr, boolAttr, decorate, listen, memoize } from '../../../esl-utils/decorators'; /** * ESLSelectRenderer component * @author Alexey Stsefanovich (ala'n) * * Auxiliary inner custom element to render {@link ESLSelect} inline field */ export class ESLSelectRenderer extends ESLBaseElement { /** Internal container */ get $container() { const $container = document.createElement('div'); $container.className = 'esl-select-text-container'; $container.appendChild(this.$text); $container.appendChild(this.$rest); return $container; } /** Inner remove button */ get $remove() { const $remove = document.createElement('button'); $remove.type = 'button'; $remove.setAttribute('aria-label', 'Clear'); $remove.className = 'esl-select-clear-btn icon-nav-close-menu'; return $remove; } /** Inner text element */ get $text() { const $text = document.createElement('span'); $text.className = 'esl-select-text'; return $text; } /** Inner rest label element */ get $rest() { const $rest = document.createElement('span'); $rest.className = 'esl-select-text'; return $rest; } /** ESLSelect owner */ get owner() { if (!this.parentElement || !this.parentElement.matches('esl-select')) return null; return this.parentElement; } connectedCallback() { super.connectedCallback(); this.appendChild(this.$container); this.appendChild(this.$remove); Promise.resolve().then(() => this.render()); } disconnectedCallback() { super.disconnectedCallback(); this.removeChild(this.$container); this.removeChild(this.$remove); } /** Rerender component with markers */ render() { if (!this.owner) return; const selected = this.owner.selectedOptions; this.hasValue = !!selected.length; this.toggleAttribute('multiple', this.owner.multiple); this.applyItems(selected.map((item) => item.text)); } /** Render item with a visible items limit */ apply(items, limit) { const length = items.length; const rest = length - limit; const options = { rest, length, limit }; this.$text.textContent = items.slice(0, limit).join(', '); if (rest > 0) { this.$rest.textContent = format(this.moreLabelFormat || '', options); } else { this.$rest.textContent = ''; } } /** Render items using adaptive algorithm */ applyItems(items) { let size = 0; do { this.apply(items, ++size); // Render with extended limit while it not fits to the container } while (size <= items.length && this.$container.scrollWidth <= this.$container.clientWidth); this.apply(items, size - 1); // Render last limit that fits } /** Handle clear button click */ _onClear(e) { if (!this.owner) return; this.owner.setAllSelected(false); e.stopPropagation(); e.preventDefault(); } _onResize() { this.render(); } } ESLSelectRenderer.is = 'esl-select-renderer'; __decorate([ attr() ], ESLSelectRenderer.prototype, "emptyText", void 0); __decorate([ attr() ], ESLSelectRenderer.prototype, "moreLabelFormat", void 0); __decorate([ boolAttr() ], ESLSelectRenderer.prototype, "hasValue", void 0); __decorate([ memoize() ], ESLSelectRenderer.prototype, "$container", null); __decorate([ memoize() ], ESLSelectRenderer.prototype, "$remove", null); __decorate([ memoize() ], ESLSelectRenderer.prototype, "$text", null); __decorate([ memoize() ], ESLSelectRenderer.prototype, "$rest", null); __decorate([ listen({ event: 'esl:change:value', target: (el) => el.owner }) ], ESLSelectRenderer.prototype, "render", null); __decorate([ listen({ event: 'click', selector: '.esl-select-clear-btn' }) ], ESLSelectRenderer.prototype, "_onClear", null); __decorate([ listen({ event: 'resize', target: window }), decorate(rafDecorator) ], ESLSelectRenderer.prototype, "_onResize", null);