@tft/crispr-forms 13.0.0 → 13.0.4
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.
- package/README.md +9 -69
- package/esm2020/lib/material/image-upload-field/image-upload-field.component.mjs +60 -23
- package/esm2020/lib/models/file-upload-field.config.mjs +1 -1
- package/esm2020/lib/models/image-upload-field.config.mjs +1 -1
- package/fesm2015/tft-crispr-forms.mjs +63 -24
- package/fesm2015/tft-crispr-forms.mjs.map +1 -1
- package/fesm2020/tft-crispr-forms.mjs +61 -23
- package/fesm2020/tft-crispr-forms.mjs.map +1 -1
- package/lib/material/image-upload-field/image-upload-field.component.d.ts +9 -2
- package/lib/models/file-upload-field.config.d.ts +1 -1
- package/lib/models/image-upload-field.config.d.ts +7 -1
- package/package.json +3 -4
- package/tft-crispr-forms-13.0.4.tgz +0 -0
- package/tft-crispr-forms-13.0.0.tgz +0 -0
|
@@ -1137,7 +1137,6 @@ function convertBytesToMb(bytes) {
|
|
|
1137
1137
|
|
|
1138
1138
|
const ImageUploadFieldMixin = crisprControlMixin(CrisprFieldComponent);
|
|
1139
1139
|
class ImageUploadFieldComponent extends ImageUploadFieldMixin {
|
|
1140
|
-
// ngControl: NgControl = null;
|
|
1141
1140
|
constructor(ngControl, domSanitizer, cdr) {
|
|
1142
1141
|
super();
|
|
1143
1142
|
this.ngControl = ngControl;
|
|
@@ -1158,42 +1157,55 @@ class ImageUploadFieldComponent extends ImageUploadFieldMixin {
|
|
|
1158
1157
|
minCompressionThresholdMb: .6,
|
|
1159
1158
|
useWebWorker: true,
|
|
1160
1159
|
};
|
|
1160
|
+
/**
|
|
1161
|
+
* The url mapped from initial input value, consumers can us mapInputValueToUrl in config to transform their input value into a src url for the image element
|
|
1162
|
+
*/
|
|
1163
|
+
// inputValueUrl: string | undefined;
|
|
1161
1164
|
this.inputImageFileSubject = new Subject();
|
|
1162
1165
|
this.inputImageFile$ = this.inputImageFileSubject.asObservable().pipe(shareReplay(1));
|
|
1163
1166
|
this.compressedFile$ = this.inputImageFile$.pipe(switchMap((file) => __awaiter(this, void 0, void 0, function* () {
|
|
1164
|
-
if (!file)
|
|
1167
|
+
if (!file || !(file instanceof File))
|
|
1165
1168
|
return null;
|
|
1166
|
-
if (typeof file === 'string')
|
|
1167
|
-
return file;
|
|
1168
1169
|
const { compressImage, targetCompressedImageFileSizeMb, minCompressionThresholdMb, maxWidthOrHeight, useWebWorker } = this.config;
|
|
1169
1170
|
const fileSizeMb = convertBytesToMb(file.size);
|
|
1170
|
-
const shouldCompress = compressImage
|
|
1171
|
+
const shouldCompress = compressImage
|
|
1172
|
+
&& targetCompressedImageFileSizeMb < fileSizeMb
|
|
1173
|
+
&& minCompressionThresholdMb < fileSizeMb;
|
|
1171
1174
|
if (shouldCompress) {
|
|
1172
|
-
const options = Object.assign(Object.assign({}, (maxWidthOrHeight ? { maxWidthOrHeight } : { maxSizeMB: targetCompressedImageFileSizeMb })), { useWebWorker, maxIterations: 30, onProgress: (
|
|
1173
|
-
this.progress =
|
|
1175
|
+
const options = Object.assign(Object.assign({}, (maxWidthOrHeight ? { maxWidthOrHeight } : { maxSizeMB: targetCompressedImageFileSizeMb })), { useWebWorker, maxIterations: 30, onProgress: (progress) => {
|
|
1176
|
+
this.progress = progress;
|
|
1174
1177
|
this.cdr.detectChanges();
|
|
1175
1178
|
} });
|
|
1176
|
-
|
|
1177
|
-
return compressedFile;
|
|
1179
|
+
return yield imageCompression(file, options);
|
|
1178
1180
|
}
|
|
1179
1181
|
else
|
|
1180
1182
|
return file;
|
|
1181
|
-
})),
|
|
1182
|
-
|
|
1183
|
+
})), map((compressedFile) => {
|
|
1184
|
+
if (!compressedFile)
|
|
1185
|
+
return compressedFile;
|
|
1186
|
+
const { type, name, lastModified } = compressedFile;
|
|
1187
|
+
return new File([compressedFile], this.config.fileName || name, {
|
|
1188
|
+
type,
|
|
1189
|
+
lastModified
|
|
1190
|
+
});
|
|
1191
|
+
}), tap(file => {
|
|
1192
|
+
// only set the value if there is a file because resetToInitialValue sets the control value
|
|
1193
|
+
// to initial value and clears the compressed image, so setting it to null here would undo that
|
|
1194
|
+
if (file) {
|
|
1195
|
+
this.control.setValue(file);
|
|
1196
|
+
}
|
|
1183
1197
|
if (file || this.value) {
|
|
1184
1198
|
this.control.markAsTouched();
|
|
1185
1199
|
setTimeout(() => {
|
|
1186
1200
|
this.cdr.detectChanges();
|
|
1187
1201
|
}, 100);
|
|
1188
1202
|
}
|
|
1189
|
-
}),
|
|
1203
|
+
}), shareReplay(1));
|
|
1190
1204
|
this.compressedImageUrlString$ = this.compressedFile$.pipe(switchMap((file) => __awaiter(this, void 0, void 0, function* () {
|
|
1191
1205
|
if (!file)
|
|
1192
1206
|
return null;
|
|
1193
1207
|
const compressedStringImage = yield imageCompression.getDataUrlFromFile(file);
|
|
1194
|
-
return
|
|
1195
|
-
? this.domSanitizer.bypassSecurityTrustResourceUrl(compressedStringImage)
|
|
1196
|
-
: compressedStringImage;
|
|
1208
|
+
return this.domSanitizer.bypassSecurityTrustResourceUrl(compressedStringImage);
|
|
1197
1209
|
})), shareReplay(1));
|
|
1198
1210
|
this.isUploaded = false;
|
|
1199
1211
|
if (this.ngControl != null) {
|
|
@@ -1204,11 +1216,19 @@ class ImageUploadFieldComponent extends ImageUploadFieldMixin {
|
|
|
1204
1216
|
}
|
|
1205
1217
|
ngOnInit() {
|
|
1206
1218
|
super.ngOnInit();
|
|
1219
|
+
// this.inputValueUrl = this.value && this.config.mapInputValueToUrl?.(this.value) || this.value;
|
|
1207
1220
|
this.imageSrcUrl$ = combineLatest([
|
|
1208
1221
|
this.compressedImageUrlString$.pipe(startWith(null)),
|
|
1209
|
-
this.control.valueChanges.pipe(startWith(this.value))
|
|
1222
|
+
this.control.valueChanges.pipe(startWith(this.value), map((controlValue) => {
|
|
1223
|
+
var _a, _b;
|
|
1224
|
+
if (!controlValue)
|
|
1225
|
+
return null;
|
|
1226
|
+
if (controlValue instanceof File)
|
|
1227
|
+
return null;
|
|
1228
|
+
return ((_b = (_a = this.config).mapInputValueToUrl) === null || _b === void 0 ? void 0 : _b.call(_a, controlValue)) || controlValue;
|
|
1229
|
+
}))
|
|
1210
1230
|
]).pipe(map(([compressedImageUrlString, controlUrl]) => {
|
|
1211
|
-
return compressedImageUrlString ||
|
|
1231
|
+
return compressedImageUrlString || controlUrl || null;
|
|
1212
1232
|
}));
|
|
1213
1233
|
this.disabled$ = this.config.disabledCallback
|
|
1214
1234
|
? this.config.disabledCallback(this.group, this.config)
|
|
@@ -1217,6 +1237,10 @@ class ImageUploadFieldComponent extends ImageUploadFieldMixin {
|
|
|
1217
1237
|
filesChanged(files) {
|
|
1218
1238
|
if (files && files.length > 0) {
|
|
1219
1239
|
const imageFile = files[0];
|
|
1240
|
+
// We clear the control here so that it is invalid while compressing
|
|
1241
|
+
// the input pipeline will take care of resetting it
|
|
1242
|
+
this.control.patchValue(null);
|
|
1243
|
+
// this.control.setErrors({compressing: {loadingMessage: 'Please wait while file compresses'}});
|
|
1220
1244
|
this.control.markAsTouched();
|
|
1221
1245
|
this.inputImageFileSubject.next(imageFile);
|
|
1222
1246
|
}
|
|
@@ -1229,8 +1253,8 @@ class ImageUploadFieldComponent extends ImageUploadFieldMixin {
|
|
|
1229
1253
|
this.isUploaded = false;
|
|
1230
1254
|
}
|
|
1231
1255
|
resetToInitialValue(initialValue) {
|
|
1232
|
-
this.inputImageFileSubject.next(
|
|
1233
|
-
|
|
1256
|
+
this.inputImageFileSubject.next(null);
|
|
1257
|
+
this.control.patchValue(initialValue);
|
|
1234
1258
|
this.isUploaded = false;
|
|
1235
1259
|
}
|
|
1236
1260
|
writeValue(value) { }
|
|
@@ -1240,10 +1264,10 @@ class ImageUploadFieldComponent extends ImageUploadFieldMixin {
|
|
|
1240
1264
|
registerOnTouched(fn) { }
|
|
1241
1265
|
}
|
|
1242
1266
|
ImageUploadFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: ImageUploadFieldComponent, deps: [{ token: i4$1.NgControl, optional: true, self: true }, { token: i2$3.DomSanitizer }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1243
|
-
ImageUploadFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.1", type: ImageUploadFieldComponent, selector: "crispr-image-upload-field", viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<crispr-field-container\n [config]=\"config\"\n [group]=\"group\">\n\n <mat-form-field floatLabel=\"always\"\n [color]=\"config.color\"\n [appearance]=\"config.appearance\"\n [formGroup]=\"group\">\n <mat-label>{{config.label}}</mat-label>\n <input [formControlName]=\"config.controlName\" matInput type=\"text\"/>\n <input\n #fileInput\n type=\"file\"\n [accept]=\"config.acceptedTypes\"\n (change)=\"filesChanged($event.target.files)\"/>\n <div class=\"ui-container\">\n\n <div class=\"image-preview\" [style.height]=\"config.imagePreviewHeight\">\n <crispr-selected-file\n *ngIf=\"(progress < 100) && inputImageFile$ | async as file; else dropzoneOrPreview\"\n [color]=\"config.color === 'primary' ? 'accent' : 'primary'\"\n [fileName]=\"'Compressing: ' + file.name\"\n [showProgress]=\"true\"\n [progress]=\"progress\">\n </crispr-selected-file>\n\n <ng-template #dropzoneOrPreview>\n <!-- <img *ngIf=\"(initialUrlString$ | async) as initialUrlString;\" [src]=\"initialUrlString\" alt=\"\"> -->\n <img *ngIf=\"imageSrcUrl$ | async as srcUrl; else noImage\" [src]=\"srcUrl\" alt=\"\">\n <ng-template #noImage>\n <div class=\"drop-container\"\n [crisprFileDropzone]=\"!(disabled$ | async)\"\n (fileDrop)=\"filesChanged($event)\">\n <mat-icon class=\"drop-icon\" inline=\"true\">cloud_upload</mat-icon>\n <h2 class=\"mat-h2\">{{config.dropZoneText}}</h2>\n </div>\n </ng-template>\n\n </ng-template>\n </div>\n\n\n\n <!-- </ng-template> -->\n <div class=\"button-container\" *ngIf=\"true\">\n\n <button\n mat-button\n (click)=\"clearFileInput()\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>delete</mat-icon>\n {{config.clearFilesButtonText}}\n </button>\n\n <button\n *ngIf=\"value\"\n mat-button\n (click)=\"resetToInitialValue(value)\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>replay</mat-icon>\n {{config.resetFilesButtonText}}\n </button>\n\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"(disabled$ | async)\"\n (click)=\"fileInput.click()\"\n [attr.aria-label]=\"config.controlName\">\n <mat-icon>\n camera\n </mat-icon>\n SELECT\n </button>\n </div>\n </div>\n\n </mat-form-field>\n\n</crispr-field-container>\n", styles: [":host ::ng-deep .mat-form-field .mat-form-field-infix{padding-top:0}:host ::ng-deep .mat-form-field .mat-button-wrapper{display:flex;flex-direction:column;align-items:center;padding-top:8px}:host .ui-container{display:flex;flex-direction:column}:host .ui-container .image-preview{display:flex;flex-direction:column;align-content:space-between;justify-content:center;align-items:center;margin:8px 0;flex-grow:1}:host .ui-container .image-preview crispr-selected-file{width:100%}:host .ui-container .image-preview .drop-container{display:flex;flex-direction:column;align-items:center;border:3px dashed gray;height:100%;width:100%;align-content:center;justify-content:center;border-radius:8px}:host .ui-container .image-preview .drop-container .drop-icon{height:32px;width:32px;font-size:36px}:host .ui-container .image-preview .drop-container .mat-h2{margin:0}:host .ui-container .image-preview img{height:inherit;max-width:100%}:host .ui-container .button-container{display:flex;flex-direction:var(--image-upload-button-container-direction);justify-content:flex-end}:host .ui-container .button-container button{margin-left:8px}:host input{position:absolute;max-height:0;visibility:hidden}\n"], components: [{ type: FieldContainerComponent, selector: "crispr-field-container", inputs: ["config", "group", "inlineField"] }, { type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: SelectedFileComponent, selector: "crispr-selected-file", inputs: ["fileName", "progress", "showProgress", "color"] }, { type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i1.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i4$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i5.ControlErrorContainerDirective, selector: "[controlErrorContainer], [formGroup]" }, { type: i2$1.MatLabel, selector: "mat-label" }, { type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i4$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i5.ControlErrorsDirective, selector: "[formControl], [formControlName]" }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: FileDropzoneDirective, selector: "[crisprFileDropzone]", inputs: ["crisprFileDropzone"], outputs: ["fileDrop"] }], pipes: { "async": i2.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true });
|
|
1267
|
+
ImageUploadFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.1", type: ImageUploadFieldComponent, selector: "crispr-image-upload-field", viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<crispr-field-container\n [config]=\"config\"\n [group]=\"group\">\n\n <mat-form-field floatLabel=\"always\"\n [color]=\"config.color\"\n [appearance]=\"config.appearance\"\n [formGroup]=\"group\">\n <mat-label>{{config.label}}</mat-label>\n <input [formControlName]=\"config.controlName\" matInput type=\"text\"/>\n <input\n #fileInput\n type=\"file\"\n [accept]=\"config.acceptedTypes\"\n (change)=\"filesChanged($event.target.files)\"/>\n <div class=\"ui-container\">\n\n <div class=\"image-preview\" [style.height]=\"config.imagePreviewHeight\">\n <crispr-selected-file\n *ngIf=\"(progress < 100) && inputImageFile$ | async as file; else dropzoneOrPreview\"\n [color]=\"config.color === 'primary' ? 'accent' : 'primary'\"\n [fileName]=\"'Compressing: ' + file.name\"\n [showProgress]=\"true\"\n [progress]=\"progress\">\n </crispr-selected-file>\n\n <ng-template #dropzoneOrPreview>\n <!-- <img *ngIf=\"(initialUrlString$ | async) as initialUrlString;\" [src]=\"initialUrlString\" alt=\"\"> -->\n <img *ngIf=\"imageSrcUrl$ | async as srcUrl; else noImage\" [src]=\"srcUrl\" alt=\"\">\n <ng-template #noImage>\n <div class=\"drop-container\"\n [crisprFileDropzone]=\"!(disabled$ | async)\"\n (fileDrop)=\"filesChanged($event)\">\n <mat-icon class=\"drop-icon\" inline=\"true\">cloud_upload</mat-icon>\n <h2 class=\"mat-h2\">{{config.dropZoneText}}</h2>\n </div>\n </ng-template>\n\n </ng-template>\n </div>\n\n\n\n <!-- </ng-template> -->\n <div class=\"button-container\" *ngIf=\"true\">\n\n <button\n mat-button\n (click)=\"clearFileInput()\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>delete</mat-icon>\n {{config.clearFilesButtonText}}\n </button>\n\n <button\n *ngIf=\"value\"\n mat-button\n (click)=\"resetToInitialValue(value)\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>replay</mat-icon>\n {{config.resetFilesButtonText}}\n </button>\n\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"(disabled$ | async)\"\n (click)=\"fileInput.click()\"\n [attr.aria-label]=\"config.controlName\">\n <mat-icon>\n camera\n </mat-icon>\n SELECT\n </button>\n </div>\n </div>\n\n </mat-form-field>\n\n</crispr-field-container>\n", styles: [":host ::ng-deep .mat-form-field .mat-form-field-infix{padding-top:0}:host ::ng-deep .mat-form-field .mat-button-wrapper{display:flex;flex-direction:column;align-items:center;padding-top:8px}:host .ui-container{display:flex;flex-direction:column}:host .ui-container .image-preview{display:flex;flex-direction:column;align-content:space-between;justify-content:center;align-items:center;margin:8px 0;flex-grow:1}:host .ui-container .image-preview crispr-selected-file{width:100%}:host .ui-container .image-preview .drop-container{display:flex;box-sizing:border-box;flex-direction:column;align-items:center;border:3px dashed gray;height:100%;width:100%;align-content:center;justify-content:center;border-radius:8px}:host .ui-container .image-preview .drop-container .drop-icon{height:32px;width:32px;font-size:36px}:host .ui-container .image-preview .drop-container .mat-h2{margin:0}:host .ui-container .image-preview img{height:inherit;max-width:100%}:host .ui-container .button-container{display:flex;flex-direction:var(--image-upload-button-container-direction);justify-content:flex-end}:host .ui-container .button-container button{margin-left:8px}:host input{position:absolute;max-height:0;visibility:hidden}\n"], components: [{ type: FieldContainerComponent, selector: "crispr-field-container", inputs: ["config", "group", "inlineField"] }, { type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: SelectedFileComponent, selector: "crispr-selected-file", inputs: ["fileName", "progress", "showProgress", "color"] }, { type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i1.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i4$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i5.ControlErrorContainerDirective, selector: "[controlErrorContainer], [formGroup]" }, { type: i2$1.MatLabel, selector: "mat-label" }, { type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i4$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i5.ControlErrorsDirective, selector: "[formControl], [formControlName]" }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: FileDropzoneDirective, selector: "[crisprFileDropzone]", inputs: ["crisprFileDropzone"], outputs: ["fileDrop"] }], pipes: { "async": i2.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush, preserveWhitespaces: true });
|
|
1244
1268
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImport: i0, type: ImageUploadFieldComponent, decorators: [{
|
|
1245
1269
|
type: Component,
|
|
1246
|
-
args: [{ selector: 'crispr-image-upload-field', changeDetection: ChangeDetectionStrategy.OnPush, template: "<crispr-field-container\n [config]=\"config\"\n [group]=\"group\">\n\n <mat-form-field floatLabel=\"always\"\n [color]=\"config.color\"\n [appearance]=\"config.appearance\"\n [formGroup]=\"group\">\n <mat-label>{{config.label}}</mat-label>\n <input [formControlName]=\"config.controlName\" matInput type=\"text\"/>\n <input\n #fileInput\n type=\"file\"\n [accept]=\"config.acceptedTypes\"\n (change)=\"filesChanged($event.target.files)\"/>\n <div class=\"ui-container\">\n\n <div class=\"image-preview\" [style.height]=\"config.imagePreviewHeight\">\n <crispr-selected-file\n *ngIf=\"(progress < 100) && inputImageFile$ | async as file; else dropzoneOrPreview\"\n [color]=\"config.color === 'primary' ? 'accent' : 'primary'\"\n [fileName]=\"'Compressing: ' + file.name\"\n [showProgress]=\"true\"\n [progress]=\"progress\">\n </crispr-selected-file>\n\n <ng-template #dropzoneOrPreview>\n <!-- <img *ngIf=\"(initialUrlString$ | async) as initialUrlString;\" [src]=\"initialUrlString\" alt=\"\"> -->\n <img *ngIf=\"imageSrcUrl$ | async as srcUrl; else noImage\" [src]=\"srcUrl\" alt=\"\">\n <ng-template #noImage>\n <div class=\"drop-container\"\n [crisprFileDropzone]=\"!(disabled$ | async)\"\n (fileDrop)=\"filesChanged($event)\">\n <mat-icon class=\"drop-icon\" inline=\"true\">cloud_upload</mat-icon>\n <h2 class=\"mat-h2\">{{config.dropZoneText}}</h2>\n </div>\n </ng-template>\n\n </ng-template>\n </div>\n\n\n\n <!-- </ng-template> -->\n <div class=\"button-container\" *ngIf=\"true\">\n\n <button\n mat-button\n (click)=\"clearFileInput()\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>delete</mat-icon>\n {{config.clearFilesButtonText}}\n </button>\n\n <button\n *ngIf=\"value\"\n mat-button\n (click)=\"resetToInitialValue(value)\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>replay</mat-icon>\n {{config.resetFilesButtonText}}\n </button>\n\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"(disabled$ | async)\"\n (click)=\"fileInput.click()\"\n [attr.aria-label]=\"config.controlName\">\n <mat-icon>\n camera\n </mat-icon>\n SELECT\n </button>\n </div>\n </div>\n\n </mat-form-field>\n\n</crispr-field-container>\n", styles: [":host ::ng-deep .mat-form-field .mat-form-field-infix{padding-top:0}:host ::ng-deep .mat-form-field .mat-button-wrapper{display:flex;flex-direction:column;align-items:center;padding-top:8px}:host .ui-container{display:flex;flex-direction:column}:host .ui-container .image-preview{display:flex;flex-direction:column;align-content:space-between;justify-content:center;align-items:center;margin:8px 0;flex-grow:1}:host .ui-container .image-preview crispr-selected-file{width:100%}:host .ui-container .image-preview .drop-container{display:flex;flex-direction:column;align-items:center;border:3px dashed gray;height:100%;width:100%;align-content:center;justify-content:center;border-radius:8px}:host .ui-container .image-preview .drop-container .drop-icon{height:32px;width:32px;font-size:36px}:host .ui-container .image-preview .drop-container .mat-h2{margin:0}:host .ui-container .image-preview img{height:inherit;max-width:100%}:host .ui-container .button-container{display:flex;flex-direction:var(--image-upload-button-container-direction);justify-content:flex-end}:host .ui-container .button-container button{margin-left:8px}:host input{position:absolute;max-height:0;visibility:hidden}\n"] }]
|
|
1270
|
+
args: [{ selector: 'crispr-image-upload-field', changeDetection: ChangeDetectionStrategy.OnPush, template: "<crispr-field-container\n [config]=\"config\"\n [group]=\"group\">\n\n <mat-form-field floatLabel=\"always\"\n [color]=\"config.color\"\n [appearance]=\"config.appearance\"\n [formGroup]=\"group\">\n <mat-label>{{config.label}}</mat-label>\n <input [formControlName]=\"config.controlName\" matInput type=\"text\"/>\n <input\n #fileInput\n type=\"file\"\n [accept]=\"config.acceptedTypes\"\n (change)=\"filesChanged($event.target.files)\"/>\n <div class=\"ui-container\">\n\n <div class=\"image-preview\" [style.height]=\"config.imagePreviewHeight\">\n <crispr-selected-file\n *ngIf=\"(progress < 100) && inputImageFile$ | async as file; else dropzoneOrPreview\"\n [color]=\"config.color === 'primary' ? 'accent' : 'primary'\"\n [fileName]=\"'Compressing: ' + file.name\"\n [showProgress]=\"true\"\n [progress]=\"progress\">\n </crispr-selected-file>\n\n <ng-template #dropzoneOrPreview>\n <!-- <img *ngIf=\"(initialUrlString$ | async) as initialUrlString;\" [src]=\"initialUrlString\" alt=\"\"> -->\n <img *ngIf=\"imageSrcUrl$ | async as srcUrl; else noImage\" [src]=\"srcUrl\" alt=\"\">\n <ng-template #noImage>\n <div class=\"drop-container\"\n [crisprFileDropzone]=\"!(disabled$ | async)\"\n (fileDrop)=\"filesChanged($event)\">\n <mat-icon class=\"drop-icon\" inline=\"true\">cloud_upload</mat-icon>\n <h2 class=\"mat-h2\">{{config.dropZoneText}}</h2>\n </div>\n </ng-template>\n\n </ng-template>\n </div>\n\n\n\n <!-- </ng-template> -->\n <div class=\"button-container\" *ngIf=\"true\">\n\n <button\n mat-button\n (click)=\"clearFileInput()\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>delete</mat-icon>\n {{config.clearFilesButtonText}}\n </button>\n\n <button\n *ngIf=\"value\"\n mat-button\n (click)=\"resetToInitialValue(value)\"\n type=\"button\"\n [disabled]=\"(disabled$ | async)\"\n aria-label=\"Remove Selected File(s)\">\n <mat-icon>replay</mat-icon>\n {{config.resetFilesButtonText}}\n </button>\n\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [disabled]=\"(disabled$ | async)\"\n (click)=\"fileInput.click()\"\n [attr.aria-label]=\"config.controlName\">\n <mat-icon>\n camera\n </mat-icon>\n SELECT\n </button>\n </div>\n </div>\n\n </mat-form-field>\n\n</crispr-field-container>\n", styles: [":host ::ng-deep .mat-form-field .mat-form-field-infix{padding-top:0}:host ::ng-deep .mat-form-field .mat-button-wrapper{display:flex;flex-direction:column;align-items:center;padding-top:8px}:host .ui-container{display:flex;flex-direction:column}:host .ui-container .image-preview{display:flex;flex-direction:column;align-content:space-between;justify-content:center;align-items:center;margin:8px 0;flex-grow:1}:host .ui-container .image-preview crispr-selected-file{width:100%}:host .ui-container .image-preview .drop-container{display:flex;box-sizing:border-box;flex-direction:column;align-items:center;border:3px dashed gray;height:100%;width:100%;align-content:center;justify-content:center;border-radius:8px}:host .ui-container .image-preview .drop-container .drop-icon{height:32px;width:32px;font-size:36px}:host .ui-container .image-preview .drop-container .mat-h2{margin:0}:host .ui-container .image-preview img{height:inherit;max-width:100%}:host .ui-container .button-container{display:flex;flex-direction:var(--image-upload-button-container-direction);justify-content:flex-end}:host .ui-container .button-container button{margin-left:8px}:host input{position:absolute;max-height:0;visibility:hidden}\n"] }]
|
|
1247
1271
|
}], ctorParameters: function () {
|
|
1248
1272
|
return [{ type: i4$1.NgControl, decorators: [{
|
|
1249
1273
|
type: Optional
|
|
@@ -1305,14 +1329,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImpor
|
|
|
1305
1329
|
function maxFileSizeValidator(maxFileSize) {
|
|
1306
1330
|
return (control) => {
|
|
1307
1331
|
const controlValue = control.value;
|
|
1308
|
-
if (!(controlValue instanceof
|
|
1332
|
+
if (!(controlValue instanceof File)) {
|
|
1309
1333
|
return null;
|
|
1334
|
+
}
|
|
1310
1335
|
const actualFileSize = +convertBytesToMb(controlValue.size).toPrecision(3);
|
|
1311
1336
|
if (maxFileSize > actualFileSize)
|
|
1312
1337
|
return null;
|
|
1313
|
-
control.setErrors({ maxFileSize: { maxFileSize, actualFileSize } });
|
|
1314
1338
|
return { maxFileSize: { maxFileSize, actualFileSize } };
|
|
1315
1339
|
};
|
|
1340
|
+
}
|
|
1341
|
+
function allowedFileExtValidator(allowedFileExtensions, onlyAllowFiles = true) {
|
|
1342
|
+
return (control) => {
|
|
1343
|
+
const controlValue = control.value;
|
|
1344
|
+
const isFile = controlValue instanceof File;
|
|
1345
|
+
if (!onlyAllowFiles && !isFile)
|
|
1346
|
+
return null;
|
|
1347
|
+
const actualExtension = isFile ? controlValue.name.split('.').pop().toLocaleLowerCase() : 'Not a file';
|
|
1348
|
+
const isAllowedExtension = allowedFileExtensions.includes(actualExtension);
|
|
1349
|
+
if (isAllowedExtension) {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
return { allowedExtension: { allowedFileExtensions, actualExtension } };
|
|
1353
|
+
};
|
|
1316
1354
|
}
|
|
1317
1355
|
|
|
1318
1356
|
// TODO: Should we import UI library?
|
|
@@ -1493,6 +1531,7 @@ var index$2 = /*#__PURE__*/Object.freeze({
|
|
|
1493
1531
|
ImageUploadFieldComponent: ImageUploadFieldComponent,
|
|
1494
1532
|
ImageUploadFieldModule: ImageUploadFieldModule,
|
|
1495
1533
|
maxFileSizeValidator: maxFileSizeValidator,
|
|
1534
|
+
allowedFileExtValidator: allowedFileExtValidator,
|
|
1496
1535
|
FileDropzoneDirective: FileDropzoneDirective,
|
|
1497
1536
|
FileUploadFieldComponent: FileUploadFieldComponent,
|
|
1498
1537
|
FileUploadFieldModule: FileUploadFieldModule,
|
|
@@ -1879,5 +1918,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.1", ngImpor
|
|
|
1879
1918
|
* Generated bundle index. Do not edit.
|
|
1880
1919
|
*/
|
|
1881
1920
|
|
|
1882
|
-
export { AbstractAutocompleteComponent, AutocompleteChiplistFieldComponent, AutocompleteFieldComponent, ButtonComponent, CheckboxFieldComponent, ControlType, CrisprFieldComponent, CrisprFormComponent, CrisprFormsModule, DEFAULT_EMPTY_OPTIONS_MESSAGE, DatepickerFieldComponent, DividerComponent, FieldContainerComponent, FieldContainerModule, FileDropzoneDirective, FileUploadFieldComponent, FileUploadFieldModule, HeadingComponent, HeadingModule, ImageUploadFieldComponent, ImageUploadFieldModule, InputFieldComponent, MaterialModule, OptionComponent, RadioFieldComponent, SelectFieldComponent, SliderFieldComponent, TextareaFieldComponent, UnitConversionFieldComponent, buildFormGroupFromConfig, callOptionsIfFunction, checkControlForValues, checkControlsForValues, computeValueFromFields, createControlForType, crisprControlMixin, filterOptionsByLabel, isControlConfig, maxFileSizeValidator, observablifyOptions };
|
|
1921
|
+
export { AbstractAutocompleteComponent, AutocompleteChiplistFieldComponent, AutocompleteFieldComponent, ButtonComponent, CheckboxFieldComponent, ControlType, CrisprFieldComponent, CrisprFormComponent, CrisprFormsModule, DEFAULT_EMPTY_OPTIONS_MESSAGE, DatepickerFieldComponent, DividerComponent, FieldContainerComponent, FieldContainerModule, FileDropzoneDirective, FileUploadFieldComponent, FileUploadFieldModule, HeadingComponent, HeadingModule, ImageUploadFieldComponent, ImageUploadFieldModule, InputFieldComponent, MaterialModule, OptionComponent, RadioFieldComponent, SelectFieldComponent, SliderFieldComponent, TextareaFieldComponent, UnitConversionFieldComponent, allowedFileExtValidator, buildFormGroupFromConfig, callOptionsIfFunction, checkControlForValues, checkControlsForValues, computeValueFromFields, createControlForType, crisprControlMixin, filterOptionsByLabel, isControlConfig, maxFileSizeValidator, observablifyOptions };
|
|
1883
1922
|
//# sourceMappingURL=tft-crispr-forms.mjs.map
|