@@ -8,6 +8,7 @@ import {HasSlotController} from "../../internal/slot";
88import { ifDefined } from "lit/directives/if-defined.js" ;
99import { LocalizeController } from "../../utilities/localize" ;
1010import { property , query , state } from 'lit/decorators.js' ;
11+ import { repeat } from 'lit/directives/repeat.js' ;
1112import { watch } from "../../internal/watch" ;
1213import ZincElement , { type ZincFormControl } from '../../internal/zinc-element' ;
1314import type ZnButton from "../button" ;
@@ -142,6 +143,9 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
142143 /** The file control's label. If you need to display HTML, use the `label` slot instead. */
143144 @property ( ) label = '' ;
144145
146+ /** If this is set, then the only way to remove files is to click the cross next to them. */
147+ @property ( { type : Boolean } ) clearable = false ;
148+
145149 /**
146150 * The file control's help text.
147151 * If you need to display HTML, use the `help-text` slot instead.
@@ -413,30 +417,60 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
413417 this . emit ( 'zn-blur' ) ;
414418 }
415419
416- private renderValue ( ) : HTMLTemplateResult {
417- let hasFiles = false ;
418- // @ts -expect-error variadic function
419- let fileChosenLabel = this . localize . term ( 'numFilesSelected' , 0 , this . webkitdirectory ) ;
420-
421- if ( this . files && this . files ?. length > 0 ) {
422- hasFiles = true ;
423- fileChosenLabel = this . files . length === 1
424- ? this . files [ 0 ] . name
425- // @ts -expect-error variadic function
426- : this . localize . term ( 'numFilesSelected' , this . files . length , this . webkitdirectory ) ;
420+ /**
421+ * Remove a file from the list of files
422+ */
423+ private removeFile = ( e : Event ) => {
424+ e . preventDefault ( ) ;
425+ e . stopPropagation ( ) ;
426+
427+ const files = Array . from ( this . files || [ ] ) ;
428+ const file = ( e . target as ZnButton ) . parentElement ?. getAttribute ( 'data-file-name' ) ;
429+
430+ const index = files . findIndex ( f => f . name === file ) ;
431+
432+ if ( index !== - 1 ) {
433+ files . splice ( index , 1 ) ;
427434 }
428435
436+ const dataTransfer = new DataTransfer ( ) ;
437+ files . forEach ( f => dataTransfer . items . add ( f ) ) ;
438+ this . files = dataTransfer . files ;
439+ this . input . dispatchEvent ( new Event ( 'change' ) ) ;
440+ }
441+
442+ private renderFileValueWithDelete ( ) : HTMLTemplateResult {
443+ // files as an array
444+ const files = Array . from ( this . files || [ ] ) ;
445+ const isClearable = this . clearable ;
446+
447+ // @ts -expect-error variadic
448+ const fileChosenLabel = this . localize . term ( 'numFilesSelected' , 0 , this . webkitdirectory ) ;
429449 return html `
430- < span
431- class =${ classMap ( {
432- input__value : true ,
433- 'input__value--hidden' : this . hideValue ,
434- 'input__value--placeholder' : ! hasFiles ,
435- } ) }
436- part ="value">
437- ${ fileChosenLabel }
438- </ span >
439- ` ;
450+ ${ files ? html `
451+ < div class ="file_wrapper ">
452+ ${ repeat ( files , ( file : File ) => html `
453+ < zn-chip
454+ class =${ classMap ( {
455+ 'input__value' : true ,
456+ 'input__value--hidden' : this . hideValue ,
457+ } ) }
458+ data-file-name ="${ file . name } "
459+ part="value">
460+ ${ file . name }
461+ ${ isClearable ? html `
462+ < zn-button
463+ slot ="action "
464+ class ="input__delete "
465+ color ="transparent "
466+ icon ="close "
467+ size ="content "
468+ icon-size ="18 "
469+ @click ="${ this . removeFile } "
470+ part ="delete "> </ zn-button > ` : '' }
471+ </ zn-chip >
472+ ` ) }
473+ </ div > ` : html `${ fileChosenLabel } ` } `;
440474 }
441475
442476 private renderDroparea ( ) : HTMLTemplateResult {
@@ -457,11 +491,10 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
457491 < zn-icon src ="upload_file "> </ zn-icon >
458492 </ slot >
459493 </ span >
460- < p
461- class ="droparea__text "
462- part ="droparea-value ">
494+ < p class ="droparea__text "
495+ part ="droparea-value ">
463496 < strong > ${ this . localize . term ( this . webkitdirectory ? 'folderDragDrop' : 'fileDragDrop' ) } </ strong >
464- ${ this . renderValue ( ) }
497+ ${ this . renderFileValueWithDelete ( ) }
465498 </ p >
466499 </ div >
467500 </ div >
@@ -491,7 +524,7 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
491524 outline>
492525 ${ buttonText }
493526 </ zn-button >
494- ${ this . renderValue ( ) }
527+ ${ this . renderFileValueWithDelete ( ) }
495528 </ div > ` ;
496529 }
497530
0 commit comments