@ng-doc/app 22.0.0-beta.2 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -29
- package/fesm2022/ng-doc-app-classes-content-anchor-controller.mjs +363 -0
- package/fesm2022/ng-doc-app-classes-content-anchor-controller.mjs.map +1 -0
- package/fesm2022/ng-doc-app-classes-content-controller.mjs +299 -0
- package/fesm2022/ng-doc-app-classes-content-controller.mjs.map +1 -0
- package/fesm2022/ng-doc-app-classes-default-search-engine.mjs +51 -35
- package/fesm2022/ng-doc-app-classes-default-search-engine.mjs.map +1 -1
- package/fesm2022/ng-doc-app-classes-root-page.mjs.map +1 -1
- package/fesm2022/ng-doc-app-classes-search-engine.mjs.map +1 -1
- package/fesm2022/ng-doc-app-classes.mjs +2 -0
- package/fesm2022/ng-doc-app-classes.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-api-list.mjs +173 -69
- package/fesm2022/ng-doc-app-components-api-list.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-breadcrumb.mjs +13 -10
- package/fesm2022/ng-doc-app-components-breadcrumb.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-code.mjs +152 -25
- package/fesm2022/ng-doc-app-components-code.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-command-palette.mjs +498 -0
- package/fesm2022/ng-doc-app-components-command-palette.mjs.map +1 -0
- package/fesm2022/ng-doc-app-components-copy-button.mjs +38 -21
- package/fesm2022/ng-doc-app-components-copy-button.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-demo-displayer.mjs +36 -29
- package/fesm2022/ng-doc-app-components-demo-displayer.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-demo-pane.mjs +39 -36
- package/fesm2022/ng-doc-app-components-demo-pane.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-demo.mjs +129 -44
- package/fesm2022/ng-doc-app-components-demo.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-fullscreen-button.mjs +12 -9
- package/fesm2022/ng-doc-app-components-fullscreen-button.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-fullscreen-toggle.mjs +79 -0
- package/fesm2022/ng-doc-app-components-fullscreen-toggle.mjs.map +1 -0
- package/fesm2022/ng-doc-app-components-heading-anchor.mjs +54 -21
- package/fesm2022/ng-doc-app-components-heading-anchor.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-image-viewer.mjs +183 -89
- package/fesm2022/ng-doc-app-components-image-viewer.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-kind-icon.mjs +42 -25
- package/fesm2022/ng-doc-app-components-kind-icon.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-link.mjs +12 -9
- package/fesm2022/ng-doc-app-components-link.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-members.mjs +30 -0
- package/fesm2022/ng-doc-app-components-members.mjs.map +1 -0
- package/fesm2022/ng-doc-app-components-mermaid-viewer.mjs +61 -20
- package/fesm2022/ng-doc-app-components-mermaid-viewer.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-navbar.mjs +39 -49
- package/fesm2022/ng-doc-app-components-navbar.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-page-header.mjs +73 -10
- package/fesm2022/ng-doc-app-components-page-header.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-page-link.mjs +123 -31
- package/fesm2022/ng-doc-app-components-page-link.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-page-navigation.mjs +17 -19
- package/fesm2022/ng-doc-app-components-page-navigation.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-page-wrapper.mjs +56 -35
- package/fesm2022/ng-doc-app-components-page-wrapper.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-page.mjs +168 -24
- package/fesm2022/ng-doc-app-components-page.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-playground.mjs +392 -263
- package/fesm2022/ng-doc-app-components-playground.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-root.mjs +48 -31
- package/fesm2022/ng-doc-app-components-root.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-search-result.mjs +22 -21
- package/fesm2022/ng-doc-app-components-search-result.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-search.mjs +64 -33
- package/fesm2022/ng-doc-app-components-search.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-sidebar.mjs +86 -61
- package/fesm2022/ng-doc-app-components-sidebar.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-tabs.mjs +18 -12
- package/fesm2022/ng-doc-app-components-tabs.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-theme-toggle.mjs +33 -21
- package/fesm2022/ng-doc-app-components-theme-toggle.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components-toc.mjs +267 -90
- package/fesm2022/ng-doc-app-components-toc.mjs.map +1 -1
- package/fesm2022/ng-doc-app-components.mjs +3 -1
- package/fesm2022/ng-doc-app-components.mjs.map +1 -1
- package/fesm2022/ng-doc-app-defaults-default-processors.mjs +2 -1
- package/fesm2022/ng-doc-app-defaults-default-processors.mjs.map +1 -1
- package/fesm2022/ng-doc-app-directives-code-highlighter.mjs +11 -5
- package/fesm2022/ng-doc-app-directives-code-highlighter.mjs.map +1 -1
- package/fesm2022/ng-doc-app-directives-members-filter.mjs +276 -0
- package/fesm2022/ng-doc-app-directives-members-filter.mjs.map +1 -0
- package/fesm2022/ng-doc-app-directives-route-active.mjs +34 -30
- package/fesm2022/ng-doc-app-directives-route-active.mjs.map +1 -1
- package/fesm2022/ng-doc-app-directives.mjs +1 -0
- package/fesm2022/ng-doc-app-directives.mjs.map +1 -1
- package/fesm2022/ng-doc-app-helpers.mjs +285 -1
- package/fesm2022/ng-doc-app-helpers.mjs.map +1 -1
- package/fesm2022/ng-doc-app-pipes-decode-uri-component.mjs +6 -4
- package/fesm2022/ng-doc-app-pipes-decode-uri-component.mjs.map +1 -1
- package/fesm2022/ng-doc-app-pipes-extract-value.mjs +6 -4
- package/fesm2022/ng-doc-app-pipes-extract-value.mjs.map +1 -1
- package/fesm2022/ng-doc-app-pipes-filter-by-text.mjs +7 -4
- package/fesm2022/ng-doc-app-pipes-filter-by-text.mjs.map +1 -1
- package/fesm2022/ng-doc-app-pipes-sanitize-html.mjs +8 -5
- package/fesm2022/ng-doc-app-pipes-sanitize-html.mjs.map +1 -1
- package/fesm2022/ng-doc-app-processors-page-processor.mjs +86 -23
- package/fesm2022/ng-doc-app-processors-page-processor.mjs.map +1 -1
- package/fesm2022/ng-doc-app-processors-processors-tooltip.mjs +26 -25
- package/fesm2022/ng-doc-app-processors-processors-tooltip.mjs.map +1 -1
- package/fesm2022/ng-doc-app-processors-processors.mjs +12 -1
- package/fesm2022/ng-doc-app-processors-processors.mjs.map +1 -1
- package/fesm2022/ng-doc-app-providers-ng-doc-app.mjs +31 -2
- package/fesm2022/ng-doc-app-providers-ng-doc-app.mjs.map +1 -1
- package/fesm2022/ng-doc-app-services-content-scroll-intent.mjs +122 -0
- package/fesm2022/ng-doc-app-services-content-scroll-intent.mjs.map +1 -0
- package/fesm2022/ng-doc-app-services-content-state.mjs +57 -0
- package/fesm2022/ng-doc-app-services-content-state.mjs.map +1 -0
- package/fesm2022/ng-doc-app-services-fullscreen-route.mjs +74 -0
- package/fesm2022/ng-doc-app-services-fullscreen-route.mjs.map +1 -0
- package/fesm2022/ng-doc-app-services-highlighter.mjs +83 -14
- package/fesm2022/ng-doc-app-services-highlighter.mjs.map +1 -1
- package/fesm2022/ng-doc-app-services-route-preloader.mjs +360 -0
- package/fesm2022/ng-doc-app-services-route-preloader.mjs.map +1 -0
- package/fesm2022/ng-doc-app-services-shortcuts.mjs +214 -0
- package/fesm2022/ng-doc-app-services-shortcuts.mjs.map +1 -0
- package/fesm2022/ng-doc-app-services-sidebar.mjs +59 -25
- package/fesm2022/ng-doc-app-services-sidebar.mjs.map +1 -1
- package/fesm2022/ng-doc-app-services-store.mjs +8 -8
- package/fesm2022/ng-doc-app-services-store.mjs.map +1 -1
- package/fesm2022/ng-doc-app-services-theme.mjs +32 -12
- package/fesm2022/ng-doc-app-services-theme.mjs.map +1 -1
- package/fesm2022/ng-doc-app-services.mjs +143 -0
- package/fesm2022/ng-doc-app-services.mjs.map +1 -1
- package/fesm2022/ng-doc-app-tokens.mjs +7 -28
- package/fesm2022/ng-doc-app-tokens.mjs.map +1 -1
- package/fesm2022/ng-doc-app-type-controls-boolean-control.mjs +18 -9
- package/fesm2022/ng-doc-app-type-controls-boolean-control.mjs.map +1 -1
- package/fesm2022/ng-doc-app-type-controls-number-control.mjs +12 -9
- package/fesm2022/ng-doc-app-type-controls-number-control.mjs.map +1 -1
- package/fesm2022/ng-doc-app-type-controls-string-control.mjs +12 -9
- package/fesm2022/ng-doc-app-type-controls-string-control.mjs.map +1 -1
- package/fesm2022/ng-doc-app-type-controls-type-alias-control.mjs +22 -16
- package/fesm2022/ng-doc-app-type-controls-type-alias-control.mjs.map +1 -1
- package/package.json +69 -28
- package/styles/global.css +1125 -201
- package/styles/main.css +1125 -201
- package/styles/themes/dark.css +78 -56
- package/types/ng-doc-app-classes-content-anchor-controller.d.ts +54 -0
- package/types/ng-doc-app-classes-content-controller.d.ts +94 -0
- package/types/ng-doc-app-classes-default-search-engine.d.ts +9 -1
- package/types/ng-doc-app-classes-root-page.d.ts +6 -1
- package/types/ng-doc-app-classes-search-engine.d.ts +5 -0
- package/types/ng-doc-app-classes.d.ts +2 -0
- package/types/ng-doc-app-components-api-list.d.ts +69 -20
- package/types/ng-doc-app-components-breadcrumb.d.ts +8 -3
- package/types/ng-doc-app-components-code.d.ts +46 -12
- package/types/ng-doc-app-components-command-palette.d.ts +147 -0
- package/types/ng-doc-app-components-copy-button.d.ts +18 -6
- package/types/ng-doc-app-components-demo-displayer.d.ts +23 -10
- package/types/ng-doc-app-components-demo-pane.d.ts +19 -15
- package/types/ng-doc-app-components-demo.d.ts +62 -15
- package/types/ng-doc-app-components-fullscreen-button.d.ts +4 -2
- package/types/ng-doc-app-components-fullscreen-toggle.d.ts +24 -0
- package/types/ng-doc-app-components-heading-anchor.d.ts +26 -7
- package/types/ng-doc-app-components-image-viewer.d.ts +71 -7
- package/types/ng-doc-app-components-kind-icon.d.ts +28 -7
- package/types/ng-doc-app-components-link.d.ts +6 -2
- package/types/ng-doc-app-components-members.d.ts +13 -0
- package/types/ng-doc-app-components-mermaid-viewer.d.ts +21 -6
- package/types/ng-doc-app-components-navbar.d.ts +25 -15
- package/types/ng-doc-app-components-page-header.d.ts +28 -4
- package/types/ng-doc-app-components-page-link.d.ts +34 -15
- package/types/ng-doc-app-components-page-navigation.d.ts +10 -5
- package/types/ng-doc-app-components-page-wrapper.d.ts +35 -11
- package/types/ng-doc-app-components-page.d.ts +57 -6
- package/types/ng-doc-app-components-playground.d.ts +146 -78
- package/types/ng-doc-app-components-root.d.ts +28 -7
- package/types/ng-doc-app-components-search-result.d.ts +14 -6
- package/types/ng-doc-app-components-search.d.ts +19 -7
- package/types/ng-doc-app-components-tabs.d.ts +13 -4
- package/types/ng-doc-app-components-theme-toggle.d.ts +18 -5
- package/types/ng-doc-app-components-toc.d.ts +76 -29
- package/types/ng-doc-app-components.d.ts +3 -1
- package/types/ng-doc-app-directives-code-highlighter.d.ts +8 -4
- package/types/ng-doc-app-directives-members-filter.d.ts +61 -0
- package/types/ng-doc-app-directives-route-active.d.ts +21 -7
- package/types/ng-doc-app-directives.d.ts +1 -0
- package/types/ng-doc-app-helpers.d.ts +124 -3
- package/types/ng-doc-app-interfaces.d.ts +48 -28
- package/types/ng-doc-app-pipes-decode-uri-component.d.ts +3 -0
- package/types/ng-doc-app-pipes-extract-value.d.ts +3 -0
- package/types/ng-doc-app-pipes-filter-by-text.d.ts +4 -0
- package/types/ng-doc-app-pipes-sanitize-html.d.ts +4 -2
- package/types/ng-doc-app-processors-page-processor.d.ts +39 -10
- package/types/ng-doc-app-processors-processors-tooltip.d.ts +11 -10
- package/types/ng-doc-app-processors-processors.d.ts +5 -1
- package/types/ng-doc-app-providers-ng-doc-app.d.ts +17 -0
- package/types/ng-doc-app-services-content-scroll-intent.d.ts +52 -0
- package/types/ng-doc-app-services-content-state.d.ts +40 -0
- package/types/ng-doc-app-services-fullscreen-route.d.ts +35 -0
- package/types/ng-doc-app-services-highlighter.d.ts +40 -5
- package/types/ng-doc-app-services-route-preloader.d.ts +109 -0
- package/types/ng-doc-app-services-shortcuts.d.ts +96 -0
- package/types/ng-doc-app-services-sidebar.d.ts +24 -4
- package/types/ng-doc-app-services-store.d.ts +24 -1
- package/types/ng-doc-app-services-theme.d.ts +19 -3
- package/types/ng-doc-app-services.d.ts +77 -0
- package/types/ng-doc-app-tokens.d.ts +10 -30
- package/types/ng-doc-app-type-controls-boolean-control.d.ts +11 -6
- package/types/ng-doc-app-type-controls-number-control.d.ts +5 -3
- package/types/ng-doc-app-type-controls-string-control.d.ts +5 -3
- package/types/ng-doc-app-type-controls-type-alias-control.d.ts +13 -6
- package/fesm2022/ng-doc-app-components-search-dialog.mjs +0 -78
- package/fesm2022/ng-doc-app-components-search-dialog.mjs.map +0 -1
- package/types/ng-doc-app-components-search-dialog.d.ts +0 -28
|
@@ -1,41 +1,74 @@
|
|
|
1
|
+
import { LocationStrategy } from '@angular/common';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject,
|
|
3
|
+
import { input, inject, ElementRef, Renderer2, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
4
|
import { NgDocCopyButtonComponent } from '@ng-doc/app/components/copy-button';
|
|
5
|
+
import { ɵngDocPageUrl as _ngDocPageUrl } from '@ng-doc/app/helpers';
|
|
4
6
|
import { NgDocIconComponent } from '@ng-doc/ui-kit';
|
|
5
7
|
import { WA_LOCATION } from '@ng-web-apis/common';
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Button next to a heading that copies the link to the heading.
|
|
11
|
+
*/
|
|
7
12
|
class NgDocHeadingAnchorComponent {
|
|
8
13
|
constructor() {
|
|
9
|
-
|
|
14
|
+
/** Id of the heading. */
|
|
15
|
+
this.anchor = input.required(/* @ts-ignore */
|
|
16
|
+
...(ngDevMode ? [{ debugName: "anchor" }] : /* istanbul ignore next */ []));
|
|
17
|
+
/** Classes of the host element. */
|
|
18
|
+
this.classes = input([], /* @ts-ignore */
|
|
19
|
+
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
10
20
|
this.location = inject(WA_LOCATION);
|
|
21
|
+
this.locationStrategy = inject(LocationStrategy);
|
|
22
|
+
this.host = inject(ElementRef).nativeElement;
|
|
23
|
+
this.renderer = inject(Renderer2);
|
|
24
|
+
// Read when the button is pressed: the location is not a signal, and the link must use the
|
|
25
|
+
// route the reader is on, in the form the location strategy shows it.
|
|
26
|
+
this.href = () => _ngDocPageUrl(this.locationStrategy, this.location, this.anchor());
|
|
11
27
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Names the heading after its own text: the anchor sits inside the heading, so the button's
|
|
30
|
+
* label would otherwise end the heading's accessible name ("Installation Copy link to
|
|
31
|
+
* section"). The heading's other content moves into a span that the heading is labelled by, so
|
|
32
|
+
* the name follows that content and leaves out whatever it hides from assistive technology.
|
|
33
|
+
* The processors insert the anchor before its first change detection, on the server as in the
|
|
34
|
+
* browser, so the heading is its parent here.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
ngOnInit() {
|
|
38
|
+
const heading = this.host.parentElement;
|
|
39
|
+
if (!heading ||
|
|
40
|
+
!/^H[1-6]$/.test(heading.tagName) ||
|
|
41
|
+
heading.hasAttribute('aria-label') ||
|
|
42
|
+
heading.hasAttribute('aria-labelledby'))
|
|
43
|
+
return;
|
|
44
|
+
const id = `ng-doc-heading-label-${heading.id || this.anchor()}`;
|
|
45
|
+
const label = this.renderer.createElement('span');
|
|
46
|
+
this.renderer.setAttribute(label, 'id', id);
|
|
47
|
+
this.renderer.setAttribute(label, 'class', 'ng-doc-heading-label');
|
|
48
|
+
for (const node of Array.from(heading.childNodes)) {
|
|
49
|
+
if (node !== this.host)
|
|
50
|
+
this.renderer.appendChild(label, node);
|
|
51
|
+
}
|
|
52
|
+
this.renderer.insertBefore(heading, label, this.host);
|
|
53
|
+
this.renderer.setAttribute(heading, 'aria-labelledby', id);
|
|
15
54
|
}
|
|
16
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
17
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
18
|
-
<ng-doc-copy-button [text]="href">
|
|
55
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocHeadingAnchorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
56
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.1", type: NgDocHeadingAnchorComponent, isStandalone: true, selector: "ng-doc-heading-anchor", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: true, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: `
|
|
57
|
+
<ng-doc-copy-button [text]="href" label="Copy link to section">
|
|
19
58
|
<ng-doc-icon icon="link-2"></ng-doc-icon>
|
|
20
59
|
</ng-doc-copy-button>
|
|
21
|
-
`, isInline: true, styles: [""], dependencies: [{ kind: "component", type: NgDocIconComponent, selector: "ng-doc-icon", inputs: ["icon", "customIcon", "size"] }, { kind: "component", type: NgDocCopyButtonComponent, selector: "ng-doc-copy-button", inputs: ["text"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
60
|
+
`, isInline: true, styles: [""], dependencies: [{ kind: "component", type: NgDocIconComponent, selector: "ng-doc-icon", inputs: ["icon", "customIcon", "size"] }, { kind: "component", type: NgDocCopyButtonComponent, selector: "ng-doc-copy-button", inputs: ["text", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
22
61
|
}
|
|
23
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
62
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocHeadingAnchorComponent, decorators: [{
|
|
24
63
|
type: Component,
|
|
25
64
|
args: [{ selector: 'ng-doc-heading-anchor', imports: [NgDocIconComponent, NgDocCopyButtonComponent], template: `
|
|
26
|
-
<ng-doc-copy-button [text]="href">
|
|
65
|
+
<ng-doc-copy-button [text]="href" label="Copy link to section">
|
|
27
66
|
<ng-doc-icon icon="link-2"></ng-doc-icon>
|
|
28
67
|
</ng-doc-copy-button>
|
|
29
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}], classes: [{
|
|
34
|
-
type: Input
|
|
35
|
-
}, {
|
|
36
|
-
type: HostBinding,
|
|
37
|
-
args: ['class']
|
|
38
|
-
}] } });
|
|
68
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
69
|
+
'[class]': 'classes()',
|
|
70
|
+
} }]
|
|
71
|
+
}], propDecorators: { anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: true }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
39
72
|
|
|
40
73
|
/**
|
|
41
74
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-doc-app-components-heading-anchor.mjs","sources":["../../../../libs/app/components/heading-anchor/heading-anchor.component.ts","../../../../libs/app/components/heading-anchor/ng-doc-app-components-heading-anchor.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"ng-doc-app-components-heading-anchor.mjs","sources":["../../../../libs/app/components/heading-anchor/heading-anchor.component.ts","../../../../libs/app/components/heading-anchor/ng-doc-app-components-heading-anchor.ts"],"sourcesContent":["import { LocationStrategy } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n inject,\n input,\n OnInit,\n Renderer2,\n} from '@angular/core';\nimport { NgDocCopyButtonComponent } from '@ng-doc/app/components/copy-button';\nimport { ɵngDocPageUrl } from '@ng-doc/app/helpers';\nimport { NgDocIconComponent } from '@ng-doc/ui-kit';\nimport { WA_LOCATION } from '@ng-web-apis/common';\n\n/**\n * Button next to a heading that copies the link to the heading.\n */\n@Component({\n selector: 'ng-doc-heading-anchor',\n imports: [NgDocIconComponent, NgDocCopyButtonComponent],\n template: `\n <ng-doc-copy-button [text]=\"href\" label=\"Copy link to section\">\n <ng-doc-icon icon=\"link-2\"></ng-doc-icon>\n </ng-doc-copy-button>\n `,\n styles: ``,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'classes()',\n },\n})\nexport class NgDocHeadingAnchorComponent implements OnInit {\n /** Id of the heading. */\n readonly anchor = input.required<string>();\n\n /** Classes of the host element. */\n readonly classes = input<string[]>([]);\n\n protected readonly location = inject(WA_LOCATION);\n\n private readonly locationStrategy = inject(LocationStrategy);\n private readonly host: HTMLElement = inject(ElementRef).nativeElement;\n private readonly renderer = inject(Renderer2);\n\n // Read when the button is pressed: the location is not a signal, and the link must use the\n // route the reader is on, in the form the location strategy shows it.\n protected readonly href = (): string =>\n ɵngDocPageUrl(this.locationStrategy, this.location, this.anchor());\n\n /**\n * Names the heading after its own text: the anchor sits inside the heading, so the button's\n * label would otherwise end the heading's accessible name (\"Installation Copy link to\n * section\"). The heading's other content moves into a span that the heading is labelled by, so\n * the name follows that content and leaves out whatever it hides from assistive technology.\n * The processors insert the anchor before its first change detection, on the server as in the\n * browser, so the heading is its parent here.\n * @internal\n */\n ngOnInit(): void {\n const heading = this.host.parentElement;\n\n if (\n !heading ||\n !/^H[1-6]$/.test(heading.tagName) ||\n heading.hasAttribute('aria-label') ||\n heading.hasAttribute('aria-labelledby')\n )\n return;\n\n const id = `ng-doc-heading-label-${heading.id || this.anchor()}`;\n const label: HTMLElement = this.renderer.createElement('span');\n\n this.renderer.setAttribute(label, 'id', id);\n this.renderer.setAttribute(label, 'class', 'ng-doc-heading-label');\n for (const node of Array.from(heading.childNodes)) {\n if (node !== this.host) this.renderer.appendChild(label, node);\n }\n this.renderer.insertBefore(heading, label, this.host);\n this.renderer.setAttribute(heading, 'aria-labelledby', id);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["ɵngDocPageUrl"],"mappings":"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"}
|
|
@@ -1,27 +1,89 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, viewChild, TemplateRef, inject, ElementRef,
|
|
2
|
+
import { input, viewChild, TemplateRef, inject, ElementRef, DOCUMENT, signal, DestroyRef, untracked, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import { NgDocOverlayService, NgDocOverlayContainerComponent } from '@ng-doc/ui-kit';
|
|
4
4
|
|
|
5
|
+
/** Easing of the zoom: fast at first, settling into the final size. */
|
|
6
|
+
const ZOOM_EASING = 'cubic-bezier(0.2, 0, 0, 1)';
|
|
7
|
+
/**
|
|
8
|
+
* Wraps an image of the page: clicking it, or pressing Enter or Space on it, opens the image at
|
|
9
|
+
* its natural size, scaled down to fit the window.
|
|
10
|
+
*
|
|
11
|
+
* An image inside a link keeps the link's behaviour, and an image with an empty `alt` is
|
|
12
|
+
* decorative: neither becomes a button.
|
|
13
|
+
*/
|
|
5
14
|
class NgDocImageViewerComponent {
|
|
6
15
|
constructor() {
|
|
16
|
+
/** Source of the image. */
|
|
7
17
|
this.src = input.required(/* @ts-ignore */
|
|
8
18
|
...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
19
|
+
/** Alternative text of the image. */
|
|
9
20
|
this.alt = input.required(/* @ts-ignore */
|
|
10
21
|
...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
|
|
11
|
-
this.image = viewChild('image', { ...(ngDevMode ? { debugName: "image" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
22
|
+
this.image = viewChild.required('image', { ...(ngDevMode ? { debugName: "image" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
12
23
|
this.overlay = inject(NgDocOverlayService);
|
|
13
24
|
this.element = inject((ElementRef)).nativeElement;
|
|
14
|
-
this.
|
|
25
|
+
this.window = inject(DOCUMENT).defaultView;
|
|
26
|
+
/** Whether the scaled image is open. */
|
|
27
|
+
this.opened = signal(false, /* @ts-ignore */
|
|
28
|
+
...(ngDevMode ? [{ debugName: "opened" }] : /* istanbul ignore next */ []));
|
|
29
|
+
/** The size of the opened image. */
|
|
30
|
+
this.size = signal({ width: 0, height: 0 }, /* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
32
|
+
this.attempt = 0;
|
|
33
|
+
this.destroyed = false;
|
|
34
|
+
inject(DestroyRef).onDestroy(() => {
|
|
35
|
+
this.destroyed = true;
|
|
36
|
+
this.overlayRef?.close();
|
|
37
|
+
});
|
|
15
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Opens the image at its natural size, scaled down to fit the window, unless the image is not
|
|
41
|
+
* interactive. The image grows from its place on the page.
|
|
42
|
+
*/
|
|
16
43
|
clickEvent() {
|
|
44
|
+
untracked(() => {
|
|
45
|
+
if (this.isInteractive()) {
|
|
46
|
+
void this.open();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Whether the image opens: it has a text alternative and is not inside a link. The page
|
|
52
|
+
* processor moves the host into place before change detection, so the check reads the DOM
|
|
53
|
+
* where the image ends up.
|
|
54
|
+
*/
|
|
55
|
+
isInteractive() {
|
|
56
|
+
return !!this.alt().trim() && !this.element.parentElement?.closest('a');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Opens the image on Space without scrolling the page.
|
|
60
|
+
* @param event - The key press.
|
|
61
|
+
*/
|
|
62
|
+
onSpace(event) {
|
|
63
|
+
if (this.isInteractive()) {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
this.clickEvent();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async open() {
|
|
17
69
|
this.overlayRef?.close();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
70
|
+
const attempt = ++this.attempt;
|
|
71
|
+
const thumbnail = this.element.querySelector('img');
|
|
72
|
+
await this.decode(thumbnail);
|
|
73
|
+
// The reader may have opened the image again, pressed Escape or left the page while it
|
|
74
|
+
// decoded.
|
|
75
|
+
if (attempt !== this.attempt || this.destroyed) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// The size is known before anything moves, so the image grows straight to it.
|
|
79
|
+
const source = this.sourceSize(thumbnail);
|
|
80
|
+
const size = this.fit(source);
|
|
81
|
+
const zoomedFrame = { transformOrigin: '0 0', transform: 'none' };
|
|
82
|
+
// The close animation reads its keyframes when it runs; a refit updates them in place.
|
|
83
|
+
const closeFrames = [zoomedFrame, this.thumbnailFrame(thumbnail, size)];
|
|
84
|
+
const animate = !this.window?.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
|
|
85
|
+
this.size.set(size);
|
|
86
|
+
const overlayRef = this.overlay.open(this.image(), {
|
|
25
87
|
overlayContainer: NgDocOverlayContainerComponent,
|
|
26
88
|
positionStrategy: this.overlay
|
|
27
89
|
.globalPositionStrategy()
|
|
@@ -30,92 +92,124 @@ class NgDocImageViewerComponent {
|
|
|
30
92
|
scrollStrategy: this.overlay.scrollStrategy().block(),
|
|
31
93
|
hasBackdrop: true,
|
|
32
94
|
backdropClass: 'ng-doc-blur-backdrop',
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
transform: 'translate(0%, 0)',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
position: 'fixed',
|
|
45
|
-
width: `${newWidth}px`,
|
|
46
|
-
height: `${newHeight}px`,
|
|
47
|
-
top: '50%',
|
|
48
|
-
left: '50%',
|
|
49
|
-
transform: 'translate(-50%, -50%)',
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
{
|
|
53
|
-
duration: 300,
|
|
54
|
-
easing: 'cubic-bezier(0.25, 0.8, 0.25, 1)',
|
|
55
|
-
},
|
|
56
|
-
//
|
|
57
|
-
// group([
|
|
58
|
-
// animate(
|
|
59
|
-
// '300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
|
60
|
-
// style({
|
|
61
|
-
// width: `${newWidth}px`,
|
|
62
|
-
// height: `${newHeight}px`,
|
|
63
|
-
// top: '50%',
|
|
64
|
-
// left: '50%',
|
|
65
|
-
// transform: 'translate(-50%, -50%)',
|
|
66
|
-
// }),
|
|
67
|
-
// ),
|
|
68
|
-
// query('.ng-doc-image-container', [
|
|
69
|
-
// style({ padding: 0 }),
|
|
70
|
-
// animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ padding: '16px' })),
|
|
71
|
-
// ]),
|
|
72
|
-
// ]),
|
|
73
|
-
],
|
|
74
|
-
// closeAnimation: [
|
|
75
|
-
// style({
|
|
76
|
-
// position: 'fixed',
|
|
77
|
-
// width: `${newWidth}px`,
|
|
78
|
-
// height: `${newHeight}px`,
|
|
79
|
-
// top: '50%',
|
|
80
|
-
// left: '50%',
|
|
81
|
-
// transform: 'translate(-50%, -50%)',
|
|
82
|
-
// }),
|
|
83
|
-
// group([
|
|
84
|
-
// animate(
|
|
85
|
-
// '300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
|
86
|
-
// style({ width, height, top, left, transform: 'translate(0%, 0)' }),
|
|
87
|
-
// ),
|
|
88
|
-
// query(
|
|
89
|
-
// '.ng-doc-image-container',
|
|
90
|
-
// animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ padding: 0 })),
|
|
91
|
-
// ),
|
|
92
|
-
// ]),
|
|
93
|
-
// ],
|
|
95
|
+
width: `${size.width}px`,
|
|
96
|
+
height: `${size.height}px`,
|
|
97
|
+
openAnimation: animate
|
|
98
|
+
? [[closeFrames[1], zoomedFrame], { duration: 300, easing: ZOOM_EASING }]
|
|
99
|
+
: undefined,
|
|
100
|
+
closeAnimation: animate
|
|
101
|
+
? [closeFrames, { duration: 200, easing: ZOOM_EASING, fill: 'forwards' }]
|
|
102
|
+
: undefined,
|
|
94
103
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
const listeners = new AbortController();
|
|
105
|
+
// A resized or rotated window fits the image again.
|
|
106
|
+
const refit = () => {
|
|
107
|
+
const fitted = this.fit(source);
|
|
108
|
+
this.size.set(fitted);
|
|
109
|
+
overlayRef.overlayRef.updateSize({
|
|
110
|
+
width: `${fitted.width}px`,
|
|
111
|
+
height: `${fitted.height}px`,
|
|
112
|
+
});
|
|
113
|
+
closeFrames[1] = this.thumbnailFrame(thumbnail, fitted);
|
|
114
|
+
};
|
|
115
|
+
this.window?.addEventListener('resize', refit, { signal: listeners.signal });
|
|
116
|
+
this.window?.addEventListener('orientationchange', refit, { signal: listeners.signal });
|
|
117
|
+
this.overlayRef = overlayRef;
|
|
118
|
+
this.opened.set(true);
|
|
119
|
+
overlayRef.afterClose().subscribe(() => {
|
|
120
|
+
listeners.abort();
|
|
121
|
+
if (this.overlayRef === overlayRef) {
|
|
122
|
+
this.overlayRef = undefined;
|
|
123
|
+
this.opened.set(false);
|
|
124
|
+
this.element.focus();
|
|
125
|
+
}
|
|
98
126
|
});
|
|
99
127
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Waits until the image is decoded, so its natural size is known. Escape cancels the open
|
|
130
|
+
* meanwhile, as it closes the opened image. A failed decode (a broken or not yet available
|
|
131
|
+
* image) leaves the sizes that are known.
|
|
132
|
+
* @param thumbnail - The image on the page.
|
|
133
|
+
*/
|
|
134
|
+
async decode(thumbnail) {
|
|
135
|
+
const listeners = new AbortController();
|
|
136
|
+
this.window?.document.addEventListener('keydown', (event) => {
|
|
137
|
+
if (event.key === 'Escape') {
|
|
138
|
+
this.attempt++;
|
|
139
|
+
}
|
|
140
|
+
}, { capture: true, signal: listeners.signal });
|
|
141
|
+
try {
|
|
142
|
+
await thumbnail?.decode?.().catch(() => undefined);
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
listeners.abort();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The size to scale: the natural size of the image, or the size of the thumbnail for an image
|
|
150
|
+
* without one (an SVG without dimensions), which may then grow to fill the window.
|
|
151
|
+
* @param thumbnail - The image on the page.
|
|
152
|
+
*/
|
|
153
|
+
sourceSize(thumbnail) {
|
|
154
|
+
const naturalWidth = thumbnail?.naturalWidth ?? 0;
|
|
155
|
+
const naturalHeight = thumbnail?.naturalHeight ?? 0;
|
|
156
|
+
if (naturalWidth > 0 && naturalHeight > 0) {
|
|
157
|
+
return { width: naturalWidth, height: naturalHeight, natural: true };
|
|
158
|
+
}
|
|
159
|
+
const rect = (thumbnail ?? this.element).getBoundingClientRect();
|
|
160
|
+
return { width: rect.width, height: rect.height, natural: false };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The size the image opens at: its natural size, scaled down to fit the viewport with a margin
|
|
164
|
+
* and never scaled up. An image without a natural size fills the available space with the
|
|
165
|
+
* proportions of its thumbnail.
|
|
166
|
+
* @param source - The size to scale.
|
|
167
|
+
*/
|
|
168
|
+
fit(source) {
|
|
169
|
+
const viewport = this.window?.document.documentElement;
|
|
170
|
+
const viewportWidth = viewport?.clientWidth || this.window?.innerWidth || 0;
|
|
171
|
+
const viewportHeight = viewport?.clientHeight || this.window?.innerHeight || 0;
|
|
172
|
+
const margin = viewportWidth <= 640 ? 16 : 48;
|
|
173
|
+
const maxWidth = Math.max(viewportWidth - margin * 2, 1);
|
|
174
|
+
const maxHeight = Math.max(viewportHeight - margin * 2, 1);
|
|
175
|
+
const width = source.width || maxWidth;
|
|
176
|
+
const height = source.height || maxHeight;
|
|
177
|
+
const scale = Math.min(source.natural ? 1 : Number.POSITIVE_INFINITY, maxWidth / width, maxHeight / height);
|
|
178
|
+
return { width: Math.round(width * scale), height: Math.round(height * scale) };
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The keyframe that puts the opened image over its thumbnail. The overlay centres the image in
|
|
182
|
+
* the viewport; the frame scales it uniformly to fit the thumbnail's box and centres it there,
|
|
183
|
+
* so an image whose proportions differ from its box's is not distorted.
|
|
184
|
+
* @param thumbnail - The image on the page.
|
|
185
|
+
* @param size - The size of the opened image.
|
|
186
|
+
*/
|
|
187
|
+
thumbnailFrame(thumbnail, size) {
|
|
188
|
+
const from = (thumbnail ?? this.element).getBoundingClientRect();
|
|
189
|
+
const viewport = this.window?.document.documentElement;
|
|
190
|
+
const left = ((viewport?.clientWidth ?? size.width) - size.width) / 2;
|
|
191
|
+
const top = ((viewport?.clientHeight ?? size.height) - size.height) / 2;
|
|
192
|
+
const scale = Math.min(from.width / size.width, from.height / size.height) || 0;
|
|
193
|
+
const x = from.left + (from.width - size.width * scale) / 2 - left;
|
|
194
|
+
const y = from.top + (from.height - size.height * scale) / 2 - top;
|
|
195
|
+
return { transformOrigin: '0 0', transform: `translate(${x}px, ${y}px) scale(${scale})` };
|
|
106
196
|
}
|
|
107
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
108
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.
|
|
197
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocImageViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
198
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.2.1", type: NgDocImageViewerComponent, isStandalone: true, selector: "ng-doc-image-viewer", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: true, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "click": "clickEvent()", "keydown.enter": "clickEvent()", "keydown.space": "onSpace($event)" }, properties: { "attr.role": "isInteractive() ? \"button\" : null", "attr.tabindex": "isInteractive() ? 0 : null", "attr.aria-label": "isInteractive() ? \"Open image: \" + alt() : null", "attr.data-interactive": "isInteractive()", "attr.data-opened": "opened()" } }, viewQueries: [{ propertyName: "image", first: true, predicate: ["image"], descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<ng-content></ng-content>\n\n<ng-template #image>\n <div\n class=\"ng-doc-image-container\"\n [style.width.px]=\"size().width\"\n [style.height.px]=\"size().height\"\n (click)=\"overlayRef?.close()\">\n <img class=\"ng-doc-scaled-image\" [src]=\"src()\" [alt]=\"alt()\" />\n </div>\n</ng-template>\n", styles: [":host{display:inline-block}:host[data-interactive=true]{cursor:zoom-in}:host{transition:var(--ng-doc-transition);border-radius:var(--ng-doc-radius-lg)}:host:focus-visible{outline:none;box-shadow:var(--ng-doc-focus-ring)}:host[data-opened=true]>::ng-deep img{opacity:0}:host>::ng-deep img{max-width:100%;vertical-align:middle;border-radius:var(--ng-doc-radius-lg);overflow:hidden}.ng-doc-image-container{display:block}.ng-doc-image-container .ng-doc-scaled-image{display:block;width:100%;height:100%;object-fit:contain;border-radius:var(--ng-doc-radius-lg);cursor:zoom-out}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
109
199
|
}
|
|
110
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
200
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocImageViewerComponent, decorators: [{
|
|
111
201
|
type: Component,
|
|
112
202
|
args: [{ selector: 'ng-doc-image-viewer', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
113
|
-
'[attr.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
203
|
+
'[attr.role]': 'isInteractive() ? "button" : null',
|
|
204
|
+
'[attr.tabindex]': 'isInteractive() ? 0 : null',
|
|
205
|
+
'[attr.aria-label]': 'isInteractive() ? "Open image: " + alt() : null',
|
|
206
|
+
'[attr.data-interactive]': 'isInteractive()',
|
|
207
|
+
'[attr.data-opened]': 'opened()',
|
|
208
|
+
'(click)': 'clickEvent()',
|
|
209
|
+
'(keydown.enter)': 'clickEvent()',
|
|
210
|
+
'(keydown.space)': 'onSpace($event)',
|
|
211
|
+
}, template: "<ng-content></ng-content>\n\n<ng-template #image>\n <div\n class=\"ng-doc-image-container\"\n [style.width.px]=\"size().width\"\n [style.height.px]=\"size().height\"\n (click)=\"overlayRef?.close()\">\n <img class=\"ng-doc-scaled-image\" [src]=\"src()\" [alt]=\"alt()\" />\n </div>\n</ng-template>\n", styles: [":host{display:inline-block}:host[data-interactive=true]{cursor:zoom-in}:host{transition:var(--ng-doc-transition);border-radius:var(--ng-doc-radius-lg)}:host:focus-visible{outline:none;box-shadow:var(--ng-doc-focus-ring)}:host[data-opened=true]>::ng-deep img{opacity:0}:host>::ng-deep img{max-width:100%;vertical-align:middle;border-radius:var(--ng-doc-radius-lg);overflow:hidden}.ng-doc-image-container{display:block}.ng-doc-image-container .ng-doc-scaled-image{display:block;width:100%;height:100%;object-fit:contain;border-radius:var(--ng-doc-radius-lg);cursor:zoom-out}\n"] }]
|
|
212
|
+
}], ctorParameters: () => [], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: true }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: true }] }], image: [{ type: i0.ViewChild, args: ['image', { ...{ read: TemplateRef }, isSignal: true }] }] } });
|
|
119
213
|
|
|
120
214
|
/**
|
|
121
215
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-doc-app-components-image-viewer.mjs","sources":["../../../../libs/app/components/image-viewer/image-viewer.component.ts","../../../../libs/app/components/image-viewer/image-viewer.component.html","../../../../libs/app/components/image-viewer/ng-doc-app-components-image-viewer.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostListener,\n inject,\n input,\n TemplateRef,\n viewChild,\n} from '@angular/core';\nimport { NgDocOverlayContainerComponent, NgDocOverlayService } from '@ng-doc/ui-kit';\nimport { NgDocOverlayRef } from '@ng-doc/ui-kit/classes';\n\n@Component({\n selector: 'ng-doc-image-viewer',\n imports: [],\n templateUrl: './image-viewer.component.html',\n styleUrl: './image-viewer.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[attr.data-opened]': '!!overlayRef',\n },\n})\nexport class NgDocImageViewerComponent {\n src = input.required<string>();\n alt = input.required<string>();\n\n protected readonly image = viewChild('image', { read: TemplateRef });\n protected readonly overlay = inject(NgDocOverlayService);\n protected readonly element = inject(ElementRef<HTMLElement>).nativeElement;\n protected readonly changeDetectorRef = inject(ChangeDetectorRef);\n protected overlayRef?: NgDocOverlayRef;\n\n @HostListener('click')\n clickEvent(): void {\n this.overlayRef?.close();\n\n const { width, height, top, left } = this.element.getBoundingClientRect();\n const windowWidth = window.innerWidth;\n const windowHeight = window.innerHeight;\n const ratio = Math.min(windowWidth / width, windowHeight / height);\n const newWidth = width * ratio;\n const newHeight = height * ratio;\n\n this.overlayRef = this.overlay.open(this.image(), {\n overlayContainer: NgDocOverlayContainerComponent,\n positionStrategy: this.overlay\n .globalPositionStrategy()\n .centerHorizontally()\n .centerVertically(),\n scrollStrategy: this.overlay.scrollStrategy().block(),\n hasBackdrop: true,\n backdropClass: 'ng-doc-blur-backdrop',\n openAnimation: [\n [\n {\n position: 'fixed',\n width: `${width}px`,\n height: `${height}px`,\n top: `${top}px`,\n left: `${left}px`,\n transform: 'translate(0%, 0)',\n },\n {\n position: 'fixed',\n width: `${newWidth}px`,\n height: `${newHeight}px`,\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n },\n ],\n {\n duration: 300,\n easing: 'cubic-bezier(0.25, 0.8, 0.25, 1)',\n },\n //\n // group([\n // animate(\n // '300ms cubic-bezier(0.25, 0.8, 0.25, 1)',\n // style({\n // width: `${newWidth}px`,\n // height: `${newHeight}px`,\n // top: '50%',\n // left: '50%',\n // transform: 'translate(-50%, -50%)',\n // }),\n // ),\n // query('.ng-doc-image-container', [\n // style({ padding: 0 }),\n // animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ padding: '16px' })),\n // ]),\n // ]),\n ],\n // closeAnimation: [\n // style({\n // position: 'fixed',\n // width: `${newWidth}px`,\n // height: `${newHeight}px`,\n // top: '50%',\n // left: '50%',\n // transform: 'translate(-50%, -50%)',\n // }),\n // group([\n // animate(\n // '300ms cubic-bezier(0.25, 0.8, 0.25, 1)',\n // style({ width, height, top, left, transform: 'translate(0%, 0)' }),\n // ),\n // query(\n // '.ng-doc-image-container',\n // animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ padding: 0 })),\n // ),\n // ]),\n // ],\n });\n\n this.overlayRef.afterClose().subscribe(() => {\n this.overlayRef = undefined;\n this.changeDetectorRef.markForCheck();\n });\n }\n\n protected enterContainer(element: HTMLElement): void {\n console.log('enterContainer');\n element.animate([{ padding: 0 }, { padding: '16px' }], {\n duration: 300,\n easing: 'cubic-bezier(0.25, 0.8, 0.25, 1)',\n });\n }\n}\n","<ng-content></ng-content>\n\n<ng-template #image>\n <div\n class=\"ng-doc-image-container\"\n (click)=\"overlayRef?.close()\"\n (animate.enter)=\"enterContainer(element)\"\n #element>\n <img class=\"ng-doc-scaled-image\" [src]=\"src()\" [alt]=\"alt()\" />\n </div>\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ng-doc-app-components-image-viewer.mjs","sources":["../../../../libs/app/components/image-viewer/image-viewer.component.ts","../../../../libs/app/components/image-viewer/image-viewer.component.html","../../../../libs/app/components/image-viewer/ng-doc-app-components-image-viewer.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n DOCUMENT,\n ElementRef,\n inject,\n input,\n signal,\n TemplateRef,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { NgDocOverlayContainerComponent, NgDocOverlayService } from '@ng-doc/ui-kit';\nimport { NgDocOverlayRef } from '@ng-doc/ui-kit/classes';\n\n/** The size of the opened image, in CSS pixels. */\ninterface ZoomSize {\n width: number;\n height: number;\n}\n\n/** Easing of the zoom: fast at first, settling into the final size. */\nconst ZOOM_EASING: string = 'cubic-bezier(0.2, 0, 0, 1)';\n\n/**\n * Wraps an image of the page: clicking it, or pressing Enter or Space on it, opens the image at\n * its natural size, scaled down to fit the window.\n *\n * An image inside a link keeps the link's behaviour, and an image with an empty `alt` is\n * decorative: neither becomes a button.\n */\n@Component({\n selector: 'ng-doc-image-viewer',\n imports: [],\n templateUrl: './image-viewer.component.html',\n styleUrl: './image-viewer.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[attr.role]': 'isInteractive() ? \"button\" : null',\n '[attr.tabindex]': 'isInteractive() ? 0 : null',\n '[attr.aria-label]': 'isInteractive() ? \"Open image: \" + alt() : null',\n '[attr.data-interactive]': 'isInteractive()',\n '[attr.data-opened]': 'opened()',\n '(click)': 'clickEvent()',\n '(keydown.enter)': 'clickEvent()',\n '(keydown.space)': 'onSpace($event)',\n },\n})\nexport class NgDocImageViewerComponent {\n /** Source of the image. */\n readonly src = input.required<string>();\n\n /** Alternative text of the image. */\n readonly alt = input.required<string>();\n\n protected readonly image = viewChild.required('image', { read: TemplateRef });\n protected readonly overlay = inject(NgDocOverlayService);\n protected readonly element: HTMLElement = inject(ElementRef<HTMLElement>).nativeElement;\n protected readonly window: Window | null = inject(DOCUMENT).defaultView;\n\n /** Whether the scaled image is open. */\n protected readonly opened = signal<boolean>(false);\n\n /** The size of the opened image. */\n protected readonly size = signal<ZoomSize>({ width: 0, height: 0 });\n\n protected overlayRef?: NgDocOverlayRef;\n\n private attempt: number = 0;\n private destroyed: boolean = false;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => {\n this.destroyed = true;\n this.overlayRef?.close();\n });\n }\n\n /**\n * Opens the image at its natural size, scaled down to fit the window, unless the image is not\n * interactive. The image grows from its place on the page.\n */\n clickEvent(): void {\n untracked(() => {\n if (this.isInteractive()) {\n void this.open();\n }\n });\n }\n\n /**\n * Whether the image opens: it has a text alternative and is not inside a link. The page\n * processor moves the host into place before change detection, so the check reads the DOM\n * where the image ends up.\n */\n protected isInteractive(): boolean {\n return !!this.alt().trim() && !this.element.parentElement?.closest('a');\n }\n\n /**\n * Opens the image on Space without scrolling the page.\n * @param event - The key press.\n */\n protected onSpace(event: Event): void {\n if (this.isInteractive()) {\n event.preventDefault();\n this.clickEvent();\n }\n }\n\n private async open(): Promise<void> {\n this.overlayRef?.close();\n\n const attempt: number = ++this.attempt;\n const thumbnail: HTMLImageElement | null = this.element.querySelector('img');\n\n await this.decode(thumbnail);\n\n // The reader may have opened the image again, pressed Escape or left the page while it\n // decoded.\n if (attempt !== this.attempt || this.destroyed) {\n return;\n }\n\n // The size is known before anything moves, so the image grows straight to it.\n const source: ZoomSize = this.sourceSize(thumbnail);\n const size: ZoomSize = this.fit(source);\n const zoomedFrame: Keyframe = { transformOrigin: '0 0', transform: 'none' };\n // The close animation reads its keyframes when it runs; a refit updates them in place.\n const closeFrames: Keyframe[] = [zoomedFrame, this.thumbnailFrame(thumbnail, size)];\n const animate: boolean = !this.window?.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n\n this.size.set(size);\n\n const overlayRef: NgDocOverlayRef = this.overlay.open(this.image(), {\n overlayContainer: NgDocOverlayContainerComponent,\n positionStrategy: this.overlay\n .globalPositionStrategy()\n .centerHorizontally()\n .centerVertically(),\n scrollStrategy: this.overlay.scrollStrategy().block(),\n hasBackdrop: true,\n backdropClass: 'ng-doc-blur-backdrop',\n width: `${size.width}px`,\n height: `${size.height}px`,\n openAnimation: animate\n ? [[closeFrames[1], zoomedFrame], { duration: 300, easing: ZOOM_EASING }]\n : undefined,\n closeAnimation: animate\n ? [closeFrames, { duration: 200, easing: ZOOM_EASING, fill: 'forwards' }]\n : undefined,\n });\n const listeners: AbortController = new AbortController();\n // A resized or rotated window fits the image again.\n const refit = (): void => {\n const fitted: ZoomSize = this.fit(source);\n\n this.size.set(fitted);\n overlayRef.overlayRef.updateSize({\n width: `${fitted.width}px`,\n height: `${fitted.height}px`,\n });\n closeFrames[1] = this.thumbnailFrame(thumbnail, fitted);\n };\n\n this.window?.addEventListener('resize', refit, { signal: listeners.signal });\n this.window?.addEventListener('orientationchange', refit, { signal: listeners.signal });\n\n this.overlayRef = overlayRef;\n this.opened.set(true);\n\n overlayRef.afterClose().subscribe(() => {\n listeners.abort();\n\n if (this.overlayRef === overlayRef) {\n this.overlayRef = undefined;\n this.opened.set(false);\n this.element.focus();\n }\n });\n }\n\n /**\n * Waits until the image is decoded, so its natural size is known. Escape cancels the open\n * meanwhile, as it closes the opened image. A failed decode (a broken or not yet available\n * image) leaves the sizes that are known.\n * @param thumbnail - The image on the page.\n */\n private async decode(thumbnail: HTMLImageElement | null): Promise<void> {\n const listeners: AbortController = new AbortController();\n\n this.window?.document.addEventListener(\n 'keydown',\n (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n this.attempt++;\n }\n },\n { capture: true, signal: listeners.signal },\n );\n\n try {\n await thumbnail?.decode?.().catch(() => undefined);\n } finally {\n listeners.abort();\n }\n }\n\n /**\n * The size to scale: the natural size of the image, or the size of the thumbnail for an image\n * without one (an SVG without dimensions), which may then grow to fill the window.\n * @param thumbnail - The image on the page.\n */\n private sourceSize(thumbnail: HTMLImageElement | null): ZoomSize & { natural: boolean } {\n const naturalWidth: number = thumbnail?.naturalWidth ?? 0;\n const naturalHeight: number = thumbnail?.naturalHeight ?? 0;\n\n if (naturalWidth > 0 && naturalHeight > 0) {\n return { width: naturalWidth, height: naturalHeight, natural: true };\n }\n\n const rect: DOMRect = (thumbnail ?? this.element).getBoundingClientRect();\n\n return { width: rect.width, height: rect.height, natural: false };\n }\n\n /**\n * The size the image opens at: its natural size, scaled down to fit the viewport with a margin\n * and never scaled up. An image without a natural size fills the available space with the\n * proportions of its thumbnail.\n * @param source - The size to scale.\n */\n private fit(source: ZoomSize & { natural?: boolean }): ZoomSize {\n const viewport: HTMLElement | undefined = this.window?.document.documentElement;\n const viewportWidth: number = viewport?.clientWidth || this.window?.innerWidth || 0;\n const viewportHeight: number = viewport?.clientHeight || this.window?.innerHeight || 0;\n const margin: number = viewportWidth <= 640 ? 16 : 48;\n const maxWidth: number = Math.max(viewportWidth - margin * 2, 1);\n const maxHeight: number = Math.max(viewportHeight - margin * 2, 1);\n const width: number = source.width || maxWidth;\n const height: number = source.height || maxHeight;\n const scale: number = Math.min(\n source.natural ? 1 : Number.POSITIVE_INFINITY,\n maxWidth / width,\n maxHeight / height,\n );\n\n return { width: Math.round(width * scale), height: Math.round(height * scale) };\n }\n\n /**\n * The keyframe that puts the opened image over its thumbnail. The overlay centres the image in\n * the viewport; the frame scales it uniformly to fit the thumbnail's box and centres it there,\n * so an image whose proportions differ from its box's is not distorted.\n * @param thumbnail - The image on the page.\n * @param size - The size of the opened image.\n */\n private thumbnailFrame(thumbnail: HTMLImageElement | null, size: ZoomSize): Keyframe {\n const from: DOMRect = (thumbnail ?? this.element).getBoundingClientRect();\n const viewport: HTMLElement | undefined = this.window?.document.documentElement;\n const left: number = ((viewport?.clientWidth ?? size.width) - size.width) / 2;\n const top: number = ((viewport?.clientHeight ?? size.height) - size.height) / 2;\n const scale: number = Math.min(from.width / size.width, from.height / size.height) || 0;\n const x: number = from.left + (from.width - size.width * scale) / 2 - left;\n const y: number = from.top + (from.height - size.height * scale) / 2 - top;\n\n return { transformOrigin: '0 0', transform: `translate(${x}px, ${y}px) scale(${scale})` };\n }\n}\n","<ng-content></ng-content>\n\n<ng-template #image>\n <div\n class=\"ng-doc-image-container\"\n [style.width.px]=\"size().width\"\n [style.height.px]=\"size().height\"\n (click)=\"overlayRef?.close()\">\n <img class=\"ng-doc-scaled-image\" [src]=\"src()\" [alt]=\"alt()\" />\n </div>\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,38 +1,55 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { input, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Words the kind chips show for declaration kinds whose name is not already a readable word.
|
|
6
|
+
* Other kinds (and value types) are shown as they are.
|
|
7
|
+
*/
|
|
8
|
+
const NG_DOC_KIND_LABELS = {
|
|
9
|
+
TypeAlias: 'Type alias',
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The label a kind chip shows for a kind.
|
|
13
|
+
* @param kind - Declaration kind (for example `Class` or `TypeAlias`) or value type (`string`).
|
|
14
|
+
* @returns The word to show, for example "Type alias".
|
|
15
|
+
*/
|
|
16
|
+
function ngDocKindLabel(kind) {
|
|
17
|
+
return NG_DOC_KIND_LABELS[kind] ?? kind;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A word chip for a declaration kind (`Class`, `Component`, `Type alias`, ...) or a value type
|
|
21
|
+
* (`string`, `boolean`, ...), coloured by the kind.
|
|
22
|
+
*/
|
|
4
23
|
class NgDocKindIconComponent {
|
|
5
24
|
constructor() {
|
|
6
|
-
|
|
7
|
-
this.
|
|
8
|
-
|
|
25
|
+
/** Declaration kind or value type. */
|
|
26
|
+
this.kind = input('', /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/** Whether `kind` is a declaration kind or a value type; it selects the colours. */
|
|
29
|
+
this.type = input('declaration', /* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/** `small` is the compact chip; `medium` the regular one. */
|
|
32
|
+
this.size = input('small', /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
34
|
+
/** The word the chip shows. */
|
|
35
|
+
this.label = computed(() => ngDocKindLabel(this.kind()), /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
9
37
|
}
|
|
10
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
11
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
38
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocKindIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
39
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.2.1", type: NgDocKindIconComponent, isStandalone: true, selector: "ng-doc-kind-icon", inputs: { kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-ng-doc-kind": "kind()", "attr.data-ng-doc-type": "type()", "attr.data-ng-doc-size": "size()" } }, ngImport: i0, template: '{{ label() }}', isInline: true, styles: [":host{display:inline-flex;align-items:center;flex:none;height:20px;padding:0 7px;border-radius:var(--ng-doc-radius-sm);font-family:var(--ng-doc-font-family);font-size:11.5px;font-weight:600;line-height:1;white-space:nowrap;color:color-mix(in oklab,var(--ng-doc-kind-icon-background, var(--ng-doc-hue-neutral)) var(--ng-doc-mix-strong),var(--ng-doc-heading-color));background:color-mix(in oklab,var(--ng-doc-kind-icon-background, var(--ng-doc-hue-neutral)) var(--ng-doc-kind-icon-background-opacity, var(--ng-doc-mix-chip)),var(--ng-doc-background));box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ng-doc-kind-icon-background, var(--ng-doc-hue-neutral)) 24%,transparent)}:host[data-ng-doc-size=small]{height:18px;padding:0 5px;font-size:10.5px}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Class]{--ng-doc-kind-icon-background: var(--ng-doc-class-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Interface]{--ng-doc-kind-icon-background: var(--ng-doc-interface-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Enum]{--ng-doc-kind-icon-background: var(--ng-doc-enum-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Variable]{--ng-doc-kind-icon-background: var(--ng-doc-variable-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Function]{--ng-doc-kind-icon-background: var(--ng-doc-function-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=TypeAlias]{--ng-doc-kind-icon-background: var(--ng-doc-type-alias-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Component]{--ng-doc-kind-icon-background: var(--ng-doc-component-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Directive]{--ng-doc-kind-icon-background: var(--ng-doc-directive-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Injectable]{--ng-doc-kind-icon-background: var(--ng-doc-injectable-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Pipe]{--ng-doc-kind-icon-background: var(--ng-doc-pipe-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=NgModule]{--ng-doc-kind-icon-background: var(--ng-doc-ng-module-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=ng-doc-tag-selector]{--ng-doc-kind-icon-background: var(--ng-doc-selector-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=string]{--ng-doc-kind-icon-background: var(--ng-doc-string-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=number]{--ng-doc-kind-icon-background: var(--ng-doc-number-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=boolean]{--ng-doc-kind-icon-background: var(--ng-doc-boolean-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=null]{--ng-doc-kind-icon-background: var(--ng-doc-null-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=undefined]{--ng-doc-kind-icon-background: var(--ng-doc-undefined-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=object]{--ng-doc-kind-icon-background: var(--ng-doc-object-background)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
12
40
|
}
|
|
13
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
41
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocKindIconComponent, decorators: [{
|
|
14
42
|
type: Component,
|
|
15
|
-
args: [{ selector: 'ng-doc-kind-icon', template: '{{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}], type: [{
|
|
22
|
-
type: Input
|
|
23
|
-
}, {
|
|
24
|
-
type: HostBinding,
|
|
25
|
-
args: ['attr.data-ng-doc-type']
|
|
26
|
-
}], size: [{
|
|
27
|
-
type: Input
|
|
28
|
-
}, {
|
|
29
|
-
type: HostBinding,
|
|
30
|
-
args: ['attr.data-ng-doc-size']
|
|
31
|
-
}] } });
|
|
43
|
+
args: [{ selector: 'ng-doc-kind-icon', template: '{{ label() }}', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
44
|
+
'[attr.data-ng-doc-kind]': 'kind()',
|
|
45
|
+
'[attr.data-ng-doc-type]': 'type()',
|
|
46
|
+
'[attr.data-ng-doc-size]': 'size()',
|
|
47
|
+
}, styles: [":host{display:inline-flex;align-items:center;flex:none;height:20px;padding:0 7px;border-radius:var(--ng-doc-radius-sm);font-family:var(--ng-doc-font-family);font-size:11.5px;font-weight:600;line-height:1;white-space:nowrap;color:color-mix(in oklab,var(--ng-doc-kind-icon-background, var(--ng-doc-hue-neutral)) var(--ng-doc-mix-strong),var(--ng-doc-heading-color));background:color-mix(in oklab,var(--ng-doc-kind-icon-background, var(--ng-doc-hue-neutral)) var(--ng-doc-kind-icon-background-opacity, var(--ng-doc-mix-chip)),var(--ng-doc-background));box-shadow:inset 0 0 0 1px color-mix(in oklab,var(--ng-doc-kind-icon-background, var(--ng-doc-hue-neutral)) 24%,transparent)}:host[data-ng-doc-size=small]{height:18px;padding:0 5px;font-size:10.5px}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Class]{--ng-doc-kind-icon-background: var(--ng-doc-class-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Interface]{--ng-doc-kind-icon-background: var(--ng-doc-interface-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Enum]{--ng-doc-kind-icon-background: var(--ng-doc-enum-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Variable]{--ng-doc-kind-icon-background: var(--ng-doc-variable-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Function]{--ng-doc-kind-icon-background: var(--ng-doc-function-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=TypeAlias]{--ng-doc-kind-icon-background: var(--ng-doc-type-alias-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Component]{--ng-doc-kind-icon-background: var(--ng-doc-component-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Directive]{--ng-doc-kind-icon-background: var(--ng-doc-directive-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Injectable]{--ng-doc-kind-icon-background: var(--ng-doc-injectable-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=Pipe]{--ng-doc-kind-icon-background: var(--ng-doc-pipe-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=NgModule]{--ng-doc-kind-icon-background: var(--ng-doc-ng-module-decorator-background)}:host[data-ng-doc-type=declaration][data-ng-doc-kind=ng-doc-tag-selector]{--ng-doc-kind-icon-background: var(--ng-doc-selector-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=string]{--ng-doc-kind-icon-background: var(--ng-doc-string-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=number]{--ng-doc-kind-icon-background: var(--ng-doc-number-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=boolean]{--ng-doc-kind-icon-background: var(--ng-doc-boolean-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=null]{--ng-doc-kind-icon-background: var(--ng-doc-null-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=undefined]{--ng-doc-kind-icon-background: var(--ng-doc-undefined-background)}:host[data-ng-doc-type=type][data-ng-doc-kind=object]{--ng-doc-kind-icon-background: var(--ng-doc-object-background)}\n"] }]
|
|
48
|
+
}], propDecorators: { kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
32
49
|
|
|
33
50
|
/**
|
|
34
51
|
* Generated bundle index. Do not edit.
|
|
35
52
|
*/
|
|
36
53
|
|
|
37
|
-
export { NgDocKindIconComponent };
|
|
54
|
+
export { NG_DOC_KIND_LABELS, NgDocKindIconComponent, ngDocKindLabel };
|
|
38
55
|
//# sourceMappingURL=ng-doc-app-components-kind-icon.mjs.map
|