@lifecorner/angular-ui-kit 3.4.0 → 3.5.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 (340) hide show
  1. package/README.md +12 -2
  2. package/fesm2022/lifecorner-angular-ui-kit-accordion.mjs +454 -0
  3. package/fesm2022/lifecorner-angular-ui-kit-accordion.mjs.map +1 -0
  4. package/fesm2022/lifecorner-angular-ui-kit-alert.mjs +297 -0
  5. package/fesm2022/lifecorner-angular-ui-kit-alert.mjs.map +1 -0
  6. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +190 -0
  7. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -0
  8. package/fesm2022/lifecorner-angular-ui-kit-area-chart.mjs +446 -0
  9. package/fesm2022/lifecorner-angular-ui-kit-area-chart.mjs.map +1 -0
  10. package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +158 -0
  11. package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -0
  12. package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +216 -0
  13. package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -0
  14. package/fesm2022/lifecorner-angular-ui-kit-badge.mjs +121 -0
  15. package/fesm2022/lifecorner-angular-ui-kit-badge.mjs.map +1 -0
  16. package/fesm2022/lifecorner-angular-ui-kit-bar-chart.mjs +360 -0
  17. package/fesm2022/lifecorner-angular-ui-kit-bar-chart.mjs.map +1 -0
  18. package/fesm2022/lifecorner-angular-ui-kit-bottom-nav.mjs +344 -0
  19. package/fesm2022/lifecorner-angular-ui-kit-bottom-nav.mjs.map +1 -0
  20. package/fesm2022/lifecorner-angular-ui-kit-breadcrumbs.mjs +191 -0
  21. package/fesm2022/lifecorner-angular-ui-kit-breadcrumbs.mjs.map +1 -0
  22. package/fesm2022/lifecorner-angular-ui-kit-button.mjs +423 -0
  23. package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -0
  24. package/fesm2022/lifecorner-angular-ui-kit-calendar.mjs +368 -0
  25. package/fesm2022/lifecorner-angular-ui-kit-calendar.mjs.map +1 -0
  26. package/fesm2022/lifecorner-angular-ui-kit-callout.mjs +203 -0
  27. package/fesm2022/lifecorner-angular-ui-kit-callout.mjs.map +1 -0
  28. package/fesm2022/lifecorner-angular-ui-kit-card.mjs +323 -0
  29. package/fesm2022/lifecorner-angular-ui-kit-card.mjs.map +1 -0
  30. package/fesm2022/lifecorner-angular-ui-kit-chat.mjs +790 -0
  31. package/fesm2022/lifecorner-angular-ui-kit-chat.mjs.map +1 -0
  32. package/fesm2022/lifecorner-angular-ui-kit-checkbox.mjs +325 -0
  33. package/fesm2022/lifecorner-angular-ui-kit-checkbox.mjs.map +1 -0
  34. package/fesm2022/lifecorner-angular-ui-kit-chip.mjs +214 -0
  35. package/fesm2022/lifecorner-angular-ui-kit-chip.mjs.map +1 -0
  36. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +375 -0
  37. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -0
  38. package/fesm2022/lifecorner-angular-ui-kit-code-block.mjs +518 -0
  39. package/fesm2022/lifecorner-angular-ui-kit-code-block.mjs.map +1 -0
  40. package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs +278 -0
  41. package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs.map +1 -0
  42. package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs +688 -0
  43. package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs.map +1 -0
  44. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +494 -0
  45. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -0
  46. package/fesm2022/lifecorner-angular-ui-kit-container.mjs +103 -0
  47. package/fesm2022/lifecorner-angular-ui-kit-container.mjs.map +1 -0
  48. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +308 -0
  49. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -0
  50. package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs +466 -0
  51. package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs.map +1 -0
  52. package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +810 -0
  53. package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -0
  54. package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs +1761 -0
  55. package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs.map +1 -0
  56. package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +165 -0
  57. package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -0
  58. package/fesm2022/lifecorner-angular-ui-kit-diff-viewer.mjs +356 -0
  59. package/fesm2022/lifecorner-angular-ui-kit-diff-viewer.mjs.map +1 -0
  60. package/fesm2022/lifecorner-angular-ui-kit-divider.mjs +119 -0
  61. package/fesm2022/lifecorner-angular-ui-kit-divider.mjs.map +1 -0
  62. package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs +762 -0
  63. package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs.map +1 -0
  64. package/fesm2022/lifecorner-angular-ui-kit-donut-chart.mjs +255 -0
  65. package/fesm2022/lifecorner-angular-ui-kit-donut-chart.mjs.map +1 -0
  66. package/fesm2022/lifecorner-angular-ui-kit-drawer.mjs +308 -0
  67. package/fesm2022/lifecorner-angular-ui-kit-drawer.mjs.map +1 -0
  68. package/fesm2022/lifecorner-angular-ui-kit-email-input.mjs +519 -0
  69. package/fesm2022/lifecorner-angular-ui-kit-email-input.mjs.map +1 -0
  70. package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs +143 -0
  71. package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs.map +1 -0
  72. package/fesm2022/lifecorner-angular-ui-kit-error-display.mjs +306 -0
  73. package/fesm2022/lifecorner-angular-ui-kit-error-display.mjs.map +1 -0
  74. package/fesm2022/lifecorner-angular-ui-kit-field-group.mjs +154 -0
  75. package/fesm2022/lifecorner-angular-ui-kit-field-group.mjs.map +1 -0
  76. package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs +281 -0
  77. package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs.map +1 -0
  78. package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs +258 -0
  79. package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs.map +1 -0
  80. package/fesm2022/lifecorner-angular-ui-kit-footer.mjs +200 -0
  81. package/fesm2022/lifecorner-angular-ui-kit-footer.mjs.map +1 -0
  82. package/fesm2022/lifecorner-angular-ui-kit-funnel-chart.mjs +292 -0
  83. package/fesm2022/lifecorner-angular-ui-kit-funnel-chart.mjs.map +1 -0
  84. package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs +563 -0
  85. package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs.map +1 -0
  86. package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs +314 -0
  87. package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs.map +1 -0
  88. package/fesm2022/lifecorner-angular-ui-kit-gauge.mjs +265 -0
  89. package/fesm2022/lifecorner-angular-ui-kit-gauge.mjs.map +1 -0
  90. package/fesm2022/lifecorner-angular-ui-kit-header.mjs +955 -0
  91. package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -0
  92. package/fesm2022/lifecorner-angular-ui-kit-heatmap.mjs +305 -0
  93. package/fesm2022/lifecorner-angular-ui-kit-heatmap.mjs.map +1 -0
  94. package/fesm2022/lifecorner-angular-ui-kit-hero.mjs +168 -0
  95. package/fesm2022/lifecorner-angular-ui-kit-hero.mjs.map +1 -0
  96. package/fesm2022/lifecorner-angular-ui-kit-icon-names.mjs +9 -0
  97. package/fesm2022/lifecorner-angular-ui-kit-icon-names.mjs.map +1 -0
  98. package/fesm2022/lifecorner-angular-ui-kit-icon.mjs +1026 -0
  99. package/fesm2022/lifecorner-angular-ui-kit-icon.mjs.map +1 -0
  100. package/fesm2022/lifecorner-angular-ui-kit-input.mjs +595 -0
  101. package/fesm2022/lifecorner-angular-ui-kit-input.mjs.map +1 -0
  102. package/fesm2022/lifecorner-angular-ui-kit-internal-chart.mjs +105 -0
  103. package/fesm2022/lifecorner-angular-ui-kit-internal-chart.mjs.map +1 -0
  104. package/fesm2022/lifecorner-angular-ui-kit-internal-overlay.mjs +50 -0
  105. package/fesm2022/lifecorner-angular-ui-kit-internal-overlay.mjs.map +1 -0
  106. package/fesm2022/lifecorner-angular-ui-kit-internal-url.mjs +22 -0
  107. package/fesm2022/lifecorner-angular-ui-kit-internal-url.mjs.map +1 -0
  108. package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs +319 -0
  109. package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs.map +1 -0
  110. package/fesm2022/lifecorner-angular-ui-kit-line-chart.mjs +413 -0
  111. package/fesm2022/lifecorner-angular-ui-kit-line-chart.mjs.map +1 -0
  112. package/fesm2022/lifecorner-angular-ui-kit-list.mjs +338 -0
  113. package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -0
  114. package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +813 -0
  115. package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -0
  116. package/fesm2022/lifecorner-angular-ui-kit-logo.mjs +226 -0
  117. package/fesm2022/lifecorner-angular-ui-kit-logo.mjs.map +1 -0
  118. package/fesm2022/lifecorner-angular-ui-kit-markdown.mjs +756 -0
  119. package/fesm2022/lifecorner-angular-ui-kit-markdown.mjs.map +1 -0
  120. package/fesm2022/lifecorner-angular-ui-kit-menu.mjs +321 -0
  121. package/fesm2022/lifecorner-angular-ui-kit-menu.mjs.map +1 -0
  122. package/fesm2022/lifecorner-angular-ui-kit-modal.mjs +329 -0
  123. package/fesm2022/lifecorner-angular-ui-kit-modal.mjs.map +1 -0
  124. package/fesm2022/lifecorner-angular-ui-kit-models.mjs +0 -0
  125. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +419 -0
  126. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -0
  127. package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +644 -0
  128. package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -0
  129. package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs +401 -0
  130. package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs.map +1 -0
  131. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +266 -0
  132. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -0
  133. package/fesm2022/lifecorner-angular-ui-kit-page-layout.mjs +127 -0
  134. package/fesm2022/lifecorner-angular-ui-kit-page-layout.mjs.map +1 -0
  135. package/fesm2022/lifecorner-angular-ui-kit-pagination.mjs +343 -0
  136. package/fesm2022/lifecorner-angular-ui-kit-pagination.mjs.map +1 -0
  137. package/fesm2022/lifecorner-angular-ui-kit-password-input.mjs +696 -0
  138. package/fesm2022/lifecorner-angular-ui-kit-password-input.mjs.map +1 -0
  139. package/fesm2022/lifecorner-angular-ui-kit-pie-chart.mjs +162 -0
  140. package/fesm2022/lifecorner-angular-ui-kit-pie-chart.mjs.map +1 -0
  141. package/fesm2022/lifecorner-angular-ui-kit-pipeline.mjs +159 -0
  142. package/fesm2022/lifecorner-angular-ui-kit-pipeline.mjs.map +1 -0
  143. package/fesm2022/lifecorner-angular-ui-kit-popover.mjs +190 -0
  144. package/fesm2022/lifecorner-angular-ui-kit-popover.mjs.map +1 -0
  145. package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs +190 -0
  146. package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs.map +1 -0
  147. package/fesm2022/lifecorner-angular-ui-kit-progress-ring.mjs +175 -0
  148. package/fesm2022/lifecorner-angular-ui-kit-progress-ring.mjs.map +1 -0
  149. package/fesm2022/lifecorner-angular-ui-kit-provider-button.mjs +255 -0
  150. package/fesm2022/lifecorner-angular-ui-kit-provider-button.mjs.map +1 -0
  151. package/fesm2022/lifecorner-angular-ui-kit-radar-chart.mjs +309 -0
  152. package/fesm2022/lifecorner-angular-ui-kit-radar-chart.mjs.map +1 -0
  153. package/fesm2022/lifecorner-angular-ui-kit-radio.mjs +708 -0
  154. package/fesm2022/lifecorner-angular-ui-kit-radio.mjs.map +1 -0
  155. package/fesm2022/lifecorner-angular-ui-kit-rating.mjs +327 -0
  156. package/fesm2022/lifecorner-angular-ui-kit-rating.mjs.map +1 -0
  157. package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs +718 -0
  158. package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs.map +1 -0
  159. package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs +415 -0
  160. package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs.map +1 -0
  161. package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs +290 -0
  162. package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs.map +1 -0
  163. package/fesm2022/lifecorner-angular-ui-kit-section.mjs +127 -0
  164. package/fesm2022/lifecorner-angular-ui-kit-section.mjs.map +1 -0
  165. package/fesm2022/lifecorner-angular-ui-kit-select.mjs +650 -0
  166. package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -0
  167. package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +691 -0
  168. package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -0
  169. package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs +144 -0
  170. package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs.map +1 -0
  171. package/fesm2022/lifecorner-angular-ui-kit-slider.mjs +204 -0
  172. package/fesm2022/lifecorner-angular-ui-kit-slider.mjs.map +1 -0
  173. package/fesm2022/lifecorner-angular-ui-kit-spacer.mjs +73 -0
  174. package/fesm2022/lifecorner-angular-ui-kit-spacer.mjs.map +1 -0
  175. package/fesm2022/lifecorner-angular-ui-kit-sparkline.mjs +318 -0
  176. package/fesm2022/lifecorner-angular-ui-kit-sparkline.mjs.map +1 -0
  177. package/fesm2022/lifecorner-angular-ui-kit-spinner.mjs +95 -0
  178. package/fesm2022/lifecorner-angular-ui-kit-spinner.mjs.map +1 -0
  179. package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs +298 -0
  180. package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs.map +1 -0
  181. package/fesm2022/lifecorner-angular-ui-kit-stack.mjs +162 -0
  182. package/fesm2022/lifecorner-angular-ui-kit-stack.mjs.map +1 -0
  183. package/fesm2022/lifecorner-angular-ui-kit-stacked-bar-chart.mjs +412 -0
  184. package/fesm2022/lifecorner-angular-ui-kit-stacked-bar-chart.mjs.map +1 -0
  185. package/fesm2022/lifecorner-angular-ui-kit-stage-list.mjs +186 -0
  186. package/fesm2022/lifecorner-angular-ui-kit-stage-list.mjs.map +1 -0
  187. package/fesm2022/lifecorner-angular-ui-kit-stat-trend.mjs +224 -0
  188. package/fesm2022/lifecorner-angular-ui-kit-stat-trend.mjs.map +1 -0
  189. package/fesm2022/lifecorner-angular-ui-kit-status-dot.mjs +122 -0
  190. package/fesm2022/lifecorner-angular-ui-kit-status-dot.mjs.map +1 -0
  191. package/fesm2022/lifecorner-angular-ui-kit-stepper.mjs +209 -0
  192. package/fesm2022/lifecorner-angular-ui-kit-stepper.mjs.map +1 -0
  193. package/fesm2022/lifecorner-angular-ui-kit-switch.mjs +249 -0
  194. package/fesm2022/lifecorner-angular-ui-kit-switch.mjs.map +1 -0
  195. package/fesm2022/lifecorner-angular-ui-kit-table.mjs +1434 -0
  196. package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -0
  197. package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs +407 -0
  198. package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs.map +1 -0
  199. package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs +380 -0
  200. package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs.map +1 -0
  201. package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +440 -0
  202. package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -0
  203. package/fesm2022/lifecorner-angular-ui-kit-theme.mjs +145 -0
  204. package/fesm2022/lifecorner-angular-ui-kit-theme.mjs.map +1 -0
  205. package/fesm2022/lifecorner-angular-ui-kit-timeline.mjs +262 -0
  206. package/fesm2022/lifecorner-angular-ui-kit-timeline.mjs.map +1 -0
  207. package/fesm2022/lifecorner-angular-ui-kit-toast.mjs +352 -0
  208. package/fesm2022/lifecorner-angular-ui-kit-toast.mjs.map +1 -0
  209. package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs +215 -0
  210. package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs.map +1 -0
  211. package/fesm2022/lifecorner-angular-ui-kit-tokens.mjs +134 -0
  212. package/fesm2022/lifecorner-angular-ui-kit-tokens.mjs.map +1 -0
  213. package/fesm2022/lifecorner-angular-ui-kit-toolbar.mjs +225 -0
  214. package/fesm2022/lifecorner-angular-ui-kit-toolbar.mjs.map +1 -0
  215. package/fesm2022/lifecorner-angular-ui-kit-tooltip.mjs +386 -0
  216. package/fesm2022/lifecorner-angular-ui-kit-tooltip.mjs.map +1 -0
  217. package/fesm2022/lifecorner-angular-ui-kit-tree-view.mjs +509 -0
  218. package/fesm2022/lifecorner-angular-ui-kit-tree-view.mjs.map +1 -0
  219. package/fesm2022/lifecorner-angular-ui-kit-typography.mjs +209 -0
  220. package/fesm2022/lifecorner-angular-ui-kit-typography.mjs.map +1 -0
  221. package/fesm2022/lifecorner-angular-ui-kit-verification-code-input.mjs +365 -0
  222. package/fesm2022/lifecorner-angular-ui-kit-verification-code-input.mjs.map +1 -0
  223. package/fesm2022/lifecorner-angular-ui-kit-waterfall-chart.mjs +371 -0
  224. package/fesm2022/lifecorner-angular-ui-kit-waterfall-chart.mjs.map +1 -0
  225. package/fesm2022/lifecorner-angular-ui-kit.mjs +109 -38925
  226. package/package.json +449 -1
  227. package/types/lifecorner-angular-ui-kit-accordion.d.ts +239 -0
  228. package/types/lifecorner-angular-ui-kit-alert.d.ts +189 -0
  229. package/types/lifecorner-angular-ui-kit-app-shell.d.ts +148 -0
  230. package/types/lifecorner-angular-ui-kit-area-chart.d.ts +180 -0
  231. package/types/lifecorner-angular-ui-kit-avatar-group.d.ts +62 -0
  232. package/types/lifecorner-angular-ui-kit-avatar.d.ts +131 -0
  233. package/types/lifecorner-angular-ui-kit-badge.d.ts +59 -0
  234. package/types/lifecorner-angular-ui-kit-bar-chart.d.ts +157 -0
  235. package/types/lifecorner-angular-ui-kit-bottom-nav.d.ts +184 -0
  236. package/types/lifecorner-angular-ui-kit-breadcrumbs.d.ts +55 -0
  237. package/types/lifecorner-angular-ui-kit-button.d.ts +181 -0
  238. package/types/lifecorner-angular-ui-kit-calendar.d.ts +136 -0
  239. package/types/lifecorner-angular-ui-kit-callout.d.ts +77 -0
  240. package/types/lifecorner-angular-ui-kit-card.d.ts +213 -0
  241. package/types/lifecorner-angular-ui-kit-chat.d.ts +379 -0
  242. package/types/lifecorner-angular-ui-kit-checkbox.d.ts +116 -0
  243. package/types/lifecorner-angular-ui-kit-chip.d.ts +104 -0
  244. package/types/lifecorner-angular-ui-kit-choice-prompt.d.ts +186 -0
  245. package/types/lifecorner-angular-ui-kit-code-block.d.ts +85 -0
  246. package/types/lifecorner-angular-ui-kit-color-picker.d.ts +88 -0
  247. package/types/lifecorner-angular-ui-kit-combobox.d.ts +222 -0
  248. package/types/lifecorner-angular-ui-kit-confirm-dialog.d.ts +211 -0
  249. package/types/lifecorner-angular-ui-kit-container.d.ts +47 -0
  250. package/types/lifecorner-angular-ui-kit-copy-field.d.ts +89 -0
  251. package/types/lifecorner-angular-ui-kit-date-range-picker.d.ts +126 -0
  252. package/types/lifecorner-angular-ui-kit-datepicker.d.ts +363 -0
  253. package/types/lifecorner-angular-ui-kit-dependency-viewer.d.ts +568 -0
  254. package/types/lifecorner-angular-ui-kit-description-list.d.ts +137 -0
  255. package/types/lifecorner-angular-ui-kit-diff-viewer.d.ts +93 -0
  256. package/types/lifecorner-angular-ui-kit-divider.d.ts +66 -0
  257. package/types/lifecorner-angular-ui-kit-document-viewer.d.ts +256 -0
  258. package/types/lifecorner-angular-ui-kit-donut-chart.d.ts +92 -0
  259. package/types/lifecorner-angular-ui-kit-drawer.d.ts +124 -0
  260. package/types/lifecorner-angular-ui-kit-email-input.d.ts +292 -0
  261. package/types/lifecorner-angular-ui-kit-empty-state.d.ts +81 -0
  262. package/types/lifecorner-angular-ui-kit-error-display.d.ts +157 -0
  263. package/types/lifecorner-angular-ui-kit-field-group.d.ts +69 -0
  264. package/types/lifecorner-angular-ui-kit-file-upload.d.ts +122 -0
  265. package/types/lifecorner-angular-ui-kit-filter-bar.d.ts +116 -0
  266. package/types/lifecorner-angular-ui-kit-footer.d.ts +97 -0
  267. package/types/lifecorner-angular-ui-kit-funnel-chart.d.ts +97 -0
  268. package/types/lifecorner-angular-ui-kit-gallery.d.ts +240 -0
  269. package/types/lifecorner-angular-ui-kit-gantt-chart.d.ts +133 -0
  270. package/types/lifecorner-angular-ui-kit-gauge.d.ts +94 -0
  271. package/types/lifecorner-angular-ui-kit-header.d.ts +496 -0
  272. package/types/lifecorner-angular-ui-kit-heatmap.d.ts +126 -0
  273. package/types/lifecorner-angular-ui-kit-hero.d.ts +121 -0
  274. package/types/lifecorner-angular-ui-kit-icon-names.d.ts +21 -0
  275. package/types/lifecorner-angular-ui-kit-icon.d.ts +260 -0
  276. package/types/lifecorner-angular-ui-kit-input.d.ts +346 -0
  277. package/types/lifecorner-angular-ui-kit-internal-chart.d.ts +86 -0
  278. package/types/lifecorner-angular-ui-kit-internal-overlay.d.ts +31 -0
  279. package/types/lifecorner-angular-ui-kit-internal-url.d.ts +22 -0
  280. package/types/lifecorner-angular-ui-kit-kanban-board.d.ts +111 -0
  281. package/types/lifecorner-angular-ui-kit-line-chart.d.ts +186 -0
  282. package/types/lifecorner-angular-ui-kit-list.d.ts +215 -0
  283. package/types/lifecorner-angular-ui-kit-log-viewer.d.ts +355 -0
  284. package/types/lifecorner-angular-ui-kit-logo.d.ts +182 -0
  285. package/types/lifecorner-angular-ui-kit-markdown.d.ts +278 -0
  286. package/types/lifecorner-angular-ui-kit-menu.d.ts +152 -0
  287. package/types/lifecorner-angular-ui-kit-modal.d.ts +207 -0
  288. package/types/lifecorner-angular-ui-kit-models.d.ts +62 -0
  289. package/types/lifecorner-angular-ui-kit-next-step-card.d.ts +262 -0
  290. package/types/lifecorner-angular-ui-kit-notification-center.d.ts +237 -0
  291. package/types/lifecorner-angular-ui-kit-number-input.d.ts +126 -0
  292. package/types/lifecorner-angular-ui-kit-page-header.d.ts +178 -0
  293. package/types/lifecorner-angular-ui-kit-page-layout.d.ts +61 -0
  294. package/types/lifecorner-angular-ui-kit-pagination.d.ts +141 -0
  295. package/types/lifecorner-angular-ui-kit-password-input.d.ts +361 -0
  296. package/types/lifecorner-angular-ui-kit-pie-chart.d.ts +58 -0
  297. package/types/lifecorner-angular-ui-kit-pipeline.d.ts +89 -0
  298. package/types/lifecorner-angular-ui-kit-popover.d.ts +104 -0
  299. package/types/lifecorner-angular-ui-kit-progress-bar.d.ts +116 -0
  300. package/types/lifecorner-angular-ui-kit-progress-ring.d.ts +67 -0
  301. package/types/lifecorner-angular-ui-kit-provider-button.d.ts +137 -0
  302. package/types/lifecorner-angular-ui-kit-radar-chart.d.ts +113 -0
  303. package/types/lifecorner-angular-ui-kit-radio.d.ts +297 -0
  304. package/types/lifecorner-angular-ui-kit-rating.d.ts +115 -0
  305. package/types/lifecorner-angular-ui-kit-rich-text-editor.d.ts +226 -0
  306. package/types/lifecorner-angular-ui-kit-scatter-plot.d.ts +190 -0
  307. package/types/lifecorner-angular-ui-kit-search-input.d.ts +137 -0
  308. package/types/lifecorner-angular-ui-kit-section.d.ts +34 -0
  309. package/types/lifecorner-angular-ui-kit-select.d.ts +274 -0
  310. package/types/lifecorner-angular-ui-kit-sidenav.d.ts +367 -0
  311. package/types/lifecorner-angular-ui-kit-skeleton.d.ts +61 -0
  312. package/types/lifecorner-angular-ui-kit-slider.d.ts +79 -0
  313. package/types/lifecorner-angular-ui-kit-spacer.d.ts +27 -0
  314. package/types/lifecorner-angular-ui-kit-sparkline.d.ts +113 -0
  315. package/types/lifecorner-angular-ui-kit-spinner.d.ts +50 -0
  316. package/types/lifecorner-angular-ui-kit-split-pane.d.ts +131 -0
  317. package/types/lifecorner-angular-ui-kit-stack.d.ts +49 -0
  318. package/types/lifecorner-angular-ui-kit-stacked-bar-chart.d.ts +171 -0
  319. package/types/lifecorner-angular-ui-kit-stage-list.d.ts +69 -0
  320. package/types/lifecorner-angular-ui-kit-stat-trend.d.ts +62 -0
  321. package/types/lifecorner-angular-ui-kit-status-dot.d.ts +62 -0
  322. package/types/lifecorner-angular-ui-kit-stepper.d.ts +113 -0
  323. package/types/lifecorner-angular-ui-kit-switch.d.ts +141 -0
  324. package/types/lifecorner-angular-ui-kit-table.d.ts +632 -0
  325. package/types/lifecorner-angular-ui-kit-tabs.d.ts +196 -0
  326. package/types/lifecorner-angular-ui-kit-tag-input.d.ts +123 -0
  327. package/types/lifecorner-angular-ui-kit-textarea.d.ts +225 -0
  328. package/types/lifecorner-angular-ui-kit-theme.d.ts +91 -0
  329. package/types/lifecorner-angular-ui-kit-timeline.d.ts +162 -0
  330. package/types/lifecorner-angular-ui-kit-toast.d.ts +204 -0
  331. package/types/lifecorner-angular-ui-kit-toggle-group.d.ts +100 -0
  332. package/types/lifecorner-angular-ui-kit-tokens.d.ts +134 -0
  333. package/types/lifecorner-angular-ui-kit-toolbar.d.ts +120 -0
  334. package/types/lifecorner-angular-ui-kit-tooltip.d.ts +120 -0
  335. package/types/lifecorner-angular-ui-kit-tree-view.d.ts +231 -0
  336. package/types/lifecorner-angular-ui-kit-typography.d.ts +126 -0
  337. package/types/lifecorner-angular-ui-kit-verification-code-input.d.ts +187 -0
  338. package/types/lifecorner-angular-ui-kit-waterfall-chart.d.ts +163 -0
  339. package/types/lifecorner-angular-ui-kit.d.ts +109 -17401
  340. package/fesm2022/lifecorner-angular-ui-kit.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-markdown.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/markdown/markdown.component.ts","../../../../libs/angular-ui-kit/src/lib/markdown/markdown.component.html"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n input,\n output,\n computed,\n signal,\n effect,\n untracked,\n inject,\n ElementRef,\n OnDestroy,\n SecurityContext,\n ViewEncapsulation,\n} from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { HttpClient } from '@angular/common/http';\nimport { Subscription } from 'rxjs';\nimport { CodeBlockComponent, CodeBlockLanguage } from '@lifecorner/angular-ui-kit/code-block';\nimport { isSafeImageUrl, isSafeLinkUrl } from '@lifecorner/angular-ui-kit/internal/url';\n\nexport interface MarkdownHeading {\n level: number;\n text: string;\n id: string;\n}\n\nexport interface MarkdownLinkClick {\n href: string;\n event: MouseEvent;\n}\n\nexport interface MarkdownRendered {\n headings: MarkdownHeading[];\n}\n\nexport interface MarkdownChangesHighlighted {\n /** Number of changed/added blocks highlighted in the current render. */\n changedBlocks: number;\n}\n\nexport interface RenderPart {\n type: 'html' | 'code' | 'mermaid';\n index: number;\n safeHtml?: SafeHtml;\n code?: string;\n lang?: CodeBlockLanguage;\n}\n\n/**\n * Stand-in for a fenced code block while the rest of the markdown is processed.\n * Bracketed in NUL characters, which the source is stripped of first — so no\n * text a user writes can ever spell a placeholder and be mistaken for a block.\n * (The earlier `<!--CODE_BLOCK_N-->` form was: an escaped literal comment in\n * the text matched it and dereferenced a block that wasn't there.)\n */\nconst BLOCK_MARK = '\\u0000';\nconst blockPlaceholder = (idx: number): string => `${BLOCK_MARK}LCBLOCK${idx}${BLOCK_MARK}`;\n// eslint-disable-next-line no-control-regex -- the NUL bracket is the point: unforgeable\nconst BLOCK_PLACEHOLDER = /\\u0000LCBLOCK(\\d+)\\u0000/g;\n\n/** Instances numbered so their mermaid render ids never collide on one page. */\nlet markdownInstances = 0;\n\n/**\n * Markdown renderer component.\n *\n * Renders GitHub-Flavored Markdown (GFM) to sanitized HTML with\n * optional syntax highlighting via `<lc-code-block>`.\n *\n * Supports headings (+ anchors), paragraphs, ordered/unordered lists, task lists\n * (`- [ ]` / `- [x]` → accessible checkbox), blockquotes, horizontal rules,\n * images, GFM tables (column alignment + horizontal scroll), bold/italic/\n * strikethrough, inline code, fenced code (incl. `mermaid`), explicit links and\n * autolinks (bare URLs / `www.` / emails, never inside code).\n *\n * Optionally highlights *changed* blocks in place: pass the pre-edit markdown as\n * `previousContent` and set `highlightChanges` — added/edited blocks (diffed at\n * block / list-item level) gain a left accent bar + subtle tint, can auto-fade\n * (`changeHighlightFadeMs`) and scroll into view (`scrollToFirstChange`).\n *\n * @example\n * ```html\n * <lc-markdown [content]=\"'# Hello World'\" />\n * <lc-markdown [src]=\"'/docs/readme.md'\" />\n * <lc-markdown\n * [content]=\"current\" [previousContent]=\"prev\"\n * [highlightChanges]=\"true\" [changeHighlightFadeMs]=\"3000\" />\n * ```\n */\n@Component({\n selector: 'lc-markdown',\n standalone: true,\n imports: [CodeBlockComponent],\n templateUrl: './markdown.component.html',\n styleUrls: ['./markdown.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class MarkdownComponent implements OnDestroy {\n private readonly sanitizer = inject(DomSanitizer);\n private readonly instanceId = ++markdownInstances;\n private readonly http = inject(HttpClient);\n private readonly host = inject(ElementRef<HTMLElement>);\n private httpSub?: Subscription;\n private fadeTimer?: ReturnType<typeof setTimeout>;\n private scrollTimer?: ReturnType<typeof setTimeout>;\n private mermaidApiPromise?: Promise<any>;\n private mermaidInitialized = false;\n private mermaidRenderRun = 0;\n\n /** URL or path to load markdown from */\n readonly src = input<string>();\n\n /** Raw markdown string */\n readonly content = input<string>();\n\n /** Display variant */\n readonly variant = input<'default' | 'compact' | 'chat'>('default');\n\n /** Target for links */\n readonly linkTarget = input<'_self' | '_blank'>('_self');\n\n /** Whether to sanitize HTML output */\n readonly sanitize = input<boolean>(true);\n\n /** Whether to use code-block for fenced code */\n readonly syntaxHighlight = input<boolean>(true);\n\n /** Whether to show anchor links on headings */\n readonly showHeadingAnchors = input<boolean>(false);\n\n /** Base URL for resolving relative links/images */\n readonly baseUrl = input<string>();\n\n // -- Change highlighting --\n /** Enable change highlighting (requires `previousContent` to compute a diff). */\n readonly highlightChanges = input<boolean>(false);\n\n /**\n * The prior Markdown. When it differs from `content`, the changed/added blocks\n * in `content` are highlighted. The caller passes the pre-edit markdown.\n */\n readonly previousContent = input<string>();\n\n /** Auto-fade the highlight after N ms. 0 / undefined ⇒ persist until content changes. */\n readonly changeHighlightFadeMs = input<number>();\n\n /** Scroll the first changed block into view when highlights appear. */\n readonly scrollToFirstChange = input<boolean>(false);\n\n /** Screen-reader marker put in front of each highlighted block (`highlightChanges`). */\n readonly changedMarkerLabel = input('(geändert)');\n\n /** Announced after the count when one block changed: `1 Abschnitt geändert`. */\n readonly changedSummaryOneLabel = input('Abschnitt geändert');\n\n /** Announced after the count when several blocks changed: `3 Abschnitte geändert`. */\n readonly changedSummaryManyLabel = input('Abschnitte geändert');\n\n /** Shown while a Mermaid diagram renders. */\n readonly mermaidLoadingLabel = input('Rendering Mermaid diagram...');\n\n /** Shown above the source when a Mermaid diagram fails. */\n readonly mermaidErrorLabel = input('Mermaid diagram could not be rendered.');\n\n /** Shown above the source when the optional `mermaid` package cannot be loaded. */\n readonly mermaidUnavailableLabel = input('Mermaid runtime is not available.');\n\n /** Emitted when a link is clicked */\n readonly linkClick = output<MarkdownLinkClick>();\n\n /** Emitted after rendering with heading TOC */\n readonly rendered = output<MarkdownRendered>();\n\n /** Emitted after a render that produced change highlights. */\n readonly changesHighlighted = output<MarkdownChangesHighlighted>();\n\n /** Internal resolved markdown source */\n protected resolvedMarkdown = signal<string>('');\n\n /** Parsed result (computed once from resolvedMarkdown) */\n private parsed = computed(() => {\n const md = this.resolvedMarkdown();\n if (!md) {\n return {\n html: '',\n blocks: [] as { kind: 'code' | 'mermaid'; lang: string; code: string }[],\n headings: [] as MarkdownHeading[],\n };\n }\n return this.parseMarkdown(md);\n });\n\n /**\n * Rendered HTML after applying change highlights. When highlighting is off (or\n * there is no differing `previousContent`) this returns the parsed HTML\n * unchanged, so the non-highlight path is byte-for-byte identical to before.\n */\n private readonly highlightResult = computed<{ html: string; count: number }>(() => {\n const { html } = this.parsed();\n const prev = this.previousContent();\n if (\n !html ||\n !this.highlightChanges() ||\n prev == null ||\n prev === this.resolvedMarkdown()\n ) {\n return { html, count: 0 };\n }\n return this.applyChangeHighlights(html, prev);\n });\n\n /** Number of changed/added blocks highlighted in the current render. */\n protected readonly changedCount = computed(() => this.highlightResult().count);\n\n /** Visually-hidden polite summary announced when highlights appear. */\n protected readonly changeSummary = computed(() => {\n const n = this.changedCount();\n if (n <= 0) return '';\n return `${n} ${n === 1 ? this.changedSummaryOneLabel() : this.changedSummaryManyLabel()}`;\n });\n\n /** Whether the current highlights have faded out (after `changeHighlightFadeMs`). */\n protected readonly highlightsFaded = signal(false);\n\n /** Computed render parts (HTML chunks + code blocks interleaved) */\n protected renderParts = computed<RenderPart[]>(() => {\n const html = this.highlightResult().html;\n const { blocks } = this.parsed();\n if (!html) return [];\n\n if (this.syntaxHighlight() && blocks.length > 0) {\n return this.splitIntoParts(html, blocks);\n }\n\n // No code blocks — single HTML part\n return [{\n type: 'html',\n index: 0,\n safeHtml: this.sanitizer.bypassSecurityTrustHtml(this.sanitizeHtml(html, { next: 0 })),\n }];\n });\n\n /**\n * The HTML as it may go into the DOM. With `sanitize` on (the default) that is\n * Angular's HTML sanitizer's output — which drops every `id`, since `id` isn't\n * on its attribute allow-list. The heading ids are put back afterwards: they\n * are what anchors and the `rendered` TOC point at, and each is a `[\\w-]`\n * slug this parser produced itself, so re-adding them reopens nothing. The\n * cursor walks the parsed headings in document order across the parts.\n */\n private sanitizeHtml(html: string, cursor: { next: number }): string {\n const headings = this.headings();\n if (!this.sanitize()) {\n cursor.next += (html.match(/<h[1-6]\\b/g) ?? []).length;\n return html;\n }\n const sanitized = this.sanitizer.sanitize(SecurityContext.HTML, html) || '';\n return sanitized.replace(/<h([1-6])(\\s[^>]*)?>/g, (tag, level: string, attrs = '') => {\n const heading = headings[cursor.next++];\n if (!heading || /\\sid=/.test(attrs)) return tag;\n return `<h${level} id=\"${heading.id}\"${attrs}>`;\n });\n }\n\n protected containerClasses = computed(() => {\n let classes = `lc-markdown lc-markdown--${this.variant()}`;\n if (this.highlightsFaded()) classes += ' lc-markdown--faded';\n return classes;\n });\n\n protected mermaidSvgs = signal<Record<number, SafeHtml>>({});\n protected mermaidErrors = signal<Record<number, string>>({});\n\n private headings = computed(() => this.parsed().headings);\n\n constructor() {\n // Load content from src when src changes\n effect(() => {\n const src = this.src();\n if (src) {\n this.loadFromUrl(src);\n }\n });\n\n // Use raw content when provided\n effect(() => {\n const content = this.content();\n if (content !== undefined) {\n this.resolvedMarkdown.set(content);\n }\n });\n\n // Emit rendered event whenever a render produced a (possibly empty) TOC\n effect(() => {\n const h = this.headings();\n untracked(() => this.rendered.emit({ headings: h }));\n });\n\n // Render Mermaid code fences as inline SVG diagrams.\n effect(() => {\n void this.renderMermaidParts(this.renderParts());\n });\n\n // React to a render that produced change highlights: emit, schedule fade,\n // and optionally scroll the first changed block into view.\n effect(() => {\n const count = this.highlightResult().count;\n untracked(() => this.onHighlightResult(count));\n });\n }\n\n ngOnDestroy(): void {\n this.httpSub?.unsubscribe();\n clearTimeout(this.fadeTimer);\n clearTimeout(this.scrollTimer);\n }\n\n protected onLinkClick(event: MouseEvent): void {\n const target = event.target as HTMLElement;\n const anchor = target.closest('a');\n if (anchor) {\n this.linkClick.emit({ href: anchor.href, event });\n }\n }\n\n // -- Change highlighting -----------------------------------------------------\n\n /** Side-effects for a render: emit, (re)arm the fade timer, optional scroll. */\n private onHighlightResult(count: number): void {\n clearTimeout(this.fadeTimer);\n clearTimeout(this.scrollTimer);\n // A fresh render starts un-faded (re-entrant: never reuse stale fade state).\n this.highlightsFaded.set(false);\n if (count <= 0) return;\n\n this.changesHighlighted.emit({ changedBlocks: count });\n\n const fadeMs = this.changeHighlightFadeMs();\n if (fadeMs && fadeMs > 0) {\n this.fadeTimer = setTimeout(() => this.highlightsFaded.set(true), fadeMs);\n }\n if (this.scrollToFirstChange()) {\n // Defer until the highlighted HTML has been written to the DOM.\n this.scrollTimer = setTimeout(() => this.scrollToFirstChanged(), 0);\n }\n }\n\n private scrollToFirstChanged(): void {\n if (typeof document === 'undefined') return;\n const el = this.host.nativeElement.querySelector('.lc-markdown__block--changed');\n el?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n }\n\n /**\n * Wraps the changed/added top-level blocks of `html` with\n * `.lc-markdown__block--changed`. A block is \"changed\" when its normalized\n * text is not present among the blocks of `prevMarkdown`. Lists are diffed\n * per `<li>` and tables per `<tr>` so a single edited item highlights alone.\n */\n private applyChangeHighlights(\n html: string,\n prevMarkdown: string\n ): { html: string; count: number } {\n if (typeof document === 'undefined') return { html, count: 0 };\n\n const prevKeys = this.collectBlockKeys(this.parseMarkdown(prevMarkdown).html);\n const root = this.htmlToElement(html);\n if (!root) return { html, count: 0 };\n\n let count = 0;\n const markIfChanged = (el: Element): void => {\n const key = this.blockTextKey(el.textContent ?? '');\n if (!key || prevKeys.has(key)) return;\n el.classList.add('lc-markdown__block--changed');\n const sr = document.createElement('span');\n sr.className = 'lc-markdown__sr-only';\n sr.textContent = `${this.changedMarkerLabel()} `;\n el.insertBefore(sr, el.firstChild);\n count++;\n };\n\n this.eachLogicalBlock(root, markIfChanged);\n return { html: root.innerHTML, count };\n }\n\n /** Normalized text set of the logical blocks within an HTML fragment. */\n private collectBlockKeys(html: string): Set<string> {\n const keys = new Set<string>();\n const root = this.htmlToElement(html);\n if (!root) return keys;\n this.eachLogicalBlock(root, (el) => {\n const key = this.blockTextKey(el.textContent ?? '');\n if (key) keys.add(key);\n });\n return keys;\n }\n\n /**\n * Visits each diffable block under `root`: top-level elements, but descending\n * into `<ul>`/`<ol>` (per `<li>`) and `<table>` (per `<tr>`).\n */\n private eachLogicalBlock(root: Element, visit: (el: Element) => void): void {\n for (const node of Array.from(root.childNodes)) {\n if (node.nodeType !== 1) continue; // elements only (skips code placeholders)\n const el = node as Element;\n const tag = el.tagName;\n if (tag === 'UL' || tag === 'OL') {\n for (const li of Array.from(el.children)) {\n if (li.tagName === 'LI') visit(li);\n }\n } else if (tag === 'TABLE' || el.querySelector('table')) {\n // Tables (incl. the scroll wrapper div) diff per row.\n for (const tr of Array.from(el.querySelectorAll('tr'))) {\n visit(tr);\n }\n } else {\n visit(el);\n }\n }\n }\n\n private blockTextKey(text: string): string {\n return text.replace(/\\s+/g, ' ').trim().toLowerCase();\n }\n\n private htmlToElement(html: string): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n const div = document.createElement('div');\n div.innerHTML = html;\n return div;\n }\n\n private loadFromUrl(url: string): void {\n this.httpSub?.unsubscribe();\n this.httpSub = this.http.get(url, { responseType: 'text' }).subscribe({\n next: (text) => this.resolvedMarkdown.set(text),\n error: () => this.resolvedMarkdown.set(`*Failed to load ${url}*`),\n });\n }\n\n private splitIntoParts(\n html: string,\n blocks: { kind: 'code' | 'mermaid'; lang: string; code: string }[]\n ): RenderPart[] {\n const parts: RenderPart[] = [];\n const regex = new RegExp(BLOCK_PLACEHOLDER.source, 'g');\n const cursor = { next: 0 };\n let lastIndex = 0;\n let partIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(html)) !== null) {\n const before = html.slice(lastIndex, match.index);\n if (before.trim()) {\n parts.push({\n type: 'html',\n index: partIndex++,\n safeHtml: this.sanitizer.bypassSecurityTrustHtml(this.sanitizeHtml(before, cursor)),\n });\n }\n const block = blocks[parseInt(match[1], 10)];\n lastIndex = match.index + match[0].length;\n // Unforgeable placeholder, so this can only be a bug — but never a crash.\n if (!block) continue;\n if (block.kind === 'mermaid') {\n parts.push({\n type: 'mermaid',\n index: partIndex++,\n code: block.code,\n });\n } else {\n parts.push({\n type: 'code',\n index: partIndex++,\n code: block.code,\n lang: block.lang as CodeBlockLanguage,\n });\n }\n }\n\n const remaining = html.slice(lastIndex);\n if (remaining.trim()) {\n parts.push({\n type: 'html',\n index: partIndex++,\n safeHtml: this.sanitizer.bypassSecurityTrustHtml(this.sanitizeHtml(remaining, cursor)),\n });\n }\n\n return parts;\n }\n\n private parseMarkdown(md: string): {\n html: string;\n blocks: { kind: 'code' | 'mermaid'; lang: string; code: string }[];\n headings: MarkdownHeading[];\n } {\n const blocks: { kind: 'code' | 'mermaid'; lang: string; code: string }[] = [];\n const headings: MarkdownHeading[] = [];\n const baseUrl = this.baseUrl();\n const linkTarget = this.linkTarget();\n const showAnchors = this.showHeadingAnchors();\n\n // 1. Extract fenced code blocks → placeholders (see BLOCK_MARK: the source\n // is stripped of the marker character first, so it can't forge one)\n // eslint-disable-next-line no-control-regex -- strip the placeholder marker (see BLOCK_MARK)\n let processed = md.replace(/\\u0000/g, '').replace(\n /```(\\w*)\\n([\\s\\S]*?)```/g,\n (_match, lang: string, code: string) => {\n const idx = blocks.length;\n const normalizedLang = (lang || 'text').toLowerCase();\n blocks.push({\n kind: normalizedLang === 'mermaid' ? 'mermaid' : 'code',\n lang: normalizedLang,\n code: code.trimEnd(),\n });\n return blockPlaceholder(idx);\n }\n );\n\n // 2. Escape HTML entities — quotes included, so nothing the parser later\n // interpolates into an attribute (link/image URLs, alt text) can close it.\n processed = this.escapeHtml(processed);\n\n // 3. Headings (# to ######)\n processed = processed.replace(\n /^(#{1,6})\\s+(.+)$/gm,\n (_match, hashes: string, text: string) => {\n const level = hashes.length;\n const id = text\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n headings.push({ level, text, id });\n const anchor = showAnchors\n ? `<a href=\"#${id}\" class=\"lc-markdown__anchor\" aria-hidden=\"true\">#</a>`\n : '';\n return `<h${level} id=\"${id}\">${anchor}${text}</h${level}>`;\n }\n );\n\n // 4. Horizontal rules\n processed = processed.replace(/^---+$/gm, '<hr>');\n\n // 5. Blockquotes\n processed = processed.replace(\n /^(?:&gt;)\\s?(.*)$/gm,\n '<blockquote>$1</blockquote>'\n );\n // Merge consecutive blockquotes\n processed = processed.replace(\n /<\\/blockquote>\\n<blockquote>/g,\n '\\n'\n );\n\n // 6. Tables (GFM)\n processed = this.parseTables(processed);\n\n // 7. Task lists. Angular's HTML sanitizer strips <input>, so the checkbox is\n // rendered as a styled <span role=\"checkbox\"> (which survives sanitization and\n // carries accessible checked/disabled state) rather than a form control.\n processed = processed.replace(\n /^[-*]\\s+\\[[xX]\\]\\s+(.*)$/gm,\n '<li class=\"lc-markdown__task-item\">' +\n '<span class=\"lc-markdown__checkbox lc-markdown__checkbox--checked\" role=\"checkbox\" aria-checked=\"true\" aria-disabled=\"true\"></span>' +\n '<span class=\"lc-markdown__task-label\">$1</span></li>'\n );\n processed = processed.replace(\n /^[-*]\\s+\\[ \\]\\s+(.*)$/gm,\n '<li class=\"lc-markdown__task-item\">' +\n '<span class=\"lc-markdown__checkbox\" role=\"checkbox\" aria-checked=\"false\" aria-disabled=\"true\"></span>' +\n '<span class=\"lc-markdown__task-label\">$1</span></li>'\n );\n\n // 8. Unordered lists\n processed = processed.replace(\n /^[-*]\\s+(.*)$/gm,\n '<li>$1</li>'\n );\n // Wrap consecutive <li> in <ul>\n processed = processed.replace(\n /((?:<li[^>]*>.*<\\/li>\\n?)+)/g,\n '<ul>$1</ul>'\n );\n\n // 9. Ordered lists — marked while wrapping, so a run of them gets its <ol>\n // and isn't confused with the <li>s already inside <ul>s above.\n processed = processed.replace(\n /^\\d+\\.\\s+(.*)$/gm,\n '<li data-ol>$1</li>'\n );\n processed = processed.replace(\n /((?:<li data-ol>.*<\\/li>\\n?)+)/g,\n (run) => `<ol>${run.replace(/ data-ol/g, '')}</ol>`\n );\n\n // 10. Inline code\n processed = processed.replace(\n /`([^`]+)`/g,\n '<code>$1</code>'\n );\n\n // 11. Bold + italic combos\n processed = processed.replace(\n /\\*\\*\\*(.+?)\\*\\*\\*/g,\n '<strong><em>$1</em></strong>'\n );\n processed = processed.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/\\*(.+?)\\*/g, '<em>$1</em>');\n\n // 12. Strikethrough (GFM)\n processed = processed.replace(/~~(.+?)~~/g, '<del>$1</del>');\n\n // 13. Images. Only allow-listed URL schemes become a `src` (see\n // safe-url.ts); anything else — `javascript:`, unknown schemes — is\n // rendered as its alt text. This holds regardless of `sanitize`.\n processed = processed.replace(\n /!\\[([^\\]]*)\\]\\(([^)]+)\\)/g,\n (_match, alt: string, src: string) => {\n if (!isSafeImageUrl(src)) return alt;\n const resolvedSrc = baseUrl && !src.startsWith('http') ? `${baseUrl}/${src}` : src;\n return `<img src=\"${resolvedSrc}\" alt=\"${alt}\" class=\"lc-markdown__img\">`;\n }\n );\n\n // 14. Links — same rule: an unsafe URL leaves plain text, not a link.\n processed = processed.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_match, text: string, href: string) => {\n if (!isSafeLinkUrl(href)) return text;\n const resolvedHref = baseUrl && !href.startsWith('http') && !href.startsWith('#')\n ? `${baseUrl}/${href}`\n : href;\n return `<a href=\"${resolvedHref}\" target=\"${linkTarget}\" rel=\"noopener\">${text}</a>`;\n }\n );\n\n // 14b. Autolinks — linkify bare URLs / www / emails in plain text. Runs after\n // explicit links and inline code so it can skip anything already inside an\n // <a> or <code> (and never touches tag attributes).\n processed = this.autolink(processed, linkTarget);\n\n // 15. Paragraphs — wrap standalone lines\n processed = processed\n .split('\\n\\n')\n .map((block) => {\n const trimmed = block.trim();\n if (!trimmed) return '';\n if (\n trimmed.startsWith('<h') ||\n trimmed.startsWith('<ul') ||\n trimmed.startsWith('<ol') ||\n trimmed.startsWith('<blockquote') ||\n trimmed.startsWith('<hr') ||\n trimmed.startsWith('<table') ||\n trimmed.startsWith('<div') ||\n trimmed.startsWith(BLOCK_MARK)\n ) {\n return trimmed;\n }\n return `<p>${trimmed.replace(/\\n/g, '<br>')}</p>`;\n })\n .join('\\n');\n\n // 16. Restore code block placeholders\n if (this.syntaxHighlight()) {\n // Leave placeholders — the template will render <lc-code-block> for each\n // No replacement needed here\n } else {\n processed = processed.replace(\n new RegExp(BLOCK_PLACEHOLDER.source, 'g'),\n (_match, idx: string) => {\n const block = blocks[parseInt(idx, 10)];\n if (!block) return '';\n return `<pre><code class=\"language-${block.lang}\">${this.escapeHtml(block.code)}</code></pre>`;\n }\n );\n }\n\n return { html: processed, blocks, headings };\n }\n\n private parseTables(text: string): string {\n return text.replace(\n /^(\\|.+\\|)\\n(\\|[-| :]+\\|)\\n((?:\\|.+\\|\\n?)*)/gm,\n (_match, header: string, separator: string, body: string) => {\n // Per-column alignment from the delimiter row: :--- left, :--: center,\n // ---: right. Surfaced as classes (the sanitizer strips inline `style`).\n const aligns = this.splitTableRow(separator).map((cell) => {\n const left = cell.startsWith(':');\n const right = cell.endsWith(':');\n if (left && right) return 'center';\n if (right) return 'right';\n if (left) return 'left';\n return '';\n });\n const alignClass = (col: number): string =>\n aligns[col] ? ` class=\"lc-markdown__cell--${aligns[col]}\"` : '';\n\n const headers = this.splitTableRow(header)\n .map((cell, i) => `<th scope=\"col\"${alignClass(i)}>${cell.trim()}</th>`)\n .join('');\n\n const rows = body\n .trim()\n .split('\\n')\n .map((row: string) => {\n const cells = this.splitTableRow(row)\n .map((cell, i) => `<td${alignClass(i)}>${cell.trim()}</td>`)\n .join('');\n return `<tr>${cells}</tr>`;\n })\n .join('');\n\n // Wrapped so wide tables scroll horizontally instead of breaking layout.\n return (\n `<div class=\"lc-markdown__table-wrap\">` +\n `<table class=\"lc-markdown__table\"><thead><tr>${headers}</tr></thead><tbody>${rows}</tbody></table>` +\n `</div>`\n );\n }\n );\n }\n\n /** Splits a pipe-table row into trimmed cells, dropping the leading/trailing edges. */\n private splitTableRow(row: string): string[] {\n return row\n .trim()\n .replace(/^\\|/, '')\n .replace(/\\|$/, '')\n .split('|')\n .map((cell) => cell.trim());\n }\n\n private escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n }\n\n /**\n * Linkifies bare URLs (`http(s)://…`, `www.…`) and email addresses in text,\n * leaving anything inside an existing `<a>` or `<code>` (and all tag\n * attributes) untouched. The HTML is tokenized into tags vs. text so only\n * top-level text runs are linkified.\n */\n private autolink(html: string, linkTarget: string): string {\n const url = /(?:https?:\\/\\/|www\\.)[^\\s<]*[^\\s<.,:;!?)\\]}'\"]/;\n const email = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}/;\n const pattern = new RegExp(`${url.source}|${email.source}`, 'g');\n\n let depth = 0; // inside <a> or <code>\n return html\n .split(/(<[^>]+>)/g)\n .map((segment) => {\n if (segment.startsWith('<')) {\n if (/^<(a|code)[\\s>]/i.test(segment)) depth++;\n else if (/^<\\/(a|code)>/i.test(segment)) depth = Math.max(0, depth - 1);\n return segment;\n }\n if (depth > 0 || !segment) return segment;\n return segment.replace(pattern, (token) => {\n const isEmail = token.includes('@') && !/^(?:https?:\\/\\/|www\\.)/.test(token);\n const href = isEmail\n ? `mailto:${token}`\n : token.startsWith('www.')\n ? `https://${token}`\n : token;\n return `<a href=\"${href}\" target=\"${linkTarget}\" rel=\"noopener\">${token}</a>`;\n });\n })\n .join('');\n }\n\n protected mermaidSvgFor(index: number): SafeHtml | null {\n return this.mermaidSvgs()[index] ?? null;\n }\n\n protected mermaidErrorFor(index: number): string | null {\n return this.mermaidErrors()[index] ?? null;\n }\n\n private async renderMermaidParts(parts: RenderPart[]): Promise<void> {\n const mermaidParts = parts.filter((part) => part.type === 'mermaid' && !!part.code);\n this.mermaidSvgs.set({});\n this.mermaidErrors.set({});\n\n if (mermaidParts.length === 0) {\n return;\n }\n\n const runId = ++this.mermaidRenderRun;\n\n try {\n const mermaidApi = await this.getMermaidApi();\n if (runId !== this.mermaidRenderRun) return;\n\n const nextSvgs: Record<number, SafeHtml> = {};\n const nextErrors: Record<number, string> = {};\n\n for (const part of mermaidParts) {\n try {\n // Per instance, per run, per part: mermaid's render() removes any\n // element already carrying the id it is given, so an id shared with\n // another <lc-markdown> on the page would delete that one's diagram.\n const renderId = `lc-md-mermaid-${this.instanceId}-${runId}-${part.index}`;\n const { svg } = await mermaidApi.render(renderId, part.code!);\n if (runId !== this.mermaidRenderRun) return;\n // Mermaid emits self-contained SVG with internal <style> rules.\n // Angular HTML sanitization strips critical style declarations,\n // which leaves only labels visible (no edges/shapes). We trust\n // Mermaid output here and rely on Mermaid's strict security mode.\n nextSvgs[part.index] = this.sanitizer.bypassSecurityTrustHtml(svg);\n } catch {\n nextErrors[part.index] = this.mermaidErrorLabel();\n }\n }\n\n if (runId !== this.mermaidRenderRun) return;\n this.mermaidSvgs.set(nextSvgs);\n this.mermaidErrors.set(nextErrors);\n } catch {\n if (runId !== this.mermaidRenderRun) return;\n const fallbackErrors: Record<number, string> = {};\n for (const part of mermaidParts) {\n fallbackErrors[part.index] = this.mermaidUnavailableLabel();\n }\n this.mermaidErrors.set(fallbackErrors);\n }\n }\n\n private async getMermaidApi(): Promise<any> {\n if (!this.mermaidApiPromise) {\n this.mermaidApiPromise = import('mermaid').then((module) => {\n const api = module.default ?? module;\n if (!this.mermaidInitialized) {\n api.initialize({\n startOnLoad: false,\n securityLevel: 'strict',\n });\n this.mermaidInitialized = true;\n }\n return api;\n });\n }\n return this.mermaidApiPromise;\n }\n}\n","<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- delegated handler for clicks on rendered links, which are focusable anchors -->\n<div [class]=\"containerClasses()\" (click)=\"onLinkClick($event)\">\n @if (highlightChanges()) {\n <div class=\"lc-markdown__sr-only\" role=\"status\" aria-live=\"polite\">{{ changeSummary() }}</div>\n }\n @for (part of renderParts(); track part.index) {\n @if (part.type === 'html') {\n <div [innerHTML]=\"part.safeHtml\"></div>\n } @else if (part.type === 'code') {\n <lc-code-block\n [code]=\"part.code!\"\n [language]=\"part.lang ?? 'text'\"\n [showLineNumbers]=\"true\"\n [showCopy]=\"true\"\n />\n } @else {\n @if (mermaidSvgFor(part.index); as svg) {\n <div class=\"lc-markdown__mermaid\" [innerHTML]=\"svg\"></div>\n } @else if (mermaidErrorFor(part.index); as errorMessage) {\n <div class=\"lc-markdown__mermaid-fallback\">\n <p class=\"lc-markdown__mermaid-error\">{{ errorMessage }}</p>\n <lc-code-block\n [code]=\"part.code!\"\n [language]=\"'text'\"\n [showLineNumbers]=\"true\"\n [showCopy]=\"true\"\n />\n </div>\n } @else {\n <div class=\"lc-markdown__mermaid-loading\">{{ mermaidLoadingLabel() }}</div>\n }\n }\n }\n</div>\n"],"mappings":"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"}
