@foblex/m-render 2.9.5 → 3.0.1

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);
300
+ }
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);
406
313
  }
407
- _getMetaTag(tag) {
408
- return this._document.querySelector(`meta[property="${tag.property}"]`) || null;
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;
566
- }
567
- if (!data.url) {
568
- data.url = this._buildAbsoluteUrl(currentUrl);
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;
569
467
  }
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`;
1913
+ }
1914
+ if (/^-?\d+(\.\d+)?(px|%|vh|vw|vmin|vmax|rem|em|ch|ex|cm|mm|in|pt|pc)$/i.test(normalizedValue)) {
1915
+ return normalizedValue;
1553
1916
  }
1554
- value = Number(value);
1555
- if (value) {
1556
- return value + 'px';
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,93 @@ 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
+ iframeResourceUrl = computed(() => {
2108
+ const url = this.iframeUrl();
2109
+ if (!url) {
2110
+ return undefined;
2111
+ }
2112
+ return this._sanitizer.bypassSecurityTrustResourceUrl(url);
2113
+ }, ...(ngDevMode ? [{ debugName: "iframeResourceUrl" }] : []));
2114
+ hasContent = computed(() => !!this.data().selector || !!this.data().iframeUrl, ...(ngDevMode ? [{ debugName: "hasContent" }] : []));
2115
+ canToggleFullscreen = computed(() => {
2116
+ return this._isBrowser
2117
+ && this.hasContent()
2118
+ && typeof this._hostElement.nativeElement.requestFullscreen === 'function'
2119
+ && typeof this._document.exitFullscreen === 'function';
2120
+ }, ...(ngDevMode ? [{ debugName: "canToggleFullscreen" }] : []));
2121
+ fullscreenLabel = computed(() => this.isFullscreen() ? 'Exit full screen' : 'Full screen', ...(ngDevMode ? [{ debugName: "fullscreenLabel" }] : []));
2122
+ isFullscreen = signal(false, ...(ngDevMode ? [{ debugName: "isFullscreen" }] : []));
2123
+ _document = inject(DOCUMENT);
2124
+ _hostElement = inject(ElementRef);
2125
+ _isBrowser = inject(IS_BROWSER_PLATFORM);
1722
2126
  _mediatr = inject(Mediatr);
1723
2127
  _viewContainerRef = viewChild.required('container', { read: ViewContainerRef });
2128
+ _sanitizer = inject(DomSanitizer);
1724
2129
  ngOnInit() {
1725
- this._mediatr.execute(new RenderExternalComponentRequest(this.data().value, this._viewContainerRef()));
2130
+ const selector = this.data().selector;
2131
+ if (selector) {
2132
+ this._mediatr.execute(new RenderExternalComponentRequest(selector, this._viewContainerRef()));
2133
+ return;
2134
+ }
2135
+ if (!this.data().iframeUrl) {
2136
+ console.error('Unsupported example source. Provide either component tag or [url].');
2137
+ }
1726
2138
  }
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 });
2139
+ async toggleFullscreen() {
2140
+ if (!this.canToggleFullscreen())
2141
+ return;
2142
+ try {
2143
+ if (this._isCurrentElementInFullscreen()) {
2144
+ await this._document.exitFullscreen?.();
2145
+ }
2146
+ else {
2147
+ await this._hostElement.nativeElement.requestFullscreen?.();
2148
+ }
2149
+ }
2150
+ catch (error) {
2151
+ console.error('Unable to toggle full-screen mode for example preview:', error);
2152
+ }
2153
+ }
2154
+ onFullscreenChange() {
2155
+ this.isFullscreen.set(this._isCurrentElementInFullscreen());
2156
+ }
2157
+ _isCurrentElementInFullscreen() {
2158
+ return this._document.fullscreenElement === this._hostElement.nativeElement;
2159
+ }
2160
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ExternalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2161
+ 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 (iframeResourceUrl()) {\n <iframe class=\"f-example-iframe\"\n [src]=\"iframeResourceUrl()\"\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
2162
  }
1730
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExternalComponent, decorators: [{
2163
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ExternalComponent, decorators: [{
1731
2164
  type: Component,
1732
2165
  args: [{ selector: 'external-component', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1733
2166
  class: 'f-example-view',
1734
2167
  '[style.height]': 'data().height',
1735
- }, template: "<ng-container #container />\n\n" }]
1736
- }] });
2168
+ '[class.f-example-view-fullscreen]': 'isFullscreen()',
2169
+ }, 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 (iframeResourceUrl()) {\n <iframe class=\"f-example-iframe\"\n [src]=\"iframeResourceUrl()\"\n loading=\"lazy\"\n referrerpolicy=\"no-referrer\"\n allow=\"fullscreen\"\n allowfullscreen></iframe>\n}\n\n<ng-container #container />\n" }]
2170
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], _viewContainerRef: [{ type: i0.ViewChild, args: ['container', { ...{ read: ViewContainerRef }, isSignal: true }] }], onFullscreenChange: [{
2171
+ type: HostListener,
2172
+ args: ['document:fullscreenchange']
2173
+ }] } });
1737
2174
 
1738
2175
  class Highlight {
1739
2176
  _highlightService = inject(HighlightService);
@@ -1747,10 +2184,10 @@ class Highlight {
1747
2184
  .pipe(take(1), takeUntilDestroyed(this._destroyRef)).subscribe();
1748
2185
  });
1749
2186
  }
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 });
2187
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Highlight, deps: [], target: i0.ɵɵFactoryTarget.Component });
2188
+ 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
2189
  }
1753
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Highlight, decorators: [{
2190
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Highlight, decorators: [{
1754
2191
  type: Component,
1755
2192
  args: [{
1756
2193
  selector: 'highlight',
@@ -1758,7 +2195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
1758
2195
  standalone: true,
1759
2196
  changeDetection: ChangeDetectionStrategy.OnPush,
1760
2197
  }]
1761
- }] });
2198
+ }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], language: [{ type: i0.Input, args: [{ isSignal: true, alias: "language", required: true }] }] } });
1762
2199
 
1763
2200
  class CodeView {
1764
2201
  _httpClient = inject(HttpClient);
@@ -1803,10 +2240,10 @@ class CodeView {
1803
2240
  _copyContentToClipboard(content) {
1804
2241
  copyToClipboard(content).pipe(take(1), takeUntilDestroyed(this._destroyRef)).subscribe(() => this._popoverService.show('Copied!'));
1805
2242
  }
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 });
2243
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeView, deps: [], target: i0.ɵɵFactoryTarget.Component });
2244
+ 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
2245
  }
1809
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CodeView, decorators: [{
2246
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeView, decorators: [{
1810
2247
  type: Component,
1811
2248
  args: [{ selector: 'code-view', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1812
2249
  class: 'f-code-view',
@@ -1814,19 +2251,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
1814
2251
  }, imports: [
1815
2252
  Highlight,
1816
2253
  ], 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
- }] });
2254
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
1818
2255
  function coerceComponentHeight(value) {
1819
- if (value === undefined) {
2256
+ if (value === undefined || value === null) {
2257
+ return undefined;
2258
+ }
2259
+ if (typeof value === 'number') {
2260
+ return Number.isFinite(value) && value > 0 ? `${value}px` : undefined;
2261
+ }
2262
+ const normalizedValue = value.trim();
2263
+ if (!normalizedValue)
1820
2264
  return undefined;
2265
+ if (normalizedValue === 'auto')
2266
+ return 'auto';
2267
+ const numericValue = Number(normalizedValue);
2268
+ if (Number.isFinite(numericValue) && numericValue > 0) {
2269
+ return `${numericValue}px`;
2270
+ }
2271
+ if (/^-?\d+(\.\d+)?(px|%|vh|vw|vmin|vmax|rem|em|ch|ex|cm|mm|in|pt|pc)$/i.test(normalizedValue)) {
2272
+ return normalizedValue;
1821
2273
  }
1822
- value = Number(value);
1823
- if (value) {
1824
- return value + 'px';
2274
+ if (/^calc\(.+\)$/i.test(normalizedValue)) {
2275
+ return normalizedValue;
1825
2276
  }
1826
2277
  return undefined;
1827
2278
  }
1828
2279
  function parseLanguageFromFileExtension(url) {
1829
- const match = url.match(/\.([0-9a-z]+)(?:[\?#]|$)/i);
2280
+ const match = url.match(/\.([0-9a-z]+)(?:[?#]|$)/i);
1830
2281
  if (match) {
1831
2282
  let extension = match[1];
1832
2283
  if (extension === 'css') {
@@ -1855,13 +2306,10 @@ function parseSyntaxLanguage(language) {
1855
2306
  default:
1856
2307
  result = extractLanguage(language);
1857
2308
  }
1858
- if (!AVAILABLE_LANGUAGES.includes(result)) {
1859
- result = 'text';
1860
- }
1861
- return result;
2309
+ return resolveHighlightLanguage(result);
1862
2310
  }
1863
2311
  function extractLanguage(language) {
1864
- const match = language.match(/^([^\s\[]+)/);
2312
+ const match = language.match(/^([^\s[]+)/);
1865
2313
  return match ? match[1].toLowerCase() : language;
1866
2314
  }
1867
2315
 
@@ -1872,15 +2320,16 @@ class MarkCodeFocusedBlocksPostProcessor {
1872
2320
  }
1873
2321
  handle(element) {
1874
2322
  const html = element.innerHTML;
1875
- if (!FOCUS_REGEX.test(html)) {
2323
+ if (!FOCUS_TEST_REGEX.test(html)) {
1876
2324
  return of(element);
1877
2325
  }
1878
- element.innerHTML = html.replace(FOCUS_REGEX, (_match, content) => {
2326
+ element.innerHTML = html.replace(FOCUS_REPLACE_REGEX, (_match, content) => {
1879
2327
  return `<focus class="focused"><div class="inline-focus">${content}</div></focus>`;
1880
2328
  });
1881
2329
  const focused = element.querySelector('.focused');
1882
- if (focused) {
1883
- this._applyOpacity(element.parentElement);
2330
+ const hostElement = element.parentElement;
2331
+ if (focused && hostElement) {
2332
+ this._applyOpacity(hostElement);
1884
2333
  }
1885
2334
  return of(element);
1886
2335
  }
@@ -1906,10 +2355,13 @@ class MarkCodeFocusedBlocksPostProcessor {
1906
2355
  return isRgb ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${opacity * alpha})`;
