@@ -12,6 +12,7 @@ export class Icon {
12
12
private io ?: IntersectionObserver ;
13
13
private iconName : string | null = null ;
14
14
private inheritedAttributes : { [ k : string ] : any } = { } ;
15
+ private svgContentInjected : boolean = false ;
15
16
16
17
@Element ( ) el ! : HTMLElement ;
17
18
@@ -80,7 +81,7 @@ export class Icon {
80
81
* @default true
81
82
*/
82
83
@Prop ( ) sanitize = true ;
83
-
84
+
84
85
componentWillLoad ( ) {
85
86
this . inheritedAttributes = inheritAttributes ( this . el , [ 'aria-label' ] ) ;
86
87
}
@@ -122,13 +123,43 @@ export class Icon {
122
123
cb ( ) ;
123
124
}
124
125
}
125
-
126
+
126
127
private hasAriaHidden = ( ) => {
127
128
const { el } = this ;
128
-
129
+
129
130
return el . hasAttribute ( 'aria-hidden' ) && el . getAttribute ( 'aria-hidden' ) === 'true' ;
130
131
}
131
132
133
+ private createSvgElement ( ) : SVGElement | null {
134
+ if ( this . svgContent ) {
135
+ const template = document . createElement ( "template" ) ;
136
+ template . innerHTML = this . svgContent ;
137
+
138
+ // Extract the first element from the template.
139
+ // It should be our <svg>.
140
+ const node = template . content . firstChild ;
141
+ if ( node ) {
142
+ if ( node . nodeType === Node . ELEMENT_NODE && ( node as Element ) . tagName === 'svg' ) {
143
+ const svg = node as SVGElement ;
144
+
145
+ // Add the shadow part
146
+ svg . setAttribute ( 'part' , 'svg' ) ;
147
+
148
+ return svg ;
149
+ }
150
+ }
151
+ }
152
+
153
+ return null ;
154
+ }
155
+
156
+ private injectSvgElement ( svgElement : SVGElement ) {
157
+ const el = ( this . el . shadowRoot as ShadowRoot ) . querySelector ( '.icon-inner' )
158
+ if ( el ) {
159
+ el . appendChild ( svgElement ) ;
160
+ }
161
+ }
162
+
132
163
@Watch ( 'name' )
133
164
@Watch ( 'src' )
134
165
@Watch ( 'icon' )
@@ -186,13 +217,29 @@ export class Icon {
186
217
{ ...inheritedAttributes }
187
218
>
188
219
{ Build . isBrowser && this . svgContent ? (
189
- < div class = "icon-inner" innerHTML = { this . svgContent } > </ div >
220
+ < div class = "icon-inner" part = "icon-inner" >
221
+ </ div >
190
222
) : (
191
223
< div class = "icon-inner" > </ div >
192
224
) }
193
225
</ Host >
194
226
) ;
195
227
}
228
+
229
+ componentDidRender ( ) {
230
+ /**
231
+ * If it has not been done already, create & inject the <SVG> element
232
+ * into `div.icon-inner`.
233
+ */
234
+ if ( ! this . svgContentInjected ) {
235
+ const svgElement = this . createSvgElement ( ) ;
236
+ if ( svgElement ) {
237
+ this . injectSvgElement ( svgElement ) ;
238
+
239
+ this . svgContentInjected = true ;
240
+ }
241
+ }
242
+ }
196
243
}
197
244
198
245
const getIonMode = ( ) =>
@@ -201,8 +248,8 @@ const getIonMode = () =>
201
248
const createColorClasses = ( color : string | undefined ) => {
202
249
return color
203
250
? {
204
- 'ion-color' : true ,
205
- [ `ion-color-${ color } ` ] : true ,
206
- }
251
+ 'ion-color' : true ,
252
+ [ `ion-color-${ color } ` ] : true ,
253
+ }
207
254
: null ;
208
255
} ;
0 commit comments