@@ -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,48 @@ 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
+
142
+ if ( node ) {
143
+ if ( node . nodeType !== Node . ELEMENT_NODE ) {
144
+ return null ;
145
+ } else {
146
+ if ( ( node as Element ) . tagName === 'svg' ) {
147
+ const svg = node as SVGElement ;
148
+
149
+ // Add the shadow part
150
+ svg . setAttribute ( 'part' , 'svg' ) ;
151
+
152
+ return svg ;
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ return null ;
159
+ }
160
+
161
+ private injectSvgElement ( svgElement : SVGElement ) {
162
+ const el = ( this . el . shadowRoot as ShadowRoot ) . querySelector ( '.icon-inner' )
163
+ if ( el ) {
164
+ el . appendChild ( svgElement ) ;
165
+ }
166
+ }
167
+
132
168
@Watch ( 'name' )
133
169
@Watch ( 'src' )
134
170
@Watch ( 'icon' )
@@ -186,13 +222,29 @@ export class Icon {
186
222
{ ...inheritedAttributes }
187
223
>
188
224
{ Build . isBrowser && this . svgContent ? (
189
- < div class = "icon-inner" innerHTML = { this . svgContent } > </ div >
225
+ < div class = "icon-inner" part = "icon-inner" >
226
+ </ div >
190
227
) : (
191
228
< div class = "icon-inner" > </ div >
192
229
) }
193
230
</ Host >
194
231
) ;
195
232
}
233
+
234
+ componentDidRender ( ) {
235
+ /**
236
+ * If it has not been done already, create & inject the <SVG> element
237
+ * into `div.icon-inner`.
238
+ */
239
+ if ( ! this . svgContentInjected ) {
240
+ const svgElement = this . createSvgElement ( ) ;
241
+ if ( svgElement ) {
242
+ this . injectSvgElement ( svgElement ) ;
243
+
244
+ this . svgContentInjected = true ;
245
+ }
246
+ }
247
+ }
196
248
}
197
249
198
250
const getIonMode = ( ) =>
@@ -201,8 +253,8 @@ const getIonMode = () =>
201
253
const createColorClasses = ( color : string | undefined ) => {
202
254
return color
203
255
? {
204
- 'ion-color' : true ,
205
- [ `ion-color-${ color } ` ] : true ,
206
- }
256
+ 'ion-color' : true ,
257
+ [ `ion-color-${ color } ` ] : true ,
258
+ }
207
259
: null ;
208
260
} ;
0 commit comments