1907
2356
  }
1908
2357
  _getRgbValues(color) {
1909
- return color.match(/\d+/g);
2358
+ const matches = color.match(/-?\d*\.?\d+/g) || [];
2359
+ const [r = '0', g = '0', b = '0', a = '1'] = matches;
2360
+ return [r, g, b, a];
1910
2361
  }
1911
2362
  }
1912
- const FOCUS_REGEX = /ƒƒƒ([\s\S]*?)¢¢¢/g;
2363
+ const FOCUS_TEST_REGEX = /ƒƒƒ([\s\S]*?)¢¢¢/;
2364
+ const FOCUS_REPLACE_REGEX = /ƒƒƒ([\s\S]*?)¢¢¢/g;
1913
2365
 
1914
2366
  const UNIVERSAL_THEME = {
1915
2367
  name: 'universal',
@@ -2192,6 +2644,32 @@ const UNIVERSAL_THEME = {
2192
2644
  ],
2193
2645
  };
2194
2646
 
2647
+ const LANGUAGE_ALIASES = {
2648
+ js: 'javascript',
2649
+ javascript: 'javascript',
2650
+ ts: 'typescript',
2651
+ typescript: 'typescript',
2652
+ md: 'markdown',
2653
+ sh: 'shell',
2654
+ zsh: 'shell',
2655
+ shell: 'shell',
2656
+ shellscript: 'shell',
2657
+ txt: 'text',
2658
+ plain: 'text',
2659
+ plaintext: 'text',
2660
+ };
2661
+ const LANGUAGE_LOADERS = new Map([
2662
+ ['javascript', () => import('@shikijs/langs/javascript')],
2663
+ ['typescript', () => import('@shikijs/langs/typescript')],
2664
+ ['angular-html', () => import('@shikijs/langs/angular-html')],
2665
+ ['angular-ts', () => import('@shikijs/langs/angular-ts')],
2666
+ ['shell', () => import('@shikijs/langs/shell')],
2667
+ ['html', () => import('@shikijs/langs/html')],
2668
+ ['bash', () => import('@shikijs/langs/bash')],
2669
+ ['css', () => import('@shikijs/langs/css')],
2670
+ ['scss', () => import('@shikijs/langs/scss')],
2671
+ ['markdown', () => import('@shikijs/langs/markdown')],
2672
+ ]);
2195
2673
  const AVAILABLE_LANGUAGES = [
2196
2674
  'javascript',
2197
2675
  'typescript',
@@ -2205,6 +2683,32 @@ const AVAILABLE_LANGUAGES = [
2205
2683
  'markdown',
2206
2684
  'text',
2207
2685
  ];
2686
+ function resolveHighlightLanguage(lang) {
2687
+ const normalized = (lang || '').trim().toLowerCase();
2688
+ if (!normalized) {
2689
+ return 'text';
2690
+ }
2691
+ const alias = LANGUAGE_ALIASES[normalized];
2692
+ if (alias) {
2693
+ return alias;
2694
+ }
2695
+ if (isAvailableLanguage(normalized)) {
2696
+ return normalized;
2697
+ }
2698
+ return 'text';
2699
+ }
2700
+ function getLanguageLoader(lang) {
2701
+ if (isPlainTextLanguage(lang)) {
2702
+ return null;
2703
+ }
2704
+ return LANGUAGE_LOADERS.get(lang) || null;
2705
+ }
2706
+ function isAvailableLanguage(lang) {
2707
+ return AVAILABLE_LANGUAGES.includes(lang);
2708
+ }
2709
+ function isPlainTextLanguage(lang) {
2710
+ return lang === 'text' || lang === 'txt' || lang === 'plain' || lang === 'plaintext';
2711
+ }
2208
2712
 
2209
2713
  class HighlightService {
2210
2714
  /**
@@ -2212,14 +2716,16 @@ class HighlightService {
2212
2716
  * It supports syntax highlighting and post-processing for focused blocks.
2213
2717
  */
2214
2718
  _isBrowser = inject(IS_BROWSER_PLATFORM);
2215
- _window = inject(WINDOW);
2216
- _highlighter$ = defer(() => from(createHighlighter({ themes: [UNIVERSAL_THEME], langs: AVAILABLE_LANGUAGES }))).pipe(shareReplay(1));
2719
+ _window = inject(WINDOW, { optional: true });
2720
+ _languageLoadingTasks = new Map();
2721
+ _highlighter$ = defer(() => from(this._createHighlighter())).pipe(shareReplay(1));
2217
2722
  highlight(element, lang, content) {
2218
2723
  if (!this._isBrowser) {
2219
2724
  console.warn('[HighlightService] Skipping highlight on server.');
2220
2725
  return of(element);
2221
2726
  }
2222
- return this._highlightCodeBlock(element, lang, content).pipe(switchMap((x) => this._postProcess(x)), catchError((err) => {
2727
+ const resolvedLanguage = resolveHighlightLanguage(lang);
2728
+ return this._ensureLanguageLoaded(resolvedLanguage).pipe(switchMap(() => this._highlightCodeBlock(element, resolvedLanguage, content)), switchMap((x) => this._postProcess(x)), catchError((err) => {
2223
2729
  console.error('[HighlightService] Failed to highlight:', err);
2224
2730
  return of(element);
2225
2731
  }));
@@ -2231,22 +2737,67 @@ class HighlightService {
2231
2737
  return new Observable((observer) => {
2232
2738
  const processedContent = this._preprocessFocus(content);
2233
2739
  element.innerHTML = highlighter.codeToHtml(processedContent, { lang, theme: 'universal', defaultColor: false });
2234
- requestAnimationFrame(() => {
2740
+ this._scheduleRender(() => {
2235
2741
  observer.next(element);
2236
2742
  observer.complete();
2237
2743
  });
2238
2744
  });
2239
2745
  }
2240
2746
  _preprocessFocus(code) {
2241
- return code.replace(/\|\:\|([\s\S]*?)\|\:\|/g, (_, p1) => `ƒƒƒ${p1}¢¢¢`);
2747
+ return code.replace(/\|:\|([\s\S]*?)\|:\|/g, (_, p1) => `ƒƒƒ${p1}¢¢¢`);
2748
+ }
2749
+ _createHighlighter() {
2750
+ return createHighlighterCore({
2751
+ engine: createOnigurumaEngine(() => import('shiki/wasm').then((x) => x.default)),
2752
+ themes: [UNIVERSAL_THEME],
2753
+ langs: [],
2754
+ });
2755
+ }
2756
+ _ensureLanguageLoaded(lang) {
2757
+ if (isSpecialLang(lang)) {
2758
+ return of(void 0);
2759
+ }
2760
+ return this._highlighter$.pipe(switchMap((highlighter) => {
2761
+ if (highlighter.getLoadedLanguages().includes(lang)) {
2762
+ return of(void 0);
2763
+ }
2764
+ const cachedTask = this._languageLoadingTasks.get(lang);
2765
+ if (cachedTask) {
2766
+ return cachedTask;
2767
+ }
2768
+ const loader = getLanguageLoader(lang);
2769
+ if (!loader) {
2770
+ return of(void 0);
2771
+ }
2772
+ const loadingTask = from(highlighter.loadLanguage(loader)).pipe(map(() => void 0), catchError((error) => {
2773
+ console.error(`[HighlightService] Failed to load language "${lang}"`, error);
2774
+ return of(void 0);
2775
+ }), finalize(() => {
2776
+ this._languageLoadingTasks.delete(lang);
2777
+ }), shareReplay(1));
2778
+ this._languageLoadingTasks.set(lang, loadingTask);
2779
+ return loadingTask;
2780
+ }));
2781
+ }
2782
+ _scheduleRender(callback) {
2783
+ const raf = this._window?.requestAnimationFrame?.bind(this._window);
2784
+ if (raf) {
2785
+ raf(callback);
2786
+ return;
2787
+ }
2788
+ queueMicrotask(callback);
2242
2789
  }
2243
2790
  _postProcess(element) {
2244
- return of(element).pipe(switchMap((x) => new MarkCodeFocusedBlocksPostProcessor(this._window).handle(x)));
2791
+ const windowRef = this._window;
2792
+ if (!windowRef) {
2793
+ return of(element);
2794
+ }
2795
+ return of(element).pipe(switchMap((x) => new MarkCodeFocusedBlocksPostProcessor(windowRef).handle(x)));
2245
2796
  }
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' });
2797
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HighlightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2798
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HighlightService, providedIn: 'root' });
2248
2799
  }
2249
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HighlightService, decorators: [{
2800
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HighlightService, decorators: [{
2250
2801
  type: Injectable,
2251
2802
  args: [{
2252
2803
  providedIn: 'root',
@@ -2260,10 +2811,10 @@ class CodeGroup {
2260
2811
  tabClick(index) {
2261
2812
  this.index.set(index);
2262
2813
  }
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 });
2814
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
2815
+ 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
2816
  }
2266
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CodeGroup, decorators: [{
2817
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CodeGroup, decorators: [{
2267
2818
  type: Component,
2268
2819
  args: [{ selector: 'code-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
2269
2820
  class: 'f-code-group',
@@ -2345,10 +2896,10 @@ class PreviewGroupService {
2345
2896
  x.hostElement.style.display = 'block';
2346
2897
  });
2347
2898
  }
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 });
2899
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewGroupService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2900
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewGroupService });
2350
2901
  }
2351
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewGroupService, decorators: [{
2902
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewGroupService, decorators: [{
2352
2903
  type: Injectable
2353
2904
  }] });
2354
2905
 
@@ -2411,15 +2962,15 @@ class PreviewCard extends PreviewCardBase {
2411
2962
  ngOnDestroy() {
2412
2963
  this._fPreviewGroupService.remove(this);
2413
2964
  }
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 });
2965
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewCard, deps: null, target: i0.ɵɵFactoryTarget.Component });
2966
+ 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
2967
  }
2417
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewCard, decorators: [{
2968
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewCard, decorators: [{
2418
2969
  type: Component,
2419
2970
  args: [{ selector: 'a[preview-card]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
2420
2971
  '[attr.href]': 'url',
2421
2972
  '[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"] }]
2973
+ }, 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
2974
  }] });
2424
2975
 
2425
2976
  var previewCard = /*#__PURE__*/Object.freeze({
@@ -2462,10 +3013,10 @@ class PreviewActionBar {
2462
3013
  this.isSortByDateChecked.set(event);
2463
3014
  this._fPreviewGroupService.sortByDate(event);
2464
3015
  }
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 });
3016
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewActionBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
3017
+ 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
3018
  }
2468
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: PreviewActionBar, decorators: [{
3019
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: PreviewActionBar, decorators: [{
2469
3020
  type: Component,
2470
3021
  args: [{ selector: 'div[preview-action-bar]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2471
3022
  FCheckboxComponent,
@@ -2488,13 +3039,13 @@ class ShowcaseItem {
2488
3039
  const model = this.model();
2489
3040
  return theme === 'dark' ? (model.imageUrlDark || model.imageUrl) : model.imageUrl;
2490
3041
  }, ...(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 });
3042
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ShowcaseItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
3043
+ 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
3044
  }
2494
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ShowcaseItem, decorators: [{
3045
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ShowcaseItem, decorators: [{
2495
3046
  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
- }] });
3047
+ 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"] }]
3048
+ }], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: true }] }] } });
2498
3049
 
