carbon-components-angular
Version:
Next generation components
555 lines (547 loc) • 20.9 kB
JavaScript
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