@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ng-doc-app-services-shortcuts.mjs","sources":["../../../../libs/app/services/shortcuts/shortcut.ts","../../../../libs/app/services/shortcuts/shortcuts.service.ts","../../../../libs/app/services/shortcuts/ng-doc-app-services-shortcuts.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * A keyboard shortcut registered with the NgDocShortcutsService.\n */\nexport interface NgDocShortcut {\n /**\n * The key that runs the shortcut, compared with the key of the keyboard event without regard to\n * case, for example '/', '[' or 'f'.\n */\n key: string;\n /**\n * Whether the shortcut is a chord with the Command key (macOS) or the Control key (elsewhere).\n * Chords always work: in text fields too, and when single-key shortcuts are turned off. Other\n * shortcuts are single keys: they run only while single-key shortcuts are on, never while the\n * reader types in a field, and never with Command, Control or Alt held.\n */\n chord?: boolean;\n /**\n * Runs the shortcut. The default action of the keyboard event is prevented before it runs. The\n * event is missing when the shortcut runs from the search palette.\n */\n handler: (event?: KeyboardEvent) => void;\n}\n\n/**\n * Whether single-key shortcuts are on for readers who have not turned them on or off themselves.\n * The default is true. Set it with the shortcuts option of provideNgDocApp.\n */\nexport const NG_DOC_SHORTCUTS: InjectionToken<boolean> = new InjectionToken<boolean>(\n 'NG_DOC_SHORTCUTS',\n { factory: () => true },\n);\n\n/**\n * The local storage key that keeps a reader's choice to turn single-key shortcuts on (\"1\") or off\n * (\"0\").\n */\nexport const NG_DOC_STORE_SHORTCUTS_KEY: string = 'ng-doc-shortcuts';\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n afterNextRender,\n computed,\n DestroyRef,\n DOCUMENT,\n inject,\n Injector,\n NgZone,\n PLATFORM_ID,\n Service,\n Signal,\n signal,\n untracked,\n} from '@angular/core';\nimport { NgDocStoreService } from '@ng-doc/app/services/store';\nimport { NgDocThemeService } from '@ng-doc/app/services/theme';\n\nimport { NG_DOC_SHORTCUTS, NG_DOC_STORE_SHORTCUTS_KEY, NgDocShortcut } from './shortcut';\n\n/**\n * Elements where a single key types text or drives the widget instead of running a shortcut:\n * fields, widgets with their own key handling or typeahead, and demos and playgrounds, which\n * host the reader's components.\n */\nconst OWN_KEYS = [\n 'input',\n 'textarea',\n 'select',\n '[contenteditable]:not([contenteditable=\"false\"])',\n ...[\n 'combobox',\n 'listbox',\n 'menu',\n 'menubar',\n 'grid',\n 'tree',\n 'treegrid',\n 'slider',\n 'spinbutton',\n 'application',\n ].map((role: string) => `[role=\"${role}\"]`),\n 'ng-doc-demo',\n 'ng-doc-demo-pane',\n 'ng-doc-playground',\n].join(', ');\n\n/**\n * Keyboard shortcuts of the documentation.\n *\n * Single-key shortcuts (slash opens the search, the square brackets open the previous and next\n * page, F focuses the filter of the page, L copies the link to the page and T switches between\n * the light and the dark theme) are on by default. Readers turn them all off with one switch, and\n * the choice is saved in the browser. A site turns them off by default with the shortcuts option\n * of provideNgDocApp. They never run while the reader types in a field or holds Command, Control\n * or Alt. Chords such as Command+K (Control+K) always work.\n */\n@Service()\nexport class NgDocShortcutsService {\n private readonly document = inject(DOCUMENT);\n private readonly injector = inject(Injector);\n private readonly ngZone = inject(NgZone);\n private readonly browser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly appDefault = inject(NG_DOC_SHORTCUTS);\n private readonly userChoice = signal<boolean | undefined>(undefined);\n private readonly shortcuts: NgDocShortcut[] = [];\n // The theme T switched away from, and the theme it set, so a second T restores the first.\n private themeToggle?: { previous: string | null; set: string | null };\n\n /**\n * Whether single-key shortcuts are on: the reader's saved choice, or the site's default.\n * Components hide the hints of single-key shortcuts while it is false.\n */\n readonly enabled: Signal<boolean> = computed(() => this.userChoice() ?? this.appDefault);\n\n constructor() {\n this.registerDefaults();\n\n if (!this.browser) {\n return;\n }\n\n // The saved choice is read after the first render, so a hydrated page first renders exactly\n // what the server rendered (the site's default) and then switches.\n afterNextRender(() => this.userChoice.set(this.readChoice()), { injector: this.injector });\n\n const listener = (event: KeyboardEvent) => this.onKeydown(event);\n // One document listener for every shortcut; change detection runs only when one matches.\n this.ngZone.runOutsideAngular(() => this.document.addEventListener('keydown', listener));\n inject(DestroyRef).onDestroy(() => this.document.removeEventListener('keydown', listener));\n }\n\n /**\n * Turns single-key shortcuts on or off for this reader and saves the choice in the browser.\n * @param enabled - Whether single-key shortcuts should run.\n */\n setEnabled(enabled: boolean): void {\n this.userChoice.set(enabled);\n\n if (this.browser) {\n try {\n this.injector.get(NgDocStoreService).set(NG_DOC_STORE_SHORTCUTS_KEY, enabled ? '1' : '0');\n } catch {\n // Storage can be unavailable (private mode, blocked cookies); the choice lasts the visit.\n }\n }\n }\n\n /** Turns single-key shortcuts off when they are on, and on when they are off. */\n toggle(): void {\n this.setEnabled(!untracked(this.enabled));\n }\n\n /**\n * Registers a shortcut. When several shortcuts use the same key, the one registered last runs,\n * so a page can take over a key while it is shown and give it back when it is destroyed.\n * @param shortcut - The shortcut to register.\n * @returns A function that removes the shortcut.\n */\n register(shortcut: NgDocShortcut): () => void {\n this.shortcuts.push(shortcut);\n\n return () => {\n const index = this.shortcuts.lastIndexOf(shortcut);\n\n if (index !== -1) {\n this.shortcuts.splice(index, 1);\n }\n };\n }\n\n /**\n * Runs the single-key shortcut registered for a key, as if the reader pressed it, even while\n * single-key shortcuts are off. The search palette uses it for its actions.\n * @param key - The key of the shortcut, for example 't'.\n * @returns Whether a shortcut is registered for the key.\n */\n run(key: string): boolean {\n const shortcut = this.find(key.toLowerCase(), false);\n\n untracked(() => shortcut?.handler());\n\n return !!shortcut;\n }\n\n private onKeydown(event: KeyboardEvent): void {\n if (event.defaultPrevented || event.isComposing || event.repeat || !event.key) {\n return;\n }\n\n // AltGr (Control+Alt on Windows) types characters such as [ and ] on many layouts: those\n // keys are plain characters, not chords.\n const altGraph = !!event.getModifierState?.('AltGraph');\n const chord = !altGraph && (event.metaKey || event.ctrlKey) && !event.altKey;\n const shortcut = this.find(event.key.toLowerCase(), chord);\n\n if (!shortcut || (!chord && !this.acceptsSingleKey(event, altGraph))) {\n return;\n }\n\n event.preventDefault();\n this.ngZone.run(() => untracked(() => shortcut.handler(event)));\n }\n\n private find(key: string, chord: boolean): NgDocShortcut | undefined {\n for (let index = this.shortcuts.length - 1; index >= 0; index--) {\n const shortcut = this.shortcuts[index];\n\n if (shortcut.key.toLowerCase() === key && !!shortcut.chord === chord) {\n return shortcut;\n }\n }\n\n return undefined;\n }\n\n private acceptsSingleKey(event: KeyboardEvent, altGraph: boolean): boolean {\n if (\n !untracked(this.enabled) ||\n event.metaKey ||\n (!altGraph && (event.ctrlKey || event.altKey))\n ) {\n return false;\n }\n\n const target = event.composedPath?.()[0] ?? event.target;\n\n return !(target instanceof Element && target.closest(OWN_KEYS));\n }\n\n private readChoice(): boolean | undefined {\n try {\n const saved = this.injector.get(NgDocStoreService).get(NG_DOC_STORE_SHORTCUTS_KEY);\n\n return saved === '1' ? true : saved === '0' ? false : undefined;\n } catch {\n return undefined;\n }\n }\n\n private registerDefaults(): void {\n this.register({ key: 't', handler: () => this.toggleDarkTheme() });\n this.register({ key: 'l', handler: () => this.copyLink() });\n // Pager links: rel=\"prev\"/\"next\" is the standard marker; the classes are the NgDoc pager's.\n this.register({ key: '[', handler: () => this.click('a[rel~=\"prev\"], a.ng-doc-prev-page') });\n this.register({ key: ']', handler: () => this.click('a[rel~=\"next\"], a.ng-doc-next-page') });\n }\n\n private toggleDarkTheme(): void {\n const themeService = this.injector.get(NgDocThemeService);\n const theme = themeService.theme();\n const toggle = this.themeToggle;\n\n // A second T restores the theme the first one replaced (auto or a custom theme), unless the\n // reader changed the theme in between.\n if (toggle && toggle.set === theme) {\n this.themeToggle = undefined;\n themeService.set(toggle.previous ?? undefined);\n\n return;\n }\n\n const dark =\n theme === 'dark' ||\n (theme === 'auto' &&\n !!this.document.defaultView?.matchMedia?.('(prefers-color-scheme: dark)').matches);\n const next = dark ? null : 'dark';\n\n this.themeToggle = { previous: theme, set: next };\n themeService.set(next ?? undefined);\n }\n\n private copyLink(): void {\n void this.document.defaultView?.navigator.clipboard\n ?.writeText(this.document.location.href)\n .catch(() => undefined);\n }\n\n private click(selector: string): void {\n this.document.querySelector<HTMLElement>(selector)?.click();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,42 +1,67 @@
1
+ import { isPlatformBrowser } from '@angular/common';
1
2
  import * as i0 from '@angular/core';
2
- import { inject, DOCUMENT, Injectable } from '@angular/core';
3
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { inject, DOCUMENT, NgZone, PLATFORM_ID, DestroyRef, Service } from '@angular/core';
4
+ import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
5
  import { Router, NavigationEnd } from '@angular/router';
5
- import { ngDocZoneOptimize } from '@ng-doc/ui-kit';
6
6
  import { NgDocScrollService } from '@ng-doc/ui-kit/services/scroll';
7
7
  import { WA_WINDOW } from '@ng-web-apis/common';
8
- import { BehaviorSubject, fromEvent, share } from 'rxjs';
9
- import { startWith, filter } from 'rxjs/operators';
8
+ import { BehaviorSubject } from 'rxjs';
9
+ import { filter } from 'rxjs/operators';
10
10
 
11
+ /**
12
+ * The widest viewport, in CSS pixels, at which the sidebar is an overlay that the navbar's menu
13
+ * button opens. It matches the `max-width: 900px` media query of `ng-doc-sidenav`.
14
+ */
15
+ const NG_DOC_SIDEBAR_COLLAPSE_WIDTH = 900;
11
16
  /**
12
17
  * Service for sidebar, it can be used to hide/show sidebar or to check if sidebar is collapsable.
18
+ *
19
+ * On wide screens the sidebar is always shown. At `NG_DOC_SIDEBAR_COLLAPSE_WIDTH` and below it is
20
+ * an overlay: `show()` opens it and blocks page scrolling, `hide()` closes it, and a navigation
21
+ * or a resize to a wide screen ends the overlay.
13
22
  */
14
23
  class NgDocSidebarService {
15
24
  constructor() {
16
- this.expanded = new BehaviorSubject(false);
17
25
  this.document = inject(DOCUMENT);
18
26
  this.window = inject(WA_WINDOW);
19
27
  this.router = inject(Router);
20
28
  this.scroll = inject(NgDocScrollService);
21
- const windowResize = fromEvent(this.window, 'resize').pipe(takeUntilDestroyed(), startWith(null), share());
22
- windowResize
23
- .pipe(filter(() => this.expanded.value && this.isMobile), ngDocZoneOptimize(), takeUntilDestroyed())
24
- .subscribe(() => this.hide());
25
- windowResize
26
- .pipe(filter(() => !this.expanded.value && !this.isMobile), ngDocZoneOptimize(), takeUntilDestroyed())
27
- .subscribe(() => this.show());
28
- windowResize
29
- .pipe(filter(() => this.expanded.value && !this.isMobile), ngDocZoneOptimize(), takeUntilDestroyed())
30
- .subscribe(() => this.scroll.unblock());
29
+ this.expanded = new BehaviorSubject(false);
30
+ /**
31
+ * Whether the sidebar is shown, as a signal. It follows the same state as `isExpanded()`.
32
+ */
33
+ this.expandedState = toSignal(this.expanded, { requireSync: true });
34
+ this.ngZone = inject(NgZone);
35
+ // On the server the sidebar stays closed: the prerendered page must not show the overlay
36
+ // open on narrow screens. The browser opens it on wide screens once the app starts.
37
+ if (isPlatformBrowser(inject(PLATFORM_ID))) {
38
+ this.syncWithViewport();
39
+ const onResize = () => {
40
+ // Only a change of the open state re-enters the Angular zone, so `isExpanded()`
41
+ // subscribers run inside it; other resizes stay outside.
42
+ if (this.isMobile === this.expanded.value) {
43
+ this.ngZone.run(() => this.syncWithViewport());
44
+ }
45
+ else if (this.expanded.value) {
46
+ this.scroll.unblock();
47
+ }
48
+ };
49
+ this.ngZone.runOutsideAngular(() => this.window.addEventListener('resize', onResize));
50
+ inject(DestroyRef).onDestroy(() => this.window.removeEventListener('resize', onResize));
51
+ }
31
52
  this.router.events
32
53
  .pipe(filter((event) => event instanceof NavigationEnd && this.expanded.value && this.isMobile), takeUntilDestroyed())
33
54
  .subscribe(() => this.hide());
34
55
  }
56
+ /**
57
+ * Whether the viewport is narrow enough for the sidebar to be an overlay.
58
+ */
35
59
  get isMobile() {
36
- return this.window.innerWidth < 1024;
60
+ return this.window.innerWidth <= NG_DOC_SIDEBAR_COLLAPSE_WIDTH;
37
61
  }
38
62
  /**
39
63
  * Indicates if sidebar is visible, based on the show/hide methods.
64
+ * Read `expandedState` for the same value as a signal.
40
65
  */
41
66
  isExpanded() {
42
67
  return this.expanded.asObservable();
@@ -65,19 +90,28 @@ class NgDocSidebarService {
65
90
  toggle() {
66
91
  this.expanded.value ? this.hide() : this.show();
67
92
  }
68
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocSidebarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
69
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocSidebarService, providedIn: 'root' }); }
93
+ syncWithViewport() {
94
+ if (this.isMobile) {
95
+ this.hide();
96
+ }
97
+ else if (this.expanded.value) {
98
+ // The overlay may have blocked scrolling before the viewport grew.
99
+ this.scroll.unblock();
100
+ }
101
+ else {
102
+ this.show();
103
+ }
104
+ }
105
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocSidebarService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
106
+ static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.2.1", ngImport: i0, type: NgDocSidebarService }); }
70
107
  }