2499
3050
  const SHOWCASE_DATA = new InjectionToken('SHOWCASE_DATA');
2500
3051
 
@@ -2515,10 +3066,10 @@ class Showcase {
2515
3066
  tagClick(tag) {
2516
3067
  this.activeTag.update((x) => x === tag ? null : tag);
2517
3068
  }
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 });
3069
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Showcase, deps: [], target: i0.ɵɵFactoryTarget.Component });
3070
+ 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
3071
  }
2521
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: Showcase, decorators: [{
3072
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Showcase, decorators: [{
2522
3073
  type: Component,
2523
3074
  args: [{ selector: 'showcase', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2524
3075
  ShowcaseItem,
@@ -2563,13 +3114,13 @@ let ActivateTocByHash = class ActivateTocByHash {
2563
3114
  })),
2564
3115
  }));
2565
3116
  }
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 });
3117
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ActivateTocByHash, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3118
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ActivateTocByHash });
2568
3119
  };
2569
3120
  ActivateTocByHash = __decorate([
2570
3121
  MExecution(ActivateTocByHashRequest)
2571
3122
  ], ActivateTocByHash);
2572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ActivateTocByHash, decorators: [{
3123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ActivateTocByHash, decorators: [{
2573
3124
  type: Injectable
2574
3125
  }] });
