@foblex/m-render 2.9.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, InjectionToken, ChangeDetectionStrategy, Component, EventEmitter, booleanAttribute, HostListener, Input, ViewChild, Output, input, output, viewChild, signal, PLATFORM_ID, computed, Renderer2, NgZone, ChangeDetectorRef, DestroyRef, Injector, ViewContainerRef, ElementRef, untracked, forwardRef, effect, afterNextRender } from '@angular/core';
2
+ import { inject, Injectable, InjectionToken, signal, PLATFORM_ID, ChangeDetectionStrategy, Component, computed, Renderer2, HostListener, input, EventEmitter, booleanAttribute, Input, ViewChild, Output, output, viewChild, NgZone, ChangeDetectorRef, DestroyRef, Injector, ElementRef, ViewContainerRef, untracked, forwardRef, effect, afterNextRender } from '@angular/core';
3
3
  import { DOCUMENT, isPlatformBrowser, TitleCasePipe } from '@angular/common';
4
4
  import { Router, NavigationEnd, RouterLink, ActivatedRoute, RouterOutlet } from '@angular/router';
5
- import { filter, tap, take, catchError, shareReplay } from 'rxjs/operators';
5
+ import { filter, tap, take, catchError, shareReplay, finalize } from 'rxjs/operators';
6
6
  import { Subject, from, map, switchMap, of, startWith, filter as filter$1, distinctUntilChanged, EMPTY, defer, Observable, fromEvent, debounceTime } from 'rxjs';
7
7
  import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
8
  import { Overlay, CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
@@ -11,7 +11,8 @@ import MarkdownIt from 'markdown-it';
11
11
  import { DomSanitizer } from '@angular/platform-browser';
12
12
  import container from 'markdown-it-container';
13
13
  import { __decorate } from 'tslib';
14
- import { createHighlighter } from 'shiki';
14
+ import { createHighlighterCore, isSpecialLang } from '@shikijs/core';
15
+ import { createOnigurumaEngine } from '@shikijs/engine-oniguruma';
15
16
 
16
17
  class GTagService {
17
18
  _config = inject(GTAG_CONFIG);
@@ -96,10 +97,10 @@ class GTagService {
96
97
  _getConfiguredIds() {
97
98
  return Array.from(this._configuredIds.values());
98
99
  }
99
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
100
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GTagService });
100
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: GTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
101
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: GTagService });
101
102
  }
102
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GTagService, decorators: [{
103
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: GTagService, decorators: [{
103
104
  type: Injectable
104
105
  }] });
105
106
 
@@ -117,127 +118,6 @@ function provideGTag(config) {
117
118
  }
118
119
  const GTAG_CONFIG = new InjectionToken('GTAG_CONFIG');
119
120
 
120
- class FSearchButtonComponent {
121
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FSearchButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
122
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: FSearchButtonComponent, isStandalone: true, selector: "f-search-button", ngImport: i0, template: "<a class=\"f-icon search\" [routerLink]=\"[]\" fragment=\"search\"></a>\n", styles: [".f-icon{display:block;width:20px;height:20px;margin-left:8px;color:var(--sponsor);cursor:pointer;transition:transform .2s ease}.f-icon:hover{transform:scale(1.1)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
123
- }
124
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FSearchButtonComponent, decorators: [{
125
- type: Component,
126
- args: [{ selector: 'f-search-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
127
- RouterLink,
128
- ], template: "<a class=\"f-icon search\" [routerLink]=\"[]\" fragment=\"search\"></a>\n", styles: [".f-icon{display:block;width:20px;height:20px;margin-left:8px;color:var(--sponsor);cursor:pointer;transition:transform .2s ease}.f-icon:hover{transform:scale(1.1)}\n"] }]
129
- }] });
130
-
131
- let uniqueId$1 = 0;
132
- class FCheckboxComponent {
133
- changeDetectorRef;
134
- id = `f-checkbox-${uniqueId$1++}`;
135
- change = new EventEmitter();
136
- inputElement;
137
- labelElement;
138
- get checked() {
139
- return this.isChecked;
140
- }
141
- set checked(value) {
142
- if (value != this.checked) {
143
- this.isChecked = value;
144
- this.changeDetectorRef.markForCheck();
145
- }
146
- }
147
- isChecked = false;
148
- constructor(changeDetectorRef) {
149
- this.changeDetectorRef = changeDetectorRef;
150
- }
151
- onInputClick() {
152
- this.handleInputClick();
153
- }
154
- onTouchTargetClick() {
155
- this.handleInputClick();
156
- this.inputElement?.nativeElement.focus();
157
- }
158
- handleInputClick() {
159
- this.isChecked = !this.isChecked;
160
- this.emitChangeEvent();
161
- }
162
- emitChangeEvent() {
163
- this.change.emit(this.isChecked);
164
- if (this.inputElement) {
165
- this.inputElement.nativeElement.checked = this.isChecked;
166
- }
167
- }
168
- onInteractionEvent(event) {
169
- event.stopPropagation();
170
- }
171
- preventBubblingFromLabel(event) {
172
- if (!!event.target && this.labelElement?.nativeElement.contains(event.target)) {
173
- event.stopPropagation();
174
- }
175
- }
176
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FCheckboxComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
177
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.1.8", type: FCheckboxComponent, isStandalone: true, selector: "f-checkbox", inputs: { id: "id", checked: ["checked", "checked", booleanAttribute] }, outputs: { change: "change" }, host: { listeners: { "click": "preventBubblingFromLabel($event)" }, properties: { "class.f-checkbox-checked": "checked" } }, viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }, { propertyName: "labelElement", first: true, predicate: ["label"], descendants: true }], ngImport: i0, template: "<input #input\n [id]=\"id\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-checkbox-container\" (click)=\"onTouchTargetClick()\">\n <svg class=\"f-checkbox-checkmark\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path class=\"f-checkbox-checkmark-path\" fill=\"none\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\"/>\n </svg>\n</div>\n<label [for]=\"id\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--checkbox-container-background);border-radius:var(--checkbox-border-radius);padding:0 8px;color:var(--checkbox-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-checkbox-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--checkbox-size);height:var(--checkbox-size);margin-right:6px;border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background);padding:2px}:host .f-checkbox-container .f-checkbox-checkmark{position:absolute;top:calc(var(--checkbox-size) / 8);right:calc(var(--checkbox-size) / 8);bottom:calc(var(--checkbox-size) / 8);left:calc(var(--checkbox-size) / 8);opacity:0}:host .f-checkbox-container .f-checkbox-checkmark .f-checkbox-checkmark-path{stroke:currentColor;stroke-width:3}:host label{-webkit-user-select:none;user-select:none}:host.f-checkbox-checked .f-checkbox-container{background-color:var(--checkbox-checked-background)}:host.f-checkbox-checked .f-checkbox-container .f-checkbox-checkmark{color:var(--checkbox-checkmark-color);opacity:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
178
- }
179
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FCheckboxComponent, decorators: [{
180
- type: Component,
181
- args: [{ selector: 'f-checkbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
182
- '[class.f-checkbox-checked]': 'checked',
183
- }, template: "<input #input\n [id]=\"id\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-checkbox-container\" (click)=\"onTouchTargetClick()\">\n <svg class=\"f-checkbox-checkmark\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path class=\"f-checkbox-checkmark-path\" fill=\"none\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\"/>\n </svg>\n</div>\n<label [for]=\"id\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--checkbox-container-background);border-radius:var(--checkbox-border-radius);padding:0 8px;color:var(--checkbox-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-checkbox-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--checkbox-size);height:var(--checkbox-size);margin-right:6px;border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background);padding:2px}:host .f-checkbox-container .f-checkbox-checkmark{position:absolute;top:calc(var(--checkbox-size) / 8);right:calc(var(--checkbox-size) / 8);bottom:calc(var(--checkbox-size) / 8);left:calc(var(--checkbox-size) / 8);opacity:0}:host .f-checkbox-container .f-checkbox-checkmark .f-checkbox-checkmark-path{stroke:currentColor;stroke-width:3}:host label{-webkit-user-select:none;user-select:none}:host.f-checkbox-checked .f-checkbox-container{background-color:var(--checkbox-checked-background)}:host.f-checkbox-checked .f-checkbox-container .f-checkbox-checkmark{color:var(--checkbox-checkmark-color);opacity:1}\n"] }]
184
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { id: [{
185
- type: Input
186
- }], change: [{
187
- type: Output
188
- }], inputElement: [{
189
- type: ViewChild,
190
- args: ['input']
191
- }], labelElement: [{
192
- type: ViewChild,
193
- args: ['label']
194
- }], checked: [{
195
- type: Input,
196
- args: [{ transform: booleanAttribute }]
197
- }], preventBubblingFromLabel: [{
198
- type: HostListener,
199
- args: ['click', ['$event']]
200
- }] } });
201
-
202
- let uniqueId = 0;
203
- class FRadioButtonComponent {
204
- id = input(`f-radio-button-${uniqueId++}`, ...(ngDevMode ? [{ debugName: "id" }] : []));
205
- change = output();
206
- checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
207
- labelElement = viewChild('label', ...(ngDevMode ? [{ debugName: "labelElement" }] : []));
208
- onInputClick() {
209
- this._handleInputClick();
210
- }
211
- onTouchTargetClick() {
212
- this._handleInputClick();
213
- }
214
- _handleInputClick() {
215
- this._emitChangeEvent();
216
- }
217
- _emitChangeEvent() {
218
- this.change.emit(true);
219
- }
220
- onInteractionEvent(event) {
221
- event.stopPropagation();
222
- }
223
- preventBubblingFromLabel(event) {
224
- if (!!event.target && this.labelElement()?.nativeElement.contains(event.target)) {
225
- event.stopPropagation();
226
- }
227
- }
228
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FRadioButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
229
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.8", type: FRadioButtonComponent, isStandalone: true, selector: "f-radio-button", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change" }, host: { listeners: { "click": "preventBubblingFromLabel($event)" }, properties: { "class.f-radio-button-checked": "checked()" } }, viewQueries: [{ propertyName: "labelElement", first: true, predicate: ["label"], descendants: true, isSignal: true }], ngImport: i0, template: "<input [id]=\"id()\"\n type=\"radio\"\n [checked]=\"checked()\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-radio-button-container\" (click)=\"onTouchTargetClick()\">\n <div class=\"f-radio-button-inner-circle\"></div>\n</div>\n<label [for]=\"id()\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--radio-button-container-background);border-radius:var(--radio-button-container-border-radius);padding:0 8px;color:var(--radio-button-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-radio-button-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--radio-button-size);height:var(--radio-button-size);margin-right:6px;border-radius:50%;border:1px solid var(--radio-button-border-color);background-color:var(--radio-button-background)}:host .f-radio-button-container .f-radio-button-inner-circle{position:absolute;top:calc(var(--radio-button-size) / 4);right:calc(var(--radio-button-size) / 4);bottom:calc(var(--radio-button-size) / 4);left:calc(var(--radio-button-size) / 4);border-radius:50%}:host label{-webkit-user-select:none;user-select:none}:host.f-radio-button-checked .f-radio-button-container{background-color:var(--radio-button-checked-background)}:host.f-radio-button-checked .f-radio-button-container .f-radio-button-inner-circle{background-color:var(--radio-button-inner-circle-color)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
230
- }
231
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FRadioButtonComponent, decorators: [{
232
- type: Component,
233
- args: [{ selector: 'f-radio-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
234
- '[class.f-radio-button-checked]': 'checked()',
235
- }, template: "<input [id]=\"id()\"\n type=\"radio\"\n [checked]=\"checked()\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-radio-button-container\" (click)=\"onTouchTargetClick()\">\n <div class=\"f-radio-button-inner-circle\"></div>\n</div>\n<label [for]=\"id()\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--radio-button-container-background);border-radius:var(--radio-button-container-border-radius);padding:0 8px;color:var(--radio-button-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-radio-button-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--radio-button-size);height:var(--radio-button-size);margin-right:6px;border-radius:50%;border:1px solid var(--radio-button-border-color);background-color:var(--radio-button-background)}:host .f-radio-button-container .f-radio-button-inner-circle{position:absolute;top:calc(var(--radio-button-size) / 4);right:calc(var(--radio-button-size) / 4);bottom:calc(var(--radio-button-size) / 4);left:calc(var(--radio-button-size) / 4);border-radius:50%}:host label{-webkit-user-select:none;user-select:none}:host.f-radio-button-checked .f-radio-button-container{background-color:var(--radio-button-checked-background)}:host.f-radio-button-checked .f-radio-button-container .f-radio-button-inner-circle{background-color:var(--radio-button-inner-circle-color)}\n"] }]
236
- }], propDecorators: { preventBubblingFromLabel: [{
237
- type: HostListener,
238
- args: ['click', ['$event']]
239
- }] } });
240
-
241
121
  function provideHeader(...configuration) {
242
122
  return {
243
123
  header: Object.assign({}, ...configuration),
@@ -291,10 +171,10 @@ class PopoverService {
291
171
  this._message.set(message);
292
172
  setTimeout(() => this._message.set(null), timeout);
293
173
  }
294
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PopoverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
295
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PopoverService, providedIn: 'root' });
174
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PopoverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
175
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PopoverService, providedIn: 'root' });
296
176
  }
297
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PopoverService, decorators: [{
177
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PopoverService, decorators: [{
298
178
  type: Injectable,
299
179
  args: [{
300
180
  providedIn: 'root',
@@ -331,10 +211,10 @@ class ThemeService {
331
211
  _isDocumentContainsDarkTheme() {
332
212
  return this._docElement.classList.contains('dark');
333
213
  }
334
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
335
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ThemeService });
214
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
215
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ThemeService });
336
216
  }
337
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ThemeService, decorators: [{
217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ThemeService, decorators: [{
338
218
  type: Injectable
339
219
  }] });
340
220
 
@@ -384,28 +264,58 @@ class FHeadTagService {
384
264
  this._document.title = title || '';
385
265
  }
386
266
  setDescription(description) {
387
- const meta = this._getDescription() || this._createElement('meta');
388
- meta.setAttribute('name', 'description');
389
- meta.setAttribute('content', description);
390
- }
391
- _getDescription() {
392
- return this._document.querySelector(`meta[name="description"]`) || null;
267
+ this.updateNameTag({ name: 'description', content: description || '' });
393
268
  }
394
269
  setCanonical(url) {
395
- const link = this._getCanonical() || this._createElement('link');
396
- link.setAttribute('rel', 'canonical');
397
- link.setAttribute('href', url);
270
+ const normalizedUrl = (url || '').trim();
271
+ const link = this._getCanonical();
272
+ if (!normalizedUrl) {
273
+ if (link) {
274
+ link.remove();
275
+ }
276
+ return;
277
+ }
278
+ const canonicalLink = link || this._createElement('link');
279
+ canonicalLink.setAttribute('rel', 'canonical');
280
+ canonicalLink.setAttribute('href', normalizedUrl);
398
281
  }
399
282
  _getCanonical() {
400
283
  return this._document.querySelector(`link[rel="canonical"]`) || null;
401
284
  }
402
285
  updateTag(tag) {
403
- const meta = this._getMetaTag(tag) || this._createElement('meta');
404
- meta.setAttribute('property', tag.property);
405
- meta.setAttribute('content', tag.content);
286
+ this.updatePropertyTag(tag);
287
+ }
288
+ updatePropertyTag(tag) {
289
+ const normalizedContent = tag.content?.trim() || '';
290
+ const meta = this._getPropertyTag(tag.property);
291
+ if (!normalizedContent) {
292
+ if (meta) {
293
+ meta.remove();
294
+ }
295
+ return;
296
+ }
297
+ const targetMeta = meta || this._createElement('meta');
298
+ targetMeta.setAttribute('property', tag.property);
299
+ targetMeta.setAttribute('content', normalizedContent);
406
300
  }
407
- _getMetaTag(tag) {
408
- return this._document.querySelector(`meta[property="${tag.property}"]`) || null;
301
+ updateNameTag(tag) {
302
+ const normalizedContent = tag.content?.trim() || '';
303
+ const meta = this._getNameTag(tag.name);
304
+ if (!normalizedContent) {
305
+ if (meta) {
306
+ meta.remove();
307
+ }
308
+ return;
309
+ }
310
+ const targetMeta = meta || this._createElement('meta');
311
+ targetMeta.setAttribute('name', tag.name);
312
+ targetMeta.setAttribute('content', normalizedContent);
313
+ }
314
+ _getPropertyTag(property) {
315
+ return this._document.querySelector(`meta[property="${property}"]`) || null;
316
+ }
317
+ _getNameTag(name) {
318
+ return this._document.querySelector(`meta[name="${name}"]`) || null;
409
319
  }
410
320
  _createElement(tag) {
411
321
  const element = this._document.createElement(tag);
@@ -413,10 +323,10 @@ class FHeadTagService {
413
323
  head.appendChild(element);
414
324
  return element;
415
325
  }
416
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHeadTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
417
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHeadTagService, providedIn: 'root' });
326
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHeadTagService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
327
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHeadTagService, providedIn: 'root' });
418
328
  }
419
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHeadTagService, decorators: [{
329
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHeadTagService, decorators: [{
420
330
  type: Injectable,
421
331
  args: [{ providedIn: 'root' }]
422
332
  }] });
@@ -547,38 +457,55 @@ class FMetaService {
547
457
  _router = inject(Router);
548
458
  _headTag = inject(FHeadTagService);
549
459
  _configuration = inject(DOCUMENTATION_CONFIGURATION);
460
+ _seoOverrides = null;
461
+ _lastPath = '';
550
462
  changes() {
551
- return this._router.events.pipe(startWith(null), filter$1((e) => e === null || e instanceof NavigationEnd), map(() => this._router.url), tap((currentUrl) => {
552
- const defaultData = this._configuration.meta;
553
- if (!defaultData)
554
- return;
555
- const data = { ...defaultData };
556
- const item = this._findDocItemByUrl(this._findDocGroupByUrl(currentUrl), currentUrl);
557
- if (item) {
558
- data.title = `${item.pageTitle || item.text} | ${defaultData.app_name}`;
559
- data.url = this._buildAbsoluteUrl(currentUrl);
560
- data.canonical = item.canonical;
561
- data.description = item.description || defaultData.description;
562
- data.image = item.image || defaultData.image;
563
- data.image_width = item.image_width || defaultData.image_width;
564
- data.image_height = item.image_height || defaultData.image_height;
565
- data.image_type = item.image_type || defaultData.image_type;
463
+ return this._router.events.pipe(startWith(null), filter$1((e) => e === null || e instanceof NavigationEnd), map(() => this._normalizeCurrentPath(this._router.url)), tap((currentUrl) => {
464
+ if (this._lastPath !== currentUrl) {
465
+ this._seoOverrides = null;
466
+ this._lastPath = currentUrl;
566
467
  }
567
- if (!data.url) {
568
- data.url = this._buildAbsoluteUrl(currentUrl);
569
- }
570
- if (data.image) {
571
- data.image = this._toAbsoluteUrl(data.image);
572
- }
573
- this._updateMetaTags(data);
468
+ this._updateMetaByUrl(currentUrl);
574
469
  }));
575
470
  }
471
+ applyMarkdownSeo(overrides) {
472
+ this._seoOverrides = overrides ? { ...overrides } : null;
473
+ this._updateMetaByUrl(this._normalizeCurrentPath(this._router.url));
474
+ }
576
475
  dispose() {
476
+ this._seoOverrides = null;
477
+ this._lastPath = '';
577
478
  if (!this._configuration.meta) {
578
479
  return;
579
480
  }
580
481
  this._updateMetaTags(this._configuration.meta);
581
482
  }
483
+ _updateMetaByUrl(currentUrl) {
484
+ const defaultData = this._configuration.meta;
485
+ if (!defaultData) {
486
+ return;
487
+ }
488
+ const data = { ...defaultData };
489
+ const item = this._findDocItemByUrl(this._findDocGroupByUrl(currentUrl), currentUrl);
490
+ if (item) {
491
+ data.title = `${item.pageTitle || item.text} | ${defaultData.app_name}`;
492
+ data.url = this._buildAbsoluteUrl(currentUrl);
493
+ data.canonical = item.canonical;
494
+ data.description = item.description || defaultData.description;
495
+ data.image = item.image || defaultData.image;
496
+ data.image_width = item.image_width || defaultData.image_width;
497
+ data.image_height = item.image_height || defaultData.image_height;
498
+ data.image_type = item.image_type || defaultData.image_type;
499
+ }
500
+ if (!data.url) {
501
+ data.url = this._buildAbsoluteUrl(currentUrl);
502
+ }
503
+ data.url = this._toAbsoluteUrl(data.url);
504
+ if (data.image) {
505
+ data.image = this._toAbsoluteUrl(data.image);
506
+ }
507
+ this._updateMetaTags(data);
508
+ }
582
509
  _findDocGroupByUrl(url) {
583
510
  return (this._configuration.navigation || []).find((g) => g.items.find((i) => url.endsWith(i.link)));
584
511
  }
@@ -602,25 +529,72 @@ class FMetaService {
602
529
  }
603
530
  }
604
531
  _updateMetaTags(item) {
605
- this._headTag.setTitle(item.title);
606
- this._headTag.setDescription(item.description);
607
- this._headTag.setCanonical(item.canonical || item.url);
608
- this._headTag.updateTag({ property: 'og:url', content: item.url });
609
- this._headTag.updateTag({ property: 'og:type', content: item.type });
610
- this._headTag.updateTag({ property: 'og:title', content: item.title });
611
- this._headTag.updateTag({ property: 'og:site_name', content: item.title });
612
- this._headTag.updateTag({ property: 'og:locale', content: item.locale });
613
- this._headTag.updateTag({ property: 'og:description', content: item.description });
614
- this._headTag.updateTag({ property: 'og:image', content: item.image });
615
- this._headTag.updateTag({ property: 'og:image:secure_url', content: item.image });
616
- this._headTag.updateTag({ property: 'og:image:type', content: item.image_type });
617
- this._headTag.updateTag({ property: 'og:image:width', content: item.image_width.toString() });
618
- this._headTag.updateTag({ property: 'og:image:height', content: item.image_height.toString() });
619
- }
620
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FMetaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
621
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FMetaService });
622
- }
623
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FMetaService, decorators: [{
532
+ const seo = this._seoOverrides || null;
533
+ const title = seo?.title || item.title;
534
+ const description = seo?.description || item.description;
535
+ const url = this._toAbsoluteUrl(seo?.url || item.url);
536
+ const canonical = this._toAbsoluteUrl(seo?.canonical || item.canonical || url);
537
+ const type = seo?.og_type || seo?.type || item.type;
538
+ const siteName = seo?.app_name || item.app_name;
539
+ const locale = seo?.locale || item.locale;
540
+ const image = this._toAbsoluteUrl(seo?.og_image || seo?.image || item.image);
541
+ const imageType = seo?.image_type || item.image_type;
542
+ const imageWidth = seo?.image_width || item.image_width;
543
+ const imageHeight = seo?.image_height || item.image_height;
544
+ const keywords = seo?.keywords || item.keywords || '';
545
+ const robots = this._resolveRobots(item.robots, seo);
546
+ const twitterCard = seo?.twitter_card || item.twitter_card || 'summary_large_image';
547
+ const twitterSite = item.twitter_site || '';
548
+ const twitterCreator = item.twitter_creator || '';
549
+ const twitterTitle = seo?.twitter_title || seo?.og_title || title;
550
+ const twitterDescription = seo?.twitter_description || seo?.og_description || description;
551
+ const twitterImage = this._toAbsoluteUrl(seo?.twitter_image || image);
552
+ this._headTag.setTitle(title);
553
+ this._headTag.setDescription(description);
554
+ this._headTag.setCanonical(canonical);
555
+ this._headTag.updateTag({ property: 'og:url', content: url });
556
+ this._headTag.updateTag({ property: 'og:type', content: type });
557
+ this._headTag.updateTag({ property: 'og:title', content: seo?.og_title || title });
558
+ this._headTag.updateTag({ property: 'og:site_name', content: siteName });
559
+ this._headTag.updateTag({ property: 'og:locale', content: locale });
560
+ this._headTag.updateTag({ property: 'og:description', content: seo?.og_description || description });
561
+ this._headTag.updateTag({ property: 'og:image', content: image });
562
+ this._headTag.updateTag({ property: 'og:image:secure_url', content: image });
563
+ this._headTag.updateTag({ property: 'og:image:type', content: imageType });
564
+ this._headTag.updateTag({ property: 'og:image:width', content: imageWidth ? imageWidth.toString() : '' });
565
+ this._headTag.updateTag({ property: 'og:image:height', content: imageHeight ? imageHeight.toString() : '' });
566
+ this._headTag.updateNameTag({ name: 'keywords', content: keywords });
567
+ this._headTag.updateNameTag({ name: 'robots', content: robots });
568
+ this._headTag.updateNameTag({ name: 'twitter:card', content: twitterCard });
569
+ this._headTag.updateNameTag({ name: 'twitter:site', content: twitterSite });
570
+ this._headTag.updateNameTag({ name: 'twitter:creator', content: twitterCreator });
571
+ this._headTag.updateNameTag({ name: 'twitter:title', content: twitterTitle });
572
+ this._headTag.updateNameTag({ name: 'twitter:description', content: twitterDescription });
573
+ this._headTag.updateNameTag({ name: 'twitter:image', content: twitterImage });
574
+ }
575
+ _resolveRobots(defaultRobots, seo) {
576
+ if (seo?.robots) {
577
+ return seo.robots;
578
+ }
579
+ const hasDirectiveOverride = typeof seo?.noindex === 'boolean' || typeof seo?.nofollow === 'boolean';
580
+ if (!hasDirectiveOverride) {
581
+ return defaultRobots || '';
582
+ }
583
+ const indexValue = seo?.noindex ? 'noindex' : 'index';
584
+ const followValue = seo?.nofollow ? 'nofollow' : 'follow';
585
+ const defaultTokens = (defaultRobots || '')
586
+ .split(',')
587
+ .map((x) => x.trim())
588
+ .filter((x) => x && !['index', 'noindex', 'follow', 'nofollow'].includes(x.toLowerCase()));
589
+ return [indexValue, followValue, ...defaultTokens].join(', ');
590
+ }
591
+ _normalizeCurrentPath(url) {
592
+ return (url || '').split('#')[0].split('?')[0];
593
+ }
594
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FMetaService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
595
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FMetaService });
596
+ }
597
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FMetaService, decorators: [{
624
598
  type: Injectable
625
599
  }] });
626
600
 
@@ -633,14 +607,14 @@ class HamburgerButton {
633
607
  _onShowNavigation() {
634
608
  this._parent?.onToggleNavigation(true);
635
609
  }
636
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HamburgerButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
637
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: HamburgerButton, isStandalone: true, selector: "button[hamburger-button]", host: { listeners: { "click": "_onShowNavigation()" } }, ngImport: i0, template: "<span class=\"f-icon hamburger\"></span>\n\n", styles: [":host{background-color:transparent;border:0;display:flex;padding:0;margin-right:16px;color:var(--secondary-text);cursor:pointer}@media (min-width: 960px){:host{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
610
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HamburgerButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
611
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: HamburgerButton, isStandalone: true, selector: "button[hamburger-button]", host: { listeners: { "click": "_onShowNavigation()" } }, ngImport: i0, template: "<span class=\"f-icon hamburger\"></span>\n\n", styles: [":host{background-color:transparent;border:0;display:flex;padding:0;margin-right:16px;color:var(--secondary-text);cursor:pointer}@media(min-width:960px){:host{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
638
612
  }
639
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HamburgerButton, decorators: [{
613
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HamburgerButton, decorators: [{
640
614
  type: Component,
641
615
  args: [{ selector: 'button[hamburger-button]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
642
616
  '(click)': '_onShowNavigation()',
643
- }, template: "<span class=\"f-icon hamburger\"></span>\n\n", styles: [":host{background-color:transparent;border:0;display:flex;padding:0;margin-right:16px;color:var(--secondary-text);cursor:pointer}@media (min-width: 960px){:host{display:none}}\n"] }]
617
+ }, template: "<span class=\"f-icon hamburger\"></span>\n\n", styles: [":host{background-color:transparent;border:0;display:flex;padding:0;margin-right:16px;color:var(--secondary-text);cursor:pointer}@media(min-width:960px){:host{display:none}}\n"] }]
644
618
  }] });
