@dotcms/angular 0.0.1-beta.3 → 0.0.1-beta.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dotcms-angular.d.ts.map +1 -1
  2. package/esm2022/dotcms-angular.mjs +2 -2
  3. package/esm2022/lib/deprecated/components/dot-editable-text/dot-editable-text.component.mjs +229 -0
  4. package/esm2022/lib/deprecated/components/dot-editable-text/utils.mjs +43 -0
  5. package/esm2022/lib/deprecated/components/no-component/no-component.component.mjs +32 -0
  6. package/esm2022/lib/deprecated/deprecated-api.mjs +11 -0
  7. package/esm2022/lib/{layout → deprecated/layout}/column/column.component.mjs +1 -1
  8. package/esm2022/lib/deprecated/layout/container/container.component.mjs +126 -0
  9. package/esm2022/lib/deprecated/layout/contentlet/contentlet.component.mjs +120 -0
  10. package/esm2022/lib/deprecated/layout/dotcms-layout/dotcms-layout.component.mjs +106 -0
  11. package/esm2022/lib/{layout → deprecated/layout}/row/row.component.mjs +1 -1
  12. package/esm2022/lib/deprecated/models/dotcms.model.mjs +3 -0
  13. package/esm2022/lib/deprecated/models/index.mjs +3 -0
  14. package/esm2022/lib/deprecated/services/dotcms-context/page-context.service.mjs +79 -0
  15. package/esm2022/lib/deprecated/utils/image_loader.mjs +74 -0
  16. package/esm2022/lib/deprecated/utils/index.mjs +84 -0
  17. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/code.component.mjs +49 -0
  18. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/contentlet.component.mjs +53 -0
  19. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/image.component.mjs +25 -0
  20. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/list.component.mjs +66 -0
  21. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/table.component.mjs +97 -0
  22. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/text.component.mjs +231 -0
  23. package/esm2022/next/components/dotcms-block-editor-renderer/blocks/video.component.mjs +48 -0
  24. package/esm2022/next/components/dotcms-block-editor-renderer/dotcms-block-editor-renderer.component.mjs +46 -0
  25. package/esm2022/next/components/dotcms-block-editor-renderer/item/dotcms-block-editor-item.component.mjs +43 -0
  26. package/esm2022/next/components/dotcms-editable-text/dotcms-editable-text.component.mjs +246 -0
  27. package/esm2022/next/components/dotcms-editable-text/utils.mjs +20 -0
  28. package/esm2022/next/components/dotcms-layout-body/components/column/column.component.mjs +45 -0
  29. package/esm2022/next/components/dotcms-layout-body/components/container/components/container-not-found/container-not-found.component.mjs +52 -0
  30. package/esm2022/next/components/dotcms-layout-body/components/container/components/empty-container/empty-container.component.mjs +43 -0
  31. package/esm2022/next/components/dotcms-layout-body/components/container/container.component.mjs +99 -0
  32. package/esm2022/next/components/dotcms-layout-body/components/contentlet/contentlet.component.mjs +145 -0
  33. package/esm2022/next/components/dotcms-layout-body/components/fallback-component/fallback-component.component.mjs +47 -0
  34. package/esm2022/next/components/dotcms-layout-body/components/page-error-message/page-error-message.component.mjs +55 -0
  35. package/esm2022/next/components/dotcms-layout-body/components/row/row.component.mjs +46 -0
  36. package/esm2022/next/components/dotcms-layout-body/dotcms-layout-body.component.mjs +69 -0
  37. package/esm2022/next/directives/dotcms-show-when/dotcms-show-when.directive.mjs +49 -0
  38. package/esm2022/next/dotcms-angular-next.mjs +5 -0
  39. package/esm2022/next/models/index.mjs +3 -0
  40. package/esm2022/next/providers/dotcms-image-loader/dotcms-image_loader.mjs +74 -0
  41. package/esm2022/next/public_api.mjs +7 -0
  42. package/esm2022/next/services/dotcms-editable-page.service.mjs +93 -0
  43. package/esm2022/next/store/dotcms.store.mjs +61 -0
  44. package/esm2022/public_api.mjs +2 -0
  45. package/fesm2022/dotcms-angular-next.mjs +1725 -0
  46. package/fesm2022/dotcms-angular-next.mjs.map +1 -0
  47. package/fesm2022/dotcms-angular.mjs +103 -10
  48. package/fesm2022/dotcms-angular.mjs.map +1 -1
  49. package/index.d.ts +6 -5
  50. package/lib/{components → deprecated/components}/dot-editable-text/dot-editable-text.component.d.ts +10 -6
  51. package/lib/deprecated/components/dot-editable-text/dot-editable-text.component.d.ts.map +1 -0
  52. package/lib/deprecated/components/dot-editable-text/utils.d.ts.map +1 -0
  53. package/lib/deprecated/components/no-component/no-component.component.d.ts.map +1 -0
  54. package/lib/deprecated/deprecated-api.d.ts +11 -0
  55. package/lib/deprecated/deprecated-api.d.ts.map +1 -0
  56. package/lib/deprecated/layout/column/column.component.d.ts.map +1 -0
  57. package/lib/deprecated/layout/container/container.component.d.ts.map +1 -0
  58. package/lib/deprecated/layout/contentlet/contentlet.component.d.ts.map +1 -0
  59. package/lib/{layout → deprecated/layout}/dotcms-layout/dotcms-layout.component.d.ts +5 -0
  60. package/lib/deprecated/layout/dotcms-layout/dotcms-layout.component.d.ts.map +1 -0
  61. package/lib/deprecated/layout/row/row.component.d.ts.map +1 -0
  62. package/lib/deprecated/models/dotcms.model.d.ts.map +1 -0
  63. package/lib/deprecated/models/index.d.ts.map +1 -0
  64. package/lib/{services → deprecated/services}/dotcms-context/page-context.service.d.ts +4 -0
  65. package/lib/deprecated/services/dotcms-context/page-context.service.d.ts.map +1 -0
  66. package/lib/deprecated/utils/image_loader.d.ts +21 -0
  67. package/lib/deprecated/utils/image_loader.d.ts.map +1 -0
  68. package/lib/deprecated/utils/index.d.ts.map +1 -0
  69. package/next/components/dotcms-block-editor-renderer/blocks/code.component.d.ts +10 -0
  70. package/next/components/dotcms-block-editor-renderer/blocks/code.component.d.ts.map +1 -0
  71. package/next/components/dotcms-block-editor-renderer/blocks/contentlet.component.d.ts +25 -0
  72. package/next/components/dotcms-block-editor-renderer/blocks/contentlet.component.d.ts.map +1 -0
  73. package/next/components/dotcms-block-editor-renderer/blocks/image.component.d.ts +9 -0
  74. package/next/components/dotcms-block-editor-renderer/blocks/image.component.d.ts.map +1 -0
  75. package/next/components/dotcms-block-editor-renderer/blocks/list.component.d.ts +14 -0
  76. package/next/components/dotcms-block-editor-renderer/blocks/list.component.d.ts.map +1 -0
  77. package/next/components/dotcms-block-editor-renderer/blocks/table.component.d.ts +10 -0
  78. package/next/components/dotcms-block-editor-renderer/blocks/table.component.d.ts.map +1 -0
  79. package/next/components/dotcms-block-editor-renderer/blocks/text.component.d.ts +27 -0
  80. package/next/components/dotcms-block-editor-renderer/blocks/text.component.d.ts.map +1 -0
  81. package/next/components/dotcms-block-editor-renderer/blocks/video.component.d.ts +10 -0
  82. package/next/components/dotcms-block-editor-renderer/blocks/video.component.d.ts.map +1 -0
  83. package/next/components/dotcms-block-editor-renderer/dotcms-block-editor-renderer.component.d.ts +37 -0
  84. package/next/components/dotcms-block-editor-renderer/dotcms-block-editor-renderer.component.d.ts.map +1 -0
  85. package/next/components/dotcms-block-editor-renderer/item/dotcms-block-editor-item.component.d.ts +12 -0
  86. package/next/components/dotcms-block-editor-renderer/item/dotcms-block-editor-item.component.d.ts.map +1 -0
  87. package/next/components/dotcms-editable-text/dotcms-editable-text.component.d.ts +129 -0
  88. package/next/components/dotcms-editable-text/dotcms-editable-text.component.d.ts.map +1 -0
  89. package/next/components/dotcms-editable-text/utils.d.ts +7 -0
  90. package/next/components/dotcms-editable-text/utils.d.ts.map +1 -0
  91. package/next/components/dotcms-layout-body/components/column/column.component.d.ts +21 -0
  92. package/next/components/dotcms-layout-body/components/column/column.component.d.ts.map +1 -0
  93. package/next/components/dotcms-layout-body/components/container/components/container-not-found/container-not-found.component.d.ts +27 -0
  94. package/next/components/dotcms-layout-body/components/container/components/container-not-found/container-not-found.component.d.ts.map +1 -0
  95. package/next/components/dotcms-layout-body/components/container/components/empty-container/empty-container.component.d.ts +23 -0
  96. package/next/components/dotcms-layout-body/components/container/components/empty-container/empty-container.component.d.ts.map +1 -0
  97. package/next/components/dotcms-layout-body/components/container/container.component.d.ts +32 -0
  98. package/next/components/dotcms-layout-body/components/container/container.component.d.ts.map +1 -0
  99. package/next/components/dotcms-layout-body/components/contentlet/contentlet.component.d.ts +48 -0
  100. package/next/components/dotcms-layout-body/components/contentlet/contentlet.component.d.ts.map +1 -0
  101. package/next/components/dotcms-layout-body/components/fallback-component/fallback-component.component.d.ts +16 -0
  102. package/next/components/dotcms-layout-body/components/fallback-component/fallback-component.component.d.ts.map +1 -0
  103. package/next/components/dotcms-layout-body/components/page-error-message/page-error-message.component.d.ts +13 -0
  104. package/next/components/dotcms-layout-body/components/page-error-message/page-error-message.component.d.ts.map +1 -0
  105. package/next/components/dotcms-layout-body/components/row/row.component.d.ts +22 -0
  106. package/next/components/dotcms-layout-body/components/row/row.component.d.ts.map +1 -0
  107. package/next/components/dotcms-layout-body/dotcms-layout-body.component.d.ts +30 -0
  108. package/next/components/dotcms-layout-body/dotcms-layout-body.component.d.ts.map +1 -0
  109. package/next/directives/dotcms-show-when/dotcms-show-when.directive.d.ts +21 -0
  110. package/next/directives/dotcms-show-when/dotcms-show-when.directive.d.ts.map +1 -0
  111. package/next/dotcms-angular-next.d.ts.map +1 -0
  112. package/next/index.d.ts +6 -0
  113. package/next/models/index.d.ts +39 -0
  114. package/next/models/index.d.ts.map +1 -0
  115. package/next/providers/dotcms-image-loader/dotcms-image_loader.d.ts +21 -0
  116. package/next/providers/dotcms-image-loader/dotcms-image_loader.d.ts.map +1 -0
  117. package/next/public_api.d.ts +7 -0
  118. package/next/public_api.d.ts.map +1 -0
  119. package/next/services/dotcms-editable-page.service.d.ts +40 -0
  120. package/next/services/dotcms-editable-page.service.d.ts.map +1 -0
  121. package/next/store/dotcms.store.d.ts +36 -0
  122. package/next/store/dotcms.store.d.ts.map +1 -0
  123. package/package.json +9 -2
  124. package/public_api.d.ts +2 -0
  125. package/public_api.d.ts.map +1 -0
  126. package/esm2022/index.mjs +0 -5
  127. package/esm2022/lib/components/dot-editable-text/dot-editable-text.component.mjs +0 -225
  128. package/esm2022/lib/components/dot-editable-text/utils.mjs +0 -43
  129. package/esm2022/lib/components/no-component/no-component.component.mjs +0 -32
  130. package/esm2022/lib/layout/container/container.component.mjs +0 -126
  131. package/esm2022/lib/layout/contentlet/contentlet.component.mjs +0 -120
  132. package/esm2022/lib/layout/dotcms-layout/dotcms-layout.component.mjs +0 -100
  133. package/esm2022/lib/models/dotcms.model.mjs +0 -3
  134. package/esm2022/lib/models/index.mjs +0 -3
  135. package/esm2022/lib/services/dotcms-context/page-context.service.mjs +0 -75
  136. package/esm2022/lib/utils/index.mjs +0 -84
  137. package/index.d.ts.map +0 -1
  138. package/lib/components/dot-editable-text/dot-editable-text.component.d.ts.map +0 -1
  139. package/lib/components/dot-editable-text/utils.d.ts.map +0 -1
  140. package/lib/components/no-component/no-component.component.d.ts.map +0 -1
  141. package/lib/layout/column/column.component.d.ts.map +0 -1
  142. package/lib/layout/container/container.component.d.ts.map +0 -1
  143. package/lib/layout/contentlet/contentlet.component.d.ts.map +0 -1
  144. package/lib/layout/dotcms-layout/dotcms-layout.component.d.ts.map +0 -1
  145. package/lib/layout/row/row.component.d.ts.map +0 -1
  146. package/lib/models/dotcms.model.d.ts.map +0 -1
  147. package/lib/models/index.d.ts.map +0 -1
  148. package/lib/services/dotcms-context/page-context.service.d.ts.map +0 -1
  149. package/lib/utils/index.d.ts.map +0 -1
  150. /package/lib/{components → deprecated/components}/dot-editable-text/utils.d.ts +0 -0
  151. /package/lib/{components → deprecated/components}/no-component/no-component.component.d.ts +0 -0
  152. /package/lib/{layout → deprecated/layout}/column/column.component.d.ts +0 -0
  153. /package/lib/{layout → deprecated/layout}/container/container.component.d.ts +0 -0
  154. /package/lib/{layout → deprecated/layout}/contentlet/contentlet.component.d.ts +0 -0
  155. /package/lib/{layout → deprecated/layout}/row/row.component.d.ts +0 -0
  156. /package/lib/{models → deprecated/models}/dotcms.model.d.ts +0 -0
  157. /package/lib/{models → deprecated/models}/index.d.ts +0 -0
  158. /package/lib/{utils → deprecated/utils}/index.d.ts +0 -0