2575
3126
 
@@ -2611,13 +3162,13 @@ let CalculateAbsoluteTopToContainer = class CalculateAbsoluteTopToContainer {
2611
3162
  }
2612
3163
  return result;
2613
3164
  }
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 });
3165
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateAbsoluteTopToContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3166
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateAbsoluteTopToContainer });
2616
3167
  };
2617
3168
  CalculateAbsoluteTopToContainer = __decorate([
2618
3169
  MExecution(CalculateAbsoluteTopToContainerRequest)
2619
3170
  ], CalculateAbsoluteTopToContainer);
2620
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateAbsoluteTopToContainer, decorators: [{
3171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateAbsoluteTopToContainer, decorators: [{
2621
3172
  type: Injectable
2622
3173
  }] });
2623
3174
 
@@ -2672,10 +3223,10 @@ class CalculateHashFromScrollPosition {
2672
3223
  }
2673
3224
  return result;
2674
3225
  }
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 });
3226
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateHashFromScrollPosition, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3227
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateHashFromScrollPosition });
2677
3228
  }
2678
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateHashFromScrollPosition, decorators: [{
3229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateHashFromScrollPosition, decorators: [{
2679
3230
  type: Injectable
2680
3231
  }] });
2681
3232
 
@@ -2731,13 +3282,13 @@ let CalculateTableOfContent = class CalculateTableOfContent {
2731
3282
  }
