@firestitch/content 18.0.4 → 18.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,136 +1,215 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ChangeDetectorRef, Component, ChangeDetectionStrategy, ViewChildren, Input, EventEmitter, Output, ViewChild, NgModule, ElementRef } from '@angular/core';
2
+ import { inject, ElementRef, Component, ChangeDetectionStrategy, ViewChild, Input, InjectionToken, ChangeDetectorRef, NgModule, EventEmitter, Output, ViewChildren } from '@angular/core';
3
+ import { DomSanitizer, Title } from '@angular/platform-browser';
4
+ import { Router, NavigationEnd, RouterLink } from '@angular/router';
5
+ import { HtmlRenderer } from '@firestitch/html';
6
+ import { Subject, of, throwError, fromEvent } from 'rxjs';
7
+ import { filter, takeUntil, tap, switchMap, finalize, map } from 'rxjs/operators';
8
+ import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
3
9
  import * as i4 from '@angular/material/dialog';
4
10
  import { MAT_DIALOG_DATA, MatDialogRef, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialog } from '@angular/material/dialog';
5
11
  import { FsMessage } from '@firestitch/message';
6
- import * as i2$1 from '@firestitch/text-editor';
7
- import { FsTextEditorComponent, FsTextEditorModule } from '@firestitch/text-editor';
8
- import { Subject, of, throwError, fromEvent } from 'rxjs';
9
- import { tap, switchMap, takeUntil, filter, finalize, map } from 'rxjs/operators';
10
- import * as i1 from '@firestitch/skeleton';
11
- import { FsSkeletonModule } from '@firestitch/skeleton';
12
- import * as i2 from '@angular/forms';
12
+ import { FsPrompt } from '@firestitch/prompt';
13
+ import * as i2 from '@firestitch/text-editor';
14
+ import { FsTextEditorModule, FsTextEditorComponent } from '@firestitch/text-editor';
15
+ import * as i1 from 'angular-split';
16
+ import { AngularSplitModule } from 'angular-split';
17
+ import { NgClass, NgTemplateOutlet } from '@angular/common';
18
+ import * as i2$1 from '@angular/forms';
13
19
  import { FormsModule } from '@angular/forms';
14
20
  import * as i3 from '@firestitch/form';
15
21
  import { FsFormModule, FsFormDirective } from '@firestitch/form';
16
- import * as i5 from '@firestitch/dialog';
22
+ import * as i5 from '@firestitch/common';
23
+ import { FsCommonModule, index } from '@firestitch/common';
24
+ import * as i1$1 from '@firestitch/skeleton';
25
+ import { FsSkeletonModule } from '@firestitch/skeleton';
26
+ import * as i5$1 from '@firestitch/dialog';
17
27
  import { FsDialogModule } from '@firestitch/dialog';
18
28
  import { CdkScrollable } from '@angular/cdk/scrolling';
19
29
  import { MatFormField, MatLabel } from '@angular/material/form-field';
20
- import { MatSelect } from '@angular/material/select';
21
- import { MatOption } from '@angular/material/core';
22
30
  import { MatInput } from '@angular/material/input';
23
- import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
24
- import { FsPrompt } from '@firestitch/prompt';
25
- import * as i1$1 from 'angular-split';
26
- import { AngularSplitModule } from 'angular-split';
27
- import { NgClass, NgTemplateOutlet } from '@angular/common';
28
- import * as i5$1 from '@firestitch/common';
29
- import { FsCommonModule, index } from '@firestitch/common';
30
- import { MatIconAnchor, MatButton, MatAnchor } from '@angular/material/button';
31
+ import * as i6 from '@angular/material/button';
32
+ import { MatButtonModule } from '@angular/material/button';
31
33
  import { MatIcon } from '@angular/material/icon';
32
34
  import { MatTooltip } from '@angular/material/tooltip';
33
- import { RouterLink, Router, NavigationEnd } from '@angular/router';
34
35
  import { ItemType } from '@firestitch/filter';
35
36
  import * as i1$2 from '@firestitch/list';
36
37
  import { FsListComponent, FsListModule } from '@firestitch/list';
37
38
  import * as i2$2 from '@firestitch/date';
38
39
  import { FsDateModule } from '@firestitch/date';
39
- import { DomSanitizer, Title } from '@angular/platform-browser';
40
- import { HtmlRenderer } from '@firestitch/html';
41
-
42
- var EditorType;
43
- (function (EditorType) {
44
- EditorType["Js"] = "js";
45
- EditorType["Html"] = "html";
46
- EditorType["Scss"] = "scss";
47
- EditorType["GlobalScss"] = "globalScss";
48
- })(EditorType || (EditorType = {}));
49
-
50
- var PageType;
51
- (function (PageType) {
52
- PageType["StandardPage"] = "standardPage";
53
- PageType["BlogPost"] = "blogPost";
54
- PageType["HomePage"] = "homePage";
55
- PageType["NotFoundPage"] = "notFoundPage";
56
- })(PageType || (PageType = {}));
40
+ import { MatSelect } from '@angular/material/select';
41
+ import { MatOption } from '@angular/material/core';
57
42
 
