@ng-doc/app 22.0.0 → 22.1.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 (50) hide show
  1. package/fesm2022/ng-doc-app-classes-root-page.mjs.map +1 -1
  2. package/fesm2022/ng-doc-app-components-demo-frame.mjs +96 -0
  3. package/fesm2022/ng-doc-app-components-demo-frame.mjs.map +1 -0
  4. package/fesm2022/ng-doc-app-components-demo-pane.mjs +1 -1
  5. package/fesm2022/ng-doc-app-components-demo-pane.mjs.map +1 -1
  6. package/fesm2022/ng-doc-app-components-demo.mjs +54 -8
  7. package/fesm2022/ng-doc-app-components-demo.mjs.map +1 -1
  8. package/fesm2022/ng-doc-app-components-playground.mjs +109 -47
  9. package/fesm2022/ng-doc-app-components-playground.mjs.map +1 -1
  10. package/fesm2022/ng-doc-app-components-tabs.mjs +21 -3
  11. package/fesm2022/ng-doc-app-components-tabs.mjs.map +1 -1
  12. package/fesm2022/ng-doc-app-components.mjs +1 -0
  13. package/fesm2022/ng-doc-app-components.mjs.map +1 -1
  14. package/fesm2022/ng-doc-app-demo-app.mjs +176 -0
  15. package/fesm2022/ng-doc-app-demo-app.mjs.map +1 -0
  16. package/fesm2022/ng-doc-app-helpers.mjs +23 -2
  17. package/fesm2022/ng-doc-app-helpers.mjs.map +1 -1
  18. package/fesm2022/ng-doc-app-processors-processors.mjs +30 -9
  19. package/fesm2022/ng-doc-app-processors-processors.mjs.map +1 -1
  20. package/fesm2022/ng-doc-app-providers-ng-doc-app.mjs.map +1 -1
  21. package/fesm2022/ng-doc-app-providers-title.mjs +129 -0
  22. package/fesm2022/ng-doc-app-providers-title.mjs.map +1 -0
  23. package/fesm2022/ng-doc-app-providers.mjs +1 -0
  24. package/fesm2022/ng-doc-app-providers.mjs.map +1 -1
  25. package/fesm2022/ng-doc-app-services-highlighter.mjs +17 -13
  26. package/fesm2022/ng-doc-app-services-highlighter.mjs.map +1 -1
  27. package/fesm2022/ng-doc-app-services-route-preloader.mjs +34 -10
  28. package/fesm2022/ng-doc-app-services-route-preloader.mjs.map +1 -1
  29. package/fesm2022/ng-doc-app-type-controls-type-alias-control.mjs +43 -8
  30. package/fesm2022/ng-doc-app-type-controls-type-alias-control.mjs.map +1 -1
  31. package/package.json +17 -4
  32. package/styles/global.css +3 -0
  33. package/styles/main.css +3 -0
  34. package/styles/themes/dark.css +10 -0
  35. package/types/ng-doc-app-classes-root-page.d.ts +8 -0
  36. package/types/ng-doc-app-components-demo-frame.d.ts +48 -0
  37. package/types/ng-doc-app-components-demo.d.ts +20 -2
  38. package/types/ng-doc-app-components-playground.d.ts +24 -3
  39. package/types/ng-doc-app-components-tabs.d.ts +13 -3
  40. package/types/ng-doc-app-components.d.ts +1 -0
  41. package/types/ng-doc-app-demo-app.d.ts +89 -0
  42. package/types/ng-doc-app-helpers.d.ts +21 -3
  43. package/types/ng-doc-app-interfaces.d.ts +15 -4
  44. package/types/ng-doc-app-processors-processors.d.ts +5 -0
  45. package/types/ng-doc-app-providers-ng-doc-app.d.ts +1 -1
  46. package/types/ng-doc-app-providers-title.d.ts +59 -0
  47. package/types/ng-doc-app-providers.d.ts +1 -0
  48. package/types/ng-doc-app-services-highlighter.d.ts +12 -5
  49. package/types/ng-doc-app-services-route-preloader.d.ts +13 -1
  50. package/types/ng-doc-app-type-controls-type-alias-control.d.ts +26 -4
