@stemy/ngx-utils 19.1.3 → 19.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { InjectionToken, PLATFORM_ID, Injectable, Inject, Optional, Injector, Ev
3
3
  import 'reflect-metadata';
4
4
  import * as i2 from '@angular/router';
5
5
  import { ActivatedRouteSnapshot, Scroll, NavigationEnd, DefaultUrlSerializer, UrlTree, UrlSegmentGroup, UrlSegment, UrlSerializer } from '@angular/router';
6
- import { BehaviorSubject, Observable, firstValueFrom, Subject, Subscription, from, TimeoutError, combineLatest } from 'rxjs';
6
+ import { BehaviorSubject, Observable, firstValueFrom, Subject, Subscription, from, TimeoutError, combineLatest, lastValueFrom } from 'rxjs';
7
7
  import { skipWhile, debounceTime, distinctUntilChanged, map, filter, mergeMap, timeout } from 'rxjs/operators';
8
8
  import * as i1$3 from '@angular/common';
9
9
  import { isPlatformBrowser, isPlatformServer, DOCUMENT, APP_BASE_HREF, CommonModule } from '@angular/common';
@@ -505,7 +505,7 @@ class AjaxRequestHandler {
505
505
  if (typeof XMLHttpRequest !== "undefined" && !AjaxRequestHandler.isOverridden) {
506
506
  AjaxRequestHandler.isOverridden = true;
507
507
  const originalOpen = XMLHttpRequest.prototype.open;
508
- XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
508
+ XMLHttpRequest.prototype.open = function (method, url) {
509
509
  originalOpen.apply(this, arguments);
510
510
  window.dispatchEvent(new CustomEvent("ajaxRequest", {
511
511
  detail: {
@@ -1589,6 +1589,54 @@ class FileUtils {
1589
1589
  }));
1590
1590
  return FileUtils.readFileAsDataURL(blob);
1591
1591
  }
1592
+ static getVideoCover(file, seekTo = null, quality = .75) {
1593
+ return new Promise((resolve, reject) => {
1594
+ // load the file to a video player
1595
+ const videoPlayer = document.createElement("video");
1596
+ videoPlayer.setAttribute("src", URL.createObjectURL(file));
1597
+ videoPlayer.load();
1598
+ videoPlayer.addEventListener("error", (ex) => {
1599
+ reject("error when loading video file");
1600
+ });
1601
+ // load metadata of the video to get video duration and dimensions
1602
+ videoPlayer.addEventListener("loadedmetadata", () => {
1603
+ if (isNaN(seekTo)) {
1604
+ seekTo = videoPlayer.duration / 2;
1605
+ }
1606
+ // seek to user defined timestamp (in seconds) if possible
1607
+ if (videoPlayer.duration < seekTo) {
1608
+ reject("video is too short.");
1609
+ return;
1610
+ }
1611
+ // delay seeking or else "seeked" event won"t fire on Safari
1612
+ setTimeout(() => {
1613
+ videoPlayer.currentTime = seekTo;
1614
+ }, 200);
1615
+ // extract video thumbnail once seeking is complete
1616
+ videoPlayer.addEventListener("seeked", () => {
1617
+ // define a canvas to have the same dimension as the video
1618
+ const canvas = document.createElement("canvas");
1619
+ canvas.width = videoPlayer.videoWidth;
1620
+ canvas.height = videoPlayer.videoHeight;
1621
+ // draw the video frame to canvas
1622
+ const ctx = canvas.getContext("2d");
1623
+ ctx.drawImage(videoPlayer, 0, 0, canvas.width, canvas.height);
1624
+ // return the canvas image as a blob
1625
+ resolve(ctx.canvas.toDataURL("image/jpeg", quality));
1626
+ });
1627
+ });
1628
+ });
1629
+ }
1630
+ static async getFilePreview(file) {
1631
+ const type = file.type.toLowerCase();
1632
+ if (type.startsWith("image/")) {
1633
+ return URL.createObjectURL(file);
1634
+ }
1635
+ if (type.startsWith("video/")) {
1636
+ return FileUtils.getVideoCover(file);
1637
+ }
1638
+ return null;
1639
+ }
1592
1640
  static readFile(callback) {
1593
1641
  return new Promise(
1594
1642
  // @dynamic
@@ -3809,7 +3857,6 @@ class DragDropHandler {
3809
3857
  this.dropEffect = ev.dataTransfer.dropEffect;
3810
3858
  };
3811
3859
  this.onDragEnter = ev => {
3812
- ev.preventDefault();
3813
3860
  if (this.first) {
3814
3861
  this.second = true;
3815
3862
  }
@@ -3837,7 +3884,6 @@ class DragDropHandler {
3837
3884
  }
3838
3885
  };
3839
3886
  this.onDrop = ev => {
3840
- ev.preventDefault();
3841
3887
  this.first = false;
3842
3888
  this.second = false;
3843
3889
  this.fireEvent("drop", ev);
@@ -5389,12 +5435,14 @@ class DropListComponent {
5389
5435
  this.context = [];
5390
5436
  this.prepareItem = () => { };
5391
5437
  this.checkFn = () => false;
5438
+ this.dropFn = () => false;
5392
5439
  this.valueMap = {};
5393
5440
  this.remove = index => {
5394
5441
  this.changeValue(this.value.filter((_, i) => i !== index));
5395
5442
  };
5396
5443
  }
5397
5444
  onDragEnter(ev, elem, data) {
5445
+ ev.preventDefault();
5398
5446
  if (!elem || !ObjectUtils.isFunction(this.checkFn) || !this.checkFn({ ev, elem, data })) {
5399
5447
  ev.dataTransfer.effectAllowed = "none";
5400
5448
  ev.dataTransfer.dropEffect = "none";
@@ -5415,11 +5463,15 @@ class DropListComponent {
5415
5463
  if (!elem) {
5416
5464
  return;
5417
5465
  }
5418
- const source = JSON.parse(ev.dataTransfer.getData("itemData"));
5466
+ const data = JSON.parse(ev.dataTransfer.getData("itemData") || "{}");
5419
5467
  elem.classList.remove("drop-allowed");
5420
5468
  checkTransitions(elem, () => {
5421
5469
  checkTransitions(elem, () => {
5422
- const id = source[this.idField] || source.id;
5470
+ if (elem && ObjectUtils.isFunction(this.dropFn) && this.dropFn({ ev, elem, data })) {
5471
+ // If drop is handled from outside function
5472
+ return;
5473
+ }
5474
+ const id = data[this.idField] || data.id;
5423
5475
  this.changeValue(this.value.concat([id]));
5424
5476
  });
5425
5477
  elem.classList.remove("dropped");
@@ -5460,7 +5512,7 @@ class DropListComponent {
5460
5512
  this.onTouched?.();
5461
5513
  }
5462
5514
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: DropListComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
5463
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: DropListComponent, isStandalone: false, selector: "drop-list", inputs: { disabled: "disabled", unique: "unique", idField: "idField", labelField: "labelField", value: "value", context: "context", prepareItem: "prepareItem", checkFn: "checkFn" }, providers: [{
5515
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: DropListComponent, isStandalone: false, selector: "drop-list", inputs: { disabled: "disabled", unique: "unique", idField: "idField", labelField: "labelField", value: "value", context: "context", prepareItem: "prepareItem", checkFn: "checkFn", dropFn: "dropFn" }, providers: [{
5464
5516
  provide: NG_VALUE_ACCESSOR,
5465
5517
  useExisting: forwardRef(() => DropListComponent),
5466
5518
  multi: true,
@@ -5489,6 +5541,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
5489
5541
  type: Input
5490
5542
  }], checkFn: [{
5491
5543
  type: Input
5544
+ }], dropFn: [{
5545
+ type: Input
5492
5546
  }], itemTemplate: [{
5493
5547
  type: ContentChild,
5494
5548
  args: ["itemTemplate"]
@@ -5670,6 +5724,7 @@ class DynamicTableComponent {
5670
5724
  ev.dataTransfer.setData(item.id, "id");
5671
5725
  }
5672
5726
  onDragEnter(ev, elem, item) {
5727
+ ev.preventDefault();
5673
5728
  if (!elem || !item || !ObjectUtils.isFunction(this.dragEnterFn) || !this.dragEnterFn({ ev, elem, item })) {
5674
5729
  ev.dataTransfer.effectAllowed = "none";
5675
5730
  ev.dataTransfer.dropEffect = "none";
@@ -5895,6 +5950,228 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
5895
5950
  args: ["defaultItemTemplate"]
5896
5951
  }] } });
5897
5952
 
5953
+ class UploadComponent {
5954
+ get http() {
5955
+ return this.api.client;
5956
+ }
5957
+ constructor(cdr, api, toaster) {
5958
+ this.cdr = cdr;
5959
+ this.api = api;
5960
+ this.toaster = toaster;
5961
+ this.value = null;
5962
+ this.disabled = false;
5963
+ this.fileImageCache = [];
5964
+ this.buttonText = "button.select-files";
5965
+ this.onUploaded = new EventEmitter();
5966
+ this.onRemove = new EventEmitter();
5967
+ this.onChange = () => {
5968
+ };
5969
+ this.onTouched = () => {
5970
+ };
5971
+ }
5972
+ onDragEnter(ev) {
5973
+ const types = Array.from(ev.dataTransfer.items || [])
5974
+ .filter(t => t.kind == "file")
5975
+ .map(t => t.type.toLowerCase());
5976
+ types.push(...Array.from(ev.dataTransfer.files || []).map(f => f.type.toLowerCase()));
5977
+ if (!types.some(type => ArrayUtils.has(this.acceptTypes, type))) {
5978
+ ev.preventDefault();
5979
+ return;
5980
+ }
5981
+ ev.dataTransfer.effectAllowed = "copy";
5982
+ ev.dataTransfer.dropEffect = "copy";
5983
+ this.dropAllowed = true;
5984
+ }
5985
+ onDrop() {
5986
+ this.dropAllowed = false;
5987
+ }
5988
+ ngOnChanges() {
5989
+ this.accept = this.accept || "";
5990
+ this.acceptAttr = ObjectUtils.isString(this.accept) ? this.accept : this.accept.join(",");
5991
+ this.acceptTypes = ObjectUtils.isString(this.accept) && this.accept.length > 0
5992
+ ? this.accept.toLowerCase().split(",")
5993
+ : (ObjectUtils.isArray(this.accept) ? this.accept : []);
5994
+ this.isImage = /(png|jpg|jpeg|webp|gif)/gi.test(this.acceptAttr);
5995
+ this.cdr.markForCheck();
5996
+ }
5997
+ registerOnChange(fn) {
5998
+ this.onChange = fn;
5999
+ }
6000
+ registerOnTouched(fn) {
6001
+ this.onTouched = fn;
6002
+ }
6003
+ writeValue(value) {
6004
+ this.value = value;
6005
+ this.cdr.markForCheck();
6006
+ this.onChange(this.value);
6007
+ this.onTouched(this.value);
6008
+ }
6009
+ setDisabledState(val) {
6010
+ this.disabled = val === true;
6011
+ this.cdr.markForCheck();
6012
+ }
6013
+ onInputClick(ev) {
6014
+ const top = document.elementFromPoint(ev.clientX, ev.clientY);
6015
+ if (ev.target !== top && !this.processing)
6016
+ return;
6017
+ ev.preventDefault();
6018
+ }
6019
+ onInputChange(ev) {
6020
+ const input = ev.currentTarget;
6021
+ if (this.processing) {
6022
+ input.value = "";
6023
+ return;
6024
+ }
6025
+ const length = input.files.length;
6026
+ if (length == 0) {
6027
+ this.writeValue(this.multiple ? [] : null);
6028
+ return;
6029
+ }
6030
+ const files = [];
6031
+ for (let i = 0; i < length; i++) {
6032
+ const file = input.files.item(i);
6033
+ if (this.acceptTypes.length == 0) {
6034
+ files.push(file);
6035
+ continue;
6036
+ }
6037
+ const type = file.type.toLowerCase();
6038
+ const ext = FileUtils.getExtension(file);
6039
+ if (!ArrayUtils.has(this.acceptTypes, type, ext))
6040
+ continue;
6041
+ files.push(file);
6042
+ }
6043
+ if (files.length == 0) {
6044
+ this.toaster.error("message.invalid-files.error");
6045
+ return;
6046
+ }
6047
+ this.processFiles(this.multiple ? files : files.slice(0, 1)).then(results => {
6048
+ const ids = results.map(t => t._id || t.id);
6049
+ this.writeValue(this.multiple ? ids : (ids[0] || null));
6050
+ this.onUploaded.emit(results);
6051
+ });
6052
+ input.value = "";
6053
+ }
6054
+ getUrl(image) {
6055
+ if (ObjectUtils.isBlob(image)) {
6056
+ let cache = this.fileImageCache.find(t => t.file == image);
6057
+ if (!cache) {
6058
+ cache = { file: image, url: URL.createObjectURL(image) };
6059
+ this.fileImageCache.push(cache);
6060
+ }
6061
+ return cache.url;
6062
+ }
6063
+ const url = !image ? null : image.imageUrl || image;
6064
+ if (!ObjectUtils.isString(url))
6065
+ return null;
6066
+ if (url.startsWith("data:"))
6067
+ return url;
6068
+ const baseUrl = this.baseUrl;
6069
+ const images = this.isImage ? `image/` : ``;
6070
+ if (!baseUrl) {
6071
+ return `${images}${url}`;
6072
+ }
6073
+ return `${baseUrl}/${images}${url}`;
6074
+ }
6075
+ async processFiles(files) {
6076
+ if (this.processing)
6077
+ return null;
6078
+ const headers = this.http.makeHeaders();
6079
+ const makeUpload = ObjectUtils.isFunction(this.makeUpload) ? this.makeUpload : f => {
6080
+ const form = new FormData();
6081
+ form.append("file", f);
6082
+ return form;
6083
+ };
6084
+ const preProcess = ObjectUtils.isFunction(this.preProcess) ? this.preProcess : () => {
6085
+ return false;
6086
+ };
6087
+ this.processing = files.filter(f => !preProcess(f)).map(file => {
6088
+ const process = {
6089
+ file,
6090
+ progress: 0
6091
+ };
6092
+ process.promise = FileUtils.getFilePreview(file).then(preview => {
6093
+ process.preview = `url('${preview}')`;
6094
+ this.cdr.detectChanges();
6095
+ });
6096
+ return process;
6097
+ });
6098
+ const baseUrl = this.baseUrl || this.api.url("assets");
6099
+ const requests = this.processing.map(async (p) => {
6100
+ await p.promise;
6101
+ const request = this.http.post(baseUrl, makeUpload(p.file), {
6102
+ headers, observe: "events", reportProgress: true
6103
+ });
6104
+ request.subscribe(value => {
6105
+ if (value.type === HttpEventType.UploadProgress) {
6106
+ p.progress = Math.round(value.loaded / value.total * 100);
6107
+ this.cdr.detectChanges();
6108
+ }
6109
+ });
6110
+ return lastValueFrom(request)
6111
+ .then((res) => {
6112
+ const body = res.body;
6113
+ if (!ObjectUtils.isObject(body)) {
6114
+ return { id: body };
6115
+ }
6116
+ return body;
6117
+ }, (e) => {
6118
+ this.toaster.error(e.error?.message || e.message || `Can"t upload file: ${p.file.name}`);
6119
+ return null;
6120
+ });
6121
+ });
6122
+ const results = await Promise.all(requests);
6123
+ this.processing = null;
6124
+ this.cdr.detectChanges();
6125
+ return results.filter(r => r !== null);
6126
+ }
6127
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: UploadComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: API_SERVICE }, { token: TOASTER_SERVICE }], target: i0.ɵɵFactoryTarget.Component }); }
6128
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: UploadComponent, isStandalone: false, selector: "upload", inputs: { value: "value", disabled: "disabled", accept: "accept", baseUrl: "baseUrl", multiple: "multiple", buttonText: "buttonText", makeUpload: "makeUpload", preProcess: "preProcess" }, outputs: { onUploaded: "onUploaded", onRemove: "onRemove" }, providers: [{
6129
+ provide: NG_VALUE_ACCESSOR,
6130
+ useExisting: forwardRef(() => UploadComponent),
6131
+ multi: true,
6132
+ }], queries: [{ propertyName: "uploadButton", first: true, predicate: ["uploadButton"], descendants: true }, { propertyName: "removeButton", first: true, predicate: ["removeButton"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-template #defaultUploadBtn let-loading=\"loading\">\r\n <a class=\"btn btn-primary\" [ngClass]=\"{loading: loading}\">\r\n {{ buttonText | translate }}\r\n </a>\r\n</ng-template>\r\n<ng-template #defaultRemoveBtn let-remove=\"remove\" let-index=\"index\">\r\n <a class=\"btn btn-danger btn-delete\" (click)=\"remove(index)\">\r\n x\r\n </a>\r\n</ng-template>\r\n\r\n<div class=\"upload\">\r\n <div class=\"upload-input\" [ngClass]=\"{'drop-allowed': dropAllowed}\">\r\n <input type=\"file\"\r\n #input\r\n [multiple]=\"multiple\"\r\n [accept]=\"acceptAttr\"\r\n (dragenter)=\"onDragEnter($event)\"\r\n (dragleave)=\"onDrop()\"\r\n (drop)=\"onDrop()\"\r\n (click)=\"onInputClick($event)\"\r\n (blur)=\"onTouched($event)\"\r\n (change)=\"onInputChange($event)\"/>\r\n <div class=\"process-container\">\r\n <div class=\"upload-process\"\r\n [ngStyle]=\"!proc.preview ? {} : {backgroundImage: proc.preview}\"\r\n *ngFor=\"let proc of processing\">\r\n <div class=\"upload-progress\">\r\n <div class=\"upload-progress-num\">{{ proc.progress }}%</div>\r\n <div class=\"upload-progress-bar\" [ngStyle]=\"{width: proc.progress + '%'}\">\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"btn-container\" (click)=\"input.click()\">\r\n <ng-container [ngTemplateOutlet]=\"uploadButton || defaultUploadBtn\"\r\n [ngTemplateOutletContext]=\"{loading: !!processing, buttonText: buttonText}\">\r\n </ng-container>\r\n </div>\r\n </div>\r\n <ng-template #defaultTemplate>\r\n <ul class=\"files\" *ngIf=\"!multiple\">\r\n <li class=\"file\" *ngIf=\"value\">\r\n <a [href]=\"getUrl(value) | safe: 'url'\" target=\"target\">\r\n <i class=\"fas fa-download\">download</i>\r\n </a>\r\n <ng-container [ngTemplateOutlet]=\"removeButton || defaultRemoveBtn\"\r\n [ngTemplateOutletContext]=\"{remove: remove}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n <ul class=\"files\" *ngIf=\"multiple\">\r\n <li class=\"file\" *ngFor=\"let file of value; let i = index\">\r\n <a [href]=\"getUrl(file) | safe: 'url'\" [target]=\"'target_' + i\">\r\n <i class=\"fas fa-download\"></i>\r\n </a>\r\n <a class=\"btn btn-danger btn-delete\" (click)=\"remove(i)\">x</a>\r\n </li>\r\n </ul>\r\n </ng-template>\r\n <ng-container *ngIf=\"isImage; else defaultTemplate\">\r\n <ul class=\"images\" *ngIf=\"!multiple\">\r\n <li class=\"image\" *ngIf=\"value\">\r\n <img alt=\"file image\" [src]=\"getUrl(value) | safe: 'url'\"/>\r\n <ng-container [ngTemplateOutlet]=\"removeButton || defaultRemoveBtn\"\r\n [ngTemplateOutletContext]=\"{remove: remove}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n <ul class=\"images\" *ngIf=\"multiple\">\r\n <li class=\"image\" *ngFor=\"let image of value; let ix = index\">\r\n <img alt=\"file image\" [src]=\"getUrl(image) | safe: 'url'\"/>\r\n <ng-container [ngTemplateOutlet]=\"removeButton || defaultRemoveBtn\"\r\n [ngTemplateOutletContext]=\"{remove: remove, index: ix}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n </ng-container>\r\n</div>\r\n", styles: [".upload{--background: var(--primary-color, var(--mat-sys-primary, black));--text: var(--text-color, var(--mat-sys-on-primary, white))}.upload .upload-input{width:100%;border:2px #bfbfbf dashed;border-radius:10px;background-color:#0000000d;transition:.2s;flex-wrap:wrap;position:relative;padding:0 10px 10px}.upload .upload-input.drop-allowed{background-color:#00000080;border-color:#a9a9a9}.upload .upload-input input{display:block;position:absolute;inset:0;opacity:0}.upload .upload-input .process-container{min-height:120px;display:flex;gap:10px;flex-wrap:wrap;margin-bottom:8px}.upload .upload-input .upload-process{margin-top:10px;width:120px;height:120px;background:#00000080 center center no-repeat;background-size:cover;display:flex;align-items:center;justify-content:center}.upload .upload-input .upload-progress{position:relative;width:90%;height:15px;border:1px solid darkgrey;background:#ffffff80}.upload .upload-input .upload-progress-bar{position:absolute;height:15px;background:var(--background);top:0}.upload .upload-input .upload-progress-num{position:relative;z-index:1;font-size:12px;line-height:15px;text-align:center;color:var(--text)}.upload .images,.upload .files{list-style-type:none;margin:10px 0;padding:0;display:flex;gap:5px}.upload .images li,.upload .files li{position:relative}.upload .images li a,.upload .files li a{position:absolute;right:8px;top:8px}.upload .images img,.upload .files img{max-width:100%;max-height:200px;margin:2px;border-radius:5px}.upload .btn-select{display:inline-block;position:relative;cursor:pointer}.upload .btn-select button{display:inline-block;position:relative;z-index:1}\n"], dependencies: [{ kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safe" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
6133
+ }
6134
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: UploadComponent, decorators: [{
6135
+ type: Component,
6136
+ args: [{ standalone: false, selector: "upload", encapsulation: ViewEncapsulation.None, providers: [{
6137
+ provide: NG_VALUE_ACCESSOR,
6138
+ useExisting: forwardRef(() => UploadComponent),
6139
+ multi: true,
6140
+ }], template: "<ng-template #defaultUploadBtn let-loading=\"loading\">\r\n <a class=\"btn btn-primary\" [ngClass]=\"{loading: loading}\">\r\n {{ buttonText | translate }}\r\n </a>\r\n</ng-template>\r\n<ng-template #defaultRemoveBtn let-remove=\"remove\" let-index=\"index\">\r\n <a class=\"btn btn-danger btn-delete\" (click)=\"remove(index)\">\r\n x\r\n </a>\r\n</ng-template>\r\n\r\n<div class=\"upload\">\r\n <div class=\"upload-input\" [ngClass]=\"{'drop-allowed': dropAllowed}\">\r\n <input type=\"file\"\r\n #input\r\n [multiple]=\"multiple\"\r\n [accept]=\"acceptAttr\"\r\n (dragenter)=\"onDragEnter($event)\"\r\n (dragleave)=\"onDrop()\"\r\n (drop)=\"onDrop()\"\r\n (click)=\"onInputClick($event)\"\r\n (blur)=\"onTouched($event)\"\r\n (change)=\"onInputChange($event)\"/>\r\n <div class=\"process-container\">\r\n <div class=\"upload-process\"\r\n [ngStyle]=\"!proc.preview ? {} : {backgroundImage: proc.preview}\"\r\n *ngFor=\"let proc of processing\">\r\n <div class=\"upload-progress\">\r\n <div class=\"upload-progress-num\">{{ proc.progress }}%</div>\r\n <div class=\"upload-progress-bar\" [ngStyle]=\"{width: proc.progress + '%'}\">\r\n\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"btn-container\" (click)=\"input.click()\">\r\n <ng-container [ngTemplateOutlet]=\"uploadButton || defaultUploadBtn\"\r\n [ngTemplateOutletContext]=\"{loading: !!processing, buttonText: buttonText}\">\r\n </ng-container>\r\n </div>\r\n </div>\r\n <ng-template #defaultTemplate>\r\n <ul class=\"files\" *ngIf=\"!multiple\">\r\n <li class=\"file\" *ngIf=\"value\">\r\n <a [href]=\"getUrl(value) | safe: 'url'\" target=\"target\">\r\n <i class=\"fas fa-download\">download</i>\r\n </a>\r\n <ng-container [ngTemplateOutlet]=\"removeButton || defaultRemoveBtn\"\r\n [ngTemplateOutletContext]=\"{remove: remove}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n <ul class=\"files\" *ngIf=\"multiple\">\r\n <li class=\"file\" *ngFor=\"let file of value; let i = index\">\r\n <a [href]=\"getUrl(file) | safe: 'url'\" [target]=\"'target_' + i\">\r\n <i class=\"fas fa-download\"></i>\r\n </a>\r\n <a class=\"btn btn-danger btn-delete\" (click)=\"remove(i)\">x</a>\r\n </li>\r\n </ul>\r\n </ng-template>\r\n <ng-container *ngIf=\"isImage; else defaultTemplate\">\r\n <ul class=\"images\" *ngIf=\"!multiple\">\r\n <li class=\"image\" *ngIf=\"value\">\r\n <img alt=\"file image\" [src]=\"getUrl(value) | safe: 'url'\"/>\r\n <ng-container [ngTemplateOutlet]=\"removeButton || defaultRemoveBtn\"\r\n [ngTemplateOutletContext]=\"{remove: remove}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n <ul class=\"images\" *ngIf=\"multiple\">\r\n <li class=\"image\" *ngFor=\"let image of value; let ix = index\">\r\n <img alt=\"file image\" [src]=\"getUrl(image) | safe: 'url'\"/>\r\n <ng-container [ngTemplateOutlet]=\"removeButton || defaultRemoveBtn\"\r\n [ngTemplateOutletContext]=\"{remove: remove, index: ix}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n </ng-container>\r\n</div>\r\n", styles: [".upload{--background: var(--primary-color, var(--mat-sys-primary, black));--text: var(--text-color, var(--mat-sys-on-primary, white))}.upload .upload-input{width:100%;border:2px #bfbfbf dashed;border-radius:10px;background-color:#0000000d;transition:.2s;flex-wrap:wrap;position:relative;padding:0 10px 10px}.upload .upload-input.drop-allowed{background-color:#00000080;border-color:#a9a9a9}.upload .upload-input input{display:block;position:absolute;inset:0;opacity:0}.upload .upload-input .process-container{min-height:120px;display:flex;gap:10px;flex-wrap:wrap;margin-bottom:8px}.upload .upload-input .upload-process{margin-top:10px;width:120px;height:120px;background:#00000080 center center no-repeat;background-size:cover;display:flex;align-items:center;justify-content:center}.upload .upload-input .upload-progress{position:relative;width:90%;height:15px;border:1px solid darkgrey;background:#ffffff80}.upload .upload-input .upload-progress-bar{position:absolute;height:15px;background:var(--background);top:0}.upload .upload-input .upload-progress-num{position:relative;z-index:1;font-size:12px;line-height:15px;text-align:center;color:var(--text)}.upload .images,.upload .files{list-style-type:none;margin:10px 0;padding:0;display:flex;gap:5px}.upload .images li,.upload .files li{position:relative}.upload .images li a,.upload .files li a{position:absolute;right:8px;top:8px}.upload .images img,.upload .files img{max-width:100%;max-height:200px;margin:2px;border-radius:5px}.upload .btn-select{display:inline-block;position:relative;cursor:pointer}.upload .btn-select button{display:inline-block;position:relative;z-index:1}\n"] }]
6141
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
6142
+ type: Inject,
6143
+ args: [API_SERVICE]
6144
+ }] }, { type: undefined, decorators: [{
6145
+ type: Inject,
6146
+ args: [TOASTER_SERVICE]
6147
+ }] }], propDecorators: { value: [{
6148
+ type: Input
6149
+ }], disabled: [{
6150
+ type: Input
6151
+ }], accept: [{
6152
+ type: Input
6153
+ }], baseUrl: [{
6154
+ type: Input
6155
+ }], multiple: [{
6156
+ type: Input
6157
+ }], buttonText: [{
6158
+ type: Input
6159
+ }], makeUpload: [{
6160
+ type: Input
6161
+ }], preProcess: [{
6162
+ type: Input
6163
+ }], onUploaded: [{
6164
+ type: Output
6165
+ }], onRemove: [{
6166
+ type: Output
6167
+ }], uploadButton: [{
6168
+ type: ContentChild,
6169
+ args: ["uploadButton"]
6170
+ }], removeButton: [{
6171
+ type: ContentChild,
6172
+ args: ["removeButton"]
6173
+ }] } });
6174
+
5898
6175
  // --- Pipes ---
5899
6176
  const pipes = [
5900
6177
  ChunkPipe,
@@ -5948,7 +6225,8 @@ const components = [
5948
6225
  DropListComponent,
5949
6226
  DynamicTableComponent,
5950
6227
  PaginationMenuComponent,
5951
- UnorderedListComponent
6228
+ UnorderedListComponent,
6229
+ UploadComponent
5952
6230
  ];
5953
6231
  const providers = [
5954
6232
  ...pipes,
@@ -6285,8 +6563,8 @@ class NgxUtilsModule {
6285
6563
  constructor() {
6286
6564
  }
6287
6565
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxUtilsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6288
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: NgxUtilsModule, declarations: [ChunkPipe, EntriesPipe, ExtraItemPropertiesPipe, FilterPipe, FindPipe, FormatNumberPipe, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplatePipe, GroupByPipe, IsTypePipe, JoinPipe, KeysPipe, MapPipe, MaxPipe, MinPipe, PopPipe, ReducePipe, RemapPipe, ReplacePipe, ReversePipe, RoundPipe, SafeHtmlPipe, ShiftPipe, SplitPipe, TranslatePipe, ValuesPipe, AsyncMethodBase, AsyncMethodDirective, BackgroundDirective, DynamicTableTemplateDirective, GlobalTemplateDirective, IconDirective, NgxTemplateOutletDirective, PaginationDirective, PaginationItemDirective, ResourceIfDirective, StickyDirective, StickyClassDirective, UnorderedListItemDirective, UnorderedListTemplateDirective, DropListComponent, DynamicTableComponent, PaginationMenuComponent, UnorderedListComponent], imports: [CommonModule,
6289
- FormsModule], exports: [ChunkPipe, EntriesPipe, ExtraItemPropertiesPipe, FilterPipe, FindPipe, FormatNumberPipe, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplatePipe, GroupByPipe, IsTypePipe, JoinPipe, KeysPipe, MapPipe, MaxPipe, MinPipe, PopPipe, ReducePipe, RemapPipe, ReplacePipe, ReversePipe, RoundPipe, SafeHtmlPipe, ShiftPipe, SplitPipe, TranslatePipe, ValuesPipe, AsyncMethodBase, AsyncMethodDirective, BackgroundDirective, DynamicTableTemplateDirective, GlobalTemplateDirective, IconDirective, NgxTemplateOutletDirective, PaginationDirective, PaginationItemDirective, ResourceIfDirective, StickyDirective, StickyClassDirective, UnorderedListItemDirective, UnorderedListTemplateDirective, DropListComponent, DynamicTableComponent, PaginationMenuComponent, UnorderedListComponent, FormsModule] }); }
6566
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: NgxUtilsModule, declarations: [ChunkPipe, EntriesPipe, ExtraItemPropertiesPipe, FilterPipe, FindPipe, FormatNumberPipe, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplatePipe, GroupByPipe, IsTypePipe, JoinPipe, KeysPipe, MapPipe, MaxPipe, MinPipe, PopPipe, ReducePipe, RemapPipe, ReplacePipe, ReversePipe, RoundPipe, SafeHtmlPipe, ShiftPipe, SplitPipe, TranslatePipe, ValuesPipe, AsyncMethodBase, AsyncMethodDirective, BackgroundDirective, DynamicTableTemplateDirective, GlobalTemplateDirective, IconDirective, NgxTemplateOutletDirective, PaginationDirective, PaginationItemDirective, ResourceIfDirective, StickyDirective, StickyClassDirective, UnorderedListItemDirective, UnorderedListTemplateDirective, DropListComponent, DynamicTableComponent, PaginationMenuComponent, UnorderedListComponent, UploadComponent], imports: [CommonModule,
6567
+ FormsModule], exports: [ChunkPipe, EntriesPipe, ExtraItemPropertiesPipe, FilterPipe, FindPipe, FormatNumberPipe, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplatePipe, GroupByPipe, IsTypePipe, JoinPipe, KeysPipe, MapPipe, MaxPipe, MinPipe, PopPipe, ReducePipe, RemapPipe, ReplacePipe, ReversePipe, RoundPipe, SafeHtmlPipe, ShiftPipe, SplitPipe, TranslatePipe, ValuesPipe, AsyncMethodBase, AsyncMethodDirective, BackgroundDirective, DynamicTableTemplateDirective, GlobalTemplateDirective, IconDirective, NgxTemplateOutletDirective, PaginationDirective, PaginationItemDirective, ResourceIfDirective, StickyDirective, StickyClassDirective, UnorderedListItemDirective, UnorderedListTemplateDirective, DropListComponent, DynamicTableComponent, PaginationMenuComponent, UnorderedListComponent, UploadComponent, FormsModule] }); }
6290
6568
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgxUtilsModule, providers: pipes, imports: [CommonModule,
6291
6569
  FormsModule, FormsModule] }); }
6292
6570
  }
@@ -6316,5 +6594,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
6316
6594
  * Generated bundle index. Do not edit.
6317
6595
  */
6318
6596
 
6319
- export { API_SERVICE, APP_BASE_URL, AUTH_SERVICE, AclService, AjaxRequestHandler, ApiService, ArrayUtils, AsyncMethodBase, AsyncMethodDirective, AuthGuard, BASE_CONFIG, BackgroundDirective, BaseDialogService, BaseHttpClient, BaseHttpService, BaseToasterService, CONFIG_SERVICE, CanvasColor, CanvasUtils, ChunkPipe, Circle, ConfigService, DIALOG_SERVICE, DateUtils, DragDropEventPlugin, DropListComponent, DynamicTableComponent, DynamicTableTemplateDirective, ERROR_HANDLER, EXPRESS_REQUEST, EntriesPipe, ErrorHandlerService, EventsService, ExtraItemPropertiesPipe, FactoryDependencies, FileSystemEntry, FileUtils, FilterPipe, FindPipe, FormatNumberPipe, FormatterService, GenericValue, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplateDirective, GlobalTemplatePipe, GlobalTemplateService, GroupByPipe, HttpPromise, ICON_SERVICE, IConfiguration, IconDirective, IconService, Initializer, IsTypePipe, JSONfn, JoinPipe, KeysPipe, LANGUAGE_SERVICE, LanguageService, LoaderUtils, LocalHttpService, MapPipe, MathUtils, MaxPipe, MinPipe, NgxTemplateOutletDirective, NgxUtilsModule, OPTIONS_TOKEN, ObjectType, ObjectUtils, ObservableUtils, OpenApiService, PROMISE_SERVICE, PaginationDirective, PaginationItemContext, PaginationItemDirective, PaginationMenuComponent, Point, PopPipe, PromiseService, RESIZE_DELAY, RESIZE_STRATEGY, ROOT_ELEMENT, Rect, ReducePipe, ReflectUtils, RemapPipe, ReplacePipe, ResizeEventPlugin, ResourceIfContext, ResourceIfDirective, ReversePipe, RoundPipe, SCRIPT_PARAMS, SafeHtmlPipe, ScrollEventPlugin, SetUtils, ShiftPipe, SplitPipe, StateService, StaticAuthService, StaticLanguageService, StickyClassDirective, StickyDirective, StorageMode, StorageService, StringUtils, TOASTER_SERVICE, TimerUtils, TranslatePipe, TranslatedUrlSerializer, UniqueUtils, UniversalService, UnorderedListComponent, UnorderedListItemDirective, UnorderedListTemplateDirective, ValuedPromise, ValuesPipe, Vector, WASI_IMPLEMENTATION, WasmService, cachedFactory, cancelablePromise, checkTransitions, impatientPromise, provideWithOptions };
6597
+ export { API_SERVICE, APP_BASE_URL, AUTH_SERVICE, AclService, AjaxRequestHandler, ApiService, ArrayUtils, AsyncMethodBase, AsyncMethodDirective, AuthGuard, BASE_CONFIG, BackgroundDirective, BaseDialogService, BaseHttpClient, BaseHttpService, BaseToasterService, CONFIG_SERVICE, CanvasColor, CanvasUtils, ChunkPipe, Circle, ConfigService, DIALOG_SERVICE, DateUtils, DragDropEventPlugin, DropListComponent, DynamicTableComponent, DynamicTableTemplateDirective, ERROR_HANDLER, EXPRESS_REQUEST, EntriesPipe, ErrorHandlerService, EventsService, ExtraItemPropertiesPipe, FactoryDependencies, FileSystemEntry, FileUtils, FilterPipe, FindPipe, FormatNumberPipe, FormatterService, GenericValue, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplateDirective, GlobalTemplatePipe, GlobalTemplateService, GroupByPipe, HttpPromise, ICON_SERVICE, IConfiguration, IconDirective, IconService, Initializer, IsTypePipe, JSONfn, JoinPipe, KeysPipe, LANGUAGE_SERVICE, LanguageService, LoaderUtils, LocalHttpService, MapPipe, MathUtils, MaxPipe, MinPipe, NgxTemplateOutletDirective, NgxUtilsModule, OPTIONS_TOKEN, ObjectType, ObjectUtils, ObservableUtils, OpenApiService, PROMISE_SERVICE, PaginationDirective, PaginationItemContext, PaginationItemDirective, PaginationMenuComponent, Point, PopPipe, PromiseService, RESIZE_DELAY, RESIZE_STRATEGY, ROOT_ELEMENT, Rect, ReducePipe, ReflectUtils, RemapPipe, ReplacePipe, ResizeEventPlugin, ResourceIfContext, ResourceIfDirective, ReversePipe, RoundPipe, SCRIPT_PARAMS, SafeHtmlPipe, ScrollEventPlugin, SetUtils, ShiftPipe, SplitPipe, StateService, StaticAuthService, StaticLanguageService, StickyClassDirective, StickyDirective, StorageMode, StorageService, StringUtils, TOASTER_SERVICE, TimerUtils, TranslatePipe, TranslatedUrlSerializer, UniqueUtils, UniversalService, UnorderedListComponent, UnorderedListItemDirective, UnorderedListTemplateDirective, UploadComponent, ValuedPromise, ValuesPipe, Vector, WASI_IMPLEMENTATION, WasmService, cachedFactory, cancelablePromise, checkTransitions, impatientPromise, provideWithOptions };
6320
6598
  //# sourceMappingURL=stemy-ngx-utils.mjs.map