import { ENTER } from '@angular/cdk/keycodes'; import { HttpRequest, HttpHeaders, HttpEventType, HttpResponse, HttpClient } from '@angular/common/http'; import * as i0 from '@angular/core'; import { inject, ElementRef, DestroyRef, Input, ViewChild, ViewEncapsulation, Component, DOCUMENT, NgZone, ChangeDetectorRef, ChangeDetectionStrategy, EventEmitter, booleanAttribute, numberAttribute, Output, NgModule } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { of, Observable, Subscription } from 'rxjs'; import { switchMap, map, tap, filter } from 'rxjs/operators'; import { warn } from 'ng-zorro-antd/core/logger'; import { fromEventOutsideAngular, toBoolean } from 'ng-zorro-antd/core/util'; import { trigger, transition, style, animate } from '@angular/animations'; import { Platform } from '@angular/cdk/platform'; import { NgTemplateOutlet } from '@angular/common'; import * as i3 from 'ng-zorro-antd/button'; import { NzButtonModule } from 'ng-zorro-antd/button'; import * as i2 from 'ng-zorro-antd/icon'; import { NzIconModule } from 'ng-zorro-antd/icon'; import * as i5 from 'ng-zorro-antd/progress'; import { NzProgressModule } from 'ng-zorro-antd/progress'; import * as i1 from 'ng-zorro-antd/tooltip'; import { NzTooltipModule } from 'ng-zorro-antd/tooltip'; import * as i4 from 'ng-zorro-antd/core/transition-patch'; import { Directionality } from '@angular/cdk/bidi'; import { NzI18nService } from 'ng-zorro-antd/i18n'; /** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ /** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ class NzUploadBtnComponent { reqs = {}; destroyed = false; file; options; onClick() { if (this.options.disabled || !this.options.openFileDialogOnClick) { return; } this.file.nativeElement.click(); } // skip safari bug onFileDrop(e) { if (this.options.disabled || e.type === 'dragover') { e.preventDefault(); return; } if (this.options.directory) { this.traverseFileTree(e.dataTransfer.items); } else { const files = Array.prototype.slice .call(e.dataTransfer.files) .filter((file) => this.attrAccept(file, this.options.accept)); if (files.length) { this.uploadFiles(files); } } e.preventDefault(); } onChange(e) { if (this.options.disabled) { return; } const hie = e.target; this.uploadFiles(hie.files); hie.value = ''; } traverseFileTree(files) { const _traverseFileTree = (item, path) => { if (item.isFile) { item.file((file) => { if (this.attrAccept(file, this.options.accept)) { this.uploadFiles([file]); } }); } else if (item.isDirectory) { const dirReader = item.createReader(); dirReader.readEntries((entries) => { for (const entrieItem of entries) { _traverseFileTree(entrieItem, `${path}${item.name}/`); } }); } }; for (const file of files) { _traverseFileTree(file.webkitGetAsEntry(), ''); } } attrAccept(file, acceptedFiles) { if (file && acceptedFiles) { const acceptedFilesArray = Array.isArray(acceptedFiles) ? acceptedFiles : acceptedFiles.split(','); const fileName = `${file.name}`; const mimeType = `${file.type}`; const baseMimeType = mimeType.replace(/\/.*$/, ''); return acceptedFilesArray.some(type => { const validType = type.trim(); if (validType.charAt(0) === '.') { return (fileName .toLowerCase() .indexOf(validType.toLowerCase(), fileName.toLowerCase().length - validType.toLowerCase().length) !== -1); } else if (/\/\*$/.test(validType)) { // This is something like an image/* mime type return baseMimeType === validType.replace(/\/.*$/, ''); } return mimeType === validType; }); } return true; } attachUid(file) { if (!file.uid) { file.uid = Math.random().toString(36).substring(2); } return file; } uploadFiles(fileList) { let filters$ = of(Array.prototype.slice.call(fileList)); if (this.options.filters) { this.options.filters.forEach(f => { filters$ = filters$.pipe(switchMap(list => { const fnRes = f.fn(list); return fnRes instanceof Observable ? fnRes : of(fnRes); })); }); } filters$.subscribe({ next: list => { list.forEach((file) => { this.attachUid(file); this.upload(file, list); }); }, error: e => { warn(`Unhandled upload filter error`, e); } }); } upload(file, fileList) { if (!this.options.beforeUpload) { return this.post(file); } const before = this.options.beforeUpload(file, fileList); const successBeforeLoadHook = (processedFile) => { const processedFileType = Object.prototype.toString.call(processedFile); if (typeof processedFile !== 'boolean' && (processedFileType === '[object File]' || processedFileType === '[object Blob]')) { processedFile.uid = file.uid; // we are sure that the file has already an uid, now nzBeforeUpload is used to transform the file, the transform file needs to have the same uid as the original file this.post(file, processedFile); } else if (processedFile) { this.post(file); } }; const errorBeforeLoadHook = (error) => { warn(`Unhandled upload beforeUpload error`, error); }; if (before instanceof Observable) { before.subscribe({ next: successBeforeLoadHook, error: errorBeforeLoadHook }); } else if (before instanceof Promise) { before.then(successBeforeLoadHook).catch(errorBeforeLoadHook); } else if (before) { return this.post(file); } } post(file, processedFile) { if (this.destroyed) { return; } let process$ = of(processedFile || file); let transformedFile; const opt = this.options; const { uid } = file; const { action, data, headers, transformFile } = opt; const args = { action: typeof action === 'string' ? action : '', name: opt.name, headers, file, postFile: file, data, withCredentials: opt.withCredentials, onProgress: opt.onProgress ? e => { opt.onProgress(e, file); } : undefined, onSuccess: (ret, xhr) => { this.clean(uid); opt.onSuccess(ret, file, xhr); }, onError: xhr => { this.clean(uid); opt.onError(xhr, file); } }; if (typeof action === 'function') { const actionResult = action(file); if (actionResult instanceof Observable) { process$ = process$.pipe(switchMap(() => actionResult), map(res => { args.action = res; return file; })); } else { args.action = actionResult; } } if (typeof transformFile === 'function') { const transformResult = transformFile(file); process$ = process$.pipe(switchMap(() => (transformResult instanceof Observable ? transformResult : of(transformResult))), tap(newFile => (transformedFile = newFile))); } /** * TODO * All this part of code needs to be removed in v22.0.0 when we will remove the `nzTransformFile` hook */ if (typeof data === 'function') { const dataResult = data(file); if (dataResult instanceof Observable) { process$ = process$.pipe( /** * this is a little bit tricky but here is the explanation: * Potentially, people can use the `beforeUpload` hook to transform the file, and also `nzTransformFile` hook to transform the file, * if beforeUpload hook transform the file, so nzTransformFile hook must not be called, otherwise the file will be transformed twice * Normally this can not happen, but it is possible until we remove the `nzTransformFile` hook */ filter(() => !processedFile), switchMap(() => dataResult), map(res => { args.data = res; return transformedFile ?? file; })); } else { args.data = dataResult; } } if (typeof headers === 'function') { const headersResult = headers(file); if (headersResult instanceof Observable) { process$ = process$.pipe(switchMap(() => headersResult), map(res => { args.headers = res; return transformedFile ?? file; })); } else { args.headers = headersResult; } } process$.subscribe(newFile => { args.postFile = newFile; const req$ = (opt.customRequest || this.xhr).call(this, args); if (!(req$ instanceof Subscription)) { warn(`Must return Subscription type in '[nzCustomRequest]' property`); } this.reqs[uid] = req$; opt.onStart(file); }); } xhr(args) { const formData = new FormData(); if (args.data) { Object.keys(args.data).map(key => { formData.append(key, args.data[key]); }); } formData.append(args.name, args.postFile); if (!args.headers) { args.headers = {}; } if (args.headers['X-Requested-With'] !== null) { args.headers['X-Requested-With'] = `XMLHttpRequest`; } else { delete args.headers['X-Requested-With']; } const req = new HttpRequest('POST', args.action, formData, { reportProgress: true, withCredentials: args.withCredentials, headers: new HttpHeaders(args.headers) }); return this.http.request(req).subscribe({ next: (event) => { if (event.type === HttpEventType.UploadProgress) { if (event.total > 0) { event.percent = (event.loaded / event.total) * 100; } args.onProgress(event, args.file); } else if (event instanceof HttpResponse) { args.onSuccess(event.body, args.file, event); } }, error: err => { this.abort(args.file); args.onError(err, args.file); } }); } clean(uid) { const req$ = this.reqs[uid]; if (req$ instanceof Subscription) { req$.unsubscribe(); } delete this.reqs[uid]; } abort(file) { if (file) { this.clean(file && file.uid); } else { Object.keys(this.reqs).forEach(uid => this.clean(uid)); } } http = inject(HttpClient, { optional: true }); elementRef = inject(ElementRef); destroyRef = inject(DestroyRef); constructor() { if (!this.http) { throw new Error(`Not found 'HttpClient', You can configure 'HttpClient' with 'provideHttpClient()' in your root module.`); } this.destroyRef.onDestroy(() => { this.destroyed = true; this.abort(); }); } ngOnInit() { // Caretaker note: `input[type=file].click()` will open a native OS file picker, // it doesn't require Angular to run `ApplicationRef.tick()`. fromEventOutsideAngular(this.elementRef.nativeElement, 'click') .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => this.onClick()); fromEventOutsideAngular(this.elementRef.nativeElement, 'keydown') .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(event => { if (this.options.disabled) { return; } if (event.key === 'Enter' || event.keyCode === ENTER) { this.onClick(); } }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadBtnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.0", type: NzUploadBtnComponent, isStandalone: true, selector: "[nz-upload-btn]", inputs: { options: "options" }, host: { listeners: { "drop": "onFileDrop($event)", "dragover": "onFileDrop($event)" }, properties: { "attr.tabindex": "\"0\"", "attr.role": "\"button\"", "class.ant-upload-disabled": "options.disabled" }, classAttribute: "ant-upload" }, viewQueries: [{ propertyName: "file", first: true, predicate: ["file"], descendants: true, static: true }], exportAs: ["nzUploadBtn"], ngImport: i0, template: "\n\n\n", encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadBtnComponent, decorators: [{ type: Component, args: [{ selector: '[nz-upload-btn]', exportAs: 'nzUploadBtn', host: { class: 'ant-upload', '[attr.tabindex]': '"0"', '[attr.role]': '"button"', '[class.ant-upload-disabled]': 'options.disabled', '(drop)': 'onFileDrop($event)', '(dragover)': 'onFileDrop($event)' }, encapsulation: ViewEncapsulation.None, template: "\n\n\n" }] }], ctorParameters: () => [], propDecorators: { file: [{ type: ViewChild, args: ['file', { static: true }] }], options: [{ type: Input }] } }); /** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ const isImageFileType = (type) => !!type && type.indexOf('image/') === 0; const MEASURE_SIZE = 200; class NzUploadListComponent { list = []; get showPic() { return this.listType === 'picture' || this.listType === 'picture-card'; } locale = {}; listType; set items(list) { this.list = list; } icons; onPreview; onRemove; onDownload; previewFile; previewIsImage; iconRender = null; dir = 'ltr'; document = inject(DOCUMENT); destroyRef = inject(DestroyRef); ngZone = inject(NgZone); cdr = inject(ChangeDetectorRef); platform = inject(Platform); genErr(file) { if (file.response && typeof file.response === 'string') { return file.response; } return (file.error && file.error.statusText) || this.locale.uploadError; } extname(url) { const temp = url.split('/'); const filename = temp[temp.length - 1]; const filenameWithoutSuffix = filename.split(/#|\?/)[0]; return (/\.[^./\\]*$/.exec(filenameWithoutSuffix) || [''])[0]; } isImageUrl(file) { if (isImageFileType(file.type)) { return true; } const url = (file.thumbUrl || file.url || ''); if (!url) { return false; } const extension = this.extname(url); if (/^data:image\//.test(url) || /(webp|svg|png|gif|jpg|jpeg|jfif|bmp|dpg)$/i.test(extension)) { return true; } else if (/^data:/.test(url)) { // other file types of base64 return false; } else if (extension) { // other file types which have extension return false; } return true; } getIconType(file) { if (!this.showPic) { return ''; } if (file.isUploading || (!file.thumbUrl && !file.url)) { return 'uploading'; } else { return 'thumbnail'; } } previewImage(file) { if (!isImageFileType(file.type) || !this.platform.isBrowser) { return of(''); } const canvas = this.document.createElement('canvas'); canvas.width = MEASURE_SIZE; canvas.height = MEASURE_SIZE; canvas.style.cssText = `position: fixed; left: 0; top: 0; width: ${MEASURE_SIZE}px; height: ${MEASURE_SIZE}px; z-index: 9999; display: none;`; this.document.body.appendChild(canvas); const ctx = canvas.getContext('2d'); const img = new Image(); const objectUrl = URL.createObjectURL(file); img.src = objectUrl; return fromEventOutsideAngular(img, 'load').pipe(map(() => { const { width, height } = img; let drawWidth = MEASURE_SIZE; let drawHeight = MEASURE_SIZE; let offsetX = 0; let offsetY = 0; if (width < height) { drawHeight = height * (MEASURE_SIZE / width); offsetY = -(drawHeight - drawWidth) / 2; } else { drawWidth = width * (MEASURE_SIZE / height); offsetX = -(drawWidth - drawHeight) / 2; } try { ctx.drawImage(img, offsetX, offsetY, drawWidth, drawHeight); } catch { // noop } const dataURL = canvas.toDataURL(); this.document.body.removeChild(canvas); URL.revokeObjectURL(objectUrl); return dataURL; })); } genThumb() { if (!this.platform.isBrowser) { return; } const win = window; if (!this.showPic || typeof document === 'undefined' || typeof win === 'undefined' || !win.FileReader || !win.File) { return; } this.list .filter(file => file.originFileObj instanceof File && file.thumbUrl === undefined) .forEach(file => { file.thumbUrl = ''; // Caretaker note: we shouldn't use promises here since they're not cancellable. // A promise microtask can be resolved after the view is destroyed. Thus, running `detectChanges()` // will cause a runtime exception (`detectChanges()` cannot be run on destroyed views). const dataUrl$ = (this.previewFile ? this.previewFile(file) : this.previewImage(file.originFileObj)).pipe(takeUntilDestroyed(this.destroyRef)); this.ngZone.runOutsideAngular(() => { dataUrl$.subscribe(dataUrl => { this.ngZone.run(() => { file.thumbUrl = dataUrl; this.detectChanges(); }); }); }); }); } showDownload(file) { return !!(this.icons.showDownloadIcon && file.status === 'done'); } fixData() { this.list.forEach(file => { file.isUploading = file.status === 'uploading'; file.message = this.genErr(file); file.linkProps = typeof file.linkProps === 'string' ? JSON.parse(file.linkProps) : file.linkProps; file.isImageUrl = this.previewIsImage ? this.previewIsImage(file) : this.isImageUrl(file); file.iconType = this.getIconType(file); file.showDownload = this.showDownload(file); }); } handlePreview(file, e) { if (!this.onPreview) { return; } e.preventDefault(); return this.onPreview(file); } handleRemove(file, e) { e.preventDefault(); if (this.onRemove) { this.onRemove(file); } } handleDownload(file) { if (typeof this.onDownload === 'function') { this.onDownload(file); } else if (file.url) { window.open(file.url); } } // #endregion detectChanges() { this.fixData(); this.cdr.detectChanges(); } ngOnChanges() { this.fixData(); this.genThumb(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: NzUploadListComponent, isStandalone: true, selector: "nz-upload-list", inputs: { locale: "locale", listType: "listType", items: "items", icons: "icons", onPreview: "onPreview", onRemove: "onRemove", onDownload: "onDownload", previewFile: "previewFile", previewIsImage: "previewIsImage", iconRender: "iconRender", dir: "dir" }, host: { properties: { "class.ant-upload-list-rtl": "dir === 'rtl'", "class.ant-upload-list-text": "listType === 'text'", "class.ant-upload-list-picture": "listType === 'picture'", "class.ant-upload-list-picture-card": "listType === 'picture-card'" }, classAttribute: "ant-upload-list" }, exportAs: ["nzUploadList"], usesOnChanges: true, ngImport: i0, template: "@for (file of list; track file) {\n
\n \n \n @switch (file.iconType) {\n @case ('uploading') {\n
\n \n
\n }\n @case ('thumbnail') {\n \n @if (file.isImageUrl) {\n \n } @else {\n
\n }\n \n }\n @default {\n
\n \n
\n }\n }\n \n\n \n @if (!iconRender) {\n @switch (listType) {\n @case ('picture') {\n @if (file.isUploading) {\n \n } @else {\n \n }\n }\n @case ('picture-card') {\n @if (file.isUploading) {\n {{ locale.uploading }}\n } @else {\n \n }\n }\n @default {\n \n }\n }\n } @else {\n \n }\n \n\n \n @if (icons.showRemoveIcon) {\n \n \n \n }\n \n\n \n @if (file.showDownload) {\n \n \n \n }\n \n\n \n @if (listType !== 'picture-card') {\n \n \n \n \n }\n \n\n \n @if (file.url) {\n \n {{ file.name }}\n \n } @else {\n \n {{ file.name }}\n \n }\n \n \n\n
\n \n \n \n \n
\n @if (listType === 'picture-card' && !file.isUploading) {\n \n @if (icons.showPreviewIcon) {\n \n \n \n }\n @if (file.status === 'done') {\n \n }\n \n \n }\n @if (file.isUploading) {\n
\n \n
\n }\n
\n \n}\n", dependencies: [{ kind: "ngmodule", type: NzTooltipModule }, { kind: "directive", type: i1.NzTooltipDirective, selector: "[nz-tooltip]", inputs: ["nzTooltipTitle", "nzTooltipTitleContext", "nz-tooltip", "nzTooltipTrigger", "nzTooltipPlacement", "nzTooltipOrigin", "nzTooltipVisible", "nzTooltipMouseEnterDelay", "nzTooltipMouseLeaveDelay", "nzTooltipOverlayClassName", "nzTooltipOverlayStyle", "nzTooltipArrowPointAtCenter", "cdkConnectedOverlayPush", "nzTooltipColor"], outputs: ["nzTooltipVisibleChange"], exportAs: ["nzTooltip"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i2.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i3.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i4.ɵNzTransitionPatchDirective, selector: "[nz-button], [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "ngmodule", type: NzProgressModule }, { kind: "component", type: i5.NzProgressComponent, selector: "nz-progress", inputs: ["nzShowInfo", "nzWidth", "nzStrokeColor", "nzSize", "nzFormat", "nzSuccessPercent", "nzPercent", "nzStrokeWidth", "nzGapDegree", "nzStatus", "nzType", "nzGapPosition", "nzStrokeLinecap", "nzSteps"], exportAs: ["nzProgress"] }], animations: [ trigger('itemState', [ transition(':enter', [ style({ height: '0', width: '0', opacity: 0 }), animate(150, style({ height: '*', width: '*', opacity: 1 })) ]), transition(':leave', [animate(150, style({ height: '0', width: '0', opacity: 0 }))]) ]) ], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadListComponent, decorators: [{ type: Component, args: [{ selector: 'nz-upload-list', exportAs: 'nzUploadList', animations: [ trigger('itemState', [ transition(':enter', [ style({ height: '0', width: '0', opacity: 0 }), animate(150, style({ height: '*', width: '*', opacity: 1 })) ]), transition(':leave', [animate(150, style({ height: '0', width: '0', opacity: 0 }))]) ]) ], host: { class: 'ant-upload-list', '[class.ant-upload-list-rtl]': `dir === 'rtl'`, '[class.ant-upload-list-text]': `listType === 'text'`, '[class.ant-upload-list-picture]': `listType === 'picture'`, '[class.ant-upload-list-picture-card]': `listType === 'picture-card'` }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NzTooltipModule, NgTemplateOutlet, NzIconModule, NzButtonModule, NzProgressModule], template: "@for (file of list; track file) {\n
\n \n \n @switch (file.iconType) {\n @case ('uploading') {\n
\n \n
\n }\n @case ('thumbnail') {\n \n @if (file.isImageUrl) {\n \n } @else {\n
\n }\n \n }\n @default {\n
\n \n
\n }\n }\n \n\n \n @if (!iconRender) {\n @switch (listType) {\n @case ('picture') {\n @if (file.isUploading) {\n \n } @else {\n \n }\n }\n @case ('picture-card') {\n @if (file.isUploading) {\n {{ locale.uploading }}\n } @else {\n \n }\n }\n @default {\n \n }\n }\n } @else {\n \n }\n \n\n \n @if (icons.showRemoveIcon) {\n \n \n \n }\n \n\n \n @if (file.showDownload) {\n \n \n \n }\n \n\n \n @if (listType !== 'picture-card') {\n \n \n \n \n }\n \n\n \n @if (file.url) {\n \n {{ file.name }}\n \n } @else {\n \n {{ file.name }}\n \n }\n \n \n\n
\n \n \n \n \n
\n @if (listType === 'picture-card' && !file.isUploading) {\n \n @if (icons.showPreviewIcon) {\n \n \n \n }\n @if (file.status === 'done') {\n \n }\n \n \n }\n @if (file.isUploading) {\n
\n \n
\n }\n
\n \n}\n" }] }], propDecorators: { locale: [{ type: Input }], listType: [{ type: Input }], items: [{ type: Input }], icons: [{ type: Input }], onPreview: [{ type: Input }], onRemove: [{ type: Input }], onDownload: [{ type: Input }], previewFile: [{ type: Input }], previewIsImage: [{ type: Input }], iconRender: [{ type: Input }], dir: [{ type: Input }] } }); /** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ class NzUploadComponent { static ngAcceptInputType_nzShowUploadList; cdr = inject(ChangeDetectorRef); i18n = inject(NzI18nService); directionality = inject(Directionality); destroyRef = inject(DestroyRef); uploadComp; listComp; locale; dir = 'ltr'; // #region fields nzType = 'select'; nzLimit = 0; nzSize = 0; nzFileType; nzAccept; nzAction; nzDirectory = false; nzOpenFileDialogOnClick = true; nzBeforeUpload; nzCustomRequest; nzData; nzFilter = []; nzFileList = []; nzDisabled = false; nzHeaders; nzListType = 'text'; nzMultiple = false; nzName = 'file'; _showUploadList = true; document = inject(DOCUMENT); set nzShowUploadList(value) { this._showUploadList = typeof value === 'boolean' ? toBoolean(value) : value; } get nzShowUploadList() { return this._showUploadList; } nzShowButton = true; nzWithCredentials = false; nzRemove; nzPreview; nzPreviewFile; nzPreviewIsImage; /** * @deprecated will be removed in v22.0.0 * Use `nzBeforeUpload` instead. */ nzTransformFile; nzDownload; nzIconRender = null; nzFileListRender = null; nzChange = new EventEmitter(); nzFileListChange = new EventEmitter(); _btnOptions; zipOptions() { if (typeof this.nzShowUploadList === 'boolean' && this.nzShowUploadList) { this.nzShowUploadList = { showPreviewIcon: true, showRemoveIcon: true, showDownloadIcon: true }; } // filters const filters = this.nzFilter.slice(); if (this.nzMultiple && this.nzLimit > 0 && filters.findIndex(w => w.name === 'limit') === -1) { filters.push({ name: 'limit', fn: (fileList) => fileList.slice(-this.nzLimit) }); } if (this.nzSize > 0 && filters.findIndex(w => w.name === 'size') === -1) { filters.push({ name: 'size', fn: (fileList) => fileList.filter(w => w.size / 1024 <= this.nzSize) }); } if (this.nzFileType && this.nzFileType.length > 0 && filters.findIndex(w => w.name === 'type') === -1) { const types = this.nzFileType.split(','); filters.push({ name: 'type', fn: (fileList) => fileList.filter(w => ~types.indexOf(w.type)) }); } this._btnOptions = { disabled: this.nzDisabled, accept: this.nzAccept, action: this.nzAction, directory: this.nzDirectory, openFileDialogOnClick: this.nzOpenFileDialogOnClick, beforeUpload: this.nzBeforeUpload, customRequest: this.nzCustomRequest, data: this.nzData, headers: this.nzHeaders, name: this.nzName, multiple: this.nzMultiple, withCredentials: this.nzWithCredentials, filters, transformFile: this.nzTransformFile, onStart: this.onStart, onProgress: this.onProgress, onSuccess: this.onSuccess, onError: this.onError }; return this; } platform = inject(Platform); // #endregion // #region upload fileToObject(file) { return { lastModified: file.lastModified, lastModifiedDate: file.lastModifiedDate, name: file.filename || file.name, size: file.size, type: file.type, uid: file.uid, response: file.response, error: file.error, percent: 0, originFileObj: file }; } getFileItem(file, fileList) { return fileList.filter(item => item.uid === file.uid)[0]; } removeFileItem(file, fileList) { return fileList.filter(item => item.uid !== file.uid); } onStart = (file) => { if (!this.nzFileList) { this.nzFileList = []; } const targetItem = this.fileToObject(file); targetItem.status = 'uploading'; this.nzFileList = this.nzFileList.concat(targetItem); this.nzFileListChange.emit(this.nzFileList); this.nzChange.emit({ file: targetItem, fileList: this.nzFileList, type: 'start' }); this.detectChangesList(); }; onProgress = (e, file) => { const fileList = this.nzFileList; const targetItem = this.getFileItem(file, fileList); targetItem.percent = e.percent; this.nzChange.emit({ event: e, file: { ...targetItem }, fileList: this.nzFileList, type: 'progress' }); this.detectChangesList(); }; onSuccess = (res, file) => { const fileList = this.nzFileList; const targetItem = this.getFileItem(file, fileList); targetItem.status = 'done'; targetItem.response = res; this.nzChange.emit({ file: { ...targetItem }, fileList, type: 'success' }); this.detectChangesList(); }; onError = (err, file) => { const fileList = this.nzFileList; const targetItem = this.getFileItem(file, fileList); targetItem.error = err; targetItem.status = 'error'; this.nzChange.emit({ file: { ...targetItem }, fileList, type: 'error' }); this.detectChangesList(); }; // #endregion // #region drag dragState; // skip safari bug fileDrop(e) { if (e.type === this.dragState) { return; } this.dragState = e.type; this.setClassMap(); } // #endregion // #region list detectChangesList() { this.cdr.detectChanges(); this.listComp?.detectChanges(); } onRemove = (file) => { this.uploadComp.abort(file); file.status = 'removed'; const fnRes = typeof this.nzRemove === 'function' ? this.nzRemove(file) : this.nzRemove == null ? true : this.nzRemove; (fnRes instanceof Observable ? fnRes : of(fnRes)).pipe(filter((res) => res)).subscribe(() => { this.nzFileList = this.removeFileItem(file, this.nzFileList); this.nzChange.emit({ file, fileList: this.nzFileList, type: 'removed' }); this.nzFileListChange.emit(this.nzFileList); this.cdr.detectChanges(); }); }; // #endregion // #region styles prefixCls = 'ant-upload'; classList = []; setClassMap() { let subCls = []; if (this.nzType === 'drag') { if (this.nzFileList.some(file => file.status === 'uploading')) { subCls.push(`${this.prefixCls}-drag-uploading`); } if (this.dragState === 'dragover') { subCls.push(`${this.prefixCls}-drag-hover`); } } else { subCls = [`${this.prefixCls}-select-${this.nzListType}`]; } this.classList = [ this.prefixCls, `${this.prefixCls}-${this.nzType}`, ...subCls, (this.nzDisabled && `${this.prefixCls}-disabled`) || '', (this.dir === 'rtl' && `${this.prefixCls}-rtl`) || '' ].filter(item => !!item); this.cdr.detectChanges(); } // #endregion ngOnInit() { this.dir = this.directionality.value; this.directionality.change?.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(direction => { this.dir = direction; this.setClassMap(); this.cdr.detectChanges(); }); this.i18n.localeChange.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.locale = this.i18n.getLocaleData('Upload'); this.detectChangesList(); }); } ngAfterViewInit() { if (this.platform.FIREFOX) { // fix firefox drop open new tab fromEventOutsideAngular(this.document.body, 'drop') .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(event => { event.preventDefault(); event.stopPropagation(); }); } } ngOnChanges() { this.zipOptions().setClassMap(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.0", type: NzUploadComponent, isStandalone: true, selector: "nz-upload", inputs: { nzType: "nzType", nzLimit: ["nzLimit", "nzLimit", numberAttribute], nzSize: ["nzSize", "nzSize", numberAttribute], nzFileType: "nzFileType", nzAccept: "nzAccept", nzAction: "nzAction", nzDirectory: ["nzDirectory", "nzDirectory", booleanAttribute], nzOpenFileDialogOnClick: ["nzOpenFileDialogOnClick", "nzOpenFileDialogOnClick", booleanAttribute], nzBeforeUpload: "nzBeforeUpload", nzCustomRequest: "nzCustomRequest", nzData: "nzData", nzFilter: "nzFilter", nzFileList: "nzFileList", nzDisabled: ["nzDisabled", "nzDisabled", booleanAttribute], nzHeaders: "nzHeaders", nzListType: "nzListType", nzMultiple: ["nzMultiple", "nzMultiple", booleanAttribute], nzName: "nzName", nzShowUploadList: "nzShowUploadList", nzShowButton: ["nzShowButton", "nzShowButton", booleanAttribute], nzWithCredentials: ["nzWithCredentials", "nzWithCredentials", booleanAttribute], nzRemove: "nzRemove", nzPreview: "nzPreview", nzPreviewFile: "nzPreviewFile", nzPreviewIsImage: "nzPreviewIsImage", nzTransformFile: "nzTransformFile", nzDownload: "nzDownload", nzIconRender: "nzIconRender", nzFileListRender: "nzFileListRender" }, outputs: { nzChange: "nzChange", nzFileListChange: "nzFileListChange" }, host: { properties: { "class.ant-upload-picture-card-wrapper": "nzListType === \"picture-card\"" } }, viewQueries: [{ propertyName: "uploadComp", first: true, predicate: ["uploadComp"], descendants: true }, { propertyName: "listComp", first: true, predicate: ["listComp"], descendants: true }], exportAs: ["nzUpload"], usesOnChanges: true, ngImport: i0, template: "\n @if (locale && !nzFileListRender) {\n \n }\n @if (nzFileListRender) {\n \n }\n\n\n\n
\n
\n \n
\n
\n
\n@if (nzType === 'drag') {\n
\n
\n
\n \n
\n
\n
\n \n} @else {\n @if (nzListType === 'picture-card') {\n \n \n } @else {\n \n \n }\n}\n", dependencies: [{ kind: "component", type: NzUploadListComponent, selector: "nz-upload-list", inputs: ["locale", "listType", "items", "icons", "onPreview", "onRemove", "onDownload", "previewFile", "previewIsImage", "iconRender", "dir"], exportAs: ["nzUploadList"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NzUploadBtnComponent, selector: "[nz-upload-btn]", inputs: ["options"], exportAs: ["nzUploadBtn"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadComponent, decorators: [{ type: Component, args: [{ selector: 'nz-upload', exportAs: 'nzUpload', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class.ant-upload-picture-card-wrapper]': 'nzListType === "picture-card"' }, imports: [NzUploadListComponent, NgTemplateOutlet, NzUploadBtnComponent], template: "\n @if (locale && !nzFileListRender) {\n \n }\n @if (nzFileListRender) {\n \n }\n\n\n\n
\n
\n \n
\n
\n
\n@if (nzType === 'drag') {\n
\n
\n
\n \n
\n
\n
\n \n} @else {\n @if (nzListType === 'picture-card') {\n \n \n } @else {\n \n \n }\n}\n" }] }], propDecorators: { uploadComp: [{ type: ViewChild, args: ['uploadComp', { static: false }] }], listComp: [{ type: ViewChild, args: ['listComp', { static: false }] }], nzType: [{ type: Input }], nzLimit: [{ type: Input, args: [{ transform: numberAttribute }] }], nzSize: [{ type: Input, args: [{ transform: numberAttribute }] }], nzFileType: [{ type: Input }], nzAccept: [{ type: Input }], nzAction: [{ type: Input }], nzDirectory: [{ type: Input, args: [{ transform: booleanAttribute }] }], nzOpenFileDialogOnClick: [{ type: Input, args: [{ transform: booleanAttribute }] }], nzBeforeUpload: [{ type: Input }], nzCustomRequest: [{ type: Input }], nzData: [{ type: Input }], nzFilter: [{ type: Input }], nzFileList: [{ type: Input }], nzDisabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], nzHeaders: [{ type: Input }], nzListType: [{ type: Input }], nzMultiple: [{ type: Input, args: [{ transform: booleanAttribute }] }], nzName: [{ type: Input }], nzShowUploadList: [{ type: Input }], nzShowButton: [{ type: Input, args: [{ transform: booleanAttribute }] }], nzWithCredentials: [{ type: Input, args: [{ transform: booleanAttribute }] }], nzRemove: [{ type: Input }], nzPreview: [{ type: Input }], nzPreviewFile: [{ type: Input }], nzPreviewIsImage: [{ type: Input }], nzTransformFile: [{ type: Input }], nzDownload: [{ type: Input }], nzIconRender: [{ type: Input }], nzFileListRender: [{ type: Input }], nzChange: [{ type: Output }], nzFileListChange: [{ type: Output }] } }); /** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ class NzUploadModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.0", ngImport: i0, type: NzUploadModule, imports: [NzUploadComponent, NzUploadBtnComponent, NzUploadListComponent], exports: [NzUploadComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadModule, imports: [NzUploadComponent, NzUploadListComponent] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: NzUploadModule, decorators: [{ type: NgModule, args: [{ imports: [NzUploadComponent, NzUploadBtnComponent, NzUploadListComponent], exports: [NzUploadComponent] }] }] }); /** * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE */ /** * Generated bundle index. Do not edit. */ export { NzUploadBtnComponent, NzUploadComponent, NzUploadListComponent, NzUploadModule }; //# sourceMappingURL=ng-zorro-antd-upload.mjs.map