@ngstarter-ui/components 21.0.30 → 21.0.31

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.
Files changed (28) hide show
  1. package/ai/component-registry.json +49 -10
  2. package/fesm2022/{ngstarter-ui-components-content-editor-code-block.component-CKrOhA7h.mjs → ngstarter-ui-components-content-editor-code-block.component-BZniTqu-.mjs} +2 -2
  3. package/fesm2022/{ngstarter-ui-components-content-editor-code-block.component-CKrOhA7h.mjs.map → ngstarter-ui-components-content-editor-code-block.component-BZniTqu-.mjs.map} +1 -1
  4. package/fesm2022/{ngstarter-ui-components-content-editor-embed-block-zSApBzF3.mjs → ngstarter-ui-components-content-editor-embed-block-QzDMzd3u.mjs} +2 -2
  5. package/fesm2022/{ngstarter-ui-components-content-editor-embed-block-zSApBzF3.mjs.map → ngstarter-ui-components-content-editor-embed-block-QzDMzd3u.mjs.map} +1 -1
  6. package/fesm2022/{ngstarter-ui-components-content-editor-heading-block.component-Dv8d0nCy.mjs → ngstarter-ui-components-content-editor-heading-block.component-CnYRnDBY.mjs} +2 -2
  7. package/fesm2022/{ngstarter-ui-components-content-editor-heading-block.component-Dv8d0nCy.mjs.map → ngstarter-ui-components-content-editor-heading-block.component-CnYRnDBY.mjs.map} +1 -1
  8. package/fesm2022/{ngstarter-ui-components-content-editor-image-block.component-g-H7a5Z_.mjs → ngstarter-ui-components-content-editor-image-block.component-IP_eRCQ2.mjs} +2 -2
  9. package/fesm2022/{ngstarter-ui-components-content-editor-image-block.component-g-H7a5Z_.mjs.map → ngstarter-ui-components-content-editor-image-block.component-IP_eRCQ2.mjs.map} +1 -1
  10. package/fesm2022/{ngstarter-ui-components-content-editor-list-block.component-PgqisgxY.mjs → ngstarter-ui-components-content-editor-list-block.component-amyfzXOW.mjs} +2 -2
  11. package/fesm2022/{ngstarter-ui-components-content-editor-list-block.component-PgqisgxY.mjs.map → ngstarter-ui-components-content-editor-list-block.component-amyfzXOW.mjs.map} +1 -1
  12. package/fesm2022/{ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs → ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs} +453 -36
  13. package/fesm2022/ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs.map +1 -0
  14. package/fesm2022/{ngstarter-ui-components-content-editor-paragraph-block.component-DS_6CzuA.mjs → ngstarter-ui-components-content-editor-paragraph-block.component-DtophI4_.mjs} +2 -2
  15. package/fesm2022/{ngstarter-ui-components-content-editor-paragraph-block.component-DS_6CzuA.mjs.map → ngstarter-ui-components-content-editor-paragraph-block.component-DtophI4_.mjs.map} +1 -1
  16. package/fesm2022/{ngstarter-ui-components-content-editor-quote-block.component-Df92Nqvp.mjs → ngstarter-ui-components-content-editor-quote-block.component-B20eHQdw.mjs} +2 -2
  17. package/fesm2022/{ngstarter-ui-components-content-editor-quote-block.component-Df92Nqvp.mjs.map → ngstarter-ui-components-content-editor-quote-block.component-B20eHQdw.mjs.map} +1 -1
  18. package/fesm2022/{ngstarter-ui-components-content-editor-table-block.component-D4rdPkGz.mjs → ngstarter-ui-components-content-editor-table-block.component-hJ4OxKRX.mjs} +4 -4
  19. package/fesm2022/{ngstarter-ui-components-content-editor-table-block.component-D4rdPkGz.mjs.map → ngstarter-ui-components-content-editor-table-block.component-hJ4OxKRX.mjs.map} +1 -1
  20. package/fesm2022/{ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs → ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs} +2 -2
  21. package/fesm2022/{ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs.map → ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs.map} +1 -1
  22. package/fesm2022/ngstarter-ui-components-content-editor.mjs +1 -1
  23. package/fesm2022/ngstarter-ui-components-toolbar.mjs +2 -2
  24. package/fesm2022/ngstarter-ui-components-toolbar.mjs.map +1 -1
  25. package/package.json +1 -1
  26. package/styles/_global.scss +11 -0
  27. package/types/ngstarter-ui-components-content-editor.d.ts +226 -7
  28. package/fesm2022/ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs.map +0 -1
@@ -1,15 +1,15 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, Component, model, input, output, Renderer2, signal, computed, Input as Input$1, InjectionToken, EventEmitter, HostListener, Output, Directive, PLATFORM_ID, ElementRef, EnvironmentInjector, ChangeDetectorRef, numberAttribute, runInInjectionContext, effect, forwardRef, ChangeDetectionStrategy } from '@angular/core';
2
+ import { Injectable, inject, Component, model, input, output, Renderer2, signal, computed, Input as Input$1, InjectionToken, EventEmitter, HostListener, Output, Directive, PLATFORM_ID, ElementRef, EnvironmentInjector, ChangeDetectorRef, numberAttribute, booleanAttribute, runInInjectionContext, effect, forwardRef, ChangeDetectionStrategy, makeEnvironmentProviders } from '@angular/core';
3
3
  import { Button } from '@ngstarter-ui/components/button';
4
4
  import { Icon } from '@ngstarter-ui/components/icon';
5
5
  import { Menu, MenuItem, MenuTrigger, MenuHeading } from '@ngstarter-ui/components/menu';
6
- import { DialogRef, DialogContent, DialogTitle, DialogActions, DialogClose, DIALOG_DATA, Dialog } from '@ngstarter-ui/components/dialog';
6
+ import { DialogRef, DialogContent, DialogTitle, DialogActions, DIALOG_DATA, Dialog } from '@ngstarter-ui/components/dialog';
7
7
  import { Input } from '@ngstarter-ui/components/input';
8
8
  import { FormField, Label, Hint } from '@ngstarter-ui/components/form-field';
9
9
  import * as i1 from '@angular/forms';
10
10
  import { FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
11
11
  import { SlideToggle } from '@ngstarter-ui/components/slide-toggle';
12
- import { DOCUMENT, isPlatformBrowser, isPlatformServer, NgComponentOutlet, AsyncPipe } from '@angular/common';
12
+ import { DOCUMENT, isPlatformBrowser, isPlatformServer, NgComponentOutlet, AsyncPipe, NgTemplateOutlet } from '@angular/common';
13
13
  import { Tooltip } from '@ngstarter-ui/components/tooltip';
14
14
  import { v7 } from 'uuid';
15
15
  import { signalStore, withState, withMethods, patchState } from '@ngrx/signals';
@@ -24,6 +24,10 @@ import SelectionArea from '@viselect/vanilla';
24
24
  import { PopoverTriggerForDirective, Popover } from '@ngstarter-ui/components/popover';
25
25
  import { SelectionModel } from '@angular/cdk/collections';
26
26
  import { ListItemTitle, ListItemIcon, ListItem, List } from '@ngstarter-ui/components/list';
27
+ import { CodeHighlighter } from '@ngstarter-ui/components/code-highlighter';
28
+ import { Divider } from '@ngstarter-ui/components/divider';
29
+ import { SafeResourceUrlPipe, SafeHtmlPipe } from '@ngstarter-ui/components/core';
30
+ import { NativeTable } from '@ngstarter-ui/components/table';
27
31
 
28
32
  class TextHighlightService {
29
33
  savedRange = null;
@@ -569,7 +573,7 @@ class AddLinkDialog {
569
573
  this._dialogRef.close(this.form.value);
570
574
  }
571
575
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AddLinkDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
572
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: AddLinkDialog, isStandalone: true, selector: "ngs-add-link", ngImport: i0, template: "<h1 ngs-dialog-title>Add link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [ngs-dialog-close]=\"true\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Add</button>\n</ngs-dialog-actions>\n", styles: [""], dependencies: [{ kind: "component", type: DialogContent, selector: "ngs-dialog-content,[ngs-dialog-content],[ngsDialogContent]" }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: DialogTitle, selector: "ngs-dialog-title, [ngs-dialog-title], [ngsDialogTitle]", inputs: ["id"], exportAs: ["ngsDialogTitle"] }, { kind: "component", type: DialogActions, selector: "ngs-dialog-actions, [ngs-dialog-actions], [ngsDialogActions]", inputs: ["align"] }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "directive", type: DialogClose, selector: "[ngs-dialog-close], [ngsDialogClose]", inputs: ["ngs-dialog-close", "ngsDialogClose", "ariaLabel", "type"], exportAs: ["ngsDialogClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "component", type: SlideToggle, selector: "ngs-slide-toggle", inputs: ["id", "name", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "disabled", "disableRipple", "tabIndex", "hideIcon", "color", "checked"], outputs: ["disabledChange", "checkedChange", "change", "toggleChange"], exportAs: ["ngsSlideToggle"] }] });
576
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: AddLinkDialog, isStandalone: true, selector: "ngs-add-link", ngImport: i0, template: "<h1 ngs-dialog-title>Add link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Add</button>\n</ngs-dialog-actions>\n", styles: [""], dependencies: [{ kind: "component", type: DialogContent, selector: "ngs-dialog-content,[ngs-dialog-content],[ngsDialogContent]" }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: DialogTitle, selector: "ngs-dialog-title, [ngs-dialog-title], [ngsDialogTitle]", inputs: ["id"], exportAs: ["ngsDialogTitle"] }, { kind: "component", type: DialogActions, selector: "ngs-dialog-actions, [ngs-dialog-actions], [ngsDialogActions]", inputs: ["align"] }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "component", type: SlideToggle, selector: "ngs-slide-toggle", inputs: ["id", "name", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "disabled", "disableRipple", "tabIndex", "hideIcon", "color", "checked"], outputs: ["disabledChange", "checkedChange", "change", "toggleChange"], exportAs: ["ngsSlideToggle"] }] });
573
577
  }
574
578
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AddLinkDialog, decorators: [{
575
579
  type: Component,
@@ -580,11 +584,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
580
584
  DialogTitle,
581
585
  DialogActions,
582
586
  Button,
583
- DialogClose,
584
587
  ReactiveFormsModule,
585
588
  Label,
586
589
  SlideToggle
587
- ], template: "<h1 ngs-dialog-title>Add link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [ngs-dialog-close]=\"true\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Add</button>\n</ngs-dialog-actions>\n" }]
590
+ ], template: "<h1 ngs-dialog-title>Add link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Add</button>\n</ngs-dialog-actions>\n" }]
588
591
  }] });
589
592
 
590
593
  class EditLinkDialog {
@@ -602,7 +605,7 @@ class EditLinkDialog {
602
605
  this._dialogRef.close(this.form.value);
603
606
  }
604
607
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EditLinkDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
605
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: EditLinkDialog, isStandalone: true, selector: "ngs-edit-link", ngImport: i0, template: "<h1 ngs-dialog-title>Edit link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n <ngs-hint>To delete the link, clear this field and apply</ngs-hint>\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\" class=\"mt-5\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [ngs-dialog-close]=\"true\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Apply</button>\n</ngs-dialog-actions>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: DialogActions, selector: "ngs-dialog-actions, [ngs-dialog-actions], [ngsDialogActions]", inputs: ["align"] }, { kind: "component", type: DialogContent, selector: "ngs-dialog-content,[ngs-dialog-content],[ngsDialogContent]" }, { kind: "component", type: DialogTitle, selector: "ngs-dialog-title, [ngs-dialog-title], [ngsDialogTitle]", inputs: ["id"], exportAs: ["ngsDialogTitle"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "component", type: SlideToggle, selector: "ngs-slide-toggle", inputs: ["id", "name", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "disabled", "disableRipple", "tabIndex", "hideIcon", "color", "checked"], outputs: ["disabledChange", "checkedChange", "change", "toggleChange"], exportAs: ["ngsSlideToggle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: DialogClose, selector: "[ngs-dialog-close], [ngsDialogClose]", inputs: ["ngs-dialog-close", "ngsDialogClose", "ariaLabel", "type"], exportAs: ["ngsDialogClose"] }, { kind: "component", type: Hint, selector: "ngs-hint", inputs: ["align"], exportAs: ["ngsHint"] }] });
608
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: EditLinkDialog, isStandalone: true, selector: "ngs-edit-link", ngImport: i0, template: "<h1 ngs-dialog-title>Edit link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n <ngs-hint>To delete the link, clear this field and apply</ngs-hint>\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\" class=\"mt-5\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Apply</button>\n</ngs-dialog-actions>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: DialogActions, selector: "ngs-dialog-actions, [ngs-dialog-actions], [ngsDialogActions]", inputs: ["align"] }, { kind: "component", type: DialogContent, selector: "ngs-dialog-content,[ngs-dialog-content],[ngsDialogContent]" }, { kind: "component", type: DialogTitle, selector: "ngs-dialog-title, [ngs-dialog-title], [ngsDialogTitle]", inputs: ["id"], exportAs: ["ngsDialogTitle"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Label, selector: "ngs-label" }, { kind: "component", type: SlideToggle, selector: "ngs-slide-toggle", inputs: ["id", "name", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "disabled", "disableRipple", "tabIndex", "hideIcon", "color", "checked"], outputs: ["disabledChange", "checkedChange", "change", "toggleChange"], exportAs: ["ngsSlideToggle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: Hint, selector: "ngs-hint", inputs: ["align"], exportAs: ["ngsHint"] }] });
606
609
  }
