UNPKG

carbon-components-angular

Version:
555 lines (547 loc) 20.9 kB
import * as i0 from '@angular/core'; import { EventEmitter, Component, Input, Output, HostBinding, TemplateRef, ViewChild, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import * as i1 from 'carbon-components-angular/i18n'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i3$1 from 'carbon-components-angular/button'; import { ButtonModule } from 'carbon-components-angular/button'; import * as i3 from 'carbon-components-angular/loading'; import { LoadingModule } from 'carbon-components-angular/loading'; import * as i4 from 'carbon-components-angular/icon'; import { IconModule } from 'carbon-components-angular/icon'; class FileComponent { constructor(i18n) { this.i18n = i18n; /** * Accessible translations for the close and complete icons */ this.translations = this.i18n.get().FILE_UPLOADER; this.size = "lg"; this.remove = new EventEmitter(); this.selectedFile = true; } get isInvalidText() { return this.fileItem.invalidText; } get fileSizeSmall() { return this.size === "sm"; } get fileSizeMedium() { return this.size === "md"; } get fileSizeLarge() { return this.size === "lg"; } ngOnDestroy() { this.remove.emit(); } } FileComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileComponent, deps: [{ token: i1.I18n }], target: i0.ɵɵFactoryTarget.Component }); FileComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FileComponent, selector: "cds-file, ibm-file", inputs: { translations: "translations", fileItem: "fileItem", size: "size" }, outputs: { remove: "remove" }, host: { properties: { "class.cds--file__selected-file": "this.selectedFile", "class.cds--file__selected-file--invalid": "this.isInvalidText", "class.cds--file__selected-file--sm": "this.fileSizeSmall", "class.cds--file__selected-file--md": "this.fileSizeMedium", "class.cds--file__selected-file--lg": "this.fileSizeLarge" } }, ngImport: i0, template: ` <p class="cds--file-filename" [title]="fileItem.file.name">{{fileItem.file.name}}</p> <span *ngIf="fileItem.state === 'edit'" class="cds--file__state-container"> <svg *ngIf="isInvalidText" cdsIcon="warning--filled" class="cds--file--invalid" size="16"> </svg> <button type="button" class="cds--file-close" [attr.aria-label]="translations.REMOVE_BUTTON" tabindex="0" (click)="remove.emit()" (keyup.enter)="remove.emit()" (keyup.space)="remove.emit()"> <svg cdsIcon="close" size="16"></svg> </button> </span> <span *ngIf="fileItem.state === 'upload'"> <div class="cds--inline-loading__animation"> <cds-loading size="sm"></cds-loading> </div> </span> <span *ngIf="fileItem.state === 'complete'" class="cds--file__state-container"> <svg cdsIcon="checkmark--filled" size="16" class="cds--file-complete" [ariaLabel]="translations.CHECKMARK"> </svg> </span> <div class="cds--form-requirement" role="alert" *ngIf="fileItem.invalid"> <div class="cds--form-requirement__title">{{fileItem.invalidTitle}}</div> <p class="cds--form-requirement__supplement">{{fileItem.invalidText}}</p> </div> `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.Loading, selector: "cds-loading, ibm-loading", inputs: ["title", "isActive", "size", "overlay"] }, { kind: "directive", type: i4.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileComponent, decorators: [{ type: Component, args: [{ selector: "cds-file, ibm-file", template: ` <p class="cds--file-filename" [title]="fileItem.file.name">{{fileItem.file.name}}</p> <span *ngIf="fileItem.state === 'edit'" class="cds--file__state-container"> <svg *ngIf="isInvalidText" cdsIcon="warning--filled" class="cds--file--invalid" size="16"> </svg> <button type="button" class="cds--file-close" [attr.aria-label]="translations.REMOVE_BUTTON" tabindex="0" (click)="remove.emit()" (keyup.enter)="remove.emit()" (keyup.space)="remove.emit()"> <svg cdsIcon="close" size="16"></svg> </button> </span> <span *ngIf="fileItem.state === 'upload'"> <div class="cds--inline-loading__animation"> <cds-loading size="sm"></cds-loading> </div> </span> <span *ngIf="fileItem.state === 'complete'" class="cds--file__state-container"> <svg cdsIcon="checkmark--filled" size="16" class="cds--file-complete" [ariaLabel]="translations.CHECKMARK"> </svg> </span> <div class="cds--form-requirement" role="alert" *ngIf="fileItem.invalid"> <div class="cds--form-requirement__title">{{fileItem.invalidTitle}}</div> <p class="cds--form-requirement__supplement">{{fileItem.invalidText}}</p> </div> ` }] }], ctorParameters: function () { return [{ type: i1.I18n }]; }, propDecorators: { translations: [{ type: Input }], fileItem: [{ type: Input }], size: [{ type: Input }], remove: [{ type: Output }], selectedFile: [{ type: HostBinding, args: ["class.cds--file__selected-file"] }], isInvalidText: [{ type: HostBinding, args: ["class.cds--file__selected-file--invalid"] }], fileSizeSmall: [{ type: HostBinding, args: ["class.cds--file__selected-file--sm"] }], fileSizeMedium: [{ type: HostBinding, args: ["class.cds--file__selected-file--md"] }], fileSizeLarge: [{ type: HostBinding, args: ["class.cds--file__selected-file--lg"] }] } }); const noop = () => { }; /** * Get started with importing the module: * * ```typescript * import { FileUploaderModule } from 'carbon-components-angular'; * ``` * * [See demo](../../?path=/story/components-file-uploader--basic) */ class FileUploader { constructor(i18n) { this.i18n = i18n; /** * Accessible text for the button that opens the upload window. * * Defaults to the `FILE_UPLOADER.OPEN` value from the i18n service */ this.buttonText = this.i18n.get().FILE_UPLOADER.OPEN; /** * Type set for button */ this.buttonType = "primary"; /** * Specify the types of files that the input should be able to receive */ this.accept = []; /** * Set to `false` to tell the component to only accept a single file on upload. * * Defaults to `true`. Accepts multiple files. */ this.multiple = true; /** * Set to `true` for a loading file uploader. */ this.skeleton = false; /** * Sets the size of the file items */ this.fileItemSize = "lg"; /** * Set to `true` to enable drag and drop. */ this.drop = false; /** * Provides a unique id for the underlying `<input>` node */ this.fileUploaderId = `file-uploader-${FileUploader.fileUploaderCount}`; /** * The list of files that have been submitted to be uploaded */ this.files = new Set(); /** * Set to `true` to disable upload button */ this.disabled = false; this.filesChange = new EventEmitter(); /** * Controls the state of the drag and drop file container */ this.dragOver = false; this.onTouchedCallback = noop; this.onChangeCallback = noop; FileUploader.fileUploaderCount++; } /** * Specifies the property to be used as the return value to `ngModel` and reactive forms. * Updates `this.files`. */ get value() { return this.files; } set value(v) { if (v !== this.files) { this.files = v; this.onChangeCallback(v); } } onBlur() { this.onTouchedCallback(); } get fileList() { return Array.from(this.fileInput.nativeElement.files); } /** * Propagates the injected `value`. */ writeValue(value) { if (value !== this.value) { this.files = value; } } createFileItem(file) { return { uploaded: false, state: "edit", invalid: false, invalidText: "", file: file }; } onFilesAdded() { const newFiles = new Set(this.files); if (!this.multiple) { newFiles.clear(); } for (let file of this.fileList) { const fileItem = this.createFileItem(file); newFiles.add(fileItem); } this.value = newFiles; this.filesChange.emit(newFiles); } onDragOver(event) { event.stopPropagation(); event.preventDefault(); if (this.disabled) { return; } this.dragOver = true; } onDragLeave(event) { event.stopPropagation(); event.preventDefault(); this.dragOver = false; } onDrop(event) { event.stopPropagation(); event.preventDefault(); if (this.disabled) { return; } const transferredFiles = Array.from(event.dataTransfer.files); const newFiles = new Set(this.files); transferredFiles.filter(({ name, type }) => { // Get the file extension and add a "." to the beginning. const fileExtension = name.split(".").pop().replace(/^/, "."); // Check if the accept array contains the mime type or extension of the file. return this.accept.includes(type) || this.accept.includes(fileExtension) || !this.accept.length; }).forEach(file => { if (!newFiles.size || this.multiple) { const fileItem = this.createFileItem(file); newFiles.add(fileItem); } }); this.value = newFiles; this.filesChange.emit(newFiles); this.dragOver = false; } removeFile(fileItem) { // Deleting an item from this.files removes the <ibm-file> component, // which triggers its ngOnDestroy(), which fires the (remove) event again. // So, (remove) may double-fire and we need to handle it here. if (this.files && this.files.has(fileItem)) { const newFiles = new Set(this.files); newFiles.delete(fileItem); this.filesChange.emit(newFiles); this.value = newFiles; } this.fileInput.nativeElement.value = ""; } isTemplate(value) { return value instanceof TemplateRef; } /** * Registers the injected function to control the touch use of the `FileUploader`. */ registerOnTouched(fn) { this.onTouchedCallback = fn; } /** * Sets a method in order to propagate changes back to the form. */ registerOnChange(fn) { this.onChangeCallback = fn; } /** * `ControlValueAccessor` method to programmatically disable the checkbox. * * ex: `this.formGroup.get("myFileUploader").disable();` * * @param isDisabled `true` to disable the file uploader */ setDisabledState(isDisabled) { this.disabled = isDisabled; } } /** * Counter used to create unique ids for file-uploader components */ FileUploader.fileUploaderCount = 0; FileUploader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploader, deps: [{ token: i1.I18n }], target: i0.ɵɵFactoryTarget.Component }); FileUploader.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: { buttonText: "buttonText", buttonType: "buttonType", title: "title", description: "description", accept: "accept", multiple: "multiple", skeleton: "skeleton", size: "size", fileItemSize: "fileItemSize", drop: "drop", dropText: "dropText", fileUploaderId: "fileUploaderId", files: "files", disabled: "disabled" }, outputs: { filesChange: "filesChange" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: FileUploader, multi: true } ], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: ` <ng-container *ngIf="!skeleton; else skeletonTemplate"> <label [for]="fileUploaderId" class="cds--file--label">{{title}}</label> <p class="cds--label-description" role="alert">{{description}}</p> <div class="cds--file"> <label *ngIf="drop" class="cds--file-browse-btn" (keyup.enter)="fileInput.click()" (keyup.space)="fileInput.click()" [ngClass]="{'cds--file-browse-btn--disabled': disabled}" tabindex="0"> <div class="cds--file__drop-container" [ngClass]="{'cds--file__drop-container--drag-over': dragOver}" role="button" (click)="fileInput.click()" [attr.for]="fileUploaderId" (dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)" (drop)="onDrop($event)"> <ng-container *ngIf="!isTemplate(dropText)">{{dropText}}</ng-container> <ng-template *ngIf="isTemplate(dropText)" [ngTemplateOutlet]="dropText"></ng-template> </div> </label> <button *ngIf="!drop" type="button" [cdsButton]="buttonType" (click)="fileInput.click()" [attr.for]="fileUploaderId" [size]="size" [disabled]="disabled"> {{buttonText}} </button> <input #fileInput type="file" class="cds--file-input" [accept]="accept" [id]="fileUploaderId" [multiple]="multiple" tabindex="-1" (change)="onFilesAdded()" [disabled]="disabled"/> <div class="cds--file-container"> <ng-container *ngFor="let fileItem of files"> <cds-file [fileItem]="fileItem" (remove)="removeFile(fileItem)" [size]="fileItemSize"> </cds-file> </ng-container> </div> </div> </ng-container> <ng-template #skeletonTemplate> <div class="cds--skeleton__text" style="width: 100px"></div> <div class="cds--skeleton__text" style="width: 225px"></div> <button cdsButton skeleton="true"></button> </ng-template> `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3$1.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "component", type: FileComponent, selector: "cds-file, ibm-file", inputs: ["translations", "fileItem", "size"], outputs: ["remove"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploader, decorators: [{ type: Component, args: [{ selector: "cds-file-uploader, ibm-file-uploader", template: ` <ng-container *ngIf="!skeleton; else skeletonTemplate"> <label [for]="fileUploaderId" class="cds--file--label">{{title}}</label> <p class="cds--label-description" role="alert">{{description}}</p> <div class="cds--file"> <label *ngIf="drop" class="cds--file-browse-btn" (keyup.enter)="fileInput.click()" (keyup.space)="fileInput.click()" [ngClass]="{'cds--file-browse-btn--disabled': disabled}" tabindex="0"> <div class="cds--file__drop-container" [ngClass]="{'cds--file__drop-container--drag-over': dragOver}" role="button" (click)="fileInput.click()" [attr.for]="fileUploaderId" (dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)" (drop)="onDrop($event)"> <ng-container *ngIf="!isTemplate(dropText)">{{dropText}}</ng-container> <ng-template *ngIf="isTemplate(dropText)" [ngTemplateOutlet]="dropText"></ng-template> </div> </label> <button *ngIf="!drop" type="button" [cdsButton]="buttonType" (click)="fileInput.click()" [attr.for]="fileUploaderId" [size]="size" [disabled]="disabled"> {{buttonText}} </button> <input #fileInput type="file" class="cds--file-input" [accept]="accept" [id]="fileUploaderId" [multiple]="multiple" tabindex="-1" (change)="onFilesAdded()" [disabled]="disabled"/> <div class="cds--file-container"> <ng-container *ngFor="let fileItem of files"> <cds-file [fileItem]="fileItem" (remove)="removeFile(fileItem)" [size]="fileItemSize"> </cds-file> </ng-container> </div> </div> </ng-container> <ng-template #skeletonTemplate> <div class="cds--skeleton__text" style="width: 100px"></div> <div class="cds--skeleton__text" style="width: 225px"></div> <button cdsButton skeleton="true"></button> </ng-template> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: FileUploader, multi: true } ] }] }], ctorParameters: function () { return [{ type: i1.I18n }]; }, propDecorators: { buttonText: [{ type: Input }], buttonType: [{ type: Input }], title: [{ type: Input }], description: [{ type: Input }], accept: [{ type: Input }], multiple: [{ type: Input }], skeleton: [{ type: Input }], size: [{ type: Input }], fileItemSize: [{ type: Input }], drop: [{ type: Input }], dropText: [{ type: Input }], fileUploaderId: [{ type: Input }], fileInput: [{ type: ViewChild, args: ["fileInput"] }], files: [{ type: Input }], disabled: [{ type: Input }], filesChange: [{ type: Output }] } }); class FileUploaderModule { } FileUploaderModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploaderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); FileUploaderModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: FileUploaderModule, declarations: [FileUploader, FileComponent], imports: [CommonModule, ButtonModule, LoadingModule, IconModule], exports: [FileUploader, FileComponent] }); FileUploaderModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploaderModule, imports: [CommonModule, ButtonModule, LoadingModule, IconModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploaderModule, decorators: [{ type: NgModule, args: [{ declarations: [FileUploader, FileComponent], exports: [FileUploader, FileComponent], imports: [ CommonModule, ButtonModule, LoadingModule, IconModule ] }] }] }); /** * Generated bundle index. Do not edit. */ export { FileComponent, FileUploader, FileUploaderModule }; //# sourceMappingURL=carbon-components-angular-file-uploader.mjs.map