71
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocSidebarService, decorators: [{
72
- type: Injectable,
73
- args: [{
74
- providedIn: 'root',
75
- }]
108
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocSidebarService, decorators: [{
109
+ type: Service
76
110
  }], ctorParameters: () => [] });
77
111
 
78
112
  /**
79
113
  * Generated bundle index. Do not edit.
80
114
  */
81
115
 
82
- export { NgDocSidebarService };
116
+ export { NG_DOC_SIDEBAR_COLLAPSE_WIDTH, NgDocSidebarService };
83
117
  //# sourceMappingURL=ng-doc-app-services-sidebar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-doc-app-services-sidebar.mjs","sources":["../../../../libs/app/services/sidebar/sidebar.service.ts","../../../../libs/app/services/sidebar/ng-doc-app-services-sidebar.ts"],"sourcesContent":["import { DOCUMENT, inject, Injectable } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NavigationEnd, Router } from '@angular/router';\nimport { ngDocZoneOptimize } from '@ng-doc/ui-kit';\nimport { NgDocScrollService } from '@ng-doc/ui-kit/services/scroll';\nimport { WA_WINDOW } from '@ng-web-apis/common';\nimport { BehaviorSubject, fromEvent, Observable, share } from 'rxjs';\nimport { filter, startWith } from 'rxjs/operators';\n\n/**\n * Service for sidebar, it can be used to hide/show sidebar or to check if sidebar is collapsable.\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class NgDocSidebarService {\n protected readonly expanded = new BehaviorSubject<boolean>(false);\n protected readonly document = inject(DOCUMENT);\n protected readonly window = inject(WA_WINDOW);\n protected readonly router = inject(Router);\n protected readonly scroll = inject(NgDocScrollService);\n\n constructor() {\n const windowResize = fromEvent(this.window, 'resize').pipe(\n takeUntilDestroyed(),\n startWith(null),\n share(),\n );\n\n windowResize\n .pipe(\n filter(() => this.expanded.value && this.isMobile),\n ngDocZoneOptimize(),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.hide());\n\n windowResize\n .pipe(\n filter(() => !this.expanded.value && !this.isMobile),\n ngDocZoneOptimize(),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.show());\n\n windowResize\n .pipe(\n filter(() => this.expanded.value && !this.isMobile),\n ngDocZoneOptimize(),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.scroll.unblock());\n\n this.router.events\n .pipe(\n filter((event) => event instanceof NavigationEnd && this.expanded.value && this.isMobile),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.hide());\n }\n\n get isMobile(): boolean {\n return this.window.innerWidth < 1024;\n }\n\n /**\n * Indicates if sidebar is visible, based on the show/hide methods.\n */\n isExpanded(): Observable<boolean> {\n return this.expanded.asObservable();\n }\n\n /**\n * Show sidebar, and block scrolling.\n */\n show(): void {\n if (!this.expanded.value) {\n this.expanded.next(true);\n this.isMobile && this.scroll.block();\n }\n }\n\n /**\n * Hide sidebar, and unblock scrolling.\n */\n hide(): void {\n if (this.expanded.value) {\n this.expanded.next(false);\n this.isMobile && this.scroll.unblock();\n }\n }\n\n /**\n * Toggle sidebar visibility.\n */\n toggle(): void {\n this.expanded.value ? this.hide() : this.show();\n }\n}\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-services-sidebar.mjs","sources":["../../../../libs/app/services/sidebar/sidebar.service.ts","../../../../libs/app/services/sidebar/ng-doc-app-services-sidebar.ts"],"sourcesContent":["import { isPlatformBrowser } from '@angular/common';\nimport { DestroyRef, DOCUMENT, inject, NgZone, PLATFORM_ID, Service, Signal } from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { NavigationEnd, Router } from '@angular/router';\nimport { NgDocScrollService } from '@ng-doc/ui-kit/services/scroll';\nimport { WA_WINDOW } from '@ng-web-apis/common';\nimport { BehaviorSubject, Observable } from 'rxjs';\nimport { filter } from 'rxjs/operators';\n\n/**\n * The widest viewport, in CSS pixels, at which the sidebar is an overlay that the navbar's menu\n * button opens. It matches the `max-width: 900px` media query of `ng-doc-sidenav`.\n */\nexport const NG_DOC_SIDEBAR_COLLAPSE_WIDTH = 900;\n\n/**\n * Service for sidebar, it can be used to hide/show sidebar or to check if sidebar is collapsable.\n *\n * On wide screens the sidebar is always shown. At `NG_DOC_SIDEBAR_COLLAPSE_WIDTH` and below it is\n * an overlay: `show()` opens it and blocks page scrolling, `hide()` closes it, and a navigation\n * or a resize to a wide screen ends the overlay.\n */\n@Service()\nexport class NgDocSidebarService {\n protected readonly document = inject(DOCUMENT);\n protected readonly window = inject(WA_WINDOW);\n protected readonly router = inject(Router);\n protected readonly scroll = inject(NgDocScrollService);\n\n protected readonly expanded = new BehaviorSubject<boolean>(false);\n\n /**\n * Whether the sidebar is shown, as a signal. It follows the same state as `isExpanded()`.\n */\n readonly expandedState: Signal<boolean> = toSignal(this.expanded, { requireSync: true });\n\n private readonly ngZone = inject(NgZone);\n\n constructor() {\n // On the server the sidebar stays closed: the prerendered page must not show the overlay\n // open on narrow screens. The browser opens it on wide screens once the app starts.\n if (isPlatformBrowser(inject(PLATFORM_ID))) {\n this.syncWithViewport();\n\n const onResize = (): void => {\n // Only a change of the open state re-enters the Angular zone, so `isExpanded()`\n // subscribers run inside it; other resizes stay outside.\n if (this.isMobile === this.expanded.value) {\n this.ngZone.run(() => this.syncWithViewport());\n } else if (this.expanded.value) {\n this.scroll.unblock();\n }\n };\n\n this.ngZone.runOutsideAngular(() => this.window.addEventListener('resize', onResize));\n inject(DestroyRef).onDestroy(() => this.window.removeEventListener('resize', onResize));\n }\n\n this.router.events\n .pipe(\n filter((event) => event instanceof NavigationEnd && this.expanded.value && this.isMobile),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.hide());\n }\n\n /**\n * Whether the viewport is narrow enough for the sidebar to be an overlay.\n */\n get isMobile(): boolean {\n return this.window.innerWidth <= NG_DOC_SIDEBAR_COLLAPSE_WIDTH;\n }\n\n /**\n * Indicates if sidebar is visible, based on the show/hide methods.\n * Read `expandedState` for the same value as a signal.\n */\n isExpanded(): Observable<boolean> {\n return this.expanded.asObservable();\n }\n\n /**\n * Show sidebar, and block scrolling.\n */\n show(): void {\n if (!this.expanded.value) {\n this.expanded.next(true);\n this.isMobile && this.scroll.block();\n }\n }\n\n /**\n * Hide sidebar, and unblock scrolling.\n */\n hide(): void {\n if (this.expanded.value) {\n this.expanded.next(false);\n this.isMobile && this.scroll.unblock();\n }\n }\n\n /**\n * Toggle sidebar visibility.\n */\n toggle(): void {\n this.expanded.value ? this.hide() : this.show();\n }\n\n private syncWithViewport(): void {\n if (this.isMobile) {\n this.hide();\n } else if (this.expanded.value) {\n // The overlay may have blocked scrolling before the viewport grew.\n this.scroll.unblock();\n } else {\n this.show();\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable } from '@angular/core';