58
- const PageTypes = [
59
- { name: 'Page', value: PageType.StandardPage },
60
- { name: 'Page (Not Found)', value: PageType.NotFoundPage },
61
- ];
43
+ class ContentRendererComponent {
44
+ _sanitizer = inject(DomSanitizer);
45
+ _router = inject(Router);
46
+ _el = inject(ElementRef);
47
+ _htmlRenderer = inject(HtmlRenderer);
48
+ script;
49
+ contentPage;
50
+ content;
51
+ _destroy$ = new Subject();
52
+ ngOnChanges(changes) {
53
+ if (changes.contentPage.currentValue) {
54
+ this._htmlRenderer.addStyle(this.contentPage.styles, { id: 'contentPageStyles' });
55
+ this.content = this._sanitizer.bypassSecurityTrustHtml(this.contentPage.content);
56
+ }
57
+ }
58
+ ngAfterViewChecked() {
59
+ this.registerHrefs();
60
+ if (this.contentPage.js) {
61
+ const script = document.createElement('script');
62
+ script.text = this.contentPage.js;
63
+ this.script.nativeElement.after(script);
64
+ }
65
+ }
66
+ registerHrefs() {
67
+ Array.from(this.el.querySelectorAll('a[href]'))
68
+ .filter((el) => {
69
+ return el.getAttribute('href').match(/^\//);
70
+ })
71
+ .forEach((el) => {
72
+ el.addEventListener('click', (event) => {
73
+ if (!event.shiftKey && !event.ctrlKey) {
74
+ event.preventDefault();
75
+ const href = el.getAttribute('href');
76
+ this._router.navigateByUrl(href);
77
+ }
78
+ });
79
+ });
80
+ }
81
+ get el() {
82
+ return this._el.nativeElement;
83
+ }
84
+ ngOnDestroy() {
85
+ this.removeStyles();
86
+ this._destroy$.next(null);
87
+ this._destroy$.complete();
88
+ }
89
+ removeStyles() {
90
+ const el = document.querySelector('#contentPageStyles');
91
+ if (el) {
92
+ el.remove();
93
+ }
94
+ }
95
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
96
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentRendererComponent, isStandalone: true, selector: "fs-content-renderer", inputs: { contentPage: "contentPage" }, viewQueries: [{ propertyName: "script", first: true, predicate: ["script"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
97
+ }
98
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, decorators: [{
99
+ type: Component,
100
+ args: [{ selector: 'fs-content-renderer', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>" }]
101
+ }], propDecorators: { script: [{
102
+ type: ViewChild,
103
+ args: ['script', { read: ElementRef }]
104
+ }], contentPage: [{
105
+ type: Input
106
+ }] } });
62
107
 
63
108
  const FS_CONTENT_CONFIG = new InjectionToken('fs-content-config');
64
109
 
65
- class ContentPageComponent {
110
+ class FsContentComponent {
66
111
  _config = inject(FS_CONTENT_CONFIG);
67
- _data = inject(MAT_DIALOG_DATA);
68
- _dialogRef = inject(MatDialogRef);
69
- _message = inject(FsMessage);
112
+ _title = inject(Title);
70
113
  _cdRef = inject(ChangeDetectorRef);
71
- textEditors;
72
- contentPage = null;
73
- PageTypes = PageTypes;
74
- contentLayouts;
75
- editors = { content: true, styles: true };
114
+ _router = inject(Router);
115
+ _el = inject(ElementRef);
116
+ _htmlRenderer = inject(HtmlRenderer);
117
+ contentPage;
76
118
  _destroy$ = new Subject();
77
119
  ngOnInit() {
78
- this._dialogRef.updateSize('600px');
79
- this._fetchData();
120
+ this._initContent();
121
+ this._initStyles();
122
+ }
123
+ get el() {
124
+ return this._el.nativeElement;
80
125
  }
81
126
  ngOnDestroy() {
82
127
  this._destroy$.next(null);
83
128
  this._destroy$.complete();
129
+ this._title.setTitle('');
130
+ document.querySelector('#content-style')?.remove();
84
131
  }
85
- save = () => {
86
- return this._config.saveContentPage(this.contentPage)
87
- .pipe(tap((contentPage) => {
88
- this._message.success('Saved Changes');
89
- this._dialogRef.close(contentPage);
90
- }));
91
- };
92
- _fetchData() {
93
- this._config.loadContentLayouts()
94
- .subscribe((contentLayouts) => {
95
- this.contentLayouts = contentLayouts;
96
- this._cdRef.markForCheck();
132
+ _initStyles() {
133
+ if (this._config.loadContentStyleCss) {
134
+ this._config.loadContentStyleCss()
135
+ .subscribe((styles) => {
136
+ this._htmlRenderer.addStyle(styles, { id: 'content-style' });
137
+ });
138
+ }
139
+ }
140
+ _initContent() {
141
+ this._loadContent();
142
+ this._router.events
143
+ .pipe(filter((e) => e instanceof NavigationEnd), takeUntil(this._destroy$))
144
+ .subscribe((e) => {
145
+ this._loadContent();
97
146
  });
98
- of(this._data.contentPage)
99
- .pipe(switchMap((contentPage) => {
100
- return of(contentPage);
101
- }), takeUntil(this._destroy$))
147
+ }
148
+ _loadContent() {
149
+ const path = window.location.pathname;
150
+ this._config.loadContent(path)
102
151
  .subscribe((contentPage) => {
103
- this.contentPage = {
104
- ...contentPage,
105
- path: contentPage.path || '/',
106
- };
152
+ if (contentPage.title) {
153
+ this._title.setTitle(contentPage.title);
154
+ let ogTitleEl = document.querySelector('head meta[property="og:title"]');
155
+ if (!ogTitleEl) {
156
+ ogTitleEl = document.createElement('meta');
157
+ ogTitleEl.setAttribute('property', 'og:title');
158
+ document.getElementsByTagName('head')[0].appendChild(ogTitleEl);
159
+ }
160
+ ogTitleEl.setAttribute('content', contentPage.title);
161
+ }
162
+ this.contentPage = contentPage;
107
163
  this._cdRef.markForCheck();
108
164
  });
109
165
  }
110
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
111
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentPageComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
166
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
167
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentComponent, isStandalone: true, selector: "fs-content", ngImport: i0, template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}", styles: [""], dependencies: [{ kind: "component", type: ContentRendererComponent, selector: "fs-content-renderer", inputs: ["contentPage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
112
168
  }
113
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, decorators: [{
169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, decorators: [{
114
170
  type: Component,
115
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
116
- FsSkeletonModule,
117
- FormsModule,
118
- FsFormModule,
119
- FsDialogModule,
120
- MatDialogTitle,
121
- CdkScrollable,
122
- MatDialogContent,
123
- MatFormField,
124
- MatLabel,
125
- MatSelect,
126
- MatOption,
127
- MatInput,
128
- MatDialogActions,
129
- ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
130
- }], propDecorators: { textEditors: [{
131
- type: ViewChildren,
132
- args: [FsTextEditorComponent]
133
- }] } });
171
+ args: [{ selector: 'fs-content', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [ContentRendererComponent], template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}" }]
172
+ }] });
173
+
174
+ class FsContentModule {
175
+ static forRoot() {
176
+ return {
177
+ ngModule: FsContentModule,
178
+ };
179
+ }
180
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
181
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule, imports: [FsContentComponent,
182
+ ContentRendererComponent], exports: [FsContentComponent] });
183
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule });
184
+ }
185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentModule, decorators: [{
186
+ type: NgModule,
187
+ args: [{
188
+ imports: [
189
+ FsContentComponent,
190
+ ContentRendererComponent,
191
+ ],
192
+ exports: [
193
+ FsContentComponent,
194
+ ],
195
+ }]
196
+ }] });
197
+
198
+ var EditorType;
199
+ (function (EditorType) {
200
+ EditorType["Js"] = "js";
201
+ EditorType["Html"] = "html";
202
+ EditorType["Scss"] = "scss";
203
+ EditorType["GlobalScss"] = "globalScss";
204
+ })(EditorType || (EditorType = {}));
205
+
206
+ var PageType;
207
+ (function (PageType) {
208
+ PageType["StandardPage"] = "standardPage";
209
+ PageType["BlogPost"] = "blogPost";
210
+ PageType["HomePage"] = "homePage";
211
+ PageType["NotFoundPage"] = "notFoundPage";
212
+ })(PageType || (PageType = {}));
134
213
 
