@bnsights/bbsf-controls 1.2.28 → 1.2.29

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 CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  BBSF Controls package is part of BBSF 3 packages. It has all the form controls that we use to build our application forms.
4
4
 
5
- For more info please visit [BBSF Controls documenation](https://bbsfadmin.bnsights.com/controls) or [BBSF documentation](https://bnsightsprojects.visualstudio.com/BBSF%203/_wiki/wikis/BBSF-3.wiki/65/BBSF-Documentation)
6
-
7
- ## 🚀 NEW! Tree-Shakable Granular Modules (v2.0+)
8
-
9
- The package now supports **true tree-shaking** through granular modules for optimal bundle size!
5
+ For more info please visit [BBSF Controls documenation](https://bbsfadmin.bnsights.com/controls) or [BBSF documentation](https://bnsightsprojects.visualstudio.com/BBSF%203/_wiki/wikis/BBSF-3.wiki/65/BBSF-Documentation)
6
+
7
+ ## 🚀 NEW! Tree-Shakable Granular Modules (v2.0+)
8
+
9
+ The package now supports **true tree-shaking** through granular modules for optimal bundle size!
10
10
 
11
11
  ### 📦 Available Modules
12
12
 
@@ -327,19 +327,19 @@ import { BBSFFormsBasicModule, BBSFUploadsModule } from '@bnsights/bbsf-controls
327
327
 
328
328
  ---
329
329
 
330
- ## 🔧 Troubleshooting
331
-
332
- ### Markdown editor assets and behavior
333
-
334
- `BBSF-MarkdownEditor` is now powered by Tiptap and no longer depends on the previous third-party markdown editor, Ace, runtime markdown scripts, or copied markdown editor assets.
335
-
336
- The control keeps the BBSF API and form integration, but the old split preview panel, `customRender`, and built-in image upload behavior are no longer provided by the editor engine.
337
-
338
- ---
339
-
340
- ### Error: `export 'DOCUMENT' (imported as 'DOCUMENT') was not found in '@angular/core'`
341
-
342
- **Problem:** This error occurs when using Angular 19+ with the `BBSFEditorsModule` (which uses `@kolkov/angular-editor`). Angular 19's build system tries to process the `@kolkov/angular-editor` package and encounters compatibility issues.
330
+ ## 🔧 Troubleshooting
331
+
332
+ ### Markdown editor assets and behavior
333
+
334
+ `BBSF-MarkdownEditor` is now powered by Tiptap and no longer depends on the previous third-party markdown editor, Ace, runtime markdown scripts, or copied markdown editor assets.
335
+
336
+ The control keeps the BBSF API and form integration, but the old split preview panel, `customRender`, and built-in image upload behavior are no longer provided by the editor engine.
337
+
338
+ ---
339
+
340
+ ### Error: `export 'DOCUMENT' (imported as 'DOCUMENT') was not found in '@angular/core'`
341
+
342
+ **Problem:** This error occurs when using Angular 19+ with the `BBSFEditorsModule` (which uses `@kolkov/angular-editor`). Angular 19's build system tries to process the `@kolkov/angular-editor` package and encounters compatibility issues.
343
343
 
344
344
  **Solution 1: Install @kolkov/angular-editor in your consuming app (Recommended)**
345
345
 
@@ -398,46 +398,61 @@ If the issue persists, consider using a different HTML editor component that's c
398
398
 
399
399
  ---
400
400
 
401
- ## Change Log
402
-
403
- ## 1.2.28 / 23-06-2026
404
-
405
- =====================
406
-
407
- - Added optional `FileUploadOptions` overrides for validation error message labels.
408
- - Supported host-provided localized labels for max file count, min file count, total size, file size, type tooltip, duplicate file, and required validation messages.
409
- - Threaded file upload options through validation helpers and applied the duplicate-file override message.
410
-
411
- ## 1.2.27 / 22-06-2026
412
-
413
- =====================
414
-
415
- - Added optional image cropper support to `BBSF-FileUpload` through `FileUploadOptions.cropperOptions`.
416
- - Added exported cropper option models for configuring modal behavior, orientation presets, and cancel behavior.
417
- - Preserved existing upload behavior unless cropper options are explicitly enabled.
418
-
419
- ## 1.2.26 / 15-06-2026
420
-
421
- =====================
422
-
423
- - Added explicit package exports for controls SCSS assets so Angular browser and application builders can resolve deep style imports from consuming packages.
424
- - Kept backward compatibility for extensionless Sass imports such as `@bnsights/bbsf-controls/src/lib/assets/sass/variables`.
425
- - Marked CSS, SCSS, and packaged assets as side-effectful so published global styles are preserved by consumers.
426
- - Added `LogoCropperComponent` as a standalone upload modal component exported from `@bnsights/bbsf-controls`.
427
- - Re-exported `LogoCropperComponent` through `BBSFUploadsModule` and the package public API.
428
- - Added `ngx-image-cropper` dependency for logo cropping support with Angular 19-compatible peer dependencies.
429
-
430
- ## 1.2.25 / 15-06-2026
431
-
432
- =====================
433
-
434
- - Replaced the BBSF MarkdownEditor engine with a Tiptap-powered markdown editor while keeping the existing `BBSF-MarkdownEditor` selector, options model, form integration, validation, and `BBSFEditorsModule` export.
435
- - Removed the old markdown editor runtime asset dependency path, including Ace and copied markdown editor assets.
436
- - Added Tiptap and PrimeIcons dependencies for the new MarkdownEditor toolbar and markdown serialization.
437
-
438
- ## 1.2.24 / 14-06-2026
439
-
440
- =====================
401
+ ## Change Log
402
+
403
+ ## 1.2.29 / 05-07-2026
404
+
405
+ =====================
406
+
407
+ - Added `allowMoveImage` support to `LogoCropperComponent` to pan the source image under a static crop box, with the CSS pointer-events fix (`.ngx-ic-cropper { pointer-events: none; }`) required to let drags reach the image instead of the crop-box overlay.
408
+ - Added `containWithinAspectRatio` support; padding is now computed from an `effectiveAspectRatio` getter so it matches the static crop box shape when one is set, instead of a mismatched `aspectRatio` input.
409
+ - Added 90° rotate left/right buttons using `canvasRotation` (does not clip corners like `transform.rotate`).
410
+ - Added a full reset button (zoom, pan, and rotation), replacing the previous zoom-only reset.
411
+ - Added mouse-wheel zoom on the cropper.
412
+ - Added `loadImageFailed` handling: logs the error, shows a toast, and dismisses the modal so the caller can clear the upload.
413
+ - Added optional display scaling (`maxDisplayWidth`/`maxDisplayHeight`, default `0` = disabled) so small target crop sizes can be shown enlarged on screen while the exported file is resized back to the true target dimensions.
414
+ - Extended `FileUploadCropperOptions` with `allowMoveImage`, `containWithinAspectRatio`, `maxDisplayWidth`, and `maxDisplayHeight`, threaded through `BBSF-FileUpload`'s cropper modal.
415
+ - Added `ResetZoom` and `ImageLoadFailed` resource keys.
416
+ - All additions are backward compatible; existing consumers are unaffected until they opt in.
417
+
418
+ ## 1.2.28 / 23-06-2026
419
+
420
+ =====================
421
+
422
+ - Added optional `FileUploadOptions` overrides for validation error message labels.
423
+ - Supported host-provided localized labels for max file count, min file count, total size, file size, type tooltip, duplicate file, and required validation messages.
424
+ - Threaded file upload options through validation helpers and applied the duplicate-file override message.
425
+
426
+ ## 1.2.27 / 22-06-2026
427
+
428
+ =====================
429
+
430
+ - Added optional image cropper support to `BBSF-FileUpload` through `FileUploadOptions.cropperOptions`.
431
+ - Added exported cropper option models for configuring modal behavior, orientation presets, and cancel behavior.
432
+ - Preserved existing upload behavior unless cropper options are explicitly enabled.
433
+
434
+ ## 1.2.26 / 15-06-2026
435
+
436
+ =====================
437
+
438
+ - Added explicit package exports for controls SCSS assets so Angular browser and application builders can resolve deep style imports from consuming packages.
439
+ - Kept backward compatibility for extensionless Sass imports such as `@bnsights/bbsf-controls/src/lib/assets/sass/variables`.
440
+ - Marked CSS, SCSS, and packaged assets as side-effectful so published global styles are preserved by consumers.
441
+ - Added `LogoCropperComponent` as a standalone upload modal component exported from `@bnsights/bbsf-controls`.
442
+ - Re-exported `LogoCropperComponent` through `BBSFUploadsModule` and the package public API.
443
+ - Added `ngx-image-cropper` dependency for logo cropping support with Angular 19-compatible peer dependencies.
444
+
445
+ ## 1.2.25 / 15-06-2026
446
+
447
+ =====================
448
+
449
+ - Replaced the BBSF MarkdownEditor engine with a Tiptap-powered markdown editor while keeping the existing `BBSF-MarkdownEditor` selector, options model, form integration, validation, and `BBSFEditorsModule` export.
450
+ - Removed the old markdown editor runtime asset dependency path, including Ace and copied markdown editor assets.
451
+ - Added Tiptap and PrimeIcons dependencies for the new MarkdownEditor toolbar and markdown serialization.
452
+
453
+ ## 1.2.24 / 14-06-2026
454
+
455
+ =====================
441
456
 
442
457
  - Add new file-upload props for override labels
443
458
  {
@@ -464,7 +479,7 @@ If the issue persists, consider using a different HTML editor component that's c
464
479
  - Fixed package stylesheet imports for Angular esbuild application builder compatibility.
465
480
  - Replaced webpack-era `/node_modules/...` SCSS imports in `src/lib/assets/Style.scss` with relative package imports.
466
481
  - Removed `.css` extensions from SCSS imports so Sass resolves and inlines vendor styles instead of leaving CSS `@import` statements for esbuild.
467
- - Fixed imports for Angular Material prebuilt theme, ngx-toastr, intl-tel-input, markdown editor styles, and angular-datetime-picker styles.
482
+ - Fixed imports for Angular Material prebuilt theme, ngx-toastr, intl-tel-input, markdown editor styles, and angular-datetime-picker styles.
468
483
 
469
484
  ## 1.2.22 / 06-05-2026
470
485
 
@@ -2568,6 +2568,14 @@ class FileUploadCropperOptions {
2568
2568
  this.backdrop = 'static';
2569
2569
  this.maintainAspectRatio = true;
2570
2570
  this.onlyScaleDown = true;
2571
+ this.allowMoveImage = false;
2572
+ this.containWithinAspectRatio = false;
2573
+ // Maximum on-screen size of the crop box; 0 keeps the crop box at its true
2574
+ // (output) size. When set, the output file is still resized back to the
2575
+ // preset's static dimensions. Pick values that fit the modal size (an
2576
+ // ng-bootstrap 'lg' modal body is ~770px wide).
2577
+ this.maxDisplayWidth = 0;
2578
+ this.maxDisplayHeight = 0;
2571
2579
  this.cancelBehavior = 'clear';
2572
2580
  this.horizontal = new FileUploadCropperPreset(3 / 1, 90, 45);
2573
2581
  this.vertical = new FileUploadCropperPreset(3 / 2, 200, 66);
@@ -7352,28 +7360,91 @@ class LogoCropperComponent {
7352
7360
  this.cropperStaticWidth = 0;
7353
7361
  this.cropperStaticHeight = 0;
7354
7362
  this.onlyScaleDown = true;
7355
- this.transform = { scale: 1 };
7363
+ this.allowMoveImage = false;
7364
+ this.containWithinAspectRatio = false;
7365
+ // Maximum on-screen size of the crop box; 0 disables display scaling and
7366
+ // keeps the crop box at its true (output) size.
7367
+ this.maxDisplayWidth = 0;
7368
+ this.maxDisplayHeight = 0;
7369
+ this.transform = { scale: 1, translateH: 0, translateV: 0, translateUnit: 'px' };
7370
+ this.canvasRotation = 0;
7356
7371
  this.croppedBlob = null;
7357
7372
  this.minScale = 1;
7358
7373
  this.maxScale = 4;
7359
7374
  this.scaleStep = 0.1;
7360
7375
  }
7361
7376
  ngOnInit() { }
7377
+ get displayScalingEnabled() {
7378
+ return this.maxDisplayWidth > 0 && this.maxDisplayHeight > 0 &&
7379
+ this.cropperStaticWidth > 0 && this.cropperStaticHeight > 0;
7380
+ }
7381
+ // Scale the crop box up so the user can see the image clearly while cropping,
7382
+ // while the uploaded file is resized back to the target dimensions.
7383
+ get displayScale() {
7384
+ if (!this.displayScalingEnabled)
7385
+ return 1;
7386
+ const scale = Math.min(this.maxDisplayWidth / this.cropperStaticWidth, this.maxDisplayHeight / this.cropperStaticHeight);
7387
+ return Math.max(1, scale);
7388
+ }
7389
+ get displayWidth() {
7390
+ return Math.round(this.cropperStaticWidth * this.displayScale);
7391
+ }
7392
+ get displayHeight() {
7393
+ return Math.round(this.cropperStaticHeight * this.displayScale);
7394
+ }
7395
+ // The contain-within-aspect-ratio padding is computed from the aspectRatio
7396
+ // option, so it must match the static crop box shape when one is set.
7397
+ get effectiveAspectRatio() {
7398
+ if (this.cropperStaticWidth && this.cropperStaticHeight) {
7399
+ return this.cropperStaticWidth / this.cropperStaticHeight;
7400
+ }
7401
+ return this.aspectRatio;
7402
+ }
7403
+ // Source-image size caps consumed by the component scss; null falls back to
7404
+ // the legacy fixed caps so display scaling stays opt-in.
7405
+ get sourceMaxHeight() {
7406
+ return this.displayScalingEnabled ? `${this.displayHeight}px` : null;
7407
+ }
7408
+ get sourceMaxWidth() {
7409
+ return this.displayScalingEnabled ? `${this.displayWidth}px` : null;
7410
+ }
7362
7411
  translate(key) {
7363
7412
  return this.utilityService.getResourceValue(key);
7364
7413
  }
7365
7414
  imageCropped(event) {
7366
7415
  this.croppedBlob = event.blob ?? null;
7367
7416
  }
7417
+ imageLoadFailed(error) {
7418
+ console.error('Logo cropper failed to load image', error);
7419
+ this.utilityService.notifyErrorMessage(this.translate('ImageLoadFailed'));
7420
+ this.activeModal.dismiss();
7421
+ }
7422
+ onWheel(event) {
7423
+ event.preventDefault();
7424
+ if (event.deltaY < 0)
7425
+ this.zoomIn();
7426
+ else if (event.deltaY > 0)
7427
+ this.zoomOut();
7428
+ }
7368
7429
  zoomIn() {
7369
7430
  this.setScale((this.transform.scale ?? 1) + this.scaleStep);
7370
7431
  }
7371
7432
  zoomOut() {
7372
7433
  this.setScale((this.transform.scale ?? 1) - this.scaleStep);
7373
7434
  }
7435
+ rotateLeft() {
7436
+ this.canvasRotation = (this.canvasRotation + 3) % 4;
7437
+ }
7438
+ rotateRight() {
7439
+ this.canvasRotation = (this.canvasRotation + 1) % 4;
7440
+ }
7374
7441
  resetZoom() {
7375
7442
  this.setScale(1);
7376
7443
  }
7444
+ reset() {
7445
+ this.canvasRotation = 0;
7446
+ this.transform = { scale: 1, translateH: 0, translateV: 0, translateUnit: 'px' };
7447
+ }
7377
7448
  confirm() {
7378
7449
  if (!this.croppedBlob)
7379
7450
  return;
@@ -7388,14 +7459,14 @@ class LogoCropperComponent {
7388
7459
  this.transform = { ...this.transform, scale: clamped };
7389
7460
  }
7390
7461
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.16", ngImport: i0, type: LogoCropperComponent, deps: [{ token: i4$1.NgbActiveModal }, { token: i3.UtilityService }], target: i0.ɵɵFactoryTarget.Component }); }
7391
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.16", type: LogoCropperComponent, isStandalone: true, selector: "BBSF-LogoCropper", inputs: { imageFile: "imageFile", isHorizontal: "isHorizontal", aspectRatio: "aspectRatio", maintainAspectRatio: "maintainAspectRatio", cropperStaticWidth: "cropperStaticWidth", cropperStaticHeight: "cropperStaticHeight", onlyScaleDown: "onlyScaleDown" }, ngImport: i0, template: "<div class=\"bbsf-logo-cropper\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">{{ translate(\"CropImage\") }}</h5>\n <button type=\"button\" class=\"btn-close\" (click)=\"dismiss()\"></button>\n </div>\n\n <div class=\"modal-body d-flex flex-column justify-content-center align-items-center py-0\" style=\"min-height: 200px;\">\n <image-cropper [class.crop-horizontal]=\"isHorizontal\" [class.crop-vertical]=\"!isHorizontal\" [imageFile]=\"imageFile\"\n [maintainAspectRatio]=\"maintainAspectRatio\" [aspectRatio]=\"aspectRatio\"\n [cropperStaticWidth]=\"cropperStaticWidth\" [cropperStaticHeight]=\"cropperStaticHeight\"\n [onlyScaleDown]=\"onlyScaleDown\" [transform]=\"transform\" format=\"png\" (imageCropped)=\"imageCropped($event)\">\n </image-cropper>\n\n <div class=\"d-flex justify-content-center align-items-center gap-2 mt-3\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomOut()\"\n [title]=\"translate('ZoomOut')\">\n <i class=\"fa fa-search-minus\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"resetZoom()\"\n [title]=\"translate('ResetZoom')\">\n <i class=\"fa fa-undo\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomIn()\" [title]=\"translate('ZoomIn')\">\n <i class=\"fa fa-search-plus\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-sm btn-light\" (click)=\"dismiss()\"> Cancel </button>\n <button type=\"button\" class=\"btn btn-sm btn-brand\" [disabled]=\"!croppedBlob\" (click)=\"confirm()\">\n {{ translate(\"Crop\") }}\n </button>\n </div>\n</div>\n", styles: [".bbsf-logo-cropper image-cropper.crop-horizontal .ngx-ic-source-image{max-height:45px!important;max-width:none!important}.bbsf-logo-cropper image-cropper.crop-vertical .ngx-ic-source-image{max-width:200px!important;max-height:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
7462
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.16", type: LogoCropperComponent, isStandalone: true, selector: "BBSF-LogoCropper", inputs: { imageFile: "imageFile", isHorizontal: "isHorizontal", aspectRatio: "aspectRatio", maintainAspectRatio: "maintainAspectRatio", cropperStaticWidth: "cropperStaticWidth", cropperStaticHeight: "cropperStaticHeight", onlyScaleDown: "onlyScaleDown", allowMoveImage: "allowMoveImage", containWithinAspectRatio: "containWithinAspectRatio", maxDisplayWidth: "maxDisplayWidth", maxDisplayHeight: "maxDisplayHeight" }, ngImport: i0, template: "<div class=\"bbsf-logo-cropper\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">{{ translate(\"CropImage\") }}</h5>\r\n <button type=\"button\" class=\"btn-close\" (click)=\"dismiss()\"></button>\r\n </div>\r\n\r\n <div class=\"modal-body d-flex flex-column justify-content-center align-items-center py-0\" style=\"min-height: 200px;\">\r\n <image-cropper [class.crop-horizontal]=\"isHorizontal\" [class.crop-vertical]=\"!isHorizontal\"\r\n [class.allow-move]=\"allowMoveImage\" [imageFile]=\"imageFile\"\r\n [style.--bbsf-cropper-source-max-height]=\"sourceMaxHeight\"\r\n [style.--bbsf-cropper-source-max-width]=\"sourceMaxWidth\"\r\n [maintainAspectRatio]=\"maintainAspectRatio\" [aspectRatio]=\"effectiveAspectRatio\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio\" [canvasRotation]=\"canvasRotation\"\r\n [cropperStaticWidth]=\"displayWidth\" [cropperStaticHeight]=\"displayHeight\"\r\n [resizeToWidth]=\"displayScalingEnabled ? cropperStaticWidth : 0\"\r\n [resizeToHeight]=\"displayScalingEnabled ? cropperStaticHeight : 0\"\r\n [onlyScaleDown]=\"onlyScaleDown\" [allowMoveImage]=\"allowMoveImage\" [(transform)]=\"transform\" format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\" (loadImageFailed)=\"imageLoadFailed($event)\" (wheel)=\"onWheel($event)\">\r\n </image-cropper>\r\n\r\n <div class=\"d-flex justify-content-center align-items-center gap-2 mt-3\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomOut()\"\r\n [title]=\"translate('ZoomOut')\">\r\n <i class=\"fa fa-search-minus\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomIn()\" [title]=\"translate('ZoomIn')\">\r\n <i class=\"fa fa-search-plus\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"rotateLeft()\"\r\n [title]=\"translate('RotateLeft')\">\r\n <i class=\"fa fa-rotate-left\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"rotateRight()\"\r\n [title]=\"translate('RotateRight')\">\r\n <i class=\"fa fa-rotate-right\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"reset()\"\r\n [title]=\"translate('ResetZoom')\">\r\n <i class=\"fa fa-refresh\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-sm btn-light\" (click)=\"dismiss()\"> Cancel </button>\r\n <button type=\"button\" class=\"btn btn-sm btn-brand\" [disabled]=\"!croppedBlob\" (click)=\"confirm()\">\r\n {{ translate(\"Crop\") }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".bbsf-logo-cropper image-cropper.crop-horizontal .ngx-ic-source-image{max-height:var(--bbsf-cropper-source-max-height, 45px)!important;max-width:none!important}.bbsf-logo-cropper image-cropper.crop-vertical .ngx-ic-source-image{max-width:var(--bbsf-cropper-source-max-width, 200px)!important;max-height:none!important}.bbsf-logo-cropper image-cropper.allow-move .ngx-ic-cropper{pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
7392
7463
  }
7393
7464
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.16", ngImport: i0, type: LogoCropperComponent, decorators: [{
7394
7465
  type: Component,
7395
7466
  args: [{ selector: 'BBSF-LogoCropper', encapsulation: ViewEncapsulation.None, standalone: true, imports: [
7396
7467
  CommonModule,
7397
7468
  ImageCropperComponent
7398
- ], template: "<div class=\"bbsf-logo-cropper\">\n <div class=\"modal-header\">\n <h5 class=\"modal-title\">{{ translate(\"CropImage\") }}</h5>\n <button type=\"button\" class=\"btn-close\" (click)=\"dismiss()\"></button>\n </div>\n\n <div class=\"modal-body d-flex flex-column justify-content-center align-items-center py-0\" style=\"min-height: 200px;\">\n <image-cropper [class.crop-horizontal]=\"isHorizontal\" [class.crop-vertical]=\"!isHorizontal\" [imageFile]=\"imageFile\"\n [maintainAspectRatio]=\"maintainAspectRatio\" [aspectRatio]=\"aspectRatio\"\n [cropperStaticWidth]=\"cropperStaticWidth\" [cropperStaticHeight]=\"cropperStaticHeight\"\n [onlyScaleDown]=\"onlyScaleDown\" [transform]=\"transform\" format=\"png\" (imageCropped)=\"imageCropped($event)\">\n </image-cropper>\n\n <div class=\"d-flex justify-content-center align-items-center gap-2 mt-3\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomOut()\"\n [title]=\"translate('ZoomOut')\">\n <i class=\"fa fa-search-minus\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"resetZoom()\"\n [title]=\"translate('ResetZoom')\">\n <i class=\"fa fa-undo\"></i>\n </button>\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomIn()\" [title]=\"translate('ZoomIn')\">\n <i class=\"fa fa-search-plus\"></i>\n </button>\n </div>\n </div>\n\n <div class=\"modal-footer\">\n <button type=\"button\" class=\"btn btn-sm btn-light\" (click)=\"dismiss()\"> Cancel </button>\n <button type=\"button\" class=\"btn btn-sm btn-brand\" [disabled]=\"!croppedBlob\" (click)=\"confirm()\">\n {{ translate(\"Crop\") }}\n </button>\n </div>\n</div>\n", styles: [".bbsf-logo-cropper image-cropper.crop-horizontal .ngx-ic-source-image{max-height:45px!important;max-width:none!important}.bbsf-logo-cropper image-cropper.crop-vertical .ngx-ic-source-image{max-width:200px!important;max-height:none!important}\n"] }]
7469
+ ], template: "<div class=\"bbsf-logo-cropper\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\">{{ translate(\"CropImage\") }}</h5>\r\n <button type=\"button\" class=\"btn-close\" (click)=\"dismiss()\"></button>\r\n </div>\r\n\r\n <div class=\"modal-body d-flex flex-column justify-content-center align-items-center py-0\" style=\"min-height: 200px;\">\r\n <image-cropper [class.crop-horizontal]=\"isHorizontal\" [class.crop-vertical]=\"!isHorizontal\"\r\n [class.allow-move]=\"allowMoveImage\" [imageFile]=\"imageFile\"\r\n [style.--bbsf-cropper-source-max-height]=\"sourceMaxHeight\"\r\n [style.--bbsf-cropper-source-max-width]=\"sourceMaxWidth\"\r\n [maintainAspectRatio]=\"maintainAspectRatio\" [aspectRatio]=\"effectiveAspectRatio\"\r\n [containWithinAspectRatio]=\"containWithinAspectRatio\" [canvasRotation]=\"canvasRotation\"\r\n [cropperStaticWidth]=\"displayWidth\" [cropperStaticHeight]=\"displayHeight\"\r\n [resizeToWidth]=\"displayScalingEnabled ? cropperStaticWidth : 0\"\r\n [resizeToHeight]=\"displayScalingEnabled ? cropperStaticHeight : 0\"\r\n [onlyScaleDown]=\"onlyScaleDown\" [allowMoveImage]=\"allowMoveImage\" [(transform)]=\"transform\" format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\" (loadImageFailed)=\"imageLoadFailed($event)\" (wheel)=\"onWheel($event)\">\r\n </image-cropper>\r\n\r\n <div class=\"d-flex justify-content-center align-items-center gap-2 mt-3\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomOut()\"\r\n [title]=\"translate('ZoomOut')\">\r\n <i class=\"fa fa-search-minus\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"zoomIn()\" [title]=\"translate('ZoomIn')\">\r\n <i class=\"fa fa-search-plus\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"rotateLeft()\"\r\n [title]=\"translate('RotateLeft')\">\r\n <i class=\"fa fa-rotate-left\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"rotateRight()\"\r\n [title]=\"translate('RotateRight')\">\r\n <i class=\"fa fa-rotate-right\"></i>\r\n </button>\r\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"reset()\"\r\n [title]=\"translate('ResetZoom')\">\r\n <i class=\"fa fa-refresh\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-sm btn-light\" (click)=\"dismiss()\"> Cancel </button>\r\n <button type=\"button\" class=\"btn btn-sm btn-brand\" [disabled]=\"!croppedBlob\" (click)=\"confirm()\">\r\n {{ translate(\"Crop\") }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".bbsf-logo-cropper image-cropper.crop-horizontal .ngx-ic-source-image{max-height:var(--bbsf-cropper-source-max-height, 45px)!important;max-width:none!important}.bbsf-logo-cropper image-cropper.crop-vertical .ngx-ic-source-image{max-width:var(--bbsf-cropper-source-max-width, 200px)!important;max-height:none!important}.bbsf-logo-cropper image-cropper.allow-move .ngx-ic-cropper{pointer-events:none}\n"] }]
7399
7470
  }], ctorParameters: () => [{ type: i4$1.NgbActiveModal }, { type: i3.UtilityService }], propDecorators: { imageFile: [{
7400
7471
  type: Input
7401
7472
  }], isHorizontal: [{
@@ -7410,6 +7481,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.16", ngImpo
7410
7481
  type: Input
7411
7482
  }], onlyScaleDown: [{
7412
7483
  type: Input
7484
+ }], allowMoveImage: [{
7485
+ type: Input
7486
+ }], containWithinAspectRatio: [{
7487
+ type: Input
7488
+ }], maxDisplayWidth: [{
7489
+ type: Input
7490
+ }], maxDisplayHeight: [{
7491
+ type: Input
7413
7492
  }] } });
7414
7493
 
7415
7494
  class FileUploadComponent {
@@ -8002,6 +8081,10 @@ class FileUploadComponent {
8002
8081
  modalRef.componentInstance.cropperStaticHeight = preset.cropperStaticHeight;
8003
8082
  modalRef.componentInstance.maintainAspectRatio = cropperOptions.maintainAspectRatio;
8004
8083
  modalRef.componentInstance.onlyScaleDown = cropperOptions.onlyScaleDown;
8084
+ modalRef.componentInstance.allowMoveImage = cropperOptions.allowMoveImage;
8085
+ modalRef.componentInstance.containWithinAspectRatio = cropperOptions.containWithinAspectRatio;
8086
+ modalRef.componentInstance.maxDisplayWidth = cropperOptions.maxDisplayWidth;
8087
+ modalRef.componentInstance.maxDisplayHeight = cropperOptions.maxDisplayHeight;
8005
8088
  modalRef.result.then((croppedFile) => {
8006
8089
  this.readCroppedFile(addedFile, croppedFile);
8007
8090
  }).catch(() => {