2
+ import { inject, Service } from '@angular/core';
3
3
  import { WA_LOCAL_STORAGE } from '@ng-web-apis/common';
4
4
 
5
5
  const DEFAULT_SERIALIZE = (v) => String(v);
6
+ /**
7
+ * Reads and writes NgDoc settings (for example the theme) in the browser's local storage.
8
+ */
6
9
  class NgDocStoreService {
7
10
  constructor() {
8
11
  this.localStorage = inject(WA_LOCAL_STORAGE);
@@ -15,14 +18,11 @@ class NgDocStoreService {
15
18
  ? deserialize(this.localStorage.getItem(key))
16
19
  : this.localStorage.getItem(key);
17
20
  }
18
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocStoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
19
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocStoreService, providedIn: 'root' }); }
21
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocStoreService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
22
+ static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.2.1", ngImport: i0, type: NgDocStoreService }); }
20
23
  }
21
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocStoreService, decorators: [{
22
- type: Injectable,
23
- args: [{
24
- providedIn: 'root',
25
- }]
24
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocStoreService, decorators: [{
25
+ type: Service
26
26
  }] });
27
27
 
28
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ng-doc-app-services-store.mjs","sources":["../../../../libs/app/services/store/store.service.ts","../../../../libs/app/services/store/ng-doc-app-services-store.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { WA_LOCAL_STORAGE } from '@ng-web-apis/common';\n\nconst DEFAULT_SERIALIZE: (v: unknown) => string = (v: unknown) => String(v);\n\n@Injectable({\n\tprovidedIn: 'root',\n})\nexport class NgDocStoreService {\n\tprotected readonly localStorage: Storage = inject(WA_LOCAL_STORAGE);\n\n\tset(key: string, data: string): void;\n\tset<T>(key: string, data: T, serialize: (v: T) => string): void;\n\tset<T>(key: string, data: T, serialize: (v: T) => string = DEFAULT_SERIALIZE): void {\n\t\treturn this.localStorage.setItem(key, serialize(data));\n\t}\n\n\tget(key: string): string | null;\n\tget<T>(key: string, deserialize: (v: string | null) => T): T;\n\tget<T>(key: string, deserialize?: (v: string | null) => T): T | string | null {\n\t\treturn deserialize\n\t\t\t? deserialize(this.localStorage.getItem(key))\n\t\t\t: this.localStorage.getItem(key);\n\t}\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAGA,MAAM,iBAAiB,GAA2B,CAAC,CAAU,KAAK,MAAM,CAAC,CAAC,CAAC;MAK9D,iBAAiB,CAAA;AAH9B,IAAA,WAAA,GAAA;AAIoB,QAAA,IAAA,CAAA,YAAY,GAAY,MAAM,CAAC,gBAAgB,CAAC;AAenE,IAAA;AAXA,IAAA,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,YAA8B,iBAAiB,EAAA;AAC3E,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IACvD;IAIA,GAAG,CAAI,GAAW,EAAE,WAAqC,EAAA;AACxD,QAAA,OAAO;cACJ,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;cAC1C,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;IAClC;8GAfY,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAjB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cAFjB,MAAM,EAAA,CAAA,CAAA;;2FAEN,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAH7B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACX,oBAAA,UAAU,EAAE,MAAM;AAClB,iBAAA;;;ACPD;;AAEG;;;;"}
1
+ {"version":3,"file":"ng-doc-app-services-store.mjs","sources":["../../../../libs/app/services/store/store.service.ts","../../../../libs/app/services/store/ng-doc-app-services-store.ts"],"sourcesContent":["import { inject, Service } from '@angular/core';\nimport { WA_LOCAL_STORAGE } from '@ng-web-apis/common';\n\nconst DEFAULT_SERIALIZE: (v: unknown) => string = (v: unknown) => String(v);\n\n/**\n * Reads and writes NgDoc settings (for example the theme) in the browser's local storage.\n */\n@Service()\nexport class NgDocStoreService {\n protected readonly localStorage: Storage = inject(WA_LOCAL_STORAGE);\n\n /**\n * Stores a string value.\n * @param key - Storage key.\n * @param data - The value to store.\n */\n set(key: string, data: string): void;\n /**\n * Stores a value after serializing it.\n * @param key - Storage key.\n * @param data - The value to store.\n * @param serialize - Converts the value to a string.\n */\n set<T>(key: string, data: T, serialize: (v: T) => string): void;\n set<T>(key: string, data: T, serialize: (v: T) => string = DEFAULT_SERIALIZE): void {\n return this.localStorage.setItem(key, serialize(data));\n }\n\n /**\n * Returns the stored string, or `null` when the key is not set.\n * @param key - Storage key.\n */\n get(key: string): string | null;\n /**\n * Returns the stored value, deserialized.\n * @param key - Storage key.\n * @param deserialize - Converts the stored string (or `null`) to the value.\n */\n get<T>(key: string, deserialize: (v: string | null) => T): T;\n get<T>(key: string, deserialize?: (v: string | null) => T): T | string | null {\n return deserialize\n ? deserialize(this.localStorage.getItem(key))\n : this.localStorage.getItem(key);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAGA,MAAM,iBAAiB,GAA2B,CAAC,CAAU,KAAK,MAAM,CAAC,CAAC,CAAC;AAE3E;;AAEG;MAEU,iBAAiB,CAAA;AAD9B,IAAA,WAAA,GAAA;AAEqB,QAAA,IAAA,CAAA,YAAY,GAAY,MAAM,CAAC,gBAAgB,CAAC;AAmCpE,IAAA;AApBC,IAAA,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,YAA8B,iBAAiB,EAAA;AAC1E,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IACxD;IAaA,GAAG,CAAI,GAAW,EAAE,WAAqC,EAAA;AACvD,QAAA,OAAO;cACH,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;cAC1C,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;IACpC;8GAnCW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,OAAA,EAAA,CAAA,CAAA;+GAAjB,iBAAiB,EAAA,CAAA,CAAA;;2FAAjB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B;;;ACRD;;AAEG;;;;"}
@@ -1,11 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DOCUMENT, Injectable } from '@angular/core';
2
+ import { inject, DOCUMENT, signal, Service } from '@angular/core';
3
3
  import { NG_DOC_STORE_THEME_KEY } from '@ng-doc/app/constants';
4
4
  import { NgDocStoreService } from '@ng-doc/app/services/store';
5
5
  import { Subject } from 'rxjs';
6
6
 
7
7
  /**
8
8
  * Service for managing themes.
9
+ *
10
+ * The theme is the `data-theme` attribute of the document element: `auto`, `dark`, the id of a
11
+ * custom theme, or no attribute for the light theme.
9
12
  */
10
13
  class NgDocThemeService {
11
14
  constructor() {
@@ -13,13 +16,25 @@ class NgDocThemeService {
13
16
  this.store = inject(NgDocStoreService);
14
17
  this.change$ = new Subject();
15
18
  this.documentElement = this.document.documentElement;
19
+ this.themeState = signal(this.readTheme(), /* @ts-ignore */
20
+ ...(ngDevMode ? [{ debugName: "themeState" }] : /* istanbul ignore next */ []));
21
+ /**
22
+ * The current theme as a signal: the theme id, or `null` for the light theme.
23
+ *
24
+ * It starts with the document's `data-theme` attribute and follows every `set()` call.
25
+ */
26
+ this.theme = this.themeState.asReadonly();
16
27
  }
17
28
  /**
18
- * Returns the current theme.
29
+ * Returns the current theme: the document's `data-theme` attribute, or `null` without one.
19
30
  */
20
31
  get currentTheme() {
21
- return document.documentElement.getAttribute('data-theme');
32
+ return this.readTheme();
22
33
  }
34
+ /**
35
+ * Emits the theme after every `set()` call. Read `theme` for the current value as a
36
+ * signal.
37
+ */
23
38
  themeChanges() {
24
39
  return this.change$.asObservable();
25
40
  }
@@ -28,18 +43,23 @@ class NgDocThemeService {
28
43
  * @param id - Theme id. If not provided, the theme will be removed.
29
44
  */
30
45
  set(id) {
31
- id
32
- ? this.documentElement.setAttribute('data-theme', id)
46
+ // An empty id removes the attribute, so it is the light theme (`null`) everywhere.
47
+ const theme = id || null;
48
+ theme
49
+ ? this.documentElement.setAttribute('data-theme', theme)
33
50
  : this.documentElement.removeAttribute('data-theme');
34
- this.store.set(NG_DOC_STORE_THEME_KEY, id ?? '');
35
- this.change$.next(id ?? null);
51
+ this.store.set(NG_DOC_STORE_THEME_KEY, theme ?? '');
52
+ this.themeState.set(theme);
53
+ this.change$.next(theme);
54
+ }
55
+ readTheme() {
56
+ return this.documentElement.getAttribute('data-theme');
36
57
  }
37
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocThemeService, providedIn: 'root' }); }
58
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocThemeService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
59
+ static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.2.1", ngImport: i0, type: NgDocThemeService }); }
39
60
  }
