@ng-prism/core 21.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 (307) hide show
  1. package/README.md +170 -0
  2. package/builders.json +14 -0
  3. package/dist/app/component-header/prism-component-header.component.d.ts +8 -0
  4. package/dist/app/component-header/prism-component-header.component.d.ts.map +1 -0
  5. package/dist/app/component-header/prism-component-header.component.js +77 -0
  6. package/dist/app/controls/boolean-control.component.d.ts +10 -0
  7. package/dist/app/controls/boolean-control.component.d.ts.map +1 -0
  8. package/dist/app/controls/boolean-control.component.js +58 -0
  9. package/dist/app/controls/json-control.component.d.ts +19 -0
  10. package/dist/app/controls/json-control.component.d.ts.map +1 -0
  11. package/dist/app/controls/json-control.component.js +136 -0
  12. package/dist/app/controls/number-control.component.d.ts +10 -0
  13. package/dist/app/controls/number-control.component.d.ts.map +1 -0
  14. package/dist/app/controls/number-control.component.js +55 -0
  15. package/dist/app/controls/string-control.component.d.ts +10 -0
  16. package/dist/app/controls/string-control.component.d.ts.map +1 -0
  17. package/dist/app/controls/string-control.component.js +55 -0
  18. package/dist/app/controls/union-control.component.d.ts +11 -0
  19. package/dist/app/controls/union-control.component.d.ts.map +1 -0
  20. package/dist/app/controls/union-control.component.js +72 -0
  21. package/dist/app/header/prism-header.component.d.ts +10 -0
  22. package/dist/app/header/prism-header.component.d.ts.map +1 -0
  23. package/dist/app/header/prism-header.component.js +241 -0
  24. package/dist/app/hmr.d.ts +4 -0
  25. package/dist/app/hmr.d.ts.map +1 -0
  26. package/dist/app/hmr.js +5 -0
  27. package/dist/app/index.d.ts +18 -0
  28. package/dist/app/index.d.ts.map +1 -0
  29. package/dist/app/index.js +21 -0
  30. package/dist/app/layout-menu/prism-layout-menu.component.d.ts +10 -0
  31. package/dist/app/layout-menu/prism-layout-menu.component.d.ts.map +1 -0
  32. package/dist/app/layout-menu/prism-layout-menu.component.js +190 -0
  33. package/dist/app/page-renderer/prism-icon-page.component.d.ts +8 -0
  34. package/dist/app/page-renderer/prism-icon-page.component.d.ts.map +1 -0
  35. package/dist/app/page-renderer/prism-icon-page.component.js +42 -0
  36. package/dist/app/page-renderer/prism-page-renderer.component.d.ts +8 -0
  37. package/dist/app/page-renderer/prism-page-renderer.component.d.ts.map +1 -0
  38. package/dist/app/page-renderer/prism-page-renderer.component.js +72 -0
  39. package/dist/app/page-renderer/prism-token-page.component.d.ts +8 -0
  40. package/dist/app/page-renderer/prism-token-page.component.d.ts.map +1 -0
  41. package/dist/app/page-renderer/prism-token-page.component.js +164 -0
  42. package/dist/app/panels/a11y/a11y-audit.service.d.ts +17 -0
  43. package/dist/app/panels/a11y/a11y-audit.service.d.ts.map +1 -0
  44. package/dist/app/panels/a11y/a11y-audit.service.js +71 -0
  45. package/dist/app/panels/a11y/a11y-core.plugin.d.ts +3 -0
  46. package/dist/app/panels/a11y/a11y-core.plugin.d.ts.map +1 -0
  47. package/dist/app/panels/a11y/a11y-core.plugin.js +8 -0
  48. package/dist/app/panels/a11y/a11y-dom-utils.d.ts +11 -0
  49. package/dist/app/panels/a11y/a11y-dom-utils.d.ts.map +1 -0
  50. package/dist/app/panels/a11y/a11y-dom-utils.js +149 -0
  51. package/dist/app/panels/a11y/a11y-keyboard-overlay.component.d.ts +24 -0
  52. package/dist/app/panels/a11y/a11y-keyboard-overlay.component.d.ts.map +1 -0
  53. package/dist/app/panels/a11y/a11y-keyboard-overlay.component.js +104 -0
  54. package/dist/app/panels/a11y/a11y-keyboard.component.d.ts +12 -0
  55. package/dist/app/panels/a11y/a11y-keyboard.component.d.ts.map +1 -0
  56. package/dist/app/panels/a11y/a11y-keyboard.component.js +150 -0
  57. package/dist/app/panels/a11y/a11y-keyboard.service.d.ts +8 -0
  58. package/dist/app/panels/a11y/a11y-keyboard.service.d.ts.map +1 -0
  59. package/dist/app/panels/a11y/a11y-keyboard.service.js +71 -0
  60. package/dist/app/panels/a11y/a11y-overlay-host.component.d.ts +6 -0
  61. package/dist/app/panels/a11y/a11y-overlay-host.component.d.ts.map +1 -0
  62. package/dist/app/panels/a11y/a11y-overlay-host.component.js +18 -0
  63. package/dist/app/panels/a11y/a11y-panel-state.service.d.ts +8 -0
  64. package/dist/app/panels/a11y/a11y-panel-state.service.d.ts.map +1 -0
  65. package/dist/app/panels/a11y/a11y-panel-state.service.js +11 -0
  66. package/dist/app/panels/a11y/a11y-panel.component.d.ts +14 -0
  67. package/dist/app/panels/a11y/a11y-panel.component.d.ts.map +1 -0
  68. package/dist/app/panels/a11y/a11y-panel.component.js +183 -0
  69. package/dist/app/panels/a11y/a11y-perspective.service.d.ts +8 -0
  70. package/dist/app/panels/a11y/a11y-perspective.service.d.ts.map +1 -0
  71. package/dist/app/panels/a11y/a11y-perspective.service.js +11 -0
  72. package/dist/app/panels/a11y/a11y-score.component.d.ts +11 -0
  73. package/dist/app/panels/a11y/a11y-score.component.d.ts.map +1 -0
  74. package/dist/app/panels/a11y/a11y-score.component.js +72 -0
  75. package/dist/app/panels/a11y/a11y-sr-overlay.component.d.ts +27 -0
  76. package/dist/app/panels/a11y/a11y-sr-overlay.component.d.ts.map +1 -0
  77. package/dist/app/panels/a11y/a11y-sr-overlay.component.js +127 -0
  78. package/dist/app/panels/a11y/a11y-sr.component.d.ts +19 -0
  79. package/dist/app/panels/a11y/a11y-sr.component.d.ts.map +1 -0
  80. package/dist/app/panels/a11y/a11y-sr.component.js +257 -0
  81. package/dist/app/panels/a11y/a11y-sr.service.d.ts +8 -0
  82. package/dist/app/panels/a11y/a11y-sr.service.d.ts.map +1 -0
  83. package/dist/app/panels/a11y/a11y-sr.service.js +102 -0
  84. package/dist/app/panels/a11y/a11y-tree.component.d.ts +27 -0
  85. package/dist/app/panels/a11y/a11y-tree.component.d.ts.map +1 -0
  86. package/dist/app/panels/a11y/a11y-tree.component.js +229 -0
  87. package/dist/app/panels/a11y/a11y-tree.service.d.ts +8 -0
  88. package/dist/app/panels/a11y/a11y-tree.service.d.ts.map +1 -0
  89. package/dist/app/panels/a11y/a11y-tree.service.js +47 -0
  90. package/dist/app/panels/a11y/a11y-violations.component.d.ts +15 -0
  91. package/dist/app/panels/a11y/a11y-violations.component.d.ts.map +1 -0
  92. package/dist/app/panels/a11y/a11y-violations.component.js +457 -0
  93. package/dist/app/panels/a11y/a11y.types.d.ts +44 -0
  94. package/dist/app/panels/a11y/a11y.types.d.ts.map +1 -0
  95. package/dist/app/panels/a11y/a11y.types.js +1 -0
  96. package/dist/app/panels/builtin-panels.d.ts +3 -0
  97. package/dist/app/panels/builtin-panels.d.ts.map +1 -0
  98. package/dist/app/panels/builtin-panels.js +8 -0
  99. package/dist/app/panels/controls/controls-plugin.d.ts +3 -0
  100. package/dist/app/panels/controls/controls-plugin.d.ts.map +1 -0
  101. package/dist/app/panels/controls/controls-plugin.js +12 -0
  102. package/dist/app/panels/controls/prism-controls-panel.component.d.ts +13 -0
  103. package/dist/app/panels/controls/prism-controls-panel.component.d.ts.map +1 -0
  104. package/dist/app/panels/controls/prism-controls-panel.component.js +178 -0
  105. package/dist/app/panels/events/events-plugin.d.ts +3 -0
  106. package/dist/app/panels/events/events-plugin.d.ts.map +1 -0
  107. package/dist/app/panels/events/events-plugin.js +12 -0
  108. package/dist/app/panels/events/prism-events-panel.component.d.ts +9 -0
  109. package/dist/app/panels/events/prism-events-panel.component.d.ts.map +1 -0
  110. package/dist/app/panels/events/prism-events-panel.component.js +83 -0
  111. package/dist/app/panels/events/prism-json-node.component.d.ts +22 -0
  112. package/dist/app/panels/events/prism-json-node.component.d.ts.map +1 -0
  113. package/dist/app/panels/events/prism-json-node.component.js +350 -0
  114. package/dist/app/panels/events/prism-json-node.utils.d.ts +2 -0
  115. package/dist/app/panels/events/prism-json-node.utils.d.ts.map +1 -0
  116. package/dist/app/panels/events/prism-json-node.utils.js +40 -0
  117. package/dist/app/panels/panel-host/prism-panel-host.component.d.ts +26 -0
  118. package/dist/app/panels/panel-host/prism-panel-host.component.d.ts.map +1 -0
  119. package/dist/app/panels/panel-host/prism-panel-host.component.js +157 -0
  120. package/dist/app/provide-prism.d.ts +8 -0
  121. package/dist/app/provide-prism.d.ts.map +1 -0
  122. package/dist/app/provide-prism.js +21 -0
  123. package/dist/app/renderer/highlight-xml.d.ts +2 -0
  124. package/dist/app/renderer/highlight-xml.d.ts.map +1 -0
  125. package/dist/app/renderer/highlight-xml.js +27 -0
  126. package/dist/app/renderer/prism-renderer.component.d.ts +32 -0
  127. package/dist/app/renderer/prism-renderer.component.d.ts.map +1 -0
  128. package/dist/app/renderer/prism-renderer.component.js +346 -0
  129. package/dist/app/renderer/snippet-generator.d.ts +7 -0
  130. package/dist/app/renderer/snippet-generator.d.ts.map +1 -0
  131. package/dist/app/renderer/snippet-generator.js +162 -0
  132. package/dist/app/services/navigation-item.types.d.ts +10 -0
  133. package/dist/app/services/navigation-item.types.d.ts.map +1 -0
  134. package/dist/app/services/navigation-item.types.js +1 -0
  135. package/dist/app/services/prism-event-log.service.d.ts +16 -0
  136. package/dist/app/services/prism-event-log.service.d.ts.map +1 -0
  137. package/dist/app/services/prism-event-log.service.js +21 -0
  138. package/dist/app/services/prism-layout.service.d.ts +23 -0
  139. package/dist/app/services/prism-layout.service.d.ts.map +1 -0
  140. package/dist/app/services/prism-layout.service.js +85 -0
  141. package/dist/app/services/prism-manifest.service.d.ts +15 -0
  142. package/dist/app/services/prism-manifest.service.d.ts.map +1 -0
  143. package/dist/app/services/prism-manifest.service.js +53 -0
  144. package/dist/app/services/prism-navigation.service.d.ts +18 -0
  145. package/dist/app/services/prism-navigation.service.d.ts.map +1 -0
  146. package/dist/app/services/prism-navigation.service.js +94 -0
  147. package/dist/app/services/prism-panel.service.d.ts +8 -0
  148. package/dist/app/services/prism-panel.service.d.ts.map +1 -0
  149. package/dist/app/services/prism-panel.service.js +12 -0
  150. package/dist/app/services/prism-plugin.service.d.ts +12 -0
  151. package/dist/app/services/prism-plugin.service.d.ts.map +1 -0
  152. package/dist/app/services/prism-plugin.service.js +32 -0
  153. package/dist/app/services/prism-renderer.service.d.ts +18 -0
  154. package/dist/app/services/prism-renderer.service.d.ts.map +1 -0
  155. package/dist/app/services/prism-renderer.service.js +84 -0
  156. package/dist/app/services/prism-search.service.d.ts +13 -0
  157. package/dist/app/services/prism-search.service.d.ts.map +1 -0
  158. package/dist/app/services/prism-search.service.js +39 -0
  159. package/dist/app/services/prism-theme.service.d.ts +9 -0
  160. package/dist/app/services/prism-theme.service.d.ts.map +1 -0
  161. package/dist/app/services/prism-theme.service.js +23 -0
  162. package/dist/app/services/prism-url-state.service.d.ts +16 -0
  163. package/dist/app/services/prism-url-state.service.d.ts.map +1 -0
  164. package/dist/app/services/prism-url-state.service.js +108 -0
  165. package/dist/app/shell/prism-shell.component.d.ts +22 -0
  166. package/dist/app/shell/prism-shell.component.d.ts.map +1 -0
  167. package/dist/app/shell/prism-shell.component.js +283 -0
  168. package/dist/app/sidebar/prism-sidebar.component.d.ts +14 -0
  169. package/dist/app/sidebar/prism-sidebar.component.d.ts.map +1 -0
  170. package/dist/app/sidebar/prism-sidebar.component.js +105 -0
  171. package/dist/app/theme/prism-default-theme.d.ts +4 -0
  172. package/dist/app/theme/prism-default-theme.d.ts.map +1 -0
  173. package/dist/app/theme/prism-default-theme.js +57 -0
  174. package/dist/app/tokens/prism-tokens.d.ts +11 -0
  175. package/dist/app/tokens/prism-tokens.d.ts.map +1 -0
  176. package/dist/app/tokens/prism-tokens.js +7 -0
  177. package/dist/app/view-tab-bar/prism-view-panel-host.component.d.ts +22 -0
  178. package/dist/app/view-tab-bar/prism-view-panel-host.component.d.ts.map +1 -0
  179. package/dist/app/view-tab-bar/prism-view-panel-host.component.js +90 -0
  180. package/dist/app/view-tab-bar/prism-view-tab-bar.component.d.ts +10 -0
  181. package/dist/app/view-tab-bar/prism-view-tab-bar.component.d.ts.map +1 -0
  182. package/dist/app/view-tab-bar/prism-view-tab-bar.component.js +65 -0
  183. package/dist/builder/build/index.d.ts +6 -0
  184. package/dist/builder/build/index.d.ts.map +1 -0
  185. package/dist/builder/build/index.js +15 -0
  186. package/dist/builder/build/schema.d.ts +9 -0
  187. package/dist/builder/build/schema.d.ts.map +1 -0
  188. package/dist/builder/build/schema.js +1 -0
  189. package/dist/builder/config-loader/config-loader.d.ts +8 -0
  190. package/dist/builder/config-loader/config-loader.d.ts.map +1 -0
  191. package/dist/builder/config-loader/config-loader.js +33 -0
  192. package/dist/builder/config-loader/index.d.ts +3 -0
  193. package/dist/builder/config-loader/index.d.ts.map +1 -0
  194. package/dist/builder/config-loader/index.js +1 -0
  195. package/dist/builder/icon-resolver/icon-resolver.d.ts +7 -0
  196. package/dist/builder/icon-resolver/icon-resolver.d.ts.map +1 -0
  197. package/dist/builder/icon-resolver/icon-resolver.js +12 -0
  198. package/dist/builder/icon-resolver/index.d.ts +2 -0
  199. package/dist/builder/icon-resolver/index.d.ts.map +1 -0
  200. package/dist/builder/icon-resolver/index.js +1 -0
  201. package/dist/builder/manifest/host-parser.d.ts +6 -0
  202. package/dist/builder/manifest/host-parser.d.ts.map +1 -0
  203. package/dist/builder/manifest/host-parser.js +9 -0
  204. package/dist/builder/manifest/index.d.ts +3 -0
  205. package/dist/builder/manifest/index.d.ts.map +1 -0
  206. package/dist/builder/manifest/index.js +1 -0
  207. package/dist/builder/manifest/runtime-manifest.generator.d.ts +9 -0
  208. package/dist/builder/manifest/runtime-manifest.generator.d.ts.map +1 -0
  209. package/dist/builder/manifest/runtime-manifest.generator.js +216 -0
  210. package/dist/builder/plugin-runner/index.d.ts +2 -0
  211. package/dist/builder/plugin-runner/index.d.ts.map +1 -0
  212. package/dist/builder/plugin-runner/index.js +1 -0
  213. package/dist/builder/plugin-runner/plugin-runner.d.ts +3 -0
  214. package/dist/builder/plugin-runner/plugin-runner.d.ts.map +1 -0
  215. package/dist/builder/plugin-runner/plugin-runner.js +38 -0
  216. package/dist/builder/scanner/ast-utils.d.ts +20 -0
  217. package/dist/builder/scanner/ast-utils.d.ts.map +1 -0
  218. package/dist/builder/scanner/ast-utils.js +100 -0
  219. package/dist/builder/scanner/component.scanner.d.ts +7 -0
  220. package/dist/builder/scanner/component.scanner.d.ts.map +1 -0
  221. package/dist/builder/scanner/component.scanner.js +113 -0
  222. package/dist/builder/scanner/entry-point-discovery.d.ts +6 -0
  223. package/dist/builder/scanner/entry-point-discovery.d.ts.map +1 -0
  224. package/dist/builder/scanner/entry-point-discovery.js +38 -0
  225. package/dist/builder/scanner/entry-point.scanner.d.ts +11 -0
  226. package/dist/builder/scanner/entry-point.scanner.d.ts.map +1 -0
  227. package/dist/builder/scanner/entry-point.scanner.js +19 -0
  228. package/dist/builder/scanner/index.d.ts +8 -0
  229. package/dist/builder/scanner/index.d.ts.map +1 -0
  230. package/dist/builder/scanner/index.js +6 -0
  231. package/dist/builder/scanner/input.extractor.d.ts +11 -0
  232. package/dist/builder/scanner/input.extractor.d.ts.map +1 -0
  233. package/dist/builder/scanner/input.extractor.js +169 -0
  234. package/dist/builder/scanner/manifest.generator.d.ts +6 -0
  235. package/dist/builder/scanner/manifest.generator.d.ts.map +1 -0
  236. package/dist/builder/scanner/manifest.generator.js +59 -0
  237. package/dist/builder/scanner/scanner.d.ts +16 -0
  238. package/dist/builder/scanner/scanner.d.ts.map +1 -0
  239. package/dist/builder/scanner/scanner.js +28 -0
  240. package/dist/builder/serve/index.d.ts +6 -0
  241. package/dist/builder/serve/index.d.ts.map +1 -0
  242. package/dist/builder/serve/index.js +48 -0
  243. package/dist/builder/serve/schema.d.ts +9 -0
  244. package/dist/builder/serve/schema.d.ts.map +1 -0
  245. package/dist/builder/serve/schema.js +1 -0
  246. package/dist/builder/shared/index.d.ts +3 -0
  247. package/dist/builder/shared/index.d.ts.map +1 -0
  248. package/dist/builder/shared/index.js +1 -0
  249. package/dist/builder/shared/prism-pipeline.d.ts +21 -0
  250. package/dist/builder/shared/prism-pipeline.d.ts.map +1 -0
  251. package/dist/builder/shared/prism-pipeline.js +95 -0
  252. package/dist/builder/token-scanner/index.d.ts +2 -0
  253. package/dist/builder/token-scanner/index.d.ts.map +1 -0
  254. package/dist/builder/token-scanner/index.js +1 -0
  255. package/dist/builder/token-scanner/token-scanner.d.ts +9 -0
  256. package/dist/builder/token-scanner/token-scanner.d.ts.map +1 -0
  257. package/dist/builder/token-scanner/token-scanner.js +95 -0
  258. package/dist/builder/watcher/index.d.ts +3 -0
  259. package/dist/builder/watcher/index.d.ts.map +1 -0
  260. package/dist/builder/watcher/index.js +1 -0
  261. package/dist/builder/watcher/prism-watcher.d.ts +29 -0
  262. package/dist/builder/watcher/prism-watcher.d.ts.map +1 -0
  263. package/dist/builder/watcher/prism-watcher.js +79 -0
  264. package/dist/config/index.d.ts +6 -0
  265. package/dist/config/index.d.ts.map +1 -0
  266. package/dist/config/index.js +2 -0
  267. package/dist/decorator/index.d.ts +3 -0
  268. package/dist/decorator/index.d.ts.map +1 -0
  269. package/dist/decorator/index.js +1 -0
  270. package/dist/decorator/showcase.decorator.d.ts +5 -0
  271. package/dist/decorator/showcase.decorator.d.ts.map +1 -0
  272. package/dist/decorator/showcase.decorator.js +7 -0
  273. package/dist/decorator/showcase.types.d.ts +54 -0
  274. package/dist/decorator/showcase.types.d.ts.map +1 -0
  275. package/dist/decorator/showcase.types.js +1 -0
  276. package/dist/index.d.ts +4 -0
  277. package/dist/index.d.ts.map +1 -0
  278. package/dist/index.js +6 -0
  279. package/dist/plugin/define-config.d.ts +4 -0
  280. package/dist/plugin/define-config.d.ts.map +1 -0
  281. package/dist/plugin/define-config.js +4 -0
  282. package/dist/plugin/index.d.ts +8 -0
  283. package/dist/plugin/index.d.ts.map +1 -0
  284. package/dist/plugin/index.js +3 -0
  285. package/dist/plugin/page-helpers.d.ts +19 -0
  286. package/dist/plugin/page-helpers.d.ts.map +1 -0
  287. package/dist/plugin/page-helpers.js +20 -0
  288. package/dist/plugin/page.types.d.ts +19 -0
  289. package/dist/plugin/page.types.d.ts.map +1 -0
  290. package/dist/plugin/page.types.js +1 -0
  291. package/dist/plugin/plugin.types.d.ts +98 -0
  292. package/dist/plugin/plugin.types.d.ts.map +1 -0
  293. package/dist/plugin/plugin.types.js +1 -0
  294. package/dist/schematics/ng-add/index.d.ts +4 -0
  295. package/dist/schematics/ng-add/index.d.ts.map +1 -0
  296. package/dist/schematics/ng-add/index.js +179 -0
  297. package/dist/schematics/ng-add/schema.d.ts +5 -0
  298. package/dist/schematics/ng-add/schema.d.ts.map +1 -0
  299. package/dist/schematics/ng-add/schema.js +1 -0
  300. package/dist/test-setup-browser.d.ts +2 -0
  301. package/dist/test-setup-browser.d.ts.map +1 -0
  302. package/dist/test-setup-browser.js +4 -0
  303. package/package.json +73 -0
  304. package/schematics/collection.json +10 -0
  305. package/schematics/ng-add/schema.json +20 -0
  306. package/src/builder/build/schema.json +35 -0
  307. package/src/builder/serve/schema.json +36 -0