607
610
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: EditLinkDialog, decorators: [{
608
611
  type: Component,
@@ -617,9 +620,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
617
620
  Label,
618
621
  SlideToggle,
619
622
  ReactiveFormsModule,
620
- DialogClose,
621
623
  Hint
622
- ], template: "<h1 ngs-dialog-title>Edit link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n <ngs-hint>To delete the link, clear this field and apply</ngs-hint>\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\" class=\"mt-5\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [ngs-dialog-close]=\"true\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Apply</button>\n</ngs-dialog-actions>\n" }]
624
+ ], template: "<h1 ngs-dialog-title>Edit link</h1>\n<ngs-dialog-content [formGroup]=\"form\" class=\"!overflow-hidden\">\n <ngs-form-field class=\"w-full\">\n <ngs-label>Href (Url, Tel or other)</ngs-label>\n <input ngsInput type=\"text\" formControlName=\"href\">\n <ngs-hint>To delete the link, clear this field and apply</ngs-hint>\n </ngs-form-field>\n <ngs-slide-toggle formControlName=\"openInNewTab\" class=\"mt-5\">Open link in a new tab</ngs-slide-toggle>\n</ngs-dialog-content>\n<ngs-dialog-actions>\n <button ngsButton (click)=\"cancel()\">Cancel</button>\n <button ngsButton=\"filled\"\n [disabled]=\"form.invalid\" (click)=\"add()\">Apply</button>\n</ngs-dialog-actions>\n" }]
623
625
  }] });
624
626
 
