croco-html 20.5.0 → 20.5.2

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Inject, Injectable, EventEmitter, Output, Input, ViewChild, Component, inject, ChangeDetectorRef, ChangeDetectionStrategy, ViewContainerRef, DestroyRef, ViewEncapsulation, Pipe, NgModule } from '@angular/core';
2
+ import { Inject, Injectable, EventEmitter, Output, Input, ViewChild, Component, inject, ChangeDetectorRef, ChangeDetectionStrategy, ViewContainerRef, DestroyRef, ViewEncapsulation, signal, computed, Pipe, NgModule } from '@angular/core';
3
3
  import * as i2 from '@angular/material/button';
4
4
  import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/button';
5
5
  import * as i1 from '@angular/common/http';
@@ -3607,45 +3607,55 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImpo
3607
3607
 
3608
3608
  class TextEditorComponent {
3609
3609
  constructor() {
3610
- this.unsubscribe = new Subject();
3611
- this._cdr = inject(ChangeDetectorRef);
3612
- this.presentOrEdit = true;
3610
+ this._destroy$ = new Subject();
3611
+ this.tag = signal(null, ...(ngDevMode ? [{ debugName: "tag" }] : /* istanbul ignore next */ []));
3612
+ this.presentOrEdit = signal(true, ...(ngDevMode ? [{ debugName: "presentOrEdit" }] : /* istanbul ignore next */ []));
3613
+ this.horizontalAlignment = signal(TextAlignment.Left, ...(ngDevMode ? [{ debugName: "horizontalAlignment" }] : /* istanbul ignore next */ []));
3614
+ this.previewHtml = computed(() => {
3615
+ const t = this.tag();
3616
+ if (!t)
3617
+ return '';
3618
+ return `<${t.tagDescription.tag}>${t.innerHtml}</${t.tagDescription.tag}>`;
3619
+ }, ...(ngDevMode ? [{ debugName: "previewHtml" }] : /* istanbul ignore next */ []));
3613
3620
  this.TextAlignment = TextAlignment;
3614
- this._horizontalAlignment = TextAlignment.Left;
3615
3621
  }
3616
3622
  set tagService(data) {
3617
- this._tagService = data;
3618
- this._tagService.tag$
3619
- .pipe(takeUntil(this.unsubscribe))
3620
- .subscribe(tag => {
3621
- this._tag = tag;
3622
- this._cdr.markForCheck();
3623
+ this._currentService = data;
3624
+ data.tag$.pipe(takeUntil(this._destroy$)).subscribe(t => {
3625
+ this.tag.set(t);
3626
+ if (t) {
3627
+ const align = t.attributes.hasOwnProperty(TextTagDataConsts.HAlign)
3628
+ ? t.attributes[TextTagDataConsts.HAlign]
3629
+ : TextAlignment.Left;
3630
+ this.horizontalAlignment.set(align);
3631
+ }
3623
3632
  });
3624
- this._tagService.presentOrEdit$
3625
- .pipe(takeUntil(this.unsubscribe))
3626
- .subscribe(val => {
3627
- this.presentOrEdit = val;
3628
- this._cdr.markForCheck();
3633
+ data.presentOrEdit$.pipe(takeUntil(this._destroy$)).subscribe(val => {
3634
+ this.presentOrEdit.set(val);
3629
3635
  });
3630
- this._horizontalAlignment = this._tag.attributes.hasOwnProperty(TextTagDataConsts.HAlign)
3631
- ? this._tag.attributes[TextTagDataConsts.HAlign]
3632
- : TextAlignment.Left;
3633
- this._cdr.markForCheck();
3634
3636
  }
3635
- changeData() {
3636
- this._tag.attributes[TextTagDataConsts.HAlign] = this._horizontalAlignment;
3637
- this._tagService.tag$.next(this._tag);
3638
- this._cdr.markForCheck();
3637
+ onInnerHtmlChange(newInnerHtml) {
3638
+ const tag = this.tag();
3639
+ if (tag) {
3640
+ const updated = { ...tag, innerHtml: newInnerHtml, attributes: { ...tag.attributes } };
3641
+ this.tag.set(updated);
3642
+ this._currentService.tag$.next(updated);
3643
+ }
3639
3644
  }
3640
- getInnerHtml() {
3641
- return `<${this._tag.tagDescription.tag}>${this._tag.innerHtml}<${this._tag.tagDescription.tag}/>`;
3645
+ onAlignmentChange() {
3646
+ const tag = this.tag();
3647
+ if (tag && tag.attributes) {
3648
+ const updated = { ...tag, attributes: { ...tag.attributes, [TextTagDataConsts.HAlign]: this.horizontalAlignment() } };
3649
+ this.tag.set(updated);
3650
+ this._currentService.tag$.next(updated);
3651
+ }
3642
3652
  }
3643
3653
  ngOnDestroy() {
3644
- this.unsubscribe.next();
3645
- this.unsubscribe.complete();
3654
+ this._destroy$.next();
3655
+ this._destroy$.complete();
3646
3656
  }
3647
3657
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: TextEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3648
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.26", type: TextEditorComponent, isStandalone: true, selector: "croco-html-text-editor", inputs: { tagService: "tagService" }, ngImport: i0, template: "@if (presentOrEdit) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n @if (_horizontalAlignment === TextAlignment.Left) {\n <div style=\"text-align: left;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @else if (_horizontalAlignment === TextAlignment.Right) {\n <div style=\"text-align: right;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @else if (_horizontalAlignment === TextAlignment.Center) {\n <div style=\"text-align: center;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n </div>\n}\n@else {\n <div>\n <div style=\"overflow-x: auto;\">\n <mat-button-toggle-group [(ngModel)]=\"_horizontalAlignment\" (ngModelChange)=\"changeData()\">\n <mat-button-toggle value=\"center\">\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"right\">\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430</mat-label>\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\n [(ngModel)]=\"_tag.innerHtml\" (ngModelChange)=\"changeData()\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}\n", dependencies: [{ kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$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]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3658
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.26", type: TextEditorComponent, isStandalone: true, selector: "croco-html-text-editor", inputs: { tagService: "tagService" }, ngImport: i0, template: "@if (presentOrEdit()) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n @if (horizontalAlignment() === TextAlignment.Left) {\n <div style=\"text-align: left;\" [innerHtml]=\"previewHtml()\">\n </div>\n }\n @else if (horizontalAlignment() === TextAlignment.Right) {\n <div style=\"text-align: right;\" [innerHtml]=\"previewHtml()\">\n </div>\n }\n @else if (horizontalAlignment() === TextAlignment.Center) {\n <div style=\"text-align: center;\" [innerHtml]=\"previewHtml()\">\n </div>\n }\n </div>\n}\n@else {\n <div>\n <div style=\"overflow-x: auto;\">\n <mat-button-toggle-group [(ngModel)]=\"horizontalAlignment\" (ngModelChange)=\"onAlignmentChange()\">\n <mat-button-toggle value=\"center\">\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"right\">\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430</mat-label>\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\n [ngModel]=\"tag()!.innerHtml\" (ngModelChange)=\"onInnerHtmlChange($event)\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}\n", dependencies: [{ kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$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]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3649
3659
  }
3650
3660
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImport: i0, type: TextEditorComponent, decorators: [{
3651
3661
  type: Component,
@@ -3658,7 +3668,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImpo
3658
3668
  MatLabel,
3659
3669
  MatInput,
3660
3670
  CdkTextareaAutosize
3661
- ], template: "@if (presentOrEdit) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n @if (_horizontalAlignment === TextAlignment.Left) {\n <div style=\"text-align: left;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @else if (_horizontalAlignment === TextAlignment.Right) {\n <div style=\"text-align: right;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n @else if (_horizontalAlignment === TextAlignment.Center) {\n <div style=\"text-align: center;\" [innerHtml]=\"getInnerHtml()\">\n </div>\n }\n </div>\n}\n@else {\n <div>\n <div style=\"overflow-x: auto;\">\n <mat-button-toggle-group [(ngModel)]=\"_horizontalAlignment\" (ngModelChange)=\"changeData()\">\n <mat-button-toggle value=\"center\">\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"right\">\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430</mat-label>\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\n [(ngModel)]=\"_tag.innerHtml\" (ngModelChange)=\"changeData()\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}\n" }]
3671
+ ], template: "@if (presentOrEdit()) {\n <div>\n <div style=\"height: 10px;\">\n </div>\n @if (horizontalAlignment() === TextAlignment.Left) {\n <div style=\"text-align: left;\" [innerHtml]=\"previewHtml()\">\n </div>\n }\n @else if (horizontalAlignment() === TextAlignment.Right) {\n <div style=\"text-align: right;\" [innerHtml]=\"previewHtml()\">\n </div>\n }\n @else if (horizontalAlignment() === TextAlignment.Center) {\n <div style=\"text-align: center;\" [innerHtml]=\"previewHtml()\">\n </div>\n }\n </div>\n}\n@else {\n <div>\n <div style=\"overflow-x: auto;\">\n <mat-button-toggle-group [(ngModel)]=\"horizontalAlignment\" (ngModelChange)=\"onAlignmentChange()\">\n <mat-button-toggle value=\"center\">\n \u041F\u043E \u0446\u0435\u043D\u0442\u0440\u0443 <mat-icon>format_align_center</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n \u0421\u043B\u0435\u0432\u0430 <mat-icon>format_align_left</mat-icon>\n </mat-button-toggle>\n <mat-button-toggle value=\"right\">\n \u0421\u043F\u0440\u0430\u0432\u0430 <mat-icon> format_align_right</mat-icon>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div style=\"height: 10px;\">\n </div>\n <div>\n <mat-form-field class=\"w-100\">\n <mat-label>\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430</mat-label>\n <textarea matInput cdkTextareaAutosize #autosize=\"cdkTextareaAutosize\"\n cdkAutosizeMinRows=\"1\"\n placeholder=\"\u0412\u043D\u0443\u0442\u0440\u0435\u043D\u043D\u044F\u044F \u0440\u0430\u0437\u043C\u0435\u0442\u043A\u0430 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u043E\u0433\u043E \u0442\u0435\u0433\u0430\"\n [ngModel]=\"tag()!.innerHtml\" (ngModelChange)=\"onInnerHtmlChange($event)\"></textarea>\n </mat-form-field>\n </div>\n </div>\n}\n" }]
3662
3672
  }], propDecorators: { tagService: [{
3663
3673
  type: Input,
3664
3674
  args: [{ required: true }]
@@ -3809,8 +3819,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.26", ngImpo
3809
3819
  class MainEditorBlockComponent {
3810
3820
  set tag(data) {
3811
3821
  this._tagSub$.next();
3812
- // Capture the original tag before the new one is set (for diff tracking)
3813
- this._originalTagBeforeSet = this._tag;
3822
+ this._originalSnapshot = MainEditorBlockComponent.copyTag(this._tag);
3814
3823
  this._tag = data;
3815
3824
  this._tagService = new TagEditorService();
3816
3825
  this._tagService.tag$.next(this._tag);
@@ -3829,22 +3838,23 @@ class MainEditorBlockComponent {
3829
3838
  this._cdr = inject(ChangeDetectorRef);
3830
3839
  this._changeDetector = inject(TagChangeDetector);
3831
3840
  this._tag = null;
3832
- this._originalTagBeforeSet = null;
3841
+ this._originalSnapshot = null;
3833
3842
  this.presentOrEdit = true;
3834
3843
  this.onTagSaved = new EventEmitter();
3835
3844
  this.onTagRemoved = new EventEmitter();
3836
3845
  }
3837
3846
  save() {
3838
3847
  const tag = this._tagService.tag$.value;
3839
- // Optimisation: skip if nothing actually changed
3840
- if (this._originalTagBeforeSet && this._changeDetector.tagsAreEqual(this._originalTagBeforeSet, tag)) {
3848
+ if (this._originalSnapshot && this._changeDetector.tagsAreEqual(this._originalSnapshot, tag)) {
3841
3849
  this._tagService.presentOrEdit$.next(true);
3842
3850
  return;
3843
3851
  }
3844
3852
  this.onTagSaved.emit(tag);
3845
3853
  this._tagService.presentOrEdit$.next(true);
3846
- // Reset original for next edit cycle
3847
- this._originalTagBeforeSet = tag;
3854
+ this._originalSnapshot = MainEditorBlockComponent.copyTag(tag);
3855
+ }
3856
+ static copyTag(tag) {
3857
+ return JSON.parse(JSON.stringify(tag));
3848
3858
  }
3849
3859
  cancelSave() {
3850
3860
  this._tagService.presentOrEdit$.next(false);