From 102847b176b6bed1a63f518f6c8d3fb24ca5148f Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Tue, 18 Jul 2017 14:07:16 -0500 Subject: [PATCH] feat(icon): load svg icons --- packages/core/src/components/icon/icon.tsx | 60 ++++++++++------------ 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/packages/core/src/components/icon/icon.tsx b/packages/core/src/components/icon/icon.tsx index 19ee3b6e32..d43e42aa9e 100644 --- a/packages/core/src/components/icon/icon.tsx +++ b/packages/core/src/components/icon/icon.tsx @@ -12,7 +12,8 @@ export declare const publicPath: string; }, host: { theme: 'icon' - } + }, + assetsDir: 'svg' }) export class Icon { mode: string; @@ -20,7 +21,7 @@ export class Icon { /** * @input {string} Specifies the label to use for accessibility. Defaults to the icon name. */ - @State() label: string = ''; + @State() ariaLabel: string = ''; /** * @input {string} Specifies which icon to use. The appropriate icon will be used based on the mode. @@ -38,11 +39,6 @@ export class Icon { */ @Prop() md: string = ''; - /** - * @input {boolean} If true, the icon is hidden. - */ - @Prop() hidden: boolean = false; - @State() svgContent: string = null; @@ -58,21 +54,23 @@ export class Icon { get iconName() { - let iconName: string; - // if no name was passed set iconName to null if (!this.name) { return null; } - if (!(/^md-|^ios-|^logo-/.test(this.name))) { + let iconName = this.name.toLowerCase(); + + const invalidChars = iconName.replace(/[a-z]|-/g, ''); + if (invalidChars !== '') { + console.error(`invalid characters in ion-icon name: ${invalidChars}`); + return null; + } + + if (!(/^md-|^ios-|^logo-/.test(iconName))) { // this does not have one of the defaults // so lets auto add in the mode prefix for them - iconName = this.mode + '-' + this.name; - - } else if (this.name) { - // this icon already has a prefix - iconName = this.name; + iconName = this.mode + '-' + iconName; } // if an icon was passed in using the ios or md attributes @@ -93,14 +91,9 @@ export class Icon { 'role': 'img' }; - if (this.hidden) { - // adds the hidden attribute - attrs['hidden'] = ''; - } - - if (this.label) { + if (this.ariaLabel) { // user provided label - attrs['aria-label'] = this.label; + attrs['aria-label'] = this.ariaLabel; } else { // come up with the label based on the icon name @@ -109,7 +102,7 @@ export class Icon { attrs['aria-label'] = iconName .replace('ios-', '') .replace('md-', '') - .replace('-', ' '); + .replace(/\-/g, ' '); } } @@ -142,15 +135,17 @@ export class Icon { // remove this url from the active requests delete IonIcon.activeRequests[svgUrl]; + // this response is the content of the svg file we're looking for + let svgContent = this.responseText; + if (this.status >= 400) { // ok, not awesome, something is up console.error('Icon could not be loaded:', svgUrl); - return; + svgContent = ``; } - // this response is the content of the svg file we're looking for // cache it in the global IonIcon constant - IonIcon.svgContents[svgUrl] = this.responseText; + IonIcon.svgContents[svgUrl] = svgContent; // find any callbacks waiting on this url const svgLoadCallbacks = IonIcon.loadCallbacks[svgUrl]; @@ -158,13 +153,13 @@ export class Icon { // loop through all the callbacks that are waiting on the svg content for (var i = 0; i < svgLoadCallbacks.length; i++) { // fire off this callback which - svgLoadCallbacks[i](this.responseText); + svgLoadCallbacks[i](svgContent); } delete IonIcon.loadCallbacks[svgUrl]; } }); - xhr.addEventListener('error', function () { + xhr.addEventListener('error', () => { // umm, idk console.error('Icon could not be loaded:', svgUrl); }); @@ -179,7 +174,7 @@ export class Icon { const svgUrl = this.getSvgUrl(); if (!svgUrl) { // we don't have good data - return(
); + return
{/* invalid svg */}
; } const svgContent = IonIcon.svgContents[svgUrl]; @@ -187,9 +182,7 @@ export class Icon { // we've already loaded up this svg at one point // and the svg content we've loaded and assigned checks out // render this svg!! - return( -
- ); + return
; } // haven't loaded this svg yet @@ -201,7 +194,7 @@ export class Icon { }); // actively requesting the svg, so let's just render a div for now - return(
); + return
{/* loading svg */}
; } } @@ -213,6 +206,7 @@ const IonIcon: GlobalIonIcon = { svgContents: {} }; + interface GlobalIonIcon { activeRequests: {[url: string]: boolean}; loadCallbacks: {[url: string]: {(loadedSvgContent: string): void}[]};