@exadel/esl
Version:
Exadel Smart Library (ESL) is the lightweight custom elements library that provide a set of super-flexible components
139 lines (138 loc) • 5.3 kB
JavaScript
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 { decorate, memoize } from '../../esl-utils/decorators';
import { microtask } from '../../esl-utils/async/microtask';
import { isObject, deepMerge } from '../../esl-utils/misc/object';
import { uniq } from '../../esl-utils/misc/array';
import { SyntheticEventTarget } from '../../esl-utils/dom/events/target';
const isNamedObject = (obj) => isObject(obj) && typeof obj.name === 'string';
const isGroupCfg = (cfg) => isNamedObject(cfg) && typeof cfg.list === 'string';
const isButtonCfg = (cfg) => isNamedObject(cfg) && typeof cfg.action === 'string';
/** Class for managing share buttons configurations */
export class ESLShareConfig extends SyntheticEventTarget {
/** @returns ESLShareConfig shared instance */
static get instance() {
return new ESLShareConfig();
}
static set(provider) {
if (typeof provider === 'function')
return this.set(provider());
if (!isObject(provider))
return ESLShareConfig.instance;
if (provider instanceof Promise)
return provider.then((cfg) => this.set(cfg));
if (Array.isArray(provider.groups))
ESLShareConfig.instance.append(provider.groups);
if (Array.isArray(provider.buttons))
ESLShareConfig.instance.append(provider.buttons);
return ESLShareConfig.instance;
}
/** Updates items configuration from the list with the specified partial config */
static update(query, changes) {
return ESLShareConfig.instance.update(query, changes);
}
/** Appends single button or group to current configuration */
static append(cfg) {
return ESLShareConfig.instance.append(cfg);
}
constructor() {
super();
this._groups = new Map();
this._buttons = new Map();
}
/** @returns list of all available groups */
get groups() {
return Array.from(this._groups.entries()).map(([name, list]) => ({ name, list }));
}
/** @returns list of all available buttons */
get buttons() {
return Array.from(this._buttons.values());
}
/** Normalize list string by removing groups and extra whitespaces */
resolve(query) {
if (/\sall\s/.test(query))
return Array.from(this._buttons.keys());
const groups = new Set(); // Deduplicate groups
while (query.includes('group:')) {
query = query.replace(/group:(\S+)/gi, (term, name) => {
if (groups.has(name))
return '';
groups.add(name);
return this._groups.get(name) || '';
});
}
return query.split(' ').filter(Boolean);
}
/**
* Selects the buttons for the given list and returns their configuration.
* @returns config of buttons
*/
get(query) {
const terms = this.resolve(query);
const list = [];
terms.forEach((name) => {
name === 'all' ? list.push(...this.buttons) : list.push(this.getButton(name));
});
return uniq(list.filter(Boolean));
}
/** Clears the configuration */
clear() {
this._buttons.clear();
this._groups.clear();
this._onUpdate();
return this;
}
/**
* Gets the group of buttons configuration.
* @returns config of group
*/
getGroup(name) {
const list = this._groups.get(name);
return list ? { name, list } : undefined;
}
/**
* Gets the button configuration.
* @returns config of button
*/
getButton(name) {
return this._buttons.get(name);
}
/** Updates the configuration with a {@link ESLShareButtonConfig} or {@link ESLShareGroupConfig} */
add(config) {
if (isGroupCfg(config))
this._groups.set(config.name, config.list);
if (isButtonCfg(config))
this._buttons.set(config.name, config);
}
/** Updates the configuration with a {@link ESLShareButtonConfig}(s) or {@link ESLShareGroupConfig}(s) */
append(config) {
if (Array.isArray(config)) {
config.forEach(this.add, this);
}
else {
this.add(config);
}
this._onUpdate();
return this;
}
/** Updates items configuration from the list with the specified partial config */
update(query, changes) {
for (const btn of this.get(query)) {
this.append(deepMerge({}, btn, changes));
}
return this;
}
_onUpdate() {
this.dispatchEvent(new CustomEvent('change'));
}
}
__decorate([
decorate(microtask)
], ESLShareConfig.prototype, "_onUpdate", null);
__decorate([
memoize()
], ESLShareConfig, "instance", null);