@@ -1 +1 @@
1
- {"version":3,"file":"ng-doc-app-type-controls-type-alias-control.mjs","sources":["../../../../libs/app/type-controls/type-alias-control/type-alias-control.component.ts","../../../../libs/app/type-controls/type-alias-control/type-alias-control.component.html","../../../../libs/app/type-controls/type-alias-control/ng-doc-app-type-controls-type-alias-control.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { NgDocTypeControl } from '@ng-doc/app/interfaces';\nimport { NgDocExtractValuePipe } from '@ng-doc/app/pipes/extract-value';\nimport {\n NgDocButtonIconComponent,\n NgDocComboboxComponent,\n NgDocDataDirective,\n NgDocFocusableDirective,\n NgDocIconComponent,\n NgDocListComponent,\n NgDocOptionComponent,\n} from '@ng-doc/ui-kit';\nimport { DIControl } from 'di-controls';\n\n/**\n * The playground control of union type aliases: a select that shows the value and whether it is\n * the default. The inspector shows the value type under the input's name.\n */\n@Component({\n selector: 'ng-doc-type-alias-control',\n templateUrl: './type-alias-control.component.html',\n styleUrls: ['./type-alias-control.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgDocComboboxComponent,\n FormsModule,\n NgDocDataDirective,\n NgDocListComponent,\n NgDocOptionComponent,\n NgTemplateOutlet,\n NgDocButtonIconComponent,\n NgDocFocusableDirective,\n NgDocIconComponent,\n NgDocExtractValuePipe,\n ],\n})\nexport class NgDocTypeAliasControlComponent<T> extends DIControl<T> implements NgDocTypeControl<T> {\n /** Default value of the input; clearing the selection returns to it. */\n readonly default = input<T | undefined>(undefined);\n\n /** Values the input accepts: literal source text, or plain values when `isManual` is set. */\n readonly options = input<string[] | undefined>(undefined);\n\n /** Whether `options` are values the user listed in the playground config. */\n readonly isManual = input<boolean | undefined>(undefined);\n\n constructor() {\n super();\n }\n\n typeOf(value: unknown): string {\n return typeof value;\n }\n\n changeModel(value: T | null): void {\n const defaultValue: T | undefined = this.default();\n\n this.updateModel(value === null && defaultValue ? defaultValue : value);\n }\n}\n","<ng-doc-combobox\n [ngModel]=\"model()\"\n [readonly]=\"true\"\n [valueContent]=\"valueTemplate\"\n [clearButton]=\"false\"\n [rightContent]=\"rightContent\"\n (ngModelChange)=\"changeModel($event)\">\n <ng-doc-list *ngDocData>\n @for (option of options(); track option) {\n @if (isManual() ? option : (option | ngDocExtractValue); as value) {\n <ng-doc-option [value]=\"value\">\n <ng-container\n *ngTemplateOutlet=\"valueTemplate; context: { $implicit: value }\"></ng-container>\n </ng-doc-option>\n }\n }\n </ng-doc-list>\n <ng-template let-value #valueTemplate>\n <div class=\"ng-doc-type-alias-value\">\n <span class=\"ng-doc-type-alias-value-text\">{{ value }}</span>\n @if (value === default()) {\n <span class=\"ng-doc-type-alias-default\">default</span>\n }\n </div>\n </ng-template>\n <ng-template #rightContent>\n @if (model() && model() !== default()) {\n <button\n ng-doc-button-icon-transparent\n size=\"large\"\n aria-label=\"Reset to the default value\"\n [ngDocFocusable]=\"false\"\n [disabled]=\"disabled\"\n [rounded]=\"false\"\n (click)=\"updateModel(default() ?? null)\"\n (focusout)=\"touch()\">\n <ng-doc-icon icon=\"x\"></ng-doc-icon>\n </button>\n }\n </ng-template>\n</ng-doc-combobox>\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-type-controls-type-alias-control.mjs","sources":["../../../../libs/app/type-controls/type-alias-control/type-alias-control.component.ts","../../../../libs/app/type-controls/type-alias-control/type-alias-control.component.html","../../../../libs/app/type-controls/type-alias-control/ng-doc-app-type-controls-type-alias-control.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, input, Signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { NgDocResolvedPlaygroundOption, resolvePlaygroundOption } from '@ng-doc/app/helpers';\nimport { NgDocTypeControl } from '@ng-doc/app/interfaces';\nimport { NgDocPlaygroundOption } from '@ng-doc/core/interfaces';\nimport {\n NgDocButtonIconComponent,\n NgDocComboboxComponent,\n NgDocDataDirective,\n NgDocFocusableDirective,\n NgDocIconComponent,\n NgDocListComponent,\n NgDocOptionComponent,\n} from '@ng-doc/ui-kit';\nimport { DIControl } from 'di-controls';\n\n/**\n * The playground control of union type aliases and enums: a select that shows the value (or the\n * name of an enum member) and whether it is the default. The inspector shows the value type under\n * the input's name.\n */\n@Component({\n selector: 'ng-doc-type-alias-control',\n templateUrl: './type-alias-control.component.html',\n styleUrls: ['./type-alias-control.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgDocComboboxComponent,\n FormsModule,\n NgDocDataDirective,\n NgDocListComponent,\n NgDocOptionComponent,\n NgTemplateOutlet,\n NgDocButtonIconComponent,\n NgDocFocusableDirective,\n NgDocIconComponent,\n ],\n})\nexport class NgDocTypeAliasControlComponent<T> extends DIControl<T> implements NgDocTypeControl<T> {\n /** Default value of the input; clearing the selection returns to it. */\n readonly default = input<T | undefined>(undefined);\n\n /**\n * Values the input accepts: literal source text, plain values when `isManual` is set, or the\n * names and values of enum members.\n */\n readonly options = input<Array<string | NgDocPlaygroundOption> | undefined>(undefined);\n\n /** Whether `options` are values the user listed in the playground config. */\n readonly isManual = input<boolean | undefined>(undefined);\n\n /**\n * The options of the select. `undefined` and `null` get no option: clearing the selection\n * returns to the default value instead.\n */\n protected readonly items: Signal<NgDocResolvedPlaygroundOption[]> = computed(() => {\n const isManual: boolean | undefined = this.isManual();\n\n return (this.options() ?? []).flatMap((option: string | NgDocPlaygroundOption) => {\n try {\n const item: NgDocResolvedPlaygroundOption = resolvePlaygroundOption(option, isManual);\n\n return item.value === undefined || item.value === null ? [] : [item];\n } catch {\n return [];\n }\n });\n });\n\n constructor() {\n super();\n }\n\n typeOf(value: unknown): string {\n return typeof value;\n }\n\n /**\n * The text of a value: the name of its option, such as the name of an enum member.\n * @param value - A value of the input.\n */\n labelOf(value: unknown): string {\n return (\n this.items().find((item: NgDocResolvedPlaygroundOption) => item.value === value)?.label ??\n String(value ?? '')\n );\n }\n\n /**\n * Whether the reset button is shown: a value other than the default is selected.\n * @param value - The selected value.\n */\n protected canReset(value: T | null): boolean {\n return value !== undefined && value !== null && value !== this.default();\n }\n\n changeModel(value: T | null): void {\n const defaultValue: T | undefined = this.default();\n\n this.updateModel(value === null && defaultValue ? defaultValue : value);\n }\n}\n","<ng-doc-combobox\n [ngModel]=\"model()\"\n [readonly]=\"true\"\n [valueContent]=\"valueTemplate\"\n [clearButton]=\"false\"\n [rightContent]=\"rightContent\"\n (ngModelChange)=\"changeModel($event)\">\n <ng-doc-list *ngDocData>\n @for (item of items(); track $index) {\n <ng-doc-option [value]=\"item.value\">\n <ng-container\n *ngTemplateOutlet=\"valueTemplate; context: { $implicit: item.value }\"></ng-container>\n </ng-doc-option>\n }\n </ng-doc-list>\n <ng-template let-value #valueTemplate>\n <div class=\"ng-doc-type-alias-value\">\n <span class=\"ng-doc-type-alias-value-text\">{{ labelOf(value) }}</span>\n @if (value === default()) {\n <span class=\"ng-doc-type-alias-default\">default</span>\n }\n </div>\n </ng-template>\n <ng-template #rightContent>\n @if (canReset(model())) {\n <button\n ng-doc-button-icon-transparent\n size=\"large\"\n aria-label=\"Reset to the default value\"\n [ngDocFocusable]=\"false\"\n [disabled]=\"disabled\"\n [rounded]=\"false\"\n (click)=\"updateModel(default() ?? null)\"\n (focusout)=\"touch()\">\n <ng-doc-icon icon=\"x\"></ng-doc-icon>\n </button>\n }\n </ng-template>\n</ng-doc-combobox>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-doc/app",
3
- "version": "22.0.0",
3
+ "version": "22.1.0",
4
4
  "description": "The NgDoc documentation site: layout, navigation, search, demos, playgrounds and API pages.",
5
5
  "keywords": [
6
6
  "angular",
@@ -32,11 +32,12 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "tslib": "^2.6.2",
35
- "@ng-doc/core": "22.0.0",
36
- "@ng-doc/ui-kit": "22.0.0",
35
+ "@ng-doc/core": "22.1.0",
36
+ "@ng-doc/ui-kit": "22.1.0",
37
37
  "@orama/plugin-match-highlight": "2.0.17",
38
38
  "@orama/stemmers": "2.0.17",
39
- "mermaid": "10.9.8"
39
+ "mermaid": "10.9.8",
40
+ "shiki": "4.5.0"
40
41
  },
41
42
  "publishConfig": {
42
43
  "access": "public"
@@ -114,6 +115,10 @@
114
115
  "types": "./types/ng-doc-app-components-demo-displayer.d.ts",
115
116
  "default": "./fesm2022/ng-doc-app-components-demo-displayer.mjs"
116
117
  },
118
+ "./components/demo-frame": {
119
+ "types": "./types/ng-doc-app-components-demo-frame.d.ts",
120
+ "default": "./fesm2022/ng-doc-app-components-demo-frame.mjs"
121
+ },
117
122
  "./components/demo-pane": {
118
123
  "types": "./types/ng-doc-app-components-demo-pane.d.ts",
119
124
  "default": "./fesm2022/ng-doc-app-components-demo-pane.mjs"
@@ -222,6 +227,10 @@
222
227
  "types": "./types/ng-doc-app-defaults-default-skeleton.d.ts",
223
228
  "default": "./fesm2022/ng-doc-app-defaults-default-skeleton.mjs"
224
229
  },
230
+ "./demo-app": {
231
+ "types": "./types/ng-doc-app-demo-app.d.ts",
232
+ "default": "./fesm2022/ng-doc-app-demo-app.mjs"
233
+ },
225
234
  "./directives": {
226
235
  "types": "./types/ng-doc-app-directives.d.ts",
227
236
  "default": "./fesm2022/ng-doc-app-directives.mjs"
@@ -310,6 +319,10 @@
310
319
  "types": "./types/ng-doc-app-providers-search-engine.d.ts",
311
320
  "default": "./fesm2022/ng-doc-app-providers-search-engine.mjs"
312
321
  },
322
+ "./providers/title": {
323
+ "types": "./types/ng-doc-app-providers-title.d.ts",
324
+ "default": "./fesm2022/ng-doc-app-providers-title.mjs"
325
+ },
313
326
  "./providers/type-control": {
314
327
  "types": "./types/ng-doc-app-providers-type-control.d.ts",
315
328
  "default": "./fesm2022/ng-doc-app-providers-type-control.mjs"
package/styles/global.css CHANGED
@@ -176,6 +176,9 @@ pre.shiki code {
176
176
  }
177
177
  pre.shiki code span {
178
178
  background-color: var(--ng-doc-code-background, inherit) !important;
179
+ font-style: var(--shiki-light-font-style);
180
+ font-weight: var(--shiki-light-font-weight);
181
+ text-decoration: var(--shiki-light-text-decoration);
179
182
  }
180
183
 
181
184
  *:not(pre) > code.ngde {
package/styles/main.css CHANGED
@@ -176,6 +176,9 @@ pre.shiki code {
176
176
  }
177
177
  pre.shiki code span {
178
178
  background-color: var(--ng-doc-code-background, inherit) !important;
179
+ font-style: var(--shiki-light-font-style);
180
+ font-weight: var(--shiki-light-font-weight);
181
+ text-decoration: var(--shiki-light-text-decoration);
179
182
  }
180
183
 
181
184
  *:not(pre) > code.ngde {
@@ -44,6 +44,11 @@
44
44
  :root[data-theme=auto] .shiki span {
45
45
  color: var(--shiki-dark) !important;
46
46
  }
47
+ :root[data-theme=auto] .shiki span {
48
+ font-style: var(--shiki-dark-font-style) !important;
49
+ font-weight: var(--shiki-dark-font-weight) !important;
50
+ text-decoration: var(--shiki-dark-text-decoration) !important;
51
+ }
47
52
  }
48
53
 
49
54
  :root[data-theme=dark] {
@@ -91,3 +96,8 @@
91
96
  :root[data-theme=dark] .shiki span {
92
97
  color: var(--shiki-dark) !important;
93
98
  }
99
+ :root[data-theme=dark] .shiki span {
100
+ font-style: var(--shiki-dark-font-style) !important;
101
+ font-weight: var(--shiki-dark-font-weight) !important;
102
+ text-decoration: var(--shiki-dark-text-decoration) !important;
103
+ }
@@ -35,6 +35,14 @@ declare abstract class NgDocRootPage {
35
35
  * The page demo assets that have code examples of the demo components
36
36
  */
37
37
  readonly demoAssets?: NgDocDemoAssets;
38
+ /**
39
+ * The path of the page's demo pages, relative to the base href, when the Vite engine built them:
40
+ * the demo `X` has its page at `<base href><demoRoute>/X`. Isolated demos show it in an iframe,
41
+ * and the demo toolbar opens it in a new tab.
42
+ */
43
+ readonly demoRoute?: string;
44
+ /** Whether the page's demos are isolated unless their `demo` action says otherwise (`isolatedDemos`). */
45
+ readonly isolatedDemos?: boolean;
38
46
  }
39
47
 
40
48
  export { NgDocRootPage };
@@ -0,0 +1,48 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { Signal } from '@angular/core';
3
+ import { SafeResourceUrl } from '@angular/platform-browser';
4
+
5
+ /**
6
+ * Shows a demo page of the demo application in an iframe, as tall as the demo's content: the demo
7
+ * page reports its height with `postMessage`, and only messages from this iframe's window and
8
+ * origin are accepted. The iframe is created in the browser after the first render (the server
9
+ * renders a placeholder with a link to the demo page) and loads lazily. Until the demo reports its
10
+ * size, a placeholder tells that it is loading; a demo page that loads without reporting it within
11
+ * 10 seconds is reported as failed, with the link.
12
+ */
13
+ declare class NgDocDemoFrameComponent {
14
+ /** The URL of the demo page, relative to the document or absolute on its origin. */
15
+ readonly src: _angular_core.InputSignal<string>;
16
+ /** The accessible title of the iframe. */
17
+ readonly frameTitle: _angular_core.InputSignal<string>;
18
+ /** Whether the iframe fills its container instead of taking the demo's height (fullscreen). */
19
+ readonly fill: _angular_core.InputSignal<boolean>;
20
+ /** The height the demo reported, in pixels. */
21
+ readonly height: _angular_core.WritableSignal<number | undefined>;
22
+ /** `loading` until the demo reports its size, then `ready`; `failed` when it never does. */
23
+ readonly state: Signal<'loading' | 'ready' | 'failed'>;
24
+ /** Whether the iframe exists: only in the browser, after the first render. */
25
+ protected readonly created: _angular_core.WritableSignal<boolean>;
26
+ /** The demo page's URL for the iframe. */
27
+ protected readonly frameSrc: Signal<SafeResourceUrl>;
28
+ private readonly sanitizer;
29
+ private readonly frame;
30
+ private readonly failed;
31
+ private timer?;
32
+ constructor();
33
+ /**
34
+ * Waits for the demo's size once its page has loaded.
35
+ * @internal
36
+ */
37
+ protected onLoad(): void;
38
+ /**
39
+ * Takes the height a demo page reports, from this iframe only.
40
+ * @param event - A message to the window.
41
+ * @internal
42
+ */
43
+ protected onMessage(event: MessageEvent): void;
44
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgDocDemoFrameComponent, never>;
45
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgDocDemoFrameComponent, "ng-doc-demo-frame", never, { "src": { "alias": "src"; "required": true; "isSignal": true; }; "frameTitle": { "alias": "frameTitle"; "required": true; "isSignal": true; }; "fill": { "alias": "fill"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
46
+ }
47
+
48
+ export { NgDocDemoFrameComponent };
@@ -11,18 +11,36 @@ type NgDocDemoPreviewWidth = 'full' | '480' | '280';
11
11
  * shows the stage fullscreen with the browser Fullscreen API; it is hidden where the browser does
12
12
  * not support it.
13
13
  *
14
- * The preview widths set the width of the demo's container; they do not emulate a device, so
15
- * media queries inside the demo do not respond to them.
14
+ * When the Vite engine built demo pages for the page (`NgDocRootPage.demoRoute`), the toolbar
15
+ * opens the demo's page in a new tab, and an isolated demo (the `isolated` option, or
16
+ * `isolatedDemos`) is shown in an iframe of its page: the preview widths are then the width of the
17
+ * iframe's viewport, so media queries inside the demo respond to them. Otherwise the demo renders
18
+ * in the page, and the preview widths set the width of its container only.
16
19
  */
17
20
  declare class NgDocDemoComponent {
18
21
  private readonly rootPage;
19
22
  private readonly document;
23
+ private readonly platformLocation;
24
+ private readonly appBaseHref;
20
25
  /** Name of the demo component in the page's `demos`. */
21
26
  readonly componentName: _angular_core.InputSignal<string | undefined>;
22
27
  /** Options of the `demo` action. */
23
28
  readonly options: _angular_core.InputSignal<NgDocDemoActionOptions>;
24
29
  /** The demo component. */
25
30
  readonly demo: Signal<Type<unknown> | undefined>;
31
+ /**
32
+ * The URL of the demo's page, when the page has demo pages and the demo exists: the generated
33
+ * demo route and the demo's name under the base href, with the `inputs` option as a query
34
+ * parameter.
35
+ */
36
+ readonly demoUrl: Signal<string | undefined>;
37
+ /** Whether the demo is shown in an iframe of its page. */
38
+ readonly isolated: Signal<boolean>;
39
+ /** The accessible title of the demo's iframe. */
40
+ protected readonly frameTitle: Signal<string>;
41
+ /** Whether the stage is fullscreen. */
42
+ protected readonly fullscreen: Signal<boolean>;
43
+ private readonly stage;
26
44
  /** Source files of the demo, filtered by the `tabs` option. */
27
45
  readonly assets: Signal<NgDocDemoAsset[]>;
28
46
  /**
@@ -64,14 +64,19 @@ declare class NgDocPlaygroundComponent<T extends NgDocPlaygroundProperties = NgD
64
64
  readonly properties: InputSignal<T | undefined>;
65
65
  /** Options of the playground action; they extend the playground configuration. */
66
66
  readonly options: InputSignal<NgDocPlaygroundOptions>;
67
- /** Whether the demo is created again each time a value changes. */
68
- readonly recreateDemo: WritableSignal<boolean>;
69
67
  /** The values of the inputs and content slots. */
70
68
  readonly formGroup: WritableSignal<FormGroup<NgDocPlaygroundForm> | undefined>;
71
69
  /** The default values of the target's inputs, reported by the first demo. */
72
70
  readonly defaultValues: WritableSignal<Record<string, unknown> | undefined>;
73
71
  /** The playground configuration of the page, extended by the options. */
74
72
  readonly configuration: Signal<NgDocPlaygroundConfig>;
73
+ /**
74
+ * Whether the demo is created again each time a value changes. It starts from the `recreate`
75
+ * option; the reader can change it unless the option is `'always'`.
76
+ */
77
+ readonly recreateDemo: WritableSignal<boolean>;
78
+ /** Whether the Recreate setting is fixed on, and hidden, by the `'always'` option. */
79
+ readonly recreateLocked: Signal<boolean>;
75
80
  private defaultProperties;
76
81
  private defaultContent;
77
82
  ngAfterViewInit(): void;
@@ -155,12 +160,19 @@ declare class NgDocPlaygroundPropertiesComponent<P extends NgDocPlaygroundProper
155
160
  readonly inspectorPosition: _angular_core.InputSignal<"right" | "bottom">;
156
161
  /** Whether the demo is recreated each time an input changes. */
157
162
  readonly recreateDemo: _angular_core.ModelSignal<boolean>;
163
+ /** Whether the Recreate setting is fixed by the playground's options and hidden. */
164
+ readonly recreateLocked: _angular_core.InputSignal<boolean>;
158
165
  /** Whether the Reset button is shown. */
159
166
  readonly showResetButton: _angular_core.InputSignal<boolean>;
160
167
  /** Emits when the reader resets the form. */
161
168
  readonly resetForm: _angular_core.OutputEmitterRef<void>;
162
169
  /** The control of each input, in display order. */
163
170
  protected readonly propertyControls: Signal<NgDocPlaygroundPropertyControl[]>;
171
+ /**
172
+ * The controls in sections: the inputs without a group first, then a section per group, in the
173
+ * order of the group's first input.
174
+ */
175
+ protected readonly propertySections: Signal<NgDocPlaygroundPropertySection[]>;
164
176
  /** The control of content slots. */
165
177
  protected readonly contentTypeControl?: NgDocProvidedTypeControl;
166
178
  /**
@@ -173,7 +185,12 @@ declare class NgDocPlaygroundPropertiesComponent<P extends NgDocPlaygroundProper
173
185
  private getControlForType;
174
186
  private getControlForTypeAlias;
175
187
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgDocPlaygroundPropertiesComponent<any, any>, never>;
176
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgDocPlaygroundPropertiesComponent<any, any>, "ng-doc-playground-properties", never, { "form": { "alias": "form"; "required": true; "isSignal": true; }; "properties": { "alias": "properties"; "required": false; "isSignal": true; }; "ignoreInputs": { "alias": "ignoreInputs"; "required": false; "isSignal": true; }; "dynamicContent": { "alias": "dynamicContent"; "required": false; "isSignal": true; }; "defaultValues": { "alias": "defaultValues"; "required": false; "isSignal": true; }; "hideSidePanel": { "alias": "hideSidePanel"; "required": false; "isSignal": true; }; "inspectorPosition": { "alias": "inspectorPosition"; "required": false; "isSignal": true; }; "recreateDemo": { "alias": "recreateDemo"; "required": false; "isSignal": true; }; "showResetButton": { "alias": "showResetButton"; "required": false; "isSignal": true; }; }, { "recreateDemo": "recreateDemoChange"; "resetForm": "resetForm"; }, never, ["*"], true, never>;
188
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgDocPlaygroundPropertiesComponent<any, any>, "ng-doc-playground-properties", never, { "form": { "alias": "form"; "required": true; "isSignal": true; }; "properties": { "alias": "properties"; "required": false; "isSignal": true; }; "ignoreInputs": { "alias": "ignoreInputs"; "required": false; "isSignal": true; }; "dynamicContent": { "alias": "dynamicContent"; "required": false; "isSignal": true; }; "defaultValues": { "alias": "defaultValues"; "required": false; "isSignal": true; }; "hideSidePanel": { "alias": "hideSidePanel"; "required": false; "isSignal": true; }; "inspectorPosition": { "alias": "inspectorPosition"; "required": false; "isSignal": true; }; "recreateDemo": { "alias": "recreateDemo"; "required": false; "isSignal": true; }; "recreateLocked": { "alias": "recreateLocked"; "required": false; "isSignal": true; }; "showResetButton": { "alias": "showResetButton"; "required": false; "isSignal": true; }; }, { "recreateDemo": "recreateDemoChange"; "resetForm": "resetForm"; }, never, ["*"], true, never>;
189
+ }
190
+ /** A titled list of controls in the inspector. */
191
+ interface NgDocPlaygroundPropertySection {
192
+ title: string;
193
+ controls: NgDocPlaygroundPropertyControl[];
177
194
  }
178
195
 
179
196
  /**
@@ -199,6 +216,10 @@ declare class NgDocPlaygroundPropertyComponent {
199
216
  protected readonly option: Signal<NgDocTypeControlProviderOptions | undefined>;
200
217
  /** The value type shown as a chip under the name, or an empty string. */
201
218
  protected readonly typeChip: Signal<string>;
219
+ /** Whether the row is a `<label>` around the control, unless its provider opts out. */
220
+ protected readonly labelWrapper: Signal<boolean>;
221
+ /** ID of the caption that names the control of a row without the `<label>`. */
222
+ protected readonly captionId: string;
202
223
  private readonly propertyOutlet;
203
224
  private propertyTypeControl?;
204
225
  constructor();
@@ -1,13 +1,23 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Signal } from '@angular/core';
2
+ import { OnInit, Signal } from '@angular/core';
3
3
  import { NgDocTab } from '@ng-doc/app/interfaces';
4
4
 
5
- /** Grouped code blocks of a page, shown as tabs. */
6
- declare class NgDocTabsComponent {
5
+ /**
6
+ * Tabs of a page: grouped code blocks, or any content that Markdown wraps in
7
+ * `<ng-doc-tab group="…" name="…">` elements.
8
+ */
9
+ declare class NgDocTabsComponent implements OnInit {
7
10
  /** The tabs; their content is moved into the open panel. */
8
11
  readonly tabs: i0.InputSignal<NgDocTab[]>;
9
12
  /** Index of the tab that opens first: the one marked active, or the first. */
10
13
  protected readonly activeIndex: Signal<number>;
14
+ /**
15
+ * Whether the tabs hold page content rather than a code group. A code group has one code block
16
+ * per tab and is drawn as one framed code surface; content tabs are only a tab bar over their
17
+ * content, so a framed demo or code block inside them doesn't sit in a second frame.
18
+ */
19
+ protected readonly contentTabs: Signal<boolean>;
20
+ ngOnInit(): void;
11
21
  /**
12
22
  * Moves a tab's content into its panel.
13
23
  * @param element - Content of the tab.
@@ -5,6 +5,7 @@ export * from '@ng-doc/app/components/command-palette';
5
5
  export * from '@ng-doc/app/components/copy-button';
6
6
  export * from '@ng-doc/app/components/demo';
7
7
  export * from '@ng-doc/app/components/demo-displayer';
8
+ export * from '@ng-doc/app/components/demo-frame';
8
9
  export * from '@ng-doc/app/components/demo-pane';
9
10
  export * from '@ng-doc/app/components/fullscreen-button';
10
11
  export * from '@ng-doc/app/components/fullscreen-toggle';
@@ -0,0 +1,89 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Provider, EnvironmentProviders, ApplicationConfig, Type } from '@angular/core';
3
+ import { Routes } from '@angular/router';
4
+ import { NgDocDemoProvidersImport } from '@ng-doc/core/interfaces';
5
+
6
+ /**
7
+ * The root of the demo application, which shows one demo per page with only Angular and that
8
+ * demo loaded. In an iframe it reports the height of its content to the page that embeds it (a
9
+ * `ResizeObserver` on its border box), and it follows the theme the reader picks on the
10
+ * documentation site, which stores it in `localStorage`.
11
+ */
12
+ declare class NgDocDemoAppComponent {
13
+ constructor();
14
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgDocDemoAppComponent, never>;
15
+ static ɵcmp: i0.ɵɵComponentDeclaration<NgDocDemoAppComponent, "ng-doc-demo-app", never, {}, {}, never, never, true, never>;
16
+ }
17
+
18
+ /**
19
+ * How the demo application starts.
20
+ * @internal
21
+ */
22
+ interface ɵNgDocDemoApplicationOptions {
23
+ /** Change detection with zone.js, when the application's polyfills load it. */
24
+ readonly zone?: boolean;
25
+ /**
26
+ * Hydration of the server-rendered page: always on the server, which then writes the hydration
27
+ * data, and in the browser only for a page the server rendered (a page without it, such as the
28
+ * page of a demo that failed to prerender or the development server's, has nothing to hydrate).
29
+ */
30
+ readonly hydration?: boolean;
31
+ /** Providers added after the others, for example server rendering. */
32
+ readonly providers?: Array<Provider | EnvironmentProviders>;
33
+ }
34
+ /**
35
+ * The configuration of the demo application: change detection, the router with the demo pages
36
+ * (and a page for unknown demos), hydration, and the providers of `demoProviders`. The generated entries of
37
+ * the demo application bootstrap `NgDocDemoAppComponent` with it, in the browser and on the server.
38
+ * @param routes - The generated demo routes.
39
+ * @param demoProviders - The generated import of the `demoProviders` module, if any.
40
+ * @param options - How the application starts.
41
+ * @internal
42
+ */
43
+ declare function ɵngDocDemoApplicationConfig(routes: Routes, demoProviders: NgDocDemoProvidersImport | undefined, options?: ɵNgDocDemoApplicationOptions): Promise<ApplicationConfig>;
44
+
45
+ /**
46
+ * Shows the demo of a demo page: the component in the route's `ngDocDemo` data, with the inputs
47
+ * of the `inputs` query parameter (the JSON of the `inputs` option of the `demo` action).
48
+ *
49
+ * The demo application hydrates its server-rendered page, but not the demo: a demo is the user's
50
+ * component and need not be hydration-safe, and the server renders it without the inputs of the
51
+ * query, which only the browser has. So the host skips hydration, as documentation pages do for
52
+ * their content, and the browser renders the demo again.
53
+ */
54
+ declare class NgDocDemoHostComponent {
55
+ private readonly route;
56
+ /** The demo component, or undefined on the page of a demo that does not exist. */
57
+ protected readonly demo: Type<unknown> | undefined;
58
+ /** The inputs of the demo. */
59
+ protected readonly inputs: Record<string, unknown>;
60
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgDocDemoHostComponent, never>;
61
+ static ɵcmp: i0.ɵɵComponentDeclaration<NgDocDemoHostComponent, "ng-doc-demo-host", never, {}, {}, never, never, true, never>;
62
+ }
63
+
64
+ /**
65
+ * The `source` of every message the demo application sends to the page that embeds it.
66
+ * @internal
67
+ */
68
+ declare const ɵNG_DOC_DEMO_MESSAGE_SOURCE = "ng-doc-demo";
69
+ /**
70
+ * The message an isolated demo sends to the page that shows it in an iframe whenever the height
71
+ * of its content changes, so that the iframe takes that height.
72
+ * @internal
73
+ */
74
+ interface ɵNgDocDemoSizeMessage {
75
+ readonly source: typeof ɵNG_DOC_DEMO_MESSAGE_SOURCE;
76
+ readonly version: 1;
77
+ readonly type: 'size';
78
+ /** The height of the demo's content, in CSS pixels, rounded up. */
79
+ readonly height: number;
80
+ }
81
+ /**
82
+ * Whether a message is a size message of the demo application.
83
+ * @param value - The data of a `message` event.
84
+ * @internal
85
+ */
86
+ declare function ɵisNgDocDemoSizeMessage(value: unknown): value is ɵNgDocDemoSizeMessage;
87
+
88
+ export { NgDocDemoAppComponent, NgDocDemoHostComponent, ɵNG_DOC_DEMO_MESSAGE_SOURCE, ɵisNgDocDemoSizeMessage, ɵngDocDemoApplicationConfig };
89
+ export type { ɵNgDocDemoApplicationOptions, ɵNgDocDemoSizeMessage };
@@ -1,6 +1,6 @@
1
1
  import { InjectionToken, ApplicationRef, ViewContainerRef, Type } from '@angular/core';
2
2
  import { Route } from '@angular/router';
3
- import { NgDocContentSource, NgDocContentModule, NgDocPlaygroundProperty } from '@ng-doc/core/interfaces';
3
+ import { NgDocContentSource, NgDocContentModule, NgDocPlaygroundProperty, NgDocPlaygroundOption } from '@ng-doc/core/interfaces';
4
4
  import { NgDocTocItem } from '@ng-doc/app/interfaces';
5
5
  import { LocationStrategy } from '@angular/common';
6
6
 
@@ -166,5 +166,23 @@ declare function ɵngDocRouteUrl(locationStrategy: LocationStrategy, documentUrl
166
166
  */
167
167
  declare function ɵngDocPageUrl(locationStrategy: LocationStrategy, location: Pick<Location, 'href' | 'origin' | 'pathname'>, fragment?: string): string;
168
168
 
169
- export { asBoolean, createComponent, formatHtml, generateToc, isDarkOsTheme, isExternalLink, isPlaygroundProperty, withNgDocContentReady, ɵNG_DOC_ASYNC_CONTENT_ATTRIBUTE, ɵNG_DOC_CONTENT_WAIT, ɵcaptureNgDocHydrationSnapshots, ɵforgetNgDocContent, ɵngDocPageUrl, ɵngDocRouteContentSources, ɵngDocRouteUrl, ɵpeekNgDocContent, ɵpendingNgDocContent, ɵpreloadNgDocContent, ɵrestoreNgDocHydrationSnapshot, ɵwithNgDocContent };
170
- export type { NgDocBootstrap };
169
+ /** An option of a playground property, resolved to the value it sets and the text it shows. */
170
+ interface NgDocResolvedPlaygroundOption {
171
+ /** The text shown for the option. */
172
+ label: string;
173
+ /** The value the option sets. */
174
+ value: unknown;
175
+ }
176
+ /**
177
+ * Resolves an option of a playground property. A named option (an enum member) carries its
178
+ * value; a plain value from the playground's `controls` is the value itself; any other option is
179
+ * the source text of a union member, such as `'small'`, and is evaluated; it throws when that
180
+ * text can't be evaluated.
181
+ * @param option - The option.
182
+ * @param isManual - Whether the options come from the playground's `controls`.
183
+ * @returns The value of the option and the text that shows it.
184
+ */
185
+ declare function resolvePlaygroundOption(option: string | NgDocPlaygroundOption, isManual?: boolean): NgDocResolvedPlaygroundOption;
186
+
187
+ export { asBoolean, createComponent, formatHtml, generateToc, isDarkOsTheme, isExternalLink, isPlaygroundProperty, resolvePlaygroundOption, withNgDocContentReady, ɵNG_DOC_ASYNC_CONTENT_ATTRIBUTE, ɵNG_DOC_CONTENT_WAIT, ɵcaptureNgDocHydrationSnapshots, ɵforgetNgDocContent, ɵngDocPageUrl, ɵngDocRouteContentSources, ɵngDocRouteUrl, ɵpeekNgDocContent, ɵpendingNgDocContent, ɵpreloadNgDocContent, ɵrestoreNgDocHydrationSnapshot, ɵwithNgDocContent };
188
+ export type { NgDocBootstrap, NgDocResolvedPlaygroundOption };
@@ -1,4 +1,4 @@
1
- import { NgDocBaseEntity, JSDocMetadata, NgDocPageIndex } from '@ng-doc/core/interfaces';
1
+ import { NgDocBaseEntity, JSDocMetadata, NgDocPlaygroundOption, NgDocPageIndex } from '@ng-doc/core/interfaces';
2
2
  import { Type, Injector, Signal } from '@angular/core';
3
3
  import { InputType } from '@ng-doc/core';
4
4
  import { Constructor } from '@ng-doc/core/types/constructor';
@@ -174,7 +174,8 @@ type NgDocTypeControlField<T> = T | Signal<T | undefined>;
174
174
  */
175
175
  interface NgDocTypeControl<T = unknown> extends ControlValueAccessor {
176
176
  /**
177
- * The name of the input for which it is created
177
+ * The name of the input for which it is created, or the `label` that the playground's
178
+ * `controls` give it
178
179
  */
179
180
  name?: NgDocTypeControlField<string>;
180
181
  /**
@@ -186,9 +187,12 @@ interface NgDocTypeControl<T = unknown> extends ControlValueAccessor {
186
187
  */
187
188
  default?: NgDocTypeControlField<T>;
188
189
  /**
189
- * The list of possible values, it usually works only for Type Aliases which has several values
190
+ * The list of possible values, it usually works only for Type Aliases which has several values.
191
+ * An option is the source text of a union member (such as `'small'`), a plain value when
192
+ * `isManual` is set, or the name and value of an enum member (`resolvePlaygroundOption` reads
193
+ * all three)
190
194
  */
191
- options?: NgDocTypeControlField<string[]>;
195
+ options?: NgDocTypeControlField<Array<string | NgDocPlaygroundOption>>;
192
196
  /**
193
197
  * Determines if the property is manually added by the user using `controls` property in playground config
194
198
  */
@@ -210,6 +214,13 @@ interface NgDocTypeControlProviderOptions {
210
214
  * NgDoc's own controls use 10 (type aliases), 20 (`string`), 30 (`number`) and 40 (`boolean`)
211
215
  */
212
216
  order?: number;
217
+ /**
218
+ * Whether the row of the control is a `<label>` that wraps the control (the default). A label
219
+ * forwards clicks on its content to the first form control inside it, which a control with
220
+ * several interactive parts, such as a list or a dialog, doesn't want. With `false`, the row is
221
+ * a `<div>` whose caption names the control through `aria-labelledby`.
222
+ */
223
+ labelWrapper?: boolean;
213
224
  }
214
225
 
215
226
  interface NgDocProvidedTypeControl {
@@ -33,6 +33,11 @@ declare const mermaidProcessor: NgDocPageProcessor<NgDocMermaidViewerComponent>;
33
33
 
34
34
  declare const playgroundProcessor: NgDocPageProcessor<NgDocPlaygroundComponent>;
35
35
 
36
+ /**
37
+ * Turns the `<ng-doc-tab group="…" name="…">` elements of a page into tabs: every tab of a group
38
+ * becomes one `NgDocTabsComponent`, where the first tab of the group was. Code groups are made of
39
+ * them, and Markdown can wrap any content in them.
40
+ */
36
41
  declare const tabsProcessor: NgDocPageProcessor<NgDocTabsComponent>;
37
42
 
38
43
  export { blockquoteProcessor, codeProcessor, demoPaneProcessor, demoProcessor, headingAnchorProcessor, iconProcessor, imageProcessor, membersProcessor, mermaidProcessor, playgroundProcessor, tabsProcessor };
@@ -22,7 +22,7 @@ interface NgDocApplicationConfig {
22
22
  */
23
23
  uiKit?: NgDocUiConfig;
24
24
  /**
25
- * Shiki theme.
25
+ * Extra Shiki themes and languages for the code that the browser highlights.
26
26
  */
27
27
  shiki?: NgDocHighlighterConfig;
28
28
  /**
@@ -0,0 +1,59 @@
1
+ import { EnvironmentProviders } from '@angular/core';
2
+ import { RouterStateSnapshot } from '@angular/router';
3
+
4
+ /**
5
+ * The parts of the current route that `provideNgDocTitle` passes to its function.
6
+ *
7
+ * Outside the documentation (a landing page, for example), `categories` is empty and `page`,
8
+ * `tab` and `api` are not set.
9
+ */
10
+ interface NgDocTitleContext {
11
+ /**
12
+ * The title Angular sets by default: the title of the deepest route that has one. It is not set
13
+ * when no route of the navigation has a title.
14
+ */
15
+ readonly title: string | undefined;
16
+ /** Titles of the categories that contain the page, the outermost category first. */
17
+ readonly categories: readonly string[];
18
+ /**
19
+ * Title of the guide or the API list. A title in the page's own route replaces it. Not set on
20
+ * an API page, which sets `api` instead.
21
+ */
22
+ readonly page: string | undefined;
23
+ /**
24
+ * Title of the active tab, when the page has more than one tab. Not set on a tab titled like
25
+ * the page, usually its first one.
26
+ */
27
+ readonly tab: string | undefined;
28
+ /** Name of the API declaration, on an API page. */
29
+ readonly api: string | undefined;
30
+ /** The router state the title is for. */
31
+ readonly snapshot: RouterStateSnapshot;
32
+ }
33
+ /**
34
+ * Builds the browser tab title from the parts of the current route. It runs in an injection
35
+ * context, so it can call `inject()`. When it returns `undefined`, the title stays as it is.
36
+ */
37
+ type NgDocTitleFn = (context: NgDocTitleContext) => string | undefined;
38
+ /**
39
+ * Builds the browser tab title of every navigation with a function that receives the categories,
40
+ * the page, the tab and the API declaration of the route, so titles like
41
+ * "Installation · Getting started | NgDoc" need no parsing of route titles.
42
+ *
43
+ * Without it, Angular sets the title of the deepest route: the page's (or its tab's) title.
44
+ * @param titleFn - Builds the title; `undefined` keeps the current title.
45
+ * @example
46
+ * ```ts
47
+ * provideNgDocTitle(({ categories, page, tab, api, title }) => {
48
+ * const name = api ?? page;
49
+ *
50
+ * return name
51
+ * ? [tab, name, ...[...categories].reverse()].filter(Boolean).join(' · ') + ' | My library'
52
+ * : (title ?? 'My library');
53
+ * });
54
+ * ```
55
+ */
56
+ declare function provideNgDocTitle(titleFn: NgDocTitleFn): EnvironmentProviders;
57
+
58
+ export { provideNgDocTitle };
59
+ export type { NgDocTitleContext, NgDocTitleFn };
@@ -3,4 +3,5 @@ export * from '@ng-doc/app/providers/ng-doc-app';
3
3
  export * from '@ng-doc/app/providers/page-skeleton';
4
4
  export * from '@ng-doc/app/providers/playground-demo';
5
5
  export * from '@ng-doc/app/providers/search-engine';
6
+ export * from '@ng-doc/app/providers/title';
6
7
  export * from '@ng-doc/app/providers/type-control';