@masmarino/gabarit 1.2.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1414 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, Injectable, InjectionToken, ViewEncapsulation, afterRenderEffect, computed, effect, inject, input, linkedSignal, output, signal, viewChild } from "@angular/core";
3
+ import { HttpClient, HttpErrorResponse } from "@angular/common/http";
4
+ import { BehaviorSubject, catchError, combineLatest, debounceTime, firstValueFrom, forkJoin, map, of, shareReplay, startWith, switchMap, tap } from "rxjs";
5
+ import { DomSanitizer } from "@angular/platform-browser";
6
+ import { ActivatedRoute, Router, RouterLink } from "@angular/router";
7
+ import { marked } from "marked";
8
+ import DOMPurify from "dompurify";
9
+ import { Alert, Autocomplete, Breadcrumb, Button, Card, CardLink, Disclosure, EmptyState, NavTab, NavTabs, PageLayout, Panel, Skeleton } from "@masmarino/gabarit";
10
+ import { takeUntilDestroyed, toSignal } from "@angular/core/rxjs-interop";
11
+ const DEFAULT_DOCS_CONFIG = Object.freeze({
12
+ root: "/docs",
13
+ callouts: {
14
+ note: "note",
15
+ warning: "warning"
16
+ }
17
+ });
18
+ const DOCS_CONFIG = new InjectionToken("DOCS_CONFIG", { factory: () => DEFAULT_DOCS_CONFIG });
19
+ const DOCS_TITLE = new InjectionToken("DOCS_TITLE");
20
+ function provideDocs(config = {}) {
21
+ return {
22
+ provide: DOCS_CONFIG,
23
+ useValue: {
24
+ ...DEFAULT_DOCS_CONFIG,
25
+ ...config
26
+ }
27
+ };
28
+ }
29
+ const DEFAULT_DOCS_LABELS = Object.freeze({
30
+ documentation: "Documentation",
31
+ showContents: "Show the contents",
32
+ hideContents: "Hide the contents",
33
+ searchLabel: "Search the documentation",
34
+ searchPlaceholder: "Search…",
35
+ searching: "Searching…",
36
+ noResults: "No page matches.",
37
+ searchFailed: "The documentation could not be loaded.",
38
+ results: (count) => count === 0 ? "No results" : count === 1 ? "1 result" : `${count} results`,
39
+ onThisPage: "On this page",
40
+ breadcrumb: "Breadcrumb",
41
+ neighbours: "Neighbouring pages",
42
+ previous: "Previous",
43
+ next: "Next",
44
+ notFoundHeading: "Page not found",
45
+ notFoundMessage: "This page does not exist in the documentation. Check the address, or start again from the beginning.",
46
+ toStart: "Go to the start of the documentation",
47
+ loadFailed: "The documentation could not be loaded.",
48
+ retry: "Retry",
49
+ loading: "Loading the page…",
50
+ codeBlock: "Code block",
51
+ table: "Table"
52
+ });
53
+ const DOCS_LABELS = new InjectionToken("DOCS_LABELS");
54
+ function provideDocsLabels(labels) {
55
+ return {
56
+ provide: DOCS_LABELS,
57
+ useValue: labels
58
+ };
59
+ }
60
+ function docsLabels() {
61
+ const provided = inject(DOCS_LABELS, { optional: true }) ?? {};
62
+ const defined = Object.fromEntries(Object.entries(provided).filter(([, value]) => value !== void 0));
63
+ return computed(() => ({
64
+ ...DEFAULT_DOCS_LABELS,
65
+ ...defined
66
+ }));
67
+ }
68
+ function docsPageCommands(root, section, page) {
69
+ return [
70
+ root,
71
+ section,
72
+ page
73
+ ];
74
+ }
75
+ function docsReadingOrder(index) {
76
+ return index.sections.flatMap((section) => section.pages.map((page) => ({
77
+ section,
78
+ page
79
+ })));
80
+ }
81
+ function firstDocsPage(root, index) {
82
+ const first = docsReadingOrder(index)[0];
83
+ return first ? docsPageCommands(root, first.section.slug, first.page.slug) : null;
84
+ }
85
+ function locateDocsPage(root, index, section, page) {
86
+ const order = docsReadingOrder(index);
87
+ const at = order.findIndex((entry) => entry.section.slug === section && entry.page.slug === page);
88
+ if (at < 0) return null;
89
+ const link = (entry) => entry ? {
90
+ sectionTitle: entry.section.title,
91
+ title: entry.page.title,
92
+ commands: docsPageCommands(root, entry.section.slug, entry.page.slug)
93
+ } : null;
94
+ return {
95
+ ...order[at],
96
+ previous: link(order[at - 1]),
97
+ next: link(order[at + 1])
98
+ };
99
+ }
100
+ const looksLikeHtml = (text) => /^\s*<!doctype html|^\s*<html[\s>]/i.test(text);
101
+ var DocsService = class DocsService {
102
+ http = inject(HttpClient);
103
+ root = inject(DOCS_CONFIG).root;
104
+ index$ = null;
105
+ pages = /* @__PURE__ */ new Map();
106
+ index() {
107
+ this.index$ ??= this.http.get(`${this.root}/index.json`).pipe(tap({ error: () => this.index$ = null }), shareReplay(1));
108
+ return this.index$;
109
+ }
110
+ page(section, page) {
111
+ const key = `${section}/${page}`;
112
+ const known = this.pages.get(key);
113
+ if (known !== void 0) return of(known);
114
+ return this.http.get(`${this.root}/${key}.md`, { responseType: "text" }).pipe(map((text) => {
115
+ if (looksLikeHtml(text)) throw new HttpErrorResponse({
116
+ status: 404,
117
+ statusText: "Not Found",
118
+ url: `${this.root}/${key}.md`
119
+ });
120
+ return text;
121
+ }), tap((text) => this.pages.set(key, text)));
122
+ }
123
+ static ɵfac = i0.ɵɵngDeclareFactory({
124
+ minVersion: "12.0.0",
125
+ version: "22.2.0",
126
+ ngImport: i0,
127
+ type: DocsService,
128
+ deps: [],
129
+ target: i0.ɵɵFactoryTarget.Injectable
130
+ });
131
+ static ɵprov = i0.ɵɵngDeclareInjectable({
132
+ minVersion: "12.0.0",
133
+ version: "22.2.0",
134
+ ngImport: i0,
135
+ type: DocsService,
136
+ providedIn: "root"
137
+ });
138
+ };
139
+ i0.ɵɵngDeclareClassMetadata({
140
+ minVersion: "12.0.0",
141
+ version: "22.2.0",
142
+ ngImport: i0,
143
+ type: DocsService,
144
+ decorators: [{
145
+ type: Injectable,
146
+ args: [{ providedIn: "root" }]
147
+ }]
148
+ });
149
+ const isNotFound = (error) => error instanceof HttpErrorResponse && error.status === 404;
150
+ let purifier = null;
151
+ function purify() {
152
+ if (purifier || typeof window === "undefined") return purifier;
153
+ purifier = DOMPurify(window);
154
+ purifier.addHook("uponSanitizeElement", (node, data) => {
155
+ if (data.tagName === "input" && node.getAttribute("type")?.toLowerCase() !== "checkbox") node.parentNode?.removeChild(node);
156
+ });
157
+ purifier.addHook("afterSanitizeAttributes", (node) => {
158
+ if (node.nodeName === "INPUT") node.setAttribute("disabled", "");
159
+ if (node.nodeName === "IMG") {
160
+ node.setAttribute("referrerpolicy", "no-referrer");
161
+ node.setAttribute("loading", "lazy");
162
+ }
163
+ });
164
+ purifier.addHook("uponSanitizeAttribute", (_node, data) => {
165
+ if (data.attrName === "class") {
166
+ const kept = data.attrValue.split(/\s+/).filter((c) => /^language-[\w+#.-]+$/.test(c));
167
+ if (kept.length) data.attrValue = kept.join(" ");
168
+ else data.keepAttr = false;
169
+ }
170
+ });
171
+ return purifier;
172
+ }
173
+ const SANITIZE_CONFIG = {
174
+ FORBID_TAGS: [
175
+ "style",
176
+ "form",
177
+ "button",
178
+ "textarea",
179
+ "select",
180
+ "option",
181
+ "optgroup",
182
+ "fieldset",
183
+ "dialog"
184
+ ],
185
+ FORBID_ATTR: [
186
+ "style",
187
+ "popover",
188
+ "popovertarget",
189
+ "popovertargetaction",
190
+ "for",
191
+ "tabindex",
192
+ "aria-owns",
193
+ "aria-controls",
194
+ "aria-labelledby",
195
+ "aria-describedby"
196
+ ],
197
+ SANITIZE_NAMED_PROPS: true
198
+ };
199
+ const ID_PREFIX = "user-content-";
200
+ function headingSlug(text) {
201
+ return text.toLowerCase().replace(/[^\p{L}\p{N}\s_-]/gu, "").trim().replace(/[\s-]+/g, "-").replace(/^-+|-+$/g, "") || "section";
202
+ }
203
+ function applyHeadingIds(root) {
204
+ const headings = Array.from(root.querySelectorAll("h1, h2, h3, h4"));
205
+ const used = /* @__PURE__ */ new Set();
206
+ const outline = [];
207
+ for (const heading of headings) {
208
+ const text = (heading.textContent ?? "").replace(/\s+/g, " ").trim();
209
+ const base = ID_PREFIX + headingSlug(text);
210
+ let id = base;
211
+ for (let n = 2; used.has(id); n++) id = `${base}-${n}`;
212
+ used.add(id);
213
+ heading.id = id;
214
+ const level = Number(heading.tagName[1]);
215
+ if (level >= 2 && !heading.parentElement?.closest("blockquote, details")) outline.push({
216
+ level,
217
+ text,
218
+ id
219
+ });
220
+ }
221
+ for (const node of Array.from(root.querySelectorAll("[id]"))) if (used.has(node.id) && !headings.includes(node)) node.removeAttribute("id");
222
+ return outline;
223
+ }
224
+ function decodeFragment(rawFragment) {
225
+ try {
226
+ return decodeURIComponent(rawFragment);
227
+ } catch {
228
+ return rawFragment;
229
+ }
230
+ }
231
+ function findAnchorTarget(root, rawFragment) {
232
+ const fragment = decodeFragment(rawFragment);
233
+ if (!fragment) return null;
234
+ for (const wanted of [fragment, ID_PREFIX + fragment]) for (const node of Array.from(root.querySelectorAll("[id], a[name]"))) if (node.id === wanted || node.tagName === "A" && node.getAttribute("name") === wanted) return node;
235
+ return null;
236
+ }
237
+ function makeScrollableBlocksFocusable(container, names) {
238
+ for (const pre of Array.from(container.querySelectorAll("pre"))) {
239
+ pre.setAttribute("tabindex", "0");
240
+ pre.setAttribute("role", "region");
241
+ pre.setAttribute("aria-label", names.codeBlock);
242
+ }
243
+ for (const table of Array.from(container.querySelectorAll("table"))) {
244
+ table.setAttribute("tabindex", "0");
245
+ table.setAttribute("aria-label", names.table);
246
+ }
247
+ }
248
+ function nameTaskCheckboxes(container) {
249
+ for (const box of Array.from(container.querySelectorAll("li > input[type=\"checkbox\"], li > p:first-child > input[type=\"checkbox\"]"))) {
250
+ const item = box.closest("li");
251
+ box.setAttribute("aria-label", (item.textContent ?? "").replace(/\s+/g, " ").trim());
252
+ }
253
+ }
254
+ var MarkdownView = class MarkdownView {
255
+ content = input.required(...ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []);
256
+ headingOffset = input(0, ...ngDevMode ? [{ debugName: "headingOffset" }] : /* istanbul ignore next */ []);
257
+ routedLinkPrefix = input(null, ...ngDevMode ? [{ debugName: "routedLinkPrefix" }] : /* istanbul ignore next */ []);
258
+ outline = output();
259
+ sanitizer = inject(DomSanitizer);
260
+ router = inject(Router, { optional: true });
261
+ labels = docsLabels();
262
+ container = viewChild.required("container", ...ngDevMode ? [{ debugName: "container" }] : /* istanbul ignore next */ []);
263
+ constructor() {
264
+ afterRenderEffect({ write: () => {
265
+ this.renderedHtml();
266
+ const container = this.container().nativeElement;
267
+ makeScrollableBlocksFocusable(container, this.labels());
268
+ nameTaskCheckboxes(container);
269
+ this.outline.emit(applyHeadingIds(container));
270
+ } });
271
+ }
272
+ onClick(event) {
273
+ if (event.defaultPrevented || event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
274
+ const container = this.container().nativeElement;
275
+ const routed = this.routedHref(event.target);
276
+ if (routed !== null) {
277
+ event.preventDefault();
278
+ this.router.navigateByUrl(routed);
279
+ return;
280
+ }
281
+ const link = event.target instanceof Element ? event.target.closest("a[href^=\"#\"]") : null;
282
+ if (!link || !container.contains(link)) return;
283
+ event.preventDefault();
284
+ const target = findAnchorTarget(container, link.getAttribute("href").slice(1));
285
+ if (!target) return;
286
+ const reduceMotion = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
287
+ target.scrollIntoView?.({
288
+ behavior: reduceMotion ? "auto" : "smooth",
289
+ block: "start"
290
+ });
291
+ if (target.tabIndex < 0) target.setAttribute("tabindex", "-1");
292
+ target.focus({ preventScroll: true });
293
+ }
294
+ routedHref(target) {
295
+ const prefix = this.routedLinkPrefix();
296
+ const link = prefix && this.router && target instanceof Element ? target.closest("a[href]") : null;
297
+ if (!link || !this.container().nativeElement.contains(link) || link.hasAttribute("target")) return null;
298
+ const href = link.getAttribute("href");
299
+ const rest = href.startsWith(prefix) ? href.slice(prefix.length) : null;
300
+ return rest !== null && (rest === "" || /^[/#?]/.test(rest)) ? href : null;
301
+ }
302
+ renderedHtml = computed(() => {
303
+ const offset = this.headingOffset();
304
+ const walkTokens = offset > 0 ? (token) => {
305
+ if (token.type === "heading") token.depth = Math.min(6, token.depth + offset);
306
+ } : null;
307
+ const sanitizer = purify();
308
+ if (!sanitizer) return "";
309
+ const rawHtml = marked.parse(this.content(), {
310
+ async: false,
311
+ walkTokens
312
+ });
313
+ return this.sanitizer.bypassSecurityTrustHtml(sanitizer.sanitize(rawHtml, SANITIZE_CONFIG));
314
+ }, ...ngDevMode ? [{ debugName: "renderedHtml" }] : /* istanbul ignore next */ []);
315
+ static ɵfac = i0.ɵɵngDeclareFactory({
316
+ minVersion: "12.0.0",
317
+ version: "22.2.0",
318
+ ngImport: i0,
319
+ type: MarkdownView,
320
+ deps: [],
321
+ target: i0.ɵɵFactoryTarget.Component
322
+ });
323
+ static ɵcmp = i0.ɵɵngDeclareComponent({
324
+ minVersion: "17.2.0",
325
+ version: "22.2.0",
326
+ type: MarkdownView,
327
+ isStandalone: true,
328
+ selector: "gbt-markdown-view",
329
+ inputs: {
330
+ content: {
331
+ classPropertyName: "content",
332
+ publicName: "content",
333
+ isSignal: true,
334
+ isRequired: true,
335
+ transformFunction: null
336
+ },
337
+ headingOffset: {
338
+ classPropertyName: "headingOffset",
339
+ publicName: "headingOffset",
340
+ isSignal: true,
341
+ isRequired: false,
342
+ transformFunction: null
343
+ },
344
+ routedLinkPrefix: {
345
+ classPropertyName: "routedLinkPrefix",
346
+ publicName: "routedLinkPrefix",
347
+ isSignal: true,
348
+ isRequired: false,
349
+ transformFunction: null
350
+ }
351
+ },
352
+ outputs: { outline: "outline" },
353
+ viewQueries: [{
354
+ propertyName: "container",
355
+ first: true,
356
+ predicate: ["container"],
357
+ descendants: true,
358
+ isSignal: true
359
+ }],
360
+ ngImport: i0,
361
+ template: `<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
362
+ <div
363
+ class="gbt-markdown-view"
364
+ #container
365
+ [innerHTML]="renderedHtml()"
366
+ (click)="onClick($event)"
367
+ ></div>`,
368
+ isInline: true,
369
+ styles: ["gbt-markdown-view{display:block}.gbt-markdown-view{color:var(--text-primary);font-size:.9375rem;line-height:1.65;overflow-wrap:break-word}.gbt-markdown-view>:first-child{margin-top:0}.gbt-markdown-view>:last-child{margin-bottom:0}.gbt-markdown-view :where(h1,h2,h3,h4,h5,h6){margin:1.75rem 0 .75rem;color:var(--text-primary);font-family:var(--gbt-font-display, inherit);font-weight:600;line-height:1.3}.gbt-markdown-view :where(h1){padding-bottom:.375rem;border-bottom:1px solid var(--gbt-hairline, var(--border-color));font-size:1.625rem;letter-spacing:-.01em}.gbt-markdown-view :where(h2){padding-bottom:.3rem;border-bottom:1px solid var(--gbt-hairline, var(--border-color));font-size:1.3125rem}.gbt-markdown-view :where(h3){font-size:1.0625rem}.gbt-markdown-view :where(h4,h5,h6){font-size:.9375rem}.gbt-markdown-view :where(p,ul,ol,blockquote,pre,table){margin:0 0 1rem}.gbt-markdown-view :where(ul,ol){padding-left:1.5rem}.gbt-markdown-view :where(li+li){margin-top:.25rem}.gbt-markdown-view :where(li:has(>input[type=checkbox]),li:has(>p:first-child>input[type=checkbox])){list-style:none}.gbt-markdown-view :where(li>input[type=checkbox],li>p:first-child>input[type=checkbox]){margin:0 .2em .2em -1.4em;vertical-align:middle}.gbt-markdown-view :where(a){color:var(--primary);text-underline-offset:2px}.gbt-markdown-view :where(strong){font-weight:600}.gbt-markdown-view :where(code){padding:.125rem .375rem;border-radius:var(--site-border-radius-sm);background:var(--bg-hover);font-family:var(--gbt-font-mono, ui-monospace, monospace);font-size:.8125em}.gbt-markdown-view :where(pre){padding:.875rem 1rem;overflow-x:auto;border:1px solid var(--gbt-hairline, var(--border-color));border-radius:var(--site-border-radius-sm);background:var(--bg-panel);line-height:1.5}.gbt-markdown-view :where(pre code){padding:0;background:none;font-size:.8125rem}.gbt-markdown-view :where(blockquote){padding:0 0 0 1rem;border-left:3px solid var(--gbt-card-border, var(--border-color));color:var(--text-secondary)}.gbt-markdown-view :where(hr){height:0;margin:1.5rem 0;border:0;border-top:1px solid var(--gbt-hairline, var(--border-color))}.gbt-markdown-view :where(img){max-width:100%;height:auto}.gbt-markdown-view :where(table){display:block;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:.875rem}.gbt-markdown-view :where(th,td){padding:.375rem .75rem;border:1px solid var(--gbt-card-border, var(--border-color));text-align:left}.gbt-markdown-view :where(th){background:var(--bg-hover);font-weight:600}.gbt-markdown-view :where(pre,table):focus-visible{outline:2px solid var(--gbt-focus-ring, var(--primary));outline-offset:2px}\n"],
370
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
371
+ encapsulation: i0.ViewEncapsulation.None
372
+ });
373
+ };
374
+ i0.ɵɵngDeclareClassMetadata({
375
+ minVersion: "12.0.0",
376
+ version: "22.2.0",
377
+ ngImport: i0,
378
+ type: MarkdownView,
379
+ decorators: [{
380
+ type: Component,
381
+ args: [{
382
+ selector: "gbt-markdown-view",
383
+ standalone: true,
384
+ template: `<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->
385
+ <div
386
+ class="gbt-markdown-view"
387
+ #container
388
+ [innerHTML]="renderedHtml()"
389
+ (click)="onClick($event)"
390
+ ></div>`,
391
+ encapsulation: ViewEncapsulation.None,
392
+ changeDetection: ChangeDetectionStrategy.OnPush,
393
+ styles: ["gbt-markdown-view{display:block}.gbt-markdown-view{color:var(--text-primary);font-size:.9375rem;line-height:1.65;overflow-wrap:break-word}.gbt-markdown-view>:first-child{margin-top:0}.gbt-markdown-view>:last-child{margin-bottom:0}.gbt-markdown-view :where(h1,h2,h3,h4,h5,h6){margin:1.75rem 0 .75rem;color:var(--text-primary);font-family:var(--gbt-font-display, inherit);font-weight:600;line-height:1.3}.gbt-markdown-view :where(h1){padding-bottom:.375rem;border-bottom:1px solid var(--gbt-hairline, var(--border-color));font-size:1.625rem;letter-spacing:-.01em}.gbt-markdown-view :where(h2){padding-bottom:.3rem;border-bottom:1px solid var(--gbt-hairline, var(--border-color));font-size:1.3125rem}.gbt-markdown-view :where(h3){font-size:1.0625rem}.gbt-markdown-view :where(h4,h5,h6){font-size:.9375rem}.gbt-markdown-view :where(p,ul,ol,blockquote,pre,table){margin:0 0 1rem}.gbt-markdown-view :where(ul,ol){padding-left:1.5rem}.gbt-markdown-view :where(li+li){margin-top:.25rem}.gbt-markdown-view :where(li:has(>input[type=checkbox]),li:has(>p:first-child>input[type=checkbox])){list-style:none}.gbt-markdown-view :where(li>input[type=checkbox],li>p:first-child>input[type=checkbox]){margin:0 .2em .2em -1.4em;vertical-align:middle}.gbt-markdown-view :where(a){color:var(--primary);text-underline-offset:2px}.gbt-markdown-view :where(strong){font-weight:600}.gbt-markdown-view :where(code){padding:.125rem .375rem;border-radius:var(--site-border-radius-sm);background:var(--bg-hover);font-family:var(--gbt-font-mono, ui-monospace, monospace);font-size:.8125em}.gbt-markdown-view :where(pre){padding:.875rem 1rem;overflow-x:auto;border:1px solid var(--gbt-hairline, var(--border-color));border-radius:var(--site-border-radius-sm);background:var(--bg-panel);line-height:1.5}.gbt-markdown-view :where(pre code){padding:0;background:none;font-size:.8125rem}.gbt-markdown-view :where(blockquote){padding:0 0 0 1rem;border-left:3px solid var(--gbt-card-border, var(--border-color));color:var(--text-secondary)}.gbt-markdown-view :where(hr){height:0;margin:1.5rem 0;border:0;border-top:1px solid var(--gbt-hairline, var(--border-color))}.gbt-markdown-view :where(img){max-width:100%;height:auto}.gbt-markdown-view :where(table){display:block;max-width:100%;overflow-x:auto;border-collapse:collapse;font-size:.875rem}.gbt-markdown-view :where(th,td){padding:.375rem .75rem;border:1px solid var(--gbt-card-border, var(--border-color));text-align:left}.gbt-markdown-view :where(th){background:var(--bg-hover);font-weight:600}.gbt-markdown-view :where(pre,table):focus-visible{outline:2px solid var(--gbt-focus-ring, var(--primary));outline-offset:2px}\n"]
394
+ }]
395
+ }],
396
+ ctorParameters: () => [],
397
+ propDecorators: {
398
+ content: [{
399
+ type: i0.Input,
400
+ args: [{
401
+ isSignal: true,
402
+ alias: "content",
403
+ required: true
404
+ }]
405
+ }],
406
+ headingOffset: [{
407
+ type: i0.Input,
408
+ args: [{
409
+ isSignal: true,
410
+ alias: "headingOffset",
411
+ required: false
412
+ }]
413
+ }],
414
+ routedLinkPrefix: [{
415
+ type: i0.Input,
416
+ args: [{
417
+ isSignal: true,
418
+ alias: "routedLinkPrefix",
419
+ required: false
420
+ }]
421
+ }],
422
+ outline: [{
423
+ type: i0.Output,
424
+ args: ["outline"]
425
+ }],
426
+ container: [{
427
+ type: i0.ViewChild,
428
+ args: ["container", { isSignal: true }]
429
+ }]
430
+ }
431
+ });
432
+ const DOCS_SEARCH_LIMIT = 8;
433
+ function fold(text) {
434
+ let folded = "";
435
+ const origin = [];
436
+ let at = 0;
437
+ for (const char of text) {
438
+ const plain = char.normalize("NFD").replace(/\p{M}/gu, "").toLowerCase();
439
+ folded += plain;
440
+ for (let i = 0; i < plain.length; i++) origin.push(at);
441
+ at += char.length;
442
+ }
443
+ return {
444
+ text,
445
+ folded,
446
+ origin
447
+ };
448
+ }
449
+ function searchTokens(query) {
450
+ return [...new Set(fold(query).folded.split(/[^\p{L}\p{N}]+/u).filter(Boolean))];
451
+ }
452
+ function inlineText(line) {
453
+ return line.replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/`+/g, "").replace(/(\*\*|__|\*|~~)/g, "").replace(/(^|\s)_(\S)/g, "$1$2").replace(/(\S)_(\s|$)/g, "$1$2");
454
+ }
455
+ function parseDocsPage(markdown) {
456
+ const headings = [];
457
+ const used = /* @__PURE__ */ new Set();
458
+ const body = [];
459
+ let fence = null;
460
+ for (const line of markdown.split(/\r?\n/)) {
461
+ const fenceMark = /^\s*(`{3,}|~{3,})/.exec(line)?.[1];
462
+ if (fence !== null) {
463
+ if (fenceMark && fenceMark[0] === fence[0] && fenceMark.length >= fence.length) fence = null;
464
+ else body.push(line);
465
+ continue;
466
+ }
467
+ if (fenceMark) {
468
+ fence = fenceMark;
469
+ continue;
470
+ }
471
+ const heading = /^(#{1,6})\s+(.*?)\s*#*\s*$/.exec(line);
472
+ if (heading) {
473
+ const level = heading[1].length;
474
+ const text = inlineText(heading[2]).replace(/\s+/g, " ").trim();
475
+ if (level <= 4) {
476
+ const base = `user-content-${headingSlug(text)}`;
477
+ let id = base;
478
+ for (let n = 2; used.has(id); n++) id = `${base}-${n}`;
479
+ used.add(id);
480
+ if (level >= 2) headings.push({
481
+ id,
482
+ text
483
+ });
484
+ }
485
+ continue;
486
+ }
487
+ if (/^\s*\|?\s*:?-{3,}/.test(line)) continue;
488
+ body.push(inlineText(line.replace(/^\s*(>\s*)+/, "").replace(/^\s*([-*+]|\d+[.)])\s+/, "").replace(/\|/g, " ")));
489
+ }
490
+ return {
491
+ headings,
492
+ body: body.join(" ").replace(/\s+/g, " ").trim()
493
+ };
494
+ }
495
+ const isWordStart = (folded, at) => at === 0 || !/[\p{L}\p{N}]/u.test(folded[at - 1]);
496
+ function count(field, token) {
497
+ let found = 0;
498
+ for (let at = field.folded.indexOf(token); at >= 0 && found < 5; at = field.folded.indexOf(token, at + token.length)) found++;
499
+ return found;
500
+ }
501
+ function weight(field, token, base) {
502
+ const at = field.folded.indexOf(token);
503
+ if (at < 0) return 0;
504
+ return isWordStart(field.folded, at) ? base * 1.5 : base;
505
+ }
506
+ const EXCERPT_BEFORE = 40;
507
+ const EXCERPT_LENGTH = 140;
508
+ function excerptAround(field, token) {
509
+ const at = field.folded.indexOf(token);
510
+ if (at < 0) return null;
511
+ const start = field.origin[at];
512
+ const end = at + token.length < field.origin.length ? field.origin[at + token.length] : field.text.length;
513
+ let from = Math.max(0, start - EXCERPT_BEFORE);
514
+ let to = Math.min(field.text.length, from + EXCERPT_LENGTH);
515
+ if (from > 0) {
516
+ const space = field.text.indexOf(" ", from);
517
+ from = space >= 0 && space < start ? space + 1 : from;
518
+ }
519
+ if (to < field.text.length) {
520
+ const space = field.text.lastIndexOf(" ", to);
521
+ to = space > end ? space : to;
522
+ }
523
+ return {
524
+ before: (from > 0 ? "…" : "") + field.text.slice(from, start),
525
+ match: field.text.slice(start, end),
526
+ after: field.text.slice(end, to) + (to < field.text.length ? "…" : "")
527
+ };
528
+ }
529
+ var DocsSearchService = class DocsSearchService {
530
+ docs = inject(DocsService);
531
+ documents = null;
532
+ prepare() {
533
+ this.load().catch(() => {});
534
+ }
535
+ load() {
536
+ this.documents ??= firstValueFrom(this.docs.index().pipe(switchMap((index) => {
537
+ const order = docsReadingOrder(index);
538
+ if (order.length === 0) return of([]);
539
+ return forkJoin(order.map(({ section, page }, position) => this.docs.page(section.slug, page.slug).pipe(map((markdown) => {
540
+ const parsed = parseDocsPage(markdown);
541
+ return {
542
+ order: position,
543
+ sectionTitle: section.title,
544
+ description: page.description,
545
+ commands: docsPageCommands(this.docs.root, section.slug, page.slug),
546
+ title: fold(page.title),
547
+ section: fold(section.title),
548
+ headings: parsed.headings.map((heading) => ({
549
+ id: heading.id,
550
+ field: fold(heading.text)
551
+ })),
552
+ body: fold(parsed.body)
553
+ };
554
+ }), catchError(() => of(null))))).pipe(map((documents) => documents.filter((document) => document !== null)));
555
+ }))).catch((error) => {
556
+ this.documents = null;
557
+ throw error;
558
+ });
559
+ return this.documents;
560
+ }
561
+ async search(query) {
562
+ const tokens = searchTokens(query);
563
+ if (tokens.length === 0) return [];
564
+ const documents = await this.load();
565
+ const scored = [];
566
+ for (const document of documents) {
567
+ let score = 0;
568
+ let complete = true;
569
+ for (const token of tokens) {
570
+ const inTitle = weight(document.title, token, 12);
571
+ const inSection = weight(document.section, token, 3);
572
+ const inHeading = Math.max(0, ...document.headings.map((heading) => weight(heading.field, token, 5)));
573
+ const inBody = count(document.body, token);
574
+ if (inTitle + inSection + inHeading + inBody === 0) {
575
+ complete = false;
576
+ break;
577
+ }
578
+ score += inTitle + inSection + inHeading + inBody;
579
+ }
580
+ if (!complete) continue;
581
+ let heading = null;
582
+ let headingMatches = 0;
583
+ for (const candidate of document.headings) {
584
+ const matches = tokens.filter((token) => candidate.field.folded.includes(token)).length;
585
+ if (matches > headingMatches) {
586
+ heading = candidate;
587
+ headingMatches = matches;
588
+ }
589
+ }
590
+ const excerpt = [...tokens].sort((a, b) => b.length - a.length).map((token) => excerptAround(document.body, token)).find((found) => found !== null) ?? {
591
+ before: document.description,
592
+ match: "",
593
+ after: ""
594
+ };
595
+ scored.push({
596
+ score,
597
+ order: document.order,
598
+ hit: {
599
+ sectionTitle: document.sectionTitle,
600
+ pageTitle: document.title.text,
601
+ commands: document.commands,
602
+ fragment: heading?.id ?? null,
603
+ heading: heading?.field.text ?? null,
604
+ excerpt
605
+ }
606
+ });
607
+ }
608
+ return scored.sort((a, b) => b.score - a.score || a.order - b.order).slice(0, 8).map((entry) => entry.hit);
609
+ }
610
+ static ɵfac = i0.ɵɵngDeclareFactory({
611
+ minVersion: "12.0.0",
612
+ version: "22.2.0",
613
+ ngImport: i0,
614
+ type: DocsSearchService,
615
+ deps: [],
616
+ target: i0.ɵɵFactoryTarget.Injectable
617
+ });
618
+ static ɵprov = i0.ɵɵngDeclareInjectable({
619
+ minVersion: "12.0.0",
620
+ version: "22.2.0",
621
+ ngImport: i0,
622
+ type: DocsSearchService,
623
+ providedIn: "root"
624
+ });
625
+ };
626
+ i0.ɵɵngDeclareClassMetadata({
627
+ minVersion: "12.0.0",
628
+ version: "22.2.0",
629
+ ngImport: i0,
630
+ type: DocsSearchService,
631
+ decorators: [{
632
+ type: Injectable,
633
+ args: [{ providedIn: "root" }]
634
+ }]
635
+ });
636
+ const docsHomeGuard = () => {
637
+ const router = inject(Router);
638
+ const docs = inject(DocsService);
639
+ return docs.index().pipe(map((index) => {
640
+ const first = firstDocsPage(docs.root, index);
641
+ return first ? router.createUrlTree(first) : true;
642
+ }), catchError(() => of(true)));
643
+ };
644
+ function docsRoutes(page) {
645
+ const loadComponent = page;
646
+ return [
647
+ {
648
+ path: "",
649
+ pathMatch: "full",
650
+ canActivate: [docsHomeGuard],
651
+ loadComponent
652
+ },
653
+ {
654
+ path: ":section/:page",
655
+ loadComponent
656
+ },
657
+ {
658
+ path: "**",
659
+ loadComponent
660
+ }
661
+ ];
662
+ }
663
+ var DocsSearch = class DocsSearch {
664
+ opened = output();
665
+ searchService = inject(DocsSearchService);
666
+ router = inject(Router);
667
+ field = viewChild.required(Autocomplete, ...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
668
+ labels = docsLabels();
669
+ search = (query) => this.searchService.search(query);
670
+ label = (hit) => hit.pageTitle;
671
+ announce = (count) => this.labels().results(count);
672
+ prepare() {
673
+ this.searchService.prepare();
674
+ }
675
+ open(hit) {
676
+ this.field().writeValue(null);
677
+ this.router.navigate(hit.commands, { fragment: hit.fragment ?? void 0 });
678
+ this.opened.emit(hit);
679
+ }
680
+ static ɵfac = i0.ɵɵngDeclareFactory({
681
+ minVersion: "12.0.0",
682
+ version: "22.2.0",
683
+ ngImport: i0,
684
+ type: DocsSearch,
685
+ deps: [],
686
+ target: i0.ɵɵFactoryTarget.Component
687
+ });
688
+ static ɵcmp = i0.ɵɵngDeclareComponent({
689
+ minVersion: "17.0.0",
690
+ version: "22.2.0",
691
+ type: DocsSearch,
692
+ isStandalone: true,
693
+ selector: "gbt-docs-search",
694
+ outputs: { opened: "opened" },
695
+ viewQueries: [{
696
+ propertyName: "field",
697
+ first: true,
698
+ predicate: Autocomplete,
699
+ descendants: true,
700
+ isSignal: true
701
+ }],
702
+ ngImport: i0,
703
+ template: "<gbt-autocomplete\n class=\"gbt-docs-search\"\n [label]=\"labels().searchLabel\"\n [placeholder]=\"labels().searchPlaceholder\"\n [search]=\"search\"\n [displayFn]=\"label\"\n [itemTemplate]=\"result\"\n [debounceMs]=\"150\"\n [minLength]=\"2\"\n [loadingMessage]=\"labels().searching\"\n [noResultsMessage]=\"labels().noResults\"\n [searchErrorMessage]=\"labels().searchFailed\"\n [resultsAnnouncement]=\"announce\"\n (focusin)=\"prepare()\"\n (itemSelected)=\"open($event)\"\n/>\n\n<ng-template #result let-hit>\n <span class=\"gbt-docs-search__result\">\n <span class=\"gbt-docs-search__where\">{{ hit.sectionTitle }}</span>\n <span class=\"gbt-docs-search__title\">\n {{ hit.pageTitle }}\n @if (hit.heading) {\n <span class=\"gbt-docs-search__heading\">› {{ hit.heading }}</span>\n }\n </span>\n @if (hit.excerpt.before || hit.excerpt.match) {\n <span class=\"gbt-docs-search__excerpt\"\n >{{ hit.excerpt.before }}<mark>{{ hit.excerpt.match }}</mark\n >{{ hit.excerpt.after }}</span\n >\n }\n </span>\n</ng-template>\n",
704
+ styles: [":host{display:block}.gbt-docs-search ::ng-deep .gbt-autocomplete__label{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.gbt-docs-search__result{display:flex;flex-direction:column;gap:.125rem;min-width:0;text-align:left}.gbt-docs-search__where{color:var(--text-secondary);font-size:.75rem;font-weight:500}.gbt-docs-search__title{color:var(--text-primary);font-size:.875rem;font-weight:600;line-height:1.35;overflow-wrap:anywhere}.gbt-docs-search__heading{color:var(--text-secondary);font-weight:500}.gbt-docs-search__excerpt{display:-webkit-box;overflow:hidden;color:var(--text-secondary);font-size:.75rem;line-height:1.45;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.gbt-docs-search__excerpt mark{padding:0 .0625rem;border-radius:2px;background:color-mix(in srgb,var(--primary) 18%,transparent);color:var(--text-primary)}\n"],
705
+ dependencies: [{
706
+ kind: "component",
707
+ type: Autocomplete,
708
+ selector: "gbt-autocomplete",
709
+ inputs: [
710
+ "id",
711
+ "label",
712
+ "placeholder",
713
+ "disabled",
714
+ "required",
715
+ "errorMessage",
716
+ "search",
717
+ "displayFn",
718
+ "itemTemplate",
719
+ "debounceMs",
720
+ "minLength",
721
+ "loadingMessage",
722
+ "noResultsMessage",
723
+ "searchErrorMessage",
724
+ "resultsAnnouncement"
725
+ ],
726
+ outputs: ["itemSelected"]
727
+ }],
728
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
729
+ });
730
+ };
731
+ i0.ɵɵngDeclareClassMetadata({
732
+ minVersion: "12.0.0",
733
+ version: "22.2.0",
734
+ ngImport: i0,
735
+ type: DocsSearch,
736
+ decorators: [{
737
+ type: Component,
738
+ args: [{
739
+ selector: "gbt-docs-search",
740
+ standalone: true,
741
+ imports: [Autocomplete],
742
+ changeDetection: ChangeDetectionStrategy.OnPush,
743
+ template: "<gbt-autocomplete\n class=\"gbt-docs-search\"\n [label]=\"labels().searchLabel\"\n [placeholder]=\"labels().searchPlaceholder\"\n [search]=\"search\"\n [displayFn]=\"label\"\n [itemTemplate]=\"result\"\n [debounceMs]=\"150\"\n [minLength]=\"2\"\n [loadingMessage]=\"labels().searching\"\n [noResultsMessage]=\"labels().noResults\"\n [searchErrorMessage]=\"labels().searchFailed\"\n [resultsAnnouncement]=\"announce\"\n (focusin)=\"prepare()\"\n (itemSelected)=\"open($event)\"\n/>\n\n<ng-template #result let-hit>\n <span class=\"gbt-docs-search__result\">\n <span class=\"gbt-docs-search__where\">{{ hit.sectionTitle }}</span>\n <span class=\"gbt-docs-search__title\">\n {{ hit.pageTitle }}\n @if (hit.heading) {\n <span class=\"gbt-docs-search__heading\">› {{ hit.heading }}</span>\n }\n </span>\n @if (hit.excerpt.before || hit.excerpt.match) {\n <span class=\"gbt-docs-search__excerpt\"\n >{{ hit.excerpt.before }}<mark>{{ hit.excerpt.match }}</mark\n >{{ hit.excerpt.after }}</span\n >\n }\n </span>\n</ng-template>\n",
744
+ styles: [":host{display:block}.gbt-docs-search ::ng-deep .gbt-autocomplete__label{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.gbt-docs-search__result{display:flex;flex-direction:column;gap:.125rem;min-width:0;text-align:left}.gbt-docs-search__where{color:var(--text-secondary);font-size:.75rem;font-weight:500}.gbt-docs-search__title{color:var(--text-primary);font-size:.875rem;font-weight:600;line-height:1.35;overflow-wrap:anywhere}.gbt-docs-search__heading{color:var(--text-secondary);font-weight:500}.gbt-docs-search__excerpt{display:-webkit-box;overflow:hidden;color:var(--text-secondary);font-size:.75rem;line-height:1.45;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}.gbt-docs-search__excerpt mark{padding:0 .0625rem;border-radius:2px;background:color-mix(in srgb,var(--primary) 18%,transparent);color:var(--text-primary)}\n"]
745
+ }]
746
+ }],
747
+ propDecorators: {
748
+ opened: [{
749
+ type: i0.Output,
750
+ args: ["opened"]
751
+ }],
752
+ field: [{
753
+ type: i0.ViewChild,
754
+ args: [i0.forwardRef(() => Autocomplete), { isSignal: true }]
755
+ }]
756
+ }
757
+ });
758
+ let nextNavId = 0;
759
+ var DocsNav = class DocsNav {
760
+ index = input.required(...ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []);
761
+ section = input(null, ...ngDevMode ? [{ debugName: "section" }] : /* istanbul ignore next */ []);
762
+ page = input(null, ...ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []);
763
+ root = inject(DocsService).root;
764
+ labels = docsLabels();
765
+ bodyId = `gbt-docs-nav-${++nextNavId}`;
766
+ navOpen = signal(false, ...ngDevMode ? [{ debugName: "navOpen" }] : /* istanbul ignore next */ []);
767
+ toggled = linkedSignal({
768
+ ...ngDevMode ? { debugName: "toggled" } : /* istanbul ignore next */ {},
769
+ source: this.section,
770
+ computation: () => ({})
771
+ });
772
+ sections = computed(() => this.index().sections.map((section) => {
773
+ const current = section.slug === this.section();
774
+ return {
775
+ slug: section.slug,
776
+ title: section.title,
777
+ open: this.toggled()[section.slug] ?? current,
778
+ pages: section.pages.map((page) => ({
779
+ slug: page.slug,
780
+ title: page.title,
781
+ commands: docsPageCommands(this.root, section.slug, page.slug),
782
+ current: current && page.slug === this.page()
783
+ }))
784
+ };
785
+ }), ...ngDevMode ? [{ debugName: "sections" }] : /* istanbul ignore next */ []);
786
+ setOpen(slug, open) {
787
+ this.toggled.update((toggled) => ({
788
+ ...toggled,
789
+ [slug]: open
790
+ }));
791
+ }
792
+ close() {
793
+ this.navOpen.set(false);
794
+ }
795
+ static ɵfac = i0.ɵɵngDeclareFactory({
796
+ minVersion: "12.0.0",
797
+ version: "22.2.0",
798
+ ngImport: i0,
799
+ type: DocsNav,
800
+ deps: [],
801
+ target: i0.ɵɵFactoryTarget.Component
802
+ });
803
+ static ɵcmp = i0.ɵɵngDeclareComponent({
804
+ minVersion: "17.0.0",
805
+ version: "22.2.0",
806
+ type: DocsNav,
807
+ isStandalone: true,
808
+ selector: "gbt-docs-nav",
809
+ inputs: {
810
+ index: {
811
+ classPropertyName: "index",
812
+ publicName: "index",
813
+ isSignal: true,
814
+ isRequired: true,
815
+ transformFunction: null
816
+ },
817
+ section: {
818
+ classPropertyName: "section",
819
+ publicName: "section",
820
+ isSignal: true,
821
+ isRequired: false,
822
+ transformFunction: null
823
+ },
824
+ page: {
825
+ classPropertyName: "page",
826
+ publicName: "page",
827
+ isSignal: true,
828
+ isRequired: false,
829
+ transformFunction: null
830
+ }
831
+ },
832
+ ngImport: i0,
833
+ template: "<div class=\"gbt-docs-nav\" [class.gbt-docs-nav--open]=\"navOpen()\">\n <div class=\"gbt-docs-nav__header\">\n <h2 class=\"gbt-docs-nav__heading\">{{ labels().documentation }}</h2>\n <gbt-button\n class=\"gbt-docs-nav__toggle\"\n variant=\"secondary\"\n size=\"small\"\n iconName=\"list\"\n [text]=\"navOpen() ? labels().hideContents : labels().showContents\"\n [ariaExpanded]=\"navOpen()\"\n [ariaControls]=\"bodyId\"\n (clicked)=\"navOpen.set(!navOpen())\"\n />\n </div>\n\n <gbt-docs-search class=\"gbt-docs-nav__search\" (opened)=\"close()\" />\n\n <div class=\"gbt-docs-nav__body\" [id]=\"bodyId\">\n @for (section of sections(); track section.slug) {\n <gbt-disclosure\n class=\"gbt-docs-nav__section\"\n appearance=\"plain\"\n [headingLevel]=\"3\"\n [label]=\"section.title\"\n [open]=\"section.open\"\n (openChange)=\"setOpen(section.slug, $event)\"\n >\n <gbt-nav-tabs orientation=\"vertical\" [landmark]=\"false\">\n @for (page of section.pages; track page.slug) {\n <a gbtNavTab [routerLink]=\"page.commands\" [active]=\"page.current\" (click)=\"close()\">{{\n page.title\n }}</a>\n }\n </gbt-nav-tabs>\n </gbt-disclosure>\n }\n </div>\n</div>\n",
834
+ styles: [":host{display:block}.gbt-docs-nav__header{display:flex;align-items:center;gap:.5rem;min-height:2.25rem;margin-bottom:.5rem}.gbt-docs-nav__heading{flex:1;min-width:0;margin:0;color:var(--text-secondary);font-size:.8125rem;font-weight:600;line-height:1.4}.gbt-docs-nav__toggle{display:none}.gbt-docs-nav__search{margin-bottom:.75rem}.gbt-docs-nav__body{display:flex;flex-direction:column;gap:.25rem}.gbt-docs-nav__section ::ng-deep .gbt-disclosure__toggle{width:100%;padding-inline:.75rem .5rem;color:var(--text-primary);font-size:.8125rem}.gbt-docs-nav__section ::ng-deep .gbt-disclosure__content{padding:.125rem 0 .5rem .5rem}@container gbt-page-layout (min-width: 769px){.gbt-docs-nav__body{max-height:calc(100vh - 8rem);margin-inline:-.25rem;padding-inline:.25rem;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin}}@container gbt-page-layout (max-width: 768px){.gbt-docs-nav{padding-bottom:.75rem;border-bottom:1px solid var(--gbt-hairline, var(--border-color))}.gbt-docs-nav__heading{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.gbt-docs-nav__toggle{display:block;flex:0 1 auto;min-width:0;margin-right:auto}.gbt-docs-nav__search{margin-bottom:0}.gbt-docs-nav__body{display:none;margin-top:.75rem}.gbt-docs-nav--open .gbt-docs-nav__body{display:flex}.gbt-docs-nav__section ::ng-deep .gbt-nav-tabs[data-orientation=vertical] div.gbt-nav-tabs__list{flex-direction:column;gap:2px;overflow:visible;box-shadow:none;-webkit-mask-image:none;mask-image:none}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical]{padding:.4375rem .75rem;border-bottom:0;border-radius:var(--site-border-radius-sm);font-weight:400;white-space:normal}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical]:hover{background:var(--bg-hover)}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical][data-active]{background:color-mix(in srgb,var(--primary) 10%,transparent);font-weight:600}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical][data-active]:before{content:\"\"}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical] .gbt-nav-tab__label{flex:1;overflow-wrap:anywhere}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical] .gbt-nav-tab__label:after{content:none}}\n"],
835
+ dependencies: [
836
+ {
837
+ kind: "directive",
838
+ type: RouterLink,
839
+ selector: "[routerLink]",
840
+ inputs: [
841
+ "target",
842
+ "queryParams",
843
+ "fragment",
844
+ "queryParamsHandling",
845
+ "state",
846
+ "info",
847
+ "relativeTo",
848
+ "preserveFragment",
849
+ "skipLocationChange",
850
+ "replaceUrl",
851
+ "browserUrl",
852
+ "routerLink"
853
+ ]
854
+ },
855
+ {
856
+ kind: "component",
857
+ type: Button,
858
+ selector: "gbt-button, a[gbtButton]",
859
+ inputs: [
860
+ "variant",
861
+ "size",
862
+ "type",
863
+ "text",
864
+ "iconName",
865
+ "ariaLabel",
866
+ "loading",
867
+ "loadingLabel",
868
+ "disabled",
869
+ "pressed",
870
+ "ariaExpanded",
871
+ "ariaControls",
872
+ "ariaHaspopup",
873
+ "block",
874
+ "iconOnly"
875
+ ],
876
+ outputs: ["clicked"]
877
+ },
878
+ {
879
+ kind: "component",
880
+ type: Disclosure,
881
+ selector: "gbt-disclosure",
882
+ inputs: [
883
+ "label",
884
+ "open",
885
+ "icon",
886
+ "appearance",
887
+ "headingLevel"
888
+ ],
889
+ outputs: ["openChange"]
890
+ },
891
+ {
892
+ kind: "component",
893
+ type: NavTab,
894
+ selector: "a[gbtNavTab]",
895
+ inputs: [
896
+ "active",
897
+ "icon",
898
+ "badge"
899
+ ]
900
+ },
901
+ {
902
+ kind: "component",
903
+ type: NavTabs,
904
+ selector: "gbt-nav-tabs",
905
+ inputs: [
906
+ "ariaLabel",
907
+ "orientation",
908
+ "landmark"
909
+ ]
910
+ },
911
+ {
912
+ kind: "component",
913
+ type: DocsSearch,
914
+ selector: "gbt-docs-search",
915
+ outputs: ["opened"]
916
+ }
917
+ ],
918
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
919
+ });
920
+ };
921
+ i0.ɵɵngDeclareClassMetadata({
922
+ minVersion: "12.0.0",
923
+ version: "22.2.0",
924
+ ngImport: i0,
925
+ type: DocsNav,
926
+ decorators: [{
927
+ type: Component,
928
+ args: [{
929
+ selector: "gbt-docs-nav",
930
+ standalone: true,
931
+ imports: [
932
+ RouterLink,
933
+ Button,
934
+ Disclosure,
935
+ NavTab,
936
+ NavTabs,
937
+ DocsSearch
938
+ ],
939
+ changeDetection: ChangeDetectionStrategy.OnPush,
940
+ template: "<div class=\"gbt-docs-nav\" [class.gbt-docs-nav--open]=\"navOpen()\">\n <div class=\"gbt-docs-nav__header\">\n <h2 class=\"gbt-docs-nav__heading\">{{ labels().documentation }}</h2>\n <gbt-button\n class=\"gbt-docs-nav__toggle\"\n variant=\"secondary\"\n size=\"small\"\n iconName=\"list\"\n [text]=\"navOpen() ? labels().hideContents : labels().showContents\"\n [ariaExpanded]=\"navOpen()\"\n [ariaControls]=\"bodyId\"\n (clicked)=\"navOpen.set(!navOpen())\"\n />\n </div>\n\n <gbt-docs-search class=\"gbt-docs-nav__search\" (opened)=\"close()\" />\n\n <div class=\"gbt-docs-nav__body\" [id]=\"bodyId\">\n @for (section of sections(); track section.slug) {\n <gbt-disclosure\n class=\"gbt-docs-nav__section\"\n appearance=\"plain\"\n [headingLevel]=\"3\"\n [label]=\"section.title\"\n [open]=\"section.open\"\n (openChange)=\"setOpen(section.slug, $event)\"\n >\n <gbt-nav-tabs orientation=\"vertical\" [landmark]=\"false\">\n @for (page of section.pages; track page.slug) {\n <a gbtNavTab [routerLink]=\"page.commands\" [active]=\"page.current\" (click)=\"close()\">{{\n page.title\n }}</a>\n }\n </gbt-nav-tabs>\n </gbt-disclosure>\n }\n </div>\n</div>\n",
941
+ styles: [":host{display:block}.gbt-docs-nav__header{display:flex;align-items:center;gap:.5rem;min-height:2.25rem;margin-bottom:.5rem}.gbt-docs-nav__heading{flex:1;min-width:0;margin:0;color:var(--text-secondary);font-size:.8125rem;font-weight:600;line-height:1.4}.gbt-docs-nav__toggle{display:none}.gbt-docs-nav__search{margin-bottom:.75rem}.gbt-docs-nav__body{display:flex;flex-direction:column;gap:.25rem}.gbt-docs-nav__section ::ng-deep .gbt-disclosure__toggle{width:100%;padding-inline:.75rem .5rem;color:var(--text-primary);font-size:.8125rem}.gbt-docs-nav__section ::ng-deep .gbt-disclosure__content{padding:.125rem 0 .5rem .5rem}@container gbt-page-layout (min-width: 769px){.gbt-docs-nav__body{max-height:calc(100vh - 8rem);margin-inline:-.25rem;padding-inline:.25rem;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin}}@container gbt-page-layout (max-width: 768px){.gbt-docs-nav{padding-bottom:.75rem;border-bottom:1px solid var(--gbt-hairline, var(--border-color))}.gbt-docs-nav__heading{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.gbt-docs-nav__toggle{display:block;flex:0 1 auto;min-width:0;margin-right:auto}.gbt-docs-nav__search{margin-bottom:0}.gbt-docs-nav__body{display:none;margin-top:.75rem}.gbt-docs-nav--open .gbt-docs-nav__body{display:flex}.gbt-docs-nav__section ::ng-deep .gbt-nav-tabs[data-orientation=vertical] div.gbt-nav-tabs__list{flex-direction:column;gap:2px;overflow:visible;box-shadow:none;-webkit-mask-image:none;mask-image:none}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical]{padding:.4375rem .75rem;border-bottom:0;border-radius:var(--site-border-radius-sm);font-weight:400;white-space:normal}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical]:hover{background:var(--bg-hover)}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical][data-active]{background:color-mix(in srgb,var(--primary) 10%,transparent);font-weight:600}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical][data-active]:before{content:\"\"}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical] .gbt-nav-tab__label{flex:1;overflow-wrap:anywhere}.gbt-docs-nav__section ::ng-deep a.gbt-nav-tab[data-orientation=vertical] .gbt-nav-tab__label:after{content:none}}\n"]
942
+ }]
943
+ }],
944
+ propDecorators: {
945
+ index: [{
946
+ type: i0.Input,
947
+ args: [{
948
+ isSignal: true,
949
+ alias: "index",
950
+ required: true
951
+ }]
952
+ }],
953
+ section: [{
954
+ type: i0.Input,
955
+ args: [{
956
+ isSignal: true,
957
+ alias: "section",
958
+ required: false
959
+ }]
960
+ }],
961
+ page: [{
962
+ type: i0.Input,
963
+ args: [{
964
+ isSignal: true,
965
+ alias: "page",
966
+ required: false
967
+ }]
968
+ }]
969
+ }
970
+ });
971
+ function hasOutline(entries) {
972
+ return entries.length >= 2;
973
+ }
974
+ var MarkdownOutline = class MarkdownOutline {
975
+ entries = input.required(...ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []);
976
+ headingLevel = input(2, ...ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []);
977
+ labels = docsLabels();
978
+ here = [];
979
+ goTo(id) {
980
+ const heading = document.getElementById(id);
981
+ if (!heading) return;
982
+ const reduceMotion = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
983
+ heading.scrollIntoView?.({
984
+ behavior: reduceMotion ? "auto" : "smooth",
985
+ block: "start"
986
+ });
987
+ heading.setAttribute("tabindex", "-1");
988
+ heading.focus({ preventScroll: true });
989
+ }
990
+ static ɵfac = i0.ɵɵngDeclareFactory({
991
+ minVersion: "12.0.0",
992
+ version: "22.2.0",
993
+ ngImport: i0,
994
+ type: MarkdownOutline,
995
+ deps: [],
996
+ target: i0.ɵɵFactoryTarget.Component
997
+ });
998
+ static ɵcmp = i0.ɵɵngDeclareComponent({
999
+ minVersion: "17.0.0",
1000
+ version: "22.2.0",
1001
+ type: MarkdownOutline,
1002
+ isStandalone: true,
1003
+ selector: "gbt-markdown-outline",
1004
+ inputs: {
1005
+ entries: {
1006
+ classPropertyName: "entries",
1007
+ publicName: "entries",
1008
+ isSignal: true,
1009
+ isRequired: true,
1010
+ transformFunction: null
1011
+ },
1012
+ headingLevel: {
1013
+ classPropertyName: "headingLevel",
1014
+ publicName: "headingLevel",
1015
+ isSignal: true,
1016
+ isRequired: false,
1017
+ transformFunction: null
1018
+ }
1019
+ },
1020
+ ngImport: i0,
1021
+ template: "<gbt-panel [heading]=\"labels().onThisPage\" [headingLevel]=\"headingLevel()\">\n <ul class=\"gbt-markdown-outline__list\">\n @for (entry of entries(); track entry.id) {\n <li class=\"gbt-markdown-outline__item\" [attr.data-level]=\"entry.level\">\n <a\n class=\"gbt-markdown-outline__link\"\n [routerLink]=\"here\"\n [fragment]=\"entry.id\"\n [title]=\"entry.text\"\n (click)=\"goTo(entry.id)\"\n >{{ entry.text }}</a\n >\n </li>\n }\n </ul>\n</gbt-panel>\n",
1022
+ styles: [":host{display:block}.gbt-markdown-outline__list{margin:0;padding:0;list-style:none;border-left:1px solid var(--gbt-hairline, var(--border-color))}.gbt-markdown-outline__link{display:block;margin-left:-1px;padding:.25rem .5rem .25rem .75rem;border-left:2px solid transparent;color:var(--text-secondary);font-size:.8125rem;line-height:1.45;text-decoration:none;overflow-wrap:anywhere;transition:border-color var(--site-transition-fast),color var(--site-transition-fast)}.gbt-markdown-outline__link:hover{border-left-color:var(--primary);color:var(--text-primary)}.gbt-markdown-outline__link:focus-visible{border-radius:var(--site-border-radius-sm);outline:2px solid var(--gbt-focus-ring, var(--primary));outline-offset:-2px}.gbt-markdown-outline__item[data-level=\"2\"] .gbt-markdown-outline__link{color:var(--text-primary)}.gbt-markdown-outline__item[data-level=\"3\"] .gbt-markdown-outline__link{padding-left:1.5rem}.gbt-markdown-outline__item[data-level=\"4\"] .gbt-markdown-outline__link{padding-left:2.25rem}@media(prefers-reduced-motion:reduce){.gbt-markdown-outline__link{transition:none}}\n"],
1023
+ dependencies: [{
1024
+ kind: "directive",
1025
+ type: RouterLink,
1026
+ selector: "[routerLink]",
1027
+ inputs: [
1028
+ "target",
1029
+ "queryParams",
1030
+ "fragment",
1031
+ "queryParamsHandling",
1032
+ "state",
1033
+ "info",
1034
+ "relativeTo",
1035
+ "preserveFragment",
1036
+ "skipLocationChange",
1037
+ "replaceUrl",
1038
+ "browserUrl",
1039
+ "routerLink"
1040
+ ]
1041
+ }, {
1042
+ kind: "component",
1043
+ type: Panel,
1044
+ selector: "gbt-panel",
1045
+ inputs: ["heading", "headingLevel"]
1046
+ }],
1047
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1048
+ });
1049
+ };
1050
+ i0.ɵɵngDeclareClassMetadata({
1051
+ minVersion: "12.0.0",
1052
+ version: "22.2.0",
1053
+ ngImport: i0,
1054
+ type: MarkdownOutline,
1055
+ decorators: [{
1056
+ type: Component,
1057
+ args: [{
1058
+ selector: "gbt-markdown-outline",
1059
+ standalone: true,
1060
+ imports: [RouterLink, Panel],
1061
+ changeDetection: ChangeDetectionStrategy.OnPush,
1062
+ template: "<gbt-panel [heading]=\"labels().onThisPage\" [headingLevel]=\"headingLevel()\">\n <ul class=\"gbt-markdown-outline__list\">\n @for (entry of entries(); track entry.id) {\n <li class=\"gbt-markdown-outline__item\" [attr.data-level]=\"entry.level\">\n <a\n class=\"gbt-markdown-outline__link\"\n [routerLink]=\"here\"\n [fragment]=\"entry.id\"\n [title]=\"entry.text\"\n (click)=\"goTo(entry.id)\"\n >{{ entry.text }}</a\n >\n </li>\n }\n </ul>\n</gbt-panel>\n",
1063
+ styles: [":host{display:block}.gbt-markdown-outline__list{margin:0;padding:0;list-style:none;border-left:1px solid var(--gbt-hairline, var(--border-color))}.gbt-markdown-outline__link{display:block;margin-left:-1px;padding:.25rem .5rem .25rem .75rem;border-left:2px solid transparent;color:var(--text-secondary);font-size:.8125rem;line-height:1.45;text-decoration:none;overflow-wrap:anywhere;transition:border-color var(--site-transition-fast),color var(--site-transition-fast)}.gbt-markdown-outline__link:hover{border-left-color:var(--primary);color:var(--text-primary)}.gbt-markdown-outline__link:focus-visible{border-radius:var(--site-border-radius-sm);outline:2px solid var(--gbt-focus-ring, var(--primary));outline-offset:-2px}.gbt-markdown-outline__item[data-level=\"2\"] .gbt-markdown-outline__link{color:var(--text-primary)}.gbt-markdown-outline__item[data-level=\"3\"] .gbt-markdown-outline__link{padding-left:1.5rem}.gbt-markdown-outline__item[data-level=\"4\"] .gbt-markdown-outline__link{padding-left:2.25rem}@media(prefers-reduced-motion:reduce){.gbt-markdown-outline__link{transition:none}}\n"]
1064
+ }]
1065
+ }],
1066
+ propDecorators: {
1067
+ entries: [{
1068
+ type: i0.Input,
1069
+ args: [{
1070
+ isSignal: true,
1071
+ alias: "entries",
1072
+ required: true
1073
+ }]
1074
+ }],
1075
+ headingLevel: [{
1076
+ type: i0.Input,
1077
+ args: [{
1078
+ isSignal: true,
1079
+ alias: "headingLevel",
1080
+ required: false
1081
+ }]
1082
+ }]
1083
+ }
1084
+ });
1085
+ const keyOf = (section, page) => `${section}/${page}`;
1086
+ var DocsPage = class DocsPage {
1087
+ docs = inject(DocsService);
1088
+ route = inject(ActivatedRoute);
1089
+ setTitle = inject(DOCS_TITLE, { optional: true });
1090
+ callouts = inject(DOCS_CONFIG).callouts;
1091
+ host = inject(ElementRef);
1092
+ labels = docsLabels();
1093
+ root = this.docs.root;
1094
+ skeletonRows = [
1095
+ "38%",
1096
+ "92%",
1097
+ "84%",
1098
+ "96%",
1099
+ "60%"
1100
+ ];
1101
+ reload$ = new BehaviorSubject(void 0);
1102
+ index = signal(null, ...ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []);
1103
+ params = toSignal(this.route.paramMap, { requireSync: true });
1104
+ sectionSlug = computed(() => this.params().get("section"), ...ngDevMode ? [{ debugName: "sectionSlug" }] : /* istanbul ignore next */ []);
1105
+ pageSlug = computed(() => this.params().get("page"), ...ngDevMode ? [{ debugName: "pageSlug" }] : /* istanbul ignore next */ []);
1106
+ view = toSignal(combineLatest([this.route.paramMap, this.reload$]).pipe(switchMap(([params]) => this.load(params))), { initialValue: { kind: "loading" } });
1107
+ page = computed(() => {
1108
+ const view = this.view();
1109
+ return view.kind === "page" ? view : null;
1110
+ }, ...ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []);
1111
+ notFound = computed(() => {
1112
+ const view = this.view();
1113
+ return view.kind === "not-found" ? view : null;
1114
+ }, ...ngDevMode ? [{ debugName: "notFound" }] : /* istanbul ignore next */ []);
1115
+ outline = signal([], ...ngDevMode ? [{ debugName: "outline" }] : /* istanbul ignore next */ []);
1116
+ showOutline = computed(() => this.view().kind === "page" && hasOutline(this.outline()), ...ngDevMode ? [{ debugName: "showOutline" }] : /* istanbul ignore next */ []);
1117
+ wanted = null;
1118
+ renderedKey = null;
1119
+ constructor() {
1120
+ effect(() => {
1121
+ const view = this.view();
1122
+ const labels = this.labels();
1123
+ this.setTitle?.(view.kind === "page" ? view.location.page.title : view.kind === "not-found" ? labels.notFoundHeading : labels.documentation);
1124
+ });
1125
+ let first = true;
1126
+ combineLatest([this.route.paramMap, this.route.fragment]).pipe(debounceTime(0), takeUntilDestroyed(inject(DestroyRef))).subscribe(([params, fragment]) => {
1127
+ this.wanted = {
1128
+ key: keyOf(params.get("section"), params.get("page")),
1129
+ fragment,
1130
+ moveFocus: !first
1131
+ };
1132
+ first = false;
1133
+ this.settle();
1134
+ });
1135
+ }
1136
+ load(params) {
1137
+ const section = params.get("section");
1138
+ const page = params.get("page");
1139
+ return this.docs.index().pipe(tap((index) => this.index.set(index)), switchMap((index) => {
1140
+ const location = locateDocsPage(this.root, index, section, page);
1141
+ const notFound = {
1142
+ kind: "not-found",
1143
+ firstPage: firstDocsPage(this.root, index)
1144
+ };
1145
+ if (!location) return of(notFound);
1146
+ return this.docs.page(location.section.slug, location.page.slug).pipe(map((content) => ({
1147
+ kind: "page",
1148
+ location,
1149
+ content
1150
+ })), catchError((error) => of(isNotFound(error) ? notFound : { kind: "failed" })));
1151
+ }), catchError(() => of({ kind: "failed" })), startWith({ kind: "loading" }));
1152
+ }
1153
+ retry() {
1154
+ this.reload$.next();
1155
+ }
1156
+ sectionLink(location) {
1157
+ return docsPageCommands(this.root, location.section.slug, location.section.pages[0].slug);
1158
+ }
1159
+ onRendered(entries) {
1160
+ this.outline.set(entries);
1161
+ const content = this.content();
1162
+ if (!content) return;
1163
+ for (const quote of Array.from(content.querySelectorAll("blockquote"))) {
1164
+ const lead = quote.firstElementChild?.tagName === "P" ? quote.firstElementChild.firstChild : null;
1165
+ const word = lead instanceof HTMLElement && lead.tagName === "STRONG" ? (lead.textContent ?? "").trim().toLowerCase() : "";
1166
+ const kind = Object.hasOwn(this.callouts, word) ? this.callouts[word] : void 0;
1167
+ if (kind) {
1168
+ quote.setAttribute("data-callout", kind);
1169
+ quote.setAttribute("role", "note");
1170
+ }
1171
+ }
1172
+ const view = this.view();
1173
+ this.renderedKey = view.kind === "page" ? keyOf(view.location.section.slug, view.location.page.slug) : null;
1174
+ this.settle();
1175
+ }
1176
+ content() {
1177
+ return this.host.nativeElement.querySelector(".gbt-docs-page__content");
1178
+ }
1179
+ settle() {
1180
+ const wanted = this.wanted;
1181
+ const content = this.content();
1182
+ if (!wanted || wanted.key !== this.renderedKey || !content) return;
1183
+ this.wanted = null;
1184
+ const reduceMotion = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
1185
+ const target = wanted.fragment ? findAnchorTarget(content, wanted.fragment) : null;
1186
+ if (target) {
1187
+ target.scrollIntoView?.({
1188
+ behavior: wanted.moveFocus && !reduceMotion ? "smooth" : "auto",
1189
+ block: "start"
1190
+ });
1191
+ if (wanted.moveFocus) this.focus(target);
1192
+ return;
1193
+ }
1194
+ if (wanted.moveFocus) {
1195
+ const heading = content.querySelector("h1");
1196
+ if (heading) this.focus(heading);
1197
+ this.host.nativeElement.ownerDocument.defaultView?.scrollTo?.({ top: 0 });
1198
+ }
1199
+ }
1200
+ focus(element) {
1201
+ if (element.tabIndex < 0) element.setAttribute("tabindex", "-1");
1202
+ element.focus({ preventScroll: true });
1203
+ }
1204
+ static ɵfac = i0.ɵɵngDeclareFactory({
1205
+ minVersion: "12.0.0",
1206
+ version: "22.2.0",
1207
+ ngImport: i0,
1208
+ type: DocsPage,
1209
+ deps: [],
1210
+ target: i0.ɵɵFactoryTarget.Component
1211
+ });
1212
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1213
+ minVersion: "17.0.0",
1214
+ version: "22.2.0",
1215
+ type: DocsPage,
1216
+ isStandalone: true,
1217
+ selector: "gbt-docs-page",
1218
+ ngImport: i0,
1219
+ template: "<gbt-page-layout\n width=\"wide\"\n asideWidth=\"sm\"\n [navLabel]=\"labels().documentation\"\n [asideLabel]=\"labels().onThisPage\"\n stickyNav\n>\n <!-- One root per projected block: a control-flow block only gets projected into a named slot that way. -->\n @if (index(); as index) {\n <gbt-docs-nav page-nav [index]=\"index\" [section]=\"sectionSlug()\" [page]=\"pageSlug()\" />\n }\n\n <div class=\"gbt-docs-page\">\n @if (page(); as page) {\n <gbt-breadcrumb class=\"gbt-docs-page__breadcrumb\" [ariaLabel]=\"labels().breadcrumb\">\n <li breadcrumb-ancestor>\n <a class=\"gbt-breadcrumb__item\" [routerLink]=\"root\">{{ labels().documentation }}</a>\n </li>\n <li breadcrumb-ancestor>\n <a class=\"gbt-breadcrumb__item\" [routerLink]=\"sectionLink(page.location)\">{{\n page.location.section.title\n }}</a>\n </li>\n {{ page.location.page.title }}\n </gbt-breadcrumb>\n\n <article class=\"gbt-docs-page__article\">\n <gbt-card variant=\"outlined\" [flush]=\"true\">\n <div class=\"gbt-docs-page__body\">\n <gbt-markdown-view\n class=\"gbt-docs-page__content\"\n [content]=\"page.content\"\n [routedLinkPrefix]=\"root\"\n (outline)=\"onRendered($event)\"\n />\n </div>\n </gbt-card>\n </article>\n\n @if (page.location.previous || page.location.next) {\n <nav class=\"gbt-docs-page__pager\" [attr.aria-label]=\"labels().neighbours\">\n @if (page.location.previous; as previous) {\n <gbt-card class=\"gbt-docs-page__neighbour\" variant=\"outlined\" hoverable>\n <span class=\"gbt-docs-page__neighbour-label\"\n >{{ labels().previous }} · {{ previous.sectionTitle }}</span\n >\n <a\n gbtCardLink\n class=\"gbt-docs-page__neighbour-link\"\n [routerLink]=\"previous.commands\"\n >{{ previous.title }}</a\n >\n </gbt-card>\n }\n @if (page.location.next; as next) {\n <gbt-card\n class=\"gbt-docs-page__neighbour gbt-docs-page__neighbour--next\"\n variant=\"outlined\"\n hoverable\n >\n <span class=\"gbt-docs-page__neighbour-label\"\n >{{ labels().next }} · {{ next.sectionTitle }}</span\n >\n <a gbtCardLink class=\"gbt-docs-page__neighbour-link\" [routerLink]=\"next.commands\">{{\n next.title\n }}</a>\n </gbt-card>\n }\n </nav>\n }\n } @else if (notFound(); as notFound) {\n <gbt-card class=\"gbt-docs-page__not-found\" variant=\"outlined\">\n <gbt-empty-state\n illustration=\"book\"\n [headingLevel]=\"1\"\n [heading]=\"labels().notFoundHeading\"\n [message]=\"labels().notFoundMessage\"\n >\n @if (notFound.firstPage; as firstPage) {\n <a gbtButton variant=\"primary\" [routerLink]=\"firstPage\">{{ labels().toStart }}</a>\n }\n </gbt-empty-state>\n </gbt-card>\n } @else if (view().kind === 'failed') {\n <gbt-alert class=\"gbt-docs-page__failed\" variant=\"error\" appearance=\"subtle\">\n {{ labels().loadFailed }}\n <gbt-button\n alert-actions\n variant=\"secondary\"\n size=\"small\"\n iconName=\"refresh-cw\"\n [text]=\"labels().retry\"\n (clicked)=\"retry()\"\n />\n </gbt-alert>\n } @else {\n <div class=\"gbt-docs-page__loading\" aria-busy=\"true\">\n <span class=\"gbt-docs-page__status\" role=\"status\">{{ labels().loading }}</span>\n <gbt-card variant=\"outlined\" [flush]=\"true\" aria-hidden=\"true\">\n <div class=\"gbt-docs-page__loading-card\">\n @for (width of skeletonRows; track $index) {\n <gbt-skeleton [width]=\"width\" [height]=\"$first ? '1.75rem' : '0.875rem'\" />\n }\n </div>\n </gbt-card>\n </div>\n }\n </div>\n\n @if (showOutline()) {\n <div page-aside class=\"gbt-docs-page__aside\">\n <gbt-markdown-outline [entries]=\"outline()\" />\n </div>\n }\n</gbt-page-layout>\n",
1220
+ styles: [":host{display:block}gbt-page-layout[data-width]{max-width:none}@container gbt-page-layout (max-width: 1100px){:host ::ng-deep .gbt-page-layout__aside{display:none}}.gbt-docs-page{display:flex;flex-direction:column;gap:1rem;min-width:0}.gbt-docs-page__breadcrumb{display:block;min-width:0}.gbt-docs-page__article{container:docs-article/inline-size;min-width:0}gbt-card ::ng-deep .gbt-card{color:inherit;font-size:inherit;line-height:inherit}.gbt-docs-page__body{padding:1.75rem 2.25rem 2rem}.gbt-docs-page__body ::ng-deep .gbt-markdown-view{font-size:1rem;line-height:1.7}.gbt-docs-page__body ::ng-deep h1,.gbt-docs-page__body ::ng-deep h2,.gbt-docs-page__body ::ng-deep h3,.gbt-docs-page__body ::ng-deep h4{scroll-margin-top:1rem}.gbt-docs-page__body ::ng-deep [tabindex=\"-1\"]:focus{outline:none}.gbt-docs-page__body ::ng-deep pre{font-size:.875rem}.gbt-docs-page__body ::ng-deep table{width:max-content;min-width:100%}.gbt-docs-page__body ::ng-deep th{background:var(--bg-panel);font-weight:600}.gbt-docs-page__body ::ng-deep td code,.gbt-docs-page__body ::ng-deep th code{white-space:nowrap}.gbt-docs-page__body ::ng-deep blockquote[data-callout]{padding:.75rem 1rem;border:1px solid transparent;border-left-width:4px;border-radius:var(--site-border-radius-sm);color:var(--text-primary)}.gbt-docs-page__body ::ng-deep blockquote[data-callout]>:last-child{margin-bottom:0}.gbt-docs-page__body ::ng-deep blockquote[data-callout=note]{border-color:color-mix(in srgb,var(--color-info-bg-text) 25%,transparent);border-left-color:var(--color-info-bg-text);background:color-mix(in srgb,var(--color-info-bg) 55%,var(--bg-principal))}.gbt-docs-page__body ::ng-deep blockquote[data-callout=warning]{border-color:color-mix(in srgb,var(--color-warning-bg-text) 25%,transparent);border-left-color:var(--color-warning-bg-text);background:color-mix(in srgb,var(--color-warning-bg) 55%,var(--bg-principal))}@container docs-article (max-width: 559px){.gbt-docs-page__body{padding:1.125rem 1rem 1.25rem}}.gbt-docs-page__pager{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}.gbt-docs-page__neighbour--next{grid-column:2;text-align:right}.gbt-docs-page__neighbour-label{display:block;margin-bottom:.25rem;color:var(--text-secondary);font-size:.75rem}.gbt-docs-page__neighbour-link{color:var(--primary);font-weight:600;overflow-wrap:anywhere}@container gbt-page-layout (max-width: 559px){.gbt-docs-page__pager{grid-template-columns:minmax(0,1fr)}.gbt-docs-page__neighbour--next{grid-column:auto}}.gbt-docs-page__not-found{display:block}.gbt-docs-page__loading-card{display:flex;flex-direction:column;gap:.875rem;padding:1.75rem 2.25rem}.gbt-docs-page__status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n"],
1221
+ dependencies: [
1222
+ {
1223
+ kind: "directive",
1224
+ type: RouterLink,
1225
+ selector: "[routerLink]",
1226
+ inputs: [
1227
+ "target",
1228
+ "queryParams",
1229
+ "fragment",
1230
+ "queryParamsHandling",
1231
+ "state",
1232
+ "info",
1233
+ "relativeTo",
1234
+ "preserveFragment",
1235
+ "skipLocationChange",
1236
+ "replaceUrl",
1237
+ "browserUrl",
1238
+ "routerLink"
1239
+ ]
1240
+ },
1241
+ {
1242
+ kind: "component",
1243
+ type: Alert,
1244
+ selector: "gbt-alert",
1245
+ inputs: [
1246
+ "variant",
1247
+ "dismissible",
1248
+ "closeLabel",
1249
+ "live",
1250
+ "heading",
1251
+ "size",
1252
+ "appearance",
1253
+ "iconAlign"
1254
+ ],
1255
+ outputs: ["dismissed"]
1256
+ },
1257
+ {
1258
+ kind: "component",
1259
+ type: Breadcrumb,
1260
+ selector: "gbt-breadcrumb",
1261
+ inputs: ["ariaLabel"]
1262
+ },
1263
+ {
1264
+ kind: "component",
1265
+ type: Button,
1266
+ selector: "gbt-button, a[gbtButton]",
1267
+ inputs: [
1268
+ "variant",
1269
+ "size",
1270
+ "type",
1271
+ "text",
1272
+ "iconName",
1273
+ "ariaLabel",
1274
+ "loading",
1275
+ "loadingLabel",
1276
+ "disabled",
1277
+ "pressed",
1278
+ "ariaExpanded",
1279
+ "ariaControls",
1280
+ "ariaHaspopup",
1281
+ "block",
1282
+ "iconOnly"
1283
+ ],
1284
+ outputs: ["clicked"]
1285
+ },
1286
+ {
1287
+ kind: "component",
1288
+ type: Card,
1289
+ selector: "gbt-card",
1290
+ inputs: [
1291
+ "hoverable",
1292
+ "heading",
1293
+ "icon",
1294
+ "headingLevel",
1295
+ "variant",
1296
+ "description",
1297
+ "count",
1298
+ "flush",
1299
+ "tone",
1300
+ "selected",
1301
+ "selectedLabel",
1302
+ "href",
1303
+ "linkLabel"
1304
+ ]
1305
+ },
1306
+ {
1307
+ kind: "component",
1308
+ type: CardLink,
1309
+ selector: "a[gbtCardLink]"
1310
+ },
1311
+ {
1312
+ kind: "component",
1313
+ type: EmptyState,
1314
+ selector: "gbt-empty-state",
1315
+ inputs: [
1316
+ "illustration",
1317
+ "heading",
1318
+ "message",
1319
+ "icon",
1320
+ "size",
1321
+ "tone",
1322
+ "headingLevel",
1323
+ "headingId",
1324
+ "headingFocusable"
1325
+ ]
1326
+ },
1327
+ {
1328
+ kind: "component",
1329
+ type: PageLayout,
1330
+ selector: "gbt-page-layout",
1331
+ inputs: [
1332
+ "width",
1333
+ "asideWidth",
1334
+ "asidePosition",
1335
+ "navLabel",
1336
+ "asideLabel",
1337
+ "stickyNav"
1338
+ ]
1339
+ },
1340
+ {
1341
+ kind: "component",
1342
+ type: Skeleton,
1343
+ selector: "gbt-skeleton",
1344
+ inputs: [
1345
+ "variant",
1346
+ "width",
1347
+ "height"
1348
+ ]
1349
+ },
1350
+ {
1351
+ kind: "component",
1352
+ type: MarkdownView,
1353
+ selector: "gbt-markdown-view",
1354
+ inputs: [
1355
+ "content",
1356
+ "headingOffset",
1357
+ "routedLinkPrefix"
1358
+ ],
1359
+ outputs: ["outline"]
1360
+ },
1361
+ {
1362
+ kind: "component",
1363
+ type: MarkdownOutline,
1364
+ selector: "gbt-markdown-outline",
1365
+ inputs: ["entries", "headingLevel"]
1366
+ },
1367
+ {
1368
+ kind: "component",
1369
+ type: DocsNav,
1370
+ selector: "gbt-docs-nav",
1371
+ inputs: [
1372
+ "index",
1373
+ "section",
1374
+ "page"
1375
+ ]
1376
+ }
1377
+ ],
1378
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1379
+ });
1380
+ };
1381
+ i0.ɵɵngDeclareClassMetadata({
1382
+ minVersion: "12.0.0",
1383
+ version: "22.2.0",
1384
+ ngImport: i0,
1385
+ type: DocsPage,
1386
+ decorators: [{
1387
+ type: Component,
1388
+ args: [{
1389
+ selector: "gbt-docs-page",
1390
+ standalone: true,
1391
+ imports: [
1392
+ RouterLink,
1393
+ Alert,
1394
+ Breadcrumb,
1395
+ Button,
1396
+ Card,
1397
+ CardLink,
1398
+ EmptyState,
1399
+ PageLayout,
1400
+ Skeleton,
1401
+ MarkdownView,
1402
+ MarkdownOutline,
1403
+ DocsNav
1404
+ ],
1405
+ changeDetection: ChangeDetectionStrategy.OnPush,
1406
+ template: "<gbt-page-layout\n width=\"wide\"\n asideWidth=\"sm\"\n [navLabel]=\"labels().documentation\"\n [asideLabel]=\"labels().onThisPage\"\n stickyNav\n>\n <!-- One root per projected block: a control-flow block only gets projected into a named slot that way. -->\n @if (index(); as index) {\n <gbt-docs-nav page-nav [index]=\"index\" [section]=\"sectionSlug()\" [page]=\"pageSlug()\" />\n }\n\n <div class=\"gbt-docs-page\">\n @if (page(); as page) {\n <gbt-breadcrumb class=\"gbt-docs-page__breadcrumb\" [ariaLabel]=\"labels().breadcrumb\">\n <li breadcrumb-ancestor>\n <a class=\"gbt-breadcrumb__item\" [routerLink]=\"root\">{{ labels().documentation }}</a>\n </li>\n <li breadcrumb-ancestor>\n <a class=\"gbt-breadcrumb__item\" [routerLink]=\"sectionLink(page.location)\">{{\n page.location.section.title\n }}</a>\n </li>\n {{ page.location.page.title }}\n </gbt-breadcrumb>\n\n <article class=\"gbt-docs-page__article\">\n <gbt-card variant=\"outlined\" [flush]=\"true\">\n <div class=\"gbt-docs-page__body\">\n <gbt-markdown-view\n class=\"gbt-docs-page__content\"\n [content]=\"page.content\"\n [routedLinkPrefix]=\"root\"\n (outline)=\"onRendered($event)\"\n />\n </div>\n </gbt-card>\n </article>\n\n @if (page.location.previous || page.location.next) {\n <nav class=\"gbt-docs-page__pager\" [attr.aria-label]=\"labels().neighbours\">\n @if (page.location.previous; as previous) {\n <gbt-card class=\"gbt-docs-page__neighbour\" variant=\"outlined\" hoverable>\n <span class=\"gbt-docs-page__neighbour-label\"\n >{{ labels().previous }} · {{ previous.sectionTitle }}</span\n >\n <a\n gbtCardLink\n class=\"gbt-docs-page__neighbour-link\"\n [routerLink]=\"previous.commands\"\n >{{ previous.title }}</a\n >\n </gbt-card>\n }\n @if (page.location.next; as next) {\n <gbt-card\n class=\"gbt-docs-page__neighbour gbt-docs-page__neighbour--next\"\n variant=\"outlined\"\n hoverable\n >\n <span class=\"gbt-docs-page__neighbour-label\"\n >{{ labels().next }} · {{ next.sectionTitle }}</span\n >\n <a gbtCardLink class=\"gbt-docs-page__neighbour-link\" [routerLink]=\"next.commands\">{{\n next.title\n }}</a>\n </gbt-card>\n }\n </nav>\n }\n } @else if (notFound(); as notFound) {\n <gbt-card class=\"gbt-docs-page__not-found\" variant=\"outlined\">\n <gbt-empty-state\n illustration=\"book\"\n [headingLevel]=\"1\"\n [heading]=\"labels().notFoundHeading\"\n [message]=\"labels().notFoundMessage\"\n >\n @if (notFound.firstPage; as firstPage) {\n <a gbtButton variant=\"primary\" [routerLink]=\"firstPage\">{{ labels().toStart }}</a>\n }\n </gbt-empty-state>\n </gbt-card>\n } @else if (view().kind === 'failed') {\n <gbt-alert class=\"gbt-docs-page__failed\" variant=\"error\" appearance=\"subtle\">\n {{ labels().loadFailed }}\n <gbt-button\n alert-actions\n variant=\"secondary\"\n size=\"small\"\n iconName=\"refresh-cw\"\n [text]=\"labels().retry\"\n (clicked)=\"retry()\"\n />\n </gbt-alert>\n } @else {\n <div class=\"gbt-docs-page__loading\" aria-busy=\"true\">\n <span class=\"gbt-docs-page__status\" role=\"status\">{{ labels().loading }}</span>\n <gbt-card variant=\"outlined\" [flush]=\"true\" aria-hidden=\"true\">\n <div class=\"gbt-docs-page__loading-card\">\n @for (width of skeletonRows; track $index) {\n <gbt-skeleton [width]=\"width\" [height]=\"$first ? '1.75rem' : '0.875rem'\" />\n }\n </div>\n </gbt-card>\n </div>\n }\n </div>\n\n @if (showOutline()) {\n <div page-aside class=\"gbt-docs-page__aside\">\n <gbt-markdown-outline [entries]=\"outline()\" />\n </div>\n }\n</gbt-page-layout>\n",
1407
+ styles: [":host{display:block}gbt-page-layout[data-width]{max-width:none}@container gbt-page-layout (max-width: 1100px){:host ::ng-deep .gbt-page-layout__aside{display:none}}.gbt-docs-page{display:flex;flex-direction:column;gap:1rem;min-width:0}.gbt-docs-page__breadcrumb{display:block;min-width:0}.gbt-docs-page__article{container:docs-article/inline-size;min-width:0}gbt-card ::ng-deep .gbt-card{color:inherit;font-size:inherit;line-height:inherit}.gbt-docs-page__body{padding:1.75rem 2.25rem 2rem}.gbt-docs-page__body ::ng-deep .gbt-markdown-view{font-size:1rem;line-height:1.7}.gbt-docs-page__body ::ng-deep h1,.gbt-docs-page__body ::ng-deep h2,.gbt-docs-page__body ::ng-deep h3,.gbt-docs-page__body ::ng-deep h4{scroll-margin-top:1rem}.gbt-docs-page__body ::ng-deep [tabindex=\"-1\"]:focus{outline:none}.gbt-docs-page__body ::ng-deep pre{font-size:.875rem}.gbt-docs-page__body ::ng-deep table{width:max-content;min-width:100%}.gbt-docs-page__body ::ng-deep th{background:var(--bg-panel);font-weight:600}.gbt-docs-page__body ::ng-deep td code,.gbt-docs-page__body ::ng-deep th code{white-space:nowrap}.gbt-docs-page__body ::ng-deep blockquote[data-callout]{padding:.75rem 1rem;border:1px solid transparent;border-left-width:4px;border-radius:var(--site-border-radius-sm);color:var(--text-primary)}.gbt-docs-page__body ::ng-deep blockquote[data-callout]>:last-child{margin-bottom:0}.gbt-docs-page__body ::ng-deep blockquote[data-callout=note]{border-color:color-mix(in srgb,var(--color-info-bg-text) 25%,transparent);border-left-color:var(--color-info-bg-text);background:color-mix(in srgb,var(--color-info-bg) 55%,var(--bg-principal))}.gbt-docs-page__body ::ng-deep blockquote[data-callout=warning]{border-color:color-mix(in srgb,var(--color-warning-bg-text) 25%,transparent);border-left-color:var(--color-warning-bg-text);background:color-mix(in srgb,var(--color-warning-bg) 55%,var(--bg-principal))}@container docs-article (max-width: 559px){.gbt-docs-page__body{padding:1.125rem 1rem 1.25rem}}.gbt-docs-page__pager{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem}.gbt-docs-page__neighbour--next{grid-column:2;text-align:right}.gbt-docs-page__neighbour-label{display:block;margin-bottom:.25rem;color:var(--text-secondary);font-size:.75rem}.gbt-docs-page__neighbour-link{color:var(--primary);font-weight:600;overflow-wrap:anywhere}@container gbt-page-layout (max-width: 559px){.gbt-docs-page__pager{grid-template-columns:minmax(0,1fr)}.gbt-docs-page__neighbour--next{grid-column:auto}}.gbt-docs-page__not-found{display:block}.gbt-docs-page__loading-card{display:flex;flex-direction:column;gap:.875rem;padding:1.75rem 2.25rem}.gbt-docs-page__status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n"]
1408
+ }]
1409
+ }],
1410
+ ctorParameters: () => []
1411
+ });
1412
+ export { DEFAULT_DOCS_CONFIG, DEFAULT_DOCS_LABELS, DOCS_CONFIG, DOCS_LABELS, DOCS_SEARCH_LIMIT, DOCS_TITLE, DocsNav, DocsPage, DocsSearch, DocsSearchService, DocsService, MarkdownOutline, MarkdownView, decodeFragment, docsHomeGuard, docsLabels, docsPageCommands, docsReadingOrder, docsRoutes, findAnchorTarget, firstDocsPage, hasOutline, headingSlug, isNotFound, locateDocsPage, makeScrollableBlocksFocusable, nameTaskCheckboxes, parseDocsPage, provideDocs, provideDocsLabels, searchTokens };
1413
+
1414
+ //# sourceMappingURL=masmarino-gabarit-docs.mjs.map