@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.
Files changed (203) hide show
  1. package/README.md +20 -29
  2. package/fesm2022/ng-doc-app-classes-content-anchor-controller.mjs +363 -0
  3. package/fesm2022/ng-doc-app-classes-content-anchor-controller.mjs.map +1 -0
  4. package/fesm2022/ng-doc-app-classes-content-controller.mjs +299 -0
  5. package/fesm2022/ng-doc-app-classes-content-controller.mjs.map +1 -0
  6. package/fesm2022/ng-doc-app-classes-default-search-engine.mjs +51 -35
  7. package/fesm2022/ng-doc-app-classes-default-search-engine.mjs.map +1 -1
  8. package/fesm2022/ng-doc-app-classes-root-page.mjs.map +1 -1
  9. package/fesm2022/ng-doc-app-classes-search-engine.mjs.map +1 -1
  10. package/fesm2022/ng-doc-app-classes.mjs +2 -0
  11. package/fesm2022/ng-doc-app-classes.mjs.map +1 -1
  12. package/fesm2022/ng-doc-app-components-api-list.mjs +173 -69
  13. package/fesm2022/ng-doc-app-components-api-list.mjs.map +1 -1
  14. package/fesm2022/ng-doc-app-components-breadcrumb.mjs +13 -10
  15. package/fesm2022/ng-doc-app-components-breadcrumb.mjs.map +1 -1
  16. package/fesm2022/ng-doc-app-components-code.mjs +152 -25
  17. package/fesm2022/ng-doc-app-components-code.mjs.map +1 -1
  18. package/fesm2022/ng-doc-app-components-command-palette.mjs +498 -0
  19. package/fesm2022/ng-doc-app-components-command-palette.mjs.map +1 -0
  20. package/fesm2022/ng-doc-app-components-copy-button.mjs +38 -21
  21. package/fesm2022/ng-doc-app-components-copy-button.mjs.map +1 -1
  22. package/fesm2022/ng-doc-app-components-demo-displayer.mjs +36 -29
  23. package/fesm2022/ng-doc-app-components-demo-displayer.mjs.map +1 -1
  24. package/fesm2022/ng-doc-app-components-demo-pane.mjs +39 -36
  25. package/fesm2022/ng-doc-app-components-demo-pane.mjs.map +1 -1
  26. package/fesm2022/ng-doc-app-components-demo.mjs +129 -44
  27. package/fesm2022/ng-doc-app-components-demo.mjs.map +1 -1
  28. package/fesm2022/ng-doc-app-components-fullscreen-button.mjs +12 -9
  29. package/fesm2022/ng-doc-app-components-fullscreen-button.mjs.map +1 -1
  30. package/fesm2022/ng-doc-app-components-fullscreen-toggle.mjs +79 -0
  31. package/fesm2022/ng-doc-app-components-fullscreen-toggle.mjs.map +1 -0
  32. package/fesm2022/ng-doc-app-components-heading-anchor.mjs +54 -21
  33. package/fesm2022/ng-doc-app-components-heading-anchor.mjs.map +1 -1
  34. package/fesm2022/ng-doc-app-components-image-viewer.mjs +183 -89
  35. package/fesm2022/ng-doc-app-components-image-viewer.mjs.map +1 -1
  36. package/fesm2022/ng-doc-app-components-kind-icon.mjs +42 -25
  37. package/fesm2022/ng-doc-app-components-kind-icon.mjs.map +1 -1
  38. package/fesm2022/ng-doc-app-components-link.mjs +12 -9
  39. package/fesm2022/ng-doc-app-components-link.mjs.map +1 -1
  40. package/fesm2022/ng-doc-app-components-members.mjs +30 -0
  41. package/fesm2022/ng-doc-app-components-members.mjs.map +1 -0
  42. package/fesm2022/ng-doc-app-components-mermaid-viewer.mjs +61 -20
  43. package/fesm2022/ng-doc-app-components-mermaid-viewer.mjs.map +1 -1
  44. package/fesm2022/ng-doc-app-components-navbar.mjs +39 -49
  45. package/fesm2022/ng-doc-app-components-navbar.mjs.map +1 -1
  46. package/fesm2022/ng-doc-app-components-page-header.mjs +73 -10
  47. package/fesm2022/ng-doc-app-components-page-header.mjs.map +1 -1
  48. package/fesm2022/ng-doc-app-components-page-link.mjs +123 -31
  49. package/fesm2022/ng-doc-app-components-page-link.mjs.map +1 -1
  50. package/fesm2022/ng-doc-app-components-page-navigation.mjs +17 -19
  51. package/fesm2022/ng-doc-app-components-page-navigation.mjs.map +1 -1
  52. package/fesm2022/ng-doc-app-components-page-wrapper.mjs +56 -35
  53. package/fesm2022/ng-doc-app-components-page-wrapper.mjs.map +1 -1
  54. package/fesm2022/ng-doc-app-components-page.mjs +168 -24
  55. package/fesm2022/ng-doc-app-components-page.mjs.map +1 -1
  56. package/fesm2022/ng-doc-app-components-playground.mjs +392 -263
  57. package/fesm2022/ng-doc-app-components-playground.mjs.map +1 -1
  58. package/fesm2022/ng-doc-app-components-root.mjs +48 -31
  59. package/fesm2022/ng-doc-app-components-root.mjs.map +1 -1
  60. package/fesm2022/ng-doc-app-components-search-result.mjs +22 -21
  61. package/fesm2022/ng-doc-app-components-search-result.mjs.map +1 -1
  62. package/fesm2022/ng-doc-app-components-search.mjs +64 -33
  63. package/fesm2022/ng-doc-app-components-search.mjs.map +1 -1
  64. package/fesm2022/ng-doc-app-components-sidebar.mjs +86 -61
  65. package/fesm2022/ng-doc-app-components-sidebar.mjs.map +1 -1
  66. package/fesm2022/ng-doc-app-components-tabs.mjs +18 -12
  67. package/fesm2022/ng-doc-app-components-tabs.mjs.map +1 -1
  68. package/fesm2022/ng-doc-app-components-theme-toggle.mjs +33 -21
  69. package/fesm2022/ng-doc-app-components-theme-toggle.mjs.map +1 -1
  70. package/fesm2022/ng-doc-app-components-toc.mjs +267 -90
  71. package/fesm2022/ng-doc-app-components-toc.mjs.map +1 -1
  72. package/fesm2022/ng-doc-app-components.mjs +3 -1
  73. package/fesm2022/ng-doc-app-components.mjs.map +1 -1
  74. package/fesm2022/ng-doc-app-defaults-default-processors.mjs +2 -1
  75. package/fesm2022/ng-doc-app-defaults-default-processors.mjs.map +1 -1
  76. package/fesm2022/ng-doc-app-directives-code-highlighter.mjs +11 -5
  77. package/fesm2022/ng-doc-app-directives-code-highlighter.mjs.map +1 -1
  78. package/fesm2022/ng-doc-app-directives-members-filter.mjs +276 -0
  79. package/fesm2022/ng-doc-app-directives-members-filter.mjs.map +1 -0
  80. package/fesm2022/ng-doc-app-directives-route-active.mjs +34 -30
  81. package/fesm2022/ng-doc-app-directives-route-active.mjs.map +1 -1
  82. package/fesm2022/ng-doc-app-directives.mjs +1 -0
  83. package/fesm2022/ng-doc-app-directives.mjs.map +1 -1
  84. package/fesm2022/ng-doc-app-helpers.mjs +285 -1
  85. package/fesm2022/ng-doc-app-helpers.mjs.map +1 -1
  86. package/fesm2022/ng-doc-app-pipes-decode-uri-component.mjs +6 -4
  87. package/fesm2022/ng-doc-app-pipes-decode-uri-component.mjs.map +1 -1
  88. package/fesm2022/ng-doc-app-pipes-extract-value.mjs +6 -4
  89. package/fesm2022/ng-doc-app-pipes-extract-value.mjs.map +1 -1
  90. package/fesm2022/ng-doc-app-pipes-filter-by-text.mjs +7 -4
  91. package/fesm2022/ng-doc-app-pipes-filter-by-text.mjs.map +1 -1
  92. package/fesm2022/ng-doc-app-pipes-sanitize-html.mjs +8 -5
  93. package/fesm2022/ng-doc-app-pipes-sanitize-html.mjs.map +1 -1
  94. package/fesm2022/ng-doc-app-processors-page-processor.mjs +86 -23
  95. package/fesm2022/ng-doc-app-processors-page-processor.mjs.map +1 -1
  96. package/fesm2022/ng-doc-app-processors-processors-tooltip.mjs +26 -25
  97. package/fesm2022/ng-doc-app-processors-processors-tooltip.mjs.map +1 -1
  98. package/fesm2022/ng-doc-app-processors-processors.mjs +12 -1
  99. package/fesm2022/ng-doc-app-processors-processors.mjs.map +1 -1
  100. package/fesm2022/ng-doc-app-providers-ng-doc-app.mjs +31 -2
  101. package/fesm2022/ng-doc-app-providers-ng-doc-app.mjs.map +1 -1
  102. package/fesm2022/ng-doc-app-services-content-scroll-intent.mjs +122 -0
  103. package/fesm2022/ng-doc-app-services-content-scroll-intent.mjs.map +1 -0
  104. package/fesm2022/ng-doc-app-services-content-state.mjs +57 -0
  105. package/fesm2022/ng-doc-app-services-content-state.mjs.map +1 -0
  106. package/fesm2022/ng-doc-app-services-fullscreen-route.mjs +74 -0
  107. package/fesm2022/ng-doc-app-services-fullscreen-route.mjs.map +1 -0
  108. package/fesm2022/ng-doc-app-services-highlighter.mjs +83 -14
  109. package/fesm2022/ng-doc-app-services-highlighter.mjs.map +1 -1
  110. package/fesm2022/ng-doc-app-services-route-preloader.mjs +360 -0
  111. package/fesm2022/ng-doc-app-services-route-preloader.mjs.map +1 -0
  112. package/fesm2022/ng-doc-app-services-shortcuts.mjs +214 -0
  113. package/fesm2022/ng-doc-app-services-shortcuts.mjs.map +1 -0
  114. package/fesm2022/ng-doc-app-services-sidebar.mjs +59 -25
  115. package/fesm2022/ng-doc-app-services-sidebar.mjs.map +1 -1
  116. package/fesm2022/ng-doc-app-services-store.mjs +8 -8
  117. package/fesm2022/ng-doc-app-services-store.mjs.map +1 -1
  118. package/fesm2022/ng-doc-app-services-theme.mjs +32 -12
  119. package/fesm2022/ng-doc-app-services-theme.mjs.map +1 -1
  120. package/fesm2022/ng-doc-app-services.mjs +143 -0
  121. package/fesm2022/ng-doc-app-services.mjs.map +1 -1
  122. package/fesm2022/ng-doc-app-tokens.mjs +7 -28
  123. package/fesm2022/ng-doc-app-tokens.mjs.map +1 -1
  124. package/fesm2022/ng-doc-app-type-controls-boolean-control.mjs +18 -9
  125. package/fesm2022/ng-doc-app-type-controls-boolean-control.mjs.map +1 -1
  126. package/fesm2022/ng-doc-app-type-controls-number-control.mjs +12 -9
  127. package/fesm2022/ng-doc-app-type-controls-number-control.mjs.map +1 -1
  128. package/fesm2022/ng-doc-app-type-controls-string-control.mjs +12 -9
  129. package/fesm2022/ng-doc-app-type-controls-string-control.mjs.map +1 -1
  130. package/fesm2022/ng-doc-app-type-controls-type-alias-control.mjs +22 -16
  131. package/fesm2022/ng-doc-app-type-controls-type-alias-control.mjs.map +1 -1
  132. package/package.json +69 -28
  133. package/styles/global.css +1125 -201
  134. package/styles/main.css +1125 -201
  135. package/styles/themes/dark.css +78 -56
  136. package/types/ng-doc-app-classes-content-anchor-controller.d.ts +54 -0
  137. package/types/ng-doc-app-classes-content-controller.d.ts +94 -0
  138. package/types/ng-doc-app-classes-default-search-engine.d.ts +9 -1
  139. package/types/ng-doc-app-classes-root-page.d.ts +6 -1
  140. package/types/ng-doc-app-classes-search-engine.d.ts +5 -0
  141. package/types/ng-doc-app-classes.d.ts +2 -0
  142. package/types/ng-doc-app-components-api-list.d.ts +69 -20
  143. package/types/ng-doc-app-components-breadcrumb.d.ts +8 -3
  144. package/types/ng-doc-app-components-code.d.ts +46 -12
  145. package/types/ng-doc-app-components-command-palette.d.ts +147 -0
  146. package/types/ng-doc-app-components-copy-button.d.ts +18 -6
  147. package/types/ng-doc-app-components-demo-displayer.d.ts +23 -10
  148. package/types/ng-doc-app-components-demo-pane.d.ts +19 -15
  149. package/types/ng-doc-app-components-demo.d.ts +62 -15
  150. package/types/ng-doc-app-components-fullscreen-button.d.ts +4 -2
  151. package/types/ng-doc-app-components-fullscreen-toggle.d.ts +24 -0
  152. package/types/ng-doc-app-components-heading-anchor.d.ts +26 -7
  153. package/types/ng-doc-app-components-image-viewer.d.ts +71 -7
  154. package/types/ng-doc-app-components-kind-icon.d.ts +28 -7
  155. package/types/ng-doc-app-components-link.d.ts +6 -2
  156. package/types/ng-doc-app-components-members.d.ts +13 -0
  157. package/types/ng-doc-app-components-mermaid-viewer.d.ts +21 -6
  158. package/types/ng-doc-app-components-navbar.d.ts +25 -15
  159. package/types/ng-doc-app-components-page-header.d.ts +28 -4
  160. package/types/ng-doc-app-components-page-link.d.ts +34 -15
  161. package/types/ng-doc-app-components-page-navigation.d.ts +10 -5
  162. package/types/ng-doc-app-components-page-wrapper.d.ts +35 -11
  163. package/types/ng-doc-app-components-page.d.ts +57 -6
  164. package/types/ng-doc-app-components-playground.d.ts +146 -78
  165. package/types/ng-doc-app-components-root.d.ts +28 -7
  166. package/types/ng-doc-app-components-search-result.d.ts +14 -6
  167. package/types/ng-doc-app-components-search.d.ts +19 -7
  168. package/types/ng-doc-app-components-tabs.d.ts +13 -4
  169. package/types/ng-doc-app-components-theme-toggle.d.ts +18 -5
  170. package/types/ng-doc-app-components-toc.d.ts +76 -29
  171. package/types/ng-doc-app-components.d.ts +3 -1
  172. package/types/ng-doc-app-directives-code-highlighter.d.ts +8 -4
  173. package/types/ng-doc-app-directives-members-filter.d.ts +61 -0
  174. package/types/ng-doc-app-directives-route-active.d.ts +21 -7
  175. package/types/ng-doc-app-directives.d.ts +1 -0
  176. package/types/ng-doc-app-helpers.d.ts +124 -3
  177. package/types/ng-doc-app-interfaces.d.ts +48 -28
  178. package/types/ng-doc-app-pipes-decode-uri-component.d.ts +3 -0
  179. package/types/ng-doc-app-pipes-extract-value.d.ts +3 -0
  180. package/types/ng-doc-app-pipes-filter-by-text.d.ts +4 -0
  181. package/types/ng-doc-app-pipes-sanitize-html.d.ts +4 -2
  182. package/types/ng-doc-app-processors-page-processor.d.ts +39 -10
  183. package/types/ng-doc-app-processors-processors-tooltip.d.ts +11 -10
  184. package/types/ng-doc-app-processors-processors.d.ts +5 -1
  185. package/types/ng-doc-app-providers-ng-doc-app.d.ts +17 -0
  186. package/types/ng-doc-app-services-content-scroll-intent.d.ts +52 -0
  187. package/types/ng-doc-app-services-content-state.d.ts +40 -0
  188. package/types/ng-doc-app-services-fullscreen-route.d.ts +35 -0
  189. package/types/ng-doc-app-services-highlighter.d.ts +40 -5
  190. package/types/ng-doc-app-services-route-preloader.d.ts +109 -0
  191. package/types/ng-doc-app-services-shortcuts.d.ts +96 -0
  192. package/types/ng-doc-app-services-sidebar.d.ts +24 -4
  193. package/types/ng-doc-app-services-store.d.ts +24 -1
  194. package/types/ng-doc-app-services-theme.d.ts +19 -3
  195. package/types/ng-doc-app-services.d.ts +77 -0
  196. package/types/ng-doc-app-tokens.d.ts +10 -30
  197. package/types/ng-doc-app-type-controls-boolean-control.d.ts +11 -6
  198. package/types/ng-doc-app-type-controls-number-control.d.ts +5 -3
  199. package/types/ng-doc-app-type-controls-string-control.d.ts +5 -3
  200. package/types/ng-doc-app-type-controls-type-alias-control.d.ts +13 -6
  201. package/fesm2022/ng-doc-app-components-search-dialog.mjs +0 -78
  202. package/fesm2022/ng-doc-app-components-search-dialog.mjs.map +0 -1
  203. 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, Input, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
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
- this.classes = [];
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
- get href() {
13
- const { origin, pathname } = this.location;
14
- return `${origin}${pathname}#${this.anchor}`;
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.0.6", ngImport: i0, type: NgDocHeadingAnchorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.6", type: NgDocHeadingAnchorComponent, isStandalone: true, selector: "ng-doc-heading-anchor", inputs: { anchor: "anchor", classes: "classes" }, host: { properties: { "class": "this.classes" } }, ngImport: i0, template: `
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.0.6", ngImport: i0, type: NgDocHeadingAnchorComponent, decorators: [{
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
- }], propDecorators: { anchor: [{
31
- type: Input,
32
- args: [{ required: true }]
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 { ChangeDetectionStrategy, Component, HostBinding, inject, Input } from '@angular/core';\nimport { NgDocCopyButtonComponent } from '@ng-doc/app/components/copy-button';\nimport { NgDocIconComponent } from '@ng-doc/ui-kit';\nimport { WA_LOCATION } from '@ng-web-apis/common';\n\n@Component({\n selector: 'ng-doc-heading-anchor',\n imports: [NgDocIconComponent, NgDocCopyButtonComponent],\n template: `\n <ng-doc-copy-button [text]=\"href\">\n <ng-doc-icon icon=\"link-2\"></ng-doc-icon>\n </ng-doc-copy-button>\n `,\n styles: ``,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class NgDocHeadingAnchorComponent {\n @Input({ required: true })\n anchor!: string;\n\n @Input()\n @HostBinding('class')\n classes: string[] = [];\n\n protected readonly location = inject(WA_LOCATION);\n\n protected get href(): string {\n const { origin, pathname } = this.location;\n\n return `${origin}${pathname}#${this.anchor}`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAgBa,2BAA2B,CAAA;AAXxC,IAAA,WAAA,GAAA;QAiBE,IAAA,CAAA,OAAO,GAAa,EAAE;AAEH,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;AAOlD,IAAA;AALC,IAAA,IAAc,IAAI,GAAA;QAChB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ;QAE1C,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAA,CAAE;IAC9C;8GAdW,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA3B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,cAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAR5B;;;;GAIT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EALS,kBAAkB,gGAAE,wBAAwB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;2FAS3C,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAXvC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,uBAAuB,WACxB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,EAAA,QAAA,EAC7C;;;;GAIT,EAAA,eAAA,EAEgB,uBAAuB,CAAC,MAAM,EAAA;;sBAG9C,KAAK;uBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;sBAGxB;;sBACA,WAAW;uBAAC,OAAO;;;ACrBtB;;AAEG;;;;"}
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, ChangeDetectorRef, HostListener, ChangeDetectionStrategy, Component } from '@angular/core';
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.changeDetectorRef = inject(ChangeDetectorRef);
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 { width, height, top, left } = this.element.getBoundingClientRect();
19
- const windowWidth = window.innerWidth;
20
- const windowHeight = window.innerHeight;
21
- const ratio = Math.min(windowWidth / width, windowHeight / height);
22
- const newWidth = width * ratio;
23
- const newHeight = height * ratio;
24
- this.overlayRef = this.overlay.open(this.image(), {
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
- openAnimation: [
34
- [
35
- {
36
- position: 'fixed',
37
- width: `${width}px`,
38
- height: `${height}px`,
39
- top: `${top}px`,
40
- left: `${left}px`,
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
- this.overlayRef.afterClose().subscribe(() => {
96
- this.overlayRef = undefined;
97
- this.changeDetectorRef.markForCheck();
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
- enterContainer(element) {
101
- console.log('enterContainer');
102
- element.animate([{ padding: 0 }, { padding: '16px' }], {
103
- duration: 300,
104
- easing: 'cubic-bezier(0.25, 0.8, 0.25, 1)',
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.0.6", ngImport: i0, type: NgDocImageViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
108
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.6", 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()" }, properties: { "attr.data-opened": "!!overlayRef" } }, 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 (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", styles: [":host{display:inline-block;cursor:zoom-in;transition:var(--ng-doc-transition)}:host[data-opened=true]>::ng-deep img{opacity:0}:host>::ng-deep img{max-width:100%;vertical-align:middle;border-radius:var(--ng-doc-base-gutter);overflow:hidden}.ng-doc-image-container{display:flex;align-items:center;justify-content:center;padding:calc(var(--ng-doc-base-gutter) * 2);width:100%;height:100%}.ng-doc-image-container .ng-doc-scaled-image{cursor:zoom-out;width:100%;height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
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.0.6", ngImport: i0, type: NgDocImageViewerComponent, decorators: [{
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.data-opened]': '!!overlayRef',
114
- }, template: "<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", styles: [":host{display:inline-block;cursor:zoom-in;transition:var(--ng-doc-transition)}:host[data-opened=true]>::ng-deep img{opacity:0}:host>::ng-deep img{max-width:100%;vertical-align:middle;border-radius:var(--ng-doc-base-gutter);overflow:hidden}.ng-doc-image-container{display:flex;align-items:center;justify-content:center;padding:calc(var(--ng-doc-base-gutter) * 2);width:100%;height:100%}.ng-doc-image-container .ng-doc-scaled-image{cursor:zoom-out;width:100%;height:100%}\n"] }]
115
- }], 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 }] }], clickEvent: [{
116
- type: HostListener,
117
- args: ['click']
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 { Input, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
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
- this.kind = '';
7
- this.type = 'declaration';
8
- this.size = 'small';
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.0.6", ngImport: i0, type: NgDocKindIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.6", type: NgDocKindIconComponent, isStandalone: true, selector: "ng-doc-kind-icon", inputs: { kind: "kind", type: "type", size: "size" }, host: { properties: { "attr.data-ng-doc-kind": "this.kind", "attr.data-ng-doc-type": "this.type", "attr.data-ng-doc-size": "this.size" } }, ngImport: i0, template: '{{kind[0]}}', isInline: true, styles: [":host{display:inline-block;width:22px;height:22px;border-radius:calc(var(--ng-doc-base-gutter) / 2);font-size:13px;text-align:center;line-height:22px;text-transform:uppercase;flex-shrink:0;font-weight:700;color:var(--ng-doc-kind-icon-background);background:color-mix(in srgb,var(--ng-doc-kind-icon-background) var(--ng-doc-kind-icon-background-opacity, 15%),transparent)}:host[data-ng-doc-size=small]{width:calc(var(--ng-doc-base-gutter) * 2);height:calc(var(--ng-doc-base-gutter) * 2);line-height:calc(var(--ng-doc-base-gutter) * 2)}: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 }); }
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.0.6", ngImport: i0, type: NgDocKindIconComponent, decorators: [{
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: '{{kind[0]}}', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [":host{display:inline-block;width:22px;height:22px;border-radius:calc(var(--ng-doc-base-gutter) / 2);font-size:13px;text-align:center;line-height:22px;text-transform:uppercase;flex-shrink:0;font-weight:700;color:var(--ng-doc-kind-icon-background);background:color-mix(in srgb,var(--ng-doc-kind-icon-background) var(--ng-doc-kind-icon-background-opacity, 15%),transparent)}:host[data-ng-doc-size=small]{width:calc(var(--ng-doc-base-gutter) * 2);height:calc(var(--ng-doc-base-gutter) * 2);line-height:calc(var(--ng-doc-base-gutter) * 2)}: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"] }]
16
- }], propDecorators: { kind: [{
17
- type: Input
18
- }, {
19
- type: HostBinding,
20
- args: ['attr.data-ng-doc-kind']
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