40
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NgDocThemeService, decorators: [{
41
- type: Injectable,
42
- args: [{ providedIn: 'root' }]
61
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocThemeService, decorators: [{
62
+ type: Service
43
63
  }] });
44
64
 
45
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ng-doc-app-services-theme.mjs","sources":["../../../../libs/app/services/theme/theme.service.ts","../../../../libs/app/services/theme/ng-doc-app-services-theme.ts"],"sourcesContent":["import { DOCUMENT, inject, Injectable } from '@angular/core';\nimport { NG_DOC_STORE_THEME_KEY } from '@ng-doc/app/constants';\nimport { NgDocStoreService } from '@ng-doc/app/services/store';\nimport { Observable, Subject } from 'rxjs';\n\n/**\n * Service for managing themes.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgDocThemeService {\n protected readonly document = inject(DOCUMENT);\n protected readonly store = inject(NgDocStoreService);\n protected readonly change$ = new Subject<string | null>();\n protected readonly documentElement = this.document.documentElement;\n\n /**\n * Returns the current theme.\n */\n get currentTheme(): string | null {\n return document.documentElement.getAttribute('data-theme');\n }\n\n themeChanges(): Observable<string | null> {\n return this.change$.asObservable();\n }\n\n /**\n * Sets the theme by id.\n * @param id - Theme id. If not provided, the theme will be removed.\n */\n set(id?: string): void {\n id\n ? this.documentElement.setAttribute('data-theme', id)\n : this.documentElement.removeAttribute('data-theme');\n\n this.store.set(NG_DOC_STORE_THEME_KEY, id ?? '');\n this.change$.next(id ?? null);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAKA;;AAEG;MAEU,iBAAiB,CAAA;AAD9B,IAAA,WAAA,GAAA;AAEqB,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC3B,QAAA,IAAA,CAAA,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;AACjC,QAAA,IAAA,CAAA,OAAO,GAAG,IAAI,OAAO,EAAiB;AACtC,QAAA,IAAA,CAAA,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe;AAyBnE,IAAA;AAvBC;;AAEG;AACH,IAAA,IAAI,YAAY,GAAA;QACd,OAAO,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,YAAY,CAAC;IAC5D;IAEA,YAAY,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;IACpC;AAEA;;;AAGG;AACH,IAAA,GAAG,CAAC,EAAW,EAAA;QACb;cACI,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,YAAY,EAAE,EAAE;cAClD,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,YAAY,CAAC;QAEtD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC;IAC/B;8GA5BW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAjB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cADJ,MAAM,EAAA,CAAA,CAAA;;2FACnB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACRlC;;AAEG;;;;"}
1
+ {"version":3,"file":"ng-doc-app-services-theme.mjs","sources":["../../../../libs/app/services/theme/theme.service.ts","../../../../libs/app/services/theme/ng-doc-app-services-theme.ts"],"sourcesContent":["import { DOCUMENT, inject, Service, Signal, signal } from '@angular/core';\nimport { NG_DOC_STORE_THEME_KEY } from '@ng-doc/app/constants';\nimport { NgDocStoreService } from '@ng-doc/app/services/store';\nimport { Observable, Subject } from 'rxjs';\n\n/**\n * Service for managing themes.\n *\n * The theme is the `data-theme` attribute of the document element: `auto`, `dark`, the id of a\n * custom theme, or no attribute for the light theme.\n */\n@Service()\nexport class NgDocThemeService {\n protected readonly document = inject(DOCUMENT);\n protected readonly store = inject(NgDocStoreService);\n protected readonly change$ = new Subject<string | null>();\n protected readonly documentElement = this.document.documentElement;\n\n private readonly themeState = signal<string | null>(this.readTheme());\n\n /**\n * The current theme as a signal: the theme id, or `null` for the light theme.\n *\n * It starts with the document's `data-theme` attribute and follows every `set()` call.\n */\n readonly theme: Signal<string | null> = this.themeState.asReadonly();\n\n /**\n * Returns the current theme: the document's `data-theme` attribute, or `null` without one.\n */\n get currentTheme(): string | null {\n return this.readTheme();\n }\n\n /**\n * Emits the theme after every `set()` call. Read `theme` for the current value as a\n * signal.\n */\n themeChanges(): Observable<string | null> {\n return this.change$.asObservable();\n }\n\n /**\n * Sets the theme by id.\n * @param id - Theme id. If not provided, the theme will be removed.\n */\n set(id?: string): void {\n // An empty id removes the attribute, so it is the light theme (`null`) everywhere.\n const theme = id || null;\n\n theme\n ? this.documentElement.setAttribute('data-theme', theme)\n : this.documentElement.removeAttribute('data-theme');\n\n this.store.set(NG_DOC_STORE_THEME_KEY, theme ?? '');\n this.themeState.set(theme);\n this.change$.next(theme);\n }\n\n private readTheme(): string | null {\n return this.documentElement.getAttribute('data-theme');\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAKA;;;;;AAKG;MAEU,iBAAiB,CAAA;AAD9B,IAAA,WAAA,GAAA;AAEqB,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC3B,QAAA,IAAA,CAAA,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;AACjC,QAAA,IAAA,CAAA,OAAO,GAAG,IAAI,OAAO,EAAiB;AACtC,QAAA,IAAA,CAAA,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe;AAEjD,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAgB,IAAI,CAAC,SAAS,EAAE;uFAAC;AAErE;;;;AAIG;AACM,QAAA,IAAA,CAAA,KAAK,GAA0B,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AAqCrE,IAAA;AAnCC;;AAEG;AACH,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE;IACzB;AAEA;;;AAGG;IACH,YAAY,GAAA;AACV,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;IACpC;AAEA;;;AAGG;AACH,IAAA,GAAG,CAAC,EAAW,EAAA;;AAEb,QAAA,MAAM,KAAK,GAAG,EAAE,IAAI,IAAI;QAExB;cACI,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK;cACrD,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,YAAY,CAAC;QAEtD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC;AACnD,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;IAC1B;IAEQ,SAAS,GAAA;QACf,OAAO,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,YAAY,CAAC;IACxD;8GAjDW,iBAAiB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,OAAA,EAAA,CAAA,CAAA;+GAAjB,iBAAiB,EAAA,CAAA,CAAA;;2FAAjB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B;;;ACXD;;AAEG;;;;"}
@@ -1,8 +1,151 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, signal, computed, Service } from '@angular/core';
4
+ import { Router } from '@angular/router';
5
+ import { NG_DOC_CONTEXT } from '@ng-doc/app/tokens';
6
+ import { NG_REQUEST_BASE_PATH } from '@ng-doc/ui-kit/tokens';
7
+ import { firstValueFrom } from 'rxjs';
8
+ export * from '@ng-doc/app/services/content-scroll-intent';
9
+ export * from '@ng-doc/app/services/content-state';
10
+ export * from '@ng-doc/app/services/fullscreen-route';
1
11
  export * from '@ng-doc/app/services/highlighter';
12
+ export * from '@ng-doc/app/services/route-preloader';
13
+ export * from '@ng-doc/app/services/shortcuts';
2
14
  export * from '@ng-doc/app/services/sidebar';
3
15
  export * from '@ng-doc/app/services/store';
16
+ export * from '@ng-doc/app/services/theme';
17
+
18
+ /**
19
+ * The route data key that names the segment of an API entry's list data
20
+ * (assets/ng-doc/SEGMENT/api-list.json). An empty string is the root list.
21
+ */
22
+ const NG_DOC_API_LIST_SEGMENT_DATA = 'ngDocApiListSegment';
23
+ /** Route folders of API declaration pages. */
24
+ const DECLARATION_ROUTE = /^(.*?)\/(classes|interfaces|functions|type-aliases|variables|enums)\/[^/]+\/[^/]+$/;
25
+ /**
26
+ * Loads the API lists of every API entry once, for the search palette. The data file of an entry
27
+ * is assets/ng-doc/SEGMENT/api-list.json, where the segment is the route of the entry in its API
28
+ * configuration, or the root when it has none.
29
+ *
30
+ * The new engine lists every segment in the generated context (`NgDocContext.apiLists`), so
31
+ * exactly those files are requested, and none when the site has no API entry. Otherwise the
32
+ * entries are found in the router configuration: a route that carries the route data key
33
+ * NG_DOC_API_LIST_SEGMENT_DATA names its segment, and a route that declaration pages live under
34
+ * (ENTRY/classes/SCOPE/NAME and so on) tries its last route segment, with the root as the
35
+ * fallback ("api" tries the root first, as that is the default route of an API entry). When the
36
+ * configuration shows no entry (lazy routes), the root list is loaded. A list that cannot be
37
+ * loaded is skipped quietly, and each file is requested at most once per application.
38
+ */
39
+ class NgDocApiListIndexService {
40
+ constructor() {
41
+ this.http = inject(HttpClient);
42
+ this.router = inject(Router);
43
+ this.basePath = inject(NG_REQUEST_BASE_PATH);
44
+ this.context = inject(NG_DOC_CONTEXT, { optional: true });
45
+ this.lists = signal(new Map(), /* @ts-ignore */
46
+ ...(ngDevMode ? [{ debugName: "lists" }] : /* istanbul ignore next */ []));
47
+ this.requests = new Map();
48
+ /** Every declaration of the loaded API lists. */
49
+ this.declarations = computed(() => [...this.lists().values()].flatMap((lists) => lists.flatMap((scope) => scope.items.map((item) => ({
50
+ name: item.name,
51
+ kind: item.type,
52
+ scope: scope.title,
53
+ route: item.route.replace(/^\/+/, ''),
54
+ description: item.description,
55
+ signature: item.signature,
56
+ })))), /* @ts-ignore */
57
+ ...(ngDevMode ? [{ debugName: "declarations" }] : /* istanbul ignore next */ []));
58
+ }
59
+ /**
60
+ * Starts loading the API lists of every API entry, once.
61
+ * @returns A promise that settles when every list has loaded or failed.
62
+ */
63
+ load() {
64
+ const generated = this.context?.apiLists;
65
+ const entries = generated
66
+ ? generated.map((segment) => ({ segments: [segment] }))
67
+ : apiEntries(this.router.config);
68
+ // Generated sites load their pages with lazy routes, which the router configuration does
69
+ // not list until they are loaded. Without the generated list, the root list is where the
70
+ // default API entry keeps its data, so it is tried when no entry is found.
71
+ this.loading ??= Promise.all((entries.length || generated ? entries : [{ segments: [''] }]).map((entry) => this.loadEntry(entry))).then(() => undefined);
72
+ return this.loading;
73
+ }
74
+ /**
75
+ * Records an API list that is already loaded (the API index page loads its own), so the
76
+ * palette does not request it again.
77
+ * @param segment - The segment of the list data, or an empty string for the root list.
78
+ * @param list - The list.
79
+ */
80
+ remember(segment, list) {
81
+ this.requests.set(segment, Promise.resolve(list));
82
+ this.store(segment, list);
83
+ }
84
+ async loadEntry(entry) {
85
+ for (const segment of entry.segments) {
86
+ const list = await this.request(segment);
87
+ if (list) {
88
+ this.store(segment, list);
89
+ return;
90
+ }
91
+ }
92
+ }
93
+ request(segment) {
94
+ let request = this.requests.get(segment);
95
+ if (!request) {
96
+ const url = `${this.basePath}assets/ng-doc/${segment ? `${segment}/` : ''}api-list.json`;
97
+ request = firstValueFrom(this.http.get(url)).then((list) => (Array.isArray(list) ? list : undefined), () => undefined);
98
+ this.requests.set(segment, request);
99
+ }
100
+ return request;
101
+ }
102
+ store(segment, list) {
103
+ this.lists.update((lists) => new Map(lists).set(segment, list));
104
+ }
105
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocApiListIndexService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
106
+ static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.2.1", ngImport: i0, type: NgDocApiListIndexService }); }
107
+ }
108
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: NgDocApiListIndexService, decorators: [{
109
+ type: Service
110
+ }] });
111
+ /**
112
+ * Finds the API entries in a router configuration.
113
+ * @param routes - The routes.
114
+ */
115
+ function apiEntries(routes) {
116
+ const entries = new Map();
117
+ const entryRoutes = new Map();
118
+ const visit = (children, prefix) => {
119
+ for (const route of children) {
120
+ const path = [prefix, route.path ?? ''].filter(Boolean).join('/');
121
+ entryRoutes.set(path, route);
122
+ if (route.children) {
123
+ visit(route.children, path);
124
+ }
125
+ }
126
+ };
127
+ visit(routes, '');
128
+ // A route with the segment in its data is an entry, even while its pages are lazy.
129
+ for (const [path, route] of entryRoutes) {
130
+ const configured = route.data?.[NG_DOC_API_LIST_SEGMENT_DATA];
131
+ if (typeof configured === 'string') {
132
+ entries.set(path, { segments: [configured] });
133
+ }
134
+ }
135
+ for (const path of entryRoutes.keys()) {
136
+ const match = DECLARATION_ROUTE.exec(path);
137
+ if (!match || entries.has(match[1])) {
138
+ continue;
139
+ }
140
+ const last = match[1].split('/').pop() ?? '';
141
+ entries.set(match[1], { segments: last === 'api' ? ['', last] : [last, ''] });
142
+ }
143
+ return [...entries.values()];
144
+ }
4
145
 