2732
3283
  stack.push(tocItem);
2733
3284
  }
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 });
3285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateTableOfContent, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3286
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateTableOfContent });
2736
3287
  };
2737
3288
  CalculateTableOfContent = __decorate([
2738
3289
  MExecution(CalculateTableOfContentRequest)
2739
3290
  ], CalculateTableOfContent);
2740
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: CalculateTableOfContent, decorators: [{
3291
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: CalculateTableOfContent, decorators: [{
2741
3292
  type: Injectable
2742
3293
  }] });
2743
3294
 
@@ -2788,25 +3339,25 @@ let ScrollToElementInContainer = class ScrollToElementInContainer {
2788
3339
  _getContainerTop() {
2789
3340
  return this._scrollableContainer.htmlElement.getBoundingClientRect().top;
2790
3341
  }
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 });
3342
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollToElementInContainer, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3343
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollToElementInContainer });
2793
3344
  };
2794
3345
  ScrollToElementInContainer = __decorate([
2795
3346
  MExecution(ScrollToElementInContainerRequest)
2796
3347
  ], ScrollToElementInContainer);
2797
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollToElementInContainer, decorators: [{
3348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollToElementInContainer, decorators: [{
2798
3349
  type: Injectable
2799
3350
  }] });
2800
3351
 