135
214
  class EditorLabelComponent {
136
215
  changed;
@@ -257,7 +336,7 @@ class EditorComponent {
257
336
  this.focused.emit(type);
258
337
  }
259
338
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: EditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
260
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: EditorComponent, isStandalone: true, selector: "app-editor", inputs: { showHtml: "showHtml", showScss: "showScss", showJs: "showJs", showGlobalScss: "showGlobalScss", html: "html", scss: "scss", js: "js", contentConfig: "contentConfig" }, outputs: { changed: "changed", focused: "focused", blured: "blured" }, ngImport: i0, template: "<as-split [unit]=\"'percent'\" [gutterSize]=\"25\"> \n <as-split-area [size]=\"70\" [visible]=\"showHtml\" [order]=\"1\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.html !== undefined\"\n [focused]=\"focusedArea === 'html'\">\n HTML\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"html\" \n name=\"html\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Html, $event)\"\n [config]=\"htmlConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showScss\" [order]=\"2\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.scss !== undefined\"\n [focused]=\"focusedArea === 'scss'\">\n SCSS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"scss\" \n name=\"scss\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Scss, $event)\"\n [config]=\"scssConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showJs\" [order]=\"3\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.js !== undefined\"\n [focused]=\"focusedArea === 'js'\">\n JS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"js\" \n name=\"js\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Js, $event)\"\n [config]=\"jsConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showGlobalScss\" [order]=\"4\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.globalScss !== undefined\"\n [focused]=\"focusedArea === 'globalScss'\">\n Global SCSS\n </app-editor-label>\n <ng-container *fsSkeleton=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"globalScss\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"change(EditorType.GlobalScss, $event)\"\n [config]=\"globalScssConfig\">\n </fs-text-editor> \n </ng-container> \n </div>\n </as-split-area>\n</as-split>\n", styles: [":host ::ng-deep .as-split-gutter{background-color:unset!important}.editor-container{height:100%;border-radius:5px;display:flex;flex-direction:column}.editor-container fs-text-editor{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: AngularSplitModule }, { kind: "component", type: i1$1.SplitComponent, selector: "as-split", inputs: ["direction", "unit", "gutterSize", "gutterStep", "restrictMove", "useTransition", "disabled", "dir", "gutterDblClickDuration", "gutterClickDeltaPx", "gutterAriaLabel"], outputs: ["transitionEnd", "dragStart", "dragEnd", "gutterClick", "gutterDblClick"], exportAs: ["asSplit"] }, { kind: "directive", type: i1$1.SplitAreaDirective, selector: "as-split-area, [as-split-area]", inputs: ["order", "size", "minSize", "maxSize", "lockSize", "visible"], exportAs: ["asSplitArea"] }, { kind: "component", type: EditorLabelComponent, selector: "app-editor-label", inputs: ["changed", "focused"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2$1.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5$1.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
339
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: EditorComponent, isStandalone: true, selector: "app-editor", inputs: { showHtml: "showHtml", showScss: "showScss", showJs: "showJs", showGlobalScss: "showGlobalScss", html: "html", scss: "scss", js: "js", contentConfig: "contentConfig" }, outputs: { changed: "changed", focused: "focused", blured: "blured" }, ngImport: i0, template: "<as-split [unit]=\"'percent'\" [gutterSize]=\"25\"> \n <as-split-area [size]=\"70\" [visible]=\"showHtml\" [order]=\"1\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.html !== undefined\"\n [focused]=\"focusedArea === 'html'\">\n HTML\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"html\" \n name=\"html\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Html, $event)\"\n [config]=\"htmlConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showScss\" [order]=\"2\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.scss !== undefined\"\n [focused]=\"focusedArea === 'scss'\">\n SCSS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"scss\" \n name=\"scss\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Scss, $event)\"\n [config]=\"scssConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showJs\" [order]=\"3\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.js !== undefined\"\n [focused]=\"focusedArea === 'js'\">\n JS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"js\" \n name=\"js\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Js, $event)\"\n [config]=\"jsConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showGlobalScss\" [order]=\"4\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.globalScss !== undefined\"\n [focused]=\"focusedArea === 'globalScss'\">\n Global SCSS\n </app-editor-label>\n <ng-container *fsSkeleton=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"globalScss\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"change(EditorType.GlobalScss, $event)\"\n [config]=\"globalScssConfig\">\n </fs-text-editor> \n </ng-container> \n </div>\n </as-split-area>\n</as-split>\n", styles: [":host{display:block;flex:1;height:100%;min-height:0}as-split{height:100%}:host ::ng-deep .as-split-gutter{background-color:unset!important}.editor-container{height:100%;border-radius:5px;display:flex;flex-direction:column}.editor-container fs-text-editor{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: AngularSplitModule }, { kind: "component", type: i1.SplitComponent, selector: "as-split", inputs: ["direction", "unit", "gutterSize", "gutterStep", "restrictMove", "useTransition", "disabled", "dir", "gutterDblClickDuration", "gutterClickDeltaPx", "gutterAriaLabel"], outputs: ["transitionEnd", "dragStart", "dragEnd", "gutterClick", "gutterDblClick"], exportAs: ["asSplit"] }, { kind: "directive", type: i1.SplitAreaDirective, selector: "as-split-area, [as-split-area]", inputs: ["order", "size", "minSize", "maxSize", "lockSize", "visible"], exportAs: ["asSplitArea"] }, { kind: "component", type: EditorLabelComponent, selector: "app-editor-label", inputs: ["changed", "focused"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
261
340
  }
262
341
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: EditorComponent, decorators: [{
263
342
  type: Component,
@@ -269,7 +348,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
269
348
  FsFormModule,
270
349
  FsCommonModule,
271
350
  FsSkeletonModule,
272
- ], template: "<as-split [unit]=\"'percent'\" [gutterSize]=\"25\"> \n <as-split-area [size]=\"70\" [visible]=\"showHtml\" [order]=\"1\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.html !== undefined\"\n [focused]=\"focusedArea === 'html'\">\n HTML\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"html\" \n name=\"html\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Html, $event)\"\n [config]=\"htmlConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showScss\" [order]=\"2\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.scss !== undefined\"\n [focused]=\"focusedArea === 'scss'\">\n SCSS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"scss\" \n name=\"scss\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Scss, $event)\"\n [config]=\"scssConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showJs\" [order]=\"3\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.js !== undefined\"\n [focused]=\"focusedArea === 'js'\">\n JS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"js\" \n name=\"js\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Js, $event)\"\n [config]=\"jsConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showGlobalScss\" [order]=\"4\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.globalScss !== undefined\"\n [focused]=\"focusedArea === 'globalScss'\">\n Global SCSS\n </app-editor-label>\n <ng-container *fsSkeleton=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"globalScss\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"change(EditorType.GlobalScss, $event)\"\n [config]=\"globalScssConfig\">\n </fs-text-editor> \n </ng-container> \n </div>\n </as-split-area>\n</as-split>\n", styles: [":host ::ng-deep .as-split-gutter{background-color:unset!important}.editor-container{height:100%;border-radius:5px;display:flex;flex-direction:column}.editor-container fs-text-editor{flex:1}\n"] }]
351
+ ], template: "<as-split [unit]=\"'percent'\" [gutterSize]=\"25\"> \n <as-split-area [size]=\"70\" [visible]=\"showHtml\" [order]=\"1\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.html !== undefined\"\n [focused]=\"focusedArea === 'html'\">\n HTML\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"html\" \n name=\"html\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Html, $event)\"\n [config]=\"htmlConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showScss\" [order]=\"2\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.scss !== undefined\"\n [focused]=\"focusedArea === 'scss'\">\n SCSS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"scss\" \n name=\"scss\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Scss, $event)\"\n [config]=\"scssConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showJs\" [order]=\"3\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.js !== undefined\"\n [focused]=\"focusedArea === 'js'\">\n JS\n </app-editor-label>\n <fs-text-editor \n [(ngModel)]=\"js\" \n name=\"js\"\n [fsModelChangeOptions]=\"{ debounce: 0 }\"\n (fsModelChange)=\"change(EditorType.Js, $event)\"\n [config]=\"jsConfig\">\n </fs-text-editor> \n </div>\n </as-split-area>\n <as-split-area [size]=\"30\" [visible]=\"showGlobalScss\" [order]=\"4\">\n <div class=\"editor-container\">\n <app-editor-label\n [changed]=\"changes.globalScss !== undefined\"\n [focused]=\"focusedArea === 'globalScss'\">\n Global SCSS\n </app-editor-label>\n <ng-container *fsSkeleton=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"globalScss\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"change(EditorType.GlobalScss, $event)\"\n [config]=\"globalScssConfig\">\n </fs-text-editor> \n </ng-container> \n </div>\n </as-split-area>\n</as-split>\n", styles: [":host{display:block;flex:1;height:100%;min-height:0}as-split{height:100%}:host ::ng-deep .as-split-gutter{background-color:unset!important}.editor-container{height:100%;border-radius:5px;display:flex;flex-direction:column}.editor-container fs-text-editor{flex:1}\n"] }]
273
352
  }], propDecorators: { showHtml: [{
274
353
  type: Input
275
354
  }], showScss: [{
@@ -294,7 +373,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
294
373
  type: Output
295
374
  }] } });
296
375
 
