Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

epic (esl-share): initial implementation #1358

Merged
merged 95 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from 80 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
bc2cc7f
docs(esl-share): create esl-share example page
dshovchko Oct 26, 2022
741fbee
docs(esl-share): create README
dshovchko Oct 28, 2022
6213f36
feat(esl-share): create esl-share-icon component
dshovchko Oct 28, 2022
0ff835a
feat(esl-share): update all.ts and all.less files
dshovchko Oct 28, 2022
9e0fb79
feat(esl-share): create esl-share-trigger component
dshovchko Oct 28, 2022
3e0a2b0
feat(esl-share): create esl-share component
dshovchko Oct 28, 2022
1e851d0
feat(esl-share): create esl-share-button initial implementation
dshovchko Nov 11, 2022
8411343
feat(esl-share): create abstract base action class
dshovchko Nov 11, 2022
d176117
chore(deps-dev): bump @typescript-eslint/parser from 5.40.1 to 5.41.0
dependabot[bot] Oct 25, 2022
6620a7c
chore(deps-dev): bump @typescript-eslint/eslint-plugin
dependabot[bot] Oct 27, 2022
ab4469d
chore(gh-pages): fix logo svg to prevent artifacts on iOS devices (#1…
Natalie-Smirnova Oct 27, 2022
d72bcd8
chore(gh-pages): add 11ty generator marker metatag
ala-n Nov 1, 2022
b830900
chore(gh-pages): add robots="noindex" meta tag for forward template
ala-n Nov 1, 2022
e3eafc5
chore(deps-dev): bump @types/jest from 29.2.0 to 29.2.1
dependabot[bot] Nov 1, 2022
126f79b
chore(deps-dev): bump @commitlint/cli from 17.1.2 to 17.2.0
dependabot[bot] Nov 1, 2022
39dd3d9
chore(deps-dev): bump @commitlint/config-conventional
dependabot[bot] Nov 1, 2022
7711733
chore(deps-dev): bump @typescript-eslint/parser from 5.41.0 to 5.42.0
dependabot[bot] Nov 1, 2022
39a9d69
chore(deps-dev): bump @typescript-eslint/eslint-plugin
dependabot[bot] Nov 1, 2022
3690d02
chore(gh-pages): remove push trigger to deploy site
ala-n Nov 1, 2022
aa64b59
chore(gh-pages): fix aurora effect for `lg-xl`, `xl` and `xs` breakpo…
Natalie-Smirnova Nov 2, 2022
59480a3
chore(deps-dev): bump stylelint from 14.14.0 to 14.14.1
dependabot[bot] Nov 4, 2022
07fc40a
chore(deps-dev): bump husky from 8.0.1 to 8.0.2
dependabot[bot] Nov 8, 2022
5c6ec49
Merge branch 'epic/share' into feature/esl-share
dshovchko Nov 11, 2022
df36651
feat(esl-share): create share actions registry
dshovchko Nov 11, 2022
9ed21fc
feat(esl-share): create print action
dshovchko Nov 11, 2022
40637cf
feat(esl-share): create copy action
dshovchko Nov 11, 2022
11ee61a
feat(esl-share): create media action
dshovchko Nov 11, 2022
0adad11
refactor(esl-share): rename actions
dshovchko Nov 13, 2022
7a6aa35
style(esl-share): update imports
dshovchko Nov 13, 2022
84ad6f4
refactor(esl-share): delete esl-share-icons
dshovchko Nov 13, 2022
0f33fe1
docs(esl-share): update demo page
dshovchko Nov 13, 2022
dcce8af
refactor(esl-share): remove esl-share-trigger
dshovchko Nov 16, 2022
258b1d3
feat(esl-share): create esl-share-config
dshovchko Nov 16, 2022
79c6ea2
feat(esl-share): create abstract base config provider
dshovchko Nov 16, 2022
aebc38a
feat(esl-share): create fetch config provider
dshovchko Nov 16, 2022
80c890f
refactor(esl-share): update share button
dshovchko Nov 16, 2022
6d3cbd2
feat(esl-share): create esl-share-list
dshovchko Nov 16, 2022
c647d9d
chore(esl-share): update localdev imports
dshovchko Nov 16, 2022
11c2733
refactor(esl-share): update getting buttons config
dshovchko Nov 17, 2022
7628070
docs(esl-share): add share buttons config
dshovchko Nov 17, 2022
ae70066
docs(esl-share): update esl-share demo page
dshovchko Nov 17, 2022
2a73734
refactor(esl-share): create share buttons getter shareData()
dshovchko Nov 17, 2022
9c82115
style(esl-share): update esl-share-list styles
dshovchko Nov 17, 2022
614cb24
docs(esl-share): update config with several social media
dshovchko Nov 22, 2022
d32ad18
Merge remote-tracking branch 'origin/epic/share' into feature/esl-share
dshovchko Nov 30, 2022
f38d402
feat(esl-share): add static register() method to register the action
dshovchko Nov 30, 2022
dbffaf3
feat(esl-share): create URL generic action
dshovchko Dec 1, 2022
c84855a
feat(esl-share): create mail action
dshovchko Dec 1, 2022
a6e5b86
docs(esl-share): update Readme
dshovchko Dec 1, 2022
d519d41
refactor(esl-share): update copy action
dshovchko Dec 1, 2022
9542ffb
Merge branch 'epic/share' of https://github.com/exadel-inc/esl into f…
ala-n Dec 14, 2022
70ec8a6
chore(esl-share): mark esl-share actions as side effects
dshovchko Dec 15, 2022
477b71a
feat(esl-share): add feature to mark button as unavailable depending …
dshovchko Dec 15, 2022
b3861c0
refactor(esl-share): separate a11y init
dshovchko Dec 15, 2022
4c1fe2c
refactor(esl-share): update shareData format for links
dshovchko Dec 15, 2022
2830c46
feat(esl-share): add action for native share mechanism on devices
dshovchko Dec 15, 2022
68abccc
docs(esl-share): update example page
dshovchko Dec 15, 2022
5ef927a
docs(esl-share): update buttons config.json
dshovchko Dec 15, 2022
7c1d8c9
refactor(esl-share): rework share config provider
dshovchko Dec 15, 2022
776db91
refactor(esl-share): update cjnfig provider type
dshovchko Dec 16, 2022
af3dd01
Merge remote-tracking branch 'origin/epic/share' into feature/esl-share
dshovchko Jan 16, 2023
52d4144
refactor(esl-share): remove creating action instance on the fly
dshovchko Jan 16, 2023
2448ac9
refactor(esl-share): rename action share method
dshovchko Jan 16, 2023
ab391fe
style(esl-share): rename mail action to external
dshovchko Jan 16, 2023
cf17913
refactor(esl-share): update a11y
dshovchko Jan 16, 2023
dbcbc3b
Merge remote-tracking branch 'origin/main' into feature/esl-share
dshovchko Jan 23, 2023
57facab
Merge branch 'epic/share' into feature/esl-share
dshovchko Jan 23, 2023
2bd45d6
style(esl-share): apply suggestion from review
dshovchko Jan 23, 2023
c676ece
style(esl-share): update ready$ getter
dshovchko Jan 23, 2023
a31b24e
Merge branch 'feature/esl-share' of github.com:exadel-inc/esl into fe…
dshovchko Jan 23, 2023
76bbf72
refactor(esl-share): update on share ready event
dshovchko Jan 23, 2023
0c70abb
refactor(esl-share): update styles
dshovchko Feb 23, 2023
05c810e
style(esl-share): apply suggestion from review
dshovchko Mar 1, 2023
8e9470c
refactor(esl-share): refactor actions
dshovchko Mar 1, 2023
4a56f94
Merge remote-tracking branch 'origin/epic/share' into feature/esl-share
dshovchko Mar 1, 2023
8679639
style(esl-share): fix linter issue
dshovchko Mar 1, 2023
9655200
refactor(esl-share): update data-share attributes
dshovchko Mar 1, 2023
10698fd
fix(esl-share): fix window.open features
dshovchko Mar 1, 2023
37edb5d
style(esl-share): replace bgcolor static property with @prop
dshovchko Mar 2, 2023
a7f35c2
refactor(esl-share): remove id from share config
dshovchko Mar 2, 2023
ac5f7ed
feat(esl-utils): added URL utility with toAbsoluteUrl method
dshovchko Mar 3, 2023
f649e47
test(esl-utils): url utility tests added
dshovchko Mar 3, 2023
5f9bf92
refactor(esl-share): rewrite share data processing
dshovchko Mar 3, 2023
40b085b
refactor(esl-share): move build method from button to list
dshovchko Mar 3, 2023
c86c426
refactor(esl-share): remove share config class
dshovchko Mar 3, 2023
9c8f763
feat(easl-share): added additional param into config to pass extra da…
dshovchko Mar 3, 2023
ee0e8c5
docs(esl-share): update local-dev page
dshovchko Mar 3, 2023
edb43e3
refactor(esl-share): simplification of titleToShare and urlToShare ge…
dshovchko Mar 5, 2023
e07d543
style(esl-share): apply suggestions from review
dshovchko Mar 6, 2023
7872cf3
Merge remote-tracking branch 'origin/epic/share' into feature/esl-share
dshovchko Mar 6, 2023
a522ba7
docs(esl-share): update esl-share demo page
dshovchko Mar 6, 2023
de671dd
refactor(esl-share): create actionInstance getter
dshovchko Mar 7, 2023
e9a833d
refactor(esl-share): removed befaultBackround from button icon
dshovchko Mar 7, 2023
63e1da4
refactor(esl-share): update share config providers
dshovchko Mar 7, 2023
f9011a6
style(esl-share): change order share button attributes
dshovchko Mar 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
"modules/lib.js",
"src/modules/lib.ts",
"modules/esl-media/providers/**/*.js",
"modules/esl-share/actions/**/*.js",
"src/modules/esl-media/providers/**/*.ts",
"src/modules/esl-share/actions/**/*.ts",
"modules/draft/esl-carousel/core/view/*.js",
"src/modules/draft/esl-carousel/core/view/*.ts",
"polyfills/**/*.js",
Expand Down
12 changes: 12 additions & 0 deletions pages/src/esl-share/esl-share.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
esl-share-list esl-share-button[unavailable] {
display: inline-block;
opacity: .3;
cursor: not-allowed;
filter: grayscale(1);
}

esl-share-button {
path, circle {
fill: #fff;
}
}
1 change: 1 addition & 0 deletions pages/src/localdev.less
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

@import "./collection-grid/collection-grid.less";
@import "./esl-media-demo/test-media.less";
@import "./esl-share/esl-share.less";

@import "../../src/modules/all.less";
@import "../../src/modules/draft/all.less";
Expand Down
11 changes: 11 additions & 0 deletions pages/src/localdev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
ESLFootnotes,
ESLTooltip,
ESLAnimate,
ESLShareList,
ESLShareConfig,
ESLRelatedTarget
} from '../../src/modules/all';