2801
3352
  class TableOfContentItemsComponent {
2802
3353
  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 });
3354
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContentItemsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3355
+ 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
3356
  }
2806
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TableOfContentItemsComponent, decorators: [{
3357
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContentItemsComponent, decorators: [{
2807
3358
  type: Component,
2808
3359
  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
- }] });
3360
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }] } });
2810
3361
 
2811
3362
  const TABLE_OF_CONTENT_MODULE_PROVIDERS = [
2812
3363
  ActivateTocByHash,
@@ -2845,12 +3396,12 @@ class TableOfContent {
2845
3396
  this._mediatr.execute(new ActivateTocByHashRequest(hash));
2846
3397
  this._mediatr.execute(new ScrollToElementInContainerRequest(hash));
2847
3398
  }
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 });
3399
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3400
+ 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
3401
  }
2851
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: TableOfContent, decorators: [{
3402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: TableOfContent, decorators: [{
2852
3403
  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"] }]
3404
+ 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
3405
  }], propDecorators: { _click: [{
2855
3406
  type: HostListener,
2856
3407
  args: ['click', ['$event']]
@@ -2861,12 +3412,17 @@ const SCROLLABLE_CONTAINER = new InjectionToken('SCROLLABLE_CONTAINER');
2861
3412
  class ScrollableContainer {
2862
3413
  _destroyRef = inject(DestroyRef);
2863
3414
  _injector = inject(Injector);
3415
+ _markdown = inject(MarkdownService);
2864
3416
  tableOfContent = inject(DOCUMENTATION_CONFIGURATION).tableOfContent;
3417
+ canShowTableOfContent = computed(() => {
3418
+ return !!this.tableOfContent && !this._markdown.pageLayout().hideTableOfContent;
3419
+ }, ...(ngDevMode ? [{ debugName: "canShowTableOfContent" }] : []));
2865
3420
  htmlElement = inject((ElementRef)).nativeElement;
2866
3421
  ngOnInit() {
2867
3422
  fromEvent(this.htmlElement, 'scroll', { passive: true })
2868
3423
  .pipe(debounceTime(100), startWith(null), filter((event) => {
2869
- const ignoreProgrammatic = event?.target?._ignoreProgrammatic ?? false;
3424
+ const target = event?.target;
3425
+ const ignoreProgrammatic = target?._ignoreProgrammatic ?? false;
2870
3426
  this.htmlElement._ignoreProgrammatic = false;
2871
3427
  return !ignoreProgrammatic;
2872
3428
  }), takeUntilDestroyed(this._destroyRef))
@@ -2875,8 +3431,8 @@ class ScrollableContainer {
2875
3431
  _calculateHashAndActivate() {
2876
3432
  this._injector.get(CalculateHashFromScrollPosition).handle();
2877
3433
  }
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: [
3434
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollableContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3435
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: ScrollableContainer, isStandalone: true, selector: "scrollable-container", providers: [
2880
3436
  {
2881
3437
  provide: SCROLLABLE_CONTAINER,
2882
3438
  useExisting: forwardRef(() => ScrollableContainer),
@@ -2885,9 +3441,9 @@ class ScrollableContainer {
2885
3441
  ...DYNAMIC_COMPONENTS_MODULE_PROVIDERS,
2886
3442
  ...TABLE_OF_CONTENT_MODULE_PROVIDERS,
2887
3443
  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 });
3444
+ ], 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
3445
  }
2890
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ScrollableContainer, decorators: [{
3446
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: ScrollableContainer, decorators: [{
2891
3447
  type: Component,
2892
3448
  args: [{ selector: 'scrollable-container', standalone: true, providers: [
2893
3449
  {
@@ -2900,7 +3456,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
2900
3456
  MarkdownService,
2901
3457
  ], changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2902
3458
  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"] }]
3459
+ ], 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
3460
  }] });
2905
3461
 
2906
3462
  class MarkdownRenderer {
@@ -2950,15 +3506,15 @@ class MarkdownRenderer {
2950
3506
  ngOnDestroy() {
2951
3507
  this._dynamicComponents.dispose();
2952
3508
  }
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 });
3509
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRenderer, deps: [], target: i0.ɵɵFactoryTarget.Component });
3510
+ 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
3511
  }
2956
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownRenderer, decorators: [{
3512
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRenderer, decorators: [{
2957
3513
  type: Component,
2958
3514
  args: [{ selector: 'markdown-renderer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MarkdownFooter], host: {
2959
3515
  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: [{
3516
+ }, 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"] }]
3517
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], _onDocumentClick: [{
2962
3518
  type: HostListener,
2963
3519
  args: ['click', ['$event']]
2964
3520
  }] } });
@@ -2968,26 +3524,31 @@ class MarkdownRouter {
2968
3524
  _activatedRoute = inject(ActivatedRoute);
2969
3525
  _markdown = inject(MarkdownService);
2970
3526
  _dataProvider = inject(DocumentationStore);
3527
+ _metaService = inject(FMetaService, { optional: true });
2971
3528
  emptyNavigation = !this._dataProvider.getNavigation().length;
3529
+ shouldExpandContent = computed(() => {
3530
+ const layout = this._markdown.pageLayout();
3531
+ return layout.hideTableOfContent && layout.expandContentWithoutTableOfContent;
3532
+ }, ...(ngDevMode ? [{ debugName: "shouldExpandContent" }] : []));
2972
3533
  _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
3534
  html = toSignal(this._path$.pipe(switchMap(path => {
2974
3535
  const url = this._dataProvider.getMarkdownUrl(path);
2975
3536
  return this._markdown.parseUrl(url).pipe(catchError(err => {
2976
3537
  console.error('[MarkdownRouter] parse error:', err, { path, url });
2977
3538
  return of(undefined); // или return EMPTY;
2978
- }));
3539
+ }), tap(() => this._metaService?.applyMarkdownSeo(this._markdown.pageSeo())));
2979
3540
  })), { 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 });
3541
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRouter, deps: [], target: i0.ɵɵFactoryTarget.Component });
3542
+ 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
3543
  }
2983
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: MarkdownRouter, decorators: [{
3544
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: MarkdownRouter, decorators: [{
2984
3545
  type: Component,
2985
3546
  args: [{ selector: 'markdown-router', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
2986
3547
  'ngSkipHydration': '',
2987
3548
  '[class.empty-navigation]': 'emptyNavigation',
2988
3549
  }, imports: [
2989
3550
  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"] }]
3551
+ ], 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
3552
  }] });
2992
3553
 
2993
3554
  var index$2 = /*#__PURE__*/Object.freeze({
@@ -3020,8 +3581,8 @@ class Documentation {
3020
3581
  this._metaService.dispose();
3021
3582
  // Cleanup logic if needed
3022
3583
  }
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: [
3584
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: Documentation, deps: [], target: i0.ɵɵFactoryTarget.Component });
3585
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: Documentation, isStandalone: true, selector: "documentation", providers: [
3025
3586
  DocumentationStore,
3026
3587
  FMetaService,
3027
3588
  {
@@ -3052,9 +3613,9 @@ class Documentation {
3052
3613
  deps: [DocumentationStore],
3053
3614
  useFactory: (store) => store.getShowcaseItems(),
3054
3615
  },
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)]] });
3616
+ ], 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
3617
  }
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: [{
3618
+ 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
3619
  type: Component,
3059
3620
  args: [{ selector: 'documentation', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3060
3621
  DocumentationStore,
@@ -3092,8 +3653,8 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.8", ng
3092
3653
  ScrollableContainer,
3093
3654
  RouterOutlet,
3094
3655
  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"] }]
3656
+ CookiePopup,
3657
+ ], 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
3658
  }], ctorParameters: null, propDecorators: null }) });
