Skip to content

Commit

Permalink
feat(alwatr-icon): icon component
Browse files Browse the repository at this point in the history
  • Loading branch information
MM25Zamanian committed Nov 2, 2022
1 parent 2fe8c12 commit 4a24cdc
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 16 deletions.
21 changes: 20 additions & 1 deletion demo/icon/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,29 @@
html {
color-scheme: light dark;
}
alwatr-icon:nth-child(1) {
font-size: 1em;
}
alwatr-icon:nth-child(2) {
font-size: 2em;
}
alwatr-icon:nth-child(3) {
font-size: 4em;
}
alwatr-icon:nth-child(4) {
font-size: 8em;
}
alwatr-icon:nth-child(5) {
font-size: 16em;
}
</style>
</head>

<body>
<alwatr-icon></alwatr-icon>
<alwatr-icon name="chatbubbles-outline"></alwatr-icon>
<alwatr-icon name="chatbubbles-outline"></alwatr-icon>
<alwatr-icon name="chatbubbles-outline"></alwatr-icon>
<alwatr-icon name="chatbubbles-outline"></alwatr-icon>
<alwatr-icon name="chatbubbles-outline"></alwatr-icon>
</body>
</html>
12 changes: 12 additions & 0 deletions demo/icon/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
import '@alwatr/icon';

// function createIcon(name: string): void {
// const iconElement = document.createElement('alwatr-icon');
// iconElement.name = name;
// document.body.appendChild(iconElement);

// setTimeout(() => {
// createIcon(name);
// }, 1000);
// }

// createIcon('chatbubbles-outline');
63 changes: 48 additions & 15 deletions packages/ui/icon/src/icon.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import {AlwatrElement} from '@alwatr/element';
import {html, css} from 'lit';
import {fetch} from '@alwatr/fetch';
import {svg, css, PropertyDeclaration, nothing} from 'lit';
import {customElement} from 'lit/decorators/custom-element.js';
import {property} from 'lit/decorators/property.js';
import {state} from 'lit/decorators/state.js';
import {unsafeSVG} from 'lit/directives/unsafe-svg.js';

import type {TemplateResult} from 'lit';

declare global {
interface HTMLElementTagNameMap {
'alwatr-icon': AlwatrIcon;
}
}

const requests: Record<string, Promise<Response>> = {};

@customElement('alwatr-icon')
export class AlwatrIcon extends AlwatrElement {
static override styles = [
Expand All @@ -17,6 +28,9 @@ export class AlwatrIcon extends AlwatrElement {
fill: currentColor;
box-sizing: content-box !important;
}
:host(.rtl) {
transform: scaleX(-1);
}
svg {
display: block;
Expand All @@ -27,19 +41,38 @@ export class AlwatrIcon extends AlwatrElement {
];

@property() name?: string;
@property({attribute: 'url-prefix'}) urlPrefix = 'https://cdn.jsdelivr.net/gh/ionic-team/ionicons@6.0.3/src/svg/';

override render(): TemplateResult {
return html`<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
<title>Book</title>
<path
d="M256 160c16-63.16 76.43-95.41 208-96a15.94 15.94 0 0116 16v288a16 16 0 01-16 16c-128 0-177.45 25.81-208 64-30.37-38-80-64-208-64-9.88 0-16-8.05-16-17.93V80a15.94 15.94 0 0116-16c131.57.59 192 32.84 208 96zM256 160v288"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="32"
/>
</svg>`;
@property({attribute: 'url-prefix'}) urlPrefix = 'https://cdn.jsdelivr.net/npm/ionicons@5/dist/svg/';
@property({attribute: 'flip-rtl', type: Boolean}) flipRtl = false;

@state() protected _svgContent: TemplateResult | typeof nothing = nothing;

override render(): TemplateResult | typeof nothing {
return this._svgContent;
}
override requestUpdate(
name?: PropertyKey,
oldValue?: unknown,
options?: PropertyDeclaration<unknown, unknown>,
): void {
super.requestUpdate(name, oldValue, options);

if ((name === 'name' || name === 'urlPrefix') && this.name !== undefined && this.urlPrefix !== undefined) {
this._getIcon(this.name, this.urlPrefix).then((iconSvg) => (this._svgContent = svg`${unsafeSVG(iconSvg)}`));
}
else if (name === 'flipRtl') {
this.classList[this.flipRtl ? 'add' : 'remove']('rtl');
}
}

protected async _getIcon(name: string, urlPrefix: string): Promise<string> {
const url = urlPrefix + name + '.svg';
let request = requests[url];

if (request == null) {
request = fetch({url, cacheStorageName: 'alwatr-icon', cacheStrategy: 'cache_first'});
requests[url] = request;
}

return request.then((response) => response.clone().text());
}
}

0 comments on commit 4a24cdc

Please sign in to comment.