@freshworks/crayons
Version:
Crayons Web Components library
353 lines (352 loc) • 9.99 kB
JavaScript
import { Build, Component, Element, Prop, State, h, Watch, } from '@stencil/core';
import { fetchIcon, waitUntilVisible } from './icon.utils';
import { getIconLibrary, watchIcon, unwatchIcon, getSVGElement, } from './library.icon.utils';
export class Icon {
constructor() {
/**
* Identifier of the icon. The attribute’s value must be a valid JS Import Name of the svg in the named export from @freshworks/crayons-icon.
*/
this.dataSvg = '';
/**
* Root Margin in px or percentage for Intersection-Observer. This means from ref to bottom of loaded view , the item loads when it crosses above the negative y margin.
*/
this.xRootMargin = '50px';
/**
* Color in which the icon is displayed, specified as a standard CSS color or as a HEX code.
*/
this.color = '';
/**
* Name of External Library to be used
*/
this.library = 'crayons';
/**
* Enable Intersection Observer. Default is false.
*/
this.lazy = false;
this.setElVisible = false;
this.visible = false;
}
async componentWillLoad() {
if (!this.lazy)
this.visible = true;
else
this.visible = this.setElVisible;
if (!Build.isBrowser || !this.visible) {
return;
}
this.applyIconPropstoState();
}
connectedCallback() {
watchIcon(this);
this.lazy &&
waitUntilVisible(this.intersectionObserver, this.xRootMargin, this.el, () => {
this.setElVisible = true;
this.applyIconPropstoState();
});
}
nameChangeHandler() {
this.applyIconPropstoState();
}
disconnectedCallback() {
unwatchIcon(this);
if (this.intersectionObserver) {
this.intersectionObserver.disconnect();
this.intersectionObserver = undefined;
}
}
async applyIconPropstoState() {
const { name, dataSvg, library } = this;
try {
if (!name && dataSvg) {
this.svg = dataSvg;
}
else if (name) {
const url = this.getIconUrl(name, library);
this.svg = await this.drawIcon(url);
}
else {
console.error("Please provide valid props either 'name' or 'data-svg'.Check the usage docs.");
throw '-invalid props-';
}
}
catch (e) {
console.error(e.message);
this.loadFallbackImage();
}
}
async drawIcon(url) {
const { name, library } = this;
try {
const svgEl = await getSVGElement(url);
this.applySVGMutation(library, name, svgEl);
return svgEl.outerHTML;
}
catch (ex) {
throw new Error(`Exception occured while drawing Icon- ${name} : ${ex.message}`);
}
}
/** Fetches the icon and redraws it. Used to handle library registrations. */
redrawIcon() {
this.applyIconPropstoState();
}
async loadFallbackImage() {
this.svg = await fetchIcon(this.getIconUrlfromlib('image', 'system'));
}
getIconUrl(icon, lib) {
let url = '';
if (!this.src) {
url = this.getIconUrlfromlib(icon, lib);
if (url === undefined) {
console.error(`Error while resolving url for ${this.name}|${this.library}. Please check the lib registration/resolver function.`);
return;
}
}
else
url = `${this.src}/${this.name}.svg`;
return url;
}
getIconUrlfromlib(icon, lib) {
const library = getIconLibrary(lib);
if (icon && library) {
return library.resolver(icon);
}
else {
console.error(`Icon ${icon}/${lib} not registered.Check the Implementation.`);
return;
}
}
applySVGMutation(library, icon, svgEl) {
const iconlibrary = getIconLibrary(library);
if (iconlibrary && iconlibrary.mutator) {
iconlibrary.mutator(svgEl, icon);
}
}
render() {
const style = {};
const accessibilityProps = { 'aria-hidden': true };
const hasLabel = typeof this.label === 'string' && this.label.length > 0;
if (hasLabel) {
accessibilityProps['role'] = 'img';
accessibilityProps['aria-label'] = this.label;
}
if (this.size !== undefined)
style['--fw-icon-size'] = `${this.size}px`;
if (this.color !== undefined)
style['--fw-icon-color'] = this.color;
return (h("div", Object.assign({ class: 'icon' }, accessibilityProps, { style: Object.assign({ height: ` ${this.height}px`, width: `${this.width}px` }, style), innerHTML: this.svg })));
}
static get is() { return "fw-icon"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() { return {
"$": ["icon.scss"]
}; }
static get styleUrls() { return {
"$": ["icon.css"]
}; }
static get assetsDirs() { return ["icon-assets"]; }
static get properties() { return {
"name": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Identifier of the icon. The attribute\u2019s value must be a valid svg Name in the Crayons-Icon set."
},
"attribute": "name",
"reflect": true
},
"label": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "An alternate description to use for accessibility. If omitted, the icon will be ignored by assistive devices."
},
"attribute": "label",
"reflect": false
},
"dataSvg": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Identifier of the icon. The attribute\u2019s value must be a valid JS Import Name of the svg in the named export from @freshworks/crayons-icon."
},
"attribute": "data-svg",
"reflect": false,
"defaultValue": "''"
},
"src": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Identifier of the icon. The attribute\u2019s value must be a valid path to svg file."
},
"attribute": "src",
"reflect": false
},
"size": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Size of the icon, specified in number of pixels. This will be square coordinates of (w X h) = size X size"
},
"attribute": "size",
"reflect": false
},
"xRootMargin": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Root Margin in px or percentage for Intersection-Observer. This means from ref to bottom of loaded view , the item loads when it crosses above the negative y margin."
},
"attribute": "x-root-margin",
"reflect": false,
"defaultValue": "'50px'"
},
"width": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Width of the icon, specified in number of pixels."
},
"attribute": "width",
"reflect": false
},
"height": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Height of the icon, specified in number of pixels."
},
"attribute": "height",
"reflect": false
},
"color": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Color in which the icon is displayed, specified as a standard CSS color or as a HEX code."
},
"attribute": "color",
"reflect": false,
"defaultValue": "''"
},
"library": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Name of External Library to be used"
},
"attribute": "library",
"reflect": false,
"defaultValue": "'crayons'"
},
"lazy": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Enable Intersection Observer. Default is false."
},
"attribute": "lazy",
"reflect": false,
"defaultValue": "false"
}
}; }
static get states() { return {
"setElVisible": {},
"visible": {},
"intersectionObserver": {},
"svg": {}
}; }
static get elementRef() { return "el"; }
static get watchers() { return [{
"propName": "name",
"methodName": "nameChangeHandler"
}]; }
}