645
619
 
646
620
  class HeaderMenuBase {
@@ -665,10 +639,10 @@ class HeaderMenuBase {
665
639
  }
666
640
 
667
641
  class InlineMenu extends HeaderMenuBase {
668
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: InlineMenu, deps: null, target: i0.ɵɵFactoryTarget.Component });
669
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: InlineMenu, isStandalone: true, selector: "inline-menu", usesInheritance: true, ngImport: i0, template: "@for (item of navigation(); track item.link) {\n <a [routerLink]=\"item.link\" [class.active]=\"item.isActive\">\n <span>{{ item.text }}</span>\n </a>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:center}a{padding:0 12px;font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}a:hover,a.active{color:var(--primary-1)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
642
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: InlineMenu, deps: null, target: i0.ɵɵFactoryTarget.Component });
643
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: InlineMenu, isStandalone: true, selector: "inline-menu", usesInheritance: true, ngImport: i0, template: "@for (item of navigation(); track item.link) {\n <a [routerLink]=\"item.link\" [class.active]=\"item.isActive\">\n <span>{{ item.text }}</span>\n </a>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:center}a{padding:0 12px;font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}a:hover,a.active{color:var(--primary-1)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
670
644
  }
671
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: InlineMenu, decorators: [{
645
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: InlineMenu, decorators: [{
672
646
  type: Component,
673
647
  args: [{ selector: 'inline-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
674
648
  RouterLink,
@@ -700,10 +674,10 @@ class ThemeButtonComponent {
700
674
  }
701
675
  this._themeService?.updateTheme();
702
676
  }
703
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ThemeButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
704
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: ThemeButtonComponent, isStandalone: true, selector: "button[theme-button]", host: { listeners: { "click": "_onClick()" } }, ngImport: i0, template: "<div class=\"f-icon-container\">\n <div class=\"f-icon moon\"></div>\n <div class=\"f-icon sun\"></div>\n</div>\n", styles: [":host{margin:0 8px;position:relative;border-radius:11px;display:block;width:44px;min-width:44px;height:22px;border:1px solid var(--theme-button-border-color);background-color:var(--theme-button-background);cursor:pointer}:host:hover{border-color:var(--theme-button-hovered-border-color)}.f-icon-container{position:absolute;top:1px;left:1px;width:18px;height:18px;padding:3px;border-radius:50%;background-color:var(--theme-button-icon-background);transition:transform .4s}.f-icon-container .f-icon{position:absolute;top:3px;left:3px;width:12px;height:12px}.f-icon-container .sun{display:block}.f-icon-container .moon{display:none}.dark :host .f-icon-container{transform:translate(22px)}.dark :host .f-icon-container .sun{display:none}.dark :host .f-icon-container .moon{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
677
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ThemeButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
678
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: ThemeButtonComponent, isStandalone: true, selector: "button[theme-button]", host: { listeners: { "click": "_onClick()" } }, ngImport: i0, template: "<div class=\"f-icon-container\">\n <div class=\"f-icon moon\"></div>\n <div class=\"f-icon sun\"></div>\n</div>\n", styles: [":host{margin:0 8px;position:relative;border-radius:11px;display:block;width:44px;min-width:44px;height:22px;border:1px solid var(--theme-button-border-color);background-color:var(--theme-button-background);cursor:pointer}:host:hover{border-color:var(--theme-button-hovered-border-color)}.f-icon-container{position:absolute;top:1px;left:1px;width:18px;height:18px;padding:3px;border-radius:50%;background-color:var(--theme-button-icon-background);transition:transform .4s}.f-icon-container .f-icon{position:absolute;top:3px;left:3px;width:12px;height:12px}.f-icon-container .sun{display:block}.f-icon-container .moon{display:none}.dark :host .f-icon-container{transform:translate(22px)}.dark :host .f-icon-container .sun{display:none}.dark :host .f-icon-container .moon{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
705
679
  }
706
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ThemeButtonComponent, decorators: [{
680
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ThemeButtonComponent, decorators: [{
707
681
  type: Component,
708
682
  args: [{ selector: 'button[theme-button]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"f-icon-container\">\n <div class=\"f-icon moon\"></div>\n <div class=\"f-icon sun\"></div>\n</div>\n", styles: [":host{margin:0 8px;position:relative;border-radius:11px;display:block;width:44px;min-width:44px;height:22px;border:1px solid var(--theme-button-border-color);background-color:var(--theme-button-background);cursor:pointer}:host:hover{border-color:var(--theme-button-hovered-border-color)}.f-icon-container{position:absolute;top:1px;left:1px;width:18px;height:18px;padding:3px;border-radius:50%;background-color:var(--theme-button-icon-background);transition:transform .4s}.f-icon-container .f-icon{position:absolute;top:3px;left:3px;width:12px;height:12px}.f-icon-container .sun{display:block}.f-icon-container .moon{display:none}.dark :host .f-icon-container{transform:translate(22px)}.dark :host .f-icon-container .sun{display:none}.dark :host .f-icon-container .moon{display:block}\n"] }]
709
683
  }], propDecorators: { _onClick: [{
@@ -724,10 +698,10 @@ const MEDIA_LINKS_PROVIDER = new InjectionToken('MEDIA_LINKS_PROVIDER');
724
698
 
725
699
  class MediaLinks {
726
700
  links = inject(MEDIA_LINKS_PROVIDER, { optional: true });
727
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MediaLinks, deps: [], target: i0.ɵɵFactoryTarget.Component });
728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: MediaLinks, isStandalone: true, selector: "media-links", ngImport: i0, template: "@for (link of links; track link.link) {\n <a href=\"{{ link.link }}\" class=\"header-link\">\n <div class=\"f-icon {{ link.icon }}\"></div>\n </a>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:center}.header-link{width:36px;height:36px;padding:8px}.f-icon{width:20px;height:20px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
701
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MediaLinks, deps: [], target: i0.ɵɵFactoryTarget.Component });
702
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: MediaLinks, isStandalone: true, selector: "media-links", ngImport: i0, template: "@for (link of links; track link.link) {\n <a href=\"{{ link.link }}\" class=\"header-link\">\n <div class=\"f-icon {{ link.icon }}\"></div>\n </a>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:center}.header-link{width:36px;height:36px;padding:8px}.f-icon{width:20px;height:20px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
729
703
  }
730
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MediaLinks, decorators: [{
704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MediaLinks, decorators: [{
731
705
  type: Component,
732
706
  args: [{ selector: 'media-links', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (link of links; track link.link) {\n <a href=\"{{ link.link }}\" class=\"header-link\">\n <div class=\"f-icon {{ link.icon }}\"></div>\n </a>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:center}.header-link{width:36px;height:36px;padding:8px}.f-icon{width:20px;height:20px}\n"] }]
733
707
  }] });
@@ -784,10 +758,10 @@ class DropdownMenu extends HeaderMenuBase {
784
758
  ngOnDestroy() {
785
759
  clearTimeout(this._hoverTimeout);
786
760
  }
787
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DropdownMenu, deps: null, target: i0.ɵɵFactoryTarget.Component });
788
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: DropdownMenu, isStandalone: true, selector: "dropdown-menu", usesInheritance: true, ngImport: i0, template: "<span class=\"label\" cdk-overlay-origin\n (click)=\"toggle()\"\n (mouseenter)=\"mouseEnter()\"\n (mouseleave)=\"mouseLeave()\"\n #overlayOrigin=\"cdkOverlayOrigin\">\n <span class=\"f-icon more-horizontal\"></span>\n</span>\n\n<ng-template\n cdk-connected-overlay\n [cdkConnectedOverlayLockPosition]=\"true\"\n [cdkConnectedOverlayHasBackdrop]=\"false\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayDisableClose]=\"false\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayOffsetY]=\"-10\"\n (backdropClick)=\"close()\"\n>\n <div class=\"dropdown-panel\"\n (mouseenter)=\"mouseEnter()\"\n (mouseleave)=\"mouseLeave()\">\n @if (navigation().length) {\n <div class=\"navigation-wrapper\">\n @for (item of navigation(); track item.link) {\n <a [routerLink]=\"item.link\" [class.active]=\"item.isActive\"><span>{{ item.text }}</span></a>\n }\n </div>\n }\n <div class=\"appearance\">\n <span>Appearance</span>\n <button theme-button></button>\n </div>\n <div class=\"social-links\">\n <media-links/>\n </div>\n\n </div>\n</ng-template>\n\n", styles: [":host{overflow:hidden}.label{margin-left:8px;margin-right:8px;display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;line-height:64px}.label .f-icon{margin-left:4px;width:14px;min-width:14px;height:14px;color:inherit}.label:hover{color:var(--secondary-text)}.dropdown-panel{border-radius:6px;min-width:202px;border:1px solid var(--divider-color);background-color:var(--background-color);box-shadow:var(--shadow-3);max-height:calc(100vh - var(--header-height));overflow-y:auto}.navigation-wrapper{display:flex;flex-direction:column;justify-content:flex-start;padding:12px;border-bottom:1px solid var(--divider-color)}.navigation-wrapper a{color:var(--primary-text);white-space:nowrap;border-radius:6px;padding:0 12px;font-size:14px;font-weight:500;line-height:32px;display:block;cursor:pointer;overflow:hidden;text-overflow:ellipsis}.navigation-wrapper a:hover{color:var(--primary-1);background-color:var(--default-3)}.navigation-wrapper a.active{color:var(--primary-1)}.appearance{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px 8px 24px;border-bottom:1px solid var(--divider-color)}.appearance span{color:var(--secondary-text);flex-grow:1;font-size:12px;font-weight:500;line-height:28px;transition:color .5s}.social-links{padding:6px 12px}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ThemeButtonComponent, selector: "button[theme-button]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: MediaLinks, selector: "media-links" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
761
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DropdownMenu, deps: null, target: i0.ɵɵFactoryTarget.Component });
762
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: DropdownMenu, isStandalone: true, selector: "dropdown-menu", usesInheritance: true, ngImport: i0, template: "<span class=\"label\" cdk-overlay-origin\n (click)=\"toggle()\"\n (mouseenter)=\"mouseEnter()\"\n (mouseleave)=\"mouseLeave()\"\n #overlayOrigin=\"cdkOverlayOrigin\">\n <span class=\"f-icon more-horizontal\"></span>\n</span>\n\n<ng-template\n cdk-connected-overlay\n [cdkConnectedOverlayLockPosition]=\"true\"\n [cdkConnectedOverlayHasBackdrop]=\"false\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayDisableClose]=\"false\"\n [cdkConnectedOverlayScrollStrategy]=\"scrollStrategy\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayOffsetY]=\"-10\"\n (backdropClick)=\"close()\"\n>\n <div class=\"dropdown-panel\"\n (mouseenter)=\"mouseEnter()\"\n (mouseleave)=\"mouseLeave()\">\n @if (navigation().length) {\n <div class=\"navigation-wrapper\">\n @for (item of navigation(); track item.link) {\n <a [routerLink]=\"item.link\" [class.active]=\"item.isActive\"><span>{{ item.text }}</span></a>\n }\n </div>\n }\n <div class=\"appearance\">\n <span>Appearance</span>\n <button theme-button></button>\n </div>\n <div class=\"social-links\">\n <media-links/>\n </div>\n\n </div>\n</ng-template>\n\n", styles: [":host{overflow:hidden}.label{margin-left:8px;margin-right:8px;display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;line-height:64px}.label .f-icon{margin-left:4px;width:14px;min-width:14px;height:14px;color:inherit}.label:hover{color:var(--secondary-text)}.dropdown-panel{border-radius:6px;min-width:202px;border:1px solid var(--divider-color);background-color:var(--background-color);box-shadow:var(--shadow-3);max-height:calc(100vh - var(--header-height));overflow-y:auto}.navigation-wrapper{display:flex;flex-direction:column;justify-content:flex-start;padding:12px;border-bottom:1px solid var(--divider-color)}.navigation-wrapper a{color:var(--primary-text);white-space:nowrap;border-radius:6px;padding:0 12px;font-size:14px;font-weight:500;line-height:32px;display:block;cursor:pointer;overflow:hidden;text-overflow:ellipsis}.navigation-wrapper a:hover{color:var(--primary-1);background-color:var(--default-3)}.navigation-wrapper a.active{color:var(--primary-1)}.appearance{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px 8px 24px;border-bottom:1px solid var(--divider-color)}.appearance span{color:var(--secondary-text);flex-grow:1;font-size:12px;font-weight:500;line-height:28px;transition:color .5s}.social-links{padding:6px 12px}\n"], dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: ThemeButtonComponent, selector: "button[theme-button]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: MediaLinks, selector: "media-links" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
789
763
  }
790
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DropdownMenu, decorators: [{
764
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DropdownMenu, decorators: [{
791
765
  type: Component,
792
766
  args: [{ selector: 'dropdown-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
793
767
  CdkConnectedOverlay,
@@ -850,10 +824,10 @@ class DocumentationStore {
850
824
  getShowcaseItems() {
851
825
  return this._configuration.showcaseItems || [];
852
826
  }
853
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DocumentationStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
854
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DocumentationStore });
827
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DocumentationStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
828
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DocumentationStore });
855
829
  }
856
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DocumentationStore, decorators: [{
830
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DocumentationStore, decorators: [{
857
831
  type: Injectable
858
832
  }] });
859
833
 
@@ -895,13 +869,149 @@ class DynamicComponentsStore {
895
869
  }
896
870
  return result;
897
871
  }
898
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DynamicComponentsStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
899
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DynamicComponentsStore });
872
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DynamicComponentsStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
873
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DynamicComponentsStore });
900
874
  }
901
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: DynamicComponentsStore, decorators: [{
875
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: DynamicComponentsStore, decorators: [{
902
876
  type: Injectable
903
877
  }] });
904
878
 
879
+ class FBrandLinkComponent {
880
+ title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
881
+ logo = input.required(...(ngDevMode ? [{ debugName: "logo" }] : []));
882
+ ariaLabel = input('Home', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
883
+ logoAlt = input('logo', ...(ngDevMode ? [{ debugName: "logoAlt" }] : []));
884
+ href = input('', ...(ngDevMode ? [{ debugName: "href" }] : []));
885
+ routerLink = input(null, ...(ngDevMode ? [{ debugName: "routerLink" }] : []));
886
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FBrandLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
887
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: FBrandLinkComponent, isStandalone: true, selector: "f-brand-link", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: true, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, logoAlt: { classPropertyName: "logoAlt", publicName: "logoAlt", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (routerLink() !== null) {\n <a [routerLink]=\"routerLink()!\" class=\"brand-link\" [attr.aria-label]=\"ariaLabel()\">\n <img [src]=\"logo()\" class=\"logo\" [alt]=\"logoAlt()\" width=\"24\" height=\"24\"/>\n <span class=\"title\">{{ title() }}</span>\n </a>\n} @else {\n <a [href]=\"href()\" class=\"brand-link\" [attr.aria-label]=\"ariaLabel()\">\n <img [src]=\"logo()\" class=\"logo\" [alt]=\"logoAlt()\" width=\"24\" height=\"24\"/>\n <span class=\"title\">{{ title() }}</span>\n </a>\n}\n", styles: [":host{display:inline-flex;min-width:0}.brand-link{display:flex;justify-content:flex-start;align-items:center;width:100%;min-width:0;text-decoration:none;color:inherit}.logo{margin-right:8px;flex-shrink:0}.title{display:inline-flex;align-items:center;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-bottom:1px solid transparent}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
888
+ }
889
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FBrandLinkComponent, decorators: [{
890
+ type: Component,
891
+ args: [{ selector: 'f-brand-link', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink], template: "@if (routerLink() !== null) {\n <a [routerLink]=\"routerLink()!\" class=\"brand-link\" [attr.aria-label]=\"ariaLabel()\">\n <img [src]=\"logo()\" class=\"logo\" [alt]=\"logoAlt()\" width=\"24\" height=\"24\"/>\n <span class=\"title\">{{ title() }}</span>\n </a>\n} @else {\n <a [href]=\"href()\" class=\"brand-link\" [attr.aria-label]=\"ariaLabel()\">\n <img [src]=\"logo()\" class=\"logo\" [alt]=\"logoAlt()\" width=\"24\" height=\"24\"/>\n <span class=\"title\">{{ title() }}</span>\n </a>\n}\n", styles: [":host{display:inline-flex;min-width:0}.brand-link{display:flex;justify-content:flex-start;align-items:center;width:100%;min-width:0;text-decoration:none;color:inherit}.logo{margin-right:8px;flex-shrink:0}.title{display:inline-flex;align-items:center;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-bottom:1px solid transparent}\n"] }]
892
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], logoAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoAlt", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], routerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "routerLink", required: false }] }] } });
893
+
894
+ class FSearchButtonComponent {
895
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FSearchButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
896
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: FSearchButtonComponent, isStandalone: true, selector: "f-search-button", ngImport: i0, template: "<a class=\"f-icon search\" [routerLink]=\"[]\" fragment=\"search\"></a>\n", styles: [".f-icon{display:block;width:20px;height:20px;margin-left:8px;color:var(--sponsor);cursor:pointer;transition:transform .2s ease}.f-icon:hover{transform:scale(1.1)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
897
+ }
898
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FSearchButtonComponent, decorators: [{
899
+ type: Component,
900
+ args: [{ selector: 'f-search-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
901
+ RouterLink,
902
+ ], template: "<a class=\"f-icon search\" [routerLink]=\"[]\" fragment=\"search\"></a>\n", styles: [".f-icon{display:block;width:20px;height:20px;margin-left:8px;color:var(--sponsor);cursor:pointer;transition:transform .2s ease}.f-icon:hover{transform:scale(1.1)}\n"] }]
903
+ }] });
904
+
905
+ let uniqueId$1 = 0;
906
+ class FCheckboxComponent {
907
+ changeDetectorRef;
908
+ id = `f-checkbox-${uniqueId$1++}`;
909
+ change = new EventEmitter();
910
+ inputElement;
911
+ labelElement;
912
+ get checked() {
913
+ return this.isChecked;
914
+ }
915
+ set checked(value) {
916
+ if (value != this.checked) {
917
+ this.isChecked = value;
918
+ this.changeDetectorRef.markForCheck();
919
+ }
920
+ }
921
+ isChecked = false;
922
+ constructor(changeDetectorRef) {
923
+ this.changeDetectorRef = changeDetectorRef;
924
+ }
925
+ onInputClick() {
926
+ this.handleInputClick();
927
+ }
928
+ onTouchTargetClick() {
929
+ this.handleInputClick();
930
+ this.inputElement?.nativeElement.focus();
931
+ }
932
+ handleInputClick() {
933
+ this.isChecked = !this.isChecked;
934
+ this.emitChangeEvent();
935
+ }
936
+ emitChangeEvent() {
937
+ this.change.emit(this.isChecked);
938
+ if (this.inputElement) {
939
+ this.inputElement.nativeElement.checked = this.isChecked;
940
+ }
941
+ }
942
+ onInteractionEvent(event) {
943
+ event.stopPropagation();
944
+ }
945
+ preventBubblingFromLabel(event) {
946
+ if (!!event.target && this.labelElement?.nativeElement.contains(event.target)) {
947
+ event.stopPropagation();
948
+ }
949
+ }
950
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FCheckboxComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
951
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.1.4", type: FCheckboxComponent, isStandalone: true, selector: "f-checkbox", inputs: { id: "id", checked: ["checked", "checked", booleanAttribute] }, outputs: { change: "change" }, host: { listeners: { "click": "preventBubblingFromLabel($event)" }, properties: { "class.f-checkbox-checked": "checked" } }, viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }, { propertyName: "labelElement", first: true, predicate: ["label"], descendants: true }], ngImport: i0, template: "<input #input\n [id]=\"id\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-checkbox-container\" (click)=\"onTouchTargetClick()\">\n <svg class=\"f-checkbox-checkmark\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path class=\"f-checkbox-checkmark-path\" fill=\"none\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\"/>\n </svg>\n</div>\n<label [for]=\"id\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--checkbox-container-background);border-radius:var(--checkbox-border-radius);padding:0 8px;color:var(--checkbox-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-checkbox-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--checkbox-size);height:var(--checkbox-size);margin-right:6px;border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background);padding:2px}:host .f-checkbox-container .f-checkbox-checkmark{position:absolute;top:calc(var(--checkbox-size) / 8);right:calc(var(--checkbox-size) / 8);bottom:calc(var(--checkbox-size) / 8);left:calc(var(--checkbox-size) / 8);opacity:0}:host .f-checkbox-container .f-checkbox-checkmark .f-checkbox-checkmark-path{stroke:currentColor;stroke-width:3}:host label{-webkit-user-select:none;user-select:none}:host.f-checkbox-checked .f-checkbox-container{background-color:var(--checkbox-checked-background)}:host.f-checkbox-checked .f-checkbox-container .f-checkbox-checkmark{color:var(--checkbox-checkmark-color);opacity:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
952
+ }
953
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FCheckboxComponent, decorators: [{
954
+ type: Component,
955
+ args: [{ selector: 'f-checkbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
956
+ '[class.f-checkbox-checked]': 'checked',
957
+ }, template: "<input #input\n [id]=\"id\"\n type=\"checkbox\"\n [checked]=\"checked\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-checkbox-container\" (click)=\"onTouchTargetClick()\">\n <svg class=\"f-checkbox-checkmark\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path class=\"f-checkbox-checkmark-path\" fill=\"none\" d=\"M1.73,12.91 8.1,19.28 22.79,4.59\"/>\n </svg>\n</div>\n<label [for]=\"id\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--checkbox-container-background);border-radius:var(--checkbox-border-radius);padding:0 8px;color:var(--checkbox-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-checkbox-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--checkbox-size);height:var(--checkbox-size);margin-right:6px;border-radius:var(--checkbox-border-radius);background-color:var(--checkbox-background);padding:2px}:host .f-checkbox-container .f-checkbox-checkmark{position:absolute;top:calc(var(--checkbox-size) / 8);right:calc(var(--checkbox-size) / 8);bottom:calc(var(--checkbox-size) / 8);left:calc(var(--checkbox-size) / 8);opacity:0}:host .f-checkbox-container .f-checkbox-checkmark .f-checkbox-checkmark-path{stroke:currentColor;stroke-width:3}:host label{-webkit-user-select:none;user-select:none}:host.f-checkbox-checked .f-checkbox-container{background-color:var(--checkbox-checked-background)}:host.f-checkbox-checked .f-checkbox-container .f-checkbox-checkmark{color:var(--checkbox-checkmark-color);opacity:1}\n"] }]
958
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { id: [{
959
+ type: Input
960
+ }], change: [{
961
+ type: Output
962
+ }], inputElement: [{
963
+ type: ViewChild,
964
+ args: ['input']
965
+ }], labelElement: [{
966
+ type: ViewChild,
967
+ args: ['label']
968
+ }], checked: [{
969
+ type: Input,
970
+ args: [{ transform: booleanAttribute }]
971
+ }], preventBubblingFromLabel: [{
972
+ type: HostListener,
973
+ args: ['click', ['$event']]
974
+ }] } });
975
+
976
+ let uniqueId = 0;
977
+ class FRadioButtonComponent {
978
+ id = input(`f-radio-button-${uniqueId++}`, ...(ngDevMode ? [{ debugName: "id" }] : []));
979
+ change = output();
980
+ checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
981
+ labelElement = viewChild('label', ...(ngDevMode ? [{ debugName: "labelElement" }] : []));
982
+ onInputClick() {
983
+ this._handleInputClick();
984
+ }
985
+ onTouchTargetClick() {
986
+ this._handleInputClick();
987
+ }
988
+ _handleInputClick() {
989
+ this._emitChangeEvent();
990
+ }
991
+ _emitChangeEvent() {
992
+ this.change.emit(true);
993
+ }
994
+ onInteractionEvent(event) {
995
+ event.stopPropagation();
996
+ }
997
+ preventBubblingFromLabel(event) {
998
+ if (!!event.target && this.labelElement()?.nativeElement.contains(event.target)) {
999
+ event.stopPropagation();
1000
+ }
1001
+ }
1002
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FRadioButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1003
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.4", type: FRadioButtonComponent, isStandalone: true, selector: "f-radio-button", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change" }, host: { listeners: { "click": "preventBubblingFromLabel($event)" }, properties: { "class.f-radio-button-checked": "checked()" } }, viewQueries: [{ propertyName: "labelElement", first: true, predicate: ["label"], descendants: true, isSignal: true }], ngImport: i0, template: "<input [id]=\"id()\"\n type=\"radio\"\n [checked]=\"checked()\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-radio-button-container\" (click)=\"onTouchTargetClick()\">\n <div class=\"f-radio-button-inner-circle\"></div>\n</div>\n<label [for]=\"id()\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--radio-button-container-background);border-radius:var(--radio-button-container-border-radius);padding:0 8px;color:var(--radio-button-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-radio-button-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--radio-button-size);height:var(--radio-button-size);margin-right:6px;border-radius:50%;border:1px solid var(--radio-button-border-color);background-color:var(--radio-button-background)}:host .f-radio-button-container .f-radio-button-inner-circle{position:absolute;top:calc(var(--radio-button-size) / 4);right:calc(var(--radio-button-size) / 4);bottom:calc(var(--radio-button-size) / 4);left:calc(var(--radio-button-size) / 4);border-radius:50%}:host label{-webkit-user-select:none;user-select:none}:host.f-radio-button-checked .f-radio-button-container{background-color:var(--radio-button-checked-background)}:host.f-radio-button-checked .f-radio-button-container .f-radio-button-inner-circle{background-color:var(--radio-button-inner-circle-color)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1004
+ }
1005
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FRadioButtonComponent, decorators: [{
1006
+ type: Component,
1007
+ args: [{ selector: 'f-radio-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1008
+ '[class.f-radio-button-checked]': 'checked()',
1009
+ }, template: "<input [id]=\"id()\"\n type=\"radio\"\n [checked]=\"checked()\"\n (click)=\"onInputClick()\"\n (change)=\"onInteractionEvent($event)\"/>\n<div class=\"f-radio-button-container\" (click)=\"onTouchTargetClick()\">\n <div class=\"f-radio-button-inner-circle\"></div>\n</div>\n<label [for]=\"id()\" #label>\n <ng-content></ng-content>\n</label>\n", styles: [":host{position:relative;display:flex;align-items:center;font-weight:400;white-space:nowrap;font-size:14px;cursor:pointer;background-color:var(--radio-button-container-background);border-radius:var(--radio-button-container-border-radius);padding:0 8px;color:var(--radio-button-text);transition:color .25s,background-color .25s}:host input{position:absolute;inset:0;opacity:0;cursor:pointer}:host .f-radio-button-container{position:relative;display:flex;align-items:center;justify-content:center;width:var(--radio-button-size);height:var(--radio-button-size);margin-right:6px;border-radius:50%;border:1px solid var(--radio-button-border-color);background-color:var(--radio-button-background)}:host .f-radio-button-container .f-radio-button-inner-circle{position:absolute;top:calc(var(--radio-button-size) / 4);right:calc(var(--radio-button-size) / 4);bottom:calc(var(--radio-button-size) / 4);left:calc(var(--radio-button-size) / 4);border-radius:50%}:host label{-webkit-user-select:none;user-select:none}:host.f-radio-button-checked .f-radio-button-container{background-color:var(--radio-button-checked-background)}:host.f-radio-button-checked .f-radio-button-container .f-radio-button-inner-circle{background-color:var(--radio-button-inner-circle-color)}\n"] }]
1010
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], change: [{ type: i0.Output, args: ["change"] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], labelElement: [{ type: i0.ViewChild, args: ['label', { isSignal: true }] }], preventBubblingFromLabel: [{
1011
+ type: HostListener,
1012
+ args: ['click', ['$event']]
1013
+ }] } });
1014
+
905
1015
  class HeaderComponent {
906
1016
  title = inject(DocumentationStore).getTitle();
907
1017
  image = inject(DocumentationStore).getLogo();
@@ -962,22 +1072,20 @@ class HeaderComponent {
962
1072
  if (this._rafId != null)
963
1073
  cancelAnimationFrame(this._rafId);
964
1074
  }
965
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
966
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: HeaderComponent, isStandalone: true, selector: "f-header", viewQueries: [{ propertyName: "_containerRef", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "_targetRef", first: true, predicate: ["target"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (emptyNavigation) {\n <a routerLink class=\"empty-navigation-title\">\n <img [src]=\"image\" width=\"24\" height=\"24\" alt=\"logo\" class=\"logo\"/> {{ title }}\n </a>\n} @else {\n <div class=\"portal-title\">\n <button hamburger-button></button>\n <div class=\"title text-ellipsis\">{{ title }}</div>\n </div>\n}\n\n<div class=\"collapsable-row\" #container>\n <div #target class=\"target\" [class.hidden]=\"initialized() && overflowed()\">\n @if (config.navigation) {\n <inline-menu />\n <div class=\"divider\"></div>\n }\n\n <button theme-button></button>\n <div class=\"divider\"></div>\n <media-links />\n </div>\n\n <div class=\"fallback\" [class.hidden]=\"!initialized() || !overflowed()\">\n <dropdown-menu />\n </div>\n</div>\n\n", styles: [":host{position:sticky;width:100%;top:0;display:flex;justify-content:flex-start;align-items:center;padding:0 32px;font-weight:600;color:var(--primary-text);height:calc(var(--header-height) + 1px);background-color:var(--background-color);border-bottom:1px solid var(--divider-color);z-index:var(--z-index-header)}@media (min-width: 1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media (min-width: 1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}.empty-navigation-title{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.empty-navigation-title img{margin-right:8px}.portal-title{display:flex;justify-content:flex-start;align-items:center}@media (min-width: 960px){.portal-title{display:none}}.portal-title .title{font-weight:600;color:var(--primary-text)}.divider{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--divider-color);content:\"\"}.collapsable-row{position:relative;width:100%;display:flex;justify-content:flex-end}.collapsable-row .target{display:flex;justify-content:flex-start;align-items:center;width:fit-content}.collapsable-row .target.hidden{position:absolute;left:-99999px;top:0;visibility:hidden;white-space:nowrap}.collapsable-row .fallback.hidden{display:none}\n"], dependencies: [{ kind: "component", type: HamburgerButton, selector: "button[hamburger-button]" }, { kind: "component", type: ThemeButtonComponent, selector: "button[theme-button]" }, { kind: "component", type: InlineMenu, selector: "inline-menu" }, { kind: "component", type: DropdownMenu, selector: "dropdown-menu" }, { kind: "component", type: MediaLinks, selector: "media-links" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1075
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1076
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: HeaderComponent, isStandalone: true, selector: "f-header", viewQueries: [{ propertyName: "_containerRef", first: true, predicate: ["container"], descendants: true, isSignal: true }, { propertyName: "_targetRef", first: true, predicate: ["target"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (emptyNavigation) {\n <f-brand-link class=\"empty-navigation-title\"\n [routerLink]=\"''\"\n [title]=\"title\"\n [logo]=\"image\" />\n} @else {\n <div class=\"portal-title\">\n <button hamburger-button></button>\n <div class=\"title text-ellipsis\">{{ title }}</div>\n </div>\n}\n\n<div class=\"collapsable-row\" #container>\n <div #target class=\"target\" [class.hidden]=\"initialized() && overflowed()\">\n @if (config.navigation) {\n <inline-menu />\n <div class=\"divider\"></div>\n }\n\n <button theme-button></button>\n <div class=\"divider\"></div>\n <media-links />\n </div>\n\n <div class=\"fallback\" [class.hidden]=\"!initialized() || !overflowed()\">\n <dropdown-menu />\n </div>\n</div>\n", styles: [":host{position:sticky;width:100%;top:0;display:flex;justify-content:flex-start;align-items:center;padding:0 32px;font-weight:600;color:var(--primary-text);height:calc(var(--header-height) + 1px);background-color:var(--background-color);border-bottom:1px solid var(--divider-color);z-index:var(--z-index-header)}@media(min-width:1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media(min-width:1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}.empty-navigation-title{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.portal-title{display:flex;justify-content:flex-start;align-items:center}@media(min-width:960px){.portal-title{display:none}}.portal-title .title{font-weight:600;color:var(--primary-text)}.divider{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--divider-color);content:\"\"}.collapsable-row{position:relative;width:100%;display:flex;justify-content:flex-end}.collapsable-row .target{display:flex;justify-content:flex-start;align-items:center;width:fit-content}.collapsable-row .target.hidden{position:absolute;left:-99999px;top:0;visibility:hidden;white-space:nowrap}.collapsable-row .fallback.hidden{display:none}\n"], dependencies: [{ kind: "component", type: HamburgerButton, selector: "button[hamburger-button]" }, { kind: "component", type: FBrandLinkComponent, selector: "f-brand-link", inputs: ["title", "logo", "ariaLabel", "logoAlt", "href", "routerLink"] }, { kind: "component", type: ThemeButtonComponent, selector: "button[theme-button]" }, { kind: "component", type: InlineMenu, selector: "inline-menu" }, { kind: "component", type: DropdownMenu, selector: "dropdown-menu" }, { kind: "component", type: MediaLinks, selector: "media-links" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
967
1077
  }
968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HeaderComponent, decorators: [{
1078
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HeaderComponent, decorators: [{
969
1079
  type: Component,
970
1080
  args: [{ selector: 'f-header', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
971
1081
  HamburgerButton,
1082
+ FBrandLinkComponent,
972
1083
  ThemeButtonComponent,
973
1084
  InlineMenu,
974
1085
  DropdownMenu,
975
- InlineMenu,
976
1086
  MediaLinks,
977
- DropdownMenu,
978
- RouterLink,
979
- ], template: "@if (emptyNavigation) {\n <a routerLink class=\"empty-navigation-title\">\n <img [src]=\"image\" width=\"24\" height=\"24\" alt=\"logo\" class=\"logo\"/> {{ title }}\n </a>\n} @else {\n <div class=\"portal-title\">\n <button hamburger-button></button>\n <div class=\"title text-ellipsis\">{{ title }}</div>\n </div>\n}\n\n<div class=\"collapsable-row\" #container>\n <div #target class=\"target\" [class.hidden]=\"initialized() && overflowed()\">\n @if (config.navigation) {\n <inline-menu />\n <div class=\"divider\"></div>\n }\n\n <button theme-button></button>\n <div class=\"divider\"></div>\n <media-links />\n </div>\n\n <div class=\"fallback\" [class.hidden]=\"!initialized() || !overflowed()\">\n <dropdown-menu />\n </div>\n</div>\n\n", styles: [":host{position:sticky;width:100%;top:0;display:flex;justify-content:flex-start;align-items:center;padding:0 32px;font-weight:600;color:var(--primary-text);height:calc(var(--header-height) + 1px);background-color:var(--background-color);border-bottom:1px solid var(--divider-color);z-index:var(--z-index-header)}@media (min-width: 1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media (min-width: 1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}.empty-navigation-title{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.empty-navigation-title img{margin-right:8px}.portal-title{display:flex;justify-content:flex-start;align-items:center}@media (min-width: 960px){.portal-title{display:none}}.portal-title .title{font-weight:600;color:var(--primary-text)}.divider{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--divider-color);content:\"\"}.collapsable-row{position:relative;width:100%;display:flex;justify-content:flex-end}.collapsable-row .target{display:flex;justify-content:flex-start;align-items:center;width:fit-content}.collapsable-row .target.hidden{position:absolute;left:-99999px;top:0;visibility:hidden;white-space:nowrap}.collapsable-row .fallback.hidden{display:none}\n"] }]
980
- }] });
1087
+ ], template: "@if (emptyNavigation) {\n <f-brand-link class=\"empty-navigation-title\"\n [routerLink]=\"''\"\n [title]=\"title\"\n [logo]=\"image\" />\n} @else {\n <div class=\"portal-title\">\n <button hamburger-button></button>\n <div class=\"title text-ellipsis\">{{ title }}</div>\n </div>\n}\n\n<div class=\"collapsable-row\" #container>\n <div #target class=\"target\" [class.hidden]=\"initialized() && overflowed()\">\n @if (config.navigation) {\n <inline-menu />\n <div class=\"divider\"></div>\n }\n\n <button theme-button></button>\n <div class=\"divider\"></div>\n <media-links />\n </div>\n\n <div class=\"fallback\" [class.hidden]=\"!initialized() || !overflowed()\">\n <dropdown-menu />\n </div>\n</div>\n", styles: [":host{position:sticky;width:100%;top:0;display:flex;justify-content:flex-start;align-items:center;padding:0 32px;font-weight:600;color:var(--primary-text);height:calc(var(--header-height) + 1px);background-color:var(--background-color);border-bottom:1px solid var(--divider-color);z-index:var(--z-index-header)}@media(min-width:1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media(min-width:1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}.empty-navigation-title{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.portal-title{display:flex;justify-content:flex-start;align-items:center}@media(min-width:960px){.portal-title{display:none}}.portal-title .title{font-weight:600;color:var(--primary-text)}.divider{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--divider-color);content:\"\"}.collapsable-row{position:relative;width:100%;display:flex;justify-content:flex-end}.collapsable-row .target{display:flex;justify-content:flex-start;align-items:center;width:fit-content}.collapsable-row .target.hidden{position:absolute;left:-99999px;top:0;visibility:hidden;white-space:nowrap}.collapsable-row .fallback.hidden{display:none}\n"] }]
1088
+ }], propDecorators: { _containerRef: [{ type: i0.ViewChild, args: ['container', { isSignal: true }] }], _targetRef: [{ type: i0.ViewChild, args: ['target', { isSignal: true }] }] } });
981
1089
 
982
1090
  class NavigationGroupComponent {
983
1091
  title = input(undefined, ...(ngDevMode ? [{ debugName: "title" }] : []));
@@ -985,22 +1093,22 @@ class NavigationGroupComponent {
985
1093
  toggle() {
986
1094
  this.isCollapsed.set(!this.isCollapsed());
987
1095
  }
988
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NavigationGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
989
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: NavigationGroupComponent, isStandalone: true, selector: "f-navigation-group", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.collapsed": "isCollapsed()", "class.no-title": "!title()" } }, ngImport: i0, template: "@if (title()) {\n <header (click)=\"toggle()\">\n <span>{{ title() }}</span>\n <div class=\"flex-space\"></div>\n <div class=\"caret\">\n <span class=\"chevron-right caret-icon\"></span>\n </div>\n </header>\n}\n@if (!isCollapsed()) {\n <ng-content></ng-content>\n}\n\n\n\n", styles: [":host{padding-top:10px;padding-bottom:24px;border-top:1px solid var(--divider-color);display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;width:100%;max-width:240px;margin-left:auto}:host.collapsed,:host.no-title{padding-top:10px;padding-bottom:10px}header{font-weight:600;color:var(--primary-text);flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;cursor:pointer;display:flex;justify-content:flex-start;align-items:center;width:100%}.caret{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--tertiary-text);cursor:pointer;transition:color .25s;flex-shrink:0}:host:hover .caret{color:var(--secondary-text)}:host:hover .caret:hover{color:var(--primary-text)}:host .caret-icon{font-size:18px;transform:rotate(90deg);transition:transform .25s;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:18px;height:18px}:host.collapsed .caret-icon{transform:rotate(0)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1096
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: NavigationGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1097
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: NavigationGroupComponent, isStandalone: true, selector: "f-navigation-group", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.collapsed": "isCollapsed()", "class.no-title": "!title()" } }, ngImport: i0, template: "@if (title()) {\n <header (click)=\"toggle()\">\n <span>{{ title() }}</span>\n <div class=\"flex-space\"></div>\n <div class=\"caret\">\n <span class=\"chevron-right caret-icon\"></span>\n </div>\n </header>\n}\n@if (!isCollapsed()) {\n <ng-content></ng-content>\n}\n\n\n\n", styles: [":host{padding-top:10px;padding-bottom:24px;border-top:1px solid var(--divider-color);display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;width:100%;max-width:240px;margin-left:auto}:host.collapsed,:host.no-title{padding-top:10px;padding-bottom:10px}header{font-weight:600;color:var(--primary-text);flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;cursor:pointer;display:flex;justify-content:flex-start;align-items:center;width:100%}.caret{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--tertiary-text);cursor:pointer;transition:color .25s;flex-shrink:0}:host:hover .caret{color:var(--secondary-text)}:host:hover .caret:hover{color:var(--primary-text)}:host .caret-icon{font-size:18px;transform:rotate(90deg);transition:transform .25s;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:18px;height:18px}:host.collapsed .caret-icon{transform:rotate(0)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
990
1098
  }
991
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NavigationGroupComponent, decorators: [{
1099
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: NavigationGroupComponent, decorators: [{
992
1100
  type: Component,
993
1101
  args: [{ selector: 'f-navigation-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
994
1102
  '[class.collapsed]': 'isCollapsed()',
995
1103
  '[class.no-title]': '!title()',
996
1104
  }, template: "@if (title()) {\n <header (click)=\"toggle()\">\n <span>{{ title() }}</span>\n <div class=\"flex-space\"></div>\n <div class=\"caret\">\n <span class=\"chevron-right caret-icon\"></span>\n </div>\n </header>\n}\n@if (!isCollapsed()) {\n <ng-content></ng-content>\n}\n\n\n\n", styles: [":host{padding-top:10px;padding-bottom:24px;border-top:1px solid var(--divider-color);display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;width:100%;max-width:240px;margin-left:auto}:host.collapsed,:host.no-title{padding-top:10px;padding-bottom:10px}header{font-weight:600;color:var(--primary-text);flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;cursor:pointer;display:flex;justify-content:flex-start;align-items:center;width:100%}.caret{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--tertiary-text);cursor:pointer;transition:color .25s;flex-shrink:0}:host:hover .caret{color:var(--secondary-text)}:host:hover .caret:hover{color:var(--primary-text)}:host .caret-icon{font-size:18px;transform:rotate(90deg);transition:transform .25s;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;width:18px;height:18px}:host.collapsed .caret-icon{transform:rotate(0)}\n"] }]
997
- }] });
1105
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }] } });
998
1106
 
999
1107
  class FNavigationItemComponent {
1000
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FNavigationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1001
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: FNavigationItemComponent, isStandalone: true, selector: "a[f-navigation-item]", ngImport: i0, template: "<ng-content></ng-content>\n\n\n\n", styles: [":host{font-weight:500;color:var(--secondary-text);flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;cursor:pointer;width:100%;display:flex;align-items:center;justify-content:flex-start;gap:2px}:host:hover{text-decoration:none;color:var(--primary-1)}:host.active{color:var(--primary-1)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1108
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FNavigationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1109
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: FNavigationItemComponent, isStandalone: true, selector: "a[f-navigation-item]", ngImport: i0, template: "<ng-content></ng-content>\n\n\n\n", styles: [":host{font-weight:500;color:var(--secondary-text);flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;cursor:pointer;width:100%;display:flex;align-items:center;justify-content:flex-start;gap:2px}:host:hover{text-decoration:none;color:var(--primary-1)}:host.active{color:var(--primary-1)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1002
1110
  }
1003
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FNavigationItemComponent, decorators: [{
1111
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FNavigationItemComponent, decorators: [{
1004
1112
  type: Component,
1005
1113
  args: [{ selector: 'a[f-navigation-item]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>\n\n\n\n", styles: [":host{font-weight:500;color:var(--secondary-text);flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;cursor:pointer;width:100%;display:flex;align-items:center;justify-content:flex-start;gap:2px}:host:hover{text-decoration:none;color:var(--primary-1)}:host.active{color:var(--primary-1)}\n"] }]
1006
1114
  }] });
@@ -1064,16 +1172,16 @@ class NavigationPanelComponent {
1064
1172
  _onDocumentClick(event) {
1065
1173
  new HandleNavigationLinksHandler().handle(new HandleNavigationLinksRequest(event, this._window, this._router));
1066
1174
  }
1067
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NavigationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1068
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: NavigationPanelComponent, isStandalone: true, selector: "f-navigation-panel", host: { listeners: { "click": "_onDocumentClick($event)" } }, ngImport: i0, template: "<a routerLink class=\"navigation-header\">\n <img [src]=\"image\" width=\"24\" height=\"24\" alt=\"logo\" class=\"logo\"/> {{ title }}\n</a>\n\n@for (group of navigation; track group) {\n <f-navigation-group [title]=\"group.text\">\n @for (item of group.items; track item.link) {\n <a f-navigation-item [href]=\"item.link\" [class.active]=\"item.link === value\">\n <div class=\"text-ellipsis\">{{ item.text }}</div>\n @if (item.badge) {\n <span class=\"f-badge {{ item.badge.type }}\">{{ item.badge.text }}</span>\n }\n </a>\n }\n </f-navigation-group>\n}\n\n", styles: [":host{height:100%;flex-direction:column;justify-content:flex-start;align-items:flex-start;padding:0 var(--navigation-panel-padding);background-color:var(--navigation-panel-background);overflow:hidden;overflow-y:auto;position:fixed;width:var(--navigation-panel-width);top:0;left:calc(-1 * var(--navigation-panel-width));transition:transform .2s ease-in-out;z-index:var(--z-index-navigation);transform:none}@media (min-width: 960px){:host{position:unset;display:flex;min-width:var(--navigation-panel-width);width:fit-content;transform:none!important}}@media (min-width: 1440px){:host{min-width:calc((100% - (var(--layout-max-width) - 64px)) / 3 + var(--navigation-panel-width) - var(--navigation-panel-padding))}}:host.visible{transform:translate(var(--navigation-panel-width))}.navigation-header{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.navigation-header img{margin-right:8px}\n"], dependencies: [{ kind: "component", type: FNavigationItemComponent, selector: "a[f-navigation-item]" }, { kind: "component", type: NavigationGroupComponent, selector: "f-navigation-group", inputs: ["title"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1175
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: NavigationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1176
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: NavigationPanelComponent, isStandalone: true, selector: "f-navigation-panel", host: { listeners: { "click": "_onDocumentClick($event)" } }, ngImport: i0, template: "<a routerLink class=\"navigation-header\">\n <img [src]=\"image\" width=\"24\" height=\"24\" alt=\"logo\" class=\"logo\"/> {{ title }}\n</a>\n\n@for (group of navigation; track group) {\n <f-navigation-group [title]=\"group.text\">\n @for (item of group.items; track item.link) {\n <a f-navigation-item [href]=\"item.link\" [class.active]=\"item.link === value\">\n <div class=\"text-ellipsis\">{{ item.text }}</div>\n @if (item.badge) {\n <span class=\"f-badge {{ item.badge.type }}\">{{ item.badge.text }}</span>\n }\n </a>\n }\n </f-navigation-group>\n}\n\n", styles: [":host{height:100%;flex-direction:column;justify-content:flex-start;align-items:flex-start;padding:0 var(--navigation-panel-padding);background-color:var(--navigation-panel-background);overflow:hidden;overflow-y:auto;position:fixed;width:var(--navigation-panel-width);top:0;left:calc(-1 * var(--navigation-panel-width));transition:transform .2s ease-in-out;z-index:var(--z-index-navigation);transform:none}@media(min-width:960px){:host{position:unset;display:flex;min-width:var(--navigation-panel-width);width:fit-content;transform:none!important}}@media(min-width:1440px){:host{min-width:calc((100% - (var(--layout-max-width) - 64px)) / 3 + var(--navigation-panel-width) - var(--navigation-panel-padding))}}:host.visible{transform:translate(var(--navigation-panel-width))}.navigation-header{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.navigation-header img{margin-right:8px}\n"], dependencies: [{ kind: "component", type: FNavigationItemComponent, selector: "a[f-navigation-item]" }, { kind: "component", type: NavigationGroupComponent, selector: "f-navigation-group", inputs: ["title"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1069
1177
  }
1070
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: NavigationPanelComponent, decorators: [{
1178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: NavigationPanelComponent, decorators: [{
1071
1179
  type: Component,
1072
1180
  args: [{ selector: 'f-navigation-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1073
1181
  FNavigationItemComponent,
1074
1182
  NavigationGroupComponent,
1075
1183
  RouterLink,
1076
- ], template: "<a routerLink class=\"navigation-header\">\n <img [src]=\"image\" width=\"24\" height=\"24\" alt=\"logo\" class=\"logo\"/> {{ title }}\n</a>\n\n@for (group of navigation; track group) {\n <f-navigation-group [title]=\"group.text\">\n @for (item of group.items; track item.link) {\n <a f-navigation-item [href]=\"item.link\" [class.active]=\"item.link === value\">\n <div class=\"text-ellipsis\">{{ item.text }}</div>\n @if (item.badge) {\n <span class=\"f-badge {{ item.badge.type }}\">{{ item.badge.text }}</span>\n }\n </a>\n }\n </f-navigation-group>\n}\n\n", styles: [":host{height:100%;flex-direction:column;justify-content:flex-start;align-items:flex-start;padding:0 var(--navigation-panel-padding);background-color:var(--navigation-panel-background);overflow:hidden;overflow-y:auto;position:fixed;width:var(--navigation-panel-width);top:0;left:calc(-1 * var(--navigation-panel-width));transition:transform .2s ease-in-out;z-index:var(--z-index-navigation);transform:none}@media (min-width: 960px){:host{position:unset;display:flex;min-width:var(--navigation-panel-width);width:fit-content;transform:none!important}}@media (min-width: 1440px){:host{min-width:calc((100% - (var(--layout-max-width) - 64px)) / 3 + var(--navigation-panel-width) - var(--navigation-panel-padding))}}:host.visible{transform:translate(var(--navigation-panel-width))}.navigation-header{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.navigation-header img{margin-right:8px}\n"] }]
1184
+ ], template: "<a routerLink class=\"navigation-header\">\n <img [src]=\"image\" width=\"24\" height=\"24\" alt=\"logo\" class=\"logo\"/> {{ title }}\n</a>\n\n@for (group of navigation; track group) {\n <f-navigation-group [title]=\"group.text\">\n @for (item of group.items; track item.link) {\n <a f-navigation-item [href]=\"item.link\" [class.active]=\"item.link === value\">\n <div class=\"text-ellipsis\">{{ item.text }}</div>\n @if (item.badge) {\n <span class=\"f-badge {{ item.badge.type }}\">{{ item.badge.text }}</span>\n }\n </a>\n }\n </f-navigation-group>\n}\n\n", styles: [":host{height:100%;flex-direction:column;justify-content:flex-start;align-items:flex-start;padding:0 var(--navigation-panel-padding);background-color:var(--navigation-panel-background);overflow:hidden;overflow-y:auto;position:fixed;width:var(--navigation-panel-width);top:0;left:calc(-1 * var(--navigation-panel-width));transition:transform .2s ease-in-out;z-index:var(--z-index-navigation);transform:none}@media(min-width:960px){:host{position:unset;display:flex;min-width:var(--navigation-panel-width);width:fit-content;transform:none!important}}@media(min-width:1440px){:host{min-width:calc((100% - (var(--layout-max-width) - 64px)) / 3 + var(--navigation-panel-width) - var(--navigation-panel-padding))}}:host.visible{transform:translate(var(--navigation-panel-width))}.navigation-header{display:flex;justify-content:flex-start;align-items:center;padding:20px 0;font-weight:600;color:var(--primary-text);height:var(--header-height);width:100%;max-width:240px;margin-left:auto;cursor:pointer}.navigation-header img{margin-right:8px}\n"] }]
1077
1185
  }], propDecorators: { _onDocumentClick: [{
1078
1186
  type: HostListener,
1079
1187
  args: ['click', ['$event']]
@@ -1134,10 +1242,10 @@ class GetPreviousNextPageNavigationRequest {
1134
1242
  class FooterNavigationButton {
1135
1243
  description;
1136
1244
  link;
1137
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FooterNavigationButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
1138
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: FooterNavigationButton, isStandalone: true, selector: "a[footer-navigation-button]", inputs: { description: "description", link: "link" }, ngImport: i0, template: "<span class=\"description\">{{ description }}</span>\n<span class=\"page-title\">{{ link.text }}</span>\n", styles: [":host{display:block;border:1px solid var(--divider-color);border-radius:2px;padding:12px 16px;flex:1;max-width:50%;min-width:260px;text-decoration:none!important;cursor:pointer;pointer-events:all}:host:hover{border-color:var(--dark-divider-color)}:host:active{border-color:var(--primary-1)}:host.next{margin-left:auto;text-align:right}:host .description{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);pointer-events:none}:host .page-title{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--primary-1);pointer-events:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1245
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FooterNavigationButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
1246
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: FooterNavigationButton, isStandalone: true, selector: "a[footer-navigation-button]", inputs: { description: "description", link: "link" }, ngImport: i0, template: "<span class=\"description\">{{ description }}</span>\n<span class=\"page-title\">{{ link.text }}</span>\n", styles: [":host{display:block;border:1px solid var(--divider-color);border-radius:2px;padding:12px 16px;flex:1;max-width:50%;min-width:260px;text-decoration:none!important;cursor:pointer;pointer-events:all}:host:hover{border-color:var(--dark-divider-color)}:host:active{border-color:var(--primary-1)}:host.next{margin-left:auto;text-align:right}:host .description{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);pointer-events:none}:host .page-title{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--primary-1);pointer-events:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1139
1247
  }
1140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FooterNavigationButton, decorators: [{
1248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FooterNavigationButton, decorators: [{
1141
1249
  type: Component,
1142
1250
  args: [{ selector: 'a[footer-navigation-button]', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<span class=\"description\">{{ description }}</span>\n<span class=\"page-title\">{{ link.text }}</span>\n", styles: [":host{display:block;border:1px solid var(--divider-color);border-radius:2px;padding:12px 16px;flex:1;max-width:50%;min-width:260px;text-decoration:none!important;cursor:pointer;pointer-events:all}:host:hover{border-color:var(--dark-divider-color)}:host:active{border-color:var(--primary-1)}:host.next{margin-left:auto;text-align:right}:host .description{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);pointer-events:none}:host .page-title{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--primary-1);pointer-events:none}\n"] }]
1143
1251
  }], propDecorators: { description: [{
@@ -1196,14 +1304,14 @@ class MarkdownFooter {
1196
1304
  _click(event) {
1197
1305
  new HandleNavigationLinksHandler().handle(new HandleNavigationLinksRequest(event, this._window, this._router));
1198
1306
  }
1199
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1200
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: MarkdownFooter, isStandalone: true, selector: "markdown-footer", host: { listeners: { "click": "_click($event)" } }, ngImport: i0, template: "@let eLink = editLink();\n@let pLink = previousLink();\n@let nLink = nextLink();\n\n@if (eLink) {\n <a class=\"footer-edit-link\" [href]=\"eLink\">\n <span class=\"edit-link-icon f-icon edit\"></span>\n {{ navigation.editLink?.text || 'Edit this page on GitHub' }}\n </a>\n}\n\n@if (pLink || nLink) {\n <nav class=\"footer-navigation\">\n @if (pLink) {\n <a footer-navigation-button\n [href]=\"pLink.link\"\n [description]=\"navigation.previous\"\n [link]=\"pLink\">\n </a>\n }\n @if (nLink) {\n <a footer-navigation-button class=\"next\"\n [href]=\"nLink.link\"\n [description]=\"navigation.next\"\n [link]=\"nLink\">\n </a>\n }\n </nav>\n}\n\n", styles: [":host{display:block;margin-top:64px}.footer-edit-link{display:flex;width:fit-content;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--primary-1);cursor:pointer;padding-bottom:18px}.footer-edit-link .edit-link-icon{margin-right:8px;width:14px;height:14px;color:inherit}.footer-edit-link:hover{color:var(--primary-2)}@media (min-width: 640px){.footer-edit-link{padding-bottom:14px}}.footer-navigation{border-top:1px solid var(--divider-color);padding-top:24px;display:flex;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap;gap:16px}\n"], dependencies: [{ kind: "component", type: FooterNavigationButton, selector: "a[footer-navigation-button]", inputs: ["description", "link"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1307
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1308
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: MarkdownFooter, isStandalone: true, selector: "markdown-footer", host: { listeners: { "click": "_click($event)" } }, ngImport: i0, template: "@let eLink = editLink();\n@let pLink = previousLink();\n@let nLink = nextLink();\n\n@if (eLink) {\n <a class=\"footer-edit-link\" [href]=\"eLink\">\n <span class=\"edit-link-icon f-icon edit\"></span>\n {{ navigation.editLink?.text || 'Edit this page on GitHub' }}\n </a>\n}\n\n@if (pLink || nLink) {\n <nav class=\"footer-navigation\">\n @if (pLink) {\n <a footer-navigation-button\n [href]=\"pLink.link\"\n [description]=\"navigation.previous\"\n [link]=\"pLink\">\n </a>\n }\n @if (nLink) {\n <a footer-navigation-button class=\"next\"\n [href]=\"nLink.link\"\n [description]=\"navigation.next\"\n [link]=\"nLink\">\n </a>\n }\n </nav>\n}\n\n", styles: [":host{display:block;margin-top:64px}.footer-edit-link{display:flex;width:fit-content;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--primary-1);cursor:pointer;padding-bottom:18px}.footer-edit-link .edit-link-icon{margin-right:8px;width:14px;height:14px;color:inherit}.footer-edit-link:hover{color:var(--primary-2)}@media(min-width:640px){.footer-edit-link{padding-bottom:14px}}.footer-navigation{border-top:1px solid var(--divider-color);padding-top:24px;display:flex;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap;gap:16px}\n"], dependencies: [{ kind: "component", type: FooterNavigationButton, selector: "a[footer-navigation-button]", inputs: ["description", "link"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1201
1309
  }
1202
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownFooter, decorators: [{
1310
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownFooter, decorators: [{
1203
1311
  type: Component,
1204
1312
  args: [{ selector: 'markdown-footer', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1205
1313
  FooterNavigationButton,
1206
- ], standalone: true, template: "@let eLink = editLink();\n@let pLink = previousLink();\n@let nLink = nextLink();\n\n@if (eLink) {\n <a class=\"footer-edit-link\" [href]=\"eLink\">\n <span class=\"edit-link-icon f-icon edit\"></span>\n {{ navigation.editLink?.text || 'Edit this page on GitHub' }}\n </a>\n}\n\n@if (pLink || nLink) {\n <nav class=\"footer-navigation\">\n @if (pLink) {\n <a footer-navigation-button\n [href]=\"pLink.link\"\n [description]=\"navigation.previous\"\n [link]=\"pLink\">\n </a>\n }\n @if (nLink) {\n <a footer-navigation-button class=\"next\"\n [href]=\"nLink.link\"\n [description]=\"navigation.next\"\n [link]=\"nLink\">\n </a>\n }\n </nav>\n}\n\n", styles: [":host{display:block;margin-top:64px}.footer-edit-link{display:flex;width:fit-content;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--primary-1);cursor:pointer;padding-bottom:18px}.footer-edit-link .edit-link-icon{margin-right:8px;width:14px;height:14px;color:inherit}.footer-edit-link:hover{color:var(--primary-2)}@media (min-width: 640px){.footer-edit-link{padding-bottom:14px}}.footer-navigation{border-top:1px solid var(--divider-color);padding-top:24px;display:flex;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap;gap:16px}\n"] }]
1314
+ ], standalone: true, template: "@let eLink = editLink();\n@let pLink = previousLink();\n@let nLink = nextLink();\n\n@if (eLink) {\n <a class=\"footer-edit-link\" [href]=\"eLink\">\n <span class=\"edit-link-icon f-icon edit\"></span>\n {{ navigation.editLink?.text || 'Edit this page on GitHub' }}\n </a>\n}\n\n@if (pLink || nLink) {\n <nav class=\"footer-navigation\">\n @if (pLink) {\n <a footer-navigation-button\n [href]=\"pLink.link\"\n [description]=\"navigation.previous\"\n [link]=\"pLink\">\n </a>\n }\n @if (nLink) {\n <a footer-navigation-button class=\"next\"\n [href]=\"nLink.link\"\n [description]=\"navigation.next\"\n [link]=\"nLink\">\n </a>\n }\n </nav>\n}\n\n", styles: [":host{display:block;margin-top:64px}.footer-edit-link{display:flex;width:fit-content;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--primary-1);cursor:pointer;padding-bottom:18px}.footer-edit-link .edit-link-icon{margin-right:8px;width:14px;height:14px;color:inherit}.footer-edit-link:hover{color:var(--primary-2)}@media(min-width:640px){.footer-edit-link{padding-bottom:14px}}.footer-navigation{border-top:1px solid var(--divider-color);padding-top:24px;display:flex;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap;gap:16px}\n"] }]
1207
1315
  }], propDecorators: { _click: [{
1208
1316
  type: HostListener,
1209
1317
  args: ['click', ['$event']]
@@ -1230,12 +1338,21 @@ var EParsedContainerType;
1230
1338
 
1231
1339
  const F_PREVIEW_NAVIGATION_PROVIDER = new InjectionToken('F_PREVIEW_NAVIGATION_PROVIDER');
1232
1340
 
1341
+ const DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS = {
1342
+ hideTableOfContent: false,
1343
+ expandContentWithoutTableOfContent: false,
1344
+ };
1345
+
1233
1346
  class MarkdownService {
1234
1347
  _markdown = new MarkdownIt({ html: true, linkify: true });
1235
1348
  _httpClient = inject(HttpClient);
1236
1349
  _domSanitizer = inject(DomSanitizer);
1237
1350
  _router = inject(Router);
1238
1351
  _provider = inject(F_PREVIEW_NAVIGATION_PROVIDER, { optional: true });
1352
+ _pageLayout = signal({ ...DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS }, ...(ngDevMode ? [{ debugName: "_pageLayout" }] : []));
1353
+ _pageSeo = signal(null, ...(ngDevMode ? [{ debugName: "_pageSeo" }] : []));
1354
+ pageLayout = this._pageLayout.asReadonly();
1355
+ pageSeo = this._pageSeo.asReadonly();
1239
1356
  constructor() {
1240
1357
  this._markdown
1241
1358
  .use((x) => new ParseSingleCodeItem().render(x))
@@ -1243,7 +1360,6 @@ class MarkdownService {
1243
1360
  .use(...new ParseAlerts().render(EMarkdownContainerType.ALERT_INFO, this._markdown))
1244
1361
  .use(...new ParseAlerts().render(EMarkdownContainerType.ALERT_WARNING, this._markdown))
1245
1362
  .use(...new ParseAlerts().render(EMarkdownContainerType.ALERT_DANGER, this._markdown))
1246
- .use(...new ParseAlerts().render(EMarkdownContainerType.ALERT_DANGER, this._markdown))
1247
1363
  .use(...new ParseAlerts().render(EMarkdownContainerType.ALERT_SUCCESS, this._markdown))
1248
1364
  .use(...new ParseGroupedCodeItems().render())
1249
1365
  .use(...new ParsePreviewGroup(this._provider?.getNavigation() || []).render())
@@ -1251,10 +1367,12 @@ class MarkdownService {
1251
1367
  .use(...new ParseAngularExampleWithCodeLinks().render());
1252
1368
  }
1253
1369
  parseUrl(src) {
1254
- return this._httpClient.get(src, { responseType: 'text' }).pipe(take(1), catchError(() => of(''))).pipe(switchMap((text) => of(this._markdown.render(text))), switchMap((x) => of(this._cleanupEmptyParagraphs(x))), switchMap((x) => of(this._cleanupWasteParagraphFromExampleView(x))), switchMap((x) => of(this._cleanupWasteParagraphFromPreviewGroup(x))), switchMap((x) => of(this._normalizeLinks(x))), switchMap((x) => of(this._domSanitizer.bypassSecurityTrustHtml(x))));
1370
+ this._resetPageContext();
1371
+ return this._httpClient.get(src, { responseType: 'text' }).pipe(take(1), catchError(() => of(''))).pipe(switchMap((text) => of(this._renderMarkdownWithPageContext(text))), switchMap((x) => of(this._cleanupEmptyParagraphs(x))), switchMap((x) => of(this._cleanupWasteParagraphFromExampleView(x))), switchMap((x) => of(this._cleanupWasteParagraphFromPreviewGroup(x))), switchMap((x) => of(this._normalizeLinks(x))), switchMap((x) => of(this._domSanitizer.bypassSecurityTrustHtml(x))));
1255
1372
  }
1256
1373
  parseText(value) {
1257
- return of(this._markdown.render(value)).pipe(switchMap((x) => of(this._cleanupEmptyParagraphs(x))), switchMap((x) => of(this._cleanupWasteParagraphFromExampleView(x))), switchMap((x) => of(this._cleanupWasteParagraphFromPreviewGroup(x))), switchMap((x) => of(this._normalizeLinks(x))), switchMap((x) => of(this._domSanitizer.bypassSecurityTrustHtml(x))));
1374
+ this._resetPageContext();
1375
+ return of(this._renderMarkdownWithPageContext(value)).pipe(switchMap((x) => of(this._cleanupEmptyParagraphs(x))), switchMap((x) => of(this._cleanupWasteParagraphFromExampleView(x))), switchMap((x) => of(this._cleanupWasteParagraphFromPreviewGroup(x))), switchMap((x) => of(this._normalizeLinks(x))), switchMap((x) => of(this._domSanitizer.bypassSecurityTrustHtml(x))));
1258
1376
  }
1259
1377
  _normalizeLinks(html) {
1260
1378
  const currentPath = this._router.url;
@@ -1282,10 +1400,204 @@ class MarkdownService {
1282
1400
  _cleanupWasteParagraphFromPreviewGroup(html) {
1283
1401
  return html.replace(/<p>(\[[^\]]+\](\s*\[[^\]]+\])*)<\/p>/g, '');
1284
1402
  }
1285
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1286
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownService });
1403
+ _renderMarkdownWithPageContext(markdown) {
1404
+ const result = this._parseFrontMatter(markdown);
1405
+ this._applyPageContext(result.data);
1406
+ return this._markdown.render(result.markdown);
1407
+ }
1408
+ _parseFrontMatter(markdown) {
1409
+ const source = (markdown || '').replace(/^\uFEFF/, '');
1410
+ const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
1411
+ const defaults = this._getDefaultFrontMatterData();
1412
+ if (!match || !match[1].includes(':')) {
1413
+ return {
1414
+ markdown: source,
1415
+ data: defaults,
1416
+ };
1417
+ }
1418
+ const rawFrontMatter = match[1];
1419
+ const parsedData = this._parseFrontMatterData(rawFrontMatter);
1420
+ return {
1421
+ markdown: source.slice(match[0].length),
1422
+ data: parsedData,
1423
+ };
1424
+ }
1425
+ _parseFrontMatterData(rawFrontMatter) {
1426
+ const layout = { ...DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS };
1427
+ const seo = {};
1428
+ rawFrontMatter
1429
+ .split(/\r?\n/)
1430
+ .forEach((line) => this._parseFrontMatterLine(line, layout, seo));
1431
+ return {
1432
+ layout,
1433
+ seo: Object.keys(seo).length ? seo : null,
1434
+ };
1435
+ }
1436
+ _parseFrontMatterLine(line, layout, seo) {
1437
+ const normalizedLine = line.trim();
1438
+ if (!normalizedLine || normalizedLine.startsWith('#')) {
1439
+ return;
1440
+ }
1441
+ const separatorIndex = normalizedLine.indexOf(':');
1442
+ if (separatorIndex < 0) {
1443
+ return;
1444
+ }
1445
+ const key = normalizedLine.slice(0, separatorIndex).trim().toLowerCase();
1446
+ const value = this._normalizeFrontMatterValue(normalizedLine.slice(separatorIndex + 1));
1447
+ if (!key || !value) {
1448
+ return;
1449
+ }
1450
+ const boolValue = this._parseBoolean(value);
1451
+ this._applyLayoutKey(key, boolValue, layout);
1452
+ this._applySeoKey(key, value, boolValue, seo);
1453
+ }
1454
+ _normalizeFrontMatterValue(value) {
1455
+ const trimmed = value.trim();
1456
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith('\'') && trimmed.endsWith('\''))) {
1457
+ return trimmed.slice(1, -1).trim();
1458
+ }
1459
+ return trimmed;
1460
+ }
1461
+ _parseBoolean(value) {
1462
+ const normalized = value.toLowerCase();
1463
+ if (['true', '1', 'yes', 'on'].includes(normalized)) {
1464
+ return true;
1465
+ }
1466
+ if (['false', '0', 'no', 'off'].includes(normalized)) {
1467
+ return false;
1468
+ }
1469
+ return null;
1470
+ }
1471
+ _applyLayoutKey(key, boolValue, layout) {
1472
+ if (boolValue === null) {
1473
+ return;
1474
+ }
1475
+ switch (key) {
1476
+ case 'toc':
1477
+ case 'showtoc':
1478
+ case 'tableofcontent':
1479
+ case 'table_of_content':
1480
+ layout.hideTableOfContent = !boolValue;
1481
+ return;
1482
+ case 'hidetoc':
1483
+ case 'hide_toc':
1484
+ layout.hideTableOfContent = boolValue;
1485
+ return;
1486
+ case 'widecontent':
1487
+ case 'expandcontent':
1488
+ case 'expandwithouttoc':
1489
+ case 'expand_no_toc':
1490
+ case 'widetableofcontentgap':
1491
+ layout.expandContentWithoutTableOfContent = boolValue;
1492
+ return;
1493
+ }
1494
+ }
1495
+ _applySeoKey(key, value, boolValue, seo) {
1496
+ switch (key) {
1497
+ case 'title':
1498
+ case 'seotitle':
1499
+ seo.title = value;
1500
+ return;
1501
+ case 'description':
1502
+ case 'seodescription':
1503
+ seo.description = value;
1504
+ return;
1505
+ case 'canonical':
1506
+ case 'seocanonical':
1507
+ seo.canonical = value;
1508
+ return;
1509
+ case 'keywords':
1510
+ case 'seokeywords':
1511
+ seo.keywords = value;
1512
+ return;
1513
+ case 'robots':
1514
+ case 'seorobots':
1515
+ seo.robots = value;
1516
+ return;
1517
+ case 'image':
1518
+ case 'seoimage':
1519
+ seo.image = value;
1520
+ return;
1521
+ case 'imagetype':
1522
+ case 'image_type':
1523
+ seo.image_type = value;
1524
+ return;
1525
+ case 'imagewidth':
1526
+ case 'image_width':
1527
+ seo.image_width = this._parseNumberOrDefault(value, seo.image_width);
1528
+ return;
1529
+ case 'imageheight':
1530
+ case 'image_height':
1531
+ seo.image_height = this._parseNumberOrDefault(value, seo.image_height);
1532
+ return;
1533
+ case 'ogtype':
1534
+ case 'og_type':
1535
+ seo.og_type = value;
1536
+ return;
1537
+ case 'ogtitle':
1538
+ case 'og_title':
1539
+ seo.og_title = value;
1540
+ return;
1541
+ case 'ogdescription':
1542
+ case 'og_description':
1543
+ seo.og_description = value;
1544
+ return;
1545
+ case 'ogimage':
1546
+ case 'og_image':
1547
+ seo.og_image = value;
1548
+ return;
1549
+ case 'twittercard':
1550
+ case 'twitter_card':
1551
+ seo.twitter_card = value;
1552
+ return;
1553
+ case 'twittertitle':
1554
+ case 'twitter_title':
1555
+ seo.twitter_title = value;
1556
+ return;
1557
+ case 'twitterdescription':
1558
+ case 'twitter_description':
1559
+ seo.twitter_description = value;
1560
+ return;
1561
+ case 'twitterimage':
1562
+ case 'twitter_image':
1563
+ seo.twitter_image = value;
1564
+ return;
1565
+ case 'noindex':
1566
+ if (boolValue !== null) {
1567
+ seo.noindex = boolValue;
1568
+ }
1569
+ return;
1570
+ case 'nofollow':
1571
+ if (boolValue !== null) {
1572
+ seo.nofollow = boolValue;
1573
+ }
1574
+ return;
1575
+ }
1576
+ }
1577
+ _parseNumberOrDefault(value, fallback) {
1578
+ const numericValue = Number(value);
1579
+ if (!Number.isFinite(numericValue) || numericValue <= 0) {
1580
+ return fallback;
1581
+ }
1582
+ return numericValue;
1583
+ }
1584
+ _applyPageContext(data) {
1585
+ this._pageLayout.set({ ...data.layout });
1586
+ this._pageSeo.set(data.seo ? { ...data.seo } : null);
1587
+ }
1588
+ _resetPageContext() {
1589
+ this._applyPageContext(this._getDefaultFrontMatterData());
1590
+ }
1591
+ _getDefaultFrontMatterData() {
1592
+ return {
1593
+ layout: { ...DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS },
1594
+ seo: null,
1595
+ };
1596
+ }
1597
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1598
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownService });
1287
1599
  }
1288
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownService, decorators: [{
1600
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownService, decorators: [{
1289
1601
  type: Injectable
1290
1602
  }], ctorParameters: () => [] });
1291
1603
 
@@ -1315,8 +1627,20 @@ function isClosingToken(token) {
1315
1627
  return token.nesting === -1;
1316
1628
  }
1317
1629
  function parseFileLinkLine(line) {
1318
- const match = line.match(/\[(.+?)\] <<< (.+)/);
1319
- return match ? { fileName: match[1], url: match[2] } : null;
1630
+ const match = line.match(/\[(.+?)\]\s*<<<\s*(.+)/);
1631
+ if (!match)
1632
+ return null;
1633
+ const fileName = match[1].trim();
1634
+ let url = match[2].trim();
1635
+ const markdownLink = url.match(/^\[[^\]]+]\((.+)\)$/);
1636
+ if (markdownLink) {
1637
+ url = markdownLink[1].trim();
1638
+ }
1639
+ const angleWrapped = url.match(/^<(.+)>$/);
1640
+ if (angleWrapped) {
1641
+ url = angleWrapped[1].trim();
1642
+ }
1643
+ return url ? { fileName, url } : null;
1320
1644
  }
1321
1645
  function parseSingleBracketText(line) {
1322
1646
  const match = line.match(/\[(.+?)\]/);
@@ -1382,7 +1706,7 @@ class ParseGroupedCodeItems {
1382
1706
  return data.match(/\[(.*)\]/)?.[1] || this._getCodeLanguage(data) || 'txt';
1383
1707
  }
1384
1708
  _getCodeLanguage(data) {
1385
- const match = data.trim().match(/^([a-zA-Z0-9_-]+)\s*\[.*\]$/);
1709
+ const match = data.trim().match(/^([a-zA-Z0-9_-]+)/);
1386
1710
  return match ? match[1] : '';
1387
1711
  }
1388
1712
  }
@@ -1425,14 +1749,14 @@ class ParseAngularExampleWithCodeLinks {
1425
1749
  }
1426
1750
  _collectData(tokens, index) {
1427
1751
  const result = [];
1428
- const component = this._parseNgComponent(tokens[index]);
1429
- const height = component?.height || 'auto';
1430
- if (component) {
1752
+ const source = this._parseNgComponent(tokens[index]);
1753
+ const height = source?.height || 'auto';
1754
+ if (source) {
1431
1755
  result.push({
1432
1756
  tab: 'Example',
1433
- value: component.tag,
1757
+ value: source.value,
1434
1758
  type: EParsedContainerType.EXAMPLE,
1435
- height: component.height || 'auto',
1759
+ height,
1436
1760
  });
1437
1761
  }
1438
1762
  const content = getContent(tokens, index, EMarkdownContainerType.EXAMPLE_GROUP);
@@ -1447,16 +1771,40 @@ class ParseAngularExampleWithCodeLinks {
1447
1771
  return result;
1448
1772
  }
1449
1773
  _parseNgComponent(token) {
1450
- const cleanedInput = token.info.replace(/ng-component\s*/, '');
1451
- const tagMatch = cleanedInput.match(/<([a-zA-Z0-9-]+)>.*<\/\1>/);
1452
- const heightMatch = cleanedInput.match(/\[height\]="(\d+)"/);
1453
- if (!tagMatch)
1774
+ const cleanedInput = token.info.replace(/^ng-component\s*/, '').trim();
1775
+ const height = this._parseHeight(cleanedInput);
1776
+ const componentTag = cleanedInput.match(/<([a-zA-Z][a-zA-Z0-9-]*)(\s[^>]*)?>\s*<\/\1>/s)?.[0]?.trim();
1777
+ if (componentTag) {
1778
+ return {
1779
+ value: componentTag,
1780
+ height,
1781
+ };
1782
+ }
1783
+ const explicitUrl = cleanedInput.match(/\[url\]=["']([^"']+)["']/)?.[1]?.trim();
1784
+ if (explicitUrl) {
1785
+ return {
1786
+ value: explicitUrl,
1787
+ height,
1788
+ };
1789
+ }
1790
+ const implicitUrl = cleanedInput
1791
+ .replace(/\[height\]=["'][^"']*["']/g, '')
1792
+ .trim()
1793
+ .replace(/^["']|["']$/g, '');
1794
+ if (!implicitUrl || implicitUrl.includes('<'))
1454
1795
  return null;
1455
1796
  return {
1456
- tag: tagMatch[0],
1457
- height: heightMatch?.[1],
1797
+ value: implicitUrl,
1798
+ height,
1458
1799
  };
1459
1800
  }
1801
+ _parseHeight(input) {
1802
+ const rawHeight = input.match(/\[height\]=["']([^"']+)["']/)?.[1]?.trim();
1803
+ if (!rawHeight)
1804
+ return undefined;
1805
+ const numericHeight = Number(rawHeight);
1806
+ return Number.isFinite(numericHeight) ? numericHeight : rawHeight;
1807
+ }
1460
1808
  }
1461
1809
 
1462
1810
  class ParsePreviewGroup {
@@ -1534,10 +1882,10 @@ class Mediatr {
1534
1882
  const handler = this._injector.get(handlerType);
1535
1883
  return handler.handle(request);
1536
1884
  }
1537
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Mediatr, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1538
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Mediatr });
1885
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Mediatr, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1886
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Mediatr });
1539
1887
  }
1540
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Mediatr, decorators: [{
1888
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Mediatr, decorators: [{
1541
1889
  type: Injectable
1542
1890
  }] });
1543
1891
 
@@ -1548,19 +1896,54 @@ function MExecution(requestType) {
1548
1896
  }
1549
1897
 
1550
1898
  function coerceComponentHeight$1(value) {
1551
- if (value === undefined) {
1899
+ if (value === undefined || value === null) {
1900
+ return undefined;
1901
+ }
1902
+ if (typeof value === 'number') {
1903
+ return Number.isFinite(value) && value > 0 ? `${value}px` : undefined;
1904
+ }
1905
+ const normalizedValue = value.trim();
1906
+ if (!normalizedValue)
1552
1907
  return undefined;
1908
+ if (normalizedValue === 'auto')
1909
+ return 'auto';
1910
+ const numericValue = Number(normalizedValue);
1911
+ if (Number.isFinite(numericValue) && numericValue > 0) {
1912
+ return `${numericValue}px`;
1553
1913
  }
1554
- value = Number(value);
1555
- if (value) {
1556
- return value + 'px';
1914
+ if (/^-?\d+(\.\d+)?(px|%|vh|vw|vmin|vmax|rem|em|ch|ex|cm|mm|in|pt|pc)$/i.test(normalizedValue)) {
1915
+ return normalizedValue;
1916
+ }
1917
+ if (/^calc\(.+\)$/i.test(normalizedValue)) {
1918
+ return normalizedValue;
1557
1919
  }
1558
1920
  return undefined;
1559
1921
  }
1560
1922
 
1923
+ const URL_PROTOCOL_REGEX = /^(https?:\/\/|\/\/|\/(?!\/)|\.\.?\/)/i;
1924
+ const BARE_DOMAIN_REGEX = /^(localhost(?::\d+)?|([a-z0-9-]+\.)+[a-z]{2,})(\/.*)?$/i;
1925
+ const UNSAFE_PROTOCOL_REGEX = /^(javascript|data|vbscript):/i;
1926
+ function parseIframeUrl(value) {
1927
+ if (!value)
1928
+ return null;
1929
+ const normalizedValue = value.trim();
1930
+ const urlFromAttr = normalizedValue.match(/\[url\]=["']([^"']+)["']/)?.[1]?.trim();
1931
+ const candidate = (urlFromAttr || normalizedValue).replace(/^["']|["']$/g, '').trim();
1932
+ if (!candidate || candidate.includes('<') || UNSAFE_PROTOCOL_REGEX.test(candidate)) {
1933
+ return null;
1934
+ }
1935
+ if (URL_PROTOCOL_REGEX.test(candidate)) {
1936
+ return candidate;
1937
+ }
1938
+ if (BARE_DOMAIN_REGEX.test(candidate)) {
1939
+ return `https://${candidate}`;
1940
+ }
1941
+ return null;
1942
+ }
1943
+
1561
1944
  function parseComponentTag(html) {
1562
- const regex = /^<([a-zA-Z0-9-]+)(\s+[^>]+)?><\/\1>$/;
1563
- const match = regex.exec(html);
1945
+ const regex = /^<([a-zA-Z][a-zA-Z0-9-]*)(\s+[^>]+)?>\s*<\/\1>$/s;
1946
+ const match = regex.exec(html.trim());
1564
1947
  return match ? match[1] : null;
1565
1948
  }
1566
1949
 
@@ -1588,12 +1971,13 @@ let RenderDynamicComponent = class RenderDynamicComponent {
1588
1971
  }
1589
1972
  _renderComponent({ selector, component }, viewContainerRef, element) {
1590
1973
  component.then(extracted => {
1591
- const componentRef = viewContainerRef.createComponent(extracted);
1592
- this._dynamicStore.addComponent(componentRef, element);
1593
- element?.replaceWith(this._extractComponentRoot(componentRef));
1594
1974
  if (!extracted) {
1595
1975
  this._logComponentResolutionError(selector);
1976
+ return;
1596
1977
  }
1978
+ const componentRef = viewContainerRef.createComponent(extracted);
1979
+ this._dynamicStore.addComponent(componentRef, element);
1980
+ element?.replaceWith(this._extractComponentRoot(componentRef));
1597
1981
  }).catch(error => this._logComponentLoadingError(selector, error));
1598
1982
  }
1599
1983
  _extractComponentRoot(componentRef) {
@@ -1609,13 +1993,13 @@ let RenderDynamicComponent = class RenderDynamicComponent {
1609
1993
  _logError(tag, error) {
1610
1994
  console.error(`Error inserting component for <${tag}>:`, error);
1611
1995
  }
1612
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderDynamicComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1613
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderDynamicComponent });
1996
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderDynamicComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1997
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderDynamicComponent });
1614
1998
  };
1615
1999
  RenderDynamicComponent = __decorate([
1616
2000
  MExecution(RenderDynamicComponentRequest)
1617
2001
  ], RenderDynamicComponent);
1618
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderDynamicComponent, decorators: [{
2002
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderDynamicComponent, decorators: [{
1619
2003
  type: Injectable
1620
2004
  }] });
1621
2005
 
@@ -1635,21 +2019,26 @@ let RenderExternalComponent = class RenderExternalComponent {
1635
2019
  _mediatr = inject(Mediatr);
1636
2020
  _componentsMap = inject(EXTERNAL_COMPONENT_PROVIDER, { optional: true }) ?? [];
1637
2021
  handle({ selector, viewContainerRef }) {
2022
+ if (!selector) {
2023
+ console.warn('Empty selector passed to RenderExternalComponentRequest.');
2024
+ return;
2025
+ }
1638
2026
  const item = this._componentsMap.find((x) => {
1639
2027
  return x.selector === selector;
1640
2028
  });
1641
2029
  if (!item) {
1642
- throw new Error(`Component for tag "${selector}" could not be found in external components map.`);
2030
+ console.error(`Component for tag "${selector}" could not be found in external components map.`);
2031
+ return;
1643
2032
  }
1644
2033
  this._mediatr.execute(new RenderDynamicComponentRequest(item, viewContainerRef));
1645
2034
  }
1646
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderExternalComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1647
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderExternalComponent });
2035
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderExternalComponent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2036
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderExternalComponent });
1648
2037
  };
1649
2038
  RenderExternalComponent = __decorate([
1650
2039
  MExecution(RenderExternalComponentRequest)
1651
2040
  ], RenderExternalComponent);
1652
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderExternalComponent, decorators: [{
2041
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderExternalComponent, decorators: [{
1653
2042
  type: Injectable
1654
2043
  }] });
1655
2044
 
@@ -1695,45 +2084,85 @@ let RenderInternalComponents = class RenderInternalComponents {
1695
2084
  _queryElements(hostElement, selector) {
1696
2085
  return Array.from(hostElement.querySelectorAll(selector));
1697
2086
  }
1698
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderInternalComponents, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1699
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderInternalComponents });
2087
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderInternalComponents, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2088
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderInternalComponents });
1700
2089
  };
1701
2090
  RenderInternalComponents = __decorate([
1702
2091
  MExecution(RenderInternalComponentsRequest)
1703
2092
  ], RenderInternalComponents);
1704
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: RenderInternalComponents, decorators: [{
2093
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: RenderInternalComponents, decorators: [{
1705
2094
  type: Injectable
1706
2095
  }] });
1707
2096
 
1708
2097
  class ExternalComponent {
1709
- data = input.required(...(ngDevMode ? [{ debugName: "data", transform: (x) => {
1710
- return {
1711
- height: coerceComponentHeight$1(x.height),
1712
- value: parseComponentTag(x.value) || '',
1713
- };
1714
- } }] : [{
1715
- transform: (x) => {
1716
- return {
1717
- height: coerceComponentHeight$1(x.height),
1718
- value: parseComponentTag(x.value) || '',
1719
- };
1720
- },
1721
- }]));
2098
+ data = input.required({ ...(ngDevMode ? { debugName: "data" } : {}), transform: (x) => {
2099
+ const value = x.value?.trim() || '';
2100
+ return {
2101
+ height: coerceComponentHeight$1(x.height),
2102
+ selector: parseComponentTag(value) || undefined,
2103
+ iframeUrl: parseIframeUrl(value) || undefined,
2104
+ };
2105
+ } });
2106
+ iframeUrl = computed(() => this.data().iframeUrl, ...(ngDevMode ? [{ debugName: "iframeUrl" }] : []));
2107
+ hasContent = computed(() => !!this.data().selector || !!this.data().iframeUrl, ...(ngDevMode ? [{ debugName: "hasContent" }] : []));
2108
+ canToggleFullscreen = computed(() => {
2109
+ return this._isBrowser
2110
+ && this.hasContent()
2111
+ && typeof this._hostElement.nativeElement.requestFullscreen === 'function'
2112
+ && typeof this._document.exitFullscreen === 'function';
2113
+ }, ...(ngDevMode ? [{ debugName: "canToggleFullscreen" }] : []));
2114
+ fullscreenLabel = computed(() => this.isFullscreen() ? 'Exit full screen' : 'Full screen', ...(ngDevMode ? [{ debugName: "fullscreenLabel" }] : []));
2115
+ isFullscreen = signal(false, ...(ngDevMode ? [{ debugName: "isFullscreen" }] : []));
2116
+ _document = inject(DOCUMENT);
2117
+ _hostElement = inject(ElementRef);
2118
+ _isBrowser = inject(IS_BROWSER_PLATFORM);
1722
2119
  _mediatr = inject(Mediatr);
1723
2120
  _viewContainerRef = viewChild.required('container', { read: ViewContainerRef });
1724
2121
  ngOnInit() {
1725
- this._mediatr.execute(new RenderExternalComponentRequest(this.data().value, this._viewContainerRef()));
2122
+ const selector = this.data().selector;
2123
+ if (selector) {
2124
+ this._mediatr.execute(new RenderExternalComponentRequest(selector, this._viewContainerRef()));
2125
+ return;
2126
+ }
2127
+ if (!this.data().iframeUrl) {
2128
+ console.error('Unsupported example source. Provide either component tag or [url].');
2129
+ }
1726
2130
  }
1727
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExternalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1728
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.1.8", type: ExternalComponent, isStandalone: true, selector: "external-component", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "style.height": "data().height" }, classAttribute: "f-example-view" }, viewQueries: [{ propertyName: "_viewContainerRef", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "<ng-container #container />\n\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2131
+ async toggleFullscreen() {
2132
+ if (!this.canToggleFullscreen())
2133
+ return;
2134
+ try {
2135
+ if (this._isCurrentElementInFullscreen()) {
2136
+ await this._document.exitFullscreen?.();
2137
+ }
2138
+ else {
2139
+ await this._hostElement.nativeElement.requestFullscreen?.();
2140
+ }
2141
+ }
2142
+ catch (error) {
2143
+ console.error('Unable to toggle full-screen mode for example preview:', error);
2144
+ }
2145
+ }
2146
+ onFullscreenChange() {
2147
+ this.isFullscreen.set(this._isCurrentElementInFullscreen());
2148
+ }
2149
+ _isCurrentElementInFullscreen() {
2150
+ return this._document.fullscreenElement === this._hostElement.nativeElement;
2151
+ }
2152
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ExternalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2153
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: ExternalComponent, isStandalone: true, selector: "external-component", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "document:fullscreenchange": "onFullscreenChange()" }, properties: { "style.height": "data().height", "class.f-example-view-fullscreen": "isFullscreen()" }, classAttribute: "f-example-view" }, viewQueries: [{ propertyName: "_viewContainerRef", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "@if (canToggleFullscreen()) {\n <button class=\"f-fullscreen-button\"\n type=\"button\"\n [class.exit]=\"isFullscreen()\"\n [attr.aria-label]=\"fullscreenLabel()\"\n [attr.title]=\"fullscreenLabel()\"\n (click)=\"toggleFullscreen()\"></button>\n}\n\n@if (iframeUrl()) {\n <iframe class=\"f-example-iframe\"\n [src]=\"iframeUrl()!\"\n loading=\"lazy\"\n referrerpolicy=\"no-referrer\"\n allow=\"fullscreen\"\n allowfullscreen></iframe>\n}\n\n<ng-container #container />\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
1729
2154
  }
1730
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExternalComponent, decorators: [{
2155
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ExternalComponent, decorators: [{
1731
2156
  type: Component,
1732
2157
  args: [{ selector: 'external-component', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1733
2158
  class: 'f-example-view',
1734
2159
  '[style.height]': 'data().height',
1735
- }, template: "<ng-container #container />\n\n" }]
1736
- }] });
2160
+ '[class.f-example-view-fullscreen]': 'isFullscreen()',
2161
+ }, template: "@if (canToggleFullscreen()) {\n <button class=\"f-fullscreen-button\"\n type=\"button\"\n [class.exit]=\"isFullscreen()\"\n [attr.aria-label]=\"fullscreenLabel()\"\n [attr.title]=\"fullscreenLabel()\"\n (click)=\"toggleFullscreen()\"></button>\n}\n\n@if (iframeUrl()) {\n <iframe class=\"f-example-iframe\"\n [src]=\"iframeUrl()!\"\n loading=\"lazy\"\n referrerpolicy=\"no-referrer\"\n allow=\"fullscreen\"\n allowfullscreen></iframe>\n}\n\n<ng-container #container />\n" }]
2162
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], _viewContainerRef: [{ type: i0.ViewChild, args: ['container', { ...{ read: ViewContainerRef }, isSignal: true }] }], onFullscreenChange: [{
2163
+ type: HostListener,
2164
+ args: ['document:fullscreenchange']
2165
+ }] } });
1737
2166
 
1738
2167
  class Highlight {
1739
2168
  _highlightService = inject(HighlightService);
@@ -1747,10 +2176,10 @@ class Highlight {
1747
2176
  .pipe(take(1), takeUntilDestroyed(this._destroyRef)).subscribe();
1748
2177
  });
1749
2178
  }
1750
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Highlight, deps: [], target: i0.ɵɵFactoryTarget.Component });
1751
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.1.8", type: Highlight, isStandalone: true, selector: "highlight", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2179
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Highlight, deps: [], target: i0.ɵɵFactoryTarget.Component });
2180
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.4", type: Highlight, isStandalone: true, selector: "highlight", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1752
2181
  }
1753
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Highlight, decorators: [{
2182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Highlight, decorators: [{
1754
2183
  type: Component,
1755
2184
  args: [{
1756
2185
  selector: 'highlight',
@@ -1758,7 +2187,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
1758
2187
  standalone: true,
1759
2188
  changeDetection: ChangeDetectionStrategy.OnPush,
1760
2189
  }]
1761
- }] });
2190
+ }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: true }] }] } });
1762
2191
 