297
- class ContentPageEditorComponent {
376
+ class ContentLayoutComponent {
377
+ _config = inject(FS_CONTENT_CONFIG);
378
+ _data = inject(MAT_DIALOG_DATA);
379
+ _dialogRef = inject(MatDialogRef);
380
+ _message = inject(FsMessage);
381
+ _cdRef = inject(ChangeDetectorRef);
382
+ textEditors;
383
+ contentLayout = null;
384
+ editors = { content: true, styles: true };
385
+ _destroy$ = new Subject();
386
+ ngOnInit() {
387
+ this._fetchData();
388
+ }
389
+ ngOnDestroy() {
390
+ this._destroy$.next(null);
391
+ this._destroy$.complete();
392
+ }
393
+ save = () => {
394
+ return this._config.saveContentLayout(this.contentLayout)
395
+ .pipe(tap((contentLayout) => {
396
+ this._message.success('Saved Changes');
397
+ this._dialogRef.close(contentLayout);
398
+ }));
399
+ };
400
+ _fetchData() {
401
+ of(this._data.contentLayout)
402
+ .pipe(switchMap((contentLayout) => {
403
+ return of(contentLayout);
404
+ }), takeUntil(this._destroy$))
405
+ .subscribe((contentLayout) => {
406
+ this.contentLayout = { ...contentLayout };
407
+ this._cdRef.markForCheck();
408
+ });
409
+ }
410
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
411
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
412
+ }
413
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, decorators: [{
414
+ type: Component,
415
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
416
+ FsSkeletonModule,
417
+ FormsModule,
418
+ FsFormModule,
419
+ FsDialogModule,
420
+ MatDialogTitle,
421
+ CdkScrollable,
422
+ MatDialogContent,
423
+ MatFormField,
424
+ MatLabel,
425
+ MatInput,
426
+ MatDialogActions,
427
+ ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
428
+ }], propDecorators: { textEditors: [{
429
+ type: ViewChildren,
430
+ args: [FsTextEditorComponent]
431
+ }] } });
432
+
433
+ class ContentLayoutEditorComponent {
298
434
  _data = inject(MAT_DIALOG_DATA);
299
435
  _dialogRef = inject(MatDialogRef);
300
436
  _message = inject(FsMessage);
@@ -302,27 +438,26 @@ class ContentPageEditorComponent {
302
438
  _cdRef = inject(ChangeDetectorRef);
303
439
  _prompt = inject(FsPrompt);
304
440
  editor;
305
- contentPage;
306
- focused = null;
441
+ contentLayout;
442
+ get isMac() {
443
+ return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
444
+ }
445
+ submitting;
307
446
  config;
308
- resizing = false;
447
+ EditorType = EditorType;
448
+ focused = null;
309
449
  title;
310
450
  editors = {
311
451
  [EditorType.Html]: true,
312
452
  [EditorType.Scss]: true,
313
- [EditorType.Js]: false,
314
453
  [EditorType.GlobalScss]: false,
315
454
  };
316
- get isMac() {
317
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
318
- }
319
- submitting;
320
455
  _destroy$ = new Subject();
321
456
  ngOnInit() {
322
457
  this._dialogRef.addPanelClass('fs-content-editor-overlay-pane');
323
458
  this._dialogRef.disableClose = true;
324
459
  this.config = this._data.contentConfig;
325
- this._initContentPage(this._data.contentPage);
460
+ this._initContentLayout(this._data.contentLayout);
326
461
  this._initEscape();
327
462
  }
328
463
  editorToggleChange(event) {
@@ -332,10 +467,10 @@ class ContentPageEditorComponent {
332
467
  this._destroy$.next(null);
333
468
  this._destroy$.complete();
334
469
  }
335
- _initContentPage(contentPage) {
336
- this.config.loadContentPage(contentPage.id)
470
+ _initContentLayout(contentLayout) {
471
+ this.config.loadContentLayout(contentLayout.id)
337
472
  .subscribe((data) => {
338
- this.contentPage = data;
473
+ this.contentLayout = data;
339
474
  this._cdRef.markForCheck();
340
475
  });
341
476
  }
@@ -351,7 +486,6 @@ class ContentPageEditorComponent {
351
486
  return of(null)
352
487
  .pipe(filter(() => this.focused), switchMap(() => {
353
488
  switch (this.focused) {
354
- case EditorType.Js:
355
489
  case EditorType.Html:
356
490
  case EditorType.Scss:
357
491
  return this.saveContentPage();
@@ -365,21 +499,19 @@ class ContentPageEditorComponent {
365
499
  }), finalize(() => {
366
500
  this.submitting = false;
367
501
  this._cdRef.markForCheck();
368
- }))
369
- .pipe(takeUntil(this._destroy$));
502
+ }));
370
503
  };
371
504
  saveContentPage() {
372
505
  const names = {
373
- [EditorType.Js]: 'js',
374
506
  [EditorType.Scss]: 'styles',
375
507
  [EditorType.Html]: 'content',
376
508
  };
377
509
  const data = {
378
- id: this.contentPage.id,
510
+ id: this.contentLayout.id,
379
511
  [names[this.focused]]: this.editor.changes[this.focused],
380
512
  };
381
- return this.config.saveContentPage({
382
- id: this.contentPage.id,
513
+ return this.config.saveContentLayout({
514
+ id: this.contentLayout.id,
383
515
  ...data,
384
516
  })
385
517
  .pipe(tap(() => {
@@ -415,17 +547,17 @@ class ContentPageEditorComponent {
415
547
  });
416
548
  }
417
549
  openSettings() {
418
- this._dialog.open(ContentPageComponent, {
550
+ this._dialog.open(ContentLayoutComponent, {
419
551
  data: {
420
- contentPage: this.contentPage,
552
+ contentLayout: this.contentLayout,
421
553
  },
422
554
  })
423
555
  .afterClosed()
424
556
  .pipe(takeUntil(this._destroy$))
425
- .subscribe((contentPage) => {
426
- this.contentPage = {
427
- ...this.contentPage,
428
- ...contentPage,
557
+ .subscribe((contentLayout) => {
558
+ this.contentLayout = {
559
+ ...this.contentLayout,
560
+ ...contentLayout,
429
561
  };
430
562
  this._cdRef.markForCheck();
431
563
  });
@@ -439,10 +571,10 @@ class ContentPageEditorComponent {
439
571
  }
440
572
  });
441
573
  }
442
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
443
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentPageEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
574
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
575
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-container{border-radius:0;height:100%}::ng-deep .fs-content-editor-overlay-pane .mdc-dialog__container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-surface{height:100%}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content,fs-dialog ::ng-deep .mat-mdc-dialog-content{max-height:none;flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
444
576
  }
445
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, decorators: [{
577
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, decorators: [{
446
578
  type: Component,
447
579
  args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
448
580
  FormsModule,
@@ -450,45 +582,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
450
582
  FsSkeletonModule,
451
583
  FsDialogModule,
452
584
  MatDialogTitle,
453
- MatIconAnchor,
585
+ MatButtonModule,
454
586
  MatIcon,
455
587
  MatButtonToggleGroup,
456
588
  MatButtonToggle,
457
- MatButton,
458
589
  MatTooltip,
459
- MatAnchor,
460
- RouterLink,
461
590
  CdkScrollable,
462
591
  MatDialogContent,
463
592
  EditorComponent,
464
- ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
593
+ ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-container{border-radius:0;height:100%}::ng-deep .fs-content-editor-overlay-pane .mdc-dialog__container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-surface{height:100%}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content,fs-dialog ::ng-deep .mat-mdc-dialog-content{max-height:none;flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
465
594
  }], propDecorators: { editor: [{
466
595
  type: ViewChild,
467
596
  args: [EditorComponent]
468
597
  }] } });
469
598
 
470
- class FsContentPagesComponent {
599
+ class FsContentLayoutsComponent {
471
600
  _config = inject(FS_CONTENT_CONFIG);
472
601
  _dialog = inject(MatDialog);
473
- htmlEditorConfig;
474
602
  listComponent;
475
603
  listConfig;
476
- pageTypes = index(PageTypes, 'value', 'name');
477
604
  _destroy$ = new Subject();
478
605
  ngOnInit() {
479
606
  this._initListConfig();
480
607
  }
481
- openEditor(contentPage) {
482
- this._dialog.open(ContentPageEditorComponent, {
483
- data: {
484
- contentPage,
485
- config: this._config,
486
- contentConfig: this._config,
487
- },
608
+ openEditor(contentLayout) {
609
+ this._dialog.open(ContentLayoutEditorComponent, {
488
610
  maxWidth: '100vw',
489
611
  width: '100%',
490
612
  height: '100%',
491
- autoFocus: false,
613
+ data: {
614
+ contentLayout,
615
+ contentConfig: this._config,
616
+ },
492
617
  })
493
618
  .afterClosed()
494
619
  .pipe(takeUntil(this._destroy$))
@@ -496,17 +621,19 @@ class FsContentPagesComponent {
496
621
  this.listComponent.reload();
497
622
  });
498
623
  }
624
+ openLayout(contentLayout) {
625
+ return this._dialog.open(ContentLayoutComponent, {
626
+ data: {
627
+ contentLayout,
628
+ },
629
+ })
630
+ .afterClosed()
631
+ .pipe(filter((_contentLayout) => !!_contentLayout), takeUntil(this._destroy$));
632
+ }
499
633
  ngOnDestroy() {
500
634
  this._destroy$.next(null);
501
635
  this._destroy$.complete();
502
636
  }
503
- openContentPage(contentPage) {
504
- return this._dialog.open(ContentPageComponent, {
505
- data: { contentPage },
506
- })
507
- .afterClosed()
508
- .pipe(takeUntil(this._destroy$));
509
- }
510
637
  _initListConfig() {
511
638
  this.listConfig = {
512
639
  filters: [
@@ -520,12 +647,8 @@ class FsContentPagesComponent {
520
647
  {
521
648
  label: 'Create',
522
649
  click: () => {
523
- this.openContentPage({
524
- type: PageType.StandardPage,
525
- })
526
- .pipe(filter((contentPage) => !!contentPage))
527
- .subscribe((contentPage) => {
528
- this.openEditor(contentPage);
650
+ this.openLayout({})
651
+ .subscribe(() => {
529
652
  this.listComponent.reload();
530
653
  });
531
654
  },
@@ -534,7 +657,7 @@ class FsContentPagesComponent {
534
657
  rowActions: [
535
658
  {
536
659
  click: (data) => {
537
- return this._config.deleteContentPage(data);
660
+ return this._config.deleteContentLayout(data);
538
661
  },
539
662
  remove: {
540
663
  title: 'Confirm',
@@ -545,13 +668,9 @@ class FsContentPagesComponent {
545
668
  },
546
669
  ],
547
670
  fetch: (query) => {
548
- query = {
549
- contentLayouts: true,
550
- ...query,
551
- };
552
- return this._config.loadContentPages(query)
671
+ return this._config.loadContentLayouts(query)
553
672
  .pipe(map((response) => {
554
- return { data: response.contentPages, paging: response.paging };
673
+ return { data: response.contentLayouts, paging: response.paging };
555
674
  }));
556
675
  },
557
676
  restore: {
@@ -560,67 +679,73 @@ class FsContentPagesComponent {
560
679
  menuLabel: 'Restore',
561
680
  reload: true,
562
681
  click: (row) => {
563
- return this._config.saveContentPage({ id: row.id, state: 'active' });
682
+ return this._config.saveContentLayout({ id: row.id, state: 'active' });
564
683
  },
565
684
  },
566
685
  };
567
686
  }
568
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
569
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentPagesComponent, isStandalone: true, selector: "fs-content-pages", inputs: { htmlEditorConfig: "htmlEditorConfig" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
687
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
688
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentLayoutsComponent, isStandalone: true, selector: "fs-content-layouts", viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
570
689
  }
571
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, decorators: [{
690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, decorators: [{
572
691
  type: Component,
573
- args: [{ selector: 'fs-content-pages', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
692
+ args: [{ selector: 'fs-content-layouts', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
574
693
  FsListModule,
575
694
  NgTemplateOutlet,
576
695
  FsDateModule,
577
- ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"] }]
578
- }], propDecorators: { htmlEditorConfig: [{
579
- type: Input
580
- }], listComponent: [{
696
+ ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n" }]
697
+ }], propDecorators: { listComponent: [{
581
698
  type: ViewChild,
582
699
  args: [FsListComponent]
583
700
  }] } });
584
701
 
585
- class FsContentPagesModule {
702
+ class FsContentLayoutsModule {
586
703
  static forRoot() {
587
704
  return {
588
- ngModule: FsContentPagesModule,
705
+ ngModule: FsContentLayoutsModule,
589
706
  };
590
707
  }
591
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
592
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
593
- ContentPageComponent,
594
- ContentPageEditorComponent], exports: [FsContentPagesComponent] });
595
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
596
- ContentPageComponent,
597
- ContentPageEditorComponent] });
708
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
709
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, imports: [FsContentLayoutsComponent,
710
+ ContentLayoutComponent,
711
+ ContentLayoutEditorComponent], exports: [FsContentLayoutsComponent] });
712
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, imports: [FsContentLayoutsComponent,
713
+ ContentLayoutComponent,
714
+ ContentLayoutEditorComponent] });
598
715
  }
599
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, decorators: [{
716
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsModule, decorators: [{
600
717
  type: NgModule,
601
718
  args: [{
602
719
  imports: [
603
- FsContentPagesComponent,
604
- ContentPageComponent,
605
- ContentPageEditorComponent,
720
+ FsContentLayoutsComponent,
721
+ ContentLayoutComponent,
722
+ ContentLayoutEditorComponent,
606
723
  ],
607
724
  exports: [
608
- FsContentPagesComponent,
725
+ FsContentLayoutsComponent,
609
726
  ],
610
727
  }]
611
728
  }] });
612
729
 
613
- class ContentLayoutComponent {
730
+ const PageTypes = [
731
+ { name: 'Page', value: PageType.StandardPage },
732
+ { name: 'Page (Not Found)', value: PageType.NotFoundPage },
733
+ ];
734
+
735
+ class ContentPageComponent {
614
736
  _config = inject(FS_CONTENT_CONFIG);
615
737
  _data = inject(MAT_DIALOG_DATA);
616
738
  _dialogRef = inject(MatDialogRef);
617
739
  _message = inject(FsMessage);
618
740
  _cdRef = inject(ChangeDetectorRef);
619
741
  textEditors;
620
- contentLayout = null;
742
+ contentPage = null;
743
+ PageTypes = PageTypes;
744
+ contentLayouts;
621
745
  editors = { content: true, styles: true };
622
746
  _destroy$ = new Subject();
623
747
  ngOnInit() {
748
+ this._dialogRef.updateSize('600px');
624
749
  this._fetchData();
625
750
  }
626
751
  ngOnDestroy() {
@@ -628,26 +753,34 @@ class ContentLayoutComponent {
628
753
  this._destroy$.complete();
629
754
  }
630
755
  save = () => {
631
- return this._config.saveContentLayout(this.contentLayout)
632
- .pipe(tap((contentLayout) => {
756
+ return this._config.saveContentPage(this.contentPage)
757
+ .pipe(tap((contentPage) => {
633
758
  this._message.success('Saved Changes');
634
- this._dialogRef.close(contentLayout);
759
+ this._dialogRef.close(contentPage);
635
760
  }));
636
761
  };
637
762
  _fetchData() {
638
- of(this._data.contentLayout)
639
- .pipe(switchMap((contentLayout) => {
640
- return of(contentLayout);
763
+ this._config.loadContentLayouts()
764
+ .subscribe((contentLayouts) => {
765
+ this.contentLayouts = contentLayouts;
766
+ this._cdRef.markForCheck();
767
+ });
768
+ of(this._data.contentPage)
769
+ .pipe(switchMap((contentPage) => {
770
+ return of(contentPage);
641
771
  }), takeUntil(this._destroy$))
642
- .subscribe((contentLayout) => {
643
- this.contentLayout = { ...contentLayout };
772
+ .subscribe((contentPage) => {
773
+ this.contentPage = {
774
+ ...contentPage,
775
+ path: contentPage.path || '/',
776
+ };
644
777
  this._cdRef.markForCheck();
645
778
  });
646
779
  }
647
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
648
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
780
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
781
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentPageComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "textEditors", predicate: FsTextEditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "component", type: i3.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i3.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
649
782
  }
650
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutComponent, decorators: [{
783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageComponent, decorators: [{
651
784
  type: Component,
652
785
  args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
653
786
  FsSkeletonModule,
@@ -659,15 +792,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
659
792
  MatDialogContent,
660
793
  MatFormField,
661
794
  MatLabel,
795
+ MatSelect,
796
+ MatOption,
662
797
  MatInput,
663
798
  MatDialogActions,
664
- ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentLayout\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentLayout.id ? 'Layout' : 'Layout Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Tag</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentLayout.tag\"\n name=\"tag\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
799
+ ], template: "<form fsForm [submit]=\"save\" *fsSkeletonForm=\"contentPage\">\n <fs-dialog>\n <h1 mat-dialog-title>{{contentPage.id ? 'Page' : 'Create Page'}}</h1>\n <div mat-dialog-content>\n <div class=\"fs-column\">\n <mat-form-field>\n <mat-label>Type</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.type\"\n name=\"type\"\n required>\n @for (item of PageTypes; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n @if (contentLayouts) {\n <mat-form-field>\n <mat-label>Layout</mat-label>\n <mat-select\n [(ngModel)]=\"contentPage.contentLayoutId\"\n required\n name=\"contentLayoutId\">\n @for (item of contentLayouts; track item) {\n <mat-option\n [value]=\"item.id\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n <mat-form-field>\n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.name\"\n name=\"name\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Path</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.path\"\n name=\"path\"\n required>\n </mat-form-field>\n <mat-form-field>\n <mat-label>Title</mat-label>\n <input\n matInput\n [(ngModel)]=\"contentPage.title\"\n name=\"title\">\n </mat-form-field>\n </div>\n </div>\n\n <div mat-dialog-actions>\n <fs-form-dialog-actions>\n </fs-form-dialog-actions>\n </div>\n </fs-dialog>\n</form>\n" }]
665
800
  }], propDecorators: { textEditors: [{
666
801
  type: ViewChildren,
667
802
  args: [FsTextEditorComponent]
668
803
  }] } });
669
804
 
670
- class ContentLayoutEditorComponent {
805
+ class ContentPageEditorComponent {
671
806
  _data = inject(MAT_DIALOG_DATA);
672
807
  _dialogRef = inject(MatDialogRef);
673
808
  _message = inject(FsMessage);
@@ -675,26 +810,27 @@ class ContentLayoutEditorComponent {
675
810
  _cdRef = inject(ChangeDetectorRef);
676
811
  _prompt = inject(FsPrompt);
677
812
  editor;
678
- contentLayout;
679
- get isMac() {
680
- return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
681
- }
682
- submitting;
683
- config;
684
- EditorType = EditorType;
813
+ contentPage;
685
814
  focused = null;
815
+ config;
816
+ resizing = false;
686
817
  title;
687
818
  editors = {
688
819
  [EditorType.Html]: true,
689
820
  [EditorType.Scss]: true,
821
+ [EditorType.Js]: false,
690
822
  [EditorType.GlobalScss]: false,
691
823
  };
824
+ get isMac() {
825
+ return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
826
+ }
827
+ submitting;
692
828
  _destroy$ = new Subject();
693
829
  ngOnInit() {
694
830
  this._dialogRef.addPanelClass('fs-content-editor-overlay-pane');
695
831
  this._dialogRef.disableClose = true;
696
832
  this.config = this._data.contentConfig;
697
- this._initContentLayout(this._data.contentLayout);
833
+ this._initContentPage(this._data.contentPage);
698
834
  this._initEscape();
699
835
  }
700
836
  editorToggleChange(event) {
@@ -704,10 +840,10 @@ class ContentLayoutEditorComponent {
704
840
  this._destroy$.next(null);
705
841
  this._destroy$.complete();
706
842
  }
707
- _initContentLayout(contentLayout) {
708
- this.config.loadContentLayout(contentLayout.id)
843
+ _initContentPage(contentPage) {
844
+ this.config.loadContentPage(contentPage.id)
709
845
  .subscribe((data) => {
710
- this.contentLayout = data;
846
+ this.contentPage = data;
711
847
  this._cdRef.markForCheck();
712
848
  });
713
849
  }
@@ -723,6 +859,7 @@ class ContentLayoutEditorComponent {
723
859
  return of(null)
724
860
  .pipe(filter(() => this.focused), switchMap(() => {
725
861
  switch (this.focused) {
862
+ case EditorType.Js:
726
863
  case EditorType.Html:
727
864
  case EditorType.Scss:
728
865
  return this.saveContentPage();
@@ -736,19 +873,21 @@ class ContentLayoutEditorComponent {
736
873
  }), finalize(() => {
737
874
  this.submitting = false;
738
875
  this._cdRef.markForCheck();
739
- }));
876
+ }))
877
+ .pipe(takeUntil(this._destroy$));
740
878
  };
741
879
  saveContentPage() {
742
880
  const names = {
881
+ [EditorType.Js]: 'js',
743
882
  [EditorType.Scss]: 'styles',
744
883
  [EditorType.Html]: 'content',
745
884
  };
746
885
  const data = {
747
- id: this.contentLayout.id,
886
+ id: this.contentPage.id,
748
887
  [names[this.focused]]: this.editor.changes[this.focused],
749
888
  };
750
- return this.config.saveContentLayout({
751
- id: this.contentLayout.id,
889
+ return this.config.saveContentPage({
890
+ id: this.contentPage.id,
752
891
  ...data,
753
892
  })
754
893
  .pipe(tap(() => {
@@ -784,17 +923,17 @@ class ContentLayoutEditorComponent {
784
923
  });
785
924
  }
786
925
  openSettings() {
787
- this._dialog.open(ContentLayoutComponent, {
926
+ this._dialog.open(ContentPageComponent, {
788
927
  data: {
789
- contentLayout: this.contentLayout,
928
+ contentPage: this.contentPage,
790
929
  },
791
930
  })
792
931
  .afterClosed()
793
932
  .pipe(takeUntil(this._destroy$))
794
- .subscribe((contentLayout) => {
795
- this.contentLayout = {
796
- ...this.contentLayout,
797
- ...contentLayout,
933
+ .subscribe((contentPage) => {
934
+ this.contentPage = {
935
+ ...this.contentPage,
936
+ ...contentPage,
798
937
  };
799
938
  this._cdRef.markForCheck();
800
939
  });
@@ -808,10 +947,10 @@ class ContentLayoutEditorComponent {
808
947
  }
809
948
  });
810
949
  }
811
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
812
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentLayoutEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "component", type: MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
950
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
951
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentPageEditorComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "editor", first: true, predicate: EditorComponent, descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-container{border-radius:0;height:100%}::ng-deep .fs-content-editor-overlay-pane .mdc-dialog__container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-surface{height:100%}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content,fs-dialog ::ng-deep .mat-mdc-dialog-content{max-height:none;flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i3.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "directive", type: i4.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i4.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i5$1.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: EditorComponent, selector: "app-editor", inputs: ["showHtml", "showScss", "showJs", "showGlobalScss", "html", "scss", "js", "contentConfig"], outputs: ["changed", "focused", "blured"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
813
952
  }
814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentLayoutEditorComponent, decorators: [{
953
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentPageEditorComponent, decorators: [{
815
954
  type: Component,
816
955
  args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
817
956
  FormsModule,
@@ -819,39 +958,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
819
958
  FsSkeletonModule,
820
959
  FsDialogModule,
821
960
  MatDialogTitle,
822
- MatIconAnchor,
961
+ MatButtonModule,
823
962
  MatIcon,
824
963
  MatButtonToggleGroup,
825
964
  MatButtonToggle,
826
- MatButton,
827
965
  MatTooltip,
966
+ RouterLink,
828
967
  CdkScrollable,
829
968
  MatDialogContent,
830
969
  EditorComponent,
831
- ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentLayout\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Layout Editor\n <div class=\"small\">{{contentLayout.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <!-- <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle> -->\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentLayout.content\"\n [scss]=\"contentLayout.styles\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n\n <!-- <div mat-dialog-actions>\n <button \n mat-button\n color=\"primary\"\n (click)=\"close()\"\n type=\"button\"> \n Done \n </button>\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n </div> -->\n </fs-dialog>\n</form>", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container{border-radius:0}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content{max-height:none;flex:1;overflow:hidden}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
970
+ ], template: "<form fsForm [submit]=\"submitted\" [dirtySubmitButton]=\"false\" [confirm]=\"false\">\n <fs-dialog *fsSkeletonForm=\"contentPage\">\n <h1 mat-dialog-title>\n <div class=\"title-container\">\n <div class=\"title\">\n Page Editor\n <div class=\"small\">{{contentPage.name}}</div> \n </div>\n <a\n (click)=\"openSettings()\"\n mat-icon-button>\n <mat-icon>settings</mat-icon>\n </a>\n\n <div class=\"toggles\">\n <mat-button-toggle-group multiple>\n <mat-button-toggle value=\"html\" [checked]=\"editors.html\" (change)=\"editorToggleChange($event)\">HTML</mat-button-toggle>\n <mat-button-toggle value=\"scss\" [checked]=\"editors.scss\" (change)=\"editorToggleChange($event)\">SCSS</mat-button-toggle>\n <mat-button-toggle value=\"js\" [checked]=\"editors.js\" (change)=\"editorToggleChange($event)\">JS</mat-button-toggle>\n <mat-button-toggle value=\"globalScss\" [checked]=\"editors.globalScss\" (change)=\"editorToggleChange($event)\">Global SCSS</mat-button-toggle>\n </mat-button-toggle-group> \n </div>\n\n <div class=\"actions\">\n <button\n #submit\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"!editor?.hasChanges || submitting\"\n [matTooltip]=\"isMac ? 'cmd+s' : 'ctrl+s'\"\n type=\"button\"\n (click)=\"save()\"> \n Save\n </button>\n\n <a \n mat-stroked-button\n target=\"_blank\"\n [routerLink]=\"contentPage.path\"\n type=\"button\"> \n Preview\n </a>\n\n <button \n mat-stroked-button\n (click)=\"close()\"\n type=\"button\"> \n Done\n </button>\n </div>\n </div>\n </h1>\n <div mat-dialog-content>\n <app-editor\n [contentConfig]=\"config\"\n [showHtml]=\"editors.html\"\n [showJs]=\"editors.js\"\n [showScss]=\"editors.scss\"\n [showGlobalScss]=\"editors.globalScss\"\n [html]=\"contentPage.content\"\n [scss]=\"contentPage.styles\"\n [js]=\"contentPage.js\"\n (focused)=\"editorFocused($event)\">\n </app-editor>\n </div>\n </fs-dialog>\n</form>\n", styles: ["::ng-deep .fs-content-editor-overlay-pane .mat-dialog-container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-container{border-radius:0;height:100%}::ng-deep .fs-content-editor-overlay-pane .mdc-dialog__container,::ng-deep .fs-content-editor-overlay-pane .mat-mdc-dialog-surface{height:100%}form{height:100%}fs-dialog{display:flex;height:100%;flex-direction:column}fs-dialog ::ng-deep .mat-dialog-content,fs-dialog ::ng-deep .mat-mdc-dialog-content{max-height:none;flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}fs-dialog ::ng-deep .mat-button-toggle-label-content{line-height:36px}h1 .toggles{display:flex;justify-content:flex-end;justify-self:baseline;font-size:13px}h1 .actions{margin-left:30px}h1 .actions .mdc-button{margin-left:5px}.title-container{display:flex;align-items:center}.title-container .title{flex:1}.title-container .title .small{line-height:normal}\n"] }]
832
971
  }], propDecorators: { editor: [{
833
972
  type: ViewChild,
834
973
  args: [EditorComponent]
835
974
  }] } });
836
975
 
837
- class FsContentLayoutsComponent {
976
+ class FsContentPagesComponent {
838
977
  _config = inject(FS_CONTENT_CONFIG);
839
978
  _dialog = inject(MatDialog);
979
+ htmlEditorConfig;
840
980
  listComponent;
841
981
  listConfig;
982
+ pageTypes = index(PageTypes, 'value', 'name');
842
983
  _destroy$ = new Subject();
843
984
  ngOnInit() {
844
985
  this._initListConfig();
845
986
  }
846
- openEditor(contentLayout) {
847
- this._dialog.open(ContentLayoutEditorComponent, {
848
- maxWidth: '100vw',
849
- width: '100%',
850
- height: '100%',
987
+ openEditor(contentPage) {
988
+ this._dialog.open(ContentPageEditorComponent, {
851
989
  data: {
852
- contentLayout,
990
+ contentPage,
991
+ config: this._config,
853
992
  contentConfig: this._config,
854
993
  },
994
+ maxWidth: '100vw',
995
+ width: '100%',
996
+ height: '100%',
997
+ autoFocus: false,
855
998
  })
856
999
  .afterClosed()
857
1000
  .pipe(takeUntil(this._destroy$))
@@ -859,19 +1002,17 @@ class FsContentLayoutsComponent {
859
1002
  this.listComponent.reload();
860
1003
  });
861
1004
  }
862
- openLayout(contentLayout) {
863
- return this._dialog.open(ContentLayoutComponent, {
864
- data: {
865
- contentLayout,
866
- },
867
- })
868
- .afterClosed()
869
- .pipe(filter((_contentLayout) => !!_contentLayout), takeUntil(this._destroy$));
870
- }
871
1005
  ngOnDestroy() {
872
1006
  this._destroy$.next(null);
873
1007
  this._destroy$.complete();
874
1008
  }
1009
+ openContentPage(contentPage) {
1010
+ return this._dialog.open(ContentPageComponent, {
1011
+ data: { contentPage },
1012
+ })
1013
+ .afterClosed()
1014
+ .pipe(takeUntil(this._destroy$));
1015
+ }
875
1016
  _initListConfig() {
876
1017
  this.listConfig = {
877
1018
  filters: [
@@ -885,8 +1026,12 @@ class FsContentLayoutsComponent {
885
1026
  {
886
1027
  label: 'Create',
887
1028
  click: () => {
888
- this.openLayout({})
889
- .subscribe(() => {
1029
+ this.openContentPage({
1030
+ type: PageType.StandardPage,
1031
+ })
1032
+ .pipe(filter((contentPage) => !!contentPage))
1033
+ .subscribe((contentPage) => {
1034
+ this.openEditor(contentPage);
890
1035
  this.listComponent.reload();
891
1036
  });
892
1037
  },
@@ -895,7 +1040,7 @@ class FsContentLayoutsComponent {
895
1040
  rowActions: [
896
1041
  {
897
1042
  click: (data) => {
898
- return this._config.deleteContentLayout(data);
1043
+ return this._config.deleteContentPage(data);
899
1044
  },
900
1045
  remove: {
901
1046
  title: 'Confirm',
@@ -906,9 +1051,13 @@ class FsContentLayoutsComponent {
906
1051
  },
907
1052
  ],
908
1053
  fetch: (query) => {
909
- return this._config.loadContentLayouts(query)
1054
+ query = {
1055
+ contentLayouts: true,
1056
+ ...query,
1057
+ };
1058
+ return this._config.loadContentPages(query)
910
1059
  .pipe(map((response) => {
911
- return { data: response.contentLayouts, paging: response.paging };
1060
+ return { data: response.contentPages, paging: response.paging };
912
1061
  }));
913
1062
  },
914
1063
  restore: {
@@ -917,26 +1066,56 @@ class FsContentLayoutsComponent {
917
1066
  menuLabel: 'Restore',
918
1067
  reload: true,
919
1068
  click: (row) => {
920
- return this._config.saveContentLayout({ id: row.id, state: 'active' });
1069
+ return this._config.saveContentPage({ id: row.id, state: 'active' });
921
1070
  },
922
1071
  },
923
1072
  };
924
1073
  }
925
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
926
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentLayoutsComponent, isStandalone: true, selector: "fs-content-layouts", viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1074
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1075
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentPagesComponent, isStandalone: true, selector: "fs-content-pages", inputs: { htmlEditorConfig: "htmlEditorConfig" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i2$2.FsDatePipe, name: "fsDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
927
1076
  }
928
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentLayoutsComponent, decorators: [{
1077
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesComponent, decorators: [{
929
1078
  type: Component,
930
- args: [{ selector: 'fs-content-layouts', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
1079
+ args: [{ selector: 'fs-content-pages', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
931
1080
  FsListModule,
932
1081
  NgTemplateOutlet,
933
1082
  FsDateModule,
934
- ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n" }]
935
- }], propDecorators: { listComponent: [{
1083
+ ], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column name=\"name\" title=\"Name\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a (click)=\"openEditor(row)\">\n <ng-container [ngTemplateOutlet]=\"name\"></ng-container>\n </a>\n } @else {\n {{row.name}}\n }\n <ng-template #name>{{row.name}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"path\" title=\"Path\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n @if (row.state !== 'deleted') {\n <a [href]=\"'/' + row.path\" target=\"_black\">\n <ng-container [ngTemplateOutlet]=\"path\"></ng-container>\n </a>\n } @else {\n /{{row.path}}\n }\n <ng-template #path>/{{row.path}}</ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"layout\" title=\"Layout\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.contentLayout?.name}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"type\" title=\"Type\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{pageTypes[row.type]}}\n </ng-template>\n </fs-list-column>\n <fs-list-column name=\"modify_date\" title=\"Modified\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.modifyDate | fsDate: 'date-time-yearless'}}\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [":host ::ng-deep .modified,:host ::ng-deep .name{width:1%;white-space:nowrap}:host ::ng-deep .preview-content img{display:none}.preview-content{position:relative;max-height:100px;max-width:100%;overflow:hidden;-webkit-mask-image:-webkit-gradient(linear,left 60%,left bottom,from(rgb(0,0,0)),to(rgba(0,0,0,0)))}\n"] }]
1084
+ }], propDecorators: { htmlEditorConfig: [{
1085
+ type: Input
1086
+ }], listComponent: [{
936
1087
  type: ViewChild,
937
1088
  args: [FsListComponent]
938
1089
  }] } });
939
1090
 
1091
+ class FsContentPagesModule {
1092
+ static forRoot() {
1093
+ return {
1094
+ ngModule: FsContentPagesModule,
1095
+ };
1096
+ }
1097
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1098
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
1099
+ ContentPageComponent,
1100
+ ContentPageEditorComponent], exports: [FsContentPagesComponent] });
1101
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, imports: [FsContentPagesComponent,
1102
+ ContentPageComponent,
1103
+ ContentPageEditorComponent] });
1104
+ }
1105
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentPagesModule, decorators: [{
1106
+ type: NgModule,
1107
+ args: [{
1108
+ imports: [
1109
+ FsContentPagesComponent,
1110
+ ContentPageComponent,
1111
+ ContentPageEditorComponent,
1112
+ ],
1113
+ exports: [
1114
+ FsContentPagesComponent,
1115
+ ],
1116
+ }]
1117
+ }] });
1118
+
940
1119
  class ContentStyleComponent {
941
1120
  _config = inject(FS_CONTENT_CONFIG);
942
1121
  _message = inject(FsMessage);
@@ -975,7 +1154,7 @@ class ContentStyleComponent {
975
1154
  })).subscribe();
976
1155
  }
977
1156
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentStyleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
978
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentStyleComponent, isStandalone: true, selector: "fs-content-style", inputs: { height: "height" }, viewQueries: [{ propertyName: "textEditors", first: true, predicate: FsTextEditorComponent, descendants: true }, { propertyName: "form", first: true, predicate: FsFormDirective, descendants: true }], ngImport: i0, template: "<ng-container *fsSkeletonForm=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"contentStyle\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"save()\"\n [config]=\"styleConfig\">\n </fs-text-editor> \n</ng-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2$1.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5$1.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1157
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ContentStyleComponent, isStandalone: true, selector: "fs-content-style", inputs: { height: "height" }, viewQueries: [{ propertyName: "textEditors", first: true, predicate: FsTextEditorComponent, descendants: true }, { propertyName: "form", first: true, predicate: FsFormDirective, descendants: true }], ngImport: i0, template: "<ng-container *fsSkeletonForm=\"contentStyle\">\n <fs-text-editor \n [(ngModel)]=\"contentStyle.scss\" \n name=\"contentStyle\"\n [fsModelChangeOptions]=\"{ debounce: 300 }\"\n (fsModelChange)=\"save()\"\n [config]=\"styleConfig\">\n </fs-text-editor> \n</ng-container>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1$1.FsSkeletonFormDirective, selector: "[fsSkeletonForm]", inputs: ["fsSkeletonForm", "fsSkeletonFormLines"] }, { kind: "ngmodule", type: FsTextEditorModule }, { kind: "component", type: i2.FsTextEditorComponent, selector: "fs-text-editor", inputs: ["config", "scrollable"], outputs: ["ready", "blur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsCommonModule }, { kind: "directive", type: i5.FsModelChangeDirective, selector: "[fsModelChange]", inputs: ["fsModelChangeOptions"], outputs: ["fsModelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
979
1158
  }
980
1159
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentStyleComponent, decorators: [{
981
1160
  type: Component,
@@ -995,138 +1174,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
995
1174
  type: Input
996
1175
  }] } });
997
1176
 
998
- class ContentRendererComponent {
999
- _sanitizer = inject(DomSanitizer);
1000
- _router = inject(Router);
1001
- _el = inject(ElementRef);
1002
- _htmlRenderer = inject(HtmlRenderer);
1003
- script;
1004
- contentPage;
1005
- content;
1006
- _destroy$ = new Subject();
1007
- ngOnChanges(changes) {
1008
- if (changes.contentPage.currentValue) {
1009
- this._htmlRenderer.addStyle(this.contentPage.styles, { id: 'contentPageStyles' });
1010
- this.content = this._sanitizer.bypassSecurityTrustHtml(this.contentPage.content);
1011
- }
1012
- }
1013
- ngAfterViewChecked() {
1014
- this.registerHrefs();
1015
- if (this.contentPage.js) {
1016
- const script = document.createElement('script');
1017
- script.text = this.contentPage.js;
1018
- this.script.nativeElement.after(script);
1019
- }
1020
- }
1021
- registerHrefs() {
1022
- Array.from(this.el.querySelectorAll('a[href]'))
1023
- .filter((el) => {
1024
- return el.getAttribute('href').match(/^\//);
1025
- })
1026
- .forEach((el) => {
1027
- el.addEventListener('click', (event) => {
1028
- if (!event.shiftKey && !event.ctrlKey) {
1029
- event.preventDefault();
1030
- const href = el.getAttribute('href');
1031
- this._router.navigateByUrl(href);
1032
- }
1033
- });
1034
- });
1035
- }
1036
- get el() {
1037
- return this._el.nativeElement;
1038
- }
1039
- ngOnDestroy() {
1040
- this.removeStyles();
1041
- this._destroy$.next(null);
1042
- this._destroy$.complete();
1043
- }
1044
- removeStyles() {
1045
- const el = document.querySelector('#contentPageStyles');
1046
- if (el) {
1047
- el.remove();
1048
- }
1049
- }
1050
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1051
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ContentRendererComponent, isStandalone: true, selector: "fs-content-renderer", inputs: { contentPage: "contentPage" }, viewQueries: [{ propertyName: "script", first: true, predicate: ["script"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1052
- }
1053
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ContentRendererComponent, decorators: [{
1054
- type: Component,
1055
- args: [{ selector: 'fs-content-renderer', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (content) {\n <div [innerHTML]=\"content\"></div>\n}\n<span #script></span>" }]
1056
- }], propDecorators: { script: [{
1057
- type: ViewChild,
1058
- args: ['script', { read: ElementRef }]
1059
- }], contentPage: [{
1060
- type: Input
1061
- }] } });
1062
-
1063
- class FsContentComponent {
1064
- _config = inject(FS_CONTENT_CONFIG);
1065
- _title = inject(Title);
1066
- _cdRef = inject(ChangeDetectorRef);
1067
- _router = inject(Router);
1068
- _el = inject(ElementRef);
1069
- _htmlRenderer = inject(HtmlRenderer);
1070
- contentPage;
1071
- _destroy$ = new Subject();
1072
- ngOnInit() {
1073
- this._initContent();
1074
- this._initStyles();
1075
- }
1076
- get el() {
1077
- return this._el.nativeElement;
1078
- }
1079
- ngOnDestroy() {
1080
- this._destroy$.next(null);
1081
- this._destroy$.complete();
1082
- this._title.setTitle('');
1083
- document.querySelector('#content-style')?.remove();
1084
- }
1085
- _initStyles() {
1086
- if (this._config.loadContentStyleCss) {
1087
- this._config.loadContentStyleCss()
1088
- .subscribe((styles) => {
1089
- this._htmlRenderer.addStyle(styles, { id: 'content-style' });
1090
- });
1091
- }
1092
- }
1093
- _initContent() {
1094
- this._loadContent();
1095
- this._router.events
1096
- .pipe(filter((e) => e instanceof NavigationEnd), takeUntil(this._destroy$))
1097
- .subscribe((e) => {
1098
- this._loadContent();
1099
- });
1100
- }
1101
- _loadContent() {
1102
- const path = window.location.pathname;
1103
- this._config.loadContent(path)
1104
- .subscribe((contentPage) => {
1105
- if (contentPage.title) {
1106
- this._title.setTitle(contentPage.title);
1107
- let ogTitleEl = document.querySelector('head meta[property="og:title"]');
1108
- if (!ogTitleEl) {
1109
- ogTitleEl = document.createElement('meta');
1110
- ogTitleEl.setAttribute('property', 'og:title');
1111
- document.getElementsByTagName('head')[0].appendChild(ogTitleEl);
1112
- }
1113
- ogTitleEl.setAttribute('content', contentPage.title);
1114
- }
1115
- this.contentPage = contentPage;
1116
- this._cdRef.markForCheck();
1117
- });
1118
- }
1119
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1120
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: FsContentComponent, isStandalone: true, selector: "fs-content", ngImport: i0, template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}", styles: [""], dependencies: [{ kind: "component", type: ContentRendererComponent, selector: "fs-content-renderer", inputs: ["contentPage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1121
- }
1122
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsContentComponent, decorators: [{
1123
- type: Component,
1124
- args: [{ selector: 'fs-content', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [ContentRendererComponent], template: "@if (contentPage) {\n <fs-content-renderer [contentPage]=\"contentPage\"></fs-content-renderer>\n}" }]
1125
- }] });
1126
-
1127
1177
  /**
1128
1178
  * Generated bundle index. Do not edit.
1129
1179
  */
1130
1180
 
1131
- export { ContentStyleComponent, FS_CONTENT_CONFIG, FsContentComponent, FsContentLayoutsComponent, FsContentPagesComponent, FsContentPagesModule };
1181
+ export { ContentStyleComponent, FS_CONTENT_CONFIG, FsContentComponent, FsContentLayoutsComponent, FsContentLayoutsModule, FsContentModule, FsContentPagesComponent, FsContentPagesModule };
1132
1182
  //# sourceMappingURL=firestitch-content.mjs.map