@@ -216,39 +216,49 @@ export class GlpiIllustrationPickerController
216216 {
217217 // Gets details of the newly selected item.
218218 const illustration_id = illustration . dataset [ 'glpiIconPickerValue' ] ;
219- const illustration_title = illustration
220- . querySelector ( 'svg' )
221- . querySelector ( 'title' )
222- ;
223219
224220 // Apply the new illustration id to the hidden input.
225221 this . #getSelectedIllustrationsInput( ) . value = illustration_id ;
226222
227- // Update the preview of the selected item.
228- const selected_svg = this . #container
229- . querySelector ( '[data-glpi-icon-picker-value-preview]' )
230- . querySelector ( 'svg' )
231- ;
232- const title = selected_svg . querySelector ( 'title' ) ;
233- const use = selected_svg . querySelector ( 'use' ) ;
234- const xlink = use . getAttribute ( 'xlink:href' ) ;
223+ if ( illustration_id === '' ) {
224+ // Empty selection: show placeholder, hide both preview slots.
225+ this . #setEmptyPreview( ) ;
226+ return ;
227+ }
235228
236- use . setAttribute (
237- 'xlink:href' ,
238- xlink . replace ( / # .* / , `#${ illustration_id } ` )
239- ) ;
240- title . innerHTML = illustration_title . innerHTML ;
229+ // Clone the clicked illustration's SVG into the native preview slot.
230+ // Cloning (vs in-place mutation) handles the transition from an empty
231+ // article — where the slot has no SVG to mutate — without requiring
232+ // the template to pre-render a skeleton SVG.
233+ const native_slot = this . #getNativePreviewSlot( ) ;
234+ const clicked_svg = illustration . querySelector ( 'svg' ) ;
235+ native_slot . replaceChildren ( clicked_svg . cloneNode ( true ) ) ;
236+
237+ native_slot . classList . remove ( 'd-none' ) ;
238+ this . #getCustomPreviewSlot( ) . classList . add ( 'd-none' ) ;
239+ this . #getPlaceholderSlot( ) ?. classList . add ( 'd-none' ) ;
240+ }
241241
242- this . #container
243- . querySelector ( '[data-glpi-icon-picker-value-preview-native]' )
244- . classList
245- . remove ( 'd-none' )
246- ;
247- this . #container
248- . querySelector ( '[data-glpi-icon-picker-value-preview-custom]' )
249- . classList
250- . add ( 'd-none' )
251- ;
242+ #setEmptyPreview( )
243+ {
244+ this . #getNativePreviewSlot( ) ?. classList . add ( 'd-none' ) ;
245+ this . #getCustomPreviewSlot( ) ?. classList . add ( 'd-none' ) ;
246+ this . #getPlaceholderSlot( ) ?. classList . remove ( 'd-none' ) ;
247+ }
248+
249+ #getNativePreviewSlot( )
250+ {
251+ return this . #container. querySelector ( '[data-glpi-icon-picker-value-preview-native]' ) ;
252+ }
253+
254+ #getCustomPreviewSlot( )
255+ {
256+ return this . #container. querySelector ( '[data-glpi-icon-picker-value-preview-custom]' ) ;
257+ }
258+
259+ #getPlaceholderSlot( )
260+ {
261+ return this . #container. querySelector ( '[data-glpi-icon-picker-value-preview-placeholder]' ) ;
252262 }
253263
254264 #setCustomIllustration( file_id )
@@ -257,21 +267,12 @@ export class GlpiIllustrationPickerController
257267 this . #getSelectedIllustrationsInput( ) . value = icon_id ;
258268
259269 // Update preview
260- this . #container
261- . querySelector ( '[data-glpi-icon-picker-value-preview-custom]' )
262- . querySelector ( 'img' )
263- . src = `${ CFG_GLPI . root_doc } /UI/Illustration/CustomIllustration/${ file_id } `
264- ;
265- this . #container
266- . querySelector ( '[data-glpi-icon-picker-value-preview-custom]' )
267- . classList
268- . remove ( 'd-none' )
269- ;
270- this . #container
271- . querySelector ( '[data-glpi-icon-picker-value-preview-native]' )
272- . classList
273- . add ( 'd-none' )
274- ;
270+ const custom_slot = this . #getCustomPreviewSlot( ) ;
271+ custom_slot . querySelector ( 'img' ) . src
272+ = `${ CFG_GLPI . root_doc } /UI/Illustration/CustomIllustration/${ file_id } ` ;
273+ custom_slot . classList . remove ( 'd-none' ) ;
274+ this . #getNativePreviewSlot( ) . classList . add ( 'd-none' ) ;
275+ this . #getPlaceholderSlot( ) ?. classList . add ( 'd-none' ) ;
275276 }
276277
277278 /**
0 commit comments