Skip to content

Commit

Permalink
feat(esl-share): create esl-share-list component
Browse files Browse the repository at this point in the history
  • Loading branch information
dshovchko committed Oct 23, 2023
1 parent c881212 commit 90b1c1d
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/modules/esl-share/core.less
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@import './core/esl-share-button.less';
@import './core/esl-share-list.less';
@import './core/esl-share-popup-trigger.less';
@import './core/esl-share.less';
1 change: 1 addition & 0 deletions src/modules/esl-share/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './core/esl-share-action';
export * from './core/esl-share-action-registry';
export * from './core/esl-share-button';
export * from './core/esl-share-config';
export * from './core/esl-share-list';
export * from './core/esl-share-popup';
export * from './core/esl-share-popup-trigger';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
esl-share[mode='list'] {
esl-share-list {
display: inline-flex;
flex-wrap: wrap;
}
27 changes: 27 additions & 0 deletions src/modules/esl-share/core/esl-share-list.shape.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape';
import type {ESLShareList} from './esl-share-list';

/**
* Tag declaration interface of ESLShareList element
* Used for TSX declaration
*/
export interface ESLShareListTagShape extends ESLBaseElementShape<ESLShareList> {
/** Define the list of social networks or groups of them to display (all by default) */
list?: string;
/** Define URL to share (current page URL by default) */
'share-url'?: string;
/** Define title to share (current document title by default) */
'share-title'?: string;

/** Children are not allowed for ESLShareList */
children?: never[];
}

declare global {
namespace JSX {
export interface IntrinsicElements {
/** {@link ESLShareList} custom tag */
'esl-share-list': ESLShareListTagShape;
}
}
}
78 changes: 78 additions & 0 deletions src/modules/esl-share/core/esl-share-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {ESLBaseElement} from '../../esl-base-element/core';
import {isEqual} from '../../esl-utils/misc/object/compare';
import {attr, boolAttr, listen, memoize, prop} from '../../esl-utils/decorators';
import {ESLShareButton} from './esl-share-button';
import {ESLShareConfig} from './esl-share-config';

import type {ESLShareButtonConfig} from './esl-share-config';

/**
* ESLShare
* @author Dmytro Shovchko
*
* ESLShare is a custom element to dynamically draw {@link ESLShareButton}s using simplified shared config
*/
export class ESLShareList extends ESLBaseElement {
public static override is = 'esl-share-list';

/** Register {@link ESLShareList} component and dependent {@link ESLShareButton} */
public static override register(): void {
ESLShareButton.register();
super.register();
}

/** Event to dispatch on change of {@link ESLShareList} */
@prop('esl:share:changed') public SHARE_CHANGED_EVENT: string;

/**
* List of social networks or groups of them to display (all by default).
* The value - a string containing the names of the buttons or groups (specified with
* the prefix group:) separated by spaces.
* @example "facebook reddit group:default"
* */
@attr({defaultValue: 'all'}) public list: string;

/** @readonly Ready state marker */
@boolAttr({readonly: true}) public ready: boolean;

/** @returns config of buttons specified by the list attribute */
@memoize()
public get buttonsConfig(): ESLShareButtonConfig[] {
return ESLShareConfig.getList(this.list);
}

public override connectedCallback(): void {
super.connectedCallback();
this.init();
}

/** Initializes the component */
protected init(force?: boolean): void {
if (this.ready && !force) return;
this.buildContent();
this.onReady();
}

/** Appends buttons to the component. */
protected buildContent(): void {
this.innerHTML = '';
this.buttonsConfig.forEach((cfg) => {
const btn = ESLShareButton.create(cfg.name);
btn && this.appendChild(btn);
});
}

/** Actions on complete init and ready component. */
private onReady(): void {
this.$$attr('ready', true);
this.$$fire(this.SHARE_CHANGED_EVENT, {bubbles: false});
}

@listen({event: 'change', target: ESLShareConfig.instance})
protected _onConfigChange(): void {
const {buttonsConfig} = this;
memoize.clear(this, 'buttonsConfig');
if (isEqual(this.buttonsConfig, buttonsConfig)) return;
this.init(true);
}
}
46 changes: 13 additions & 33 deletions src/modules/esl-share/core/esl-share.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import {ESLBaseElement} from '../../esl-base-element/core';
import {isEqual} from '../../esl-utils/misc/object/compare';
import {attr, bind, boolAttr, jsonAttr, listen, memoize, prop} from '../../esl-utils/decorators';
import {ESLShareButton} from './esl-share-button';
import {attr, bind, boolAttr, jsonAttr} from '../../esl-utils/decorators';
import {ESLShareList} from './esl-share-list';
import {ESLSharePopupTrigger} from './esl-share-popup-trigger';
import {ESLShareConfig} from './esl-share-config';

import type {ESLSharePopupActionParams} from './esl-share-popup';
import type {ESLShareButtonConfig} from './esl-share-config';

/**
* ESLShare
Expand All @@ -17,9 +15,9 @@ import type {ESLShareButtonConfig} from './esl-share-config';
export class ESLShare extends ESLBaseElement {
public static override is = 'esl-share';

/** Register {@link ESLShare} component and dependent {@link ESLShareButton} */
/** Register {@link ESLShare} component and dependent {@link ESLShareList} and {@link ESLSharePopupTrigger} */
public static override register(): void {
ESLShareButton.register();
ESLShareList.register();
ESLSharePopupTrigger.register();
super.register();
}
Expand All @@ -32,9 +30,6 @@ export class ESLShare extends ESLBaseElement {
*/
public static readonly config = ESLShareConfig.set;

/** Event to dispatch on change of {@link ESLShare} */
@prop('esl:share:changed') public SHARE_CHANGED_EVENT: string;

/** Default initial params to pass into the popup trigger */
@jsonAttr<ESLSharePopupActionParams>({defaultValue: {
trackClick: true,
Expand All @@ -60,17 +55,12 @@ export class ESLShare extends ESLBaseElement {

protected _content: string;

/** @returns config of buttons specified by the list attribute */
@memoize()
public get buttonsConfig(): ESLShareButtonConfig[] {
return ESLShareConfig.getList(this.list);
}

public override connectedCallback(): void {
super.connectedCallback();
this.init();
}

/** Initializes the component */
protected init(force?: boolean): void {
if (this.ready && !force) return;
if (!this.mode) this.mode = 'list';
Expand All @@ -83,19 +73,18 @@ export class ESLShare extends ESLBaseElement {
@bind
protected buildContent(): void {
this.innerHTML = '';
this.mode === 'list' ? this.appendButtons() : this.appendTrigger();
this.mode === 'list' ? this.appendList() : this.appendPopupTrigger();
}

/** Appends buttons to the share component. */
protected appendButtons(): void {
this.buttonsConfig.forEach((cfg) => {
const btn = ESLShareButton.create(cfg.name);
btn && this.appendChild(btn);
});
/** Appends share list to the share component. */
protected appendList(): void {
const $list = ESLShareList.create();
$list.list = this.list;
this.appendChild($list);
}

/** Appends trigger to the share component. */
protected appendTrigger(): void {
/** Appends share popup trigger to the share component. */
protected appendPopupTrigger(): void {
const {list} = this;
const $trigger = ESLSharePopupTrigger.create();
Object.assign($trigger, this.triggerInitialParams, {list});
Expand All @@ -106,14 +95,5 @@ export class ESLShare extends ESLBaseElement {
/** Actions on complete init and ready component. */
private onReady(): void {
this.$$attr('ready', true);
this.$$fire(this.SHARE_CHANGED_EVENT, {bubbles: false});
}

@listen({event: 'change', target: ESLShareConfig.instance})
protected _onConfigChange(): void {
const {buttonsConfig} = this;
memoize.clear(this, 'buttonsConfig');
if (isEqual(this.buttonsConfig, buttonsConfig)) return;
this.init(true);
}
}

0 comments on commit 90b1c1d

Please sign in to comment.