3098
3659
 
3099
3660
  const DOCUMENTATION_ROUTES = [
@@ -3118,6 +3679,7 @@ var index$1 = /*#__PURE__*/Object.freeze({
3118
3679
  CalculateHashFromScrollPosition: CalculateHashFromScrollPosition,
3119
3680
  get CalculateTableOfContent () { return CalculateTableOfContent; },
3120
3681
  CalculateTableOfContentRequest: CalculateTableOfContentRequest,
3682
+ DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS: DEFAULT_MARKDOWN_PAGE_LAYOUT_OPTIONS,
3121
3683
  DOCUMENTATION_CONFIGURATION: DOCUMENTATION_CONFIGURATION,
3122
3684
  DOCUMENTATION_ROUTES: DOCUMENTATION_ROUTES,
3123
3685
  Documentation: Documentation,
@@ -3255,84 +3817,85 @@ class HomeStore {
3255
3817
  getImageComponent() {
3256
3818
  return this._configuration.image;
3257
3819
  }
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 });
3820
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3821
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeStore });
3260
3822
  }
3261
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: HomeStore, decorators: [{
3823
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeStore, decorators: [{
3262
3824
  type: Injectable
3263
3825
  }] });
3264
3826
 
3265
3827
  class FHomePageButtonsRowComponent {
3266
3828
  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"] }] });
3829
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageButtonsRowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3830
+ 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
3831
  }