1763
2192
  class CodeView {
1764
2193
  _httpClient = inject(HttpClient);
@@ -1803,10 +2232,10 @@ class CodeView {
1803
2232
  _copyContentToClipboard(content) {
1804
2233
  copyToClipboard(content).pipe(take(1), takeUntilDestroyed(this._destroyRef)).subscribe(() => this._popoverService.show('Copied!'));
1805
2234
  }
1806
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CodeView, deps: [], target: i0.ɵɵFactoryTarget.Component });
1807
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: CodeView, isStandalone: true, selector: "code-view", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.height": "height()" }, classAttribute: "f-code-view" }, ngImport: i0, template: "<span class=\"f-code-language\">{{ visibleLanguage() }}</span>\n<button class=\"f-copy-button\" (click)=\"onCopyClick()\"></button>\n@if (content()) {\n <highlight [content]=\"content()\" [language]=\"syntaxLanguage()\"/>\n}\n\n", dependencies: [{ kind: "component", type: Highlight, selector: "highlight", inputs: ["content", "language"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeView, deps: [], target: i0.ɵɵFactoryTarget.Component });
2236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: CodeView, isStandalone: true, selector: "code-view", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.height": "height()" }, classAttribute: "f-code-view" }, ngImport: i0, template: "<span class=\"f-code-language\">{{ visibleLanguage() }}</span>\n<button class=\"f-copy-button\" (click)=\"onCopyClick()\"></button>\n@if (content()) {\n <highlight [content]=\"content()\" [language]=\"syntaxLanguage()\"/>\n}\n\n", dependencies: [{ kind: "component", type: Highlight, selector: "highlight", inputs: ["content", "language"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1808
2237
  }
1809
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CodeView, decorators: [{
2238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeView, decorators: [{
1810
2239
  type: Component,
1811
2240
  args: [{ selector: 'code-view', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1812
2241
  class: 'f-code-view',
@@ -1814,19 +2243,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
1814
2243
  }, imports: [
1815
2244
  Highlight,
1816
2245
  ], template: "<span class=\"f-code-language\">{{ visibleLanguage() }}</span>\n<button class=\"f-copy-button\" (click)=\"onCopyClick()\"></button>\n@if (content()) {\n <highlight [content]=\"content()\" [language]=\"syntaxLanguage()\"/>\n}\n\n" }]
1817
- }] });
2246
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
1818
2247
  function coerceComponentHeight(value) {
1819
- if (value === undefined) {
2248
+ if (value === undefined || value === null) {
2249
+ return undefined;
2250
+ }
2251
+ if (typeof value === 'number') {
2252
+ return Number.isFinite(value) && value > 0 ? `${value}px` : undefined;
2253
+ }
2254
+ const normalizedValue = value.trim();
2255
+ if (!normalizedValue)
1820
2256
  return undefined;
2257
+ if (normalizedValue === 'auto')
2258
+ return 'auto';
2259
+ const numericValue = Number(normalizedValue);
2260
+ if (Number.isFinite(numericValue) && numericValue > 0) {
2261
+ return `${numericValue}px`;
2262
+ }
2263
+ if (/^-?\d+(\.\d+)?(px|%|vh|vw|vmin|vmax|rem|em|ch|ex|cm|mm|in|pt|pc)$/i.test(normalizedValue)) {
2264
+ return normalizedValue;
1821
2265
  }
1822
- value = Number(value);
1823
- if (value) {
1824
- return value + 'px';
2266
+ if (/^calc\(.+\)$/i.test(normalizedValue)) {
2267
+ return normalizedValue;
1825
2268
  }
1826
2269
  return undefined;
1827
2270
  }
1828
2271
  function parseLanguageFromFileExtension(url) {
1829
- const match = url.match(/\.([0-9a-z]+)(?:[\?#]|$)/i);
2272
+ const match = url.match(/\.([0-9a-z]+)(?:[?#]|$)/i);
1830
2273
  if (match) {
1831
2274
  let extension = match[1];
1832
2275
  if (extension === 'css') {
@@ -1855,13 +2298,10 @@ function parseSyntaxLanguage(language) {
1855
2298
  default:
1856
2299
  result = extractLanguage(language);
1857
2300
  }
1858
- if (!AVAILABLE_LANGUAGES.includes(result)) {
1859
- result = 'text';
1860
- }
1861
- return result;
2301
+ return resolveHighlightLanguage(result);
1862
2302
  }
1863
2303
  function extractLanguage(language) {
1864
- const match = language.match(/^([^\s\[]+)/);
2304
+ const match = language.match(/^([^\s[]+)/);
1865
2305
  return match ? match[1].toLowerCase() : language;
1866
2306
  }
1867
2307
 
@@ -1872,15 +2312,16 @@ class MarkCodeFocusedBlocksPostProcessor {
1872
2312
  }
1873
2313
  handle(element) {
1874
2314
  const html = element.innerHTML;
1875
- if (!FOCUS_REGEX.test(html)) {
2315
+ if (!FOCUS_TEST_REGEX.test(html)) {
1876
2316
  return of(element);
1877
2317
  }
1878
- element.innerHTML = html.replace(FOCUS_REGEX, (_match, content) => {
2318
+ element.innerHTML = html.replace(FOCUS_REPLACE_REGEX, (_match, content) => {
1879
2319
  return `<focus class="focused"><div class="inline-focus">${content}</div></focus>`;
1880
2320
  });
1881
2321
  const focused = element.querySelector('.focused');
1882
- if (focused) {
1883
- this._applyOpacity(element.parentElement);
2322
+ const hostElement = element.parentElement;
2323
+ if (focused && hostElement) {
2324
+ this._applyOpacity(hostElement);
1884
2325
  }
1885
2326
  return of(element);
1886
2327
  }
@@ -1906,10 +2347,13 @@ class MarkCodeFocusedBlocksPostProcessor {
1906
2347
  return isRgb ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${opacity * alpha})`;
1907
2348
  }
1908
2349
  _getRgbValues(color) {
1909
- return color.match(/\d+/g);
2350
+ const matches = color.match(/-?\d*\.?\d+/g) || [];
2351
+ const [r = '0', g = '0', b = '0', a = '1'] = matches;
2352
+ return [r, g, b, a];
1910
2353
  }
1911
2354
  }
1912
- const FOCUS_REGEX = /ƒƒƒ([\s\S]*?)¢¢¢/g;
2355
+ const FOCUS_TEST_REGEX = /ƒƒƒ([\s\S]*?)¢¢¢/;
2356
+ const FOCUS_REPLACE_REGEX = /ƒƒƒ([\s\S]*?)¢¢¢/g;
1913
2357
 
1914
2358
  const UNIVERSAL_THEME = {
1915
2359
  name: 'universal',
@@ -2192,6 +2636,32 @@ const UNIVERSAL_THEME = {
2192
2636
  ],
2193
2637
  };
2194
2638
 
2639
+ const LANGUAGE_ALIASES = {
2640
+ js: 'javascript',
2641
+ javascript: 'javascript',
2642
+ ts: 'typescript',
2643
+ typescript: 'typescript',
2644
+ md: 'markdown',
2645
+ sh: 'shell',
2646
+ zsh: 'shell',
2647
+ shell: 'shell',
2648
+ shellscript: 'shell',
2649
+ txt: 'text',
2650
+ plain: 'text',
2651
+ plaintext: 'text',
2652
+ };
2653
+ const LANGUAGE_LOADERS = new Map([
2654
+ ['javascript', () => import('@shikijs/langs/javascript')],
2655
+ ['typescript', () => import('@shikijs/langs/typescript')],
2656
+ ['angular-html', () => import('@shikijs/langs/angular-html')],
2657
+ ['angular-ts', () => import('@shikijs/langs/angular-ts')],
2658
+ ['shell', () => import('@shikijs/langs/shell')],
2659
+ ['html', () => import('@shikijs/langs/html')],
2660
+ ['bash', () => import('@shikijs/langs/bash')],
2661
+ ['css', () => import('@shikijs/langs/css')],
2662
+ ['scss', () => import('@shikijs/langs/scss')],
2663
+ ['markdown', () => import('@shikijs/langs/markdown')],
2664
+ ]);
2195
2665
  const AVAILABLE_LANGUAGES = [
2196
2666
  'javascript',
2197
2667
  'typescript',
@@ -2205,6 +2675,32 @@ const AVAILABLE_LANGUAGES = [
2205
2675
  'markdown',
2206
2676
  'text',
2207
2677
  ];
2678
+ function resolveHighlightLanguage(lang) {
2679
+ const normalized = (lang || '').trim().toLowerCase();
2680
+ if (!normalized) {
2681
+ return 'text';
2682
+ }
2683
+ const alias = LANGUAGE_ALIASES[normalized];
2684
+ if (alias) {
2685
+ return alias;
2686
+ }
2687
+ if (isAvailableLanguage(normalized)) {
2688
+ return normalized;
2689
+ }
2690
+ return 'text';
2691
+ }
2692
+ function getLanguageLoader(lang) {
2693
+ if (isPlainTextLanguage(lang)) {
2694
+ return null;
2695
+ }
2696
+ return LANGUAGE_LOADERS.get(lang) || null;
2697
+ }
2698
+ function isAvailableLanguage(lang) {
2699
+ return AVAILABLE_LANGUAGES.includes(lang);
2700
+ }
2701
+ function isPlainTextLanguage(lang) {
2702
+ return lang === 'text' || lang === 'txt' || lang === 'plain' || lang === 'plaintext';
2703
+ }
2208
2704
 
2209
2705
  class HighlightService {
2210
2706
  /**
@@ -2212,14 +2708,16 @@ class HighlightService {
2212
2708
  * It supports syntax highlighting and post-processing for focused blocks.
2213
2709
  */
2214
2710
  _isBrowser = inject(IS_BROWSER_PLATFORM);
2215
- _window = inject(WINDOW);
2216
- _highlighter$ = defer(() => from(createHighlighter({ themes: [UNIVERSAL_THEME], langs: AVAILABLE_LANGUAGES }))).pipe(shareReplay(1));
2711
+ _window = inject(WINDOW, { optional: true });
2712
+ _languageLoadingTasks = new Map();
2713
+ _highlighter$ = defer(() => from(this._createHighlighter())).pipe(shareReplay(1));
2217
2714
  highlight(element, lang, content) {
2218
2715
  if (!this._isBrowser) {
2219
2716
  console.warn('[HighlightService] Skipping highlight on server.');
2220
2717
  return of(element);
2221
2718
  }
2222
- return this._highlightCodeBlock(element, lang, content).pipe(switchMap((x) => this._postProcess(x)), catchError((err) => {
2719
+ const resolvedLanguage = resolveHighlightLanguage(lang);
2720
+ return this._ensureLanguageLoaded(resolvedLanguage).pipe(switchMap(() => this._highlightCodeBlock(element, resolvedLanguage, content)), switchMap((x) => this._postProcess(x)), catchError((err) => {
2223
2721
  console.error('[HighlightService] Failed to highlight:', err);
2224
2722
  return of(element);
2225
2723
  }));
@@ -2231,22 +2729,67 @@ class HighlightService {
2231
2729
  return new Observable((observer) => {
2232
2730
  const processedContent = this._preprocessFocus(content);
2233
2731
  element.innerHTML = highlighter.codeToHtml(processedContent, { lang, theme: 'universal', defaultColor: false });
2234
- requestAnimationFrame(() => {
2732
+ this._scheduleRender(() => {
2235
2733
  observer.next(element);
2236
2734
  observer.complete();
2237
2735
  });
2238
2736
  });
2239
2737
  }
2240
2738
  _preprocessFocus(code) {
2241
- return code.replace(/\|\:\|([\s\S]*?)\|\:\|/g, (_, p1) => `ƒƒƒ${p1}¢¢¢`);
2739
+ return code.replace(/\|:\|([\s\S]*?)\|:\|/g, (_, p1) => `ƒƒƒ${p1}¢¢¢`);
2740
+ }
2741
+ _createHighlighter() {
2742
+ return createHighlighterCore({
2743
+ engine: createOnigurumaEngine(() => import('shiki/wasm').then((x) => x.default)),
2744
+ themes: [UNIVERSAL_THEME],
2745
+ langs: [],
2746
+ });
2747
+ }
2748
+ _ensureLanguageLoaded(lang) {
2749
+ if (isSpecialLang(lang)) {
2750
+ return of(void 0);
2751
+ }
2752
+ return this._highlighter$.pipe(switchMap((highlighter) => {
2753
+ if (highlighter.getLoadedLanguages().includes(lang)) {
2754
+ return of(void 0);
2755
+ }
2756
+ const cachedTask = this._languageLoadingTasks.get(lang);
2757
+ if (cachedTask) {
2758
+ return cachedTask;
2759
+ }
2760
+ const loader = getLanguageLoader(lang);
2761
+ if (!loader) {
2762
+ return of(void 0);
2763
+ }
2764
+ const loadingTask = from(highlighter.loadLanguage(loader)).pipe(map(() => void 0), catchError((error) => {
2765
+ console.error(`[HighlightService] Failed to load language "${lang}"`, error);
2766
+ return of(void 0);
2767
+ }), finalize(() => {
2768
+ this._languageLoadingTasks.delete(lang);
2769
+ }), shareReplay(1));
2770
+ this._languageLoadingTasks.set(lang, loadingTask);
2771
+ return loadingTask;
2772
+ }));
2773
+ }
2774
+ _scheduleRender(callback) {
2775
+ const raf = this._window?.requestAnimationFrame?.bind(this._window);
2776
+ if (raf) {
2777
+ raf(callback);
2778
+ return;
2779
+ }
2780
+ queueMicrotask(callback);
2242
2781
  }
2243
2782
  _postProcess(element) {
2244
- return of(element).pipe(switchMap((x) => new MarkCodeFocusedBlocksPostProcessor(this._window).handle(x)));
2783
+ const windowRef = this._window;
2784
+ if (!windowRef) {
2785
+ return of(element);
2786
+ }
2787
+ return of(element).pipe(switchMap((x) => new MarkCodeFocusedBlocksPostProcessor(windowRef).handle(x)));
2245
2788
  }
2246
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2247
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HighlightService, providedIn: 'root' });
2789
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2790
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HighlightService, providedIn: 'root' });
2248
2791
  }
2249
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HighlightService, decorators: [{
2792
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HighlightService, decorators: [{
2250
2793
  type: Injectable,
2251
2794
  args: [{
2252
2795
  providedIn: 'root',
@@ -2260,10 +2803,10 @@ class CodeGroup {
2260
2803
  tabClick(index) {
2261
2804
  this.index.set(index);
2262
2805
  }
2263
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CodeGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
2264
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: CodeGroup, isStandalone: true, selector: "code-group", host: { classAttribute: "f-code-group" }, ngImport: i0, template: "@let views = data();\n\n@if (views.length > 1) {\n <div class=\"f-code-group-tabs\">\n @for (data of views; track data) {\n <button class=\"f-tab-button\" [class.active]=\"$index === index()\" (click)=\"tabClick($index)\">\n {{ data.tab }}\n </button>\n }\n </div>\n}\n\n<div class=\"f-code-group-body\">\n @for (data of views; track data) {\n\n @let isExampleView = data.type === containerType.EXAMPLE;\n @let display = $index === index() ? 'block' : 'none';\n\n @if (isExampleView) {\n <external-component [style.display]=\"display\" [data]=\"data\" />\n } @else {\n <code-view [style.display]=\"display\" [data]=\"data\" />\n }\n }\n</div>\n", dependencies: [{ kind: "component", type: ExternalComponent, selector: "external-component", inputs: ["data"] }, { kind: "component", type: CodeView, selector: "code-view", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2806
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
2807
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: CodeGroup, isStandalone: true, selector: "code-group", host: { classAttribute: "f-code-group" }, ngImport: i0, template: "@let views = data();\n\n@if (views.length > 1) {\n <div class=\"f-code-group-tabs\">\n @for (data of views; track data) {\n <button class=\"f-tab-button\" [class.active]=\"$index === index()\" (click)=\"tabClick($index)\">\n {{ data.tab }}\n </button>\n }\n </div>\n}\n\n<div class=\"f-code-group-body\">\n @for (data of views; track data) {\n\n @let isExampleView = data.type === containerType.EXAMPLE;\n @let display = $index === index() ? 'block' : 'none';\n\n @if (isExampleView) {\n <external-component [style.display]=\"display\" [data]=\"data\" />\n } @else {\n <code-view [style.display]=\"display\" [data]=\"data\" />\n }\n }\n</div>\n", dependencies: [{ kind: "component", type: ExternalComponent, selector: "external-component", inputs: ["data"] }, { kind: "component", type: CodeView, selector: "code-view", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2265
2808
  }
2266
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CodeGroup, decorators: [{
2809
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeGroup, decorators: [{
2267
2810
  type: Component,
2268
2811
  args: [{ selector: 'code-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
2269
2812
  class: 'f-code-group',
@@ -2345,10 +2888,10 @@ class PreviewGroupService {
2345
2888
  x.hostElement.style.display = 'block';
2346
2889
  });
2347
2890
  }
2348
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewGroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2349
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewGroupService });
2891
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewGroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2892
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewGroupService });
2350
2893
  }
2351
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewGroupService, decorators: [{
2894
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewGroupService, decorators: [{
2352
2895
  type: Injectable
2353
2896
  }] });
2354
2897
 
@@ -2411,15 +2954,15 @@ class PreviewCard extends PreviewCardBase {
2411
2954
  ngOnDestroy() {
2412
2955
  this._fPreviewGroupService.remove(this);
2413
2956
  }
2414
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewCard, deps: null, target: i0.ɵɵFactoryTarget.Component });
2415
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: PreviewCard, isStandalone: true, selector: "a[preview-card]", host: { properties: { "attr.href": "url", "attr.title": "viewModel?.text" } }, usesInheritance: true, ngImport: i0, template: "@if (viewModel) {\n <img [src]=\"src()\" [alt]=\"viewModel.description\" [title]=\"viewModel.text\">\n <div class=\"title\">\n {{ viewModel.text }}\n @if (viewModel.badge) {\n <span class=\"f-badge {{viewModel.badge.type}}\">{{ viewModel.badge.text }}</span>\n }\n </div>\n <div class=\"description\">{{ viewModel.description }}</div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px;cursor:pointer}:host:hover img{transform:scale(1.1)}:host img{display:block;margin-bottom:16px;width:100%;height:180px;border-radius:4px;object-fit:cover;transition:transform .3s}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media (min-width: 640px){:host{width:calc((100% - 32px)/2)}}.f-badge{padding:0 6px;line-height:14px;text-transform:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2957
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewCard, deps: null, target: i0.ɵɵFactoryTarget.Component });
2958
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: PreviewCard, isStandalone: true, selector: "a[preview-card]", host: { properties: { "attr.href": "url", "attr.title": "viewModel?.text" } }, usesInheritance: true, ngImport: i0, template: "@if (viewModel) {\n <img [src]=\"src()\" [alt]=\"viewModel.description\" [title]=\"viewModel.text\">\n <div class=\"title\">\n {{ viewModel.text }}\n @if (viewModel.badge) {\n <span class=\"f-badge {{viewModel.badge.type}}\">{{ viewModel.badge.text }}</span>\n }\n </div>\n <div class=\"description\">{{ viewModel.description }}</div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px;cursor:pointer}:host:hover img{transform:scale(1.1)}:host img{display:block;margin-bottom:16px;width:100%;height:180px;border-radius:4px;object-fit:cover;transition:transform .3s}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media(min-width:640px){:host{width:calc((100% - 32px)/2)}}.f-badge{padding:0 6px;line-height:14px;text-transform:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2416
2959
  }
2417
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewCard, decorators: [{
2960
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewCard, decorators: [{
2418
2961
  type: Component,
2419
2962
  args: [{ selector: 'a[preview-card]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
2420
2963
  '[attr.href]': 'url',
2421
2964
  '[attr.title]': 'viewModel?.text',
2422
- }, template: "@if (viewModel) {\n <img [src]=\"src()\" [alt]=\"viewModel.description\" [title]=\"viewModel.text\">\n <div class=\"title\">\n {{ viewModel.text }}\n @if (viewModel.badge) {\n <span class=\"f-badge {{viewModel.badge.type}}\">{{ viewModel.badge.text }}</span>\n }\n </div>\n <div class=\"description\">{{ viewModel.description }}</div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px;cursor:pointer}:host:hover img{transform:scale(1.1)}:host img{display:block;margin-bottom:16px;width:100%;height:180px;border-radius:4px;object-fit:cover;transition:transform .3s}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media (min-width: 640px){:host{width:calc((100% - 32px)/2)}}.f-badge{padding:0 6px;line-height:14px;text-transform:none}\n"] }]
2965
+ }, template: "@if (viewModel) {\n <img [src]=\"src()\" [alt]=\"viewModel.description\" [title]=\"viewModel.text\">\n <div class=\"title\">\n {{ viewModel.text }}\n @if (viewModel.badge) {\n <span class=\"f-badge {{viewModel.badge.type}}\">{{ viewModel.badge.text }}</span>\n }\n </div>\n <div class=\"description\">{{ viewModel.description }}</div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px;cursor:pointer}:host:hover img{transform:scale(1.1)}:host img{display:block;margin-bottom:16px;width:100%;height:180px;border-radius:4px;object-fit:cover;transition:transform .3s}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media(min-width:640px){:host{width:calc((100% - 32px)/2)}}.f-badge{padding:0 6px;line-height:14px;text-transform:none}\n"] }]
2423
2966
  }] });
2424
2967
 
2425
2968
  var previewCard = /*#__PURE__*/Object.freeze({
@@ -2462,10 +3005,10 @@ class PreviewActionBar {
2462
3005
  this.isSortByDateChecked.set(event);
2463
3006
  this._fPreviewGroupService.sortByDate(event);
2464
3007
  }
2465
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
2466
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: PreviewActionBar, isStandalone: true, selector: "div[preview-action-bar]", ngImport: i0, template: "@if (filters().length) {\n <div class=\"filters-row\">\n @for (filter of filters(); track filter) {\n <f-radio-button [checked]=\"activeFilter() === filter\"\n (change)=\"onFilterChange(filter)\">{{ filter | titlecase }}\n </f-radio-button>\n }\n <div class=\"flex-space\"></div>\n <f-checkbox [checked]=\"isSortByDateChecked()\" (change)=\"onSortByDateChange($event)\">Sort by Newness</f-checkbox>\n </div>\n}\n\n\n\n", styles: [".filters-row{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;width:100%;padding-top:20px;gap:8px}\n"], dependencies: [{ kind: "component", type: FCheckboxComponent, selector: "f-checkbox", inputs: ["id", "checked"], outputs: ["change"] }, { kind: "component", type: FRadioButtonComponent, selector: "f-radio-button", inputs: ["id", "checked"], outputs: ["change"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3008
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
3009
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: PreviewActionBar, isStandalone: true, selector: "div[preview-action-bar]", ngImport: i0, template: "@if (filters().length) {\n <div class=\"filters-row\">\n @for (filter of filters(); track filter) {\n <f-radio-button [checked]=\"activeFilter() === filter\"\n (change)=\"onFilterChange(filter)\">{{ filter | titlecase }}\n </f-radio-button>\n }\n <div class=\"flex-space\"></div>\n <f-checkbox [checked]=\"isSortByDateChecked()\" (change)=\"onSortByDateChange($event)\">Sort by Newness</f-checkbox>\n </div>\n}\n\n\n\n", styles: [".filters-row{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;width:100%;padding-top:20px;gap:8px}\n"], dependencies: [{ kind: "component", type: FCheckboxComponent, selector: "f-checkbox", inputs: ["id", "checked"], outputs: ["change"] }, { kind: "component", type: FRadioButtonComponent, selector: "f-radio-button", inputs: ["id", "checked"], outputs: ["change"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2467
3010
  }
2468
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewActionBar, decorators: [{
3011
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewActionBar, decorators: [{
2469
3012
  type: Component,
2470
3013
  args: [{ selector: 'div[preview-action-bar]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2471
3014
  FCheckboxComponent,
@@ -2488,13 +3031,13 @@ class ShowcaseItem {
2488
3031
  const model = this.model();
2489
3032
  return theme === 'dark' ? (model.imageUrlDark || model.imageUrl) : model.imageUrl;
2490
3033
  }, ...(ngDevMode ? [{ debugName: "src" }] : []));
2491
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ShowcaseItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
2492
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: ShowcaseItem, isStandalone: true, selector: "showcase-item", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let data = model();\n\n@if (data) {\n <img [src]=\"src()\" [alt]=\"data.description\" [title]=\"data.name\">\n <div class=\"title\">{{ data.name }}</div>\n <div class=\"description\">{{ data.description }}</div>\n <div class=\"links\">\n @for (link of (data.links || []); track link.text) {\n <a href=\"{{ link.url }}\" target=\"_blank\" rel=\"noopener\">{{ link.text }}</a>\n }\n </div>\n <div class=\"tags\">\n @for (tag of (data.tags || []); track tag) {\n <span class=\"f-badge tip\">{{ tag }}</span>\n }\n </div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px}:host img{display:block;margin-bottom:16px;width:100%;height:240px;border-radius:4px;object-fit:cover}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media (min-width: 640px){:host{width:calc((100% - 32px)/2)}}.links{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:16px}.links a{font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.links a:hover,.links a.active{color:var(--primary-1)}.tags{display:flex;flex-wrap:wrap;gap:8px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3034
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ShowcaseItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
3035
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: ShowcaseItem, isStandalone: true, selector: "showcase-item", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let data = model();\n\n@if (data) {\n <img [src]=\"src()\" [alt]=\"data.description\" [title]=\"data.name\">\n <div class=\"title\">{{ data.name }}</div>\n <div class=\"description\">{{ data.description }}</div>\n <div class=\"links\">\n @for (link of (data.links || []); track link.text) {\n <a href=\"{{ link.url }}\" target=\"_blank\" rel=\"noopener\">{{ link.text }}</a>\n }\n </div>\n <div class=\"tags\">\n @for (tag of (data.tags || []); track tag) {\n <span class=\"f-badge tip\">{{ tag }}</span>\n }\n </div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px}:host img{display:block;margin-bottom:16px;width:100%;height:240px;border-radius:4px;object-fit:cover}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media(min-width:640px){:host{width:calc((100% - 32px)/2)}}.links{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:16px}.links a{font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.links a:hover,.links a.active{color:var(--primary-1)}.tags{display:flex;flex-wrap:wrap;gap:8px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2493
3036
  }
2494
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ShowcaseItem, decorators: [{
3037
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ShowcaseItem, decorators: [{
2495
3038
  type: Component,
2496
- args: [{ selector: 'showcase-item', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let data = model();\n\n@if (data) {\n <img [src]=\"src()\" [alt]=\"data.description\" [title]=\"data.name\">\n <div class=\"title\">{{ data.name }}</div>\n <div class=\"description\">{{ data.description }}</div>\n <div class=\"links\">\n @for (link of (data.links || []); track link.text) {\n <a href=\"{{ link.url }}\" target=\"_blank\" rel=\"noopener\">{{ link.text }}</a>\n }\n </div>\n <div class=\"tags\">\n @for (tag of (data.tags || []); track tag) {\n <span class=\"f-badge tip\">{{ tag }}</span>\n }\n </div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px}:host img{display:block;margin-bottom:16px;width:100%;height:240px;border-radius:4px;object-fit:cover}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media (min-width: 640px){:host{width:calc((100% - 32px)/2)}}.links{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:16px}.links a{font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.links a:hover,.links a.active{color:var(--primary-1)}.tags{display:flex;flex-wrap:wrap;gap:8px}\n"] }]
2497
- }] });
3039
+ args: [{ selector: 'showcase-item', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let data = model();\n\n@if (data) {\n <img [src]=\"src()\" [alt]=\"data.description\" [title]=\"data.name\">\n <div class=\"title\">{{ data.name }}</div>\n <div class=\"description\">{{ data.description }}</div>\n <div class=\"links\">\n @for (link of (data.links || []); track link.text) {\n <a href=\"{{ link.url }}\" target=\"_blank\" rel=\"noopener\">{{ link.text }}</a>\n }\n </div>\n <div class=\"tags\">\n @for (tag of (data.tags || []); track tag) {\n <span class=\"f-badge tip\">{{ tag }}</span>\n }\n </div>\n}\n\n\n\n", styles: [":host{display:block;border-radius:4px;background-color:var(--soft-background);padding:24px;width:100%;text-decoration:none!important;color:inherit!important;line-height:24px;font-size:14px}:host img{display:block;margin-bottom:16px;width:100%;height:240px;border-radius:4px;object-fit:cover}:host .title{line-height:inherit;font-weight:600;text-transform:uppercase;color:var(--primary-text);display:flex;justify-content:space-between;align-items:center}:host .description{margin:8px 0!important;line-height:inherit;color:var(--secondary-text);width:100%;word-wrap:break-word;white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media(min-width:640px){:host{width:calc((100% - 32px)/2)}}.links{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:16px}.links a{font-size:14px;font-weight:500;color:var(--primary-text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.links a:hover,.links a.active{color:var(--primary-1)}.tags{display:flex;flex-wrap:wrap;gap:8px}\n"] }]
3040
+ }], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: true }] }] } });
2498
3041
 
2499
3042
  const SHOWCASE_DATA = new InjectionToken('SHOWCASE_DATA');
2500
3043
 
@@ -2515,10 +3058,10 @@ class Showcase {
2515
3058
  tagClick(tag) {
2516
3059
  this.activeTag.update((x) => x === tag ? null : tag);
2517
3060
  }
2518
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Showcase, deps: [], target: i0.ɵɵFactoryTarget.Component });
2519
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: Showcase, isStandalone: true, selector: "showcase", ngImport: i0, template: "<div class=\"filters-panel\">\n @for (tag of tags(); track tag) {\n <span class=\"f-badge tip\" (click)=\"tagClick(tag)\" [class.info]=\"activeTag() === tag\">{{ tag }}</span>\n }\n</div>\n<div class=\"showcase-list\">\n @for (item of items(); track item.imageUrl) {\n <showcase-item [model]=\"item\"/>\n }\n</div>\n\n", styles: [".filters-panel{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px}.filters-panel .f-badge{cursor:pointer}.showcase-list{display:flex;justify-content:flex-start;align-items:normal;flex-wrap:wrap;gap:32px;pointer-events:all;overflow:hidden}\n"], dependencies: [{ kind: "component", type: ShowcaseItem, selector: "showcase-item", inputs: ["model"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3061
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Showcase, deps: [], target: i0.ɵɵFactoryTarget.Component });
3062
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: Showcase, isStandalone: true, selector: "showcase", ngImport: i0, template: "<div class=\"filters-panel\">\n @for (tag of tags(); track tag) {\n <span class=\"f-badge tip\" (click)=\"tagClick(tag)\" [class.info]=\"activeTag() === tag\">{{ tag }}</span>\n }\n</div>\n<div class=\"showcase-list\">\n @for (item of items(); track item.imageUrl) {\n <showcase-item [model]=\"item\"/>\n }\n</div>\n\n", styles: [".filters-panel{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px}.filters-panel .f-badge{cursor:pointer}.showcase-list{display:flex;justify-content:flex-start;align-items:normal;flex-wrap:wrap;gap:32px;pointer-events:all;overflow:hidden}\n"], dependencies: [{ kind: "component", type: ShowcaseItem, selector: "showcase-item", inputs: ["model"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2520
3063
  }
2521
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Showcase, decorators: [{
3064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Showcase, decorators: [{
2522
3065
  type: Component,
2523
3066
  args: [{ selector: 'showcase', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2524
3067
  ShowcaseItem,
@@ -2563,13 +3106,13 @@ let ActivateTocByHash = class ActivateTocByHash {
2563
3106
  })),
2564
3107
  }));
2565
3108
  }
2566
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ActivateTocByHash, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2567
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ActivateTocByHash });
3109
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ActivateTocByHash, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3110
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ActivateTocByHash });
2568
3111
  };
2569
3112
  ActivateTocByHash = __decorate([
2570
3113
  MExecution(ActivateTocByHashRequest)
2571
3114
  ], ActivateTocByHash);
2572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ActivateTocByHash, decorators: [{
3115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ActivateTocByHash, decorators: [{
2573
3116
  type: Injectable
2574
3117
  }] });
2575
3118
 
@@ -2611,13 +3154,13 @@ let CalculateAbsoluteTopToContainer = class CalculateAbsoluteTopToContainer {
2611
3154
  }
2612
3155
  return result;
2613
3156
  }
2614
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateAbsoluteTopToContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2615
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateAbsoluteTopToContainer });
3157
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateAbsoluteTopToContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3158
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateAbsoluteTopToContainer });
2616
3159
  };
2617
3160
  CalculateAbsoluteTopToContainer = __decorate([
2618
3161
  MExecution(CalculateAbsoluteTopToContainerRequest)
2619
3162
  ], CalculateAbsoluteTopToContainer);
2620
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateAbsoluteTopToContainer, decorators: [{
3163
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateAbsoluteTopToContainer, decorators: [{
2621
3164
  type: Injectable
2622
3165
  }] });
2623
3166
 
@@ -2672,10 +3215,10 @@ class CalculateHashFromScrollPosition {
2672
3215
  }
2673
3216
  return result;
2674
3217
  }
2675
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateHashFromScrollPosition, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2676
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateHashFromScrollPosition });
3218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateHashFromScrollPosition, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3219
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateHashFromScrollPosition });
2677
3220
  }
2678
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateHashFromScrollPosition, decorators: [{
3221
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateHashFromScrollPosition, decorators: [{
2679
3222
  type: Injectable
2680
3223
  }] });
2681
3224
 
@@ -2731,13 +3274,13 @@ let CalculateTableOfContent = class CalculateTableOfContent {
2731
3274
  }
2732
3275
  stack.push(tocItem);
2733
3276
  }
2734
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateTableOfContent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2735
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateTableOfContent });
3277
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateTableOfContent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3278
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateTableOfContent });
2736
3279
  };
2737
3280
  CalculateTableOfContent = __decorate([
2738
3281
  MExecution(CalculateTableOfContentRequest)
2739
3282
  ], CalculateTableOfContent);
2740
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateTableOfContent, decorators: [{
3283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateTableOfContent, decorators: [{
2741
3284
  type: Injectable
2742
3285
  }] });
2743
3286
 
@@ -2788,25 +3331,25 @@ let ScrollToElementInContainer = class ScrollToElementInContainer {
2788
3331
  _getContainerTop() {
2789
3332
  return this._scrollableContainer.htmlElement.getBoundingClientRect().top;
2790
3333
  }
2791
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollToElementInContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2792
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollToElementInContainer });
3334
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollToElementInContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3335
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollToElementInContainer });
2793
3336
  };
2794
3337
  ScrollToElementInContainer = __decorate([
2795
3338
  MExecution(ScrollToElementInContainerRequest)
2796
3339
  ], ScrollToElementInContainer);
2797
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollToElementInContainer, decorators: [{
3340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollToElementInContainer, decorators: [{
2798
3341
  type: Injectable
2799
3342
  }] });
2800
3343
 
2801
3344
  class TableOfContentItemsComponent {
2802
3345
  items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
2803
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TableOfContentItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2804
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: TableOfContentItemsComponent, isStandalone: true, selector: "ul[f-table-of-content-items]", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@for (item of items(); track item.hash) {\n <li [class.active]=\"item.isActive\"><a class=\"text-ellipsis\" [href]=\"item.hash\">{{ item.title }}</a></li>\n @if (item.children) {\n <ul f-table-of-content-items [items]=\"item.children\"></ul>\n }\n}\n", styles: [":host{list-style:none;margin:0;padding:0}:host li{overflow-wrap:break-word;color:var(--secondary-text);max-width:180px}:host li a{display:block;line-height:var(--on-page-navigation-item-height);font-size:14px;color:inherit;font-weight:400}:host li.active{color:var(--primary-text)}:host li+ul{padding:0 16px}\n"], dependencies: [{ kind: "component", type: TableOfContentItemsComponent, selector: "ul[f-table-of-content-items]", inputs: ["items"] }], changeDetection: i0.ChangeDetectionStrategy.Default });
3346
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContentItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3347
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: TableOfContentItemsComponent, isStandalone: true, selector: "ul[f-table-of-content-items]", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@for (item of items(); track item.hash) {\n <li [class.active]=\"item.isActive\"><a class=\"text-ellipsis\" [href]=\"item.hash\">{{ item.title }}</a></li>\n @if (item.children) {\n <ul f-table-of-content-items [items]=\"item.children\"></ul>\n }\n}\n", styles: [":host{list-style:none;margin:0;padding:0}:host li{overflow-wrap:break-word;color:var(--secondary-text);max-width:180px}:host li a{display:block;line-height:var(--on-page-navigation-item-height);font-size:14px;color:inherit;font-weight:400}:host li.active{color:var(--primary-text)}:host li+ul{padding:0 16px}\n"], dependencies: [{ kind: "component", type: TableOfContentItemsComponent, selector: "ul[f-table-of-content-items]", inputs: ["items"] }], changeDetection: i0.ChangeDetectionStrategy.Default });
2805
3348
  }
2806
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TableOfContentItemsComponent, decorators: [{
3349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContentItemsComponent, decorators: [{
2807
3350
  type: Component,
2808
3351
  args: [{ selector: 'ul[f-table-of-content-items]', changeDetection: ChangeDetectionStrategy.Default, standalone: true, template: "@for (item of items(); track item.hash) {\n <li [class.active]=\"item.isActive\"><a class=\"text-ellipsis\" [href]=\"item.hash\">{{ item.title }}</a></li>\n @if (item.children) {\n <ul f-table-of-content-items [items]=\"item.children\"></ul>\n }\n}\n", styles: [":host{list-style:none;margin:0;padding:0}:host li{overflow-wrap:break-word;color:var(--secondary-text);max-width:180px}:host li a{display:block;line-height:var(--on-page-navigation-item-height);font-size:14px;color:inherit;font-weight:400}:host li.active{color:var(--primary-text)}:host li+ul{padding:0 16px}\n"] }]
2809
- }] });
3352
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }] } });
2810
3353
 
2811
3354
  const TABLE_OF_CONTENT_MODULE_PROVIDERS = [
2812
3355
  ActivateTocByHash,
@@ -2845,12 +3388,12 @@ class TableOfContent {
2845
3388
  this._mediatr.execute(new ActivateTocByHashRequest(hash));
2846
3389
  this._mediatr.execute(new ScrollToElementInContainerRequest(hash));
2847
3390
  }
2848
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TableOfContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2849
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: TableOfContent, isStandalone: true, selector: "table-of-content", host: { listeners: { "click": "_click($event)" } }, ngImport: i0, template: "@let data = tocData();\n@if (data) {\n <div class=\"title\">{{ title || 'In this article' }}</div>\n <ul f-table-of-content-items [items]=\"data.tree\"></ul>\n <div class=\"active-marker\" [style.top]=\"activeMarkerPosition() + 'px'\"></div>\n}\n\n", styles: [":host{--on-page-navigation-item-height: 32px;display:none;padding-left:16px;border-left:1px solid var(--divider-color);font-size:13px;font-weight:500;position:relative}:host .title{line-height:32px;font-size:14px;font-weight:600}@media (min-width: 1280px){:host{display:block;width:var(--on-page-navigation-width);position:fixed;top:calc(var(--header-height) + 48px);right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3)}}:host .active-marker{position:absolute;top:0;left:0;width:2px;height:calc(var(--on-page-navigation-item-height) / 2);border-radius:2px;background-color:var(--primary-1);transition:top .25s cubic-bezier(0,1,.5,1),opacity .25s}\n"], dependencies: [{ kind: "component", type: TableOfContentItemsComponent, selector: "ul[f-table-of-content-items]", inputs: ["items"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3391
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3392
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: TableOfContent, isStandalone: true, selector: "table-of-content", host: { listeners: { "click": "_click($event)" } }, ngImport: i0, template: "@let data = tocData();\n@if (data) {\n <div class=\"title\">{{ title || 'In this article' }}</div>\n <ul f-table-of-content-items [items]=\"data.tree\"></ul>\n <div class=\"active-marker\" [style.top]=\"activeMarkerPosition() + 'px'\"></div>\n}\n\n", styles: [":host{--on-page-navigation-item-height: 32px;display:none;padding-left:16px;border-left:1px solid var(--divider-color);font-size:13px;font-weight:500;position:relative}:host .title{line-height:32px;font-size:14px;font-weight:600}@media(min-width:1280px){:host{display:block;width:var(--on-page-navigation-width);position:fixed;top:calc(var(--header-height) + 48px);right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3)}}:host .active-marker{position:absolute;top:0;left:0;width:2px;height:calc(var(--on-page-navigation-item-height) / 2);border-radius:2px;background-color:var(--primary-1);transition:top .25s cubic-bezier(0,1,.5,1),opacity .25s}\n"], dependencies: [{ kind: "component", type: TableOfContentItemsComponent, selector: "ul[f-table-of-content-items]", inputs: ["items"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2850
3393
  }
2851
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TableOfContent, decorators: [{
3394
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContent, decorators: [{
2852
3395
  type: Component,
2853
- args: [{ selector: 'table-of-content', standalone: true, imports: [TableOfContentItemsComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let data = tocData();\n@if (data) {\n <div class=\"title\">{{ title || 'In this article' }}</div>\n <ul f-table-of-content-items [items]=\"data.tree\"></ul>\n <div class=\"active-marker\" [style.top]=\"activeMarkerPosition() + 'px'\"></div>\n}\n\n", styles: [":host{--on-page-navigation-item-height: 32px;display:none;padding-left:16px;border-left:1px solid var(--divider-color);font-size:13px;font-weight:500;position:relative}:host .title{line-height:32px;font-size:14px;font-weight:600}@media (min-width: 1280px){:host{display:block;width:var(--on-page-navigation-width);position:fixed;top:calc(var(--header-height) + 48px);right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3)}}:host .active-marker{position:absolute;top:0;left:0;width:2px;height:calc(var(--on-page-navigation-item-height) / 2);border-radius:2px;background-color:var(--primary-1);transition:top .25s cubic-bezier(0,1,.5,1),opacity .25s}\n"] }]
3396
+ args: [{ selector: 'table-of-content', standalone: true, imports: [TableOfContentItemsComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let data = tocData();\n@if (data) {\n <div class=\"title\">{{ title || 'In this article' }}</div>\n <ul f-table-of-content-items [items]=\"data.tree\"></ul>\n <div class=\"active-marker\" [style.top]=\"activeMarkerPosition() + 'px'\"></div>\n}\n\n", styles: [":host{--on-page-navigation-item-height: 32px;display:none;padding-left:16px;border-left:1px solid var(--divider-color);font-size:13px;font-weight:500;position:relative}:host .title{line-height:32px;font-size:14px;font-weight:600}@media(min-width:1280px){:host{display:block;width:var(--on-page-navigation-width);position:fixed;top:calc(var(--header-height) + 48px);right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 3)}}:host .active-marker{position:absolute;top:0;left:0;width:2px;height:calc(var(--on-page-navigation-item-height) / 2);border-radius:2px;background-color:var(--primary-1);transition:top .25s cubic-bezier(0,1,.5,1),opacity .25s}\n"] }]
2854
3397
  }], propDecorators: { _click: [{
2855
3398
  type: HostListener,
2856
3399
  args: ['click', ['$event']]
@@ -2861,12 +3404,17 @@ const SCROLLABLE_CONTAINER = new InjectionToken('SCROLLABLE_CONTAINER');
2861
3404
  class ScrollableContainer {
2862
3405
  _destroyRef = inject(DestroyRef);
2863
3406
  _injector = inject(Injector);
3407
+ _markdown = inject(MarkdownService);
2864
3408
  tableOfContent = inject(DOCUMENTATION_CONFIGURATION).tableOfContent;
3409
+ canShowTableOfContent = computed(() => {
3410
+ return !!this.tableOfContent && !this._markdown.pageLayout().hideTableOfContent;
3411
+ }, ...(ngDevMode ? [{ debugName: "canShowTableOfContent" }] : []));
2865
3412
  htmlElement = inject((ElementRef)).nativeElement;
2866
3413
  ngOnInit() {
2867
3414
  fromEvent(this.htmlElement, 'scroll', { passive: true })
2868
3415
  .pipe(debounceTime(100), startWith(null), filter((event) => {
2869
- const ignoreProgrammatic = event?.target?._ignoreProgrammatic ?? false;
3416
+ const target = event?.target;
3417
+ const ignoreProgrammatic = target?._ignoreProgrammatic ?? false;
2870
3418
  this.htmlElement._ignoreProgrammatic = false;
2871
3419
  return !ignoreProgrammatic;
2872
3420
  }), takeUntilDestroyed(this._destroyRef))
@@ -2875,8 +3423,8 @@ class ScrollableContainer {
2875
3423
  _calculateHashAndActivate() {
2876
3424
  this._injector.get(CalculateHashFromScrollPosition).handle();
2877
3425
  }
2878
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollableContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2879
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: ScrollableContainer, isStandalone: true, selector: "scrollable-container", providers: [
3426
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollableContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3427
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: ScrollableContainer, isStandalone: true, selector: "scrollable-container", providers: [
2880
3428
  {
2881
3429
  provide: SCROLLABLE_CONTAINER,
2882
3430
  useExisting: forwardRef(() => ScrollableContainer),
@@ -2885,9 +3433,9 @@ class ScrollableContainer {
2885
3433
  ...DYNAMIC_COMPONENTS_MODULE_PROVIDERS,
2886
3434
  ...TABLE_OF_CONTENT_MODULE_PROVIDERS,
2887
3435
  MarkdownService,
2888
- ], ngImport: i0, template: "<ng-content></ng-content>\n@if (tableOfContent) {\n <table-of-content />\n}\n\n\n\n", styles: [":host{position:relative;width:100%;height:100%;overflow:hidden;overflow-y:auto;scrollbar-gutter:stable}\n"], dependencies: [{ kind: "component", type: TableOfContent, selector: "table-of-content" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3436
+ ], ngImport: i0, template: "<ng-content></ng-content>\n@if (canShowTableOfContent()) {\n <table-of-content />\n}\n\n\n", styles: [":host{position:relative;width:100%;height:100%;overflow:hidden;overflow-y:auto;scrollbar-gutter:stable}\n"], dependencies: [{ kind: "component", type: TableOfContent, selector: "table-of-content" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2889
3437
  }
2890
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollableContainer, decorators: [{
3438
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollableContainer, decorators: [{
2891
3439
  type: Component,
2892
3440
  args: [{ selector: 'scrollable-container', standalone: true, providers: [
2893
3441
  {
@@ -2900,7 +3448,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
2900
3448
  MarkdownService,
2901
3449
  ], changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2902
3450
  TableOfContent,
2903
- ], template: "<ng-content></ng-content>\n@if (tableOfContent) {\n <table-of-content />\n}\n\n\n\n", styles: [":host{position:relative;width:100%;height:100%;overflow:hidden;overflow-y:auto;scrollbar-gutter:stable}\n"] }]
3451
+ ], template: "<ng-content></ng-content>\n@if (canShowTableOfContent()) {\n <table-of-content />\n}\n\n\n", styles: [":host{position:relative;width:100%;height:100%;overflow:hidden;overflow-y:auto;scrollbar-gutter:stable}\n"] }]
2904
3452
  }] });
2905
3453
 
2906
3454
  class MarkdownRenderer {
@@ -2950,15 +3498,15 @@ class MarkdownRenderer {
2950
3498
  ngOnDestroy() {
2951
3499
  this._dynamicComponents.dispose();
2952
3500
  }
2953
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2954
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: MarkdownRenderer, isStandalone: true, selector: "markdown-renderer", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "click": "_onDocumentClick($event)" }, classAttribute: "m-render" }, ngImport: i0, template: "<div [innerHTML]=\"value()\"></div>\n@if (value()) {\n <markdown-footer />\n}\n\n", styles: [":host{display:block;width:100%}@media (min-width: 1280px){:host{width:calc(100% - var(--on-page-navigation-width) - var(--page-padding))}}:host.empty-navigation{margin:auto;max-width:900px}\n"], dependencies: [{ kind: "component", type: MarkdownFooter, selector: "markdown-footer" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3501
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3502
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: MarkdownRenderer, isStandalone: true, selector: "markdown-renderer", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "click": "_onDocumentClick($event)" }, classAttribute: "m-render" }, ngImport: i0, template: "<div [innerHTML]=\"value()\"></div>\n@if (value()) {\n <markdown-footer />\n}\n\n", styles: [":host{display:block;width:100%}@media(min-width:1280px){:host{width:calc(100% - var(--on-page-navigation-width) - var(--page-padding))}}@media(min-width:1280px){:host.expand-no-toc{width:100%}}:host.empty-navigation{margin:auto;max-width:900px}\n"], dependencies: [{ kind: "component", type: MarkdownFooter, selector: "markdown-footer" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2955
3503
  }
2956
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownRenderer, decorators: [{
3504
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRenderer, decorators: [{
2957
3505
  type: Component,
2958
3506
  args: [{ selector: 'markdown-renderer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MarkdownFooter], host: {
2959
3507
  class: 'm-render',
2960
- }, template: "<div [innerHTML]=\"value()\"></div>\n@if (value()) {\n <markdown-footer />\n}\n\n", styles: [":host{display:block;width:100%}@media (min-width: 1280px){:host{width:calc(100% - var(--on-page-navigation-width) - var(--page-padding))}}:host.empty-navigation{margin:auto;max-width:900px}\n"] }]
2961
- }], propDecorators: { _onDocumentClick: [{
3508
+ }, template: "<div [innerHTML]=\"value()\"></div>\n@if (value()) {\n <markdown-footer />\n}\n\n", styles: [":host{display:block;width:100%}@media(min-width:1280px){:host{width:calc(100% - var(--on-page-navigation-width) - var(--page-padding))}}@media(min-width:1280px){:host.expand-no-toc{width:100%}}:host.empty-navigation{margin:auto;max-width:900px}\n"] }]
3509
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], _onDocumentClick: [{
2962
3510
  type: HostListener,
2963
3511
  args: ['click', ['$event']]
2964
3512
  }] } });
@@ -2968,26 +3516,31 @@ class MarkdownRouter {
2968
3516
  _activatedRoute = inject(ActivatedRoute);
2969
3517
  _markdown = inject(MarkdownService);
2970
3518
  _dataProvider = inject(DocumentationStore);
3519
+ _metaService = inject(FMetaService, { optional: true });
2971
3520
  emptyNavigation = !this._dataProvider.getNavigation().length;
3521
+ shouldExpandContent = computed(() => {
3522
+ const layout = this._markdown.pageLayout();
3523
+ return layout.hideTableOfContent && layout.expandContentWithoutTableOfContent;
3524
+ }, ...(ngDevMode ? [{ debugName: "shouldExpandContent" }] : []));
2972
3525
  _path$ = this._router.events.pipe(startWith(null), filter((e) => e === null || e instanceof NavigationEnd), map(() => this._activatedRoute.snapshot.url.map(u => u.path).join('/')), distinctUntilChanged());
2973
3526
  html = toSignal(this._path$.pipe(switchMap(path => {
2974
3527
  const url = this._dataProvider.getMarkdownUrl(path);
2975
3528
  return this._markdown.parseUrl(url).pipe(catchError(err => {
2976
3529
  console.error('[MarkdownRouter] parse error:', err, { path, url });
2977
3530
  return of(undefined); // или return EMPTY;
2978
- }));
3531
+ }), tap(() => this._metaService?.applyMarkdownSeo(this._markdown.pageSeo())));
2979
3532
  })), { initialValue: undefined });
2980
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownRouter, deps: [], target: i0.ɵɵFactoryTarget.Component });
2981
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: MarkdownRouter, isStandalone: true, selector: "markdown-router", host: { attributes: { "ngSkipHydration": "" }, properties: { "class.empty-navigation": "emptyNavigation" } }, ngImport: i0, template: "<markdown-renderer [value]=\"html()\" [class.empty-navigation]=\"emptyNavigation\"/>\n\n", styles: [":host{display:block;width:100%;padding:48px var(--page-padding) 140px}@media (min-width: 1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media (min-width: 1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}\n"], dependencies: [{ kind: "component", type: MarkdownRenderer, selector: "markdown-renderer", inputs: ["value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3533
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRouter, deps: [], target: i0.ɵɵFactoryTarget.Component });
3534
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: MarkdownRouter, isStandalone: true, selector: "markdown-router", host: { attributes: { "ngSkipHydration": "" }, properties: { "class.empty-navigation": "emptyNavigation" } }, ngImport: i0, template: "<markdown-renderer [value]=\"html()\"\n [class.empty-navigation]=\"emptyNavigation\"\n [class.expand-no-toc]=\"shouldExpandContent()\"/>\n", styles: [":host{display:block;width:100%;padding:48px var(--page-padding) 140px}@media(min-width:1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media(min-width:1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}\n"], dependencies: [{ kind: "component", type: MarkdownRenderer, selector: "markdown-renderer", inputs: ["value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2982
3535
  }
2983
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownRouter, decorators: [{
3536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRouter, decorators: [{
2984
3537
  type: Component,
2985
3538
  args: [{ selector: 'markdown-router', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
2986
3539
  'ngSkipHydration': '',
2987
3540
  '[class.empty-navigation]': 'emptyNavigation',
2988
3541
  }, imports: [
2989
3542
  MarkdownRenderer,
2990
- ], template: "<markdown-renderer [value]=\"html()\" [class.empty-navigation]=\"emptyNavigation\"/>\n\n", styles: [":host{display:block;width:100%;padding:48px var(--page-padding) 140px}@media (min-width: 1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media (min-width: 1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}\n"] }]
3543
+ ], template: "<markdown-renderer [value]=\"html()\"\n [class.empty-navigation]=\"emptyNavigation\"\n [class.expand-no-toc]=\"shouldExpandContent()\"/>\n", styles: [":host{display:block;width:100%;padding:48px var(--page-padding) 140px}@media(min-width:1280px){:host{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 4)}}@media(min-width:1280px){:host.empty-navigation{padding-right:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2);padding-left:max(var(--page-padding),(100vw - var(--layout-max-width)) / 2)}}\n"] }]
2991
3544
  }] });
2992
3545
 
2993
3546
  var index$2 = /*#__PURE__*/Object.freeze({
@@ -3020,8 +3573,8 @@ class Documentation {
3020
3573
  this._metaService.dispose();
3021
3574
  // Cleanup logic if needed
3022
3575
  }
3023
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Documentation, deps: [], target: i0.ɵɵFactoryTarget.Component });
3024
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: Documentation, isStandalone: true, selector: "documentation", providers: [
3576
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Documentation, deps: [], target: i0.ɵɵFactoryTarget.Component });
3577
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: Documentation, isStandalone: true, selector: "documentation", providers: [
3025
3578
  DocumentationStore,
3026
3579
  FMetaService,
3027
3580
  {
@@ -3052,9 +3605,9 @@ class Documentation {
3052
3605
  deps: [DocumentationStore],
3053
3606
  useFactory: (store) => store.getShowcaseItems(),
3054
3607
  },
3055
- ], ngImport: i0, template: "@if (!emptyNavigation) {\n <f-navigation-panel [class.visible]=\"isNavigationVisible()\"/>\n <div class=\"f-backdrop\" [class.visible]=\"isNavigationVisible()\" (click)=\"onToggleNavigation(false)\"></div>\n}\n\n<scrollable-container>\n <f-header [class.empty-navigation]=\"emptyNavigation\"/>\n <router-outlet/>\n</scrollable-container>\n\n@if (popover()) {\n <div class=\"popover\">{{ popover() }}</div>\n}\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:flex-start;height:100%;gap:5px}.f-backdrop{position:fixed;inset:0;opacity:0;z-index:var(--z-index-backdrop);background:var(--backdrop-color);transition:opacity .2s ease-in-out;pointer-events:none}.f-backdrop.visible{opacity:1;pointer-events:all}@media (min-width: 960px){.f-backdrop{position:unset}}.popover{position:fixed;min-width:120px;bottom:50%;left:50%;text-align:center;transform:translate(-50%,-50%);background-color:var(--code-view-copy-button-hover-background);border:1px solid var(--code-view-copy-button-border-color);box-shadow:var(--shadow-3);color:var(--primary-text);font-size:14px;padding:4px 8px;border-radius:4px;z-index:var(--z-index-popover);opacity:1}\n"], dependencies: [{ kind: "component", type: NavigationPanelComponent, selector: "f-navigation-panel" }, { kind: "component", type: ScrollableContainer, selector: "scrollable-container" }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: HeaderComponent, selector: "f-header" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./foblex-m-render-cookie-popup.component-Cx-ELX3C.mjs').then(m => m.CookiePopupComponent)]] });
3608
+ ], ngImport: i0, template: "@if (!emptyNavigation) {\n <f-navigation-panel [class.visible]=\"isNavigationVisible()\"/>\n <div class=\"f-backdrop\" [class.visible]=\"isNavigationVisible()\" (click)=\"onToggleNavigation(false)\"></div>\n}\n\n<scrollable-container>\n <f-header [class.empty-navigation]=\"emptyNavigation\"/>\n <router-outlet/>\n</scrollable-container>\n\n@if (popover()) {\n <div class=\"popover\">{{ popover() }}</div>\n}\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:flex-start;height:100%;gap:5px}.f-backdrop{position:fixed;inset:0;opacity:0;z-index:var(--z-index-backdrop);background:var(--backdrop-color);transition:opacity .2s ease-in-out;pointer-events:none}.f-backdrop.visible{opacity:1;pointer-events:all}@media(min-width:960px){.f-backdrop{position:unset}}.popover{position:fixed;min-width:120px;bottom:50%;left:50%;text-align:center;transform:translate(-50%,-50%);background-color:var(--code-view-copy-button-hover-background);border:1px solid var(--code-view-copy-button-border-color);box-shadow:var(--shadow-3);color:var(--primary-text);font-size:14px;padding:4px 8px;border-radius:4px;z-index:var(--z-index-popover);opacity:1}\n"], dependencies: [{ kind: "component", type: NavigationPanelComponent, selector: "f-navigation-panel" }, { kind: "component", type: ScrollableContainer, selector: "scrollable-container" }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: HeaderComponent, selector: "f-header" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./foblex-m-render-cookie-popup-DzpgC1SS.mjs').then(m => m.CookiePopup)]] });
3056
3609
  }
3057
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.8", ngImport: i0, type: Documentation, resolveDeferredDeps: () => [import('./foblex-m-render-cookie-popup.component-Cx-ELX3C.mjs').then(m => m.CookiePopupComponent)], resolveMetadata: CookiePopupComponent => ({ decorators: [{
3610
+ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.1.4", ngImport: i0, type: Documentation, resolveDeferredDeps: () => [import('./foblex-m-render-cookie-popup-DzpgC1SS.mjs').then(m => m.CookiePopup)], resolveMetadata: CookiePopup => ({ decorators: [{
3058
3611
  type: Component,
3059
3612
  args: [{ selector: 'documentation', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3060
3613
  DocumentationStore,
@@ -3092,8 +3645,8 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.8", ng
3092
3645
  ScrollableContainer,
3093
3646
  RouterOutlet,
3094
3647
  HeaderComponent,
3095
- CookiePopupComponent,
3096
- ], template: "@if (!emptyNavigation) {\n <f-navigation-panel [class.visible]=\"isNavigationVisible()\"/>\n <div class=\"f-backdrop\" [class.visible]=\"isNavigationVisible()\" (click)=\"onToggleNavigation(false)\"></div>\n}\n\n<scrollable-container>\n <f-header [class.empty-navigation]=\"emptyNavigation\"/>\n <router-outlet/>\n</scrollable-container>\n\n@if (popover()) {\n <div class=\"popover\">{{ popover() }}</div>\n}\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:flex-start;height:100%;gap:5px}.f-backdrop{position:fixed;inset:0;opacity:0;z-index:var(--z-index-backdrop);background:var(--backdrop-color);transition:opacity .2s ease-in-out;pointer-events:none}.f-backdrop.visible{opacity:1;pointer-events:all}@media (min-width: 960px){.f-backdrop{position:unset}}.popover{position:fixed;min-width:120px;bottom:50%;left:50%;text-align:center;transform:translate(-50%,-50%);background-color:var(--code-view-copy-button-hover-background);border:1px solid var(--code-view-copy-button-border-color);box-shadow:var(--shadow-3);color:var(--primary-text);font-size:14px;padding:4px 8px;border-radius:4px;z-index:var(--z-index-popover);opacity:1}\n"] }]
3648
+ CookiePopup,
3649
+ ], template: "@if (!emptyNavigation) {\n <f-navigation-panel [class.visible]=\"isNavigationVisible()\"/>\n <div class=\"f-backdrop\" [class.visible]=\"isNavigationVisible()\" (click)=\"onToggleNavigation(false)\"></div>\n}\n\n<scrollable-container>\n <f-header [class.empty-navigation]=\"emptyNavigation\"/>\n <router-outlet/>\n</scrollable-container>\n\n@if (popover()) {\n <div class=\"popover\">{{ popover() }}</div>\n}\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;justify-content:flex-start;align-items:flex-start;height:100%;gap:5px}.f-backdrop{position:fixed;inset:0;opacity:0;z-index:var(--z-index-backdrop);background:var(--backdrop-color);transition:opacity .2s ease-in-out;pointer-events:none}.f-backdrop.visible{opacity:1;pointer-events:all}@media(min-width:960px){.f-backdrop{position:unset}}.popover{position:fixed;min-width:120px;bottom:50%;left:50%;text-align:center;transform:translate(-50%,-50%);background-color:var(--code-view-copy-button-hover-background);border:1px solid var(--code-view-copy-button-border-color);box-shadow:var(--shadow-3);color:var(--primary-text);font-size:14px;padding:4px 8px;border-radius:4px;z-index:var(--z-index-popover);opacity:1}\n"] }]
3097
3650
  }], ctorParameters: null, propDecorators: null }) });
3098
3651
 
3099
3652
  const DOCUMENTATION_ROUTES = [
@@ -3118,6 +3671,7 @@ var index$1 = /*#__PURE__*/Object.freeze({
3118
3671
  CalculateHashFromScrollPosition: CalculateHashFromScrollPosition,
3119
3672
  get CalculateTableOfContent () { return CalculateTableOfContent; },
3120
3673
  CalculateTableOfContentRequest: CalculateTableOfContentRequest,
3674
+ DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS: DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS,
3121
3675
  DOCUMENTATION_CONFIGURATION: DOCUMENTATION_CONFIGURATION,
3122
3676
  DOCUMENTATION_ROUTES: DOCUMENTATION_ROUTES,
3123
3677
  Documentation: Documentation,
@@ -3255,84 +3809,85 @@ class HomeStore {
3255
3809
  getImageComponent() {
3256
3810
  return this._configuration.image;
3257
3811
  }
3258
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HomeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3259
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HomeStore });
3812
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3813
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeStore });
3260
3814
  }
3261
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HomeStore, decorators: [{
3815
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeStore, decorators: [{
3262
3816
  type: Injectable
3263
3817
  }] });
3264
3818
 
3265
3819
  class FHomePageButtonsRowComponent {
3266
3820
  viewModel = inject(HomeStore).getButtons();
3267
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageButtonsRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3268
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: FHomePageButtonsRowComponent, isStandalone: true, selector: "f-home-page-buttons-row", host: { properties: { "class.display-none": "!viewModel.length" } }, ngImport: i0, template: "@for (button of viewModel; track button.text) {\n @if (button.routerLink) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" routerLink=\"{{ button.routerLink }}\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n } @else if(button.href) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" href=\"{{ button.href }}\" target=\"_blank\" rel=\"noopener noreferrer\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n }\n}\n\n", styles: [":host{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;width:fit-content;margin:0 auto;padding:32px 10px 0}@media (min-width: 960px){:host{margin:0;padding:32px 0 0;justify-content:flex-start}}.f-button{display:flex;align-items:center;gap:6px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
3821
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageButtonsRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3822
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: FHomePageButtonsRowComponent, isStandalone: true, selector: "f-home-page-buttons-row", host: { properties: { "class.display-none": "!viewModel.length" } }, ngImport: i0, template: "@for (button of viewModel; track button.text) {\n @if (button.routerLink) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" routerLink=\"{{ button.routerLink }}\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n } @else if(button.href) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" href=\"{{ button.href }}\" target=\"_blank\" rel=\"noopener noreferrer\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n }\n}\n\n", styles: [":host{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;width:fit-content;margin:0 auto;padding:32px 10px 0}@media(min-width:960px){:host{margin:0;padding:32px 0 0;justify-content:flex-start}}.f-button{display:flex;align-items:center;gap:6px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
3269
3823
  }
3270
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageButtonsRowComponent, decorators: [{
3824
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageButtonsRowComponent, decorators: [{
3271
3825
  type: Component,
3272
3826
  args: [{ selector: 'f-home-page-buttons-row', standalone: true, imports: [
3273
3827
  RouterLink,
3274
3828
  ], host: {
3275
3829
  '[class.display-none]': '!viewModel.length',
3276
- }, template: "@for (button of viewModel; track button.text) {\n @if (button.routerLink) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" routerLink=\"{{ button.routerLink }}\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n } @else if(button.href) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" href=\"{{ button.href }}\" target=\"_blank\" rel=\"noopener noreferrer\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n }\n}\n\n", styles: [":host{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;width:fit-content;margin:0 auto;padding:32px 10px 0}@media (min-width: 960px){:host{margin:0;padding:32px 0 0;justify-content:flex-start}}.f-button{display:flex;align-items:center;gap:6px}\n"] }]
3830
+ }, template: "@for (button of viewModel; track button.text) {\n @if (button.routerLink) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" routerLink=\"{{ button.routerLink }}\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n } @else if(button.href) {\n <a class=\"f-button\" [class.primary]=\"button.primary\" href=\"{{ button.href }}\" target=\"_blank\" rel=\"noopener noreferrer\">\n @if (button.icon) {\n <span class=\"f-icon {{ button.icon }}\"></span>\n }\n {{ button.text }}\n </a>\n }\n}\n\n", styles: [":host{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;width:fit-content;margin:0 auto;padding:32px 10px 0}@media(min-width:960px){:host{margin:0;padding:32px 0 0;justify-content:flex-start}}.f-button{display:flex;align-items:center;gap:6px}\n"] }]
3277
3831
  }] });
3278
3832
 
3279
3833
  class FHomePageFeaturesComponent {
3280
3834
  viewModel = inject(HomeStore).getFeatures();
3281
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageFeaturesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3282
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: FHomePageFeaturesComponent, isStandalone: true, selector: "f-home-page-features", host: { properties: { "class.display-none": "!viewModel.length" } }, ngImport: i0, template: "<div class=\"feature-list\">\n @for (feature of viewModel; track feature.headline) {\n <div class=\"feature\">\n <h2>{{ feature.headline }}</h2>\n <p>{{ feature.description }}</p>\n </div>\n }\n</div>\n\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .feature-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .feature{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;pointer-events:all}:host .feature h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .feature p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}@media (min-width: 640px){:host{padding:0 48px}:host .feature{width:calc(50% - 12px)}}@media (min-width: 960px){:host{padding:0 64px}:host .feature{width:calc(25% - 12px)}}\n"] });
3835
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFeaturesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3836
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: FHomePageFeaturesComponent, isStandalone: true, selector: "f-home-page-features", host: { properties: { "class.display-none": "!viewModel.length" } }, ngImport: i0, template: "<div class=\"feature-list\">\n @for (feature of viewModel; track feature.headline) {\n <div class=\"feature\">\n <h2>{{ feature.headline }}</h2>\n <p>{{ feature.description }}</p>\n </div>\n }\n</div>\n\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .feature-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .feature{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;pointer-events:all}:host .feature h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .feature p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}@media(min-width:640px){:host{padding:0 48px}:host .feature{width:calc(50% - 12px)}}@media(min-width:960px){:host{padding:0 64px}:host .feature{width:calc(25% - 12px)}}\n"] });
3283
3837
  }
3284
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageFeaturesComponent, decorators: [{
3838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFeaturesComponent, decorators: [{
3285
3839
  type: Component,
3286
3840
  args: [{ selector: 'f-home-page-features', standalone: true, host: {
3287
3841
  '[class.display-none]': '!viewModel.length',
3288
- }, template: "<div class=\"feature-list\">\n @for (feature of viewModel; track feature.headline) {\n <div class=\"feature\">\n <h2>{{ feature.headline }}</h2>\n <p>{{ feature.description }}</p>\n </div>\n }\n</div>\n\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .feature-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .feature{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;pointer-events:all}:host .feature h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .feature p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}@media (min-width: 640px){:host{padding:0 48px}:host .feature{width:calc(50% - 12px)}}@media (min-width: 960px){:host{padding:0 64px}:host .feature{width:calc(25% - 12px)}}\n"] }]
3842
+ }, template: "<div class=\"feature-list\">\n @for (feature of viewModel; track feature.headline) {\n <div class=\"feature\">\n <h2>{{ feature.headline }}</h2>\n <p>{{ feature.description }}</p>\n </div>\n }\n</div>\n\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .feature-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .feature{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;pointer-events:all}:host .feature h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .feature p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}@media(min-width:640px){:host{padding:0 48px}:host .feature{width:calc(50% - 12px)}}@media(min-width:960px){:host{padding:0 64px}:host .feature{width:calc(25% - 12px)}}\n"] }]
3289
3843
  }] });
3290
3844
 
3291
3845
  class FHomePageFooterComponent {
3292
3846
  viewModel = inject(HomeStore).getFooter();
3293
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3294
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: FHomePageFooterComponent, isStandalone: true, selector: "footer[f-home-page-footer]", ngImport: i0, template: "<div class=\"content\">\n <div class=\"flex-space\"></div>\n <div>\n <div class=\"item\">Created with Foblex <a href=\"https://m-render.foblex.com/\" target=\"_blank\">MRender</a></div>\n <div class=\"item\">{{ viewModel.text }}</div>\n </div>\n</div>\n\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .content{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;width:100%;height:64px;max-width:1376px;margin:0 auto}:host .item{line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);text-align:right}@media (min-width: 640px){:host{padding:0 48px}}@media (min-width: 960px){:host{padding:0 64px}}\n"] });
3847
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3848
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: FHomePageFooterComponent, isStandalone: true, selector: "footer[f-home-page-footer]", ngImport: i0, template: "<div class=\"content\">\n <div class=\"flex-space\"></div>\n <div>\n <div class=\"item\">Created with Foblex <a href=\"https://m-render.foblex.com/\" target=\"_blank\">MRender</a></div>\n <div class=\"item\">{{ viewModel.text }}</div>\n </div>\n</div>\n\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .content{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;width:100%;height:64px;max-width:1376px;margin:0 auto}:host .item{line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);text-align:right}@media(min-width:640px){:host{padding:0 48px}}@media(min-width:960px){:host{padding:0 64px}}\n"] });
3295
3849
  }
3296
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageFooterComponent, decorators: [{
3850
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFooterComponent, decorators: [{
3297
3851
  type: Component,
3298
- args: [{ selector: 'footer[f-home-page-footer]', standalone: true, template: "<div class=\"content\">\n <div class=\"flex-space\"></div>\n <div>\n <div class=\"item\">Created with Foblex <a href=\"https://m-render.foblex.com/\" target=\"_blank\">MRender</a></div>\n <div class=\"item\">{{ viewModel.text }}</div>\n </div>\n</div>\n\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .content{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;width:100%;height:64px;max-width:1376px;margin:0 auto}:host .item{line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);text-align:right}@media (min-width: 640px){:host{padding:0 48px}}@media (min-width: 960px){:host{padding:0 64px}}\n"] }]
3852
+ args: [{ selector: 'footer[f-home-page-footer]', standalone: true, template: "<div class=\"content\">\n <div class=\"flex-space\"></div>\n <div>\n <div class=\"item\">Created with Foblex <a href=\"https://m-render.foblex.com/\" target=\"_blank\">MRender</a></div>\n <div class=\"item\">{{ viewModel.text }}</div>\n </div>\n</div>\n\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .content{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;width:100%;height:64px;max-width:1376px;margin:0 auto}:host .item{line-height:20px;font-size:12px;font-weight:500;color:var(--secondary-text);text-align:right}@media(min-width:640px){:host{padding:0 48px}}@media(min-width:960px){:host{padding:0 64px}}\n"] }]
3299
3853
  }] });
3300
3854
 
3301
3855
  class FHomePageHeaderComponent {
3302
3856
  logo = inject(HomeStore).getLogo();
3303
3857
  title = inject(HomeStore).getTitle();
3304
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3305
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: FHomePageHeaderComponent, isStandalone: true, selector: "header[f-home-page-header]", ngImport: i0, template: "<div class=\"content\">\n <a class=\"logo-link\" href=\"\" aria-label=\"Home\">\n <img [src]=\"logo\" class=\"logo\" alt=\"{{ title }} Logo\" width=\"24\" height=\"24\"/>\n <span class=\"title\">{{ title }}</span>\n </a>\n\n <div class=\"flex-space\"></div>\n <button theme-button aria-label=\"Change theme\"></button>\n</div>\n\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .logo-link{display:flex;align-items:center;text-decoration:none}:host .content{display:flex;justify-content:flex-start;align-items:center;width:100%;height:64px;max-width:1376px;margin:0 auto}:host .logo{margin-right:8px}:host .title{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;font-size:16px;font-weight:600;color:var(--primary-text)}@media (min-width: 640px){:host{padding:0 48px}}@media (min-width: 960px){:host{padding:0 64px}}.divider{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--divider-color);content:\"\"}\n"], dependencies: [{ kind: "component", type: ThemeButtonComponent, selector: "button[theme-button]" }] });
3858
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3859
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: FHomePageHeaderComponent, isStandalone: true, selector: "header[f-home-page-header]", ngImport: i0, template: "<div class=\"content\">\n <f-brand-link class=\"logo-link\" [title]=\"title\" [logo]=\"logo\" [logoAlt]=\"title + ' Logo'\" />\n\n <div class=\"flex-space\"></div>\n <button theme-button aria-label=\"Change theme\"></button>\n</div>\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .logo-link{display:flex;align-items:center;color:var(--primary-text);font-size:16px;font-weight:600;width:100%;min-width:0}:host .content{display:flex;justify-content:flex-start;align-items:center;width:100%;height:64px;max-width:1376px;margin:0 auto}@media(min-width:640px){:host{padding:0 48px}}@media(min-width:960px){:host{padding:0 64px}}\n"], dependencies: [{ kind: "component", type: FBrandLinkComponent, selector: "f-brand-link", inputs: ["title", "logo", "ariaLabel", "logoAlt", "href", "routerLink"] }, { kind: "component", type: ThemeButtonComponent, selector: "button[theme-button]" }] });
3306
3860
  }
3307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageHeaderComponent, decorators: [{
3861
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeaderComponent, decorators: [{
3308
3862
  type: Component,
3309
3863
  args: [{ selector: 'header[f-home-page-header]', standalone: true, imports: [
3864
+ FBrandLinkComponent,
3310
3865
  ThemeButtonComponent,
3311
- ], template: "<div class=\"content\">\n <a class=\"logo-link\" href=\"\" aria-label=\"Home\">\n <img [src]=\"logo\" class=\"logo\" alt=\"{{ title }} Logo\" width=\"24\" height=\"24\"/>\n <span class=\"title\">{{ title }}</span>\n </a>\n\n <div class=\"flex-space\"></div>\n <button theme-button aria-label=\"Change theme\"></button>\n</div>\n\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .logo-link{display:flex;align-items:center;text-decoration:none}:host .content{display:flex;justify-content:flex-start;align-items:center;width:100%;height:64px;max-width:1376px;margin:0 auto}:host .logo{margin-right:8px}:host .title{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;font-size:16px;font-weight:600;color:var(--primary-text)}@media (min-width: 640px){:host{padding:0 48px}}@media (min-width: 960px){:host{padding:0 64px}}.divider{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--divider-color);content:\"\"}\n"] }]
3866
+ ], template: "<div class=\"content\">\n <f-brand-link class=\"logo-link\" [title]=\"title\" [logo]=\"logo\" [logoAlt]=\"title + ' Logo'\" />\n\n <div class=\"flex-space\"></div>\n <button theme-button aria-label=\"Change theme\"></button>\n</div>\n", styles: [":host{position:relative;z-index:5;padding:0 24px}:host .logo-link{display:flex;align-items:center;color:var(--primary-text);font-size:16px;font-weight:600;width:100%;min-width:0}:host .content{display:flex;justify-content:flex-start;align-items:center;width:100%;height:64px;max-width:1376px;margin:0 auto}@media(min-width:640px){:host{padding:0 48px}}@media(min-width:960px){:host{padding:0 64px}}\n"] }]
3312
3867
  }] });
3313
3868
 
3314
3869
  class FHomePageHeroComponent {
3315
3870
  viewModel = inject(HomeStore).getHero();
3316
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageHeroComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3317
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: FHomePageHeroComponent, isStandalone: true, selector: "f-home-page-hero", ngImport: i0, template: "<h1>{{ viewModel.headline }}</h1>\n<p class=\"powered\">{{ viewModel.tagline1 }}</p>\n<p class=\"powered\">{{ viewModel.tagline2 }}</p>\n<p class=\"second-description\">{{ viewModel.subDescription }}</p>\n<f-home-page-buttons-row></f-home-page-buttons-row>\n", styles: [":host{display:block;width:100%;padding:0 10px}@media (min-width: 640px){:host{padding:0;width:100%}}@media (min-width: 960px){:host{width:50%}}.powered,h1{letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;width:fit-content;margin:0 auto;text-align:center;white-space:pre-wrap;pointer-events:all}@media (min-width: 640px){.powered,h1{line-height:56px;font-size:48px}}@media (min-width: 960px){.powered,h1{line-height:64px;font-size:56px;margin:0;text-align:left}}h1{background:-webkit-linear-gradient(120deg,#bd34fe 30%,#41d1ff);-webkit-background-clip:text;background-clip:text;color:transparent}.second-description{line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--secondary-text);margin:0 auto;width:fit-content;pointer-events:all;text-align:center;padding:8px 16px 0}@media (min-width: 640px){.second-description{padding-top:12px;line-height:32px;font-size:20px}}@media (min-width: 960px){.second-description{line-height:36px;font-size:24px;margin:0;text-align:left;padding:8px 0 0}}\n"], dependencies: [{ kind: "component", type: FHomePageButtonsRowComponent, selector: "f-home-page-buttons-row" }] });
3871
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeroComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3872
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.4", type: FHomePageHeroComponent, isStandalone: true, selector: "f-home-page-hero", ngImport: i0, template: "<h1>{{ viewModel.headline }}</h1>\n<p class=\"powered\">{{ viewModel.tagline1 }}</p>\n<p class=\"powered\">{{ viewModel.tagline2 }}</p>\n<p class=\"second-description\">{{ viewModel.subDescription }}</p>\n<f-home-page-buttons-row></f-home-page-buttons-row>\n", styles: [":host{display:block;width:100%;padding:0 10px}@media(min-width:640px){:host{padding:0;width:100%}}@media(min-width:960px){:host{width:50%}}.powered,h1{letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;width:fit-content;margin:0 auto;text-align:center;white-space:pre-wrap;pointer-events:all}@media(min-width:640px){.powered,h1{line-height:56px;font-size:48px}}@media(min-width:960px){.powered,h1{line-height:64px;font-size:56px;margin:0;text-align:left}}h1{background:-webkit-linear-gradient(120deg,#bd34fe 30%,#41d1ff);-webkit-background-clip:text;background-clip:text;color:transparent}.second-description{line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--secondary-text);margin:0 auto;width:fit-content;pointer-events:all;text-align:center;padding:8px 16px 0}@media(min-width:640px){.second-description{padding-top:12px;line-height:32px;font-size:20px}}@media(min-width:960px){.second-description{line-height:36px;font-size:24px;margin:0;text-align:left;padding:8px 0 0}}\n"], dependencies: [{ kind: "component", type: FHomePageButtonsRowComponent, selector: "f-home-page-buttons-row" }] });
3318
3873
  }
3319
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageHeroComponent, decorators: [{
3874
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeroComponent, decorators: [{
3320
3875
  type: Component,
3321
3876
  args: [{ selector: 'f-home-page-hero', standalone: true, imports: [
3322
3877
  FHomePageButtonsRowComponent,
3323
- ], template: "<h1>{{ viewModel.headline }}</h1>\n<p class=\"powered\">{{ viewModel.tagline1 }}</p>\n<p class=\"powered\">{{ viewModel.tagline2 }}</p>\n<p class=\"second-description\">{{ viewModel.subDescription }}</p>\n<f-home-page-buttons-row></f-home-page-buttons-row>\n", styles: [":host{display:block;width:100%;padding:0 10px}@media (min-width: 640px){:host{padding:0;width:100%}}@media (min-width: 960px){:host{width:50%}}.powered,h1{letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;width:fit-content;margin:0 auto;text-align:center;white-space:pre-wrap;pointer-events:all}@media (min-width: 640px){.powered,h1{line-height:56px;font-size:48px}}@media (min-width: 960px){.powered,h1{line-height:64px;font-size:56px;margin:0;text-align:left}}h1{background:-webkit-linear-gradient(120deg,#bd34fe 30%,#41d1ff);-webkit-background-clip:text;background-clip:text;color:transparent}.second-description{line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--secondary-text);margin:0 auto;width:fit-content;pointer-events:all;text-align:center;padding:8px 16px 0}@media (min-width: 640px){.second-description{padding-top:12px;line-height:32px;font-size:20px}}@media (min-width: 960px){.second-description{line-height:36px;font-size:24px;margin:0;text-align:left;padding:8px 0 0}}\n"] }]
3878
+ ], template: "<h1>{{ viewModel.headline }}</h1>\n<p class=\"powered\">{{ viewModel.tagline1 }}</p>\n<p class=\"powered\">{{ viewModel.tagline2 }}</p>\n<p class=\"second-description\">{{ viewModel.subDescription }}</p>\n<f-home-page-buttons-row></f-home-page-buttons-row>\n", styles: [":host{display:block;width:100%;padding:0 10px}@media(min-width:640px){:host{padding:0;width:100%}}@media(min-width:960px){:host{width:50%}}.powered,h1{letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;width:fit-content;margin:0 auto;text-align:center;white-space:pre-wrap;pointer-events:all}@media(min-width:640px){.powered,h1{line-height:56px;font-size:48px}}@media(min-width:960px){.powered,h1{line-height:64px;font-size:56px;margin:0;text-align:left}}h1{background:-webkit-linear-gradient(120deg,#bd34fe 30%,#41d1ff);-webkit-background-clip:text;background-clip:text;color:transparent}.second-description{line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--secondary-text);margin:0 auto;width:fit-content;pointer-events:all;text-align:center;padding:8px 16px 0}@media(min-width:640px){.second-description{padding-top:12px;line-height:32px;font-size:20px}}@media(min-width:960px){.second-description{line-height:36px;font-size:24px;margin:0;text-align:left;padding:8px 0 0}}\n"] }]
3324
3879
  }] });
3325
3880
 
3326
3881
  class FHomePageMembershipsComponent {
3327
3882
  viewModel = inject(HomeStore).getMemberships();
3328
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageMembershipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3329
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: FHomePageMembershipsComponent, isStandalone: true, selector: "f-home-page-memberships", host: { properties: { "class.display-none": "!viewModel.length" } }, ngImport: i0, template: "<div class=\"membership-list\">\n @for (membership of viewModel; track membership.id) {\n <div class=\"membership\">\n <h2>{{ membership.name }}</h2>\n <p>{{ membership.description }}</p>\n <div class=\"benefit-list\">\n @for (benefit of membership.benefits; track benefit) {\n <p class=\"benefit\">\u2705 {{ benefit }}</p>\n }\n </div>\n <a class=\"f-button\" [href]=\"membership.buttonRef\">{{ membership.buttonText }}</a>\n </div>\n }\n</div>\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .membership-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .membership{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;position:relative;pointer-events:all}:host .membership h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .membership p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}:host .membership .price{color:var(--primary-text);font-size:1.2rem;font-weight:700;padding-top:16px}:host .membership .price span{font-weight:600;color:var(--primary-color)}:host .membership .benefit-list{display:flex;flex-direction:column;padding:16px 0}@media (min-width: 640px){:host{padding:0 48px}:host .membership{width:calc(50% - 12px);min-width:unset}}@media (min-width: 960px){:host{padding:0 64px}:host .membership{width:calc(25% - 12px);min-width:300px}}.ribbon{position:absolute;top:-10px;right:-10px;color:var(--button-primary-text);background-color:var(--button-primary-bg);padding:4px 8px;font-size:.8rem;border-radius:2px}\n"] });
3883
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageMembershipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3884
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: FHomePageMembershipsComponent, isStandalone: true, selector: "f-home-page-memberships", host: { properties: { "class.display-none": "!viewModel.length" } }, ngImport: i0, template: "<div class=\"membership-list\">\n @for (membership of viewModel; track membership.id) {\n <div class=\"membership\">\n <h2>{{ membership.name }}</h2>\n <p>{{ membership.description }}</p>\n <div class=\"benefit-list\">\n @for (benefit of membership.benefits; track benefit) {\n <p class=\"benefit\">\u2705 {{ benefit }}</p>\n }\n </div>\n <a class=\"f-button\" [href]=\"membership.buttonRef\">{{ membership.buttonText }}</a>\n </div>\n }\n</div>\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .membership-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .membership{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;position:relative;pointer-events:all}:host .membership h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .membership p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}:host .membership .price{color:var(--primary-text);font-size:1.2rem;font-weight:700;padding-top:16px}:host .membership .price span{font-weight:600;color:var(--primary-color)}:host .membership .benefit-list{display:flex;flex-direction:column;padding:16px 0}@media(min-width:640px){:host{padding:0 48px}:host .membership{width:calc(50% - 12px);min-width:unset}}@media(min-width:960px){:host{padding:0 64px}:host .membership{width:calc(25% - 12px);min-width:300px}}.ribbon{position:absolute;top:-10px;right:-10px;color:var(--button-primary-text);background-color:var(--button-primary-bg);padding:4px 8px;font-size:.8rem;border-radius:2px}\n"] });
3330
3885
  }
3331
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageMembershipsComponent, decorators: [{
3886
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageMembershipsComponent, decorators: [{
3332
3887
  type: Component,
3333
3888
  args: [{ selector: 'f-home-page-memberships', standalone: true, host: {
3334
3889
  '[class.display-none]': '!viewModel.length',
3335
- }, template: "<div class=\"membership-list\">\n @for (membership of viewModel; track membership.id) {\n <div class=\"membership\">\n <h2>{{ membership.name }}</h2>\n <p>{{ membership.description }}</p>\n <div class=\"benefit-list\">\n @for (benefit of membership.benefits; track benefit) {\n <p class=\"benefit\">\u2705 {{ benefit }}</p>\n }\n </div>\n <a class=\"f-button\" [href]=\"membership.buttonRef\">{{ membership.buttonText }}</a>\n </div>\n }\n</div>\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .membership-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .membership{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;position:relative;pointer-events:all}:host .membership h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .membership p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}:host .membership .price{color:var(--primary-text);font-size:1.2rem;font-weight:700;padding-top:16px}:host .membership .price span{font-weight:600;color:var(--primary-color)}:host .membership .benefit-list{display:flex;flex-direction:column;padding:16px 0}@media (min-width: 640px){:host{padding:0 48px}:host .membership{width:calc(50% - 12px);min-width:unset}}@media (min-width: 960px){:host{padding:0 64px}:host .membership{width:calc(25% - 12px);min-width:300px}}.ribbon{position:absolute;top:-10px;right:-10px;color:var(--button-primary-text);background-color:var(--button-primary-bg);padding:4px 8px;font-size:.8rem;border-radius:2px}\n"] }]
3890
+ }, template: "<div class=\"membership-list\">\n @for (membership of viewModel; track membership.id) {\n <div class=\"membership\">\n <h2>{{ membership.name }}</h2>\n <p>{{ membership.description }}</p>\n <div class=\"benefit-list\">\n @for (benefit of membership.benefits; track benefit) {\n <p class=\"benefit\">\u2705 {{ benefit }}</p>\n }\n </div>\n <a class=\"f-button\" [href]=\"membership.buttonRef\">{{ membership.buttonText }}</a>\n </div>\n }\n</div>\n", styles: [":host{margin-top:64px;margin-bottom:64px;width:100%;display:block;padding:0 24px}:host .membership-list{margin:0 auto;display:flex;flex-wrap:wrap;gap:16px;max-width:1248px;pointer-events:none}:host .membership{width:100%;border-radius:4px;background-color:var(--soft-background);display:flex;flex-direction:column;padding:24px;position:relative;pointer-events:all}:host .membership h2{margin:0;line-height:24px;font-size:16px;font-weight:600}:host .membership p{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--secondary-text)}:host .membership .price{color:var(--primary-text);font-size:1.2rem;font-weight:700;padding-top:16px}:host .membership .price span{font-weight:600;color:var(--primary-color)}:host .membership .benefit-list{display:flex;flex-direction:column;padding:16px 0}@media(min-width:640px){:host{padding:0 48px}:host .membership{width:calc(50% - 12px);min-width:unset}}@media(min-width:960px){:host{padding:0 64px}:host .membership{width:calc(25% - 12px);min-width:300px}}.ribbon{position:absolute;top:-10px;right:-10px;color:var(--button-primary-text);background-color:var(--button-primary-bg);padding:4px 8px;font-size:.8rem;border-radius:2px}\n"] }]
3336
3891
  }] });
3337
3892
 
3338
3893
  class HomeRootComponent {
@@ -3372,12 +3927,12 @@ class HomeRootComponent {
3372
3927
  _requestComponentRedraw(componentRef) {
3373
3928
  componentRef.changeDetectorRef.markForCheck();
3374
3929
  }
3375
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HomeRootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3376
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: HomeRootComponent, isStandalone: true, selector: "home-root", providers: [
3930
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeRootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3931
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: HomeRootComponent, isStandalone: true, selector: "home-root", providers: [
3377
3932
  HomeStore,
3378
- ], viewQueries: [{ propertyName: "_backgroundContainer", first: true, predicate: ["backgroundContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_heroImageContainer", first: true, predicate: ["heroImageContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<ng-container #backgroundContainer></ng-container>\n<header f-home-page-header></header>\n\n<div class=\"body\">\n <div class=\"hero-row\">\n <f-home-page-hero></f-home-page-hero>\n <ng-container #heroImageContainer></ng-container>\n </div>\n <f-home-page-features></f-home-page-features>\n <f-home-page-memberships></f-home-page-memberships>\n</div>\n\n<div class=\"flex-space\"></div>\n<footer f-home-page-footer></footer>\n\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;flex-direction:column;position:relative;width:100%;height:100%;min-height:100%;overflow:hidden;overflow-y:auto}.body{position:relative;z-index:3;pointer-events:none}@media (min-width: 960px){.body{margin-top:50px}}@media (min-width: 1376px){.body{margin-top:100px}}.hero-row{display:flex;flex-direction:column-reverse;justify-content:space-between;align-items:center;margin:0 auto}@media (min-width: 960px){.hero-row{flex-direction:row;margin-left:64px;margin-right:64px}}@media (min-width: 1376px){.hero-row{flex-direction:row;margin-left:calc(50% - 624px);margin-right:calc(50% - 624px)}}\n"], dependencies: [{ kind: "component", type: FHomePageFooterComponent, selector: "footer[f-home-page-footer]" }, { kind: "component", type: FHomePageHeaderComponent, selector: "header[f-home-page-header]" }, { kind: "component", type: FHomePageFeaturesComponent, selector: "f-home-page-features" }, { kind: "component", type: FHomePageHeroComponent, selector: "f-home-page-hero" }, { kind: "component", type: FHomePageMembershipsComponent, selector: "f-home-page-memberships" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./foblex-m-render-cookie-popup.component-Cx-ELX3C.mjs').then(m => m.CookiePopupComponent)]] });
3933
+ ], viewQueries: [{ propertyName: "_backgroundContainer", first: true, predicate: ["backgroundContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "_heroImageContainer", first: true, predicate: ["heroImageContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<ng-container #backgroundContainer></ng-container>\n<header f-home-page-header></header>\n\n<div class=\"body\">\n <div class=\"hero-row\">\n <f-home-page-hero></f-home-page-hero>\n <ng-container #heroImageContainer></ng-container>\n </div>\n <f-home-page-features></f-home-page-features>\n <f-home-page-memberships></f-home-page-memberships>\n</div>\n\n<div class=\"flex-space\"></div>\n<footer f-home-page-footer></footer>\n\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;flex-direction:column;position:relative;width:100%;height:100%;min-height:100%;overflow:hidden;overflow-y:auto}.body{position:relative;z-index:3;pointer-events:none}@media(min-width:960px){.body{margin-top:50px}}@media(min-width:1376px){.body{margin-top:100px}}.hero-row{display:flex;flex-direction:column-reverse;justify-content:space-between;align-items:center;margin:0 auto}@media(min-width:960px){.hero-row{flex-direction:row;margin-left:64px;margin-right:64px}}@media(min-width:1376px){.hero-row{flex-direction:row;margin-left:calc(50% - 624px);margin-right:calc(50% - 624px)}}\n"], dependencies: [{ kind: "component", type: FHomePageFooterComponent, selector: "footer[f-home-page-footer]" }, { kind: "component", type: FHomePageHeaderComponent, selector: "header[f-home-page-header]" }, { kind: "component", type: FHomePageFeaturesComponent, selector: "f-home-page-features" }, { kind: "component", type: FHomePageHeroComponent, selector: "f-home-page-hero" }, { kind: "component", type: FHomePageMembershipsComponent, selector: "f-home-page-memberships" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [import('./foblex-m-render-cookie-popup-DzpgC1SS.mjs').then(m => m.CookiePopup)]] });
3379
3934
  }
3380
- i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.8", ngImport: i0, type: HomeRootComponent, resolveDeferredDeps: () => [import('./foblex-m-render-cookie-popup.component-Cx-ELX3C.mjs').then(m => m.CookiePopupComponent)], resolveMetadata: CookiePopupComponent => ({ decorators: [{
3935
+ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.1.4", ngImport: i0, type: HomeRootComponent, resolveDeferredDeps: () => [import('./foblex-m-render-cookie-popup-DzpgC1SS.mjs').then(m => m.CookiePopup)], resolveMetadata: CookiePopup => ({ decorators: [{
3381
3936
  type: Component,
3382
3937
  args: [{ selector: 'home-root', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3383
3938
  HomeStore,
@@ -3387,8 +3942,8 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.8", ng
3387
3942
  FHomePageFeaturesComponent,
3388
3943
  FHomePageHeroComponent,
3389
3944
  FHomePageMembershipsComponent,
3390
- CookiePopupComponent,
3391
- ], template: "<ng-container #backgroundContainer></ng-container>\n<header f-home-page-header></header>\n\n<div class=\"body\">\n <div class=\"hero-row\">\n <f-home-page-hero></f-home-page-hero>\n <ng-container #heroImageContainer></ng-container>\n </div>\n <f-home-page-features></f-home-page-features>\n <f-home-page-memberships></f-home-page-memberships>\n</div>\n\n<div class=\"flex-space\"></div>\n<footer f-home-page-footer></footer>\n\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;flex-direction:column;position:relative;width:100%;height:100%;min-height:100%;overflow:hidden;overflow-y:auto}.body{position:relative;z-index:3;pointer-events:none}@media (min-width: 960px){.body{margin-top:50px}}@media (min-width: 1376px){.body{margin-top:100px}}.hero-row{display:flex;flex-direction:column-reverse;justify-content:space-between;align-items:center;margin:0 auto}@media (min-width: 960px){.hero-row{flex-direction:row;margin-left:64px;margin-right:64px}}@media (min-width: 1376px){.hero-row{flex-direction:row;margin-left:calc(50% - 624px);margin-right:calc(50% - 624px)}}\n"] }]
3945
+ CookiePopup,
3946
+ ], template: "<ng-container #backgroundContainer></ng-container>\n<header f-home-page-header></header>\n\n<div class=\"body\">\n <div class=\"hero-row\">\n <f-home-page-hero></f-home-page-hero>\n <ng-container #heroImageContainer></ng-container>\n </div>\n <f-home-page-features></f-home-page-features>\n <f-home-page-memberships></f-home-page-memberships>\n</div>\n\n<div class=\"flex-space\"></div>\n<footer f-home-page-footer></footer>\n\n@defer (when isBrowser) {\n <cookie-popup/>\n}\n", styles: [":host{display:flex;flex-direction:column;position:relative;width:100%;height:100%;min-height:100%;overflow:hidden;overflow-y:auto}.body{position:relative;z-index:3;pointer-events:none}@media(min-width:960px){.body{margin-top:50px}}@media(min-width:1376px){.body{margin-top:100px}}.hero-row{display:flex;flex-direction:column-reverse;justify-content:space-between;align-items:center;margin:0 auto}@media(min-width:960px){.hero-row{flex-direction:row;margin-left:64px;margin-right:64px}}@media(min-width:1376px){.hero-row{flex-direction:row;margin-left:calc(50% - 624px);margin-right:calc(50% - 624px)}}\n"] }]
3392
3947
  }], ctorParameters: null, propDecorators: { _backgroundContainer: [{
3393
3948
  type: ViewChild,
3394
3949
  args: ['backgroundContainer', { read: ViewContainerRef }]
@@ -3429,5 +3984,5 @@ var index = /*#__PURE__*/Object.freeze({
3429
3984
  * Generated bundle index. Do not edit.
3430
3985
  */
3431
3986
 
3432
- export { AVAILABLE_LANGUAGES, ActivateTocByHash, ActivateTocByHashRequest, CalculateAbsoluteTopToContainer, CalculateAbsoluteTopToContainerRequest, CalculateHashFromScrollPosition, CalculateTableOfContent, CalculateTableOfContentRequest, CodeGroup, CodeView, DOCUMENTATION_CONFIGURATION, DOCUMENTATION_ROUTES, DOCUMENT_ELEMENT, DYNAMIC_COMPONENTS_MODULE_PROVIDERS, Documentation, DocumentationStore, DropdownMenu, DynamicComponentsStore, EMarkdownContainerType, EParsedContainerType, EXTERNAL_COMPONENT_PROVIDER, ExternalComponent, FCheckboxComponent, FHomePageButtonsRowComponent, FHomePageFeaturesComponent, FHomePageFooterComponent, FHomePageHeaderComponent, FHomePageHeroComponent, FHomePageMembershipsComponent, FMetaService, FNavigationItemComponent, FRadioButtonComponent, FSearchButtonComponent, F_PREVIEW_NAVIGATION_PROVIDER, FooterNavigationButton, GTAG_CONFIG, GTagService, GetPreviousNextPageNavigationHandler, GetPreviousNextPageNavigationRequest, GetPreviousNextPageNavigationResponse, HEADER_CONFIGURATION_PROVIDER, HOME_PAGE_CONFIGURATION, HOME_ROUTES, HamburgerButton, HandleNavigationLinksHandler, HandleNavigationLinksRequest, HeaderComponent, HeaderMenuBase, Highlight, HighlightService, HomeRootComponent, HomeStore, IS_BROWSER_PLATFORM, InlineMenu, LOCAL_STORAGE, LOCATION, MEDIA_LINKS_PROVIDER, MExecution, MarkCodeFocusedBlocksPostProcessor, MarkdownFooter, MarkdownRenderer, MarkdownRouter, MarkdownService, MediaLinks, Mediatr, NavigationGroupComponent, NavigationPanelComponent, ParseAlerts, ParseAngularExampleWithCodeLinks, ParseGroupedCodeItems, ParsePreviewGroup, ParseShowcase, ParseSingleCodeItem, PopoverService, PreviewActionBar, PreviewCard, PreviewCardBase, PreviewGroupService, RenderDynamicComponent, RenderDynamicComponentRequest, RenderExternalComponent, RenderExternalComponentRequest, RenderInternalComponents, RenderInternalComponentsRequest, SCROLLABLE_CONTAINER, SHOWCASE_DATA, ScrollToElementInContainer, ScrollToElementInContainerRequest, ScrollableContainer, Showcase, ShowcaseItem, TABLE_OF_CONTENT_MODULE_PROVIDERS, TOGGLE_NAVIGATION_COMPONENT, TableOfContent, TableOfContentData, TableOfContentItemsComponent, ThemeButtonComponent, ThemeService, UNIVERSAL_THEME, WINDOW, calculateMarkdownUrl, coerceComponentHeight$1 as coerceComponentHeight, copyToClipboard, defineLazyComponent, defineNavigationGroup, encodeDataAttr, extractComponent, getContent, isClosingToken, isOpeningToken, parseComponentTag, parseFileLinkLine, parseSingleBracketText, provide404Markdown, provideBackground, provideComponents, provideDirectory, provideDocumentation, provideFooterNavigation, provideGTag, provideHeader, provideHeaderMediaLinks, provideHeaderNavigation, provideHeaderSearch, provideHero, provideHomeButtons, provideHomeFeatures, provideHomeFooter, provideHomePage, provideImage, provideLanguage, provideLogo, provideMeta, provideNavigation, provideShowcase, provideTableOfContent, provideTheme, provideTitle };
3987
+ export { AVAILABLE_LANGUAGES, ActivateTocByHash, ActivateTocByHashRequest, CalculateAbsoluteTopToContainer, CalculateAbsoluteTopToContainerRequest, CalculateHashFromScrollPosition, CalculateTableOfContent, CalculateTableOfContentRequest, CodeGroup, CodeView, DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS, DOCUMENTATION_CONFIGURATION, DOCUMENTATION_ROUTES, DOCUMENT_ELEMENT, DYNAMIC_COMPONENTS_MODULE_PROVIDERS, Documentation, DocumentationStore, DropdownMenu, DynamicComponentsStore, EMarkdownContainerType, EParsedContainerType, EXTERNAL_COMPONENT_PROVIDER, ExternalComponent, FBrandLinkComponent, FCheckboxComponent, FHomePageButtonsRowComponent, FHomePageFeaturesComponent, FHomePageFooterComponent, FHomePageHeaderComponent, FHomePageHeroComponent, FHomePageMembershipsComponent, FMetaService, FNavigationItemComponent, FRadioButtonComponent, FSearchButtonComponent, F_PREVIEW_NAVIGATION_PROVIDER, FooterNavigationButton, GTAG_CONFIG, GTagService, GetPreviousNextPageNavigationHandler, GetPreviousNextPageNavigationRequest, GetPreviousNextPageNavigationResponse, HEADER_CONFIGURATION_PROVIDER, HOME_PAGE_CONFIGURATION, HOME_ROUTES, HamburgerButton, HandleNavigationLinksHandler, HandleNavigationLinksRequest, HeaderComponent, HeaderMenuBase, Highlight, HighlightService, HomeRootComponent, HomeStore, IS_BROWSER_PLATFORM, InlineMenu, LOCAL_STORAGE, LOCATION, MEDIA_LINKS_PROVIDER, MExecution, MarkCodeFocusedBlocksPostProcessor, MarkdownFooter, MarkdownRenderer, MarkdownRouter, MarkdownService, MediaLinks, Mediatr, NavigationGroupComponent, NavigationPanelComponent, ParseAlerts, ParseAngularExampleWithCodeLinks, ParseGroupedCodeItems, ParsePreviewGroup, ParseShowcase, ParseSingleCodeItem, PopoverService, PreviewActionBar, PreviewCard, PreviewCardBase, PreviewGroupService, RenderDynamicComponent, RenderDynamicComponentRequest, RenderExternalComponent, RenderExternalComponentRequest, RenderInternalComponents, RenderInternalComponentsRequest, SCROLLABLE_CONTAINER, SHOWCASE_DATA, ScrollToElementInContainer, ScrollToElementInContainerRequest, ScrollableContainer, Showcase, ShowcaseItem, TABLE_OF_CONTENT_MODULE_PROVIDERS, TOGGLE_NAVIGATION_COMPONENT, TableOfContent, TableOfContentData, TableOfContentItemsComponent, ThemeButtonComponent, ThemeService, UNIVERSAL_THEME, WINDOW, calculateMarkdownUrl, coerceComponentHeight$1 as coerceComponentHeight, copyToClipboard, defineLazyComponent, defineNavigationGroup, encodeDataAttr, extractComponent, getContent, getLanguageLoader, isClosingToken, isOpeningToken, parseComponentTag, parseFileLinkLine, parseIframeUrl, parseSingleBracketText, provide404Markdown, provideBackground, provideComponents, provideDirectory, provideDocumentation, provideFooterNavigation, provideGTag, provideHeader, provideHeaderMediaLinks, provideHeaderNavigation, provideHeaderSearch, provideHero, provideHomeButtons, provideHomeFeatures, provideHomeFooter, provideHomePage, provideImage, provideLanguage, provideLogo, provideMeta, provideNavigation, provideShowcase, provideTableOfContent, provideTheme, provideTitle, resolveHighlightLanguage };
3433
3988
  //# sourceMappingURL=foblex-m-render.mjs.map