@alyle/ui
Version:
Minimal Design, a set of components for Angular
332 lines (326 loc) • 12.9 kB
JavaScript
import * as i0 from '@angular/core';
import { SecurityContext, Optional, Inject, Injectable, Input, Directive, NgModule } from '@angular/core';
import * as i2$1 from '@alyle/ui';
import { keyframesUniqueId, mixinStyleUpdater, mixinBg, mixinColor, mixinRaised, mixinOutlined, mixinElevation, mixinShadowColor, StyleRenderer, LyCommonModule } from '@alyle/ui';
import { share, map, take } from 'rxjs/operators';
import { DOCUMENT } from '@angular/common';
import * as i1 from '@angular/common/http';
import * as i2 from '@angular/platform-browser';
import * as i3 from '@angular/cdk/platform';
const STYLE_PRIORITY$1 = -2;
/** The following styles will never be updated */
const styles = {
svg: {
width: 'inherit',
height: 'inherit',
fill: 'currentColor',
}
};
class LyIconService {
get defaultClass() {
return this._defaultClass;
}
get defaultClassPrefix() {
return this._defaultClassPrefix;
}
constructor(http, _sanitizer, _document, theme) {
this.http = http;
this._sanitizer = _sanitizer;
this._document = _document;
this.theme = theme;
this._defaultClass = 'material-icons';
this.svgMap = new Map();
this._fontClasses = new Map();
/**
* Styles
* @docs-private
*/
this.classes = this.theme.addStyleSheet(styles, STYLE_PRIORITY$1);
this.defaultSvgIcon = '<svg viewBox="0 0 20 20"><circle cx="10" cy="10" r="10"></circle></svg>';
}
setSvg(key, url) {
if (!this.svgMap.has(key)) {
const urlSanitized = this._sanitizer.sanitize(SecurityContext.RESOURCE_URL, url);
const svgIcon = {
obs: this.http.get(`${urlSanitized}.svg`, { responseType: 'text' })
.pipe(share(), map(svgText => {
if (svgIcon.svg) {
return svgIcon.svg;
}
const svg = this._textToSvg(svgText);
this._cacheSvgIcon(svg, key);
return svg;
}))
};
this.svgMap.set(key, svgIcon);
}
}
addSvgIconLiteral(key, literal) {
if (!this.svgMap.has(key)) {
const sanitizedLiteral = this._sanitizer.sanitize(SecurityContext.HTML, literal);
if (!sanitizedLiteral) {
throw new Error(`LyIconService: Failed sanitize '${key}'`);
}
const svg = this._textToSvg(sanitizedLiteral);
this.svgMap.set(key, {
svg
});
}
}
/** String to SVG */
_textToSvg(str) {
const div = this._document.createElement('DIV');
div.innerHTML = str;
const svg = div.querySelector('svg');
return svg;
}
_cacheSvgIcon(svg, key) {
const svgIconInfo = this.svgMap.get(key);
if (!svgIconInfo.svg) {
this.svgMap.get(key).svg = svg;
}
}
getSvg(key) {
if (!this.svgMap.has(key)) {
throw new Error(`LyIconService: Icon ${key} not found`);
}
return this.svgMap.get(key);
}
/**
* Set default className for `ly-icon`
* @param className class name
* @param prefix Class prefix,
* For example if you use FontAwesome your prefix would be `fa-`,
* then in the template it is no longer necessary to use the prefix
* Example: `<ly-icon fontIcon="alarm">`
*/
setDefaultClass(className, prefix) {
this._defaultClass = className;
this._defaultClassPrefix = prefix;
}
/**
* Register new font class alias
* demo:
* For FontAwesome
* registerFontClass({
* key: 'fa',
* class: 'fa'
* prefix: 'fa-'
* })
*/
registerFontClass(opt) {
this._fontClasses.set(opt.key, opt);
}
getFontClass(key) {
return this._fontClasses.get(key);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIconService, deps: [{ token: i1.HttpClient }, { token: i2.DomSanitizer }, { token: DOCUMENT, optional: true }, { token: i2$1.LyTheme2 }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIconService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIconService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.DomSanitizer }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [DOCUMENT]
}] }, { type: i2$1.LyTheme2 }] });
const STYLE_PRIORITY = -2;
const STYLES = (theme) => {
const loading = keyframesUniqueId.next();
const { primary, secondary, tertiary } = theme.background;
const lum = primary.default.luminance();
let one = (lum < .5
? tertiary
: secondary);
let two = (lum < .5
? secondary
: tertiary);
one = one.darken(.25 * (lum < .5 ? -1 : 1.1));
two = two.darken(.25 * (lum < .5 ? -1 : 1.1));
return {
$priority: STYLE_PRIORITY,
$global: (_className) => ` ${loading}{0%{background-position:200% 50%;}100%{background-position:-200% 50%;}}`,
root: () => (_className) => `${_className}{font-size:${theme.icon.fontSize};width:1em;position:relative;height:1em;display:inline-flex;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}`,
loading: (_className) => `${_className}{background:${`linear-gradient(270deg, ${one}, ${two}, ${two}, ${one})`};background-size:400% 400%;animation:${loading} 8s ease-in-out infinite;}`,
defaultIcon: (_className) => `${_className}{border-radius:50px;}`
};
};
/** @docs-private */
class LyIconBase {
constructor(_theme) {
this._theme = _theme;
}
}
/** @docs-private */
const LyIconMixinBase = mixinStyleUpdater(mixinBg(mixinColor(mixinRaised(mixinOutlined(mixinElevation(mixinShadowColor(LyIconBase)))))));
class LyIcon extends LyIconMixinBase {
get icon() {
return this._icon;
}
set icon(val) {
this._icon = val;
this._addDefaultIcon();
if (this._platform.isBrowser) {
this._prepareSvgIcon(this.iconService.getSvg(val));
}
}
get fontSet() {
return this._fontSet;
}
set fontSet(key) {
this._fontSet = key;
}
get fontIcon() {
return this._fontIcon;
}
set fontIcon(key) {
this._fontIcon = key;
}
/** @docs-private */
get hostElement() {
return this._el.nativeElement;
}
constructor(iconService, _el, _renderer, theme, sRenderer, _platform) {
super(theme);
this.iconService = iconService;
this._el = _el;
this._renderer = _renderer;
this.sRenderer = sRenderer;
this._platform = _platform;
this.classes = this.sRenderer.renderSheet(STYLES, true);
this.setAutoContrast();
}
ngOnChanges() {
if (this.fontSet || this.fontIcon) {
this._updateFontClass();
}
this.updateStyle(this._el);
}
_isDefault() {
return !(this.icon || this.fontSet);
}
_prepareSvgIcon(svgIcon) {
if (svgIcon.svg) {
this._appendChild(svgIcon.svg.cloneNode(true));
}
else {
svgIcon.obs
.pipe(take(1))
.subscribe((svgElement) => {
this._appendChild(svgElement.cloneNode(true));
});
}
}
_appendChild(svg) {
this._cleanIcon();
this._iconElement = svg;
this._renderer.addClass(svg, this.iconService.classes.svg);
this._renderer.appendChild(this._el.nativeElement, svg);
}
_addDefaultIcon() {
this.sRenderer.addClass(this.classes.defaultIcon);
this.sRenderer.addClass(this.classes.loading);
}
// private _appendDefaultSvgIcon() {
// const svgIcon = this.iconService._textToSvg(this.iconService.defaultSvgIcon) as SVGAElement;
// svgIcon.classList.add(this.classes.loading);
// this._appendChild(svgIcon);
// }
_updateClass() {
if (this._isDefault() && this.iconService.defaultClass) {
this._renderer.addClass(this._el.nativeElement, this.iconService.defaultClass);
}
}
ngOnInit() {
this._updateClass();
}
ngOnDestroy() {
this._cleanIcon();
}
/**
* run only browser
* remove current icon
*/
_cleanIcon() {
const icon = this._iconElement;
this.sRenderer.removeClass(this.classes.defaultIcon);
this.sRenderer.removeClass(this.classes.loading);
if (icon) {
this._renderer.removeChild(this._el.nativeElement, icon);
this._iconElement = undefined;
}
}
_updateFontClass() {
const currentClass = this._currentClass;
const fontSetKey = this.fontSet;
const icon = this.fontIcon;
const el = this._el.nativeElement;
const iconClass = this.iconService.getFontClass(fontSetKey);
if (currentClass) {
this._renderer.removeClass(el, currentClass);
}
if (this._previousFontSet) {
if (this._previousFontSet.class) {
this._renderer.removeClass(el, this._previousFontSet.class);
}
}
if (iconClass) {
this._previousFontSet = iconClass;
}
else {
throw new Error(`Icon with key${fontSetKey} not found`);
}
this._currentClass = `${iconClass.prefix}${icon}`;
this._renderer.addClass(el, this._currentClass);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIcon, deps: [{ token: LyIconService }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i2$1.LyTheme2 }, { token: i2$1.StyleRenderer }, { token: i3.Platform }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.10", type: LyIcon, isStandalone: false, selector: "ly-icon", inputs: { bg: "bg", color: "color", raised: "raised", outlined: "outlined", elevation: "elevation", shadowColor: "shadowColor", icon: "icon", fontSet: "fontSet", fontIcon: "fontIcon" }, providers: [
StyleRenderer
], exportAs: ["lyIcon"], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIcon, decorators: [{
type: Directive,
args: [{
selector: 'ly-icon',
inputs: [
'bg',
'color',
'raised',
'outlined',
'elevation',
'shadowColor',
],
exportAs: 'lyIcon',
providers: [
StyleRenderer
],
standalone: false
}]
}], ctorParameters: () => [{ type: LyIconService }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i2$1.LyTheme2 }, { type: i2$1.StyleRenderer }, { type: i3.Platform }], propDecorators: { icon: [{
type: Input
}], fontSet: [{
type: Input
}], fontIcon: [{
type: Input
}] } });
class LyIconModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIconModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.10", ngImport: i0, type: LyIconModule, declarations: [LyIcon], exports: [LyIcon, LyCommonModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIconModule, imports: [LyCommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: LyIconModule, decorators: [{
type: NgModule,
args: [{
declarations: [LyIcon],
exports: [LyIcon, LyCommonModule]
}]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { LyIcon, LyIconBase, LyIconMixinBase, LyIconModule, LyIconService, STYLES };
//# sourceMappingURL=alyle-ui-icon.mjs.map