3270
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageButtonsRowComponent, decorators: [{
3832
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageButtonsRowComponent, decorators: [{
3271
3833
  type: Component,
3272
3834
  args: [{ selector: 'f-home-page-buttons-row', standalone: true, imports: [
3273
3835
  RouterLink,
3274
3836
  ], host: {
3275
3837
  '[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"] }]
3838
+ }, 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
3839
  }] });
3278
3840
 
3279
3841
  class FHomePageFeaturesComponent {
3280
3842
  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"] });
3843
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFeaturesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3844
+ 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
3845
  }
3284
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageFeaturesComponent, decorators: [{
3846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFeaturesComponent, decorators: [{
3285
3847
  type: Component,
3286
3848
  args: [{ selector: 'f-home-page-features', standalone: true, host: {
3287
3849
  '[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"] }]
3850
+ }, 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
3851
  }] });
3290
3852
 
3291
3853
  class FHomePageFooterComponent {
3292
3854
  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"] });
3855
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3856
+ 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
3857
  }
3296
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageFooterComponent, decorators: [{
3858
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageFooterComponent, decorators: [{
3297
3859
  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"] }]
3860
+ 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
3861
  }] });
3300
3862
 
3301
3863
  class FHomePageHeaderComponent {
3302
3864
  logo = inject(HomeStore).getLogo();
3303
3865
  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]" }] });
3866
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3867
+ 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
3868
  }
3307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageHeaderComponent, decorators: [{
3869
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeaderComponent, decorators: [{
3308
3870
  type: Component,
3309
3871
  args: [{ selector: 'header[f-home-page-header]', standalone: true, imports: [
3872
+ FBrandLinkComponent,
3310
3873
  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"] }]
3874
+ ], 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
3875
  }] });
3313
3876
 
3314
3877
  class FHomePageHeroComponent {
3315
3878
  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" }] });
3879
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeroComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3880
+ 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
3881
  }
3319
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageHeroComponent, decorators: [{
3882
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageHeroComponent, decorators: [{
3320
3883
  type: Component,
3321
3884
  args: [{ selector: 'f-home-page-hero', standalone: true, imports: [
3322
3885
  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"] }]
3886
+ ], 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
3887
  }] });
3325
3888
 
3326
3889
  class FHomePageMembershipsComponent {
3327
3890
  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"] });
3891
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageMembershipsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3892
+ 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
3893
  }
3331
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: FHomePageMembershipsComponent, decorators: [{
3894
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: FHomePageMembershipsComponent, decorators: [{
3332
3895
  type: Component,
3333
3896
  args: [{ selector: 'f-home-page-memberships', standalone: true, host: {
3334
3897
  '[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"] }]
3898
+ }, 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
3899
  }] });
3337
3900
 
3338
3901
  class HomeRootComponent {
@@ -3372,12 +3935,12 @@ class HomeRootComponent {
3372
3935
  _requestComponentRedraw(componentRef) {
3373
3936
  componentRef.changeDetectorRef.markForCheck();
3374
3937
  }
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: [
3938
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.4", ngImport: i0, type: HomeRootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3939
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.4", type: HomeRootComponent, isStandalone: true, selector: "home-root", providers: [
3377
3940
  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)]] });
3941
+ ], 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
3942
  }
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: [{
3943
+ 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
3944
  type: Component,
3382
3945
  args: [{ selector: 'home-root', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
3383
3946
  HomeStore,
@@ -3387,8 +3950,8 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.8", ng
3387
3950
  FHomePageFeaturesComponent,
3388
3951
  FHomePageHeroComponent,
3389
3952
  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"] }]
3953
+ CookiePopup,
3954
+ ], 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
3955
  }], ctorParameters: null, propDecorators: { _backgroundContainer: [{
3393
3956
  type: ViewChild,
3394
3957
  args: ['backgroundContainer', { read: ViewContainerRef }]
@@ -3429,5 +3992,5 @@ var index = /*#__PURE__*/Object.freeze({
3429
3992
  * Generated bundle index. Do not edit.
3430
3993
  */
3431
3994
 
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 };
3995
+ 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
3996
  //# sourceMappingURL=foblex-m-render.mjs.map