625
627
  class TextColorComponent {
@@ -779,6 +781,7 @@ class CommandBarComponent {
779
781
  _renderer = inject(Renderer2);
780
782
  _dialog = inject(Dialog);
781
783
  observedElement = null;
784
+ _linkDialogOpen = false;
782
785
  props = signal([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
783
786
  alignment = computed(() => {
784
787
  const alignment = this.props().find(prop => prop.name === 'text-alignment');
@@ -827,12 +830,14 @@ class CommandBarComponent {
827
830
  }
828
831
  addLink() {
829
832
  this._textHighlightService.toggleWrapSelection('span', undefined, ['link-selection']);
833
+ this._linkDialogOpen = true;
830
834
  const dialogRef = this._dialog.open(AddLinkDialog, {
831
835
  width: '500px',
832
836
  disableClose: true,
833
837
  hasBackdrop: true
834
838
  });
835
839
  dialogRef.afterClosed().subscribe((res) => {
840
+ this._linkDialogOpen = false;
836
841
  this._textHighlightService.unwrapElementByClassAndSelectContents('link-selection');
837
842
  if (res && res.href) {
838
843
  this._textHighlightService.toggleWrapSelection('a', undefined, ['link'], {
@@ -848,6 +853,7 @@ class CommandBarComponent {
848
853
  if (!link) {
849
854
  return;
850
855
  }
856
+ this._linkDialogOpen = true;
851
857
  const dialogRef = this._dialog.open(EditLinkDialog, {
852
858
  data: {
853
859
  href: link.getAttribute('href'),
@@ -858,6 +864,7 @@ class CommandBarComponent {
858
864
  hasBackdrop: true
859
865
  });
860
866
  dialogRef.afterClosed().subscribe((res) => {
867
+ this._linkDialogOpen = false;
861
868
  this._textHighlightService.unwrapElementByClassAndSelectContents('link-selection');
862
869
  if (res) {
863
870
  if (res.href) {
@@ -924,7 +931,9 @@ class CommandBarComponent {
924
931
  this.props.set(props);
925
932
  }
926
933
  ngOnDestroy() {
927
- this._textHighlightService.unwrapElementByClassAndSelectContents('link-selection');
934
+ if (!this._linkDialogOpen) {
935
+ this._textHighlightService.unwrapElementByClassAndSelectContents('link-selection');
936
+ }
928
937
  this._unwrapTextSelection();
929
938
  }
930
939
  _unwrapTextSelection() {
@@ -1475,6 +1484,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
1475
1484
  }], ctorParameters: () => [], propDecorators: { blockSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "blockSelector", required: false }] }], autoScrollContainerSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoScrollContainerSelector", required: false }] }], selectionAreaClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionAreaClass", required: false }] }], ignoreClasses: [{ type: i0.Input, args: [{ isSignal: true, alias: "ignoreClasses", required: false }] }] } });
1476
1485
 
1477
1486
  class ContentBuilderComponent {
1487
+ static DRAFT_STORAGE_PREFIX = 'ngs-content-editor-builder:draft';
1478
1488
  _platformId = inject(PLATFORM_ID);
1479
1489
  _store = inject(ContentBuilderStore);
1480
1490
  elRef = inject((ElementRef));
@@ -1505,7 +1515,7 @@ class ContentBuilderComponent {
1505
1515
  }
1506
1516
  },
1507
1517
  {
1508
- component: () => import('./ngstarter-ui-components-content-editor-paragraph-block.component-DS_6CzuA.mjs').then(c => c.ParagraphBlockComponent),
1518
+ component: () => import('./ngstarter-ui-components-content-editor-paragraph-block.component-DtophI4_.mjs').then(c => c.ParagraphBlockComponent),
1509
1519
  type: 'paragraph',
1510
1520
  options: {},
1511
1521
  empty: () => {
@@ -1517,7 +1527,7 @@ class ContentBuilderComponent {
1517
1527
  }
1518
1528
  },
1519
1529
  {
1520
- component: () => import('./ngstarter-ui-components-content-editor-code-block.component-CKrOhA7h.mjs').then(c => c.CodeBlockComponent),
1530
+ component: () => import('./ngstarter-ui-components-content-editor-code-block.component-BZniTqu-.mjs').then(c => c.CodeBlockComponent),
1521
1531
  type: 'code',
1522
1532
  options: {},
1523
1533
  empty: () => {
@@ -1530,7 +1540,7 @@ class ContentBuilderComponent {
1530
1540
  }
1531
1541
  },
1532
1542
  {
1533
- component: () => import('./ngstarter-ui-components-content-editor-heading-block.component-Dv8d0nCy.mjs').then(c => c.HeadingBlockComponent),
1543
+ component: () => import('./ngstarter-ui-components-content-editor-heading-block.component-CnYRnDBY.mjs').then(c => c.HeadingBlockComponent),
1534
1544
  type: 'heading',
1535
1545
  options: {},
1536
1546
  empty: () => {
@@ -1544,7 +1554,7 @@ class ContentBuilderComponent {
1544
1554
  }
1545
1555
  },
1546
1556
  {
1547
- component: () => import('./ngstarter-ui-components-content-editor-image-block.component-g-H7a5Z_.mjs').then(c => c.ImageBlockComponent),
1557
+ component: () => import('./ngstarter-ui-components-content-editor-image-block.component-IP_eRCQ2.mjs').then(c => c.ImageBlockComponent),
1548
1558
  type: 'image',
1549
1559
  options: {
1550
1560
  uploadFn: (file, base64) => {
@@ -1571,7 +1581,7 @@ class ContentBuilderComponent {
1571
1581
  }
1572
1582
  },
1573
1583
  {
1574
- component: () => import('./ngstarter-ui-components-content-editor-video-block.component-DqS9Lhp_.mjs').then(c => c.VideoBlockComponent),
1584
+ component: () => import('./ngstarter-ui-components-content-editor-video-block.component-Cs7L1wwX.mjs').then(c => c.VideoBlockComponent),
1575
1585
  type: 'video',
1576
1586
  options: {
1577
1587
  uploadFn: (file, base64) => {
@@ -1599,7 +1609,7 @@ class ContentBuilderComponent {
1599
1609
  }
1600
1610
  },
1601
1611
  {
1602
- component: () => import('./ngstarter-ui-components-content-editor-list-block.component-PgqisgxY.mjs').then(c => c.ListBlockComponent),
1612
+ component: () => import('./ngstarter-ui-components-content-editor-list-block.component-amyfzXOW.mjs').then(c => c.ListBlockComponent),
1603
1613
  type: 'bulletList',
1604
1614
  options: {},
1605
1615
  empty: () => {
@@ -1612,7 +1622,7 @@ class ContentBuilderComponent {
1612
1622
  }
1613
1623
  },
1614
1624
  {
1615
- component: () => import('./ngstarter-ui-components-content-editor-list-block.component-PgqisgxY.mjs').then(c => c.ListBlockComponent),
1625
+ component: () => import('./ngstarter-ui-components-content-editor-list-block.component-amyfzXOW.mjs').then(c => c.ListBlockComponent),
1616
1626
  type: 'orderedList',
1617
1627
  options: {},
1618
1628
  empty: () => {
@@ -1625,7 +1635,7 @@ class ContentBuilderComponent {
1625
1635
  }
1626
1636
  },
1627
1637
  {
1628
- component: () => import('./ngstarter-ui-components-content-editor-table-block.component-D4rdPkGz.mjs').then(c => c.TableBlockComponent),
1638
+ component: () => import('./ngstarter-ui-components-content-editor-table-block.component-hJ4OxKRX.mjs').then(c => c.TableBlockComponent),
1629
1639
  type: 'table',
1630
1640
  options: {},
1631
1641
  empty: () => {
@@ -1694,7 +1704,7 @@ class ContentBuilderComponent {
1694
1704
  }
1695
1705
  },
1696
1706
  {
1697
- component: () => import('./ngstarter-ui-components-content-editor-quote-block.component-Df92Nqvp.mjs').then(c => c.QuoteBlockComponent),
1707
+ component: () => import('./ngstarter-ui-components-content-editor-quote-block.component-B20eHQdw.mjs').then(c => c.QuoteBlockComponent),
1698
1708
  type: 'quote',
1699
1709
  options: {},
1700
1710
  empty: () => {
@@ -1714,7 +1724,7 @@ class ContentBuilderComponent {
1714
1724
  }
1715
1725
  },
1716
1726
  {
1717
- component: () => import('./ngstarter-ui-components-content-editor-embed-block-zSApBzF3.mjs').then(c => c.EmbedBlock),
1727
+ component: () => import('./ngstarter-ui-components-content-editor-embed-block-QzDMzd3u.mjs').then(c => c.EmbedBlock),
1718
1728
  type: 'embed',
1719
1729
  options: {},
1720
1730
  empty: () => {
@@ -1730,6 +1740,7 @@ class ContentBuilderComponent {
1730
1740
  ], ...(ngDevMode ? [{ debugName: "blockDefs" }] : /* istanbul ignore next */ []));
1731
1741
  content = input([], ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
1732
1742
  contentChangedDelay = input(500, { ...(ngDevMode ? { debugName: "contentChangedDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
1743
+ persistDraft = input(true, { ...(ngDevMode ? { debugName: "persistDraft" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1733
1744
  suggestions = input([
1734
1745
  {
1735
1746
  type: 'heading',
@@ -1911,7 +1922,8 @@ class ContentBuilderComponent {
1911
1922
  return this.blockDefsOptionsMap.get(type)[key];
1912
1923
  }
1913
1924
  ngOnInit() {
1914
- const content = this.content();
1925
+ const draftContent = this._getDraftContent();
1926
+ const content = draftContent || this.content();
1915
1927
  if (content.length > 0) {
1916
1928
  const lastItem = content[content.length - 1];
1917
1929
  if (lastItem.type !== 'paragraph' || (lastItem.type === 'paragraph' && lastItem.content !== '')) {
@@ -2195,7 +2207,9 @@ class ContentBuilderComponent {
2195
2207
  return this._store.blocks();
2196
2208
  }
2197
2209
  emitContentChangeEvent() {
2198
- this.contentChanged.emit(this.getData());
2210
+ const data = this.getData();
2211
+ this._saveDraft(data);
2212
+ this.contentChanged.emit(data);
2199
2213
  }
2200
2214
  selectBlock(blockId, multiple = false) {
2201
2215
  if (!multiple) {
@@ -2312,6 +2326,43 @@ class ContentBuilderComponent {
2312
2326
  }
2313
2327
  this._scroll$ = null;
2314
2328
  }
2329
+ _getDraftContent() {
2330
+ if (!this._canUseDraftStorage()) {
2331
+ return null;
2332
+ }
2333
+ try {
2334
+ const draft = localStorage.getItem(this._getDraftStorageKey());
2335
+ if (!draft) {
2336
+ return null;
2337
+ }
2338
+ const content = JSON.parse(draft);
2339
+ return Array.isArray(content) ? content : null;
2340
+ }
2341
+ catch {
2342
+ return null;
2343
+ }
2344
+ }
2345
+ _saveDraft(content) {
2346
+ if (!this._canUseDraftStorage()) {
2347
+ return;
2348
+ }
2349
+ try {
2350
+ localStorage.setItem(this._getDraftStorageKey(), JSON.stringify(content));
2351
+ }
2352
+ catch {
2353
+ }
2354
+ }
2355
+ _canUseDraftStorage() {
2356
+ return !isPlatformServer(this._platformId) && this.persistDraft();
2357
+ }
2358
+ _getDraftStorageKey(prefix = ContentBuilderComponent.DRAFT_STORAGE_PREFIX) {
2359
+ const elementId = this.elRef.nativeElement.id;
2360
+ const locationKey = typeof window === 'undefined'
2361
+ ? 'server'
2362
+ : `${window.location.pathname}${window.location.search}`;
2363
+ const instanceKey = elementId ? `:${elementId}` : '';
2364
+ return `${prefix}:${locationKey}${instanceKey}`;
2365
+ }
2315
2366
  onSettingsPopoverClose() {
2316
2367
  }
2317
2368
  _onPaste(event) {
@@ -2475,17 +2526,17 @@ class ContentBuilderComponent {
2475
2526
  }));
2476
2527
  }
2477
2528
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2478
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentBuilderComponent, isStandalone: true, selector: "ngs-content-builder", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, contentChangedDelay: { classPropertyName: "contentChangedDelay", publicName: "contentChangedDelay", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, scrollContainer: { classPropertyName: "scrollContainer", publicName: "scrollContainer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChanged: "contentChanged" }, host: { attributes: { "tabindex": "0" }, listeners: { "paste": "_onPaste($event)", "keydown": "_onKeyDown($event)" }, properties: { "class.is-block-dragging": "_blockDragging()", "class.is-selection-of-blocks-active": "isSelectionOfBlocksActive()", "class.select-none": "isSelectionOfBlocksActive()", "style.user-select": "isSelectionOfBlocksActive() ? \"none\" : null" }, classAttribute: "ngs-content-builder" }, providers: [
2529
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentBuilderComponent, isStandalone: true, selector: "ngs-content-editor-builder", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, contentChangedDelay: { classPropertyName: "contentChangedDelay", publicName: "contentChangedDelay", isSignal: true, isRequired: false, transformFunction: null }, persistDraft: { classPropertyName: "persistDraft", publicName: "persistDraft", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, scrollContainer: { classPropertyName: "scrollContainer", publicName: "scrollContainer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChanged: "contentChanged" }, host: { attributes: { "tabindex": "0" }, listeners: { "paste": "_onPaste($event)", "keydown": "_onKeyDown($event)" }, properties: { "class.is-block-dragging": "_blockDragging()", "class.is-selection-of-blocks-active": "isSelectionOfBlocksActive()", "class.select-none": "isSelectionOfBlocksActive()", "style.user-select": "isSelectionOfBlocksActive() ? \"none\" : null" }, classAttribute: "ngs-content-editor-builder" }, providers: [
2479
2530
  ContentBuilderStore,
2480
2531
  {
2481
2532
  provide: CONTENT_BUILDER,
2482
2533
  useExisting: forwardRef(() => ContentBuilderComponent)
2483
2534
  }
2484
- ], exportAs: ["ngsContentBuilder"], hostDirectives: [{ directive: BlockSelectionDirective, inputs: ["autoScrollContainerSelector", "autoScrollContainerSelector"] }], ngImport: i0, template: "<div class=\"container py-4\">\n <div class=\"content\"\n cdkDropList\n ngsTextSelectionPopup\n closestContentObserverClass=\"ngs-content-editor-content-editable\"\n [targetComponent]=\"commandBar\"\n (tagSelected)=\"onTagSelected($event)\"\n (cdkDropListDropped)=\"drop($event)\">\n @for (contentBlock of _content(); track contentBlock.id) {\n <div class=\"block\"\n [attr.data-block-id]=\"contentBlock.id\"\n [class.is-focused]=\"isBlockFocused(contentBlock.id)\"\n [class.is-active]=\"isActiveBlock(contentBlock.id)\"\n cdkDrag\n cdkDragLockAxis=\"y\"\n cdkMonitorSubtreeFocus\n (cdkDragStarted)=\"onDragStarted($event, contentBlock)\"\n (cdkDragEnded)=\"onDragEnded($event, contentBlock)\"\n (cdkFocusChange)=\"onFocusChange($event, contentBlock)\">\n <div class=\"block-controls\" [class.is-settings-popover-open]=\"settingsTrigger.api.isOpen()\">\n <button class=\"block-control\">\n <ngs-icon name=\"fluent:add-24-regular\"\n (mousedown)=\"setActiveBlockId($event, contentBlock.id)\"\n [ngsMenuTriggerFor]=\"suggestionsMenu\"\n [ngsMenuTriggerRestoreFocus]=\"false\"\n (menuOpened)=\"onSuggestionsMenuOpen()\"\n (menuClosed)=\"onSuggestionsMenuClose($event)\"/>\n </button>\n <div class=\"block-control block-control-drag\"\n (click)=\"selectBlock(contentBlock.id)\"\n [ngsPopoverTriggerFor]=\"settingsPopover\"\n (closed)=\"onSettingsPopoverClose()\"\n #settingsTrigger=\"ngsPopoverTriggerFor\"\n hasBackdrop\n position=\"before-center\">\n <button cdkDragHandle\n trigger=\"hover\"\n closeOnOriginClick\n closeOnOriginMouseLeave\n #dragTrigger=\"ngsPopoverTriggerFor\"\n [ngsPopoverTriggerFor]=\"dragControlTooltip\"\n position=\"below-center\"\n (mousedown)=\"dragTrigger.api.close()\"\n delay=\"1000\" class=\"w-full h-full flex items-center justify-center\">\n <ngs-icon name=\"fluent:re-order-dots-vertical-24-regular\"/>\n </button>\n </div>\n <ng-template #dragControlTooltip>\n <div class=\"bg-neutral-900 text-xs flex flex-col gap-0.5 rounded-lg items-center px-2 py-1.5 font-medium\">\n <div>\n <div class=\"text-neutral-100\">Drag <span class=\"text-neutral-400\">to move</span></div>\n </div>\n <div>\n <div class=\"text-neutral-100\">Click <span class=\"text-neutral-400\">to open menu</span></div>\n </div>\n </div>\n </ng-template>\n </div>\n <div class=\"block-content\" [class.is-selected]=\"isBlockSelected(contentBlock.id)\">\n <div class=\"drag-placeholder\" *cdkDragPlaceholder></div>\n <ng-container [ngComponentOutlet]=\"blockDefsMap.get(contentBlock.type) | async\"\n [ngComponentOutletInputs]=\"{\n id: contentBlock.id,\n content: contentBlock.content,\n settings: contentBlock.settings,\n index: $index\n }\"/>\n </div>\n </div>\n }\n </div>\n</div>\n\n<ngs-popover #settingsPopover=\"ngsPopover\">\n <div class=\"px-2 py-0 w-72 settings-popover\">\n <ngs-list>\n <ngs-list-item (click)=\"duplicateSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:copy-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Duplicate</div>\n </ngs-list-item>\n <ngs-list-item (click)=\"deleteSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:delete-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Delete</div>\n </ngs-list-item>\n </ngs-list>\n </div>\n</ngs-popover>\n\n<ngs-menu #suggestionsMenu=\"ngsMenu\">\n <div (click)=\"preventMenuClose($event)\">\n @for (suggestionItem of suggestions(); track $index; let first = $first) {\n @switch (suggestionItem.type) {\n @case ('heading') {\n <ngs-menu-heading>{{ suggestionItem.title }}</ngs-menu-heading>\n }\n @case ('item') {\n <button ngs-menu-item (click)=\"addBlockFromSuggestionMenu(suggestionsMenu, suggestionItem.blockType, suggestionItem.blockOptions)\">\n <div class=\"h-full flex items-center gap-3 py-2\">\n <div class=\"size-9 flex items-center rounded-lg justify-center bg-surface-container\">\n <ngs-icon [name]=\"suggestionItem.iconName\" class=\"!me-0\"/>\n </div>\n <div class=\"grow min-w-[200px]\">\n <div>{{ suggestionItem.title }}</div>\n <div class=\"text-2xs text-neutral-500\">{{ suggestionItem.description }}</div>\n </div>\n @if (suggestionItem.hotKeys) {\n <div class=\"ms-auto bg-surface-container-highest rounded-full h-5\n text-4xs px-2 flex items-center font-bold\">{{ suggestionItem.hotKeys }}</div>\n }\n </div>\n </button>\n }\n }\n }\n </div>\n</ngs-menu>\n", styles: [":host{--ngs-content-builder-content-width: 704px;outline:none}:host ::ng-deep .link-selection,:host ::ng-deep .text-selection{display:inline-block;background:var(--ngs-color-secondary-fixed)}:host.is-block-dragging{cursor:grabbing}:host .container{display:flex;width:820px;min-height:200px;height:100%;padding:calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) 0;margin:0 auto;outline:none}:host .content{flex-grow:1;width:calc(var(--ngs-content-builder-content-width) + calc(var(--spacing, .25rem) * 10))}:host .block{position:relative;flex:none;padding:calc(var(--spacing, .25rem) * 1) 0;display:flex;align-items:center}:host .block:not(:has(.block-content.is-selected)):hover .block-content{background:var(--ngs-color-neutral-50)}:host:not(.is-block-dragging) .block:hover .block-controls,:host:not(.is-block-dragging) .block.is-active .block-controls{opacity:1}:host .block-content{position:relative;flex-grow:1;padding:calc(var(--spacing, .25rem) * 3)}:host .block-content.is-selected{background:var(--ngs-color-primary-100)}:host ::ng-deep .selection-area{background:var(--ngs-color-primary-100);opacity:.4;border:1px solid var(--ngs-color-primary);border-radius:var(--ngs-radius-sm)}:host ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:text;user-select:text}:host.select-none ::ng-deep .ngs-content-editor-content-editable,:host.is-selection-of-blocks-active ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:none!important;user-select:none!important}:host .block-controls{left:0;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2);opacity:0;flex:none}:host .block-controls.is-settings-popover-open{opacity:1}:host .block-controls.is-settings-popover-open .block-control:not(.block-control-drag){opacity:0}:host .block-control{cursor:pointer;width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center}:host .block-control:hover{background:var(--ngs-color-surface-container-low);color:var(--ngs-color-on-surface)}:host .block-control-drag button{cursor:grab}:host .drag-placeholder{height:calc(var(--spacing, .25rem) * 8);flex:none;position:relative}:host .drag-placeholder:before{position:absolute;left:calc(var(--spacing, .25rem) * 18);display:block;right:0;content:\"\";height:calc(var(--spacing, .25rem) * 2);top:50%;transform:translateY(-50%);background:var(--ngs-color-primary-300);border-radius:calc(var(--spacing, .25rem) * .5)}:host ::ng-deep code{color:var(--ngs-color-primary)}.cdk-drag.cdk-drag-preview{overflow:hidden;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2)}.cdk-drag.cdk-drag-preview .block-control{width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center;cursor:grabbing}.cdk-drag.cdk-drag-preview .block-control:first-child{opacity:0}.cdk-drag.cdk-drag-preview .block-control:last-child{color:var(--ngs-color-on-surface)}.cdk-drag.cdk-drag-preview .block-content{opacity:0}.settings-popover{--ngs-list-list-item-one-line-container-height: calc(var(--spacing, .25rem) * 10)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: Menu, selector: "ngs-menu", inputs: ["role", "classList", "xPosition", "yPosition"], outputs: ["closed"], exportAs: ["ngsMenu"] }, { kind: "component", type: MenuItem, selector: "ngs-menu-item, [ngs-menu-item]", inputs: ["disabled", "role", "selected"], outputs: ["_triggered"], exportAs: ["ngsMenuItem"] }, { kind: "directive", type: MenuTrigger, selector: "[ngsMenuTriggerFor]", inputs: ["ngsMenuTriggerFor", "ngsMenuTriggerData", "ngsMenuDisabled", "xPosition", "yPosition", "ngsMenuTriggerRestoreFocus"], outputs: ["menuOpened", "menuClosed"], exportAs: ["ngsMenuTrigger"] }, { kind: "directive", type: CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }, { kind: "directive", type: TextSelectionPopupDirective, selector: "[ngsTextSelectionPopup]", inputs: ["targetComponent", "closestContentObserverClass"], outputs: ["tagSelected"] }, { kind: "directive", type: PopoverTriggerForDirective, selector: "[ngsPopoverTriggerFor]", inputs: ["ngsPopoverTriggerFor", "ngsPopoverContext", "trigger", "position", "delay", "origin", "closeOnOriginClick", "closeOnOriginMouseLeave", "hasBackdrop"], outputs: ["opened", "closed"], exportAs: ["ngsPopoverTriggerFor"] }, { kind: "component", type: Popover, selector: "ngs-popover", exportAs: ["ngsPopover"] }, { kind: "directive", type: ListItemTitle, selector: "[ngsListItemTitle]" }, { kind: "directive", type: ListItemIcon, selector: "[ngsListItemIcon]" }, { kind: "component", type: ListItem, selector: "ngs-list-item, a[ngs-list-item], button[ngs-list-item]", inputs: ["disabled", "lines"], exportAs: ["ngsListItem"] }, { kind: "component", type: List, selector: "ngs-list", inputs: ["disabled", "disableRipple"], exportAs: ["ngsList"] }, { kind: "component", type: MenuHeading, selector: "ngs-menu-heading" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2535
+ ], exportAs: ["ngsContentEditorBuilder"], hostDirectives: [{ directive: BlockSelectionDirective, inputs: ["autoScrollContainerSelector", "autoScrollContainerSelector"] }], ngImport: i0, template: "<div class=\"container py-4\">\n <div class=\"content\"\n cdkDropList\n ngsTextSelectionPopup\n closestContentObserverClass=\"ngs-content-editor-content-editable\"\n [targetComponent]=\"commandBar\"\n (tagSelected)=\"onTagSelected($event)\"\n (cdkDropListDropped)=\"drop($event)\">\n @for (contentBlock of _content(); track contentBlock.id) {\n <div class=\"block\"\n [attr.data-block-id]=\"contentBlock.id\"\n [class.is-focused]=\"isBlockFocused(contentBlock.id)\"\n [class.is-active]=\"isActiveBlock(contentBlock.id)\"\n cdkDrag\n cdkDragLockAxis=\"y\"\n cdkMonitorSubtreeFocus\n (cdkDragStarted)=\"onDragStarted($event, contentBlock)\"\n (cdkDragEnded)=\"onDragEnded($event, contentBlock)\"\n (cdkFocusChange)=\"onFocusChange($event, contentBlock)\">\n <div class=\"block-controls\" [class.is-settings-popover-open]=\"settingsTrigger.api.isOpen()\">\n <button class=\"block-control\">\n <ngs-icon name=\"fluent:add-24-regular\"\n (mousedown)=\"setActiveBlockId($event, contentBlock.id)\"\n [ngsMenuTriggerFor]=\"suggestionsMenu\"\n [ngsMenuTriggerRestoreFocus]=\"false\"\n (menuOpened)=\"onSuggestionsMenuOpen()\"\n (menuClosed)=\"onSuggestionsMenuClose($event)\"/>\n </button>\n <div class=\"block-control block-control-drag\"\n (click)=\"selectBlock(contentBlock.id)\"\n [ngsPopoverTriggerFor]=\"settingsPopover\"\n (closed)=\"onSettingsPopoverClose()\"\n #settingsTrigger=\"ngsPopoverTriggerFor\"\n hasBackdrop\n position=\"before-center\">\n <button cdkDragHandle\n trigger=\"hover\"\n closeOnOriginClick\n closeOnOriginMouseLeave\n #dragTrigger=\"ngsPopoverTriggerFor\"\n [ngsPopoverTriggerFor]=\"dragControlTooltip\"\n position=\"below-center\"\n (mousedown)=\"dragTrigger.api.close()\"\n delay=\"1000\" class=\"w-full h-full flex items-center justify-center\">\n <ngs-icon name=\"fluent:re-order-dots-vertical-24-regular\"/>\n </button>\n </div>\n <ng-template #dragControlTooltip>\n <div class=\"bg-neutral-900 text-xs flex flex-col gap-0.5 rounded-lg items-center px-2 py-1.5 font-medium\">\n <div>\n <div class=\"text-neutral-100\">Drag <span class=\"text-neutral-400\">to move</span></div>\n </div>\n <div>\n <div class=\"text-neutral-100\">Click <span class=\"text-neutral-400\">to open menu</span></div>\n </div>\n </div>\n </ng-template>\n </div>\n <div class=\"block-content\" [class.is-selected]=\"isBlockSelected(contentBlock.id)\">\n <div class=\"drag-placeholder\" *cdkDragPlaceholder></div>\n <ng-container [ngComponentOutlet]=\"blockDefsMap.get(contentBlock.type) | async\"\n [ngComponentOutletInputs]=\"{\n id: contentBlock.id,\n content: contentBlock.content,\n settings: contentBlock.settings,\n index: $index\n }\"/>\n </div>\n </div>\n }\n </div>\n</div>\n\n<ngs-popover #settingsPopover=\"ngsPopover\">\n <div class=\"px-2 py-0 w-72 settings-popover\">\n <ngs-list>\n <ngs-list-item (click)=\"duplicateSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:copy-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Duplicate</div>\n </ngs-list-item>\n <ngs-list-item (click)=\"deleteSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:delete-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Delete</div>\n </ngs-list-item>\n </ngs-list>\n </div>\n</ngs-popover>\n\n<ngs-menu #suggestionsMenu=\"ngsMenu\">\n <div (click)=\"preventMenuClose($event)\">\n @for (suggestionItem of suggestions(); track $index; let first = $first) {\n @switch (suggestionItem.type) {\n @case ('heading') {\n <ngs-menu-heading>{{ suggestionItem.title }}</ngs-menu-heading>\n }\n @case ('item') {\n <button ngs-menu-item (click)=\"addBlockFromSuggestionMenu(suggestionsMenu, suggestionItem.blockType, suggestionItem.blockOptions)\">\n <div class=\"h-full flex items-center gap-3 py-2\">\n <div class=\"size-9 flex items-center rounded-lg justify-center bg-surface-container\">\n <ngs-icon [name]=\"suggestionItem.iconName\" class=\"!me-0\"/>\n </div>\n <div class=\"grow min-w-[200px]\">\n <div>{{ suggestionItem.title }}</div>\n <div class=\"text-2xs text-neutral-500\">{{ suggestionItem.description }}</div>\n </div>\n @if (suggestionItem.hotKeys) {\n <div class=\"ms-auto bg-surface-container-highest rounded-full h-5\n text-4xs px-2 flex items-center font-bold\">{{ suggestionItem.hotKeys }}</div>\n }\n </div>\n </button>\n }\n }\n }\n </div>\n</ngs-menu>\n", styles: [":host{--ngs-content-editor-builder-content-width: 704px;outline:none}:host ::ng-deep .link-selection,:host ::ng-deep .text-selection{display:inline-block;background:var(--ngs-color-secondary-fixed)}:host.is-block-dragging{cursor:grabbing}:host .container{display:flex;width:820px;min-height:200px;height:100%;padding:calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) 0;margin:0 auto;outline:none}:host .content{flex-grow:1;width:calc(var(--ngs-content-editor-builder-content-width) + calc(var(--spacing, .25rem) * 10))}:host .block{position:relative;flex:none;padding:calc(var(--spacing, .25rem) * 1) 0;display:flex;align-items:center}:host .block:not(:has(.block-content.is-selected)):hover .block-content{background:var(--ngs-color-neutral-50)}:host:not(.is-block-dragging) .block:hover .block-controls,:host:not(.is-block-dragging) .block.is-active .block-controls{opacity:1}:host .block-content{position:relative;flex-grow:1;padding:calc(var(--spacing, .25rem) * 3)}:host .block-content.is-selected{background:var(--ngs-color-primary-100)}:host ::ng-deep .selection-area{background:var(--ngs-color-primary-100);opacity:.4;border:1px solid var(--ngs-color-primary);border-radius:var(--ngs-radius-sm)}:host ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:text;user-select:text}:host.select-none ::ng-deep .ngs-content-editor-content-editable,:host.is-selection-of-blocks-active ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:none!important;user-select:none!important}:host .block-controls{left:0;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2);opacity:0;flex:none}:host .block-controls.is-settings-popover-open{opacity:1}:host .block-controls.is-settings-popover-open .block-control:not(.block-control-drag){opacity:0}:host .block-control{cursor:pointer;width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center}:host .block-control:hover{background:var(--ngs-color-surface-container-low);color:var(--ngs-color-on-surface)}:host .block-control-drag button{cursor:grab}:host .drag-placeholder{height:calc(var(--spacing, .25rem) * 8);flex:none;position:relative}:host .drag-placeholder:before{position:absolute;left:calc(var(--spacing, .25rem) * 18);display:block;right:0;content:\"\";height:calc(var(--spacing, .25rem) * 2);top:50%;transform:translateY(-50%);background:var(--ngs-color-primary-300);border-radius:calc(var(--spacing, .25rem) * .5)}:host ::ng-deep code{color:var(--ngs-color-primary)}.cdk-drag.cdk-drag-preview{overflow:hidden;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2)}.cdk-drag.cdk-drag-preview .block-control{width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center;cursor:grabbing}.cdk-drag.cdk-drag-preview .block-control:first-child{opacity:0}.cdk-drag.cdk-drag-preview .block-control:last-child{color:var(--ngs-color-on-surface)}.cdk-drag.cdk-drag-preview .block-content{opacity:0}.settings-popover{--ngs-list-list-item-one-line-container-height: calc(var(--spacing, .25rem) * 10)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: Menu, selector: "ngs-menu", inputs: ["role", "classList", "xPosition", "yPosition"], outputs: ["closed"], exportAs: ["ngsMenu"] }, { kind: "component", type: MenuItem, selector: "ngs-menu-item, [ngs-menu-item]", inputs: ["disabled", "role", "selected"], outputs: ["_triggered"], exportAs: ["ngsMenuItem"] }, { kind: "directive", type: MenuTrigger, selector: "[ngsMenuTriggerFor]", inputs: ["ngsMenuTriggerFor", "ngsMenuTriggerData", "ngsMenuDisabled", "xPosition", "yPosition", "ngsMenuTriggerRestoreFocus"], outputs: ["menuOpened", "menuClosed"], exportAs: ["ngsMenuTrigger"] }, { kind: "directive", type: CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }, { kind: "directive", type: TextSelectionPopupDirective, selector: "[ngsTextSelectionPopup]", inputs: ["targetComponent", "closestContentObserverClass"], outputs: ["tagSelected"] }, { kind: "directive", type: PopoverTriggerForDirective, selector: "[ngsPopoverTriggerFor]", inputs: ["ngsPopoverTriggerFor", "ngsPopoverContext", "trigger", "position", "delay", "origin", "closeOnOriginClick", "closeOnOriginMouseLeave", "hasBackdrop"], outputs: ["opened", "closed"], exportAs: ["ngsPopoverTriggerFor"] }, { kind: "component", type: Popover, selector: "ngs-popover", exportAs: ["ngsPopover"] }, { kind: "directive", type: ListItemTitle, selector: "[ngsListItemTitle]" }, { kind: "directive", type: ListItemIcon, selector: "[ngsListItemIcon]" }, { kind: "component", type: ListItem, selector: "ngs-list-item, a[ngs-list-item], button[ngs-list-item]", inputs: ["disabled", "lines"], exportAs: ["ngsListItem"] }, { kind: "component", type: List, selector: "ngs-list", inputs: ["disabled", "disableRipple"], exportAs: ["ngsList"] }, { kind: "component", type: MenuHeading, selector: "ngs-menu-heading" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2485
2536
  }
2486
2537
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentBuilderComponent, decorators: [{
2487
2538
  type: Component,
2488
- args: [{ selector: 'ngs-content-builder', exportAs: 'ngsContentBuilder', imports: [
2539
+ args: [{ selector: 'ngs-content-editor-builder', exportAs: 'ngsContentEditorBuilder', imports: [
2489
2540
  Icon,
2490
2541
  NgComponentOutlet,
2491
2542
  AsyncPipe,
@@ -2519,7 +2570,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
2519
2570
  useExisting: forwardRef(() => ContentBuilderComponent)
2520
2571
  }
2521
2572
  ], host: {
2522
- 'class': 'ngs-content-builder',
2573
+ 'class': 'ngs-content-editor-builder',
2523
2574
  '[class.is-block-dragging]': '_blockDragging()',
2524
2575
  '[class.is-selection-of-blocks-active]': 'isSelectionOfBlocksActive()',
2525
2576
  '[class.select-none]': 'isSelectionOfBlocksActive()',
@@ -2527,21 +2578,387 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
2527
2578
  'tabindex': '0',
2528
2579
  '(paste)': '_onPaste($event)',
2529
2580
  '(keydown)': '_onKeyDown($event)',
2530
- }, template: "<div class=\"container py-4\">\n <div class=\"content\"\n cdkDropList\n ngsTextSelectionPopup\n closestContentObserverClass=\"ngs-content-editor-content-editable\"\n [targetComponent]=\"commandBar\"\n (tagSelected)=\"onTagSelected($event)\"\n (cdkDropListDropped)=\"drop($event)\">\n @for (contentBlock of _content(); track contentBlock.id) {\n <div class=\"block\"\n [attr.data-block-id]=\"contentBlock.id\"\n [class.is-focused]=\"isBlockFocused(contentBlock.id)\"\n [class.is-active]=\"isActiveBlock(contentBlock.id)\"\n cdkDrag\n cdkDragLockAxis=\"y\"\n cdkMonitorSubtreeFocus\n (cdkDragStarted)=\"onDragStarted($event, contentBlock)\"\n (cdkDragEnded)=\"onDragEnded($event, contentBlock)\"\n (cdkFocusChange)=\"onFocusChange($event, contentBlock)\">\n <div class=\"block-controls\" [class.is-settings-popover-open]=\"settingsTrigger.api.isOpen()\">\n <button class=\"block-control\">\n <ngs-icon name=\"fluent:add-24-regular\"\n (mousedown)=\"setActiveBlockId($event, contentBlock.id)\"\n [ngsMenuTriggerFor]=\"suggestionsMenu\"\n [ngsMenuTriggerRestoreFocus]=\"false\"\n (menuOpened)=\"onSuggestionsMenuOpen()\"\n (menuClosed)=\"onSuggestionsMenuClose($event)\"/>\n </button>\n <div class=\"block-control block-control-drag\"\n (click)=\"selectBlock(contentBlock.id)\"\n [ngsPopoverTriggerFor]=\"settingsPopover\"\n (closed)=\"onSettingsPopoverClose()\"\n #settingsTrigger=\"ngsPopoverTriggerFor\"\n hasBackdrop\n position=\"before-center\">\n <button cdkDragHandle\n trigger=\"hover\"\n closeOnOriginClick\n closeOnOriginMouseLeave\n #dragTrigger=\"ngsPopoverTriggerFor\"\n [ngsPopoverTriggerFor]=\"dragControlTooltip\"\n position=\"below-center\"\n (mousedown)=\"dragTrigger.api.close()\"\n delay=\"1000\" class=\"w-full h-full flex items-center justify-center\">\n <ngs-icon name=\"fluent:re-order-dots-vertical-24-regular\"/>\n </button>\n </div>\n <ng-template #dragControlTooltip>\n <div class=\"bg-neutral-900 text-xs flex flex-col gap-0.5 rounded-lg items-center px-2 py-1.5 font-medium\">\n <div>\n <div class=\"text-neutral-100\">Drag <span class=\"text-neutral-400\">to move</span></div>\n </div>\n <div>\n <div class=\"text-neutral-100\">Click <span class=\"text-neutral-400\">to open menu</span></div>\n </div>\n </div>\n </ng-template>\n </div>\n <div class=\"block-content\" [class.is-selected]=\"isBlockSelected(contentBlock.id)\">\n <div class=\"drag-placeholder\" *cdkDragPlaceholder></div>\n <ng-container [ngComponentOutlet]=\"blockDefsMap.get(contentBlock.type) | async\"\n [ngComponentOutletInputs]=\"{\n id: contentBlock.id,\n content: contentBlock.content,\n settings: contentBlock.settings,\n index: $index\n }\"/>\n </div>\n </div>\n }\n </div>\n</div>\n\n<ngs-popover #settingsPopover=\"ngsPopover\">\n <div class=\"px-2 py-0 w-72 settings-popover\">\n <ngs-list>\n <ngs-list-item (click)=\"duplicateSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:copy-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Duplicate</div>\n </ngs-list-item>\n <ngs-list-item (click)=\"deleteSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:delete-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Delete</div>\n </ngs-list-item>\n </ngs-list>\n </div>\n</ngs-popover>\n\n<ngs-menu #suggestionsMenu=\"ngsMenu\">\n <div (click)=\"preventMenuClose($event)\">\n @for (suggestionItem of suggestions(); track $index; let first = $first) {\n @switch (suggestionItem.type) {\n @case ('heading') {\n <ngs-menu-heading>{{ suggestionItem.title }}</ngs-menu-heading>\n }\n @case ('item') {\n <button ngs-menu-item (click)=\"addBlockFromSuggestionMenu(suggestionsMenu, suggestionItem.blockType, suggestionItem.blockOptions)\">\n <div class=\"h-full flex items-center gap-3 py-2\">\n <div class=\"size-9 flex items-center rounded-lg justify-center bg-surface-container\">\n <ngs-icon [name]=\"suggestionItem.iconName\" class=\"!me-0\"/>\n </div>\n <div class=\"grow min-w-[200px]\">\n <div>{{ suggestionItem.title }}</div>\n <div class=\"text-2xs text-neutral-500\">{{ suggestionItem.description }}</div>\n </div>\n @if (suggestionItem.hotKeys) {\n <div class=\"ms-auto bg-surface-container-highest rounded-full h-5\n text-4xs px-2 flex items-center font-bold\">{{ suggestionItem.hotKeys }}</div>\n }\n </div>\n </button>\n }\n }\n }\n </div>\n</ngs-menu>\n", styles: [":host{--ngs-content-builder-content-width: 704px;outline:none}:host ::ng-deep .link-selection,:host ::ng-deep .text-selection{display:inline-block;background:var(--ngs-color-secondary-fixed)}:host.is-block-dragging{cursor:grabbing}:host .container{display:flex;width:820px;min-height:200px;height:100%;padding:calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) 0;margin:0 auto;outline:none}:host .content{flex-grow:1;width:calc(var(--ngs-content-builder-content-width) + calc(var(--spacing, .25rem) * 10))}:host .block{position:relative;flex:none;padding:calc(var(--spacing, .25rem) * 1) 0;display:flex;align-items:center}:host .block:not(:has(.block-content.is-selected)):hover .block-content{background:var(--ngs-color-neutral-50)}:host:not(.is-block-dragging) .block:hover .block-controls,:host:not(.is-block-dragging) .block.is-active .block-controls{opacity:1}:host .block-content{position:relative;flex-grow:1;padding:calc(var(--spacing, .25rem) * 3)}:host .block-content.is-selected{background:var(--ngs-color-primary-100)}:host ::ng-deep .selection-area{background:var(--ngs-color-primary-100);opacity:.4;border:1px solid var(--ngs-color-primary);border-radius:var(--ngs-radius-sm)}:host ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:text;user-select:text}:host.select-none ::ng-deep .ngs-content-editor-content-editable,:host.is-selection-of-blocks-active ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:none!important;user-select:none!important}:host .block-controls{left:0;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2);opacity:0;flex:none}:host .block-controls.is-settings-popover-open{opacity:1}:host .block-controls.is-settings-popover-open .block-control:not(.block-control-drag){opacity:0}:host .block-control{cursor:pointer;width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center}:host .block-control:hover{background:var(--ngs-color-surface-container-low);color:var(--ngs-color-on-surface)}:host .block-control-drag button{cursor:grab}:host .drag-placeholder{height:calc(var(--spacing, .25rem) * 8);flex:none;position:relative}:host .drag-placeholder:before{position:absolute;left:calc(var(--spacing, .25rem) * 18);display:block;right:0;content:\"\";height:calc(var(--spacing, .25rem) * 2);top:50%;transform:translateY(-50%);background:var(--ngs-color-primary-300);border-radius:calc(var(--spacing, .25rem) * .5)}:host ::ng-deep code{color:var(--ngs-color-primary)}.cdk-drag.cdk-drag-preview{overflow:hidden;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2)}.cdk-drag.cdk-drag-preview .block-control{width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center;cursor:grabbing}.cdk-drag.cdk-drag-preview .block-control:first-child{opacity:0}.cdk-drag.cdk-drag-preview .block-control:last-child{color:var(--ngs-color-on-surface)}.cdk-drag.cdk-drag-preview .block-content{opacity:0}.settings-popover{--ngs-list-list-item-one-line-container-height: calc(var(--spacing, .25rem) * 10)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2531
- }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], contentChangedDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentChangedDelay", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], scrollContainer: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollContainer", required: false }] }], contentChanged: [{ type: i0.Output, args: ["contentChanged"] }] } });
2581
+ }, template: "<div class=\"container py-4\">\n <div class=\"content\"\n cdkDropList\n ngsTextSelectionPopup\n closestContentObserverClass=\"ngs-content-editor-content-editable\"\n [targetComponent]=\"commandBar\"\n (tagSelected)=\"onTagSelected($event)\"\n (cdkDropListDropped)=\"drop($event)\">\n @for (contentBlock of _content(); track contentBlock.id) {\n <div class=\"block\"\n [attr.data-block-id]=\"contentBlock.id\"\n [class.is-focused]=\"isBlockFocused(contentBlock.id)\"\n [class.is-active]=\"isActiveBlock(contentBlock.id)\"\n cdkDrag\n cdkDragLockAxis=\"y\"\n cdkMonitorSubtreeFocus\n (cdkDragStarted)=\"onDragStarted($event, contentBlock)\"\n (cdkDragEnded)=\"onDragEnded($event, contentBlock)\"\n (cdkFocusChange)=\"onFocusChange($event, contentBlock)\">\n <div class=\"block-controls\" [class.is-settings-popover-open]=\"settingsTrigger.api.isOpen()\">\n <button class=\"block-control\">\n <ngs-icon name=\"fluent:add-24-regular\"\n (mousedown)=\"setActiveBlockId($event, contentBlock.id)\"\n [ngsMenuTriggerFor]=\"suggestionsMenu\"\n [ngsMenuTriggerRestoreFocus]=\"false\"\n (menuOpened)=\"onSuggestionsMenuOpen()\"\n (menuClosed)=\"onSuggestionsMenuClose($event)\"/>\n </button>\n <div class=\"block-control block-control-drag\"\n (click)=\"selectBlock(contentBlock.id)\"\n [ngsPopoverTriggerFor]=\"settingsPopover\"\n (closed)=\"onSettingsPopoverClose()\"\n #settingsTrigger=\"ngsPopoverTriggerFor\"\n hasBackdrop\n position=\"before-center\">\n <button cdkDragHandle\n trigger=\"hover\"\n closeOnOriginClick\n closeOnOriginMouseLeave\n #dragTrigger=\"ngsPopoverTriggerFor\"\n [ngsPopoverTriggerFor]=\"dragControlTooltip\"\n position=\"below-center\"\n (mousedown)=\"dragTrigger.api.close()\"\n delay=\"1000\" class=\"w-full h-full flex items-center justify-center\">\n <ngs-icon name=\"fluent:re-order-dots-vertical-24-regular\"/>\n </button>\n </div>\n <ng-template #dragControlTooltip>\n <div class=\"bg-neutral-900 text-xs flex flex-col gap-0.5 rounded-lg items-center px-2 py-1.5 font-medium\">\n <div>\n <div class=\"text-neutral-100\">Drag <span class=\"text-neutral-400\">to move</span></div>\n </div>\n <div>\n <div class=\"text-neutral-100\">Click <span class=\"text-neutral-400\">to open menu</span></div>\n </div>\n </div>\n </ng-template>\n </div>\n <div class=\"block-content\" [class.is-selected]=\"isBlockSelected(contentBlock.id)\">\n <div class=\"drag-placeholder\" *cdkDragPlaceholder></div>\n <ng-container [ngComponentOutlet]=\"blockDefsMap.get(contentBlock.type) | async\"\n [ngComponentOutletInputs]=\"{\n id: contentBlock.id,\n content: contentBlock.content,\n settings: contentBlock.settings,\n index: $index\n }\"/>\n </div>\n </div>\n }\n </div>\n</div>\n\n<ngs-popover #settingsPopover=\"ngsPopover\">\n <div class=\"px-2 py-0 w-72 settings-popover\">\n <ngs-list>\n <ngs-list-item (click)=\"duplicateSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:copy-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Duplicate</div>\n </ngs-list-item>\n <ngs-list-item (click)=\"deleteSelectedBlocks(settingsPopover)\">\n <ngs-icon name=\"fluent:delete-24-regular\" ngsListItemIcon/>\n <div ngsListItemTitle>Delete</div>\n </ngs-list-item>\n </ngs-list>\n </div>\n</ngs-popover>\n\n<ngs-menu #suggestionsMenu=\"ngsMenu\">\n <div (click)=\"preventMenuClose($event)\">\n @for (suggestionItem of suggestions(); track $index; let first = $first) {\n @switch (suggestionItem.type) {\n @case ('heading') {\n <ngs-menu-heading>{{ suggestionItem.title }}</ngs-menu-heading>\n }\n @case ('item') {\n <button ngs-menu-item (click)=\"addBlockFromSuggestionMenu(suggestionsMenu, suggestionItem.blockType, suggestionItem.blockOptions)\">\n <div class=\"h-full flex items-center gap-3 py-2\">\n <div class=\"size-9 flex items-center rounded-lg justify-center bg-surface-container\">\n <ngs-icon [name]=\"suggestionItem.iconName\" class=\"!me-0\"/>\n </div>\n <div class=\"grow min-w-[200px]\">\n <div>{{ suggestionItem.title }}</div>\n <div class=\"text-2xs text-neutral-500\">{{ suggestionItem.description }}</div>\n </div>\n @if (suggestionItem.hotKeys) {\n <div class=\"ms-auto bg-surface-container-highest rounded-full h-5\n text-4xs px-2 flex items-center font-bold\">{{ suggestionItem.hotKeys }}</div>\n }\n </div>\n </button>\n }\n }\n }\n </div>\n</ngs-menu>\n", styles: [":host{--ngs-content-editor-builder-content-width: 704px;outline:none}:host ::ng-deep .link-selection,:host ::ng-deep .text-selection{display:inline-block;background:var(--ngs-color-secondary-fixed)}:host.is-block-dragging{cursor:grabbing}:host .container{display:flex;width:820px;min-height:200px;height:100%;padding:calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) calc(var(--spacing, .25rem) * 5) 0;margin:0 auto;outline:none}:host .content{flex-grow:1;width:calc(var(--ngs-content-editor-builder-content-width) + calc(var(--spacing, .25rem) * 10))}:host .block{position:relative;flex:none;padding:calc(var(--spacing, .25rem) * 1) 0;display:flex;align-items:center}:host .block:not(:has(.block-content.is-selected)):hover .block-content{background:var(--ngs-color-neutral-50)}:host:not(.is-block-dragging) .block:hover .block-controls,:host:not(.is-block-dragging) .block.is-active .block-controls{opacity:1}:host .block-content{position:relative;flex-grow:1;padding:calc(var(--spacing, .25rem) * 3)}:host .block-content.is-selected{background:var(--ngs-color-primary-100)}:host ::ng-deep .selection-area{background:var(--ngs-color-primary-100);opacity:.4;border:1px solid var(--ngs-color-primary);border-radius:var(--ngs-radius-sm)}:host ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:text;user-select:text}:host.select-none ::ng-deep .ngs-content-editor-content-editable,:host.is-selection-of-blocks-active ::ng-deep .ngs-content-editor-content-editable{-webkit-user-select:none!important;user-select:none!important}:host .block-controls{left:0;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2);opacity:0;flex:none}:host .block-controls.is-settings-popover-open{opacity:1}:host .block-controls.is-settings-popover-open .block-control:not(.block-control-drag){opacity:0}:host .block-control{cursor:pointer;width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center}:host .block-control:hover{background:var(--ngs-color-surface-container-low);color:var(--ngs-color-on-surface)}:host .block-control-drag button{cursor:grab}:host .drag-placeholder{height:calc(var(--spacing, .25rem) * 8);flex:none;position:relative}:host .drag-placeholder:before{position:absolute;left:calc(var(--spacing, .25rem) * 18);display:block;right:0;content:\"\";height:calc(var(--spacing, .25rem) * 2);top:50%;transform:translateY(-50%);background:var(--ngs-color-primary-300);border-radius:calc(var(--spacing, .25rem) * .5)}:host ::ng-deep code{color:var(--ngs-color-primary)}.cdk-drag.cdk-drag-preview{overflow:hidden;display:flex;align-items:center;color:var(--ngs-color-neutral-500);width:calc(var(--spacing, .25rem) * 18);padding:0 calc(var(--spacing, .25rem) * 2)}.cdk-drag.cdk-drag-preview .block-control{width:calc(var(--spacing, .25rem) * 7);height:calc(var(--spacing, .25rem) * 7);flex:none;border-radius:var(--ngs-radius-lg);display:inline-flex;align-items:center;justify-content:center;cursor:grabbing}.cdk-drag.cdk-drag-preview .block-control:first-child{opacity:0}.cdk-drag.cdk-drag-preview .block-control:last-child{color:var(--ngs-color-on-surface)}.cdk-drag.cdk-drag-preview .block-content{opacity:0}.settings-popover{--ngs-list-list-item-one-line-container-height: calc(var(--spacing, .25rem) * 10)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2582
+ }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], contentChangedDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentChangedDelay", required: false }] }], persistDraft: [{ type: i0.Input, args: [{ isSignal: true, alias: "persistDraft", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], scrollContainer: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollContainer", required: false }] }], contentChanged: [{ type: i0.Output, args: ["contentChanged"] }] } });
2532
2583
 
2533
- class ContentViewerComponent {
2534
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2535
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: ContentViewerComponent, isStandalone: true, selector: "ngs-content-viewer", ngImport: i0, template: "<p>content-viewer works!</p>\n", styles: [""] });
2584
+ const CONTENT_EDITOR_BLOCK_RENDERERS = new InjectionToken('CONTENT_EDITOR_BLOCK_RENDERERS', {
2585
+ factory: () => [],
2586
+ });
2587
+ function provideContentEditorRenderers(renderers) {
2588
+ return makeEnvironmentProviders([
2589
+ {
2590
+ provide: CONTENT_EDITOR_BLOCK_RENDERERS,
2591
+ useValue: renderers,
2592
+ multi: true,
2593
+ },
2594
+ ]);
2595
+ }
2596
+ function provideContentEditorRenderer(renderer) {
2597
+ return provideContentEditorRenderers([renderer]);
2598
+ }
2599
+
2600
+ function getTextAlignment(props) {
2601
+ const value = props?.find(prop => prop.name === 'text-alignment')?.value;
2602
+ if (value === 'center' || value === 'right' || value === 'justify') {
2603
+ return value;
2604
+ }
2605
+ return 'left';
2606
+ }
2607
+ function getDimensionAttribute(value) {
2608
+ if (typeof value === 'number' && Number.isFinite(value)) {
2609
+ return value;
2610
+ }
2611
+ if (typeof value === 'string') {
2612
+ const trimmed = value.trim();
2613
+ if (!trimmed || trimmed === 'auto') {
2614
+ return null;
2615
+ }
2616
+ const parsed = Number.parseFloat(trimmed);
2617
+ return Number.isFinite(parsed) ? parsed : null;
2618
+ }
2619
+ return null;
2620
+ }
2621
+ function getHtmlContent(value) {
2622
+ return typeof value === 'string' ? value : '';
2536
2623
  }
2537
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentViewerComponent, decorators: [{
2624
+
2625
+ class ContentEditorCodeRenderer {
2626
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2627
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2628
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2629
+ content = input('', ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2630
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2631
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2632
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2633
+ code = computed(() => getHtmlContent(this.content()), ...(ngDevMode ? [{ debugName: "code" }] : /* istanbul ignore next */ []));
2634
+ language = computed(() => this.settings()?.language || 'none', ...(ngDevMode ? [{ debugName: "language" }] : /* istanbul ignore next */ []));
2635
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorCodeRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2636
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: ContentEditorCodeRenderer, isStandalone: true, selector: "ngs-content-editor-code-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-code-renderer" }, ngImport: i0, template: "<ngs-code-highlighter\n [code]=\"code()\"\n [language]=\"language()\"\n appearance=\"bordered\"\n showLanguage\n/>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: CodeHighlighter, selector: "ngs-code-highlighter", inputs: ["code", "language", "theme", "title", "appearance", "diff", "highlightLines", "showLanguage", "showCopyButton", "disableOverflow"], exportAs: ["ngsCodeHighlighter"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2637
+ }
2638
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorCodeRenderer, decorators: [{
2538
2639
  type: Component,
2539
- args: [{ selector: 'ngs-content-viewer', imports: [], template: "<p>content-viewer works!</p>\n" }]
2540
- }] });
2640
+ args: [{ selector: 'ngs-content-editor-code-renderer', imports: [
2641
+ CodeHighlighter,
2642
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2643
+ 'class': 'ngs-content-editor-code-renderer',
2644
+ }, template: "<ngs-code-highlighter\n [code]=\"code()\"\n [language]=\"language()\"\n appearance=\"bordered\"\n showLanguage\n/>\n", styles: [":host{display:block}\n"] }]
2645
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2646
+
2647
+ class ContentEditorDividerRenderer {
2648
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2649
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2650
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2651
+ content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2652
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2653
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2654
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2655
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorDividerRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2656
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: ContentEditorDividerRenderer, isStandalone: true, selector: "ngs-content-editor-divider-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-divider-renderer" }, ngImport: i0, template: "<ngs-divider/>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: Divider, selector: "ngs-divider", inputs: ["vertical", "inset", "fixedHeight"], exportAs: ["ngsDivider"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2657
+ }
2658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorDividerRenderer, decorators: [{
2659
+ type: Component,
2660
+ args: [{ selector: 'ngs-content-editor-divider-renderer', imports: [
2661
+ Divider,
2662
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2663
+ 'class': 'ngs-content-editor-divider-renderer',
2664
+ }, template: "<ngs-divider/>\n", styles: [":host{display:block}\n"] }]
2665
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2666
+
2667
+ class ContentEditorEmbedRenderer {
2668
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2669
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2670
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2671
+ content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2672
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2673
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2674
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2675
+ url = computed(() => this.content()?.url || '', ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
2676
+ embedType = computed(() => this.content()?.type || '', ...(ngDevMode ? [{ debugName: "embedType" }] : /* istanbul ignore next */ []));
2677
+ width = computed(() => getDimensionAttribute(this.settings()?.width) || 700, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
2678
+ height = computed(() => getDimensionAttribute(this.settings()?.height) || 400, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
2679
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorEmbedRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2680
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorEmbedRenderer, isStandalone: true, selector: "ngs-content-editor-embed-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-embed-renderer" }, ngImport: i0, template: "@if (url()) {\n <figure>\n <iframe\n [attr.title]=\"embedType() || 'Embedded content'\"\n [src]=\"url() | safeResourceUrl\"\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n frameborder=\"0\"\n allowfullscreen\n ></iframe>\n </figure>\n}\n", styles: [":host{display:block}:host figure{margin:0}:host iframe{background:var(--ngs-color-surface-container-low);display:block;max-width:100%}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "pipe", type: SafeResourceUrlPipe, name: "safeResourceUrl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2681
+ }
2682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorEmbedRenderer, decorators: [{
2683
+ type: Component,
2684
+ args: [{ selector: 'ngs-content-editor-embed-renderer', imports: [
2685
+ SafeResourceUrlPipe,
2686
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2687
+ 'class': 'ngs-content-editor-embed-renderer',
2688
+ }, template: "@if (url()) {\n <figure>\n <iframe\n [attr.title]=\"embedType() || 'Embedded content'\"\n [src]=\"url() | safeResourceUrl\"\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n frameborder=\"0\"\n allowfullscreen\n ></iframe>\n </figure>\n}\n", styles: [":host{display:block}:host figure{margin:0}:host iframe{background:var(--ngs-color-surface-container-low);display:block;max-width:100%}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2689
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2690
+
2691
+ class ContentEditorHeadingRenderer {
2692
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2693
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2694
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2695
+ content = input('', ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2696
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2697
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2698
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2699
+ html = computed(() => getHtmlContent(this.content()), ...(ngDevMode ? [{ debugName: "html" }] : /* istanbul ignore next */ []));
2700
+ level = computed(() => {
2701
+ const level = this.settings()?.level;
2702
+ return level === 1 || level === 2 || level === 3 ? level : 2;
2703
+ }, ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
2704
+ alignment = computed(() => getTextAlignment(this.props()), ...(ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []));
2705
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorHeadingRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2706
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorHeadingRenderer, isStandalone: true, selector: "ngs-content-editor-heading-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.level-1": "level() === 1", "class.level-2": "level() === 2", "class.level-3": "level() === 3" }, classAttribute: "ngs-content-editor-heading-renderer" }, ngImport: i0, template: "@switch (level()) {\n @case (1) {\n <h1\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n ></h1>\n }\n @case (3) {\n <h3\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n ></h3>\n }\n @default {\n <h2\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n ></h2>\n }\n}\n", styles: [":host{display:block}:host .content-html{margin:0;font-weight:700;line-height:1.12}:host.level-1 .content-html{font-size:3rem}:host.level-2 .content-html{font-size:2.25rem}:host.level-3 .content-html{font-size:1.875rem}:host .align-left{text-align:left}:host .align-center{text-align:center}:host .align-right{text-align:right}:host .align-justify{text-align:justify}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2707
+ }
2708
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorHeadingRenderer, decorators: [{
2709
+ type: Component,
2710
+ args: [{ selector: 'ngs-content-editor-heading-renderer', imports: [
2711
+ SafeHtmlPipe,
2712
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2713
+ 'class': 'ngs-content-editor-heading-renderer',
2714
+ '[class.level-1]': 'level() === 1',
2715
+ '[class.level-2]': 'level() === 2',
2716
+ '[class.level-3]': 'level() === 3',
2717
+ }, template: "@switch (level()) {\n @case (1) {\n <h1\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n ></h1>\n }\n @case (3) {\n <h3\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n ></h3>\n }\n @default {\n <h2\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n ></h2>\n }\n}\n", styles: [":host{display:block}:host .content-html{margin:0;font-weight:700;line-height:1.12}:host.level-1 .content-html{font-size:3rem}:host.level-2 .content-html{font-size:2.25rem}:host.level-3 .content-html{font-size:1.875rem}:host .align-left{text-align:left}:host .align-center{text-align:center}:host .align-right{text-align:right}:host .align-justify{text-align:justify}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2718
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2719
+
2720
+ class ContentEditorImageRenderer {
2721
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2722
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2723
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2724
+ content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2725
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2726
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2727
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2728
+ src = computed(() => this.content()?.src || '', ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
2729
+ alt = computed(() => this.content()?.alt || '', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
2730
+ width = computed(() => getDimensionAttribute(this.settings()?.width), ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
2731
+ height = computed(() => getDimensionAttribute(this.settings()?.height), ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
2732
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorImageRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2733
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorImageRenderer, isStandalone: true, selector: "ngs-content-editor-image-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-image-renderer" }, ngImport: i0, template: "@if (src()) {\n <figure>\n <img [src]=\"src()\" [alt]=\"alt()\" [attr.width]=\"width()\" [attr.height]=\"height()\">\n @if (alt()) {\n <figcaption>{{ alt() }}</figcaption>\n }\n </figure>\n}\n", styles: [":host{display:block}:host figure{margin:0}:host img{display:block;max-width:100%;height:auto}:host figcaption{margin-top:calc(var(--spacing, .25rem) * 2);color:var(--ngs-color-neutral-600);font-size:var(--ngs-font-size-sm);text-align:center}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2734
+ }
2735
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorImageRenderer, decorators: [{
2736
+ type: Component,
2737
+ args: [{ selector: 'ngs-content-editor-image-renderer', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2738
+ 'class': 'ngs-content-editor-image-renderer',
2739
+ }, template: "@if (src()) {\n <figure>\n <img [src]=\"src()\" [alt]=\"alt()\" [attr.width]=\"width()\" [attr.height]=\"height()\">\n @if (alt()) {\n <figcaption>{{ alt() }}</figcaption>\n }\n </figure>\n}\n", styles: [":host{display:block}:host figure{margin:0}:host img{display:block;max-width:100%;height:auto}:host figcaption{margin-top:calc(var(--spacing, .25rem) * 2);color:var(--ngs-color-neutral-600);font-size:var(--ngs-font-size-sm);text-align:center}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2740
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2741
+
2742
+ class ContentEditorListRenderer {
2743
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2744
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2745
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2746
+ content = input([], ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2747
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2748
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2749
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2750
+ items = computed(() => this.content() || [], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
2751
+ listStyle = computed(() => this.settings()?.listStyle || 'bullet', ...(ngDevMode ? [{ debugName: "listStyle" }] : /* istanbul ignore next */ []));
2752
+ childItems(item) {
2753
+ return item.children || [];
2754
+ }
2755
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorListRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2756
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorListRenderer, isStandalone: true, selector: "ngs-content-editor-list-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.list-bullet": "listStyle() === 'bullet'", "class.list-ordered": "listStyle() === 'ordered'" }, classAttribute: "ngs-content-editor-list-renderer" }, ngImport: i0, template: "@if (listStyle() === 'ordered') {\n <ol class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: items(), ordered: true }\"\n />\n </ol>\n} @else {\n <ul class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: items(), ordered: false }\"\n />\n </ul>\n}\n\n<ng-template #listTpl let-list let-ordered=\"ordered\">\n @for (item of list; track $index) {\n <li>\n <span class=\"content-html\" [innerHTML]=\"item.content | safeHtml\"></span>\n @if (childItems(item).length > 0) {\n @if (ordered) {\n <ol class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: childItems(item), ordered: ordered }\"\n />\n </ol>\n } @else {\n <ul class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: childItems(item), ordered: ordered }\"\n />\n </ul>\n }\n }\n </li>\n }\n</ng-template>\n", styles: [":host{display:block}:host .list{margin:0;padding-inline-start:calc(var(--spacing, .25rem) * 4)}:host .list .list{margin-top:calc(var(--spacing, .25rem) * 2)}:host li{margin:calc(var(--spacing, .25rem) * 1) 0}:host.list-bullet .list{list-style-type:disc}:host.list-ordered .list{list-style-type:decimal}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2757
+ }
2758
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorListRenderer, decorators: [{
2759
+ type: Component,
2760
+ args: [{ selector: 'ngs-content-editor-list-renderer', imports: [
2761
+ NgTemplateOutlet,
2762
+ SafeHtmlPipe,
2763
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2764
+ 'class': 'ngs-content-editor-list-renderer',
2765
+ '[class.list-bullet]': "listStyle() === 'bullet'",
2766
+ '[class.list-ordered]': "listStyle() === 'ordered'",
2767
+ }, template: "@if (listStyle() === 'ordered') {\n <ol class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: items(), ordered: true }\"\n />\n </ol>\n} @else {\n <ul class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: items(), ordered: false }\"\n />\n </ul>\n}\n\n<ng-template #listTpl let-list let-ordered=\"ordered\">\n @for (item of list; track $index) {\n <li>\n <span class=\"content-html\" [innerHTML]=\"item.content | safeHtml\"></span>\n @if (childItems(item).length > 0) {\n @if (ordered) {\n <ol class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: childItems(item), ordered: ordered }\"\n />\n </ol>\n } @else {\n <ul class=\"list\">\n <ng-container\n [ngTemplateOutlet]=\"listTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: childItems(item), ordered: ordered }\"\n />\n </ul>\n }\n }\n </li>\n }\n</ng-template>\n", styles: [":host{display:block}:host .list{margin:0;padding-inline-start:calc(var(--spacing, .25rem) * 4)}:host .list .list{margin-top:calc(var(--spacing, .25rem) * 2)}:host li{margin:calc(var(--spacing, .25rem) * 1) 0}:host.list-bullet .list{list-style-type:disc}:host.list-ordered .list{list-style-type:decimal}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2768
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2769
+
2770
+ class ContentEditorParagraphRenderer {
2771
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2772
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2773
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2774
+ content = input('', ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2775
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2776
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2777
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2778
+ html = computed(() => getHtmlContent(this.content()), ...(ngDevMode ? [{ debugName: "html" }] : /* istanbul ignore next */ []));
2779
+ alignment = computed(() => getTextAlignment(this.props()), ...(ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []));
2780
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorParagraphRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2781
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.4", type: ContentEditorParagraphRenderer, isStandalone: true, selector: "ngs-content-editor-paragraph-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-paragraph-renderer" }, ngImport: i0, template: "<p\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n></p>\n", styles: [":host{display:block}:host .content-html{margin:0;line-height:var(--leading-normal)}:host .align-left{text-align:left}:host .align-center{text-align:center}:host .align-right{text-align:right}:host .align-justify{text-align:justify}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2782
+ }
2783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorParagraphRenderer, decorators: [{
2784
+ type: Component,
2785
+ args: [{ selector: 'ngs-content-editor-paragraph-renderer', imports: [
2786
+ SafeHtmlPipe,
2787
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2788
+ 'class': 'ngs-content-editor-paragraph-renderer',
2789
+ }, template: "<p\n class=\"content-html\"\n [class.align-left]=\"alignment() === 'left'\"\n [class.align-center]=\"alignment() === 'center'\"\n [class.align-right]=\"alignment() === 'right'\"\n [class.align-justify]=\"alignment() === 'justify'\"\n [innerHTML]=\"html() | safeHtml\"\n></p>\n", styles: [":host{display:block}:host .content-html{margin:0;line-height:var(--leading-normal)}:host .align-left{text-align:left}:host .align-center{text-align:center}:host .align-right{text-align:right}:host .align-justify{text-align:justify}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2790
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2791
+
2792
+ class ContentEditorQuoteRenderer {
2793
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2794
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2795
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2796
+ content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2797
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2798
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2799
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2800
+ quoteHtml = computed(() => getHtmlContent(this.content()?.cite?.content), ...(ngDevMode ? [{ debugName: "quoteHtml" }] : /* istanbul ignore next */ []));
2801
+ captionHtml = computed(() => getHtmlContent(this.content()?.caption?.content), ...(ngDevMode ? [{ debugName: "captionHtml" }] : /* istanbul ignore next */ []));
2802
+ quoteAlignment = computed(() => getTextAlignment(this.content()?.cite?.props), ...(ngDevMode ? [{ debugName: "quoteAlignment" }] : /* istanbul ignore next */ []));
2803
+ captionAlignment = computed(() => getTextAlignment(this.content()?.caption?.props), ...(ngDevMode ? [{ debugName: "captionAlignment" }] : /* istanbul ignore next */ []));
2804
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorQuoteRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2805
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorQuoteRenderer, isStandalone: true, selector: "ngs-content-editor-quote-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-quote-renderer" }, ngImport: i0, template: "<blockquote\n class=\"content-html\"\n [class.align-left]=\"quoteAlignment() === 'left'\"\n [class.align-center]=\"quoteAlignment() === 'center'\"\n [class.align-right]=\"quoteAlignment() === 'right'\"\n [class.align-justify]=\"quoteAlignment() === 'justify'\"\n [innerHTML]=\"quoteHtml() | safeHtml\"\n></blockquote>\n@if (captionHtml()) {\n <figcaption\n class=\"caption-html\"\n [class.align-left]=\"captionAlignment() === 'left'\"\n [class.align-center]=\"captionAlignment() === 'center'\"\n [class.align-right]=\"captionAlignment() === 'right'\"\n [class.align-justify]=\"captionAlignment() === 'justify'\"\n [innerHTML]=\"captionHtml() | safeHtml\"\n ></figcaption>\n}\n", styles: [":host{display:block}:host .content-html{border-inline-start:calc(var(--spacing, .25rem) * 1) solid var(--ngs-color-border);margin:0 0 calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 3)}:host .caption-html{color:var(--ngs-color-neutral-600);display:block;font-size:var(--ngs-font-size-sm)}:host .align-left{text-align:left}:host .align-center{text-align:center}:host .align-right{text-align:right}:host .align-justify{text-align:justify}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2806
+ }
2807
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorQuoteRenderer, decorators: [{
2808
+ type: Component,
2809
+ args: [{ selector: 'ngs-content-editor-quote-renderer', imports: [
2810
+ SafeHtmlPipe,
2811
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2812
+ 'class': 'ngs-content-editor-quote-renderer',
2813
+ }, template: "<blockquote\n class=\"content-html\"\n [class.align-left]=\"quoteAlignment() === 'left'\"\n [class.align-center]=\"quoteAlignment() === 'center'\"\n [class.align-right]=\"quoteAlignment() === 'right'\"\n [class.align-justify]=\"quoteAlignment() === 'justify'\"\n [innerHTML]=\"quoteHtml() | safeHtml\"\n></blockquote>\n@if (captionHtml()) {\n <figcaption\n class=\"caption-html\"\n [class.align-left]=\"captionAlignment() === 'left'\"\n [class.align-center]=\"captionAlignment() === 'center'\"\n [class.align-right]=\"captionAlignment() === 'right'\"\n [class.align-justify]=\"captionAlignment() === 'justify'\"\n [innerHTML]=\"captionHtml() | safeHtml\"\n ></figcaption>\n}\n", styles: [":host{display:block}:host .content-html{border-inline-start:calc(var(--spacing, .25rem) * 1) solid var(--ngs-color-border);margin:0 0 calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 3)}:host .caption-html{color:var(--ngs-color-neutral-600);display:block;font-size:var(--ngs-font-size-sm)}:host .align-left{text-align:left}:host .align-center{text-align:center}:host .align-right{text-align:right}:host .align-justify{text-align:justify}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2814
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2815
+
2816
+ class ContentEditorTableRenderer {
2817
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2818
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2819
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2820
+ content = input([], ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2821
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2822
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2823
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2824
+ rows = computed(() => this.content() || [], ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
2825
+ firstRow = computed(() => this.rows()[0] || [], ...(ngDevMode ? [{ debugName: "firstRow" }] : /* istanbul ignore next */ []));
2826
+ width(cell) {
2827
+ return getDimensionAttribute(cell.options?.width);
2828
+ }
2829
+ colSpan(cell) {
2830
+ return cell.options?.colspan || 1;
2831
+ }
2832
+ rowSpan(cell) {
2833
+ return cell.options?.rowspan || 1;
2834
+ }
2835
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorTableRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2836
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorTableRenderer, isStandalone: true, selector: "ngs-content-editor-table-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-table-renderer" }, ngImport: i0, template: "@if (rows().length > 0) {\n <div class=\"table-overflow\">\n <table ngs-native-table>\n <colgroup>\n @for (cell of firstRow(); track $index) {\n <col [attr.width]=\"width(cell)\">\n }\n </colgroup>\n <tbody>\n @for (row of rows(); track $index) {\n <tr>\n @for (cell of row; track $index) {\n <td\n [attr.colspan]=\"colSpan(cell)\"\n [attr.rowspan]=\"rowSpan(cell)\"\n [innerHTML]=\"(cell.content || '') | safeHtml\"\n ></td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n}\n", styles: [":host{display:block}:host .table-overflow{overflow-x:auto;overflow-y:hidden;width:100%}:host table{min-width:100%;word-break:break-word}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: NativeTable, selector: "table[ngs-native-table]", exportAs: ["ngsNativeTable"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2837
+ }
2838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorTableRenderer, decorators: [{
2839
+ type: Component,
2840
+ args: [{ selector: 'ngs-content-editor-table-renderer', imports: [
2841
+ NativeTable,
2842
+ SafeHtmlPipe,
2843
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2844
+ 'class': 'ngs-content-editor-table-renderer',
2845
+ }, template: "@if (rows().length > 0) {\n <div class=\"table-overflow\">\n <table ngs-native-table>\n <colgroup>\n @for (cell of firstRow(); track $index) {\n <col [attr.width]=\"width(cell)\">\n }\n </colgroup>\n <tbody>\n @for (row of rows(); track $index) {\n <tr>\n @for (cell of row; track $index) {\n <td\n [attr.colspan]=\"colSpan(cell)\"\n [attr.rowspan]=\"rowSpan(cell)\"\n [innerHTML]=\"(cell.content || '') | safeHtml\"\n ></td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n}\n", styles: [":host{display:block}:host .table-overflow{overflow-x:auto;overflow-y:hidden;width:100%}:host table{min-width:100%;word-break:break-word}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2846
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2847
+
2848
+ class ContentEditorVideoRenderer {
2849
+ block = input(null, ...(ngDevMode ? [{ debugName: "block" }] : /* istanbul ignore next */ []));
2850
+ id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2851
+ type = input('', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2852
+ content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2853
+ props = input([], ...(ngDevMode ? [{ debugName: "props" }] : /* istanbul ignore next */ []));
2854
+ settings = input({}, ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
2855
+ index = input(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
2856
+ src = computed(() => this.content()?.src || '', ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
2857
+ caption = computed(() => this.content()?.caption || '', ...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
2858
+ width = computed(() => getDimensionAttribute(this.settings()?.width), ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
2859
+ height = computed(() => getDimensionAttribute(this.settings()?.height), ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
2860
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorVideoRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2861
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorVideoRenderer, isStandalone: true, selector: "ngs-content-editor-video-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-video-renderer" }, ngImport: i0, template: "@if (src()) {\n <figure>\n <video\n [src]=\"src()\"\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n controls\n ></video>\n @if (caption()) {\n <figcaption>{{ caption() }}</figcaption>\n }\n </figure>\n}\n", styles: [":host{display:block}:host figure{margin:0}:host video{display:block;max-width:100%;height:auto}:host figcaption{margin-top:calc(var(--spacing, .25rem) * 2);color:var(--ngs-color-neutral-600);font-size:var(--ngs-font-size-sm);text-align:center}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2862
+ }
2863
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorVideoRenderer, decorators: [{
2864
+ type: Component,
2865
+ args: [{ selector: 'ngs-content-editor-video-renderer', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2866
+ 'class': 'ngs-content-editor-video-renderer',
2867
+ }, template: "@if (src()) {\n <figure>\n <video\n [src]=\"src()\"\n [attr.width]=\"width()\"\n [attr.height]=\"height()\"\n controls\n ></video>\n @if (caption()) {\n <figcaption>{{ caption() }}</figcaption>\n }\n </figure>\n}\n", styles: [":host{display:block}:host figure{margin:0}:host video{display:block;max-width:100%;height:auto}:host figcaption{margin-top:calc(var(--spacing, .25rem) * 2);color:var(--ngs-color-neutral-600);font-size:var(--ngs-font-size-sm);text-align:center}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2868
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], settings: [{ type: i0.Input, args: [{ isSignal: true, alias: "settings", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
2869
+
2870
+ const CONTENT_EDITOR_DEFAULT_RENDERERS = [
2871
+ {
2872
+ type: 'paragraph',
2873
+ component: ContentEditorParagraphRenderer,
2874
+ },
2875
+ {
2876
+ type: 'heading',
2877
+ component: ContentEditorHeadingRenderer,
2878
+ },
2879
+ {
2880
+ type: 'code',
2881
+ component: ContentEditorCodeRenderer,
2882
+ },
2883
+ {
2884
+ type: 'divider',
2885
+ component: ContentEditorDividerRenderer,
2886
+ },
2887
+ {
2888
+ type: 'image',
2889
+ component: ContentEditorImageRenderer,
2890
+ },
2891
+ {
2892
+ type: 'video',
2893
+ component: ContentEditorVideoRenderer,
2894
+ },
2895
+ {
2896
+ type: 'bulletList',
2897
+ component: ContentEditorListRenderer,
2898
+ },
2899
+ {
2900
+ type: 'orderedList',
2901
+ component: ContentEditorListRenderer,
2902
+ },
2903
+ {
2904
+ type: 'table',
2905
+ component: ContentEditorTableRenderer,
2906
+ },
2907
+ {
2908
+ type: 'quote',
2909
+ component: ContentEditorQuoteRenderer,
2910
+ },
2911
+ {
2912
+ type: 'embed',
2913
+ component: ContentEditorEmbedRenderer,
2914
+ },
2915
+ ];
2916
+
2917
+ class ContentEditorRenderer {
2918
+ providedRendererGroups = inject(CONTENT_EDITOR_BLOCK_RENDERERS, {
2919
+ optional: true,
2920
+ }) || [];
2921
+ content = input([], ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
2922
+ blocks = input(null, ...(ngDevMode ? [{ debugName: "blocks" }] : /* istanbul ignore next */ []));
2923
+ rendererMap = computed(() => {
2924
+ const renderers = [
2925
+ ...CONTENT_EDITOR_DEFAULT_RENDERERS,
2926
+ ...this.providedRendererGroups.flat(),
2927
+ ];
2928
+ return new Map(renderers.map(renderer => [renderer.type, renderer.component]));
2929
+ }, ...(ngDevMode ? [{ debugName: "rendererMap" }] : /* istanbul ignore next */ []));
2930
+ items = computed(() => {
2931
+ const content = this.blocks() || this.content() || [];
2932
+ const rendererMap = this.rendererMap();
2933
+ return content.map((block, index) => ({
2934
+ block,
2935
+ component: rendererMap.get(block.type) || null,
2936
+ inputs: {
2937
+ block,
2938
+ id: block.id,
2939
+ type: block.type,
2940
+ content: block.content,
2941
+ props: block.props || [],
2942
+ settings: block.settings || {},
2943
+ index,
2944
+ },
2945
+ }));
2946
+ }, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
2947
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2948
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: ContentEditorRenderer, isStandalone: true, selector: "ngs-content-editor-renderer", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, blocks: { classPropertyName: "blocks", publicName: "blocks", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngs-content-editor-renderer prose max-w-full" }, exportAs: ["ngsContentEditorRenderer"], ngImport: i0, template: "@for (item of items(); track item.block.id || $index) {\n @if (item.component) {\n <div class=\"block\" [attr.data-block-id]=\"item.block.id\" [attr.data-block-type]=\"item.block.type\">\n <ng-container\n [ngComponentOutlet]=\"item.component\"\n [ngComponentOutletInputs]=\"item.inputs\"\n />\n </div>\n }\n}\n", styles: [":host{--ngs-content-editor-renderer-block-gap: calc(var(--spacing, .25rem) * 4);display:flex;flex-direction:column;gap:var(--ngs-content-editor-renderer-block-gap)}:host .block{min-width:0}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2949
+ }
2950
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: ContentEditorRenderer, decorators: [{
2951
+ type: Component,
2952
+ args: [{ selector: 'ngs-content-editor-renderer', exportAs: 'ngsContentEditorRenderer', imports: [
2953
+ NgComponentOutlet,
2954
+ ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
2955
+ 'class': 'ngs-content-editor-renderer prose max-w-full',
2956
+ }, template: "@for (item of items(); track item.block.id || $index) {\n @if (item.component) {\n <div class=\"block\" [attr.data-block-id]=\"item.block.id\" [attr.data-block-type]=\"item.block.type\">\n <ng-container\n [ngComponentOutlet]=\"item.component\"\n [ngComponentOutletInputs]=\"item.inputs\"\n />\n </div>\n }\n}\n", styles: [":host{--ngs-content-editor-renderer-block-gap: calc(var(--spacing, .25rem) * 4);display:flex;flex-direction:column;gap:var(--ngs-content-editor-renderer-block-gap)}:host .block{min-width:0}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
2957
+ }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], blocks: [{ type: i0.Input, args: [{ isSignal: true, alias: "blocks", required: false }] }] } });
2541
2958
 
2542
2959
  /**
2543
2960
  * Generated bundle index. Do not edit.
2544
2961
  */
2545
2962
 
2546
- export { BlockSelectionDirective as B, ContentBuilderStore as C, TextSelectionPopupDirective as T, CONTENT_BUILDER as a, CONTENT_EDITOR_BLOCK as b, CommandBarComponent as c, ContentBuilderComponent as d, ContentViewerComponent as e };
2547
- //# sourceMappingURL=ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-BuMm25ea.mjs.map
2963
+ export { BlockSelectionDirective as B, ContentBuilderStore as C, TextSelectionPopupDirective as T, CONTENT_BUILDER as a, CONTENT_EDITOR_BLOCK as b, CONTENT_EDITOR_BLOCK_RENDERERS as c, CONTENT_EDITOR_DEFAULT_RENDERERS as d, CommandBarComponent as e, ContentBuilderComponent as f, ContentEditorCodeRenderer as g, ContentEditorDividerRenderer as h, ContentEditorEmbedRenderer as i, ContentEditorHeadingRenderer as j, ContentEditorImageRenderer as k, ContentEditorListRenderer as l, ContentEditorParagraphRenderer as m, ContentEditorQuoteRenderer as n, ContentEditorRenderer as o, ContentEditorTableRenderer as p, ContentEditorVideoRenderer as q, provideContentEditorRenderer as r, provideContentEditorRenderers as s };
2964
+ //# sourceMappingURL=ngstarter-ui-components-content-editor-ngstarter-ui-components-content-editor-DA-VnRa_.mjs.map