@limetech/lime-elements
Version:
204 lines (197 loc) • 6.64 kB
JavaScript
import { r as registerInstance, h, g as getElement } from './index-2714248e.js';
import { g as globalConfig } from './config-656a588f.js';
class CacheStorageIconCache {
constructor(cache) {
this.promises = {};
this.cache = cache;
}
/**
* Get icon data from the cache
*
* @param name - Name of the icon
* @param path - Path on the server where the assets are located
* @returns SVG markup
*/
async get(name, path = '') {
const cache = await this.cache;
const url = this.getUrl(name, path);
let response = await cache.match(url);
if (!response) {
response = await this.fetchData(url, cache);
}
return this.getIcon(response);
}
async fetchData(url, cache) {
let requestPromise = this.promises[url];
if (requestPromise === undefined) {
requestPromise = cache.add(url);
this.promises[url] = requestPromise;
}
await requestPromise;
return cache.match(url);
}
/*
* Get icon data from a response
*/
async getIcon(response) {
let svgData = await response.text();
// Some of the icons in the Icons8 library have hard coded black color on some of the paths.
// In order to apply coloring with CSS, these have to be set to 'currentColor'
svgData = svgData.replaceAll('#000000', 'currentColor');
if (!this.validSvg(svgData)) {
throw new Error('Invalid SVG');
}
return svgData;
}
/*
* Check if the given data is a valid SVG document
*/
validSvg(data) {
const parser = new DOMParser();
const svgDoc = parser.parseFromString(data, 'image/svg+xml');
return svgDoc.documentElement.tagName.toLowerCase() === 'svg';
}
getUrl(name, path) {
let iconPath = path || '';
if (path && !path.endsWith('/')) {
iconPath = `${path}/`;
}
return `${iconPath}assets/icons/${name}.svg`;
}
}
class InMemoryIconCache {
constructor() {
/*
* Cache of all loaded SVGs
*/
this.cache = {};
/*
* Contains resolve functions for all unresolved promises that are waiting for SVG data.
*/
this.resolveFunctions = {};
}
/**
* Get icon data from the cache
*
* @param name - Name of the icon
* @param path - Path on the server where the assets are located
* @returns SVG markup
*/
async get(name, path = '') {
if (!this.cache[name]) {
this.cache[name] = await this.getIcon(name, path);
}
return this.cache[name];
}
/*
* Creates and returns a promise that will be resolved when SVG data is available
*/
getIcon(name, path) {
return new Promise((resolve) => {
if (!this.resolveFunctions[name]) {
this.resolveFunctions[name] = [];
this.fetchData(name, path);
}
this.resolveFunctions[name].push(resolve);
});
}
/*
* Fetch SVG data from the server
*/
async fetchData(name, path) {
let iconPath = path || '';
if (path && !path.endsWith('/')) {
iconPath = `${path}/`;
}
const response = await fetch(`${iconPath}assets/icons/${name}.svg`);
let svgData = await response.text();
// Some of the icons in the Icons8 library have hard coded black color on some of the paths.
// In order to apply coloring with CSS, these have to be set to 'currentColor'
svgData = svgData.replaceAll('#000000', 'currentColor');
if (!this.validSvg(svgData)) {
throw new Error('Invalid SVG');
}
this.resolvePromises(name, svgData);
}
/*
* Check if the given data is a valid SVG document
*/
validSvg(data) {
const parser = new DOMParser();
const svgDoc = parser.parseFromString(data, 'image/svg+xml');
return svgDoc.documentElement.tagName.toLowerCase() === 'svg';
}
/*
* Resolve all promises waiting for data for a specific icon
*/
resolvePromises(name, svgData) {
const resolves = this.resolveFunctions[name];
for (const resolve of resolves) {
resolve(svgData);
}
this.resolveFunctions[name] = null;
}
}
const CACHE_NAME = '@limetech/lime-elements/icons';
function createIconCache() {
try {
const cache = caches.open(CACHE_NAME);
return new CacheStorageIconCache(cache);
}
catch (_a) {
return new InMemoryIconCache();
}
}
const iconCache = (() => {
return createIconCache();
})();
const iconCss = ":host{background-color:var(--icon-background-color, transparent);border-radius:50%;display:inline-block;line-height:0;box-sizing:border-box}:host svg{fill:currentColor;height:100%;pointer-events:none;width:100%}:host div{margin:var(--limel-icon-svg-margin, 0)}:host([hidden]){display:none}:host([size=x-small]){height:1rem !important;width:1rem !important}:host([size=small]){height:1.25rem !important;width:1.25rem !important}:host([size=medium]){height:1.5rem !important;width:1.5rem !important}:host([size=large]){height:1.75rem !important;width:1.75rem !important}:host([badge][size=x-small]){height:1.5rem !important;width:1.5rem !important;--limel-icon-svg-margin:0.25rem}:host([badge][size=small]){height:1.75rem !important;width:1.75rem !important;--limel-icon-svg-margin:0.25rem}:host([badge][size=medium]){height:2.5rem !important;width:2.5rem !important;--limel-icon-svg-margin:0.5rem}:host([badge][size=large]){height:2.75rem !important;width:2.75rem !important;--limel-icon-svg-margin:0.5rem}";
const Icon = class {
constructor(hostRef) {
registerInstance(this, hostRef);
this.size = undefined;
this.name = undefined;
this.badge = undefined;
}
componentDidLoad() {
this.loadIcon(this.name);
}
render() {
return h("div", { class: "container" });
}
async loadIcon(name) {
if (name === undefined || name === '') {
return;
}
const svgData = await this.loadSvg(name);
this.renderSvg(svgData);
}
/**
* Load the SVG data for the icon from the icon cache
*
* @param name - name of the icon
* @returns the icon SVG data
*/
loadSvg(name) {
return iconCache.get(name, globalConfig.iconPath);
}
/*
* There is no way to style external SVG files with CSS, i.e. SVGs loaded
* with <img src="file.svg" /> or <object data="file.svg" type="image/svg+xml" />
* will remain the way they look in the file.
* Therefore we inject the svg as inline markup instead.
*/
renderSvg(svgData) {
const container = this.host.shadowRoot.querySelector('div.container');
if (container) {
container.innerHTML = svgData;
}
}
get host() { return getElement(this); }
static get watchers() { return {
"name": ["loadIcon"]
}; }
};
Icon.style = iconCss;
export { Icon as limel_icon };
//# sourceMappingURL=limel-icon.entry.js.map