@@ -264,6 +264,15 @@ class MappingInputProvider extends HTMLElement {
264264 options . labelIdle = `Drag & Drop your files or Browse (File size limit: ${ options . maxFileSize } )` ;
265265 this . fileChooser = FilePondLib . create ( filepondElement , options ) ;
266266 queueMicrotask ( ( ) => this . decorateFilePondLabel ( options . maxFileSize as string ) ) ;
267+ this . fileChooser . on ( 'addfile' , ( ) => {
268+ if ( this . selectedMappingId ) {
269+ this . setSubmitEnabled ( true ) ;
270+ }
271+ this . removeMessage ( ) ;
272+ } ) ;
273+ this . fileChooser . on ( 'removefile' , ( ) => {
274+ this . setSubmitEnabled ( false ) ;
275+ } ) ;
267276 }
268277
269278 private decorateFilePondLabel ( limit : string ) : void {
@@ -281,20 +290,23 @@ class MappingInputProvider extends HTMLElement {
281290 // Using text nodes avoids surprises from HTML whitespace collapsing rules or CSS resets.
282291 '' ;
283292 dropLabel . replaceChildren ( ) ;
293+
294+ const div = document . createElement ( 'div' ) ;
284295 // Use non‑breaking spaces (\u00A0) so spacing is preserved regardless of CSS white-space rules.
285- dropLabel . append ( 'Drag & Drop your files or\u00A0' ) ;
296+ div . append ( document . createTextNode ( 'Drag & Drop your files or\u00A0' ) ) ;
286297 const browseEl = document . createElement ( 'span' ) ;
287298 browseEl . className = 'filepond--label-action' ;
288299 browseEl . setAttribute ( 'role' , 'button' ) ;
289300 browseEl . setAttribute ( 'tabindex' , '0' ) ;
290301 browseEl . textContent = 'Browse' ;
291- dropLabel . append ( browseEl ) ;
292- dropLabel . append ( '\u00A0' ) ;
293- dropLabel . append ( document . createElement ( 'br' ) ) ;
302+ div . append ( browseEl ) ;
303+ div . append ( '\u00A0' ) ;
304+ div . append ( document . createElement ( 'br' ) ) ;
294305 const info = document . createElement ( 'span' ) ;
295306 info . className = 'info-small' ;
296307 info . textContent = `(File size is limited to ${ limit } )` ;
297- dropLabel . append ( info ) ;
308+ div . append ( info ) ;
309+ dropLabel . appendChild ( div ) ;
298310 const trigger = ( ) => this . fileChooser ?. browse ( ) ;
299311 browseEl . addEventListener ( 'click' , trigger ) ;
300312 browseEl . addEventListener ( 'keydown' , ( e : Event ) => {
@@ -374,7 +386,7 @@ class MappingInputProvider extends HTMLElement {
374386 descWrapper . classList . add ( 'description' ) ;
375387 descWrapper . appendChild ( document . createElement ( 'br' ) ) ;
376388 const scrollSpan = document . createElement ( 'span' ) ;
377- scrollSpan . setAttribute ( 'style' , 'display:inline-block; overflow: auto; height: 124px ;' ) ;
389+ scrollSpan . setAttribute ( 'style' , 'display:inline-block; overflow: auto; height: 10rem ;' ) ;
378390 scrollSpan . textContent = mapping . description ?? '' ;
379391 descWrapper . appendChild ( scrollSpan ) ;
380392 const buttonEl = document . createElement ( 'button' ) ;
@@ -440,17 +452,20 @@ class MappingInputProvider extends HTMLElement {
440452 b . classList . remove ( 'selected-id' ) ;
441453 b . setAttribute ( 'aria-selected' , 'false' ) ;
442454 } ) ;
443- if ( id && id !== this . selectedMappingId ) {
455+ if ( id && id !== this . selectedMappingId && id !== '' ) {
444456 buttonEl . classList . add ( 'selected-id' ) ;
445457 buttonEl . setAttribute ( 'aria-selected' , 'true' ) ;
458+ buttonEl . innerText = '✓ Selected' ;
446459 this . selectedMappingId = id ;
447- this . showMessage (
448- 'Mapping selected. Please choose a file and then activate <b><i>Execute Mapping</i></b> to start the process.' ,
449- ) ;
450- this . setSubmitEnabled ( true ) ;
460+ if ( this . fileChooser && this . fileChooser . getFiles ( ) . length > 0 ) {
461+ this . setSubmitEnabled ( true ) ;
462+ this . removeMessage ( ) ;
463+ } else this . setSubmitEnabled ( false ) ;
451464 } else {
465+ buttonEl . innerText = 'Select' ;
452466 this . selectedMappingId = null ;
453467 this . showMessage ( 'Please select a mapping from the list above.' ) ;
468+ this . removeMessage ( ) ;
454469 this . setSubmitEnabled ( false ) ;
455470 }
456471 }
@@ -498,8 +513,15 @@ class MappingInputProvider extends HTMLElement {
498513 submit . setAttribute ( 'disabled' , 'true' ) ;
499514 submit . innerText = 'Please wait...' ;
500515 const ok = await this . executeMapping ( ) ;
501- if ( ok ) console . log ( 'Mapping successfully finished.' ) ;
502- else console . error ( 'Mapping failed.' ) ;
516+ if ( ok ) {
517+ console . log ( 'Mapping successfully finished.' ) ;
518+ this . showMessage (
519+ 'Mapping successfully finished. You can now select another mapping or upload a new file.' ,
520+ ) ;
521+ setTimeout ( ( ) => this . removeMessage ( ) , 10000 ) ;
522+ } else {
523+ console . error ( 'Mapping failed.' ) ;
524+ }
503525 if ( this . selectedMappingId ) submit . removeAttribute ( 'disabled' ) ;
504526 else submit . setAttribute ( 'disabled' , 'true' ) ;
505527 submit . innerText = 'Execute Mapping' ;
@@ -519,6 +541,18 @@ class MappingInputProvider extends HTMLElement {
519541 return false ;
520542 }
521543
544+ private removeMessage ( ) : void {
545+ /**
546+ * Clear any existing status or error message from the message area.
547+ */
548+ const el = this . shadowRoot . querySelector ( '#message' ) ;
549+ if ( ! el ) return ;
550+ el . replaceChildren ( ) ;
551+ el . setAttribute ( 'hidden' , 'true' ) ;
552+ el . classList . add ( 'hidden' ) ;
553+ el . classList . remove ( 'info' , 'error' ) ;
554+ }
555+
522556 /**
523557 * Render a status or error message in the message area.
524558 * Accepts a limited HTML subset (currently: <span class="heroicons-outline--exclamation"></span> and <br> tags).
@@ -533,6 +567,7 @@ class MappingInputProvider extends HTMLElement {
533567 const isError = type === 'ERROR' ;
534568 el . setAttribute ( 'role' , isError ? 'alert' : 'status' ) ;
535569 el . setAttribute ( 'aria-live' , isError ? 'assertive' : 'polite' ) ;
570+ el . removeAttribute ( 'hidden' ) ;
536571 // Sanitize supplied HTML and append
537572 const fragment = this . sanitizeMessageHtml ( text ) ;
538573 el . appendChild ( fragment ) ;
0 commit comments