5
146
  /**
6
147
  * Generated bundle index. Do not edit.
7
148
  */
149
+
150
+ export { NG_DOC_API_LIST_SEGMENT_DATA, NgDocApiListIndexService };
8
151
  //# sourceMappingURL=ng-doc-app-services.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-doc-app-services.mjs","sources":["../../../../libs/app/services/ng-doc-app-services.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAAA;;AAEG"}
1
+ {"version":3,"file":"ng-doc-app-services.mjs","sources":["../../../../libs/app/services/search-index/api-list-index.service.ts","../../../../libs/app/services/ng-doc-app-services.ts"],"sourcesContent":["import { HttpClient } from '@angular/common/http';\nimport { computed, inject, Service, Signal, signal } from '@angular/core';\nimport { Route, Router } from '@angular/router';\nimport { NG_DOC_CONTEXT } from '@ng-doc/app/tokens';\nimport type { NgDocApiList } from '@ng-doc/core/interfaces';\nimport { NG_REQUEST_BASE_PATH } from '@ng-doc/ui-kit/tokens';\nimport { firstValueFrom } from 'rxjs';\n\n/**\n * A declaration of an API list, with the scope it belongs to.\n */\nexport interface NgDocApiListDeclaration {\n /** The name of the declaration. */\n name: string;\n /** The kind of the declaration, for example Class or Function. */\n kind: string;\n /** The scope of the declaration, for example the package name. */\n scope: string;\n /** The route of the declaration page, without the leading slash. */\n route: string;\n /** A one-line description, when the API list data carries one. */\n description?: string;\n /** The declaration header, when the API list data carries it. */\n signature?: string;\n}\n\n/**\n * The route data key that names the segment of an API entry's list data\n * (assets/ng-doc/SEGMENT/api-list.json). An empty string is the root list.\n */\nexport const NG_DOC_API_LIST_SEGMENT_DATA: string = 'ngDocApiListSegment';\n\n/** Route folders of API declaration pages. */\nconst DECLARATION_ROUTE =\n /^(.*?)\\/(classes|interfaces|functions|type-aliases|variables|enums)\\/[^/]+\\/[^/]+$/;\n\n/**\n * Loads the API lists of every API entry once, for the search palette. The data file of an entry\n * is assets/ng-doc/SEGMENT/api-list.json, where the segment is the route of the entry in its API\n * configuration, or the root when it has none.\n *\n * The new engine lists every segment in the generated context (`NgDocContext.apiLists`), so\n * exactly those files are requested, and none when the site has no API entry. Otherwise the\n * entries are found in the router configuration: a route that carries the route data key\n * NG_DOC_API_LIST_SEGMENT_DATA names its segment, and a route that declaration pages live under\n * (ENTRY/classes/SCOPE/NAME and so on) tries its last route segment, with the root as the\n * fallback (\"api\" tries the root first, as that is the default route of an API entry). When the\n * configuration shows no entry (lazy routes), the root list is loaded. A list that cannot be\n * loaded is skipped quietly, and each file is requested at most once per application.\n */\n@Service()\nexport class NgDocApiListIndexService {\n private readonly http = inject(HttpClient);\n private readonly router = inject(Router);\n private readonly basePath = inject(NG_REQUEST_BASE_PATH);\n private readonly context = inject(NG_DOC_CONTEXT, { optional: true });\n private readonly lists = signal<ReadonlyMap<string, NgDocApiList[]>>(new Map());\n private readonly requests = new Map<string, Promise<NgDocApiList[] | undefined>>();\n private loading?: Promise<void>;\n\n /** Every declaration of the loaded API lists. */\n readonly declarations: Signal<NgDocApiListDeclaration[]> = computed(() =>\n [...this.lists().values()].flatMap((lists: NgDocApiList[]) =>\n lists.flatMap((scope: NgDocApiList) =>\n scope.items.map((item) => ({\n name: item.name,\n kind: item.type,\n scope: scope.title,\n route: item.route.replace(/^\\/+/, ''),\n description: item.description,\n signature: item.signature,\n })),\n ),\n ),\n );\n\n /**\n * Starts loading the API lists of every API entry, once.\n * @returns A promise that settles when every list has loaded or failed.\n */\n load(): Promise<void> {\n const generated: readonly string[] | undefined = this.context?.apiLists;\n const entries: ApiEntry[] = generated\n ? generated.map((segment: string) => ({ segments: [segment] }))\n : apiEntries(this.router.config);\n\n // Generated sites load their pages with lazy routes, which the router configuration does\n // not list until they are loaded. Without the generated list, the root list is where the\n // default API entry keeps its data, so it is tried when no entry is found.\n this.loading ??= Promise.all(\n (entries.length || generated ? entries : [{ segments: [''] }]).map((entry: ApiEntry) =>\n this.loadEntry(entry),\n ),\n ).then(() => undefined);\n\n return this.loading;\n }\n\n /**\n * Records an API list that is already loaded (the API index page loads its own), so the\n * palette does not request it again.\n * @param segment - The segment of the list data, or an empty string for the root list.\n * @param list - The list.\n */\n remember(segment: string, list: NgDocApiList[]): void {\n this.requests.set(segment, Promise.resolve(list));\n this.store(segment, list);\n }\n\n private async loadEntry(entry: ApiEntry): Promise<void> {\n for (const segment of entry.segments) {\n const list = await this.request(segment);\n\n if (list) {\n this.store(segment, list);\n\n return;\n }\n }\n }\n\n private request(segment: string): Promise<NgDocApiList[] | undefined> {\n let request = this.requests.get(segment);\n\n if (!request) {\n const url = `${this.basePath}assets/ng-doc/${segment ? `${segment}/` : ''}api-list.json`;\n\n request = firstValueFrom(this.http.get<NgDocApiList[]>(url)).then(\n (list: NgDocApiList[]) => (Array.isArray(list) ? list : undefined),\n () => undefined,\n );\n this.requests.set(segment, request);\n }\n\n return request;\n }\n\n private store(segment: string, list: NgDocApiList[]): void {\n this.lists.update((lists: ReadonlyMap<string, NgDocApiList[]>) =>\n new Map(lists).set(segment, list),\n );\n }\n}\n\ninterface ApiEntry {\n segments: string[];\n}\n\n/**\n * Finds the API entries in a router configuration.\n * @param routes - The routes.\n */\nfunction apiEntries(routes: Route[]): ApiEntry[] {\n const entries = new Map<string, ApiEntry>();\n const entryRoutes = new Map<string, Route>();\n\n const visit = (children: Route[], prefix: string) => {\n for (const route of children) {\n const path = [prefix, route.path ?? ''].filter(Boolean).join('/');\n\n entryRoutes.set(path, route);\n if (route.children) {\n visit(route.children, path);\n }\n }\n };\n\n visit(routes, '');\n\n // A route with the segment in its data is an entry, even while its pages are lazy.\n for (const [path, route] of entryRoutes) {\n const configured = route.data?.[NG_DOC_API_LIST_SEGMENT_DATA];\n\n if (typeof configured === 'string') {\n entries.set(path, { segments: [configured] });\n }\n }\n\n for (const path of entryRoutes.keys()) {\n const match = DECLARATION_ROUTE.exec(path);\n\n if (!match || entries.has(match[1])) {\n continue;\n }\n\n const last = match[1].split('/').pop() ?? '';\n\n entries.set(match[1], { segments: last === 'api' ? ['', last] : [last, ''] });\n }\n\n return [...entries.values()];\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA0BA;;;AAGG;AACI,MAAM,4BAA4B,GAAW;AAEpD;AACA,MAAM,iBAAiB,GACrB,oFAAoF;AAEtF;;;;;;;;;;;;;AAaG;MAEU,wBAAwB,CAAA;AADrC,IAAA,WAAA,GAAA;AAEmB,QAAA,IAAA,CAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;AACzB,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,oBAAoB,CAAC;QACvC,IAAA,CAAA,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACpD,QAAA,IAAA,CAAA,KAAK,GAAG,MAAM,CAAsC,IAAI,GAAG,EAAE;kFAAC;AAC9D,QAAA,IAAA,CAAA,QAAQ,GAAG,IAAI,GAAG,EAA+C;;QAIzE,IAAA,CAAA,YAAY,GAAsC,QAAQ,CAAC,MAClE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,KAAqB,KACvD,KAAK,CAAC,OAAO,CAAC,CAAC,KAAmB,KAChC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC,CACJ,CACF;yFACF;AAoEF,IAAA;AAlEC;;;AAGG;IACH,IAAI,GAAA;AACF,QAAA,MAAM,SAAS,GAAkC,IAAI,CAAC,OAAO,EAAE,QAAQ;QACvE,MAAM,OAAO,GAAe;AAC1B,cAAE,SAAS,CAAC,GAAG,CAAC,CAAC,OAAe,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;cAC5D,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;;;;QAKlC,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,GAAG,CAC1B,CAAC,OAAO,CAAC,MAAM,IAAI,SAAS,GAAG,OAAO,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,KAAe,KACjF,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CACtB,CACF,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC;QAEvB,OAAO,IAAI,CAAC,OAAO;IACrB;AAEA;;;;;AAKG;IACH,QAAQ,CAAC,OAAe,EAAE,IAAoB,EAAA;AAC5C,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACjD,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC;IAC3B;IAEQ,MAAM,SAAS,CAAC,KAAe,EAAA;AACrC,QAAA,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;YACpC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAExC,IAAI,IAAI,EAAE;AACR,gBAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC;gBAEzB;YACF;QACF;IACF;AAEQ,IAAA,OAAO,CAAC,OAAe,EAAA;QAC7B,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC;QAExC,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,MAAM,GAAG,GAAG,CAAA,EAAG,IAAI,CAAC,QAAQ,iBAAiB,OAAO,GAAG,CAAA,EAAG,OAAO,CAAA,CAAA,CAAG,GAAG,EAAE,eAAe;AAExF,YAAA,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAiB,GAAG,CAAC,CAAC,CAAC,IAAI,CAC/D,CAAC,IAAoB,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,EAClE,MAAM,SAAS,CAChB;YACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QACrC;AAEA,QAAA,OAAO,OAAO;IAChB;IAEQ,KAAK,CAAC,OAAe,EAAE,IAAoB,EAAA;QACjD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAA0C,KAC3D,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAClC;IACH;8GA1FW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,OAAA,EAAA,CAAA,CAAA;+GAAxB,wBAAwB,EAAA,CAAA,CAAA;;2FAAxB,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBADpC;;AAkGD;;;AAGG;AACH,SAAS,UAAU,CAAC,MAAe,EAAA;AACjC,IAAA,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB;AAC3C,IAAA,MAAM,WAAW,GAAG,IAAI,GAAG,EAAiB;AAE5C,IAAA,MAAM,KAAK,GAAG,CAAC,QAAiB,EAAE,MAAc,KAAI;AAClD,QAAA,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE;YAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAEjE,YAAA,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;AAC5B,YAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,gBAAA,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC;YAC7B;QACF;AACF,IAAA,CAAC;AAED,IAAA,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;;IAGjB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,WAAW,EAAE;QACvC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,GAAG,4BAA4B,CAAC;AAE7D,QAAA,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;AAClC,YAAA,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C;IACF;IAEA,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;AAE1C,QAAA,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;YACnC;QACF;AAEA,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE;AAE5C,QAAA,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;IAC/E;AAEA,IAAA,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;AAC9B;;AC/LA;;AAEG;;;;"}
@@ -1,6 +1,12 @@
1
1
  import { InjectionToken } from '@angular/core';
2
2
  import { asArray } from '@ng-doc/core/helpers/as-array';
3
3
 
4
+ /** Enables one delayed anchor replay after asynchronous NgDoc content is processed. */
5
+ const NG_DOC_CONTENT_ANCHOR_SCROLLING = new InjectionToken('NG_DOC_CONTENT_ANCHOR_SCROLLING', { providedIn: 'root', factory: () => false });
6
+
7
+ /** Declares whether delayed NgDoc content may replay a missed saved scroll position. */
8
+ const NG_DOC_CONTENT_SCROLL_POSITION_RESTORATION = new InjectionToken('NG_DOC_CONTENT_SCROLL_POSITION_RESTORATION', { providedIn: 'root', factory: () => 'disabled' });
9
+
4
10
  const NG_DOC_CONTEXT = new InjectionToken('NG_DOC_CONTEXT');
5
11
 
6
12
  const NG_DOC_MERMAID = new InjectionToken('NG_DOC_MERMAID');
@@ -37,38 +43,11 @@ const NG_DOC_ROUTE_PREFIX = new InjectionToken('NG_DOC_ROUTE_PREFIX');
37
43
 
38
44
  const NG_DOC_SHIKI_THEME = new InjectionToken('NG_DOC_SHIKI_THEME');
39
45
 
40
- /**
41
- * Token that can be used to provide custom theme.
42
- * You must compile your theme to CSS and add it to `assets` so that NgDoc can load it dynamically.
43
- *
44
- * You always should provide custom themes in root of your application with `multi: true` parameter.
45
- *
46
- * For example
47
- * ```typescript
48
- * @NgModule({
49
- * declarations: [AppComponent],
50
- * imports: [],
51
- * providers: [
52
- * {provide: NG_DOC_THEME, useValue: {id: 'CustomTheme', path: '/assets/themes/custom.css'}, multi: true}
53
- * ],
54
- * bootstrap: [AppComponent],
55
- * })
56
- * export class AppModule {}
57
- * ```
58
- */
59
- const NG_DOC_THEME = new InjectionToken(`NG_DOC_THEME`);
60
- /**
61
- * Default theme for application if user didn't change it manually.
62
- *
63
- * You can provide this token in the root of you application, to set theme by default.
64
- */
65
- const NG_DOC_DEFAULT_THEME_ID = new InjectionToken(`NG_DOC_DEFAULT_THEME`);
66
-
67
46
  const NG_DOC_TYPE_CONTROL = new InjectionToken('NG_DOC_TYPE_CONTROL');
68
47
 
69
48
  /**
70
49
  * Generated bundle index. Do not edit.
71
50
  */
72
51
 
73
- export { NG_DOC_CONTEXT, NG_DOC_DEFAULT_THEME_ID, NG_DOC_MERMAID, NG_DOC_PAGE_CUSTOM_PROCESSOR, NG_DOC_PAGE_PROCESSOR, NG_DOC_PAGE_SKELETON, NG_DOC_ROUTE_PREFIX, NG_DOC_SHIKI_THEME, NG_DOC_THEME, NG_DOC_TYPE_CONTROL, provideMainPageProcessor, providePageProcessor };
52
+ export { NG_DOC_CONTENT_ANCHOR_SCROLLING, NG_DOC_CONTENT_SCROLL_POSITION_RESTORATION, NG_DOC_CONTEXT, NG_DOC_MERMAID, NG_DOC_PAGE_CUSTOM_PROCESSOR, NG_DOC_PAGE_PROCESSOR, NG_DOC_PAGE_SKELETON, NG_DOC_ROUTE_PREFIX, NG_DOC_SHIKI_THEME, NG_DOC_TYPE_CONTROL, provideMainPageProcessor, providePageProcessor };
74
53
  //# sourceMappingURL=ng-doc-app-tokens.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-doc-app-tokens.mjs","sources":["../../../../libs/app/tokens/context.ts","../../../../libs/app/tokens/mermaid.ts","../../../../libs/app/tokens/page-processor.ts","../../../../libs/app/tokens/page-skeleton.ts","../../../../libs/app/tokens/route-prefix.ts","../../../../libs/app/tokens/shiki-theme.ts","../../../../libs/app/tokens/theme.ts","../../../../libs/app/tokens/type-control.ts","../../../../libs/app/tokens/ng-doc-app-tokens.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NgDocContext } from '@ng-doc/app/interfaces';\n\nexport const NG_DOC_CONTEXT: InjectionToken<NgDocContext> = new InjectionToken<NgDocContext>(\n\t'NG_DOC_CONTEXT',\n);\n","import { InjectionToken } from '@angular/core';\nimport type { Mermaid } from 'mermaid';\n\nexport const NG_DOC_MERMAID = new InjectionToken<Mermaid>('NG_DOC_MERMAID');\n","import { InjectionToken, Provider } from '@angular/core';\nimport { NgDocPageProcessor } from '@ng-doc/app/interfaces';\nimport { asArray } from '@ng-doc/core/helpers/as-array';\n\nexport const NG_DOC_PAGE_PROCESSOR: InjectionToken<NgDocPageProcessor<unknown>> =\n new InjectionToken<NgDocPageProcessor<unknown>>('NG_DOC_PAGE_PROCESSOR');\nexport const NG_DOC_PAGE_CUSTOM_PROCESSOR: InjectionToken<NgDocPageProcessor<unknown>> =\n new InjectionToken<NgDocPageProcessor<unknown>>('NG_DOC_PAGE_CUSTOM_PROCESSOR');\n\n/**\n * Provide a main processor to replace html nodes with an Angular component.\n * Main processors are run before custom processors.\n * @param processors - The processor to provide.\n */\nexport function provideMainPageProcessor(\n processors: NgDocPageProcessor<unknown> | Array<NgDocPageProcessor<unknown>>,\n): Provider[] {\n return asArray(processors).map((processor) => ({\n provide: NG_DOC_PAGE_PROCESSOR,\n useValue: processor,\n multi: true,\n }));\n}\n\n/**\n * Provide a processor to replace html nodes with an Angular component.\n * @param processors - The processor to provide.\n */\nexport function providePageProcessor<T>(\n processors: NgDocPageProcessor<T> | Array<NgDocPageProcessor<T>>,\n): Provider[] {\n return asArray(processors).map((processor) => ({\n provide: NG_DOC_PAGE_CUSTOM_PROCESSOR,\n useValue: processor,\n multi: true,\n }));\n}\n","import { InjectionToken } from '@angular/core';\nimport { NgDocPageSkeleton } from '@ng-doc/app/interfaces';\n\nexport const NG_DOC_PAGE_SKELETON: InjectionToken<NgDocPageSkeleton> =\n\tnew InjectionToken<NgDocPageSkeleton>('NG_DOC_PAGE_SKELETON');\n","import { InjectionToken } from '@angular/core';\n\nexport const NG_DOC_ROUTE_PREFIX = new InjectionToken<string>('NG_DOC_ROUTE_PREFIX');\n","import { InjectionToken } from '@angular/core';\n\nexport interface NgDocShikiTheme {\n light: string;\n dark: string;\n}\n\nexport const NG_DOC_SHIKI_THEME = new InjectionToken<NgDocShikiTheme>('NG_DOC_SHIKI_THEME');\n","import { InjectionToken } from '@angular/core';\nimport { NgDocTheme } from '@ng-doc/app/interfaces';\n\n/**\n * Token that can be used to provide custom theme.\n * You must compile your theme to CSS and add it to `assets` so that NgDoc can load it dynamically.\n *\n * You always should provide custom themes in root of your application with `multi: true` parameter.\n *\n * For example\n * ```typescript\n * @NgModule({\n * declarations: [AppComponent],\n * imports: [],\n * providers: [\n * {provide: NG_DOC_THEME, useValue: {id: 'CustomTheme', path: '/assets/themes/custom.css'}, multi: true}\n * ],\n * bootstrap: [AppComponent],\n * })\n * export class AppModule {}\n * ```\n */\nexport const NG_DOC_THEME: InjectionToken<NgDocTheme> = new InjectionToken<NgDocTheme>(\n\t`NG_DOC_THEME`,\n);\n\n/**\n * Default theme for application if user didn't change it manually.\n *\n * You can provide this token in the root of you application, to set theme by default.\n */\nexport const NG_DOC_DEFAULT_THEME_ID: InjectionToken<string> = new InjectionToken<string>(\n\t`NG_DOC_DEFAULT_THEME`,\n);\n","import { InjectionToken } from '@angular/core';\nimport { NgDocTypeControl } from '@ng-doc/app/interfaces';\n\nexport const NG_DOC_TYPE_CONTROL: InjectionToken<NgDocTypeControl> =\n\tnew InjectionToken<NgDocTypeControl>('NG_DOC_TYPE_CONTROL');\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;MAGa,cAAc,GAAiC,IAAI,cAAc,CAC7E,gBAAgB;;MCDJ,cAAc,GAAG,IAAI,cAAc,CAAU,gBAAgB;;MCC7D,qBAAqB,GAChC,IAAI,cAAc,CAA8B,uBAAuB;MAC5D,4BAA4B,GACvC,IAAI,cAAc,CAA8B,8BAA8B;AAEhF;;;;AAIG;AACG,SAAU,wBAAwB,CACtC,UAA4E,EAAA;AAE5E,IAAA,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM;AAC7C,QAAA,OAAO,EAAE,qBAAqB;AAC9B,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,KAAK,EAAE,IAAI;AACZ,KAAA,CAAC,CAAC;AACL;AAEA;;;AAGG;AACG,SAAU,oBAAoB,CAClC,UAAgE,EAAA;AAEhE,IAAA,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM;AAC7C,QAAA,OAAO,EAAE,4BAA4B;AACrC,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,KAAK,EAAE,IAAI;AACZ,KAAA,CAAC,CAAC;AACL;;MCjCa,oBAAoB,GAChC,IAAI,cAAc,CAAoB,sBAAsB;;MCFhD,mBAAmB,GAAG,IAAI,cAAc,CAAS,qBAAqB;;MCKtE,kBAAkB,GAAG,IAAI,cAAc,CAAkB,oBAAoB;;ACJ1F;;;;;;;;;;;;;;;;;;AAkBG;MACU,YAAY,GAA+B,IAAI,cAAc,CACzE,CAAA,YAAA,CAAc;AAGf;;;;AAIG;MACU,uBAAuB,GAA2B,IAAI,cAAc,CAChF,CAAA,oBAAA,CAAsB;;MC7BV,mBAAmB,GAC/B,IAAI,cAAc,CAAmB,qBAAqB;;ACJ3D;;AAEG;;;;"}
1
+ {"version":3,"file":"ng-doc-app-tokens.mjs","sources":["../../../../libs/app/tokens/content-anchor-scrolling.ts","../../../../libs/app/tokens/content-scroll-position-restoration.ts","../../../../libs/app/tokens/context.ts","../../../../libs/app/tokens/mermaid.ts","../../../../libs/app/tokens/page-processor.ts","../../../../libs/app/tokens/page-skeleton.ts","../../../../libs/app/tokens/route-prefix.ts","../../../../libs/app/tokens/shiki-theme.ts","../../../../libs/app/tokens/type-control.ts","../../../../libs/app/tokens/ng-doc-app-tokens.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/** Enables one delayed anchor replay after asynchronous NgDoc content is processed. */\nexport const NG_DOC_CONTENT_ANCHOR_SCROLLING = new InjectionToken<boolean>(\n 'NG_DOC_CONTENT_ANCHOR_SCROLLING',\n { providedIn: 'root', factory: () => false },\n);\n","import { InjectionToken } from '@angular/core';\n\nexport type NgDocContentScrollPositionRestoration = 'enabled' | 'top' | 'disabled';\n\n/** Declares whether delayed NgDoc content may replay a missed saved scroll position. */\nexport const NG_DOC_CONTENT_SCROLL_POSITION_RESTORATION =\n new InjectionToken<NgDocContentScrollPositionRestoration>(\n 'NG_DOC_CONTENT_SCROLL_POSITION_RESTORATION',\n { providedIn: 'root', factory: () => 'disabled' },\n );\n","import { InjectionToken } from '@angular/core';\nimport { NgDocContext } from '@ng-doc/app/interfaces';\n\nexport const NG_DOC_CONTEXT: InjectionToken<NgDocContext> = new InjectionToken<NgDocContext>(\n\t'NG_DOC_CONTEXT',\n);\n","import { InjectionToken } from '@angular/core';\nimport type { Mermaid } from 'mermaid';\n\nexport const NG_DOC_MERMAID = new InjectionToken<Mermaid>('NG_DOC_MERMAID');\n","import { InjectionToken, Provider } from '@angular/core';\nimport { NgDocPageProcessor } from '@ng-doc/app/interfaces';\nimport { asArray } from '@ng-doc/core/helpers/as-array';\n\nexport const NG_DOC_PAGE_PROCESSOR: InjectionToken<NgDocPageProcessor<unknown>> =\n new InjectionToken<NgDocPageProcessor<unknown>>('NG_DOC_PAGE_PROCESSOR');\nexport const NG_DOC_PAGE_CUSTOM_PROCESSOR: InjectionToken<NgDocPageProcessor<unknown>> =\n new InjectionToken<NgDocPageProcessor<unknown>>('NG_DOC_PAGE_CUSTOM_PROCESSOR');\n\n/**\n * Provide a main processor to replace html nodes with an Angular component.\n * Main processors are run before custom processors.\n * @param processors - The processor to provide.\n */\nexport function provideMainPageProcessor(\n processors: NgDocPageProcessor<unknown> | Array<NgDocPageProcessor<unknown>>,\n): Provider[] {\n return asArray(processors).map((processor) => ({\n provide: NG_DOC_PAGE_PROCESSOR,\n useValue: processor,\n multi: true,\n }));\n}\n\n/**\n * Provide a processor to replace html nodes with an Angular component.\n * @param processors - The processor to provide.\n */\nexport function providePageProcessor<T>(\n processors: NgDocPageProcessor<T> | Array<NgDocPageProcessor<T>>,\n): Provider[] {\n return asArray(processors).map((processor) => ({\n provide: NG_DOC_PAGE_CUSTOM_PROCESSOR,\n useValue: processor,\n multi: true,\n }));\n}\n","import { InjectionToken } from '@angular/core';\nimport { NgDocPageSkeleton } from '@ng-doc/app/interfaces';\n\nexport const NG_DOC_PAGE_SKELETON: InjectionToken<NgDocPageSkeleton> =\n\tnew InjectionToken<NgDocPageSkeleton>('NG_DOC_PAGE_SKELETON');\n","import { InjectionToken } from '@angular/core';\n\nexport const NG_DOC_ROUTE_PREFIX = new InjectionToken<string>('NG_DOC_ROUTE_PREFIX');\n","import { InjectionToken } from '@angular/core';\n\nexport interface NgDocShikiTheme {\n light: string;\n dark: string;\n}\n\nexport const NG_DOC_SHIKI_THEME = new InjectionToken<NgDocShikiTheme>('NG_DOC_SHIKI_THEME');\n","import { InjectionToken } from '@angular/core';\nimport { NgDocTypeControl } from '@ng-doc/app/interfaces';\n\nexport const NG_DOC_TYPE_CONTROL: InjectionToken<NgDocTypeControl> =\n\tnew InjectionToken<NgDocTypeControl>('NG_DOC_TYPE_CONTROL');\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAEA;MACa,+BAA+B,GAAG,IAAI,cAAc,CAC/D,iCAAiC,EACjC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,EAAE;;ACD9C;MACa,0CAA0C,GACrD,IAAI,cAAc,CAChB,4CAA4C,EAC5C,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAAU,EAAE;;MCLxC,cAAc,GAAiC,IAAI,cAAc,CAC7E,gBAAgB;;MCDJ,cAAc,GAAG,IAAI,cAAc,CAAU,gBAAgB;;MCC7D,qBAAqB,GAChC,IAAI,cAAc,CAA8B,uBAAuB;MAC5D,4BAA4B,GACvC,IAAI,cAAc,CAA8B,8BAA8B;AAEhF;;;;AAIG;AACG,SAAU,wBAAwB,CACtC,UAA4E,EAAA;AAE5E,IAAA,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM;AAC7C,QAAA,OAAO,EAAE,qBAAqB;AAC9B,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,KAAK,EAAE,IAAI;AACZ,KAAA,CAAC,CAAC;AACL;AAEA;;;AAGG;AACG,SAAU,oBAAoB,CAClC,UAAgE,EAAA;AAEhE,IAAA,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM;AAC7C,QAAA,OAAO,EAAE,4BAA4B;AACrC,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,KAAK,EAAE,IAAI;AACZ,KAAA,CAAC,CAAC;AACL;;MCjCa,oBAAoB,GAChC,IAAI,cAAc,CAAoB,sBAAsB;;MCFhD,mBAAmB,GAAG,IAAI,cAAc,CAAS,qBAAqB;;MCKtE,kBAAkB,GAAG,IAAI,cAAc,CAAkB,oBAAoB;;MCJ7E,mBAAmB,GAC/B,IAAI,cAAc,CAAmB,qBAAqB;;ACJ3D;;AAEG;;;;"}