Expand All @@ -41,6 +43,12 @@ import '../../src/modules/esl-media/providers/html5/video-provider';
import '../../src/modules/esl-media/providers/youtube-provider';
import '../../src/modules/esl-media/providers/brightcove-provider';

import '../../src/modules/esl-share/actions/copy-action';
import '../../src/modules/esl-share/actions/external-action';
import '../../src/modules/esl-share/actions/media-action';
import '../../src/modules/esl-share/actions/native-action';
import '../../src/modules/esl-share/actions/print-action';

import {
ESLCarousel,
ESLCarouselPlugins
Expand Down Expand Up @@ -106,5 +114,8 @@ ESLCarouselPlugins.Link.register();
ESLCarouselPlugins.Touch.register();
ESLCarouselPlugins.Autoplay.register();

ESLShareConfig.use(() => fetch('/assets/share/config.json').then((response) => response.json()));
ESLShareList.register();

// Register ESL Mixins
ESLRelatedTarget.register();
10 changes: 10 additions & 0 deletions pages/static/assets/examples/share.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
174 changes: 174 additions & 0 deletions pages/static/assets/share/config.json

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions pages/views/examples/share.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
layout: content
title: Share
name: Share
tags: [examples, beta]
icon: examples/share.svg
aside:
components:
- esl-share
---
{% import 'lorem.njk' as lorem %}

<section>
<h2>Share example</h2>

<h3>Just a standalone share button</h3>
<esl-share-button action="media" link="//www.linkedin.com/sharing/share-offsite/?url={u}" name="linkedin" tabindex="0" role="button" title="LinkedIn">
<span title="Linkedin" class="esl-share-icon" style="background-color:#0b77b3;">
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" role="presentation" viewBox="0 0 27.99 27.99"><path d="M6.37 11.33h3.25v10.45H6.37zM8 6.13A1.88 1.88 0 116.12 8 1.88 1.88 0 018 6.13M11.65 11.33h3.12v1.43h.05a3.4 3.4 0 013.07-1.69c3.29 0 3.9 2.17 3.9 5v5.73h-3.25v-5.11c0-1.21 0-2.77-1.69-2.77s-1.94 1.32-1.94 2.69v5.17h-3.25V11.33z"></path></svg>
</span>
</esl-share-button>
<hr>

<h3>Display list of share buttons of group 'demo'</h3>
<p>Shows buttons from a specified group.</p>
<esl-share-list group="demo"></esl-share-list>
<hr>

<h3>Display list of share buttons of group 'alternative'</h3>
<p>Shows buttons from a specified group.</p>
<esl-share-list group="alternative"></esl-share-list>
<hr>

<h3>Display list of share buttons on nonexistent group</h3>
<p>Shows buttons from a specified group. Displays all buttons from config when a nonexistent group is specified.</p>
<esl-share-list group="foo"></esl-share-list>
<hr>

<h3>Display list of share buttons via list of buttons id</h3>
<p>Shows specified buttons. Displays nothing in the case when specified wrong button id.</p>
<esl-share-list list="kakao,pusha,alladin,mix,myspace"></esl-share-list>
<hr>

<h3>List of share buttons which presents buttons with all action types</h3>
<p>This example shows a button with the native share mechanism on the device which will be inactive on the desktop browser.</p>
<esl-share-list list="copy,linkedin,mail,native,print"></esl-share-list>
<hr>

<h3>Display list of share buttons via incorrect list</h3>
<p>Shows buttons only with the correct id.</p>
<esl-share-list list="twittor , copi"></esl-share-list>
dshovchko marked this conversation as resolved.
Show resolved Hide resolved
<hr>

<h3>Display list of share buttons (without group or list)</h3>
<p>Shows all buttons from config.</p>
<esl-share-list data-share-url="https://esl-ui.com/" data-share-title="Exadel Smart Library"></esl-share-list>
<hr>

<h3>Trigger icon with share popup</h3>
<p>Displays trigger icon. Hovering or clicking on the icon shows a popup with the list of share icons.</p>
<esl-trigger target="#demo-share-popup" mode="toggle" track-click track-hover style="display: inline-block; width: 40px; height: 40px;">
<svg viewBox="0 0 483 483" fill="none" xmlns="http://www.w3.org/2000/svg">
<g fill="#add1fa">
<path d="M395.72,0c-48.204,0-87.281,39.078-87.281,87.281c0,2.036,0.164,4.03,0.309,6.029l-161.233,75.674 c-15.668-14.971-36.852-24.215-60.231-24.215c-48.204,0.001-87.282,39.079-87.282,87.282c0,48.204,39.078,87.281,87.281,87.281 c15.206,0,29.501-3.907,41.948-10.741l69.789,58.806c-3.056,8.896-4.789,18.396-4.789,28.322c0,48.204,39.078,87.281,87.281,87.281 c48.205,0,87.281-39.078,87.281-87.281s-39.077-87.281-87.281-87.281c-15.205,0-29.5,3.908-41.949,10.74l-69.788-58.805 c3.057-8.891,4.789-18.396,4.789-28.322c0-2.035-0.164-4.024-0.308-6.029l161.232-75.674c15.668,14.971,36.852,24.215,60.23,24.215 c48.203,0,87.281-39.078,87.281-87.281C482.999,39.079,443.923,0,395.72,0z"/>
</g>
</svg>
</esl-trigger>
<esl-popup id="demo-share-popup" position="top" default-params="{hideDelay: 500}" close-on-esc close-on-outside-action>
<esl-share-list group="alternative" style="margin: 10px;"></esl-share-list><span class="esl-popup-arrow"></span>
</esl-popup>
</section>
2 changes: 2 additions & 0 deletions src/modules/all.less
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@
@import "./esl-tooltip/core.less";

@import "./esl-animate/core.less";

@import "./esl-share/core.less";
3 changes: 3 additions & 0 deletions src/modules/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ export * from './esl-animate/core';

// Related Target Mixin
export * from './esl-related-target/core';

// Share
export * from './esl-share/core';
15 changes: 15 additions & 0 deletions src/modules/esl-share/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# [ESL](../../../) Share

Version: *1.0.0-beta*.

Authors: *Dmytro Shovchko*.

***Important Notice: the component is under beta version, it is tested and ready to use but be aware of its potential critical API changes.***

<a name="intro"></a>

The ESL Share component allows the user to share the page on social media platforms.

**ESLShareButton** is a custom element that is used to show the "Share on social media" button.

**ESLShareList** is a custom element that is used to show the list of social media buttons.
38 changes: 38 additions & 0 deletions src/modules/esl-share/actions/copy-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {ESLShareBaseAction} from '../core/esl-share-action';
import {ESLEventUtils} from '../../esl-utils/dom/events';

import type {ESLShareButton} from '../core/esl-share-button';
import type {AlertActionParams} from '../../esl-alert/core';

@ESLShareBaseAction.register
export class ESLShareCopyAction extends ESLShareBaseAction {
public static override readonly is: string = 'copy';

public override get isAvailable(): boolean {
return navigator.clipboard !== undefined;
}

protected get alertText(): string {
return 'Copied to clipboard';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cosmetic: we need to think about more accessible or prepared value by default.
It is strange if we give an action that the user needs to overwrite anyway (as it is not internalized|prepared|etc.) if we are talking about prod usage.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed (02.03)

Alert config moved as additionalParams to the action configuration
Passs this param to the button as an additionalParams field (@prop / @jsonParam)

}

protected get alertParams(): AlertActionParams {
return {
cls: 'esl-share-alert',
html: `<span aria-label="${this.alertText}">${this.alertText}</span>`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need an aria-label? span is a block that's a11y representation is equal to the content by default

};
}

public share(shareData: ShareData, $button: ESLShareButton): void {
const {url} = shareData;
if (!this.isAvailable || !url) return;

navigator.clipboard.writeText(url);
this.showCopyAlert();
}

protected showCopyAlert(): void {
const detail = this.alertParams;
ESLEventUtils.dispatch(document.body, 'esl:alert:show', {detail});
}
}
17 changes: 17 additions & 0 deletions src/modules/esl-share/actions/external-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {ESLShareUrlGenericAction} from './url-generic-action';

import type {ESLShareButton} from '../core/esl-share-button';

@ESLShareUrlGenericAction.register
export class ESLShareExternalAction extends ESLShareUrlGenericAction {
public static override readonly is: string = 'external';

public share(shareData: ShareData, $button: ESLShareButton): void {
const {link} = $button;
if (!link) return;

const a = document.createElement('a');
a.href = this.buildURL(link, shareData);
a.click();
}
}
32 changes: 32 additions & 0 deletions src/modules/esl-share/actions/media-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {ESLShareUrlGenericAction} from './url-generic-action';

import type {ESLShareButton} from '../core/esl-share-button';

@ESLShareUrlGenericAction.register
export class ESLShareMediaAction extends ESLShareUrlGenericAction {
public static override readonly is: string = 'media';

public static FEATURES: Record<string, number> = {
scrollbars: 0,
resizable: 1,
menubar: 0,
left: 100,
top: 100,
width: 750,
height: 500,
toolbar: 0,
status: 0
};

protected get windowFeatures(): string {
const features = (this.constructor as typeof ESLShareMediaAction).FEATURES;
return Object.entries(features).map(([key, value]) => `${key}=${value}`).join(',');
}

public share(shareData: ShareData, $button: ESLShareButton): void {
const {link} = $button;
if (!link) return;

window.open(this.buildURL(link, shareData), '_blank', this.windowFeatures);
}
}
18 changes: 18 additions & 0 deletions src/modules/esl-share/actions/native-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {ESLShareBaseAction} from '../core/esl-share-action';

import type {ESLShareButton} from '../core/esl-share-button';

@ESLShareBaseAction.register
export class ESLShareNativeAction extends ESLShareBaseAction {
public static override readonly is: string = 'native';

public override get isAvailable(): boolean {
return navigator.share !== undefined;
}

public share(shareData: ShareData, $button: ESLShareButton): void {
if (!this.isAvailable) return;

navigator.share(shareData);
}
}
12 changes: 12 additions & 0 deletions src/modules/esl-share/actions/print-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {ESLShareBaseAction} from '../core/esl-share-action';

import type {ESLShareButton} from '../core/esl-share-button';

@ESLShareBaseAction.register
export class ESLSharePrintAction extends ESLShareBaseAction {
public static override readonly is: string = 'print';

public share(shareData: ShareData, $button: ESLShareButton): void {
window.print();
}
}
20 changes: 20 additions & 0 deletions src/modules/esl-share/actions/url-generic-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {ESLShareBaseAction} from '../core/esl-share-action';
import {format} from '../../esl-utils/misc/format';

export abstract class ESLShareUrlGenericAction extends ESLShareBaseAction {

protected getFormatSource(shareData: ShareData): Record<string, string> {
const title = encodeURIComponent(shareData.title || '');
const url = encodeURIComponent(shareData.url || '');
return {
u: url,
t: title,
url,
title
};
}

protected buildURL(link: string, shareData: ShareData): string {
return format(link, this.getFormatSource(shareData));
}
}
2 changes: 2 additions & 0 deletions src/modules/esl-share/core.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "./core/esl-share-button.less";
@import "./core/esl-share-list.less";
5 changes: 5 additions & 0 deletions src/modules/esl-share/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './core/esl-share-list';
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';
36 changes: 36 additions & 0 deletions src/modules/esl-share/core/esl-share-action-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {memoize} from '../../esl-utils/decorators';

import type {ActionType, ESLShareBaseAction} from './esl-share-action';
import type {ESLShareButton} from './esl-share-button';

export class ESLShareActionRegistry {
private actionsMap: Map<string, ESLShareBaseAction> = new Map();

@memoize()
public static get instance(): ESLShareActionRegistry {
return new ESLShareActionRegistry();
}

/** Register action */
public register(action: ActionType): void {
if (!action.is) throw new Error('Action should have a name');
this.actionsMap.set(action.is, new action());
}

/** Checks if action is registered for passed name */
public has(name: string): boolean {
return this.actionsMap.has(name);
}

/** Get action by name */
public get(name: string): ESLShareBaseAction | null {
if (!name) return null;
return this.actionsMap.get(name.toLowerCase()) || null;
}

/** Do the share action at passed Share button */
public share(button: ESLShareButton): void {
const action = this.get(button.action);
action && action.share(button.shareData, button);
}
}
25 changes: 25 additions & 0 deletions src/modules/esl-share/core/esl-share-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {ESLShareActionRegistry} from './esl-share-action-registry';

import type {ESLShareButton} from './esl-share-button';

export type ActionType = (new() => ESLShareBaseAction) & typeof ESLShareBaseAction;

export abstract class ESLShareBaseAction {
public static readonly is: string;

/** Register this action. Can be used as a decorator */
public static register(this: ActionType): void;
public static register(this: unknown, action?: ActionType): void;
public static register(this: any, action?: ActionType): void {
action = action || this;
if (action === ESLShareBaseAction) throw new Error('`ESLShareBaseAction` can\'t be registered.');
if (!(action?.prototype instanceof ESLShareBaseAction)) throw new Error('Action should be instanceof `ESLShareBaseAction`');
ESLShareActionRegistry.instance.register(action);
}

public get isAvailable(): boolean {
return true;
}

public abstract share(shareData: ShareData, $button: ESLShareButton): void;
}
Loading