UNPKG

@exadel/esl

Version:

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

170 lines (169 loc) 6.07 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 { bind, attr, boolAttr, listen } from '../../../esl-utils/decorators'; import { ARROW_DOWN, ARROW_UP, ENTER, SPACE } from '../../../esl-utils/dom/keys'; import { ExportNs } from '../../../esl-utils/environment/export-ns'; import { ESLScrollbar } from '../../../esl-scrollbar/core'; import { ESLSelectItem } from './esl-select-item'; import { ESLSelectWrapper } from './esl-select-wrapper'; /** * ESLSelectList component * @author Alexey Stsefanovich (ala'n) * * ESLSelectList is a component to show selectable list of items. Decorates native HTMLSelectElement */ let ESLSelectList = class ESLSelectList extends ESLSelectWrapper { static register() { ESLSelectItem.register(); super.register(); } constructor() { super(); this.$list = document.createElement('div'); this.$list.setAttribute('role', 'list'); this.$list.classList.add('esl-scrollable-content'); this.$list.classList.add('esl-select-list-container'); this.$scroll = ESLScrollbar.create(); this.$scroll.target = '::prev'; this.$selectAll = ESLSelectItem.create(); this.$selectAll.classList.add('esl-select-all-item'); } attributeChangedCallback(attrName, oldVal, newVal) { if (!this.connected || newVal === oldVal) return; if (attrName === 'select-all-label') { this.$selectAll.textContent = newVal; } if (attrName === 'disabled') { this._updateDisabled(); } } connectedCallback() { super.connectedCallback(); this.appendChild(this.$selectAll); this.appendChild(this.$list); this.appendChild(this.$scroll); this.bindSelect(); this._updateDisabled(); } disconnectedCallback() { super.disconnectedCallback(); this.appendChild(this.$selectAll); this.appendChild(this.$list); this.appendChild(this.$scroll); } bindSelect() { const target = this.querySelector('[esl-select-target]'); if (!target || !(target instanceof HTMLSelectElement)) return; this.$select = target; } _renderItems() { if (!this.$select) return; this.$list.innerHTML = ''; this.$items = this.options.map(ESLSelectItem.build); if (this.pinSelected) { this._renderGroup(this.$items.filter((option) => option.selected)); this._renderGroup(this.$items.filter((option) => !option.selected)); } else { this._renderGroup(this.$items); } this.toggleAttribute('multiple', this.multiple); } _renderGroup(items) { items.forEach((item) => this.$list.appendChild(item)); const [last] = items.slice(-1); last && last.classList.add('last-in-group'); } _updateSelectAll() { if (!this.multiple) { this.$selectAll.removeAttribute('tabindex'); return; } this.$selectAll.tabIndex = 0; this.$selectAll.selected = this.isAllSelected(); this.$selectAll.textContent = this.selectAllLabel; } _updateDisabled() { this.setAttribute('aria-disabled', String(this.disabled)); if (!this.$select) return; this.$select.disabled = this.disabled; } _onTargetChange(newTarget, oldTarget) { super._onTargetChange(newTarget, oldTarget); this._updateSelectAll(); this._renderItems(); } _onChange() { this._updateSelectAll(); this.$items.forEach((item) => item.update()); } _onListChange() { this._renderItems(); } _onClick(e) { if (this.disabled) return; const target = e.target; if (!target || !(target instanceof ESLSelectItem)) return; if (target.classList.contains('esl-select-all-item')) { this.setAllSelected(!target.selected); } else { this.setSelected(target.value, !target.selected); } } _onKeydown(e) { if ([ENTER, SPACE].includes(e.key)) { this._onClick(e); e.preventDefault(); } if ([ARROW_UP, ARROW_DOWN].includes(e.key)) { const index = this.$items.indexOf(document.activeElement); const count = this.$items.length; const increment = e.key === ARROW_UP ? -1 : 1; if (index === -1) return; this.$items[(index + increment + count) % count].focus(); e.preventDefault(); } } }; ESLSelectList.is = 'esl-select-list'; ESLSelectList.observedAttributes = ['select-all-label', 'disabled']; __decorate([ attr({ defaultValue: 'Select All' }) ], ESLSelectList.prototype, "selectAllLabel", void 0); __decorate([ boolAttr() ], ESLSelectList.prototype, "disabled", void 0); __decorate([ boolAttr() ], ESLSelectList.prototype, "pinSelected", void 0); __decorate([ bind ], ESLSelectList.prototype, "_onTargetChange", null); __decorate([ listen({ inherit: true }) ], ESLSelectList.prototype, "_onChange", null); __decorate([ bind ], ESLSelectList.prototype, "_onListChange", null); __decorate([ listen('click') ], ESLSelectList.prototype, "_onClick", null); __decorate([ listen('keydown') ], ESLSelectList.prototype, "_onKeydown", null); ESLSelectList = __decorate([ ExportNs('SelectList') ], ESLSelectList); export { ESLSelectList };