@@ -0,0 +1,321 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, ElementRef, HostListener, Injector, Renderer2, afterNextRender, afterRenderEffect, effect, inject, input, output, signal, untracked, viewChildren } from "@angular/core";
3
+ import { IconComponent } from "@lifecorner/angular-ui-kit/icon";
4
+ import { OverlayStackService } from "@lifecorner/angular-ui-kit/internal/overlay";
5
+ const INTERACTIVE_SELECTOR = "button, a[href], input, select, textarea, [tabindex]";
6
+ var MenuComponent = class MenuComponent {
7
+ static nextId = 0;
8
+ menuId = `lc-menu-${++MenuComponent.nextId}`;
9
+ items = input([], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
10
+ isOpen = input(false, ...ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []);
11
+ position = input("bottom-right", ...ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []);
12
+ size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
13
+ minWidth = input("220px", ...ngDevMode ? [{ debugName: "minWidth" }] : /* istanbul ignore next */ []);
14
+ maxWidth = input("", ...ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []);
15
+ itemClick = output();
16
+ closed = output();
17
+ panelId = `${this.menuId}-panel`;
18
+ activeIndex = signal(-1, ...ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []);
19
+ itemElements = viewChildren("menuItem", ...ngDevMode ? [{ debugName: "itemElements" }] : /* istanbul ignore next */ []);
20
+ elementRef = inject(ElementRef);
21
+ renderer = inject(Renderer2);
22
+ injector = inject(Injector);
23
+ overlayStack = inject(OverlayStackService);
24
+ constructor() {
25
+ let initialized = false;
26
+ effect(() => {
27
+ const open = this.isOpen();
28
+ untracked(() => {
29
+ if (open) {
30
+ this.overlayStack.push(this.menuId);
31
+ this.activeIndex.set(this.firstEnabledIndex());
32
+ if (initialized) afterNextRender(() => this.focusActiveItem(), { injector: this.injector });
33
+ } else {
34
+ this.overlayStack.remove(this.menuId);
35
+ this.restoreFocus();
36
+ this.activeIndex.set(-1);
37
+ }
38
+ initialized = true;
39
+ });
40
+ });
41
+ afterRenderEffect(() => {
42
+ const open = this.isOpen();
43
+ const trigger = this.triggerElement();
44
+ if (!trigger) return;
45
+ this.renderer.setAttribute(trigger, "aria-haspopup", "menu");
46
+ this.renderer.setAttribute(trigger, "aria-expanded", String(open));
47
+ if (open) this.renderer.setAttribute(trigger, "aria-controls", this.panelId);
48
+ else this.renderer.removeAttribute(trigger, "aria-controls");
49
+ });
50
+ }
51
+ ngOnDestroy() {
52
+ this.overlayStack.remove(this.menuId);
53
+ }
54
+ onItemClick(item, event) {
55
+ if (item.disabled) {
56
+ event.preventDefault();
57
+ return;
58
+ }
59
+ if (!item.href) event.preventDefault();
60
+ this.itemClick.emit(item);
61
+ }
62
+ close() {
63
+ this.closed.emit();
64
+ }
65
+ onDocumentClick(event) {
66
+ if (!this.isOpen()) return;
67
+ const target = event.target;
68
+ if (target instanceof Node && this.elementRef.nativeElement.contains(target)) return;
69
+ if (!this.overlayStack.claim(this.menuId, event)) return;
70
+ this.close();
71
+ }
72
+ onEscapeKey(event) {
73
+ if (!this.isOpen()) return;
74
+ if (!this.overlayStack.claim(this.menuId, event)) return;
75
+ event.stopPropagation();
76
+ this.triggerElement()?.focus();
77
+ this.close();
78
+ }
79
+ onPanelKeydown(event) {
80
+ switch (event.key) {
81
+ case "ArrowDown":
82
+ event.preventDefault();
83
+ this.focusIndex(this.nextEnabledIndex(this.activeIndex(), 1));
84
+ break;
85
+ case "ArrowUp":
86
+ event.preventDefault();
87
+ this.focusIndex(this.nextEnabledIndex(this.activeIndex(), -1));
88
+ break;
89
+ case "Home":
90
+ event.preventDefault();
91
+ this.focusIndex(this.firstEnabledIndex());
92
+ break;
93
+ case "End":
94
+ event.preventDefault();
95
+ this.focusIndex(this.nextEnabledIndex(0, -1));
96
+ break;
97
+ case " ": {
98
+ const target = event.target;
99
+ if (target?.matches("a[role=\"menuitem\"]")) {
100
+ event.preventDefault();
101
+ target.click();
102
+ }
103
+ break;
104
+ }
105
+ case "Tab": this.close();
106
+ }
107
+ }
108
+ tabindexFor(index, item) {
109
+ return !item.disabled && index === this.activeIndex() ? 0 : -1;
110
+ }
111
+ focusIndex(index) {
112
+ if (index < 0) return;
113
+ this.activeIndex.set(index);
114
+ this.focusActiveItem();
115
+ }
116
+ focusActiveItem() {
117
+ this.itemElements()[this.activeIndex()]?.nativeElement.focus();
118
+ }
119
+ firstEnabledIndex() {
120
+ return this.items().findIndex((item) => !item.disabled);
121
+ }
122
+ nextEnabledIndex(from, direction) {
123
+ const items = this.items();
124
+ for (let step = 1; step <= items.length; step++) {
125
+ const index = (from + direction * step + items.length) % items.length;
126
+ if (!items[index]?.disabled) return index;
127
+ }
128
+ return -1;
129
+ }
130
+ triggerElement() {
131
+ const slot = this.elementRef.nativeElement.querySelector(".lc-menu__trigger [trigger]");
132
+ if (!slot) return null;
133
+ return slot.matches(INTERACTIVE_SELECTOR) ? slot : slot.querySelector(INTERACTIVE_SELECTOR) ?? slot;
134
+ }
135
+ restoreFocus() {
136
+ if (typeof document === "undefined") return;
137
+ if (this.elementRef.nativeElement.querySelector(".lc-menu__dropdown")?.contains(document.activeElement)) this.triggerElement()?.focus();
138
+ }
139
+ static ɵfac = i0.ɵɵngDeclareFactory({
140
+ minVersion: "12.0.0",
141
+ version: "22.2.2",
142
+ ngImport: i0,
143
+ type: MenuComponent,
144
+ deps: [],
145
+ target: i0.ɵɵFactoryTarget.Component
146
+ });
147
+ static ɵcmp = i0.ɵɵngDeclareComponent({
148
+ minVersion: "17.0.0",
149
+ version: "22.2.2",
150
+ type: MenuComponent,
151
+ isStandalone: true,
152
+ selector: "lc-menu",
153
+ inputs: {
154
+ items: {
155
+ classPropertyName: "items",
156
+ publicName: "items",
157
+ isSignal: true,
158
+ isRequired: false,
159
+ transformFunction: null
160
+ },
161
+ isOpen: {
162
+ classPropertyName: "isOpen",
163
+ publicName: "isOpen",
164
+ isSignal: true,
165
+ isRequired: false,
166
+ transformFunction: null
167
+ },
168
+ position: {
169
+ classPropertyName: "position",
170
+ publicName: "position",
171
+ isSignal: true,
172
+ isRequired: false,
173
+ transformFunction: null
174
+ },
175
+ size: {
176
+ classPropertyName: "size",
177
+ publicName: "size",
178
+ isSignal: true,
179
+ isRequired: false,
180
+ transformFunction: null
181
+ },
182
+ minWidth: {
183
+ classPropertyName: "minWidth",
184
+ publicName: "minWidth",
185
+ isSignal: true,
186
+ isRequired: false,
187
+ transformFunction: null
188
+ },
189
+ maxWidth: {
190
+ classPropertyName: "maxWidth",
191
+ publicName: "maxWidth",
192
+ isSignal: true,
193
+ isRequired: false,
194
+ transformFunction: null
195
+ }
196
+ },
197
+ outputs: {
198
+ itemClick: "itemClick",
199
+ closed: "closed"
200
+ },
201
+ host: { listeners: {
202
+ "document:click": "onDocumentClick($event)",
203
+ "document:keydown.escape": "onEscapeKey($event)"
204
+ } },
205
+ viewQueries: [{
206
+ propertyName: "itemElements",
207
+ predicate: ["menuItem"],
208
+ descendants: true,
209
+ isSignal: true
210
+ }],
211
+ ngImport: i0,
212
+ template: "<div class=\"lc-menu\">\n <!-- Trigger slot -->\n <div class=\"lc-menu__trigger\">\n <ng-content select=\"[trigger]\" />\n </div>\n\n <!-- Dropdown menu -->\n @if (isOpen()) {\n <div\n class=\"lc-menu__dropdown\"\n [class.lc-menu__dropdown--bottom-left]=\"position() === 'bottom-left'\"\n [class.lc-menu__dropdown--bottom-right]=\"position() === 'bottom-right'\"\n [class.lc-menu__dropdown--top-left]=\"position() === 'top-left'\"\n [class.lc-menu__dropdown--top-right]=\"position() === 'top-right'\"\n [class.lc-menu__dropdown--sm]=\"size() === 'sm'\"\n [class.lc-menu__dropdown--lg]=\"size() === 'lg'\"\n [style.min-width]=\"minWidth()\"\n [style.max-width]=\"maxWidth() || null\"\n [class.lc-menu__dropdown--capped]=\"!!maxWidth()\"\n >\n <!-- Optional header slot (outside the menu role: it is not an item) -->\n <ng-content select=\"[header]\" />\n\n <!-- Menu items -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -- keydown bubbles from the focused menu items (roving tabindex) -->\n <div\n class=\"lc-menu__items\"\n role=\"menu\"\n [id]=\"panelId\"\n (keydown)=\"onPanelKeydown($event)\"\n >\n @for (item of items(); track item.id; let i = $index) {\n @if (item.href) {\n <!-- Link item -->\n <a\n #menuItem\n role=\"menuitem\"\n [href]=\"item.href\"\n [target]=\"item.target || '_self'\"\n [attr.rel]=\"item.target === '_blank' ? 'noopener noreferrer' : null\"\n [attr.tabindex]=\"tabindexFor(i, item)\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n class=\"lc-menu__item\"\n [class.lc-menu__item--danger]=\"item.variant === 'danger'\"\n [class.lc-menu__item--disabled]=\"item.disabled\"\n (click)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <lc-icon [name]=\"item.icon\" [size]=\"item.iconSize || 'sm'\" />\n }\n <span class=\"lc-menu__item-content\">\n <span class=\"lc-menu__item-label\">{{ item.label }}</span>\n @if (item.metadata?.subtitle; as subtitle) {\n <span class=\"lc-menu__item-subtitle\">{{ subtitle }}</span>\n }\n </span>\n @if (item.metadata?.badge; as badge) {\n <span class=\"lc-menu__item-badge\">{{ badge }}</span>\n }\n </a>\n } @else {\n <!-- Button item -->\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n class=\"lc-menu__item\"\n [class.lc-menu__item--danger]=\"item.variant === 'danger'\"\n [class.lc-menu__item--disabled]=\"item.disabled\"\n [attr.tabindex]=\"tabindexFor(i, item)\"\n [disabled]=\"item.disabled\"\n (click)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <lc-icon [name]=\"item.icon\" [size]=\"item.iconSize || 'sm'\" />\n }\n <span class=\"lc-menu__item-content\">\n <span class=\"lc-menu__item-label\">{{ item.label }}</span>\n @if (item.metadata?.subtitle; as subtitle) {\n <span class=\"lc-menu__item-subtitle\">{{ subtitle }}</span>\n }\n </span>\n @if (item.metadata?.badge; as badge) {\n <span class=\"lc-menu__item-badge\">{{ badge }}</span>\n }\n </button>\n }\n\n @if (item.dividerAfter) {\n <hr class=\"lc-menu__divider\" />\n }\n }\n </div>\n\n <!-- Optional footer slot -->\n <ng-content select=\"[footer]\" />\n </div>\n }\n</div>\n",
213
+ styles: [".lc-menu{position:relative;display:inline-block}.lc-menu__trigger{display:inline-block}.lc-menu__dropdown{position:absolute;background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg, .5rem);box-shadow:var(--elevation-4);padding:var(--lc-density-padding-xs, var(--spacing-2)) 0;z-index:9999;animation:slideDown .15s ease-out}.lc-menu__dropdown--bottom-left{top:calc(100% + var(--spacing-2));left:0}.lc-menu__dropdown--bottom-right{top:calc(100% + var(--spacing-2));right:0}.lc-menu__dropdown--top-left{bottom:calc(100% + var(--spacing-2));left:0}.lc-menu__dropdown--top-right{bottom:calc(100% + var(--spacing-2));right:0}.lc-menu__dropdown--capped{width:max-content}.lc-menu__item{display:flex;align-items:center;gap:var(--spacing-3);width:100%;padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));background:transparent;border:none;text-align:left;text-decoration:none;color:var(--color-text-primary);font-size:var(--font-size-base);font-family:var(--font-family-base);cursor:pointer;transition:background-color .2s ease}.lc-menu__item:hover:not(.lc-menu__item--disabled){background-color:var(--color-surface-hover)}.lc-menu__item:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px;background-color:var(--color-surface-hover)}.lc-menu__item--danger{color:var(--color-error)}.lc-menu__item--danger:hover:not(.lc-menu__item--danger--disabled){background-color:#9d0e0e24}.lc-menu__item--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.lc-menu__item-content{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));flex:1}.lc-menu__item-label{font-size:var(--font-size-base);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight)}.lc-menu__item-subtitle{font-size:var(--font-size-sm);color:var(--color-text-secondary);line-height:var(--line-height-tight)}.lc-menu__item-badge{padding:var(--spacing-1) var(--spacing-2);background-color:var(--color-primary-100);color:var(--color-primary-700);font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);border-radius:var(--border-radius-full);line-height:1}.lc-menu__divider{margin:var(--spacing-2) 0;border:none;border-top:1px solid var(--color-divider)}.lc-menu__dropdown--sm{padding:var(--spacing-1, .25rem) 0}.lc-menu__dropdown--sm .lc-menu__item{gap:var(--lc-density-gap-sm, var(--spacing-2));padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm)}.lc-menu__dropdown--sm .lc-menu__item-label{font-size:var(--font-size-sm)}.lc-menu__dropdown--sm .lc-menu__item-subtitle{font-size:var(--font-size-xs)}.lc-menu__dropdown--sm .lc-menu__item-badge{font-size:.625rem;padding:1px var(--spacing-1)}.lc-menu__dropdown--sm .lc-menu__divider{margin:var(--spacing-1) 0}.lc-menu__dropdown--lg .lc-menu__item{gap:var(--lc-density-gap-md, var(--spacing-4));padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--font-size-lg)}.lc-menu__dropdown--lg .lc-menu__item-label{font-size:var(--font-size-lg)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}\n"],
214
+ dependencies: [{
215
+ kind: "component",
216
+ type: IconComponent,
217
+ selector: "lc-icon",
218
+ inputs: [
219
+ "name",
220
+ "variant",
221
+ "size",
222
+ "color",
223
+ "ariaLabel",
224
+ "decorative",
225
+ "strict"
226
+ ]
227
+ }],
228
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
229
+ });
230
+ };
231
+ i0.ɵɵngDeclareClassMetadata({
232
+ minVersion: "12.0.0",
233
+ version: "22.2.2",
234
+ ngImport: i0,
235
+ type: MenuComponent,
236
+ decorators: [{
237
+ type: Component,
238
+ args: [{
239
+ selector: "lc-menu",
240
+ standalone: true,
241
+ imports: [IconComponent],
242
+ changeDetection: ChangeDetectionStrategy.OnPush,
243
+ template: "<div class=\"lc-menu\">\n <!-- Trigger slot -->\n <div class=\"lc-menu__trigger\">\n <ng-content select=\"[trigger]\" />\n </div>\n\n <!-- Dropdown menu -->\n @if (isOpen()) {\n <div\n class=\"lc-menu__dropdown\"\n [class.lc-menu__dropdown--bottom-left]=\"position() === 'bottom-left'\"\n [class.lc-menu__dropdown--bottom-right]=\"position() === 'bottom-right'\"\n [class.lc-menu__dropdown--top-left]=\"position() === 'top-left'\"\n [class.lc-menu__dropdown--top-right]=\"position() === 'top-right'\"\n [class.lc-menu__dropdown--sm]=\"size() === 'sm'\"\n [class.lc-menu__dropdown--lg]=\"size() === 'lg'\"\n [style.min-width]=\"minWidth()\"\n [style.max-width]=\"maxWidth() || null\"\n [class.lc-menu__dropdown--capped]=\"!!maxWidth()\"\n >\n <!-- Optional header slot (outside the menu role: it is not an item) -->\n <ng-content select=\"[header]\" />\n\n <!-- Menu items -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -- keydown bubbles from the focused menu items (roving tabindex) -->\n <div\n class=\"lc-menu__items\"\n role=\"menu\"\n [id]=\"panelId\"\n (keydown)=\"onPanelKeydown($event)\"\n >\n @for (item of items(); track item.id; let i = $index) {\n @if (item.href) {\n <!-- Link item -->\n <a\n #menuItem\n role=\"menuitem\"\n [href]=\"item.href\"\n [target]=\"item.target || '_self'\"\n [attr.rel]=\"item.target === '_blank' ? 'noopener noreferrer' : null\"\n [attr.tabindex]=\"tabindexFor(i, item)\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n class=\"lc-menu__item\"\n [class.lc-menu__item--danger]=\"item.variant === 'danger'\"\n [class.lc-menu__item--disabled]=\"item.disabled\"\n (click)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <lc-icon [name]=\"item.icon\" [size]=\"item.iconSize || 'sm'\" />\n }\n <span class=\"lc-menu__item-content\">\n <span class=\"lc-menu__item-label\">{{ item.label }}</span>\n @if (item.metadata?.subtitle; as subtitle) {\n <span class=\"lc-menu__item-subtitle\">{{ subtitle }}</span>\n }\n </span>\n @if (item.metadata?.badge; as badge) {\n <span class=\"lc-menu__item-badge\">{{ badge }}</span>\n }\n </a>\n } @else {\n <!-- Button item -->\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n class=\"lc-menu__item\"\n [class.lc-menu__item--danger]=\"item.variant === 'danger'\"\n [class.lc-menu__item--disabled]=\"item.disabled\"\n [attr.tabindex]=\"tabindexFor(i, item)\"\n [disabled]=\"item.disabled\"\n (click)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <lc-icon [name]=\"item.icon\" [size]=\"item.iconSize || 'sm'\" />\n }\n <span class=\"lc-menu__item-content\">\n <span class=\"lc-menu__item-label\">{{ item.label }}</span>\n @if (item.metadata?.subtitle; as subtitle) {\n <span class=\"lc-menu__item-subtitle\">{{ subtitle }}</span>\n }\n </span>\n @if (item.metadata?.badge; as badge) {\n <span class=\"lc-menu__item-badge\">{{ badge }}</span>\n }\n </button>\n }\n\n @if (item.dividerAfter) {\n <hr class=\"lc-menu__divider\" />\n }\n }\n </div>\n\n <!-- Optional footer slot -->\n <ng-content select=\"[footer]\" />\n </div>\n }\n</div>\n",
244
+ styles: [".lc-menu{position:relative;display:inline-block}.lc-menu__trigger{display:inline-block}.lc-menu__dropdown{position:absolute;background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg, .5rem);box-shadow:var(--elevation-4);padding:var(--lc-density-padding-xs, var(--spacing-2)) 0;z-index:9999;animation:slideDown .15s ease-out}.lc-menu__dropdown--bottom-left{top:calc(100% + var(--spacing-2));left:0}.lc-menu__dropdown--bottom-right{top:calc(100% + var(--spacing-2));right:0}.lc-menu__dropdown--top-left{bottom:calc(100% + var(--spacing-2));left:0}.lc-menu__dropdown--top-right{bottom:calc(100% + var(--spacing-2));right:0}.lc-menu__dropdown--capped{width:max-content}.lc-menu__item{display:flex;align-items:center;gap:var(--spacing-3);width:100%;padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));background:transparent;border:none;text-align:left;text-decoration:none;color:var(--color-text-primary);font-size:var(--font-size-base);font-family:var(--font-family-base);cursor:pointer;transition:background-color .2s ease}.lc-menu__item:hover:not(.lc-menu__item--disabled){background-color:var(--color-surface-hover)}.lc-menu__item:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px;background-color:var(--color-surface-hover)}.lc-menu__item--danger{color:var(--color-error)}.lc-menu__item--danger:hover:not(.lc-menu__item--danger--disabled){background-color:#9d0e0e24}.lc-menu__item--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.lc-menu__item-content{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));flex:1}.lc-menu__item-label{font-size:var(--font-size-base);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight)}.lc-menu__item-subtitle{font-size:var(--font-size-sm);color:var(--color-text-secondary);line-height:var(--line-height-tight)}.lc-menu__item-badge{padding:var(--spacing-1) var(--spacing-2);background-color:var(--color-primary-100);color:var(--color-primary-700);font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);border-radius:var(--border-radius-full);line-height:1}.lc-menu__divider{margin:var(--spacing-2) 0;border:none;border-top:1px solid var(--color-divider)}.lc-menu__dropdown--sm{padding:var(--spacing-1, .25rem) 0}.lc-menu__dropdown--sm .lc-menu__item{gap:var(--lc-density-gap-sm, var(--spacing-2));padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm)}.lc-menu__dropdown--sm .lc-menu__item-label{font-size:var(--font-size-sm)}.lc-menu__dropdown--sm .lc-menu__item-subtitle{font-size:var(--font-size-xs)}.lc-menu__dropdown--sm .lc-menu__item-badge{font-size:.625rem;padding:1px var(--spacing-1)}.lc-menu__dropdown--sm .lc-menu__divider{margin:var(--spacing-1) 0}.lc-menu__dropdown--lg .lc-menu__item{gap:var(--lc-density-gap-md, var(--spacing-4));padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--font-size-lg)}.lc-menu__dropdown--lg .lc-menu__item-label{font-size:var(--font-size-lg)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}\n"]
245
+ }]
246
+ }],
247
+ ctorParameters: () => [],
248
+ propDecorators: {
249
+ items: [{
250
+ type: i0.Input,
251
+ args: [{
252
+ isSignal: true,
253
+ alias: "items",
254
+ required: false
255
+ }]
256
+ }],
257
+ isOpen: [{
258
+ type: i0.Input,
259
+ args: [{
260
+ isSignal: true,
261
+ alias: "isOpen",
262
+ required: false
263
+ }]
264
+ }],
265
+ position: [{
266
+ type: i0.Input,
267
+ args: [{
268
+ isSignal: true,
269
+ alias: "position",
270
+ required: false
271
+ }]
272
+ }],
273
+ size: [{
274
+ type: i0.Input,
275
+ args: [{
276
+ isSignal: true,
277
+ alias: "size",
278
+ required: false
279
+ }]
280
+ }],
281
+ minWidth: [{
282
+ type: i0.Input,
283
+ args: [{
284
+ isSignal: true,
285
+ alias: "minWidth",
286
+ required: false
287
+ }]
288
+ }],
289
+ maxWidth: [{
290
+ type: i0.Input,
291
+ args: [{
292
+ isSignal: true,
293
+ alias: "maxWidth",
294
+ required: false
295
+ }]
296
+ }],
297
+ itemClick: [{
298
+ type: i0.Output,
299
+ args: ["itemClick"]
300
+ }],
301
+ closed: [{
302
+ type: i0.Output,
303
+ args: ["closed"]
304
+ }],
305
+ itemElements: [{
306
+ type: i0.ViewChildren,
307
+ args: ["menuItem", { isSignal: true }]
308
+ }],
309
+ onDocumentClick: [{
310
+ type: HostListener,
311
+ args: ["document:click", ["$event"]]
312
+ }],
313
+ onEscapeKey: [{
314
+ type: HostListener,
315
+ args: ["document:keydown.escape", ["$event"]]
316
+ }]
317
+ }
318
+ });
319
+ export { MenuComponent };
320
+
321
+ //# sourceMappingURL=lifecorner-angular-ui-kit-menu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-menu.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/menu/menu.component.ts","../../../../libs/angular-ui-kit/src/lib/menu/menu.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n effect,\n untracked,\n afterNextRender,\n afterRenderEffect,\n viewChildren,\n ChangeDetectionStrategy,\n HostListener,\n ElementRef,\n Injector,\n Renderer2,\n OnDestroy,\n inject,\n} from '@angular/core';\nimport { IconComponent } from '@lifecorner/angular-ui-kit/icon';\nimport { OverlayStackService } from '@lifecorner/angular-ui-kit/internal/overlay';\n\nexport interface MenuItem {\n id: string;\n label: string;\n icon?: string;\n iconSize?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n href?: string;\n target?: '_blank' | '_self' | '_parent' | '_top';\n variant?: 'default' | 'danger';\n dividerAfter?: boolean;\n disabled?: boolean;\n metadata?: {\n subtitle?: string;\n badge?: string;\n };\n}\n\n/** Natively focusable elements a projected trigger may be or contain. */\nconst INTERACTIVE_SELECTOR = 'button, a[href], input, select, textarea, [tabindex]';\n\n/**\n * Menu Component - Dropdown menu for navigation and actions\n *\n * Features:\n * - Customizable menu items with icons\n * - Support for links and buttons\n * - Dividers between menu sections\n * - Optional subtitle/metadata for items\n * - Danger variant for destructive actions\n * - Click outside to close (top-most overlay only)\n * - Keyboard navigation: focus moves into the menu on open, Arrow keys /\n * Home / End move between items (roving tabindex), Enter / Space activate,\n * Escape closes and returns focus to the trigger, Tab closes\n * - ARIA menu semantics (`aria-haspopup` / `aria-expanded` / `aria-controls`\n * on the projected trigger, `role=\"menu\"` / `role=\"menuitem\"` on the panel)\n * - OnPush change detection for performance\n *\n * @example\n * ```html\n * <lc-menu\n * [items]=\"menuItems\"\n * [isOpen]=\"isMenuOpen\"\n * (itemClick)=\"handleMenuClick($event)\"\n * (closed)=\"isMenuOpen = false\"\n * >\n * <button trigger>Open Menu</button>\n * <div header>User Profile</div>\n * </lc-menu>\n * ```\n */\n@Component({\n selector: 'lc-menu',\n standalone: true,\n imports: [IconComponent],\n templateUrl: './menu.component.html',\n styleUrl: './menu.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MenuComponent implements OnDestroy {\n private static nextId = 0;\n /** Identifies this instance in the overlay stack. */\n private readonly menuId = `lc-menu-${++MenuComponent.nextId}`;\n\n readonly items = input<MenuItem[]>([]);\n readonly isOpen = input(false);\n readonly position = input<'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'>('bottom-right');\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n readonly minWidth = input('220px');\n /**\n * Maximum width of the panel (any CSS width, e.g. `min(18rem, calc(100vw - 2rem))`).\n * Empty leaves it unbounded. Long item labels and header lines wrap within it.\n */\n readonly maxWidth = input('');\n\n readonly itemClick = output<MenuItem>();\n readonly closed = output<void>();\n\n /** Id of the `role=\"menu\"` element, referenced by the trigger's `aria-controls`. */\n protected readonly panelId = `${this.menuId}-panel`;\n\n /** Index (into `items()`) of the item that currently owns the roving tabindex. */\n protected readonly activeIndex = signal(-1);\n\n private readonly itemElements = viewChildren<ElementRef<HTMLElement>>('menuItem');\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly injector = inject(Injector);\n private readonly overlayStack = inject(OverlayStackService);\n\n constructor() {\n // Whether the menu has been through its first open-state evaluation; a menu\n // that is already open when it renders (demo pages) must not steal focus.\n let initialized = false;\n effect(() => {\n const open = this.isOpen();\n untracked(() => {\n if (open) {\n this.overlayStack.push(this.menuId);\n this.activeIndex.set(this.firstEnabledIndex());\n // Move focus into the menu once the panel has rendered\n if (initialized) {\n afterNextRender(() => this.focusActiveItem(), { injector: this.injector });\n }\n } else {\n this.overlayStack.remove(this.menuId);\n this.restoreFocus();\n this.activeIndex.set(-1);\n }\n initialized = true;\n });\n });\n\n // Mirror the open state onto the projected trigger so assistive tech knows\n // it opens a menu (the trigger is caller-supplied, so we set the\n // attributes rather than bind them).\n afterRenderEffect(() => {\n const open = this.isOpen();\n const trigger = this.triggerElement();\n if (!trigger) return;\n this.renderer.setAttribute(trigger, 'aria-haspopup', 'menu');\n this.renderer.setAttribute(trigger, 'aria-expanded', String(open));\n if (open) {\n this.renderer.setAttribute(trigger, 'aria-controls', this.panelId);\n } else {\n this.renderer.removeAttribute(trigger, 'aria-controls');\n }\n });\n }\n\n ngOnDestroy(): void {\n this.overlayStack.remove(this.menuId);\n }\n\n /**\n * Handle menu item click\n */\n onItemClick(item: MenuItem, event: Event): void {\n if (item.disabled) {\n event.preventDefault();\n return;\n }\n\n // Links navigate natively; button items only emit\n if (!item.href) {\n event.preventDefault();\n }\n\n this.itemClick.emit(item);\n }\n\n /**\n * Close the menu\n */\n close(): void {\n this.closed.emit();\n }\n\n /**\n * Handle click outside to close menu — only while the menu is the top-most\n * overlay, so a click inside a layer above it (a modal opened from a menu\n * item) is left alone.\n */\n @HostListener('document:click', ['$event'])\n onDocumentClick(event: MouseEvent): void {\n if (!this.isOpen()) {\n return;\n }\n\n const target = event.target;\n if (target instanceof Node && this.elementRef.nativeElement.contains(target)) {\n return;\n }\n if (!this.overlayStack.claim(this.menuId, event)) return;\n this.close();\n }\n\n /**\n * Escape closes the menu (top-most overlay only) and returns focus to the\n * trigger; the event is consumed so overlays underneath stay open.\n */\n @HostListener('document:keydown.escape', ['$event'])\n onEscapeKey(event: Event): void {\n if (!this.isOpen()) return;\n if (!this.overlayStack.claim(this.menuId, event)) return;\n event.stopPropagation();\n this.triggerElement()?.focus();\n this.close();\n }\n\n /** Keyboard navigation inside the `role=\"menu\"` panel. */\n protected onPanelKeydown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.focusIndex(this.nextEnabledIndex(this.activeIndex(), 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusIndex(this.nextEnabledIndex(this.activeIndex(), -1));\n break;\n case 'Home':\n event.preventDefault();\n this.focusIndex(this.firstEnabledIndex());\n break;\n case 'End':\n event.preventDefault();\n this.focusIndex(this.nextEnabledIndex(0, -1));\n break;\n case ' ': {\n // Buttons activate on Space natively, links only on Enter\n const target = event.target as HTMLElement | null;\n if (target?.matches('a[role=\"menuitem\"]')) {\n event.preventDefault();\n target.click();\n }\n break;\n }\n case 'Tab':\n // Focus leaves the menu — let it move on naturally, but close the menu\n this.close();\n break;\n }\n }\n\n /** Roving tabindex: only the active item is in the tab sequence. */\n protected tabindexFor(index: number, item: MenuItem): number {\n return !item.disabled && index === this.activeIndex() ? 0 : -1;\n }\n\n private focusIndex(index: number): void {\n if (index < 0) return;\n this.activeIndex.set(index);\n this.focusActiveItem();\n }\n\n private focusActiveItem(): void {\n this.itemElements()[this.activeIndex()]?.nativeElement.focus();\n }\n\n private firstEnabledIndex(): number {\n return this.items().findIndex((item) => !item.disabled);\n }\n\n /** Index of the next enabled item in `direction`, wrapping around; -1 if none. */\n private nextEnabledIndex(from: number, direction: 1 | -1): number {\n const items = this.items();\n for (let step = 1; step <= items.length; step++) {\n const index = (from + direction * step + items.length) % items.length;\n if (!items[index]?.disabled) return index;\n }\n return -1;\n }\n\n /**\n * The element that carries the menu-button ARIA attributes and receives\n * focus back: the projected `[trigger]` node itself when it is natively\n * interactive, otherwise the first interactive element inside it (e.g. the\n * `<button>` inside an `<lc-button trigger>`).\n */\n private triggerElement(): HTMLElement | null {\n const slot = this.elementRef.nativeElement.querySelector<HTMLElement>('.lc-menu__trigger [trigger]');\n if (!slot) return null;\n return slot.matches(INTERACTIVE_SELECTOR)\n ? slot\n : (slot.querySelector<HTMLElement>(INTERACTIVE_SELECTOR) ?? slot);\n }\n\n /**\n * Closing removes the panel from the DOM; if focus is inside it (an item was\n * activated by keyboard) it would silently drop to `<body>`, so send it back\n * to the trigger.\n */\n private restoreFocus(): void {\n if (typeof document === 'undefined') return;\n const panel = this.elementRef.nativeElement.querySelector<HTMLElement>('.lc-menu__dropdown');\n if (panel?.contains(document.activeElement)) {\n this.triggerElement()?.focus();\n }\n }\n}\n","<div class=\"lc-menu\">\n <!-- Trigger slot -->\n <div class=\"lc-menu__trigger\">\n <ng-content select=\"[trigger]\" />\n </div>\n\n <!-- Dropdown menu -->\n @if (isOpen()) {\n <div\n class=\"lc-menu__dropdown\"\n [class.lc-menu__dropdown--bottom-left]=\"position() === 'bottom-left'\"\n [class.lc-menu__dropdown--bottom-right]=\"position() === 'bottom-right'\"\n [class.lc-menu__dropdown--top-left]=\"position() === 'top-left'\"\n [class.lc-menu__dropdown--top-right]=\"position() === 'top-right'\"\n [class.lc-menu__dropdown--sm]=\"size() === 'sm'\"\n [class.lc-menu__dropdown--lg]=\"size() === 'lg'\"\n [style.min-width]=\"minWidth()\"\n [style.max-width]=\"maxWidth() || null\"\n [class.lc-menu__dropdown--capped]=\"!!maxWidth()\"\n >\n <!-- Optional header slot (outside the menu role: it is not an item) -->\n <ng-content select=\"[header]\" />\n\n <!-- Menu items -->\n <!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -- keydown bubbles from the focused menu items (roving tabindex) -->\n <div\n class=\"lc-menu__items\"\n role=\"menu\"\n [id]=\"panelId\"\n (keydown)=\"onPanelKeydown($event)\"\n >\n @for (item of items(); track item.id; let i = $index) {\n @if (item.href) {\n <!-- Link item -->\n <a\n #menuItem\n role=\"menuitem\"\n [href]=\"item.href\"\n [target]=\"item.target || '_self'\"\n [attr.rel]=\"item.target === '_blank' ? 'noopener noreferrer' : null\"\n [attr.tabindex]=\"tabindexFor(i, item)\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n class=\"lc-menu__item\"\n [class.lc-menu__item--danger]=\"item.variant === 'danger'\"\n [class.lc-menu__item--disabled]=\"item.disabled\"\n (click)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <lc-icon [name]=\"item.icon\" [size]=\"item.iconSize || 'sm'\" />\n }\n <span class=\"lc-menu__item-content\">\n <span class=\"lc-menu__item-label\">{{ item.label }}</span>\n @if (item.metadata?.subtitle; as subtitle) {\n <span class=\"lc-menu__item-subtitle\">{{ subtitle }}</span>\n }\n </span>\n @if (item.metadata?.badge; as badge) {\n <span class=\"lc-menu__item-badge\">{{ badge }}</span>\n }\n </a>\n } @else {\n <!-- Button item -->\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n class=\"lc-menu__item\"\n [class.lc-menu__item--danger]=\"item.variant === 'danger'\"\n [class.lc-menu__item--disabled]=\"item.disabled\"\n [attr.tabindex]=\"tabindexFor(i, item)\"\n [disabled]=\"item.disabled\"\n (click)=\"onItemClick(item, $event)\"\n >\n @if (item.icon) {\n <lc-icon [name]=\"item.icon\" [size]=\"item.iconSize || 'sm'\" />\n }\n <span class=\"lc-menu__item-content\">\n <span class=\"lc-menu__item-label\">{{ item.label }}</span>\n @if (item.metadata?.subtitle; as subtitle) {\n <span class=\"lc-menu__item-subtitle\">{{ subtitle }}</span>\n }\n </span>\n @if (item.metadata?.badge; as badge) {\n <span class=\"lc-menu__item-badge\">{{ badge }}</span>\n }\n </button>\n }\n\n @if (item.dividerAfter) {\n <hr class=\"lc-menu__divider\" />\n }\n }\n </div>\n\n <!-- Optional footer slot -->\n <ng-content select=\"[footer]\" />\n </div>\n }\n</div>\n"],"mappings":"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"}