@@ -0,0 +1,71 @@
1
+ import { computed, Injectable, signal } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export function calculateScore(results) {
4
+ const violations = results.violations;
5
+ const critical = violations.filter((v) => v.impact === 'critical').length;
6
+ const serious = violations.filter((v) => v.impact === 'serious').length;
7
+ const moderate = violations.filter((v) => v.impact === 'moderate').length;
8
+ const minor = violations.filter((v) => v.impact === 'minor').length;
9
+ const deductions = critical * 25 + serious * 10 + moderate * 5 + minor * 1;
10
+ return {
11
+ score: Math.max(0, 100 - deductions),
12
+ violations: violations.length,
13
+ critical,
14
+ serious,
15
+ moderate,
16
+ minor,
17
+ passes: results.passes.length,
18
+ incomplete: results.incomplete.length,
19
+ };
20
+ }
21
+ export async function runCoreAudit(element, config) {
22
+ const axe = await import('axe-core');
23
+ const options = {};
24
+ if (config?.rules) {
25
+ const keys = Object.keys(config.rules);
26
+ if (keys.length > 0) {
27
+ options.rules = Object.fromEntries(keys.map((id) => [id, config.rules[id]]));
28
+ }
29
+ }
30
+ return axe.default.run(element, options);
31
+ }
32
+ export class A11yAuditService {
33
+ results = signal(null, ...(ngDevMode ? [{ debugName: "results" }] : []));
34
+ running = signal(false, ...(ngDevMode ? [{ debugName: "running" }] : []));
35
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
36
+ scoreResult = computed(() => {
37
+ const r = this.results();
38
+ return r ? calculateScore(r) : null;
39
+ }, ...(ngDevMode ? [{ debugName: "scoreResult" }] : []));
40
+ timer = null;
41
+ scheduleAudit(element, config, debounceMs = 500) {
42
+ if (this.timer)
43
+ clearTimeout(this.timer);
44
+ this.running.set(true);
45
+ this.error.set(null);
46
+ this.timer = setTimeout(() => {
47
+ runCoreAudit(element, config).then((result) => {
48
+ this.results.set(result);
49
+ this.running.set(false);
50
+ }, (err) => {
51
+ this.error.set(err instanceof Error ? err.message : String(err));
52
+ this.running.set(false);
53
+ });
54
+ }, debounceMs);
55
+ }
56
+ clear() {
57
+ if (this.timer) {
58
+ clearTimeout(this.timer);
59
+ this.timer = null;
60
+ }
61
+ this.results.set(null);
62
+ this.running.set(false);
63
+ this.error.set(null);
64
+ }
65
+ static ɵfac = function A11yAuditService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || A11yAuditService)(); };
66
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: A11yAuditService, factory: A11yAuditService.ɵfac, providedIn: 'root' });
67
+ }
68
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(A11yAuditService, [{
69
+ type: Injectable,
70
+ args: [{ providedIn: 'root' }]
71
+ }], null, null); })();
@@ -0,0 +1,3 @@
1
+ import type { PanelDefinition } from '../../../plugin/plugin.types.js';
2
+ export declare const A11Y_CORE_PANEL: PanelDefinition;
3
+ //# sourceMappingURL=a11y-core.plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-core.plugin.d.ts","sourceRoot":"","sources":["../../../../src/app/panels/a11y/a11y-core.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,eAAO,MAAM,eAAe,EAAE,eAS7B,CAAC"}
@@ -0,0 +1,8 @@
1
+ export const A11Y_CORE_PANEL = {
2
+ id: 'a11y',
3
+ label: 'A11y',
4
+ position: 'bottom',
5
+ placement: 'addon',
6
+ loadComponent: () => import('./a11y-panel.component.js').then((m) => m.A11yPanelComponent),
7
+ loadOverlayComponent: () => import('./a11y-overlay-host.component.js').then((m) => m.A11yOverlayHostComponent),
8
+ };
@@ -0,0 +1,11 @@
1
+ export declare function getImplicitRole(element: Element): string;
2
+ export declare function getRole(element: Element): string;
3
+ export interface AccessibleName {
4
+ name: string;
5
+ source: string;
6
+ }
7
+ export declare function computeAccessibleName(element: Element, getById?: (id: string) => Element | null): AccessibleName;
8
+ export declare function extractStates(element: Element): Record<string, string | boolean>;
9
+ export declare function isHidden(element: Element): boolean;
10
+ export declare function statesToList(states: Record<string, string | boolean>): string[];
11
+ //# sourceMappingURL=a11y-dom-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-dom-utils.d.ts","sourceRoot":"","sources":["../../../../src/app/panels/a11y/a11y-dom-utils.ts"],"names":[],"mappings":"AAmDA,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAaxD;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,GACvC,cAAc,CA8BhB;AAGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAsChF;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAIlD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,MAAM,EAAE,CAQ/E"}
@@ -0,0 +1,149 @@
1
+ const IMPLICIT_ROLES = {
2
+ A: 'link',
3
+ BUTTON: 'button',
4
+ SUMMARY: 'button',
5
+ INPUT: 'textbox',
6
+ TEXTAREA: 'textbox',
7
+ SELECT: 'listbox',
8
+ IMG: 'img',
9
+ H1: 'heading',
10
+ H2: 'heading',
11
+ H3: 'heading',
12
+ H4: 'heading',
13
+ H5: 'heading',
14
+ H6: 'heading',
15
+ UL: 'list',
16
+ OL: 'list',
17
+ LI: 'listitem',
18
+ NAV: 'navigation',
19
+ MAIN: 'main',
20
+ HEADER: 'banner',
21
+ FOOTER: 'contentinfo',
22
+ ASIDE: 'complementary',
23
+ FORM: 'form',
24
+ DIALOG: 'dialog',
25
+ TABLE: 'table',
26
+ TR: 'row',
27
+ TH: 'columnheader',
28
+ TD: 'cell',
29
+ THEAD: 'rowgroup',
30
+ TBODY: 'rowgroup',
31
+ DETAILS: 'group',
32
+ ARTICLE: 'article',
33
+ SECTION: 'region',
34
+ };
35
+ const INPUT_TYPE_ROLES = {
36
+ checkbox: 'checkbox',
37
+ radio: 'radio',
38
+ range: 'slider',
39
+ number: 'spinbutton',
40
+ submit: 'button',
41
+ reset: 'button',
42
+ button: 'button',
43
+ image: 'button',
44
+ search: 'searchbox',
45
+ };
46
+ const HEADING_LEVELS = {
47
+ H1: 1, H2: 2, H3: 3, H4: 4, H5: 5, H6: 6,
48
+ };
49
+ export function getImplicitRole(element) {
50
+ const tag = element.tagName.toUpperCase();
51
+ if (tag === 'INPUT') {
52
+ const type = (element.getAttribute('type') ?? 'text').toLowerCase();
53
+ return INPUT_TYPE_ROLES[type] ?? 'textbox';
54
+ }
55
+ if (tag === 'A' && !element.getAttribute('href')) {
56
+ return '';
57
+ }
58
+ return IMPLICIT_ROLES[tag] ?? '';
59
+ }
60
+ export function getRole(element) {
61
+ return element.getAttribute('role') ?? getImplicitRole(element);
62
+ }
63
+ export function computeAccessibleName(element, getById) {
64
+ const labelledBy = element.getAttribute('aria-labelledby');
65
+ if (labelledBy && getById) {
66
+ const parts = labelledBy.trim().split(/\s+/);
67
+ const names = parts
68
+ .map((id) => getById(id)?.textContent?.trim() ?? '')
69
+ .filter(Boolean);
70
+ if (names.length)
71
+ return { name: names.join(' '), source: 'aria-labelledby' };
72
+ }
73
+ const ariaLabel = element.getAttribute('aria-label');
74
+ if (ariaLabel?.trim())
75
+ return { name: ariaLabel.trim(), source: 'aria-label' };
76
+ const tag = element.tagName.toUpperCase();
77
+ if (tag === 'IMG') {
78
+ const alt = element.getAttribute('alt');
79
+ if (alt !== null)
80
+ return { name: alt, source: 'alt' };
81
+ }
82
+ const text = element.textContent?.trim() ?? '';
83
+ if (text)
84
+ return { name: text, source: 'text-content' };
85
+ const title = element.getAttribute('title');
86
+ if (title?.trim())
87
+ return { name: title.trim(), source: 'title' };
88
+ const placeholder = element.getAttribute('placeholder');
89
+ if (placeholder?.trim())
90
+ return { name: placeholder.trim(), source: 'placeholder' };
91
+ return { name: '', source: 'none' };
92
+ }
93
+ export function extractStates(element) {
94
+ const states = {};
95
+ const tag = element.tagName.toUpperCase();
96
+ if (element.getAttribute('aria-hidden') === 'true')
97
+ states['hidden'] = true;
98
+ if (element.getAttribute('aria-disabled') === 'true' || element.hasAttribute('disabled')) {
99
+ states['disabled'] = true;
100
+ }
101
+ if (element.getAttribute('aria-required') === 'true' || element.hasAttribute('required')) {
102
+ states['required'] = true;
103
+ }
104
+ const checked = element.getAttribute('aria-checked');
105
+ if (checked !== null)
106
+ states['checked'] = checked;
107
+ const expanded = element.getAttribute('aria-expanded');
108
+ if (expanded !== null)
109
+ states['expanded'] = expanded === 'true';
110
+ const selected = element.getAttribute('aria-selected');
111
+ if (selected !== null)
112
+ states['selected'] = selected === 'true';
113
+ const pressed = element.getAttribute('aria-pressed');
114
+ if (pressed !== null)
115
+ states['pressed'] = pressed;
116
+ const level = element.getAttribute('aria-level');
117
+ if (level !== null) {
118
+ states['level'] = level;
119
+ }
120
+ else if (HEADING_LEVELS[tag]) {
121
+ states['level'] = String(HEADING_LEVELS[tag]);
122
+ }
123
+ const setsize = element.getAttribute('aria-setsize');
124
+ const posinset = element.getAttribute('aria-posinset');
125
+ if (setsize !== null)
126
+ states['setsize'] = setsize;
127
+ if (posinset !== null)
128
+ states['posinset'] = posinset;
129
+ return states;
130
+ }
131
+ export function isHidden(element) {
132
+ if (element.getAttribute('aria-hidden') === 'true')
133
+ return true;
134
+ if (element.hasAttribute('hidden'))
135
+ return true;
136
+ return false;
137
+ }
138
+ export function statesToList(states) {
139
+ const result = [];
140
+ for (const [key, value] of Object.entries(states)) {
141
+ if (key === 'hidden')
142
+ continue;
143
+ if (value === true)
144
+ result.push(key);
145
+ else if (value !== false)
146
+ result.push(`${key}: ${value}`);
147
+ }
148
+ return result;
149
+ }
@@ -0,0 +1,24 @@
1
+ import { A11yPanelStateService } from './a11y-panel-state.service.js';
2
+ import * as i0 from "@angular/core";
3
+ export interface BadgePosition {
4
+ index: number;
5
+ name: string;
6
+ role: string;
7
+ x: number;
8
+ y: number;
9
+ width: number;
10
+ height: number;
11
+ }
12
+ export declare class A11yKeyboardOverlayComponent {
13
+ protected readonly panelState: A11yPanelStateService;
14
+ private readonly rendererService;
15
+ private readonly keyboardService;
16
+ private readonly elementRef;
17
+ protected readonly badges: import("@angular/core").WritableSignal<BadgePosition[]>;
18
+ private rafId;
19
+ constructor();
20
+ private computeBadges;
21
+ static ɵfac: i0.ɵɵFactoryDeclaration<A11yKeyboardOverlayComponent, never>;
22
+ static ɵcmp: i0.ɵɵComponentDeclaration<A11yKeyboardOverlayComponent, "prism-a11y-kbd-overlay", never, {}, {}, never, never, true, never>;
23
+ }
24
+ //# sourceMappingURL=a11y-keyboard-overlay.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-keyboard-overlay.component.d.ts","sourceRoot":"","sources":["../../../../src/app/panels/a11y/a11y-keyboard-overlay.component.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;;AAGtE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBA4Da,4BAA4B;IACvC,SAAS,CAAC,QAAQ,CAAC,UAAU,wBAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;IAChE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAC/D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAE9D,SAAS,CAAC,QAAQ,CAAC,MAAM,0DAA+B;IAExD,OAAO,CAAC,KAAK,CAAuB;;IAsBpC,OAAO,CAAC,aAAa;yCA9BV,4BAA4B;2CAA5B,4BAA4B;CA2DxC"}
@@ -0,0 +1,104 @@
1
+ import { ChangeDetectionStrategy, Component, effect, ElementRef, inject, signal, } from '@angular/core';
2
+ import { A11yKeyboardService } from './a11y-keyboard.service.js';
3
+ import { A11yPanelStateService } from './a11y-panel-state.service.js';
4
+ import { PrismRendererService } from '../../services/prism-renderer.service.js';
5
+ import * as i0 from "@angular/core";
6
+ const _forTrack0 = ($index, $item) => $item.index;
7
+ function A11yKeyboardOverlayComponent_Conditional_0_For_1_Template(rf, ctx) { if (rf & 1) {
8
+ i0.ɵɵdomElement(0, "div", 0);
9
+ i0.ɵɵdomElementStart(1, "div", 1);
10
+ i0.ɵɵtext(2);
11
+ i0.ɵɵdomElementEnd();
12
+ } if (rf & 2) {
13
+ const badge_r1 = ctx.$implicit;
14
+ i0.ɵɵstyleProp("left", badge_r1.x, "px")("top", badge_r1.y, "px")("width", badge_r1.width, "px")("height", badge_r1.height, "px");
15
+ i0.ɵɵdomProperty("title", badge_r1.name || badge_r1.role);
16
+ i0.ɵɵadvance();
17
+ i0.ɵɵstyleProp("left", badge_r1.x - 10, "px")("top", badge_r1.y - 10, "px");
18
+ i0.ɵɵadvance();
19
+ i0.ɵɵtextInterpolate(badge_r1.index);
20
+ } }
21
+ function A11yKeyboardOverlayComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
22
+ i0.ɵɵrepeaterCreate(0, A11yKeyboardOverlayComponent_Conditional_0_For_1_Template, 3, 14, null, null, _forTrack0);
23
+ } if (rf & 2) {
24
+ const ctx_r1 = i0.ɵɵnextContext();
25
+ i0.ɵɵrepeater(ctx_r1.badges());
26
+ } }
27
+ export class A11yKeyboardOverlayComponent {
28
+ panelState = inject(A11yPanelStateService);
29
+ rendererService = inject(PrismRendererService);
30
+ keyboardService = inject(A11yKeyboardService);
31
+ elementRef = inject((ElementRef));
32
+ badges = signal([], ...(ngDevMode ? [{ debugName: "badges" }] : []));
33
+ rafId = null;
34
+ constructor() {
35
+ effect(() => {
36
+ const root = this.rendererService.renderedElement();
37
+ this.rendererService.inputValues();
38
+ this.rendererService.activeVariantIndex();
39
+ const isKeyboard = this.panelState.activeTab() === 'keyboard';
40
+ if (!root || !isKeyboard) {
41
+ this.badges.set([]);
42
+ return;
43
+ }
44
+ if (this.rafId !== null)
45
+ cancelAnimationFrame(this.rafId);
46
+ this.rafId = requestAnimationFrame(() => {
47
+ this.rafId = null;
48
+ this.computeBadges(root);
49
+ });
50
+ });
51
+ }
52
+ computeBadges(root) {
53
+ const canvas = this.elementRef.nativeElement.closest('.prism-renderer__canvas');
54
+ if (!canvas)
55
+ return;
56
+ const doc = root.ownerDocument;
57
+ const items = this.keyboardService.extractTabOrder(root, doc ? (id) => doc.getElementById(id) : undefined);
58
+ const canvasRect = canvas.getBoundingClientRect();
59
+ const scrollLeft = canvas.scrollLeft;
60
+ const scrollTop = canvas.scrollTop;
61
+ const positions = items.map((item) => {
62
+ const elRect = item.element.getBoundingClientRect();
63
+ return {
64
+ index: item.index,
65
+ name: item.name,
66
+ role: item.role,
67
+ x: elRect.left - canvasRect.left + scrollLeft,
68
+ y: elRect.top - canvasRect.top + scrollTop,
69
+ width: elRect.width,
70
+ height: elRect.height,
71
+ };
72
+ });
73
+ this.badges.set(positions);
74
+ }
75
+ static ɵfac = function A11yKeyboardOverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || A11yKeyboardOverlayComponent)(); };
76
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: A11yKeyboardOverlayComponent, selectors: [["prism-a11y-kbd-overlay"]], decls: 1, vars: 1, consts: [[1, "prism-a11y-kbd-ov__highlight", 3, "title"], [1, "prism-a11y-kbd-ov__badge"]], template: function A11yKeyboardOverlayComponent_Template(rf, ctx) { if (rf & 1) {
77
+ i0.ɵɵconditionalCreate(0, A11yKeyboardOverlayComponent_Conditional_0_Template, 2, 0);
78
+ } if (rf & 2) {
79
+ i0.ɵɵconditional(ctx.panelState.activeTab() === "keyboard" ? 0 : -1);
80
+ } }, styles: ["[_nghost-%COMP%] {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 100;\n overflow: hidden;\n }\n\n .prism-a11y-kbd-ov__highlight[_ngcontent-%COMP%] {\n position: absolute;\n border: 2px solid rgba(129, 140, 248, 0.5);\n border-radius: 4px;\n background: rgba(129, 140, 248, 0.06);\n box-shadow: 0 0 0 4px rgba(129, 140, 248, 0.08);\n pointer-events: none;\n }\n\n .prism-a11y-kbd-ov__badge[_ngcontent-%COMP%] {\n position: absolute;\n width: 20px;\n height: 20px;\n background: #818cf8;\n color: white;\n border-radius: 50%;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 0 0 2px white, 0 2px 6px rgba(0, 0, 0, 0.3);\n font-family: var(--prism-font-sans, system-ui, sans-serif);\n pointer-events: auto;\n cursor: default;\n }"], changeDetection: 0 });
81
+ }
82
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(A11yKeyboardOverlayComponent, [{
83
+ type: Component,
84
+ args: [{ selector: 'prism-a11y-kbd-overlay', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
85
+ @if (panelState.activeTab() === 'keyboard') {
86
+ @for (badge of badges(); track badge.index) {
87
+ <div
88
+ class="prism-a11y-kbd-ov__highlight"
89
+ [style.left.px]="badge.x"
90
+ [style.top.px]="badge.y"
91
+ [style.width.px]="badge.width"
92
+ [style.height.px]="badge.height"
93
+ [title]="badge.name || badge.role"
94
+ ></div>
95
+ <div
96
+ class="prism-a11y-kbd-ov__badge"
97
+ [style.left.px]="badge.x - 10"
98
+ [style.top.px]="badge.y - 10"
99
+ >{{ badge.index }}</div>
100
+ }
101
+ }
102
+ `, styles: ["\n :host {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 100;\n overflow: hidden;\n }\n\n .prism-a11y-kbd-ov__highlight {\n position: absolute;\n border: 2px solid rgba(129, 140, 248, 0.5);\n border-radius: 4px;\n background: rgba(129, 140, 248, 0.06);\n box-shadow: 0 0 0 4px rgba(129, 140, 248, 0.08);\n pointer-events: none;\n }\n\n .prism-a11y-kbd-ov__badge {\n position: absolute;\n width: 20px;\n height: 20px;\n background: #818cf8;\n color: white;\n border-radius: 50%;\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 0 0 2px white, 0 2px 6px rgba(0, 0, 0, 0.3);\n font-family: var(--prism-font-sans, system-ui, sans-serif);\n pointer-events: auto;\n cursor: default;\n }\n "] }]
103
+ }], () => [], null); })();
104
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(A11yKeyboardOverlayComponent, { className: "A11yKeyboardOverlayComponent", filePath: "app/panels/a11y/a11y-keyboard-overlay.component.ts", lineNumber: 83 }); })();
@@ -0,0 +1,12 @@
1
+ import { PrismRendererService } from '../../services/prism-renderer.service.js';
2
+ import * as i0 from "@angular/core";
3
+ export declare class A11yKeyboardComponent {
4
+ protected readonly rendererService: PrismRendererService;
5
+ private readonly keyboardService;
6
+ readonly activeComponent: import("@angular/core").InputSignal<unknown>;
7
+ protected readonly items: import("@angular/core").Signal<import("./a11y.types.js").FocusableElement[]>;
8
+ protected typeAttr(el: Element): string;
9
+ static ɵfac: i0.ɵɵFactoryDeclaration<A11yKeyboardComponent, never>;
10
+ static ɵcmp: i0.ɵɵComponentDeclaration<A11yKeyboardComponent, "prism-a11y-keyboard", never, { "activeComponent": { "alias": "activeComponent"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
11
+ }
12
+ //# sourceMappingURL=a11y-keyboard.component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-keyboard.component.d.ts","sourceRoot":"","sources":["../../../../src/app/panels/a11y/a11y-keyboard.component.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;;AAEhF,qBAsIa,qBAAqB;IAChC,SAAS,CAAC,QAAQ,CAAC,eAAe,uBAAgC;IAClE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA+B;IAE/D,QAAQ,CAAC,eAAe,+CAAwB;IAEhD,SAAS,CAAC,QAAQ,CAAC,KAAK,+EAQrB;IAEH,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM;yCAhB5B,qBAAqB;2CAArB,qBAAqB;CAoBjC"}
@@ -0,0 +1,150 @@
1
+ import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
2
+ import { A11yKeyboardService } from './a11y-keyboard.service.js';
3
+ import { PrismRendererService } from '../../services/prism-renderer.service.js';
4
+ import * as i0 from "@angular/core";
5
+ const _forTrack0 = ($index, $item) => $item.index;
6
+ function A11yKeyboardComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
7
+ i0.ɵɵdomElementStart(0, "div", 1);
8
+ i0.ɵɵtext(1, "Select a component to inspect keyboard navigation.");
9
+ i0.ɵɵdomElementEnd();
10
+ } }
11
+ function A11yKeyboardComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
12
+ i0.ɵɵdomElementStart(0, "div", 1);
13
+ i0.ɵɵtext(1, "No focusable elements found.");
14
+ i0.ɵɵdomElementEnd();
15
+ } }
16
+ function A11yKeyboardComponent_Conditional_3_For_7_Conditional_6_Template(rf, ctx) { if (rf & 1) {
17
+ i0.ɵɵdomElementStart(0, "span", 10);
18
+ i0.ɵɵtext(1);
19
+ i0.ɵɵdomElementEnd();
20
+ i0.ɵɵdomElementStart(2, "span", 11);
21
+ i0.ɵɵtext(3);
22
+ i0.ɵɵdomElementEnd();
23
+ } if (rf & 2) {
24
+ const item_r1 = i0.ɵɵnextContext().$implicit;
25
+ i0.ɵɵadvance();
26
+ i0.ɵɵtextInterpolate1("\"", item_r1.name, "\"");
27
+ i0.ɵɵadvance(2);
28
+ i0.ɵɵtextInterpolate1("via ", item_r1.nameSource);
29
+ } }
30
+ function A11yKeyboardComponent_Conditional_3_For_7_Conditional_7_For_2_Template(rf, ctx) { if (rf & 1) {
31
+ i0.ɵɵdomElementStart(0, "span", 12);
32
+ i0.ɵɵtext(1);
33
+ i0.ɵɵdomElementEnd();
34
+ } if (rf & 2) {
35
+ const s_r2 = ctx.$implicit;
36
+ i0.ɵɵadvance();
37
+ i0.ɵɵtextInterpolate(s_r2);
38
+ } }
39
+ function A11yKeyboardComponent_Conditional_3_For_7_Conditional_7_Template(rf, ctx) { if (rf & 1) {
40
+ i0.ɵɵdomElementStart(0, "div", 9);
41
+ i0.ɵɵrepeaterCreate(1, A11yKeyboardComponent_Conditional_3_For_7_Conditional_7_For_2_Template, 2, 1, "span", 12, i0.ɵɵrepeaterTrackByIdentity);
42
+ i0.ɵɵdomElementEnd();
43
+ } if (rf & 2) {
44
+ const item_r1 = i0.ɵɵnextContext().$implicit;
45
+ i0.ɵɵadvance();
46
+ i0.ɵɵrepeater(item_r1.states);
47
+ } }
48
+ function A11yKeyboardComponent_Conditional_3_For_7_Template(rf, ctx) { if (rf & 1) {
49
+ i0.ɵɵdomElementStart(0, "div", 5)(1, "div", 6);
50
+ i0.ɵɵtext(2);
51
+ i0.ɵɵdomElementEnd();
52
+ i0.ɵɵdomElementStart(3, "div", 7)(4, "span", 8);
53
+ i0.ɵɵtext(5);
54
+ i0.ɵɵdomElementEnd();
55
+ i0.ɵɵconditionalCreate(6, A11yKeyboardComponent_Conditional_3_For_7_Conditional_6_Template, 4, 2);
56
+ i0.ɵɵconditionalCreate(7, A11yKeyboardComponent_Conditional_3_For_7_Conditional_7_Template, 3, 0, "div", 9);
57
+ i0.ɵɵdomElementEnd()();
58
+ } if (rf & 2) {
59
+ const item_r1 = ctx.$implicit;
60
+ const ctx_r2 = i0.ɵɵnextContext(2);
61
+ i0.ɵɵadvance(2);
62
+ i0.ɵɵtextInterpolate(item_r1.index);
63
+ i0.ɵɵadvance(3);
64
+ i0.ɵɵtextInterpolate2("", item_r1.element.tagName.toLowerCase(), "", ctx_r2.typeAttr(item_r1.element));
65
+ i0.ɵɵadvance();
66
+ i0.ɵɵconditional(item_r1.name ? 6 : -1);
67
+ i0.ɵɵadvance();
68
+ i0.ɵɵconditional(item_r1.states.length ? 7 : -1);
69
+ } }
70
+ function A11yKeyboardComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
71
+ i0.ɵɵdomElementStart(0, "div", 2)(1, "span");
72
+ i0.ɵɵtext(2);
73
+ i0.ɵɵdomElementEnd();
74
+ i0.ɵɵdomElementStart(3, "span", 3);
75
+ i0.ɵɵtext(4, "\u25CF Overlay aktiv");
76
+ i0.ɵɵdomElementEnd()();
77
+ i0.ɵɵdomElementStart(5, "div", 4);
78
+ i0.ɵɵrepeaterCreate(6, A11yKeyboardComponent_Conditional_3_For_7_Template, 8, 5, "div", 5, _forTrack0);
79
+ i0.ɵɵdomElementEnd();
80
+ } if (rf & 2) {
81
+ const ctx_r2 = i0.ɵɵnextContext();
82
+ i0.ɵɵadvance(2);
83
+ i0.ɵɵtextInterpolate1("", ctx_r2.items().length, " fokussierbare Elemente");
84
+ i0.ɵɵadvance(4);
85
+ i0.ɵɵrepeater(ctx_r2.items());
86
+ } }
87
+ export class A11yKeyboardComponent {
88
+ rendererService = inject(PrismRendererService);
89
+ keyboardService = inject(A11yKeyboardService);
90
+ activeComponent = input(null, ...(ngDevMode ? [{ debugName: "activeComponent" }] : []));
91
+ items = computed(() => {
92
+ const root = this.rendererService.renderedElement();
93
+ if (!root)
94
+ return [];
95
+ const doc = root.ownerDocument;
96
+ return this.keyboardService.extractTabOrder(root, doc ? (id) => doc.getElementById(id) : undefined);
97
+ }, ...(ngDevMode ? [{ debugName: "items" }] : []));
98
+ typeAttr(el) {
99
+ const type = el.getAttribute('type');
100
+ return type ? `[type=${type}]` : '';
101
+ }
102
+ static ɵfac = function A11yKeyboardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || A11yKeyboardComponent)(); };
103
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: A11yKeyboardComponent, selectors: [["prism-a11y-keyboard"]], inputs: { activeComponent: [1, "activeComponent"] }, decls: 4, vars: 1, consts: [[1, "prism-a11y-kbd"], [1, "prism-a11y-kbd__empty"], [1, "prism-a11y-kbd__header"], [1, "prism-a11y-kbd__overlay-badge"], [1, "prism-a11y-kbd__list"], [1, "prism-a11y-kbd__item"], [1, "prism-a11y-kbd__num"], [1, "prism-a11y-kbd__info"], [1, "prism-a11y-kbd__tag"], [1, "prism-a11y-kbd__states"], [1, "prism-a11y-kbd__name"], [1, "prism-a11y-kbd__source"], [1, "prism-a11y-kbd__state"]], template: function A11yKeyboardComponent_Template(rf, ctx) { if (rf & 1) {
104
+ i0.ɵɵdomElementStart(0, "div", 0);
105
+ i0.ɵɵconditionalCreate(1, A11yKeyboardComponent_Conditional_1_Template, 2, 0, "div", 1)(2, A11yKeyboardComponent_Conditional_2_Template, 2, 0, "div", 1)(3, A11yKeyboardComponent_Conditional_3_Template, 8, 1);
106
+ i0.ɵɵdomElementEnd();
107
+ } if (rf & 2) {
108
+ i0.ɵɵadvance();
109
+ i0.ɵɵconditional(!ctx.rendererService.renderedElement() ? 1 : !ctx.items().length ? 2 : 3);
110
+ } }, styles: ["[_nghost-%COMP%] { display: flex; flex-direction: column; height: 100%; }\n\n .prism-a11y-kbd[_ngcontent-%COMP%] { height: 100%; display: flex; flex-direction: column; }\n\n .prism-a11y-kbd__empty[_ngcontent-%COMP%] {\n display: flex; align-items: center; justify-content: center;\n min-height: 100px; color: var(--prism-text-muted); font-size: 13px;\n }\n\n .prism-a11y-kbd__header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border-bottom: 1px solid var(--prism-border);\n font-size: 12px;\n color: var(--prism-text-muted);\n flex-shrink: 0;\n }\n\n .prism-a11y-kbd__overlay-badge[_ngcontent-%COMP%] {\n margin-left: auto;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n background: color-mix(in srgb, #818cf8 12%, transparent);\n color: #818cf8;\n border: 1px solid color-mix(in srgb, #818cf8 22%, transparent);\n }\n\n .prism-a11y-kbd__list[_ngcontent-%COMP%] { flex: 1; overflow: auto; }\n\n .prism-a11y-kbd__item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px 16px;\n border-bottom: 1px solid var(--prism-border);\n }\n .prism-a11y-kbd__item[_ngcontent-%COMP%]:hover { background: rgba(129, 140, 248, 0.04); }\n\n .prism-a11y-kbd__num[_ngcontent-%COMP%] {\n width: 20px; height: 20px;\n background: #818cf8;\n color: white;\n border-radius: 50%;\n font-size: 10px; font-weight: 700;\n display: flex; align-items: center; justify-content: center;\n flex-shrink: 0; margin-top: 1px;\n font-family: var(--prism-font-sans, system-ui, sans-serif);\n }\n\n .prism-a11y-kbd__info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .prism-a11y-kbd__tag[_ngcontent-%COMP%] {\n font-family: var(--prism-font-mono, monospace);\n font-size: 12px;\n color: var(--prism-primary);\n }\n\n .prism-a11y-kbd__name[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--prism-text-2);\n }\n\n .prism-a11y-kbd__source[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--prism-text-muted);\n }\n\n .prism-a11y-kbd__states[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 2px;\n }\n\n .prism-a11y-kbd__state[_ngcontent-%COMP%] {\n padding: 0 5px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n background: color-mix(in srgb, #fbbf24 12%, transparent);\n color: #fbbf24;\n }"], changeDetection: 0 });
111
+ }
112
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(A11yKeyboardComponent, [{
113
+ type: Component,
114
+ args: [{ selector: 'prism-a11y-keyboard', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
115
+ <div class="prism-a11y-kbd">
116
+ @if (!rendererService.renderedElement()) {
117
+ <div class="prism-a11y-kbd__empty">Select a component to inspect keyboard navigation.</div>
118
+ } @else if (!items().length) {
119
+ <div class="prism-a11y-kbd__empty">No focusable elements found.</div>
120
+ } @else {
121
+ <div class="prism-a11y-kbd__header">
122
+ <span>{{ items().length }} fokussierbare Elemente</span>
123
+ <span class="prism-a11y-kbd__overlay-badge">● Overlay aktiv</span>
124
+ </div>
125
+ <div class="prism-a11y-kbd__list">
126
+ @for (item of items(); track item.index) {
127
+ <div class="prism-a11y-kbd__item">
128
+ <div class="prism-a11y-kbd__num">{{ item.index }}</div>
129
+ <div class="prism-a11y-kbd__info">
130
+ <span class="prism-a11y-kbd__tag">{{ item.element.tagName.toLowerCase() }}{{ typeAttr(item.element) }}</span>
131
+ @if (item.name) {
132
+ <span class="prism-a11y-kbd__name">"{{ item.name }}"</span>
133
+ <span class="prism-a11y-kbd__source">via {{ item.nameSource }}</span>
134
+ }
135
+ @if (item.states.length) {
136
+ <div class="prism-a11y-kbd__states">
137
+ @for (s of item.states; track s) {
138
+ <span class="prism-a11y-kbd__state">{{ s }}</span>
139
+ }
140
+ </div>
141
+ }
142
+ </div>
143
+ </div>
144
+ }
145
+ </div>
146
+ }
147
+ </div>
148
+ `, styles: ["\n :host { display: flex; flex-direction: column; height: 100%; }\n\n .prism-a11y-kbd { height: 100%; display: flex; flex-direction: column; }\n\n .prism-a11y-kbd__empty {\n display: flex; align-items: center; justify-content: center;\n min-height: 100px; color: var(--prism-text-muted); font-size: 13px;\n }\n\n .prism-a11y-kbd__header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n border-bottom: 1px solid var(--prism-border);\n font-size: 12px;\n color: var(--prism-text-muted);\n flex-shrink: 0;\n }\n\n .prism-a11y-kbd__overlay-badge {\n margin-left: auto;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n background: color-mix(in srgb, #818cf8 12%, transparent);\n color: #818cf8;\n border: 1px solid color-mix(in srgb, #818cf8 22%, transparent);\n }\n\n .prism-a11y-kbd__list { flex: 1; overflow: auto; }\n\n .prism-a11y-kbd__item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px 16px;\n border-bottom: 1px solid var(--prism-border);\n }\n .prism-a11y-kbd__item:hover { background: rgba(129, 140, 248, 0.04); }\n\n .prism-a11y-kbd__num {\n width: 20px; height: 20px;\n background: #818cf8;\n color: white;\n border-radius: 50%;\n font-size: 10px; font-weight: 700;\n display: flex; align-items: center; justify-content: center;\n flex-shrink: 0; margin-top: 1px;\n font-family: var(--prism-font-sans, system-ui, sans-serif);\n }\n\n .prism-a11y-kbd__info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .prism-a11y-kbd__tag {\n font-family: var(--prism-font-mono, monospace);\n font-size: 12px;\n color: var(--prism-primary);\n }\n\n .prism-a11y-kbd__name {\n font-size: 12px;\n color: var(--prism-text-2);\n }\n\n .prism-a11y-kbd__source {\n font-size: 11px;\n color: var(--prism-text-muted);\n }\n\n .prism-a11y-kbd__states {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-top: 2px;\n }\n\n .prism-a11y-kbd__state {\n padding: 0 5px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n background: color-mix(in srgb, #fbbf24 12%, transparent);\n color: #fbbf24;\n }\n "] }]
149
+ }], null, { activeComponent: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeComponent", required: false }] }] }); })();
150
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(A11yKeyboardComponent, { className: "A11yKeyboardComponent", filePath: "app/panels/a11y/a11y-keyboard.component.ts", lineNumber: 139 }); })();
@@ -0,0 +1,8 @@
1
+ import type { FocusableElement } from './a11y.types.js';
2
+ import * as i0 from "@angular/core";
3
+ export declare class A11yKeyboardService {
4
+ extractTabOrder(root: Element, getById?: (id: string) => Element | null): FocusableElement[];
5
+ static ɵfac: i0.ɵɵFactoryDeclaration<A11yKeyboardService, never>;
6
+ static ɵprov: i0.ɵɵInjectableDeclaration<A11yKeyboardService>;
7
+ }
8
+ //# sourceMappingURL=a11y-keyboard.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-keyboard.service.d.ts","sourceRoot":"","sources":["../../../../src/app/panels/a11y/a11y-keyboard.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;;AA2BxD,qBACa,mBAAmB;IAC9B,eAAe,CACb,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,GACvC,gBAAgB,EAAE;yCAJV,mBAAmB;6CAAnB,mBAAmB;CAyB/B"}
@@ -0,0 +1,71 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { computeAccessibleName, getRole } from './a11y-dom-utils.js';
3
+ import * as i0 from "@angular/core";
4
+ const FOCUSABLE_SELECTOR = [
5
+ 'a[href]',
6
+ 'button:not([disabled])',
7
+ 'input:not([disabled])',
8
+ 'select:not([disabled])',
9
+ 'textarea:not([disabled])',
10
+ '[tabindex]:not([tabindex="-1"])',
11
+ '[contenteditable="true"]',
12
+ ].join(', ');
13
+ function getTabindex(element) {
14
+ const attr = element.getAttribute('tabindex');
15
+ if (attr === null)
16
+ return 0;
17
+ return parseInt(attr, 10);
18
+ }
19
+ function sortByTabOrder(elements) {
20
+ const positive = elements.filter((el) => getTabindex(el) > 0);
21
+ const natural = elements.filter((el) => getTabindex(el) === 0);
22
+ positive.sort((a, b) => getTabindex(a) - getTabindex(b));
23
+ return [...positive, ...natural];
24
+ }
25
+ export class A11yKeyboardService {
26
+ extractTabOrder(root, getById) {
27
+ const found = Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR));
28
+ const sorted = sortByTabOrder(found);
29
+ return sorted.map((element, i) => {
30
+ const { name, source } = computeAccessibleName(element, getById);
31
+ const role = getRole(element);
32
+ const states = extractFocusableStates(element);
33
+ const tabindex = element.getAttribute('tabindex');
34
+ return {
35
+ element,
36
+ index: i + 1,
37
+ role,
38
+ name,
39
+ nameSource: source,
40
+ states,
41
+ tabindex: tabindex !== null ? parseInt(tabindex, 10) : null,
42
+ };
43
+ });
44
+ }
45
+ static ɵfac = function A11yKeyboardService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || A11yKeyboardService)(); };
46
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: A11yKeyboardService, factory: A11yKeyboardService.ɵfac, providedIn: 'root' });
47
+ }
48
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(A11yKeyboardService, [{
49
+ type: Injectable,
50
+ args: [{ providedIn: 'root' }]
51
+ }], null, null); })();
52
+ function extractFocusableStates(element) {
53
+ const states = [];
54
+ if (element.getAttribute('aria-required') === 'true' || element.hasAttribute('required')) {
55
+ states.push('required');
56
+ }
57
+ if (element.getAttribute('aria-disabled') === 'true') {
58
+ states.push('disabled');
59
+ }
60
+ const checked = element.getAttribute('aria-checked');
61
+ if (checked === 'true')
62
+ states.push('checked');
63
+ if (checked === 'false')
64
+ states.push('unchecked');
65
+ const expanded = element.getAttribute('aria-expanded');
66
+ if (expanded === 'true')
67
+ states.push('expanded');
68
+ if (expanded === 'false')
69
+ states.push('collapsed');
70
+ return states;
71
+ }