@@ -0,0 +1,1725 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ViewContainerRef, TemplateRef, Input, Directive, Renderer2, ElementRef, SecurityContext, HostListener, ViewChild, Component, ChangeDetectionStrategy, computed, signal, Injectable, HostBinding } from '@angular/core';
3
+ import { UVE_MODE, DotCMSUVEAction, UVEEventType } from '@dotcms/types';
4
+ import { getUVEState, sendMessageToUVE, initUVE, updateNavigation, createUVESubscription } from '@dotcms/uve';
5
+ import { IMAGE_LOADER, NgComponentOutlet, AsyncPipe, NgTemplateOutlet, NgStyle } from '@angular/common';
6
+ import { EditorComponent, TINYMCE_SCRIPT_SRC } from '@tinymce/tinymce-angular';
7
+ import { DomSanitizer } from '@angular/platform-browser';
8
+ import { __DOTCMS_UVE_EVENT__, BlockEditorDefaultBlocks } from '@dotcms/types/internal';
9
+ import { __DEFAULT_TINYMCE_CONFIG__, __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__, __TINYMCE_PATH_ON_DOTCMS__, isValidBlocks, PRODUCTION_MODE, DEVELOPMENT_MODE, EMPTY_CONTAINER_STYLE_ANGULAR, getDotContentletAttributes, CUSTOM_NO_COMPONENT, getDotContainerAttributes, getContainersData, getContentletsInContainer, getColumnPositionClasses, combineClasses } from '@dotcms/uve/internal';
10
+ import { Subject, of } from 'rxjs';
11
+ import { finalize } from 'rxjs/operators';
12
+
13
+ /**
14
+ * Directive to show a template when the UVE is in a specific mode.
15
+ *
16
+ * @example
17
+ * <div *dotCMSShowWhen="UVE_MODE.EDIT">
18
+ * This will be shown when the UVE is in edit mode.
19
+ * </div>
20
+ *
21
+ * @export
22
+ * @class DotCMSShowWhenDirective
23
+ */
24
+ class DotCMSShowWhenDirective {
25
+ #when = UVE_MODE.EDIT;
26
+ #hasView = false;
27
+ set dotCMSShowWhen(value) {
28
+ this.#when = value;
29
+ this.updateViewContainer();
30
+ }
31
+ #viewContainerRef = inject(ViewContainerRef);
32
+ #templateRef = inject(TemplateRef);
33
+ updateViewContainer() {
34
+ const state = getUVEState();
35
+ const shouldShow = state?.mode === this.#when;
36
+ if (shouldShow && !this.#hasView) {
37
+ this.#viewContainerRef.createEmbeddedView(this.#templateRef);
38
+ this.#hasView = true;
39
+ }
40
+ else if (!shouldShow && this.#hasView) {
41
+ this.#viewContainerRef.clear();
42
+ this.#hasView = false;
43
+ }
44
+ }
45
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSShowWhenDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
46
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.3", type: DotCMSShowWhenDirective, isStandalone: true, selector: "[dotCMSShowWhen]", inputs: { dotCMSShowWhen: "dotCMSShowWhen" }, ngImport: i0 }); }
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSShowWhenDirective, decorators: [{
49
+ type: Directive,
50
+ args: [{
51
+ selector: '[dotCMSShowWhen]',
52
+ standalone: true
53
+ }]
54
+ }], propDecorators: { dotCMSShowWhen: [{
55
+ type: Input
56
+ }] } });
57
+
58
+ /**
59
+ * Validates if a given path is a valid URL string
60
+ *
61
+ * @param path - The path to validate
62
+ * @returns boolean indicating if the path is valid
63
+ */
64
+ function isValidPath(path) {
65
+ if (typeof path !== 'string' || path.trim() === '') {
66
+ return false;
67
+ }
68
+ try {
69
+ new URL(path);
70
+ return true;
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ /**
77
+ * Provides a DotCMS image loader configuration for the Angular Image directive
78
+ *
79
+ * @param path - The base URL path to the DotCMS instance, or empty to use current site
80
+ * @returns An array of providers for the IMAGE_LOADER token
81
+ * @throws Error if the provided path is invalid
82
+ * @example
83
+ * ```typescript
84
+ * // In your app.config.ts
85
+ * export const appConfig: ApplicationConfig = {
86
+ * providers: [
87
+ * provideDotCMSImageLoader('https://demo.dotcms.com')
88
+ * // Or use current site:
89
+ * // provideDotCMSImageLoader()
90
+ * ]
91
+ * };
92
+ * ```
93
+ */
94
+ function provideDotCMSImageLoader(path) {
95
+ // If path is provided, validate it
96
+ if (path && !isValidPath(path)) {
97
+ throw new Error(`Image loader has detected an invalid path (\`${path}\`). ` +
98
+ `To fix this, supply either the full URL to the dotCMS site, or leave it empty to use the current site.`);
99
+ }
100
+ return [
101
+ {
102
+ provide: IMAGE_LOADER,
103
+ useValue: (config) => createDotCMSURL(config, path)
104
+ }
105
+ ];
106
+ }
107
+ /**
108
+ * Creates a DotCMS-compatible URL for image loading
109
+ *
110
+ * @param config - The image loader configuration
111
+ * @param path - The base URL path to the DotCMS instance
112
+ * @returns A fully qualified URL for the image
113
+ * @internal
114
+ */
115
+ function createDotCMSURL(config, path) {
116
+ const { loaderParams, src, width } = config;
117
+ const params = loaderParams;
118
+ if (params?.isOutsideSRC) {
119
+ return src;
120
+ }
121
+ // Use empty string as fallback to support using current site
122
+ const dotcmsHost = path ? new URL(path).origin : '';
123
+ const imageSRC = src.includes('/dA/') ? src : `/dA/${src}`;
124
+ const languageId = params?.languageId ?? '1';
125
+ if (width) {
126
+ return `${dotcmsHost}${imageSRC}/${width}w?language_id=${languageId}`;
127
+ }
128
+ return `${dotcmsHost}${imageSRC}?language_id=${languageId}`;
129
+ }
130
+
131
+ const DEFAULT_TINYMCE_CONFIG = {
132
+ ...__DEFAULT_TINYMCE_CONFIG__,
133
+ license_key: 'gpl' // Using self-hosted license key
134
+ };
135
+ const TINYMCE_CONFIG = {
136
+ minimal: {
137
+ ...DEFAULT_TINYMCE_CONFIG,
138
+ ...__BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__.minimal
139
+ },
140
+ full: {
141
+ ...DEFAULT_TINYMCE_CONFIG,
142
+ ...__BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__.full
143
+ },
144
+ plain: {
145
+ ...DEFAULT_TINYMCE_CONFIG,
146
+ ...__BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__.plain
147
+ }
148
+ };
149
+
150
+ /**
151
+ * Dot editable text component.
152
+ * This component is responsible to render a text field that can be edited inline.
153
+ *
154
+ * @export
155
+ * @class DotCMSEditableTextComponent
156
+ * @implements {OnInit}
157
+ * @implements {OnChanges}
158
+ */
159
+ class DotCMSEditableTextComponent {
160
+ constructor() {
161
+ /**
162
+ * Represents the mode of the editor which can be `plain`, `minimal`, or `full`
163
+ *
164
+ * @type {DOT_EDITABLE_TEXT_MODE}
165
+ * @memberof DotCMSEditableTextComponent
166
+ */
167
+ this.mode = 'plain';
168
+ /**
169
+ * Represents the format of the editor which can be `text` or `html`
170
+ *
171
+ * @type {DOT_EDITABLE_TEXT_FORMAT}
172
+ * @memberof DotCMSEditableTextComponent
173
+ */
174
+ this.format = 'text';
175
+ /**
176
+ * Represents the field name of the `contentlet` that can be edited
177
+ *
178
+ * @memberof DotCMSEditableTextComponent
179
+ */
180
+ this.fieldName = '';
181
+ /**
182
+ * Represents the content of the `contentlet` that can be edited
183
+ *
184
+ * @protected
185
+ * @memberof DotCMSEditableTextComponent
186
+ */
187
+ this.content = '';
188
+ this.#NotDotCMSHostMessage = 'The `dotCMSHost` parameter is not defined. Check that the UVE is sending the correct parameters.';
189
+ this.#sanitizer = inject(DomSanitizer);
190
+ this.#renderer = inject(Renderer2);
191
+ this.#elementRef = inject(ElementRef);
192
+ }
193
+ #NotDotCMSHostMessage;
194
+ #sanitizer;
195
+ #renderer;
196
+ #elementRef;
197
+ /**
198
+ * The TinyMCE editor
199
+ *
200
+ * @readonly
201
+ * @memberof DotCMSEditableTextComponent
202
+ */
203
+ get editor() {
204
+ return this.editorComponent?.editor;
205
+ }
206
+ /**
207
+ * Represents if the component is inside the editor
208
+ *
209
+ * @protected
210
+ * @type {boolean}
211
+ * @memberof DotCMSEditableTextComponent
212
+ */
213
+ get isEditMode() {
214
+ const { mode, dotCMSHost } = getUVEState() || {};
215
+ return mode === UVE_MODE.EDIT && dotCMSHost;
216
+ }
217
+ /**
218
+ * Returns the number of pages the contentlet is on
219
+ *
220
+ * @readonly
221
+ * @memberof DotCMSEditableTextComponent
222
+ */
223
+ get onNumberOfPages() {
224
+ return this.contentlet['onNumberOfPages'] || 1;
225
+ }
226
+ /**
227
+ * Handle copy contentlet inline editing success event
228
+ *
229
+ * @param {MessageEvent} { data }
230
+ * @return {*}
231
+ * @memberof DotCMSEditableTextComponent
232
+ */
233
+ onMessage({ data }) {
234
+ const { name, payload } = data;
235
+ if (name !== __DOTCMS_UVE_EVENT__.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS) {
236
+ return;
237
+ }
238
+ const { oldInode, inode } = payload;
239
+ const currentInode = this.contentlet.inode;
240
+ if (currentInode === oldInode || currentInode === inode) {
241
+ this.editorComponent.editor.focus();
242
+ return;
243
+ }
244
+ }
245
+ ngOnInit() {
246
+ const { dotCMSHost } = getUVEState() || {};
247
+ if (!this.isEditMode) {
248
+ this.innerHTMLToElement();
249
+ if (!dotCMSHost) {
250
+ console.warn(this.#NotDotCMSHostMessage);
251
+ }
252
+ return;
253
+ }
254
+ this.init = {
255
+ ...TINYMCE_CONFIG[this.mode],
256
+ base_url: `${dotCMSHost}/ext/tinymcev7`
257
+ };
258
+ }
259
+ ngOnChanges() {
260
+ this.content = this.contentlet[this.fieldName] || '';
261
+ if (this.editor) {
262
+ this.editor.setContent(this.content, { format: this.format });
263
+ }
264
+ }
265
+ /**
266
+ * Handle mouse down event
267
+ *
268
+ * @param {EventObj<MouseEvent>} { event }
269
+ * @return {*}
270
+ * @memberof DotCMSEditableTextComponent
271
+ */
272
+ onMouseDown({ event }) {
273
+ if (Number(this.onNumberOfPages) <= 1 || this.editorComponent.editor.hasFocus()) {
274
+ return;
275
+ }
276
+ const { inode, languageId: language } = this.contentlet;
277
+ event.stopPropagation();
278
+ event.preventDefault();
279
+ try {
280
+ sendMessageToUVE({
281
+ action: DotCMSUVEAction.COPY_CONTENTLET_INLINE_EDITING,
282
+ payload: {
283
+ dataset: {
284
+ inode,
285
+ language,
286
+ fieldName: this.fieldName
287
+ }
288
+ }
289
+ });
290
+ }
291
+ catch (error) {
292
+ console.error('Failed to post message to editor:', error);
293
+ }
294
+ }
295
+ /**
296
+ * Handle focus out event
297
+ *
298
+ * @return {*}
299
+ * @memberof DotCMSEditableTextComponent
300
+ */
301
+ onFocusOut() {
302
+ const content = this.editor.getContent({ format: this.format });
303
+ if (!this.editor.isDirty() || !this.didContentChange(content)) {
304
+ return;
305
+ }
306
+ const { inode, languageId: langId } = this.contentlet;
307
+ try {
308
+ sendMessageToUVE({
309
+ action: DotCMSUVEAction.UPDATE_CONTENTLET_INLINE_EDITING,
310
+ payload: {
311
+ content,
312
+ dataset: {
313
+ inode,
314
+ langId,
315
+ fieldName: this.fieldName
316
+ }
317
+ }
318
+ });
319
+ }
320
+ catch (error) {
321
+ console.error('Failed to post message to editor:', error);
322
+ }
323
+ }
324
+ /**
325
+ * inner HTML to element
326
+ *
327
+ * @private
328
+ * @param {string} editedContent
329
+ * @return {*}
330
+ * @memberof DotCMSEditableTextComponent
331
+ */
332
+ innerHTMLToElement() {
333
+ const element = this.#elementRef.nativeElement;
334
+ const safeHtml = this.#sanitizer.bypassSecurityTrustHtml(this.content);
335
+ const content = this.#sanitizer.sanitize(SecurityContext.HTML, safeHtml) || '';
336
+ this.#renderer.setProperty(element, 'innerHTML', content);
337
+ }
338
+ /**
339
+ * Check if the content has changed
340
+ *
341
+ * @private
342
+ * @param {string} editedContent
343
+ * @return {*}
344
+ * @memberof DotCMSEditableTextComponent
345
+ */
346
+ didContentChange(editedContent) {
347
+ return this.content !== editedContent;
348
+ }
349
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSEditableTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
350
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotCMSEditableTextComponent, isStandalone: true, selector: "dotcms-editable-text", inputs: { mode: "mode", format: "format", contentlet: "contentlet", fieldName: "fieldName" }, host: { listeners: { "window:message": "onMessage($event)" } }, providers: [
351
+ {
352
+ provide: TINYMCE_SCRIPT_SRC,
353
+ useFactory: () => {
354
+ const { dotCMSHost } = getUVEState() || {};
355
+ return `${dotCMSHost || ''}${__TINYMCE_PATH_ON_DOTCMS__}`;
356
+ }
357
+ }
358
+ ], viewQueries: [{ propertyName: "editorComponent", first: true, predicate: EditorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isEditMode) {\n <editor\n #tinyEditor\n [init]=\"init\"\n [initialValue]=\"content\"\n (onMouseDown)=\"onMouseDown($event)\"\n (onFocusOut)=\"onFocusOut()\" />\n}\n", styles: [":host ::ng-deep .mce-content-body:not(.mce-edit-focus):hover{outline:2px solid #006ce7;border-radius:4px}\n"], dependencies: [{ kind: "component", type: EditorComponent, selector: "editor", inputs: ["cloudChannel", "apiKey", "init", "id", "initialValue", "outputFormat", "inline", "tagName", "plugins", "toolbar", "modelEvents", "allowedEvents", "ignoreEvents", "disabled"] }] }); }
359
+ }
360
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSEditableTextComponent, decorators: [{
361
+ type: Component,
362
+ args: [{ selector: 'dotcms-editable-text', standalone: true, imports: [EditorComponent], providers: [
363
+ {
364
+ provide: TINYMCE_SCRIPT_SRC,
365
+ useFactory: () => {
366
+ const { dotCMSHost } = getUVEState() || {};
367
+ return `${dotCMSHost || ''}${__TINYMCE_PATH_ON_DOTCMS__}`;
368
+ }
369
+ }
370
+ ], template: "@if (isEditMode) {\n <editor\n #tinyEditor\n [init]=\"init\"\n [initialValue]=\"content\"\n (onMouseDown)=\"onMouseDown($event)\"\n (onFocusOut)=\"onFocusOut()\" />\n}\n", styles: [":host ::ng-deep .mce-content-body:not(.mce-edit-focus):hover{outline:2px solid #006ce7;border-radius:4px}\n"] }]
371
+ }], propDecorators: { editorComponent: [{
372
+ type: ViewChild,
373
+ args: [EditorComponent]
374
+ }], mode: [{
375
+ type: Input
376
+ }], format: [{
377
+ type: Input
378
+ }], contentlet: [{
379
+ type: Input
380
+ }], fieldName: [{
381
+ type: Input
382
+ }], onMessage: [{
383
+ type: HostListener,
384
+ args: ['window:message', ['$event']]
385
+ }] } });
386
+
387
+ class DotCodeBlock {
388
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCodeBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
389
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotCodeBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-code-block", ngImport: i0, template: `
390
+ <pre>
391
+ <code>
392
+ <ng-content />
393
+ </code>
394
+ </pre>
395
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
396
+ }
397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCodeBlock, decorators: [{
398
+ type: Component,
399
+ args: [{
400
+ selector: 'dotcms-block-editor-renderer-code-block',
401
+ standalone: true,
402
+ template: `
403
+ <pre>
404
+ <code>
405
+ <ng-content />
406
+ </code>
407
+ </pre>
408
+ `,
409
+ changeDetection: ChangeDetectionStrategy.OnPush
410
+ }]
411
+ }] });
412
+ class DotBlockQuote {
413
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotBlockQuote, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
414
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotBlockQuote, isStandalone: true, selector: "dotcms-block-editor-renderer-block-quote", ngImport: i0, template: `
415
+ <blockquote>
416
+ <ng-content />
417
+ </blockquote>
418
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
419
+ }
420
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotBlockQuote, decorators: [{
421
+ type: Component,
422
+ args: [{
423
+ selector: 'dotcms-block-editor-renderer-block-quote',
424
+ standalone: true,
425
+ template: `
426
+ <blockquote>
427
+ <ng-content />
428
+ </blockquote>
429
+ `,
430
+ changeDetection: ChangeDetectionStrategy.OnPush
431
+ }]
432
+ }] });
433
+
434
+ /**
435
+ * Default component for unknown content type
436
+ */
437
+ class DotDefaultContentBlock {
438
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotDefaultContentBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
439
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotDefaultContentBlock, selector: "dot-default-content", inputs: { contentlet: "contentlet" }, ngImport: i0, template: '<div>Unknown Content Type: {{ contentlet?.contentType }}</div>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
440
+ }
441
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotDefaultContentBlock, decorators: [{
442
+ type: Component,
443
+ args: [{
444
+ selector: 'dot-default-content',
445
+ template: '<div>Unknown Content Type: {{ contentlet?.contentType }}</div>',
446
+ changeDetection: ChangeDetectionStrategy.OnPush
447
+ }]
448
+ }], propDecorators: { contentlet: [{
449
+ type: Input
450
+ }] } });
451
+ /**
452
+ * DotContent component that renders content based on content type
453
+ */
454
+ class DotContentletBlock {
455
+ constructor() {
456
+ this.$data = computed(() => this.attrs?.['data']);
457
+ }
458
+ ngOnInit() {
459
+ if (!this.$data()) {
460
+ console.error('DotCMSBlockEditorRendererContentlet: No data provided');
461
+ }
462
+ this.contentComponent =
463
+ this.customRenderers?.[this.$data()?.contentType] ??
464
+ Promise.resolve().then(function () { return contentlet_component; }).then((m) => m.DotDefaultContentBlock);
465
+ }
466
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotContentletBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
467
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotContentletBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-contentlet", inputs: { customRenderers: "customRenderers", attrs: "attrs" }, ngImport: i0, template: '<ng-container *ngComponentOutlet="contentComponent | async; inputs: { contentlet: $data() }"></ng-container>', isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
468
+ }
469
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotContentletBlock, decorators: [{
470
+ type: Component,
471
+ args: [{
472
+ selector: 'dotcms-block-editor-renderer-contentlet',
473
+ standalone: true,
474
+ imports: [NgComponentOutlet, AsyncPipe],
475
+ changeDetection: ChangeDetectionStrategy.OnPush,
476
+ template: '<ng-container *ngComponentOutlet="contentComponent | async; inputs: { contentlet: $data() }"></ng-container>'
477
+ }]
478
+ }], propDecorators: { customRenderers: [{
479
+ type: Input
480
+ }], attrs: [{
481
+ type: Input
482
+ }] } });
483
+
484
+ var contentlet_component = /*#__PURE__*/Object.freeze({
485
+ __proto__: null,
486
+ DotContentletBlock: DotContentletBlock,
487
+ DotDefaultContentBlock: DotDefaultContentBlock
488
+ });
489
+
490
+ class DotImageBlock {
491
+ constructor() {
492
+ this.$srcURL = computed(() => this.attrs?.['src']);
493
+ }
494
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotImageBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
495
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotImageBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-image", inputs: { attrs: "attrs" }, ngImport: i0, template: `
496
+ <img [alt]="attrs?.['alt']" [src]="$srcURL()" />
497
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
498
+ }
499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotImageBlock, decorators: [{
500
+ type: Component,
501
+ args: [{
502
+ selector: 'dotcms-block-editor-renderer-image',
503
+ standalone: true,
504
+ template: `
505
+ <img [alt]="attrs?.['alt']" [src]="$srcURL()" />
506
+ `,
507
+ changeDetection: ChangeDetectionStrategy.OnPush
508
+ }]
509
+ }], propDecorators: { attrs: [{
510
+ type: Input
511
+ }] } });
512
+
513
+ class DotBulletList {
514
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotBulletList, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
515
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotBulletList, isStandalone: true, selector: "dotcms-block-editor-renderer-bullet-list", ngImport: i0, template: `
516
+ <ul>
517
+ <ng-content />
518
+ </ul>
519
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
520
+ }
521
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotBulletList, decorators: [{
522
+ type: Component,
523
+ args: [{
524
+ selector: 'dotcms-block-editor-renderer-bullet-list',
525
+ standalone: true,
526
+ changeDetection: ChangeDetectionStrategy.OnPush,
527
+ template: `
528
+ <ul>
529
+ <ng-content />
530
+ </ul>
531
+ `
532
+ }]
533
+ }] });
534
+ class DotOrdererList {
535
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotOrdererList, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
536
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotOrdererList, isStandalone: true, selector: "dotcms-block-editor-renderer-ordered-list", ngImport: i0, template: `
537
+ <ol>
538
+ <ng-content />
539
+ </ol>
540
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
541
+ }
542
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotOrdererList, decorators: [{
543
+ type: Component,
544
+ args: [{
545
+ selector: 'dotcms-block-editor-renderer-ordered-list',
546
+ standalone: true,
547
+ changeDetection: ChangeDetectionStrategy.OnPush,
548
+ template: `
549
+ <ol>
550
+ <ng-content />
551
+ </ol>
552
+ `
553
+ }]
554
+ }] });
555
+ class DotListItem {
556
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotListItem, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
557
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotListItem, isStandalone: true, selector: "dotcms-block-editor-renderer-list-item", ngImport: i0, template: `
558
+ <li>
559
+ <ng-content />
560
+ </li>
561
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
562
+ }
563
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotListItem, decorators: [{
564
+ type: Component,
565
+ args: [{
566
+ selector: 'dotcms-block-editor-renderer-list-item',
567
+ standalone: true,
568
+ changeDetection: ChangeDetectionStrategy.OnPush,
569
+ template: `
570
+ <li>
571
+ <ng-content />
572
+ </li>
573
+ `
574
+ }]
575
+ }] });
576
+
577
+ class DotTableBlock {
578
+ constructor() {
579
+ this.blockEditorItem = DotCMSBlockEditorItemComponent;
580
+ }
581
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotTableBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
582
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotTableBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-table", inputs: { content: "content" }, ngImport: i0, template: `
583
+ <table>
584
+ <thead>
585
+ @for (rowNode of content?.slice(0, 1); track rowNode.type) {
586
+ <tr>
587
+ @for (cellNode of rowNode.content; track cellNode.type) {
588
+ <th
589
+ [attr.colspan]="cellNode.attrs?.['colspan'] || 1"
590
+ [attr.rowspan]="cellNode.attrs?.['rowspan'] || 1">
591
+ <ng-container
592
+ *ngComponentOutlet="
593
+ blockEditorItem;
594
+ inputs: { content: cellNode.content }
595
+ "></ng-container>
596
+ </th>
597
+ }
598
+ </tr>
599
+ }
600
+ </thead>
601
+ <tbody>
602
+ @for (rowNode of content?.slice(1); track rowNode.type) {
603
+ <tr>
604
+ @for (cellNode of rowNode.content; track cellNode.type) {
605
+ <td
606
+ [attr.colspan]="cellNode.attrs?.['colspan'] || 1"
607
+ [attr.rowspan]="cellNode.attrs?.['rowspan'] || 1">
608
+ <ng-container
609
+ *ngComponentOutlet="
610
+ blockEditorItem;
611
+ inputs: { content: cellNode.content }
612
+ "></ng-container>
613
+ </td>
614
+ }
615
+ </tr>
616
+ }
617
+ </tbody>
618
+ </table>
619
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }] }); }
620
+ }
621
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotTableBlock, decorators: [{
622
+ type: Component,
623
+ args: [{
624
+ selector: 'dotcms-block-editor-renderer-table',
625
+ standalone: true,
626
+ imports: [NgComponentOutlet],
627
+ template: `
628
+ <table>
629
+ <thead>
630
+ @for (rowNode of content?.slice(0, 1); track rowNode.type) {
631
+ <tr>
632
+ @for (cellNode of rowNode.content; track cellNode.type) {
633
+ <th
634
+ [attr.colspan]="cellNode.attrs?.['colspan'] || 1"
635
+ [attr.rowspan]="cellNode.attrs?.['rowspan'] || 1">
636
+ <ng-container
637
+ *ngComponentOutlet="
638
+ blockEditorItem;
639
+ inputs: { content: cellNode.content }
640
+ "></ng-container>
641
+ </th>
642
+ }
643
+ </tr>
644
+ }
645
+ </thead>
646
+ <tbody>
647
+ @for (rowNode of content?.slice(1); track rowNode.type) {
648
+ <tr>
649
+ @for (cellNode of rowNode.content; track cellNode.type) {
650
+ <td
651
+ [attr.colspan]="cellNode.attrs?.['colspan'] || 1"
652
+ [attr.rowspan]="cellNode.attrs?.['rowspan'] || 1">
653
+ <ng-container
654
+ *ngComponentOutlet="
655
+ blockEditorItem;
656
+ inputs: { content: cellNode.content }
657
+ "></ng-container>
658
+ </td>
659
+ }
660
+ </tr>
661
+ }
662
+ </tbody>
663
+ </table>
664
+ `
665
+ }]
666
+ }], propDecorators: { content: [{
667
+ type: Input
668
+ }] } });
669
+
670
+ class DotParagraphBlock {
671
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotParagraphBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
672
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotParagraphBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-paragraph", ngImport: i0, template: `
673
+ <p>
674
+ <ng-content />
675
+ </p>
676
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
677
+ }
678
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotParagraphBlock, decorators: [{
679
+ type: Component,
680
+ args: [{
681
+ selector: 'dotcms-block-editor-renderer-paragraph',
682
+ standalone: true,
683
+ changeDetection: ChangeDetectionStrategy.OnPush,
684
+ template: `
685
+ <p>
686
+ <ng-content />
687
+ </p>
688
+ `
689
+ }]
690
+ }] });
691
+ class DotHeadingBlock {
692
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotHeadingBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
693
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotHeadingBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-heading", inputs: { level: "level" }, ngImport: i0, template: `
694
+ @switch (level) {
695
+ @case ('1') {
696
+ <h1>
697
+ <ng-content />
698
+ </h1>
699
+ }
700
+ @case ('2') {
701
+ <h2>
702
+ <ng-content />
703
+ </h2>
704
+ }
705
+ @case ('3') {
706
+ <h3>
707
+ <ng-content />
708
+ </h3>
709
+ }
710
+ @case ('4') {
711
+ <h4>
712
+ <ng-content />
713
+ </h4>
714
+ }
715
+ @case ('5') {
716
+ <h5>
717
+ <ng-content />
718
+ </h5>
719
+ }
720
+ @case ('6') {
721
+ <h6>
722
+ <ng-content />
723
+ </h6>
724
+ }
725
+ @default {
726
+ <h1>
727
+ <ng-content />
728
+ </h1>
729
+ }
730
+ }
731
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
732
+ }
733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotHeadingBlock, decorators: [{
734
+ type: Component,
735
+ args: [{
736
+ selector: 'dotcms-block-editor-renderer-heading',
737
+ standalone: true,
738
+ changeDetection: ChangeDetectionStrategy.OnPush,
739
+ template: `
740
+ @switch (level) {
741
+ @case ('1') {
742
+ <h1>
743
+ <ng-content />
744
+ </h1>
745
+ }
746
+ @case ('2') {
747
+ <h2>
748
+ <ng-content />
749
+ </h2>
750
+ }
751
+ @case ('3') {
752
+ <h3>
753
+ <ng-content />
754
+ </h3>
755
+ }
756
+ @case ('4') {
757
+ <h4>
758
+ <ng-content />
759
+ </h4>
760
+ }
761
+ @case ('5') {
762
+ <h5>
763
+ <ng-content />
764
+ </h5>
765
+ }
766
+ @case ('6') {
767
+ <h6>
768
+ <ng-content />
769
+ </h6>
770
+ }
771
+ @default {
772
+ <h1>
773
+ <ng-content />
774
+ </h1>
775
+ }
776
+ }
777
+ `
778
+ }]
779
+ }], propDecorators: { level: [{
780
+ type: Input
781
+ }] } });
782
+ class DotTextBlock {
783
+ constructor() {
784
+ this.marks = [];
785
+ this.text = '';
786
+ this.$remainingMarks = computed(() => this.marks?.slice(1));
787
+ this.$currentAttrs = computed(() => {
788
+ const attrs = { ...(this.marks?.[0]?.attrs || {}) };
789
+ if (attrs['class']) {
790
+ attrs['className'] = attrs['class'];
791
+ delete attrs['class'];
792
+ }
793
+ return attrs;
794
+ });
795
+ }
796
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotTextBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
797
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotTextBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-text", inputs: { marks: "marks", text: "text" }, ngImport: i0, template: `
798
+ @switch (marks?.[0]?.type) {
799
+ @case ('link') {
800
+ <a
801
+ [attr.href]="$currentAttrs()['href'] || ''"
802
+ [attr.target]="$currentAttrs()['target'] || ''">
803
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
804
+ </a>
805
+ }
806
+ @case ('bold') {
807
+ <strong>
808
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
809
+ </strong>
810
+ }
811
+ @case ('underline') {
812
+ <u>
813
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
814
+ </u>
815
+ }
816
+ @case ('italic') {
817
+ <em>
818
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
819
+ </em>
820
+ }
821
+ @case ('strike') {
822
+ <s>
823
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
824
+ </s>
825
+ }
826
+ @case ('superscript') {
827
+ <sup>
828
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
829
+ </sup>
830
+ }
831
+ @case ('subscript') {
832
+ <sub>
833
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
834
+ </sub>
835
+ }
836
+ @default {
837
+ {{ text }}
838
+ }
839
+ }
840
+ `, isInline: true, dependencies: [{ kind: "component", type: DotTextBlock, selector: "dotcms-block-editor-renderer-text", inputs: ["marks", "text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
841
+ }
842
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotTextBlock, decorators: [{
843
+ type: Component,
844
+ args: [{
845
+ selector: 'dotcms-block-editor-renderer-text',
846
+ standalone: true,
847
+ changeDetection: ChangeDetectionStrategy.OnPush,
848
+ template: `
849
+ @switch (marks?.[0]?.type) {
850
+ @case ('link') {
851
+ <a
852
+ [attr.href]="$currentAttrs()['href'] || ''"
853
+ [attr.target]="$currentAttrs()['target'] || ''">
854
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
855
+ </a>
856
+ }
857
+ @case ('bold') {
858
+ <strong>
859
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
860
+ </strong>
861
+ }
862
+ @case ('underline') {
863
+ <u>
864
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
865
+ </u>
866
+ }
867
+ @case ('italic') {
868
+ <em>
869
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
870
+ </em>
871
+ }
872
+ @case ('strike') {
873
+ <s>
874
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
875
+ </s>
876
+ }
877
+ @case ('superscript') {
878
+ <sup>
879
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
880
+ </sup>
881
+ }
882
+ @case ('subscript') {
883
+ <sub>
884
+ <dotcms-block-editor-renderer-text [marks]="$remainingMarks()" [text]="text" />
885
+ </sub>
886
+ }
887
+ @default {
888
+ {{ text }}
889
+ }
890
+ }
891
+ `
892
+ }]
893
+ }], propDecorators: { marks: [{
894
+ type: Input
895
+ }], text: [{
896
+ type: Input
897
+ }] } });
898
+
899
+ class DotVideoBlock {
900
+ constructor() {
901
+ this.$srcURL = computed(() => this.attrs?.['src']);
902
+ this.$posterURL = computed(() => this.attrs?.['data']?.['thumbnail']);
903
+ }
904
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotVideoBlock, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
905
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: DotVideoBlock, isStandalone: true, selector: "dotcms-block-editor-renderer-video", inputs: { attrs: "attrs" }, ngImport: i0, template: `
906
+ <video
907
+ [controls]="true"
908
+ preload="metadata"
909
+ [poster]="this.$posterURL()"
910
+ [width]="attrs?.['width']"
911
+ [height]="attrs?.['height']">
912
+ <track default kind="captions" srclang="en" />
913
+ <source [src]="this.$srcURL()" [type]="attrs?.['mimeType']" />
914
+ Your browser does not support the
915
+ <code>video</code>
916
+ element.
917
+ </video>
918
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
919
+ }
920
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotVideoBlock, decorators: [{
921
+ type: Component,
922
+ args: [{
923
+ selector: 'dotcms-block-editor-renderer-video',
924
+ standalone: true,
925
+ changeDetection: ChangeDetectionStrategy.OnPush,
926
+ template: `
927
+ <video
928
+ [controls]="true"
929
+ preload="metadata"
930
+ [poster]="this.$posterURL()"
931
+ [width]="attrs?.['width']"
932
+ [height]="attrs?.['height']">
933
+ <track default kind="captions" srclang="en" />
934
+ <source [src]="this.$srcURL()" [type]="attrs?.['mimeType']" />
935
+ Your browser does not support the
936
+ <code>video</code>
937
+ element.
938
+ </video>
939
+ `
940
+ }]
941
+ }], propDecorators: { attrs: [{
942
+ type: Input
943
+ }] } });
944
+
945
+ class DotCMSBlockEditorItemComponent {
946
+ constructor() {
947
+ this.BLOCKS = BlockEditorDefaultBlocks;
948
+ }
949
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSBlockEditorItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
950
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotCMSBlockEditorItemComponent, isStandalone: true, selector: "dotcms-block-editor-renderer-block", inputs: { content: "content", customRenderers: "customRenderers" }, ngImport: i0, template: "@for (node of content; track node) {\n @if (customRenderers?.[node.type]) {\n <ng-container\n *ngTemplateOutlet=\"\n customRender;\n context: { customRender: customRenderers?.[node.type], node: node }\n \"></ng-container>\n } @else {\n @switch (node.type) {\n @case (BLOCKS.PARAGRAPH) {\n <dotcms-block-editor-renderer-paragraph [style]=\"node.attrs\">\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-paragraph>\n }\n\n @case (BLOCKS.TEXT) {\n <dotcms-block-editor-renderer-text [marks]=\"node.marks\" [text]=\"node.text || ''\" />\n }\n\n @case (BLOCKS.HEADING) {\n <dotcms-block-editor-renderer-heading\n [style]=\"node.attrs || {}\"\n [level]=\"node.attrs?.['level'] || '1'\">\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-heading>\n }\n\n @case (BLOCKS.BULLET_LIST) {\n <dotcms-block-editor-renderer-bullet-list>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-bullet-list>\n }\n\n @case (BLOCKS.ORDERED_LIST) {\n <dotcms-block-editor-renderer-ordered-list>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-ordered-list>\n }\n\n @case (BLOCKS.LIST_ITEM) {\n <dotcms-block-editor-renderer-list-item>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-list-item>\n }\n\n @case (BLOCKS.BLOCK_QUOTE) {\n <dotcms-block-editor-renderer-block-quote>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-block-quote>\n }\n\n @case (BLOCKS.CODE_BLOCK) {\n <dotcms-block-editor-renderer-code-block>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-code-block>\n }\n\n @case (BLOCKS.HARDBREAK) {\n <br />\n }\n\n @case (BLOCKS.HORIZONTAL_RULE) {\n <hr />\n }\n\n @case (BLOCKS.DOT_IMAGE) {\n <dotcms-block-editor-renderer-image [attrs]=\"node.attrs || {}\" />\n }\n\n @case (BLOCKS.DOT_VIDEO) {\n <dotcms-block-editor-renderer-video [attrs]=\"node.attrs || {}\" />\n }\n\n @case (BLOCKS.TABLE) {\n <dotcms-block-editor-renderer-table [content]=\"node.content\" />\n }\n\n @case (BLOCKS.DOT_CONTENT) {\n <dotcms-block-editor-renderer-contentlet\n [attrs]=\"node.attrs || {}\"\n [customRenderers]=\"customRenderers\" />\n }\n\n @default {\n <div>Unknown Block Type: {{ node.type }}</div>\n }\n }\n }\n}\n\n<ng-template #customRender let-customRender=\"customRender\" let-node=\"node\">\n <ng-container\n *ngComponentOutlet=\"customRender | async; inputs: { content: node }\"></ng-container>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "component", type: DotCMSBlockEditorItemComponent, selector: "dotcms-block-editor-renderer-block", inputs: ["content", "customRenderers"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: DotParagraphBlock, selector: "dotcms-block-editor-renderer-paragraph" }, { kind: "component", type: DotTextBlock, selector: "dotcms-block-editor-renderer-text", inputs: ["marks", "text"] }, { kind: "component", type: DotHeadingBlock, selector: "dotcms-block-editor-renderer-heading", inputs: ["level"] }, { kind: "component", type: DotBulletList, selector: "dotcms-block-editor-renderer-bullet-list" }, { kind: "component", type: DotOrdererList, selector: "dotcms-block-editor-renderer-ordered-list" }, { kind: "component", type: DotListItem, selector: "dotcms-block-editor-renderer-list-item" }, { kind: "component", type: DotCodeBlock, selector: "dotcms-block-editor-renderer-code-block" }, { kind: "component", type: DotBlockQuote, selector: "dotcms-block-editor-renderer-block-quote" }, { kind: "component", type: DotImageBlock, selector: "dotcms-block-editor-renderer-image", inputs: ["attrs"] }, { kind: "component", type: DotVideoBlock, selector: "dotcms-block-editor-renderer-video", inputs: ["attrs"] }, { kind: "component", type: DotTableBlock, selector: "dotcms-block-editor-renderer-table", inputs: ["content"] }, { kind: "component", type: DotContentletBlock, selector: "dotcms-block-editor-renderer-contentlet", inputs: ["customRenderers", "attrs"] }] }); }
951
+ }
952
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSBlockEditorItemComponent, decorators: [{
953
+ type: Component,
954
+ args: [{ selector: 'dotcms-block-editor-renderer-block', standalone: true, imports: [
955
+ NgTemplateOutlet,
956
+ NgComponentOutlet,
957
+ AsyncPipe,
958
+ DotParagraphBlock,
959
+ DotTextBlock,
960
+ DotHeadingBlock,
961
+ DotBulletList,
962
+ DotOrdererList,
963
+ DotListItem,
964
+ DotCodeBlock,
965
+ DotBlockQuote,
966
+ DotImageBlock,
967
+ DotVideoBlock,
968
+ DotTableBlock,
969
+ DotContentletBlock
970
+ ], template: "@for (node of content; track node) {\n @if (customRenderers?.[node.type]) {\n <ng-container\n *ngTemplateOutlet=\"\n customRender;\n context: { customRender: customRenderers?.[node.type], node: node }\n \"></ng-container>\n } @else {\n @switch (node.type) {\n @case (BLOCKS.PARAGRAPH) {\n <dotcms-block-editor-renderer-paragraph [style]=\"node.attrs\">\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-paragraph>\n }\n\n @case (BLOCKS.TEXT) {\n <dotcms-block-editor-renderer-text [marks]=\"node.marks\" [text]=\"node.text || ''\" />\n }\n\n @case (BLOCKS.HEADING) {\n <dotcms-block-editor-renderer-heading\n [style]=\"node.attrs || {}\"\n [level]=\"node.attrs?.['level'] || '1'\">\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-heading>\n }\n\n @case (BLOCKS.BULLET_LIST) {\n <dotcms-block-editor-renderer-bullet-list>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-bullet-list>\n }\n\n @case (BLOCKS.ORDERED_LIST) {\n <dotcms-block-editor-renderer-ordered-list>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-ordered-list>\n }\n\n @case (BLOCKS.LIST_ITEM) {\n <dotcms-block-editor-renderer-list-item>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-list-item>\n }\n\n @case (BLOCKS.BLOCK_QUOTE) {\n <dotcms-block-editor-renderer-block-quote>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-block-quote>\n }\n\n @case (BLOCKS.CODE_BLOCK) {\n <dotcms-block-editor-renderer-code-block>\n <dotcms-block-editor-renderer-block\n [content]=\"node.content\"\n [customRenderers]=\"customRenderers\" />\n </dotcms-block-editor-renderer-code-block>\n }\n\n @case (BLOCKS.HARDBREAK) {\n <br />\n }\n\n @case (BLOCKS.HORIZONTAL_RULE) {\n <hr />\n }\n\n @case (BLOCKS.DOT_IMAGE) {\n <dotcms-block-editor-renderer-image [attrs]=\"node.attrs || {}\" />\n }\n\n @case (BLOCKS.DOT_VIDEO) {\n <dotcms-block-editor-renderer-video [attrs]=\"node.attrs || {}\" />\n }\n\n @case (BLOCKS.TABLE) {\n <dotcms-block-editor-renderer-table [content]=\"node.content\" />\n }\n\n @case (BLOCKS.DOT_CONTENT) {\n <dotcms-block-editor-renderer-contentlet\n [attrs]=\"node.attrs || {}\"\n [customRenderers]=\"customRenderers\" />\n }\n\n @default {\n <div>Unknown Block Type: {{ node.type }}</div>\n }\n }\n }\n}\n\n<ng-template #customRender let-customRender=\"customRender\" let-node=\"node\">\n <ng-container\n *ngComponentOutlet=\"customRender | async; inputs: { content: node }\"></ng-container>\n</ng-template>\n" }]
971
+ }], propDecorators: { content: [{
972
+ type: Input
973
+ }], customRenderers: [{
974
+ type: Input
975
+ }] } });
976
+
977
+ /**
978
+ * A component that renders content from DotCMS's Block Editor field.
979
+ *
980
+ * This component provides an easy way to render Block Editor content in your Angular applications.
981
+ * It handles the rendering of standard blocks and allows customization through custom renderers.
982
+ *
983
+ * For more information about Block Editor, see {@link https://dev.dotcms.com/docs/block-editor}
984
+ *
985
+ * @example
986
+ * ```html
987
+ * <dotcms-block-editor-renderer
988
+ * [blocks]="myBlockEditorContent"
989
+ * [customRenderers]="myCustomRenderers">
990
+ * </dotcms-block-editor-renderer>
991
+ * ```
992
+ */
993
+ class DotCMSBlockEditorRendererComponent {
994
+ constructor() {
995
+ this.$blockEditorState = signal({ error: null });
996
+ this.$isInEditMode = signal(getUVEState()?.mode === UVE_MODE.EDIT);
997
+ }
998
+ ngOnInit() {
999
+ const state = isValidBlocks(this.blocks);
1000
+ if (state.error) {
1001
+ console.error('Error in dotcms-block-editor-renderer: ', state.error);
1002
+ }
1003
+ this.$blockEditorState.set(isValidBlocks(this.blocks));
1004
+ }
1005
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSBlockEditorRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1006
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotCMSBlockEditorRendererComponent, isStandalone: true, selector: "dotcms-block-editor-renderer", inputs: { blocks: "blocks", customRenderers: "customRenderers" }, ngImport: i0, template: "@if ($blockEditorState().error && $isInEditMode()) {\n <div data-testid=\"invalid-blocks-message\">\n {{ $blockEditorState().error }}\n </div>\n} @else if (!$blockEditorState().error) {\n <dotcms-block-editor-renderer-block\n [content]=\"blocks.content\"\n [customRenderers]=\"customRenderers\" />\n}\n", styles: [""], dependencies: [{ kind: "component", type: DotCMSBlockEditorItemComponent, selector: "dotcms-block-editor-renderer-block", inputs: ["content", "customRenderers"] }] }); }
1007
+ }
1008
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSBlockEditorRendererComponent, decorators: [{
1009
+ type: Component,
1010
+ args: [{ selector: 'dotcms-block-editor-renderer', standalone: true, imports: [DotCMSBlockEditorItemComponent], template: "@if ($blockEditorState().error && $isInEditMode()) {\n <div data-testid=\"invalid-blocks-message\">\n {{ $blockEditorState().error }}\n </div>\n} @else if (!$blockEditorState().error) {\n <dotcms-block-editor-renderer-block\n [content]=\"blocks.content\"\n [customRenderers]=\"customRenderers\" />\n}\n" }]
1011
+ }], propDecorators: { blocks: [{
1012
+ type: Input
1013
+ }], customRenderers: [{
1014
+ type: Input
1015
+ }] } });
1016
+
1017
+ /**
1018
+ * @description This component is used to display a message when a page is missing the required `layout.body` property.
1019
+ * @internal
1020
+ * @class PageErrorMessageComponent
1021
+ */
1022
+ class PageErrorMessageComponent {
1023
+ ngOnInit() {
1024
+ console.warn('Missing required layout.body property in page');
1025
+ }
1026
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: PageErrorMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1027
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.3", type: PageErrorMessageComponent, isStandalone: true, selector: "dotcms-page-error-message", ngImport: i0, template: `
1028
+ <div
1029
+ data-testid="error-message"
1030
+ style="padding: 1rem; border: 1px solid #e0e0e0; border-radius: 4px;">
1031
+ <p style="margin: 0 0 0.5rem; color: #666;">
1032
+ The
1033
+ <code>page</code>
1034
+ is missing the required
1035
+ <code>layout.body</code>
1036
+ property.
1037
+ </p>
1038
+ <p style="margin: 0; color: #666;">
1039
+ Make sure the page asset is properly loaded and includes a layout configuration.
1040
+ </p>
1041
+ </div>
1042
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1043
+ }
1044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: PageErrorMessageComponent, decorators: [{
1045
+ type: Component,
1046
+ args: [{
1047
+ selector: 'dotcms-page-error-message',
1048
+ standalone: true,
1049
+ imports: [],
1050
+ template: `
1051
+ <div
1052
+ data-testid="error-message"
1053
+ style="padding: 1rem; border: 1px solid #e0e0e0; border-radius: 4px;">
1054
+ <p style="margin: 0 0 0.5rem; color: #666;">
1055
+ The
1056
+ <code>page</code>
1057
+ is missing the required
1058
+ <code>layout.body</code>
1059
+ property.
1060
+ </p>
1061
+ <p style="margin: 0; color: #666;">
1062
+ Make sure the page asset is properly loaded and includes a layout configuration.
1063
+ </p>
1064
+ </div>
1065
+ `,
1066
+ changeDetection: ChangeDetectionStrategy.OnPush
1067
+ }]
1068
+ }] });
1069
+
1070
+ const EMPTY_DOTCMS_PAGE_STORE = {
1071
+ page: {},
1072
+ components: {},
1073
+ mode: PRODUCTION_MODE
1074
+ };
1075
+ /**
1076
+ * @description This service is responsible for managing the page context.
1077
+ * @internal
1078
+ * @author dotCMS
1079
+ * @export
1080
+ * @class DotCMSStore
1081
+ */
1082
+ class DotCMSStore {
1083
+ constructor() {
1084
+ this.$store = signal(EMPTY_DOTCMS_PAGE_STORE);
1085
+ /**
1086
+ * @description Get if the current context is in development mode
1087
+ * @readonly
1088
+ * @type {boolean}
1089
+ * @memberof DotCMSStore
1090
+ */
1091
+ this.$isDevMode = computed(() => {
1092
+ const uveState = getUVEState();
1093
+ if (uveState?.mode) {
1094
+ return uveState?.mode === UVE_MODE.EDIT;
1095
+ }
1096
+ return this.$store()?.mode === DEVELOPMENT_MODE;
1097
+ });
1098
+ }
1099
+ /**
1100
+ * @description Get the store
1101
+ * @readonly
1102
+ * @type {DotCMSPageStore}
1103
+ * @memberof DotCMSStore
1104
+ */
1105
+ get store() {
1106
+ return this.$store();
1107
+ }
1108
+ /**
1109
+ * @description Set the store
1110
+ * @param {DotCMSPageStore} value
1111
+ * @memberof DotCMSStore
1112
+ */
1113
+ setStore(store) {
1114
+ this.$store.set(store);
1115
+ }
1116
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1117
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSStore, providedIn: 'root' }); }
1118
+ }
1119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSStore, decorators: [{
1120
+ type: Injectable,
1121
+ args: [{
1122
+ providedIn: 'root'
1123
+ }]
1124
+ }] });
1125
+
1126
+ /**
1127
+ * @description This component is used to display a message when a container is not found.
1128
+ * @export
1129
+ * @internal
1130
+ * @class ContainerNotFoundComponent
1131
+ * @implements {OnInit}
1132
+ */
1133
+ class ContainerNotFoundComponent {
1134
+ constructor() {
1135
+ this.identifier = 'unknown';
1136
+ this.#dotcmsContextService = inject(DotCMSStore);
1137
+ this.$isDevMode = this.#dotcmsContextService.$isDevMode;
1138
+ this.emptyContainerStyle = EMPTY_CONTAINER_STYLE_ANGULAR;
1139
+ }
1140
+ #dotcmsContextService;
1141
+ ngOnInit() {
1142
+ if (this.$isDevMode()) {
1143
+ console.error(`Container with identifier ${this.identifier} not found`);
1144
+ }
1145
+ }
1146
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContainerNotFoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1147
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: ContainerNotFoundComponent, isStandalone: true, selector: "dotcms-container-not-found", inputs: { identifier: "identifier" }, ngImport: i0, template: `
1148
+ @if ($isDevMode()) {
1149
+ <div [attr.data-testid]="'container-not-found'" [ngStyle]="emptyContainerStyle">
1150
+ This container with identifier {{ identifier }} was not found.
1151
+ </div>
1152
+ }
1153
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
1154
+ }
1155
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContainerNotFoundComponent, decorators: [{
1156
+ type: Component,
1157
+ args: [{
1158
+ selector: 'dotcms-container-not-found',
1159
+ standalone: true,
1160
+ imports: [NgStyle],
1161
+ template: `
1162
+ @if ($isDevMode()) {
1163
+ <div [attr.data-testid]="'container-not-found'" [ngStyle]="emptyContainerStyle">
1164
+ This container with identifier {{ identifier }} was not found.
1165
+ </div>
1166
+ }
1167
+ `
1168
+ }]
1169
+ }], propDecorators: { identifier: [{
1170
+ type: Input
1171
+ }] } });
1172
+
1173
+ /**
1174
+ * @description This component is used to display a message when a container is empty.
1175
+ * @export
1176
+ * @internal
1177
+ * @class EmptyContainerComponent
1178
+ */
1179
+ class EmptyContainerComponent {
1180
+ constructor() {
1181
+ this.emptyContainerStyle = EMPTY_CONTAINER_STYLE_ANGULAR;
1182
+ this.#dotCMSStore = inject(DotCMSStore);
1183
+ this.$isDevMode = this.#dotCMSStore.$isDevMode;
1184
+ }
1185
+ #dotCMSStore;
1186
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: EmptyContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1187
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: EmptyContainerComponent, isStandalone: true, selector: "dotcms-empty-container", ngImport: i0, template: `
1188
+ @if ($isDevMode()) {
1189
+ <div [ngStyle]="emptyContainerStyle" data-testid="empty-container">
1190
+ <span data-testid="empty-container-message">This container is empty.</span>
1191
+ </div>
1192
+ }
1193
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
1194
+ }
1195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: EmptyContainerComponent, decorators: [{
1196
+ type: Component,
1197
+ args: [{
1198
+ selector: 'dotcms-empty-container',
1199
+ standalone: true,
1200
+ imports: [NgStyle],
1201
+ template: `
1202
+ @if ($isDevMode()) {
1203
+ <div [ngStyle]="emptyContainerStyle" data-testid="empty-container">
1204
+ <span data-testid="empty-container-message">This container is empty.</span>
1205
+ </div>
1206
+ }
1207
+ `
1208
+ }]
1209
+ }] });
1210
+
1211
+ /**
1212
+ * @description Fallback component that renders when no custom component is found for a contentlet
1213
+ * @category Components
1214
+ * @internal
1215
+ * @class FallbackComponent
1216
+ */
1217
+ class FallbackComponent {
1218
+ constructor() {
1219
+ this.UserNoComponent = null;
1220
+ }
1221
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: FallbackComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1222
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: FallbackComponent, isStandalone: true, selector: "dotcms-fallback-component", inputs: { UserNoComponent: "UserNoComponent", contentlet: "contentlet" }, ngImport: i0, template: `
1223
+ @if (UserNoComponent) {
1224
+ <ng-container *ngComponentOutlet="UserNoComponent | async; inputs: { contentlet }" />
1225
+ } @else {
1226
+ <div data-testid="dotcms-fallback-component">
1227
+ <p>No component found for content type: {{ contentlet.contentType }}</p>
1228
+ </div>
1229
+ }
1230
+ `, isInline: true, dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1231
+ }
1232
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: FallbackComponent, decorators: [{
1233
+ type: Component,
1234
+ args: [{
1235
+ selector: 'dotcms-fallback-component',
1236
+ standalone: true,
1237
+ imports: [AsyncPipe, NgComponentOutlet],
1238
+ template: `
1239
+ @if (UserNoComponent) {
1240
+ <ng-container *ngComponentOutlet="UserNoComponent | async; inputs: { contentlet }" />
1241
+ } @else {
1242
+ <div data-testid="dotcms-fallback-component">
1243
+ <p>No component found for content type: {{ contentlet.contentType }}</p>
1244
+ </div>
1245
+ }
1246
+ `,
1247
+ changeDetection: ChangeDetectionStrategy.OnPush
1248
+ }]
1249
+ }], propDecorators: { UserNoComponent: [{
1250
+ type: Input
1251
+ }], contentlet: [{
1252
+ type: Input
1253
+ }] } });
1254
+
1255
+ /**
1256
+ * @description Contentlet component that renders DotCMS content with development mode support
1257
+ *
1258
+ * @component
1259
+ * @param {DotCMSContentlet} contentlet - The contentlet to be rendered
1260
+ * @param {string} container - The container identifier
1261
+ * @class ContentletComponent
1262
+ */
1263
+ class ContentletComponent {
1264
+ constructor() {
1265
+ this.dotObject = 'contentlet';
1266
+ this.#dotCMSStore = inject(DotCMSStore);
1267
+ this.$contentlet = signal(null);
1268
+ this.$UserComponent = signal(null);
1269
+ this.$UserNoComponent = signal(null);
1270
+ this.$isDevMode = this.#dotCMSStore.$isDevMode;
1271
+ this.$haveContent = signal(false);
1272
+ this.$style = computed(() => this.$isDevMode() && !this.$haveContent() ? { minHeight: '4rem' } : {});
1273
+ this.$dotAttributes = computed(() => {
1274
+ const contentlet = this.$contentlet();
1275
+ if (!contentlet || !this.$isDevMode())
1276
+ return {};
1277
+ return getDotContentletAttributes(contentlet, this.containerData.identifier);
1278
+ });
1279
+ this.identifier = null;
1280
+ this.basetype = null;
1281
+ this.title = null;
1282
+ this.inode = null;
1283
+ this.type = null;
1284
+ this.containerAttribute = null;
1285
+ this.onNumberOfPages = null;
1286
+ this.styleAttribute = null;
1287
+ }
1288
+ #dotCMSStore;
1289
+ ngOnChanges() {
1290
+ this.$contentlet.set(this.contentlet);
1291
+ this.setupComponents();
1292
+ this.identifier = this.$dotAttributes()['data-dot-identifier'];
1293
+ this.basetype = this.$dotAttributes()['data-dot-basetype'];
1294
+ this.title = this.$dotAttributes()['data-dot-title'];
1295
+ this.inode = this.$dotAttributes()['data-dot-inode'];
1296
+ this.type = this.$dotAttributes()['data-dot-type'];
1297
+ this.containerAttribute = JSON.stringify(this.containerData);
1298
+ this.onNumberOfPages = this.$dotAttributes()['data-dot-on-number-of-pages'];
1299
+ this.styleAttribute = this.$style();
1300
+ }
1301
+ ngAfterViewInit() {
1302
+ this.checkContent();
1303
+ }
1304
+ setupComponents() {
1305
+ const store = this.#dotCMSStore.store;
1306
+ if (!store)
1307
+ return;
1308
+ if (!store?.components)
1309
+ return;
1310
+ this.$UserComponent.set(store.components[this.contentlet?.contentType]);
1311
+ this.$UserNoComponent.set(store.components[CUSTOM_NO_COMPONENT]);
1312
+ }
1313
+ checkContent() {
1314
+ const element = this.contentletRef?.nativeElement;
1315
+ if (element) {
1316
+ const hasContent = element.getBoundingClientRect().height > 0;
1317
+ this.$haveContent.set(hasContent);
1318
+ }
1319
+ }
1320
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContentletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1321
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: ContentletComponent, isStandalone: true, selector: "dotcms-contentlet", inputs: { contentlet: "contentlet", containerData: "containerData" }, host: { properties: { "attr.data-dot-object": "this.dotObject", "attr.data-dot-identifier": "this.identifier", "attr.data-dot-basetype": "this.basetype", "attr.data-dot-title": "this.title", "attr.data-dot-inode": "this.inode", "attr.data-dot-type": "this.type", "attr.data-dot-container": "this.containerAttribute", "attr.data-dot-on-number-of-pages": "this.onNumberOfPages", "style": "this.styleAttribute" } }, viewQueries: [{ propertyName: "contentletRef", first: true, predicate: ["contentletRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
1322
+ @if ($UserComponent()) {
1323
+ <ng-container
1324
+ *ngComponentOutlet="
1325
+ $UserComponent() | async;
1326
+ inputs: { contentlet: $contentlet() ?? contentlet }
1327
+ " />
1328
+ } @else if ($isDevMode()) {
1329
+ <dotcms-fallback-component
1330
+ [UserNoComponent]="$UserNoComponent()"
1331
+ [contentlet]="$contentlet() ?? contentlet" />
1332
+ }
1333
+ `, isInline: true, dependencies: [{ kind: "component", type: FallbackComponent, selector: "dotcms-fallback-component", inputs: ["UserNoComponent", "contentlet"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1334
+ }
1335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContentletComponent, decorators: [{
1336
+ type: Component,
1337
+ args: [{
1338
+ selector: 'dotcms-contentlet',
1339
+ standalone: true,
1340
+ imports: [FallbackComponent, AsyncPipe, NgComponentOutlet],
1341
+ template: `
1342
+ @if ($UserComponent()) {
1343
+ <ng-container
1344
+ *ngComponentOutlet="
1345
+ $UserComponent() | async;
1346
+ inputs: { contentlet: $contentlet() ?? contentlet }
1347
+ " />
1348
+ } @else if ($isDevMode()) {
1349
+ <dotcms-fallback-component
1350
+ [UserNoComponent]="$UserNoComponent()"
1351
+ [contentlet]="$contentlet() ?? contentlet" />
1352
+ }
1353
+ `,
1354
+ changeDetection: ChangeDetectionStrategy.OnPush
1355
+ }]
1356
+ }], propDecorators: { contentlet: [{
1357
+ type: Input,
1358
+ args: [{ required: true }]
1359
+ }], containerData: [{
1360
+ type: Input,
1361
+ args: [{ required: true }]
1362
+ }], contentletRef: [{
1363
+ type: ViewChild,
1364
+ args: ['contentletRef']
1365
+ }], dotObject: [{
1366
+ type: HostBinding,
1367
+ args: ['attr.data-dot-object']
1368
+ }], identifier: [{
1369
+ type: HostBinding,
1370
+ args: ['attr.data-dot-identifier']
1371
+ }], basetype: [{
1372
+ type: HostBinding,
1373
+ args: ['attr.data-dot-basetype']
1374
+ }], title: [{
1375
+ type: HostBinding,
1376
+ args: ['attr.data-dot-title']
1377
+ }], inode: [{
1378
+ type: HostBinding,
1379
+ args: ['attr.data-dot-inode']
1380
+ }], type: [{
1381
+ type: HostBinding,
1382
+ args: ['attr.data-dot-type']
1383
+ }], containerAttribute: [{
1384
+ type: HostBinding,
1385
+ args: ['attr.data-dot-container']
1386
+ }], onNumberOfPages: [{
1387
+ type: HostBinding,
1388
+ args: ['attr.data-dot-on-number-of-pages']
1389
+ }], styleAttribute: [{
1390
+ type: HostBinding,
1391
+ args: ['style']
1392
+ }] } });
1393
+
1394
+ /**
1395
+ * @description This component renders a container with all its content using the layout provided by dotCMS Page API.
1396
+ *
1397
+ * @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
1398
+ * @category Components
1399
+ * @internal
1400
+ * @class ContainerComponent
1401
+ */
1402
+ class ContainerComponent {
1403
+ constructor() {
1404
+ this.#dotCMSStore = inject(DotCMSStore);
1405
+ this.$containerData = signal(null);
1406
+ this.$contentlets = signal([]);
1407
+ this.$isEmpty = computed(() => this.$contentlets().length === 0);
1408
+ this.$dotAttributes = computed(() => {
1409
+ const containerData = this.$containerData();
1410
+ if (!containerData || !this.#dotCMSStore.$isDevMode()) {
1411
+ return {};
1412
+ }
1413
+ return getDotContainerAttributes(containerData);
1414
+ });
1415
+ this.dotObject = 'container';
1416
+ this.acceptTypes = null;
1417
+ this.identifier = null;
1418
+ this.maxContentlets = null;
1419
+ this.uuid = null;
1420
+ }
1421
+ #dotCMSStore;
1422
+ ngOnChanges() {
1423
+ const { page } = this.#dotCMSStore.store ?? {};
1424
+ if (!page) {
1425
+ return;
1426
+ }
1427
+ this.$containerData.set(getContainersData(page, this.container));
1428
+ this.$contentlets.set(getContentletsInContainer(page, this.container));
1429
+ this.acceptTypes = this.$dotAttributes()['data-dot-accept-types'];
1430
+ this.identifier = this.$dotAttributes()['data-dot-identifier'];
1431
+ this.maxContentlets = this.$dotAttributes()['data-max-contentlets'];
1432
+ this.uuid = this.$dotAttributes()['data-dot-uuid'];
1433
+ }
1434
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1435
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: ContainerComponent, isStandalone: true, selector: "dotcms-container", inputs: { container: "container" }, host: { properties: { "attr.data-dot-object": "this.dotObject", "attr.data-dot-accept-types": "this.acceptTypes", "attr.data-dot-identifier": "this.identifier", "attr.data-max-contentlets": "this.maxContentlets", "attr.data-dot-uuid": "this.uuid" } }, usesOnChanges: true, ngImport: i0, template: `
1436
+ @if (!$containerData()) {
1437
+ <dotcms-container-not-found [identifier]="container.identifier" />
1438
+ } @else if ($isEmpty()) {
1439
+ <dotcms-empty-container />
1440
+ } @else {
1441
+ @for (contentlet of $contentlets(); track contentlet.identifier) {
1442
+ <dotcms-contentlet [contentlet]="contentlet" [containerData]="$containerData()!" />
1443
+ }
1444
+ }
1445
+ `, isInline: true, dependencies: [{ kind: "component", type: ContainerNotFoundComponent, selector: "dotcms-container-not-found", inputs: ["identifier"] }, { kind: "component", type: EmptyContainerComponent, selector: "dotcms-empty-container" }, { kind: "component", type: ContentletComponent, selector: "dotcms-contentlet", inputs: ["contentlet", "containerData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1446
+ }
1447
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ContainerComponent, decorators: [{
1448
+ type: Component,
1449
+ args: [{
1450
+ selector: 'dotcms-container',
1451
+ standalone: true,
1452
+ imports: [ContainerNotFoundComponent, EmptyContainerComponent, ContentletComponent],
1453
+ template: `
1454
+ @if (!$containerData()) {
1455
+ <dotcms-container-not-found [identifier]="container.identifier" />
1456
+ } @else if ($isEmpty()) {
1457
+ <dotcms-empty-container />
1458
+ } @else {
1459
+ @for (contentlet of $contentlets(); track contentlet.identifier) {
1460
+ <dotcms-contentlet [contentlet]="contentlet" [containerData]="$containerData()!" />
1461
+ }
1462
+ }
1463
+ `,
1464
+ changeDetection: ChangeDetectionStrategy.OnPush
1465
+ }]
1466
+ }], propDecorators: { container: [{
1467
+ type: Input,
1468
+ args: [{ required: true }]
1469
+ }], dotObject: [{
1470
+ type: HostBinding,
1471
+ args: ['attr.data-dot-object']
1472
+ }], acceptTypes: [{
1473
+ type: HostBinding,
1474
+ args: ['attr.data-dot-accept-types']
1475
+ }], identifier: [{
1476
+ type: HostBinding,
1477
+ args: ['attr.data-dot-identifier']
1478
+ }], maxContentlets: [{
1479
+ type: HostBinding,
1480
+ args: ['attr.data-max-contentlets']
1481
+ }], uuid: [{
1482
+ type: HostBinding,
1483
+ args: ['attr.data-dot-uuid']
1484
+ }] } });
1485
+
1486
+ /**
1487
+ * This component renders a column with all its content using the layout provided by dotCMS Page API.
1488
+ *
1489
+ * @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
1490
+ * @category Components
1491
+ * @internal
1492
+ */
1493
+ class ColumnComponent {
1494
+ constructor() {
1495
+ this.customClasses = '';
1496
+ }
1497
+ ngOnChanges() {
1498
+ const positionClasses = getColumnPositionClasses(this.column);
1499
+ this.customClasses = combineClasses([positionClasses.startClass, positionClasses.endClass]);
1500
+ }
1501
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1502
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: ColumnComponent, isStandalone: true, selector: "dotcms-column", inputs: { column: "column" }, host: { properties: { "class": "this.customClasses" } }, usesOnChanges: true, ngImport: i0, template: `
1503
+ <div [class]="column.styleClass" data-testid="dotcms-column">
1504
+ @for (container of column.containers; track $index) {
1505
+ <dotcms-container [container]="container" />
1506
+ }
1507
+ </div>
1508
+ `, isInline: true, styles: [":host.col-start-1{grid-column-start:1}:host.col-start-2{grid-column-start:2}:host.col-start-3{grid-column-start:3}:host.col-start-4{grid-column-start:4}:host.col-start-5{grid-column-start:5}:host.col-start-6{grid-column-start:6}:host.col-start-7{grid-column-start:7}:host.col-start-8{grid-column-start:8}:host.col-start-9{grid-column-start:9}:host.col-start-10{grid-column-start:10}:host.col-start-11{grid-column-start:11}:host.col-start-12{grid-column-start:12}:host.col-end-1{grid-column-end:1}:host.col-end-2{grid-column-end:2}:host.col-end-3{grid-column-end:3}:host.col-end-4{grid-column-end:4}:host.col-end-5{grid-column-end:5}:host.col-end-6{grid-column-end:6}:host.col-end-7{grid-column-end:7}:host.col-end-8{grid-column-end:8}:host.col-end-9{grid-column-end:9}:host.col-end-10{grid-column-end:10}:host.col-end-11{grid-column-end:11}:host.col-end-12{grid-column-end:12}:host.col-end-13{grid-column-end:13}\n"], dependencies: [{ kind: "component", type: ContainerComponent, selector: "dotcms-container", inputs: ["container"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1509
+ }
1510
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: ColumnComponent, decorators: [{
1511
+ type: Component,
1512
+ args: [{ selector: 'dotcms-column', standalone: true, imports: [ContainerComponent], template: `
1513
+ <div [class]="column.styleClass" data-testid="dotcms-column">
1514
+ @for (container of column.containers; track $index) {
1515
+ <dotcms-container [container]="container" />
1516
+ }
1517
+ </div>
1518
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host.col-start-1{grid-column-start:1}:host.col-start-2{grid-column-start:2}:host.col-start-3{grid-column-start:3}:host.col-start-4{grid-column-start:4}:host.col-start-5{grid-column-start:5}:host.col-start-6{grid-column-start:6}:host.col-start-7{grid-column-start:7}:host.col-start-8{grid-column-start:8}:host.col-start-9{grid-column-start:9}:host.col-start-10{grid-column-start:10}:host.col-start-11{grid-column-start:11}:host.col-start-12{grid-column-start:12}:host.col-end-1{grid-column-end:1}:host.col-end-2{grid-column-end:2}:host.col-end-3{grid-column-end:3}:host.col-end-4{grid-column-end:4}:host.col-end-5{grid-column-end:5}:host.col-end-6{grid-column-end:6}:host.col-end-7{grid-column-end:7}:host.col-end-8{grid-column-end:8}:host.col-end-9{grid-column-end:9}:host.col-end-10{grid-column-end:10}:host.col-end-11{grid-column-end:11}:host.col-end-12{grid-column-end:12}:host.col-end-13{grid-column-end:13}\n"] }]
1519
+ }], propDecorators: { column: [{
1520
+ type: Input,
1521
+ args: [{ required: true }]
1522
+ }], customClasses: [{
1523
+ type: HostBinding,
1524
+ args: ['class']
1525
+ }] } });
1526
+
1527
+ /**
1528
+ * @description This component renders a row with all its content using the layout provided by dotCMS Page API.
1529
+ *
1530
+ * @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
1531
+ * @category Components
1532
+ * @internal
1533
+ * @class RowComponent
1534
+ */
1535
+ class RowComponent {
1536
+ constructor() {
1537
+ this.customClasses = signal('');
1538
+ }
1539
+ ngOnChanges() {
1540
+ this.customClasses.set(combineClasses([this.row.styleClass || 'dot-row']));
1541
+ }
1542
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: RowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1543
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: RowComponent, isStandalone: true, selector: "dotcms-row", inputs: { row: "row" }, usesOnChanges: true, ngImport: i0, template: `
1544
+ <div class="dot-row-container">
1545
+ <div [class]="customClasses()" data-dot-object="row" data-testid="dotcms-row">
1546
+ @for (column of row.columns; track $index) {
1547
+ <dotcms-column [column]="column" />
1548
+ }
1549
+ </div>
1550
+ </div>
1551
+ `, isInline: true, styles: [".dot-row{display:grid;grid-template-columns:repeat(12,1fr);gap:1rem}\n"], dependencies: [{ kind: "component", type: ColumnComponent, selector: "dotcms-column", inputs: ["column"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1552
+ }
1553
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: RowComponent, decorators: [{
1554
+ type: Component,
1555
+ args: [{ selector: 'dotcms-row', standalone: true, imports: [ColumnComponent], template: `
1556
+ <div class="dot-row-container">
1557
+ <div [class]="customClasses()" data-dot-object="row" data-testid="dotcms-row">
1558
+ @for (column of row.columns; track $index) {
1559
+ <dotcms-column [column]="column" />
1560
+ }
1561
+ </div>
1562
+ </div>
1563
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".dot-row{display:grid;grid-template-columns:repeat(12,1fr);gap:1rem}\n"] }]
1564
+ }], propDecorators: { row: [{
1565
+ type: Input,
1566
+ args: [{ required: true }]
1567
+ }] } });
1568
+
1569
+ /**
1570
+ * @description This component is used to render the layout for a DotCMS page.
1571
+ * @param {DotCMSPageAsset} page - The page to render the layout for
1572
+ * @param {DotCMSPageComponent} components - The components to render the layout for
1573
+ * @param {DotCMSPageRendererMode} mode - The mode to render the layout for
1574
+ *
1575
+ * @example
1576
+ * <dotcms-layout-body [page]="page" [components]="components" [mode]="'development'" />
1577
+ *
1578
+ * @export
1579
+ * @implements {OnChanges}
1580
+ * @class DotCMSLayoutBodyComponent
1581
+ */
1582
+ class DotCMSLayoutBodyComponent {
1583
+ constructor() {
1584
+ this.components = {};
1585
+ this.mode = 'production';
1586
+ this.#dotCMSStore = inject(DotCMSStore);
1587
+ this.$isDevMode = this.#dotCMSStore.$isDevMode;
1588
+ this.$rows = signal([]);
1589
+ this.$isEmpty = signal(false);
1590
+ }
1591
+ #dotCMSStore;
1592
+ ngOnChanges() {
1593
+ this.#dotCMSStore.setStore({
1594
+ page: this.page,
1595
+ components: this.components,
1596
+ mode: this.mode
1597
+ });
1598
+ this.$isEmpty.set(!this.page?.layout?.body);
1599
+ this.$rows.set(this.page?.layout?.body?.rows ?? []);
1600
+ }
1601
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSLayoutBodyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1602
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.3", type: DotCMSLayoutBodyComponent, isStandalone: true, selector: "dotcms-layout-body", inputs: { page: "page", components: "components", mode: "mode" }, providers: [DotCMSStore], usesOnChanges: true, ngImport: i0, template: `
1603
+ @if ($isEmpty() && $isDevMode()) {
1604
+ <dotcms-page-error-message />
1605
+ } @else {
1606
+ @for (row of $rows(); track row.identifier) {
1607
+ <dotcms-row [row]="row" />
1608
+ }
1609
+ }
1610
+ `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: PageErrorMessageComponent, selector: "dotcms-page-error-message" }, { kind: "component", type: RowComponent, selector: "dotcms-row", inputs: ["row"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1611
+ }
1612
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSLayoutBodyComponent, decorators: [{
1613
+ type: Component,
1614
+ args: [{ selector: 'dotcms-layout-body', standalone: true, imports: [PageErrorMessageComponent, RowComponent], providers: [DotCMSStore], template: `
1615
+ @if ($isEmpty() && $isDevMode()) {
1616
+ <dotcms-page-error-message />
1617
+ } @else {
1618
+ @for (row of $rows(); track row.identifier) {
1619
+ <dotcms-row [row]="row" />
1620
+ }
1621
+ }
1622
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
1623
+ }], propDecorators: { page: [{
1624
+ type: Input,
1625
+ args: [{ required: true }]
1626
+ }], components: [{
1627
+ type: Input,
1628
+ args: [{ required: true }]
1629
+ }], mode: [{
1630
+ type: Input
1631
+ }] } });
1632
+
1633
+ class DotCMSEditablePageService {
1634
+ /**
1635
+ * Subject that emits the current editable page asset or null.
1636
+ * Used internally to track changes to the page data.
1637
+ *
1638
+ * @private
1639
+ * @type {Subject<DotCMSPageResponse | null>}
1640
+ */
1641
+ #responseSubject = new Subject();
1642
+ /**
1643
+ * Observable stream of the page asset changes.
1644
+ * Exposes the pageAssetSubject as an Observable for subscribers.
1645
+ *
1646
+ * @private
1647
+ * @type {Observable<DotCMSPageResponse | null>}
1648
+ */
1649
+ #response$ = this.#responseSubject.asObservable();
1650
+ /**
1651
+ * Listens for changes to an editable page and returns an Observable that emits the updated page data.
1652
+ * This method initializes the UVE (Universal Visual Editor) and sets up subscriptions to track content changes.
1653
+ *
1654
+ * @example
1655
+ * ```ts
1656
+ * // Import the service
1657
+ * import { DotCMSEditablePageService } from '@dotcms/angular';
1658
+ *
1659
+ * // Inject the service
1660
+ * constructor(private editablePageService: DotCMSEditablePageService) {}
1661
+ *
1662
+ * // Get the page data from your API call
1663
+ * const page = await client.page.get('/');
1664
+ *
1665
+ * // Listen for changes
1666
+ * const subscription = this.editablePageService.listen(page).subscribe(updatedPage => {
1667
+ * if (updatedPage) {
1668
+ * // Handle updated page data
1669
+ * console.log('Page updated:', updatedPage);
1670
+ * }
1671
+ * });
1672
+ *
1673
+ * // When done listening, unsubscribe
1674
+ * subscription.unsubscribe();
1675
+ * ```
1676
+ *
1677
+ * @param response Optional initial page data
1678
+ * @returns Observable that emits the updated page data or null
1679
+ */
1680
+ listen(response) {
1681
+ if (!getUVEState()) {
1682
+ return of(response || null);
1683
+ }
1684
+ const pageURI = response?.pageAsset?.page?.pageURI;
1685
+ initUVE(response);
1686
+ // Update the navigation to the pageURI, when we have a pageURI
1687
+ // Sometimes the page is null due to permissions, so we don't want to update the navigation
1688
+ // And wait for the UVE to resolve the page
1689
+ if (pageURI) {
1690
+ updateNavigation(pageURI);
1691
+ }
1692
+ const unsubscribeUVEChanges = this.#listenUVEChanges();
1693
+ return this.#response$.pipe(finalize(() => {
1694
+ unsubscribeUVEChanges();
1695
+ }));
1696
+ }
1697
+ /**
1698
+ * Sets up a subscription to listen for UVE content changes and updates the page asset subject.
1699
+ * This is an internal method used by listenEditablePage() to handle UVE events.
1700
+ *
1701
+ * @returns {UVEUnsubscribeFunction} Function to unsubscribe from the UVE content changes
1702
+ * @private
1703
+ */
1704
+ #listenUVEChanges() {
1705
+ const { unsubscribe } = createUVESubscription(UVEEventType.CONTENT_CHANGES, (payload) => {
1706
+ this.#responseSubject.next(payload);
1707
+ });
1708
+ return unsubscribe;
1709
+ }
1710
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSEditablePageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1711
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSEditablePageService, providedIn: 'root' }); }
1712
+ }
1713
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.3", ngImport: i0, type: DotCMSEditablePageService, decorators: [{
1714
+ type: Injectable,
1715
+ args: [{
1716
+ providedIn: 'root'
1717
+ }]
1718
+ }] });
1719
+
1720
+ /**
1721
+ * Generated bundle index. Do not edit.
1722
+ */
1723
+
1724
+ export { DotCMSBlockEditorRendererComponent, DotCMSEditablePageService, DotCMSEditableTextComponent, DotCMSLayoutBodyComponent, DotCMSShowWhenDirective, provideDotCMSImageLoader };
1725
+ //# sourceMappingURL=dotcms-angular-next.mjs.map