@lifecorner/angular-ui-kit 3.4.1 → 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,1761 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, ElementRef, HostListener, computed, effect, inject, input, output, signal, untracked, viewChild } from "@angular/core";
3
+ const NODE_MIN_WIDTH = 160;
4
+ const NODE_MAX_WIDTH = 240;
5
+ const NODE_HEIGHT = 40;
6
+ const NODE_HEIGHT_TWO_LINE = 54;
7
+ const LABEL_FONT_SIZE = 12;
8
+ const LABEL_FONT_WEIGHT = 500;
9
+ const LABEL_LINE_HEIGHT = 15;
10
+ const LABEL_BASELINE_SHIFT = 4;
11
+ const EDGE_LABEL_FONT_SIZE = 9;
12
+ const EDGE_LABEL_GAP = 4;
13
+ const H_GAP = 80;
14
+ const V_GAP = 24;
15
+ const BOW_CLEARANCE = 28;
16
+ const BOW_LANE_STEP = 18;
17
+ const BOW_LABEL_MARGIN = 10;
18
+ const TOGGLE_EXTENT = 18;
19
+ const TOGGLE_CLEARANCE = 13;
20
+ const ROUTE_SAMPLES = 24;
21
+ const ROUTE_INSET = 3;
22
+ const FIT_PADDING = 24;
23
+ const MAX_FIT_SCALE = 1;
24
+ const MIN_FIT_SCALE = .05;
25
+ const CHAR_WIDTH_CLASSES = [
26
+ ["ijl", .23],
27
+ [" !.,:;'|Ift/\\[]", .28],
28
+ ["-()r`", .33],
29
+ ["ckszxyvJ", .5],
30
+ ["abdeghnopqu0123456789$#?_L", .56],
31
+ ["TZF", .61],
32
+ ["ABEKPSVXY&", .67],
33
+ ["CDHNRUw", .72],
34
+ ["GOQ", .78],
35
+ ["Mm%", .83],
36
+ ["W", .94],
37
+ ["@", 1]
38
+ ];
39
+ const CHAR_WIDTHS = /* @__PURE__ */ new Map();
40
+ for (const [chars, width] of CHAR_WIDTH_CLASSES) for (const c of chars) CHAR_WIDTHS.set(c, width);
41
+ function estimateTextWidth(text, fontSize) {
42
+ let em = 0;
43
+ for (const ch of text.normalize("NFD")) {
44
+ if (/\p{M}/u.test(ch)) continue;
45
+ const code = ch.codePointAt(0) ?? 0;
46
+ em += CHAR_WIDTHS.get(ch) ?? (code > 11903 ? 1 : .6);
47
+ }
48
+ return em * fontSize * 1.04;
49
+ }
50
+ function createTextMeasurer(fontFamily, fontSize, fontWeight) {
51
+ if (typeof document !== "undefined" && typeof CanvasRenderingContext2D === "function") {
52
+ const ctx = document.createElement("canvas").getContext("2d");
53
+ if (ctx) {
54
+ ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
55
+ if (!ctx.font.includes(`${fontSize}px`)) ctx.font = `${fontWeight} ${fontSize}px sans-serif`;
56
+ return (text) => ctx.measureText(text).width;
57
+ }
58
+ }
59
+ return (text) => estimateTextWidth(text, fontSize);
60
+ }
61
+ function ellipsize(text, maxWidth, measure) {
62
+ let lo = 0;
63
+ let hi = text.length;
64
+ while (lo < hi) {
65
+ const mid = lo + hi + 1 >> 1;
66
+ if (measure(text.slice(0, mid).trimEnd() + "…") <= maxWidth) lo = mid;
67
+ else hi = mid - 1;
68
+ }
69
+ return text.slice(0, lo).trimEnd() + "…";
70
+ }
71
+ function splitWord(word, maxWidth, measure) {
72
+ for (let i = word.length - 1; i > 0; i--) if (word[i - 1] === "-" && measure(word.slice(0, i)) <= maxWidth) return [word.slice(0, i), word.slice(i)];
73
+ let lo = 1;
74
+ let hi = word.length;
75
+ while (lo < hi) {
76
+ const mid = lo + hi + 1 >> 1;
77
+ if (measure(word.slice(0, mid)) <= maxWidth) lo = mid;
78
+ else hi = mid - 1;
79
+ }
80
+ return [word.slice(0, lo), word.slice(lo)];
81
+ }
82
+ function wrapLabel(text, maxWidth, measure) {
83
+ const label = text.trim().replace(/\s+/g, " ");
84
+ if (!label || measure(label) <= maxWidth) return {
85
+ lines: [label],
86
+ truncated: false
87
+ };
88
+ const lines = [];
89
+ let rest = label.split(" ");
90
+ while (rest.length && lines.length < 1) {
91
+ let take = 0;
92
+ while (take < rest.length && measure(rest.slice(0, take + 1).join(" ")) <= maxWidth) take++;
93
+ if (take === 0) {
94
+ const [head, tail] = splitWord(rest[0], maxWidth, measure);
95
+ lines.push(head);
96
+ rest = [tail, ...rest.slice(1)];
97
+ } else {
98
+ lines.push(rest.slice(0, take).join(" "));
99
+ rest = rest.slice(take);
100
+ }
101
+ }
102
+ const last = rest.join(" ");
103
+ if (!last) return {
104
+ lines,
105
+ truncated: false
106
+ };
107
+ if (measure(last) <= maxWidth) return {
108
+ lines: [...lines, last],
109
+ truncated: false
110
+ };
111
+ return {
112
+ lines: [...lines, ellipsize(last, maxWidth, measure)],
113
+ truncated: true
114
+ };
115
+ }
116
+ const edgeLabelWidth = (measure, label) => label ? measure(label) * EDGE_LABEL_FONT_SIZE / LABEL_FONT_SIZE : 0;
117
+ function measureNodes(nodes, measure) {
118
+ const all = [...nodes];
119
+ let widest = 0;
120
+ for (const node of all) widest = Math.max(widest, measure(node.label ?? ""));
121
+ const width = Math.min(NODE_MAX_WIDTH, Math.max(NODE_MIN_WIDTH, Math.ceil(widest) + 24));
122
+ const labels = /* @__PURE__ */ new Map();
123
+ let twoLine = false;
124
+ for (const node of all) {
125
+ const wrapped = wrapLabel(node.label ?? "", width - 24, measure);
126
+ labels.set(node.id, wrapped);
127
+ if (wrapped.lines.length > 1) twoLine = true;
128
+ }
129
+ return {
130
+ width,
131
+ height: twoLine ? NODE_HEIGHT_TWO_LINE : NODE_HEIGHT,
132
+ gap: H_GAP,
133
+ labels,
134
+ measure
135
+ };
136
+ }
137
+ const RELATION_STYLES = {
138
+ depends: {
139
+ color: "var(--color-neutral-400)",
140
+ dashed: false,
141
+ label: "depends on"
142
+ },
143
+ blocks: {
144
+ color: "var(--color-error-default)",
145
+ dashed: false,
146
+ label: "blocks"
147
+ },
148
+ references: {
149
+ color: "var(--color-info-default, #3b82f6)",
150
+ dashed: true,
151
+ label: "references"
152
+ },
153
+ requires: {
154
+ color: "var(--color-warning-default)",
155
+ dashed: false,
156
+ label: "requires"
157
+ },
158
+ extends: {
159
+ color: "var(--color-primary-400)",
160
+ dashed: true,
161
+ label: "extends"
162
+ },
163
+ implements: {
164
+ color: "var(--color-success-default)",
165
+ dashed: true,
166
+ label: "implements"
167
+ },
168
+ uses: {
169
+ color: "var(--color-neutral-300)",
170
+ dashed: true,
171
+ label: "uses"
172
+ }
173
+ };
174
+ function measureTree(node, depth, dir, visited, backEdges, metrics) {
175
+ visited.add(node.id);
176
+ const children = [];
177
+ for (const child of node.children || []) {
178
+ if (visited.has(child.id)) {
179
+ backEdges.push({
180
+ from: node.id,
181
+ to: child.id
182
+ });
183
+ continue;
184
+ }
185
+ children.push(measureTree(child, depth + 1, dir, visited, backEdges, metrics));
186
+ }
187
+ const nodePrimary = dir === "horizontal" ? metrics.width : metrics.height;
188
+ const nodeSecondary = dir === "horizontal" ? metrics.height : metrics.width;
189
+ if (children.length === 0) return {
190
+ node,
191
+ primary: nodePrimary,
192
+ secondary: nodeSecondary,
193
+ children,
194
+ depth
195
+ };
196
+ const totalChildSecondary = children.reduce((sum, c) => sum + c.secondary, 0) + (children.length - 1) * V_GAP;
197
+ const maxChildPrimary = Math.max(...children.map((c) => c.primary));
198
+ return {
199
+ node,
200
+ primary: nodePrimary + metrics.gap + maxChildPrimary,
201
+ secondary: Math.max(nodeSecondary, totalChildSecondary),
202
+ children,
203
+ depth
204
+ };
205
+ }
206
+ function placeNode(source, original, x, y, depth, parentId, metrics) {
207
+ const label = metrics.labels.get(source.id);
208
+ return {
209
+ id: source.id,
210
+ label: source.label,
211
+ description: source.description,
212
+ icon: source.icon,
213
+ status: source.status || "default",
214
+ type: source.type,
215
+ moreCount: source.moreCount,
216
+ x,
217
+ y,
218
+ width: metrics.width,
219
+ height: metrics.height,
220
+ lines: label?.lines ?? [source.label],
221
+ truncated: label?.truncated ?? false,
222
+ depth,
223
+ parentId,
224
+ incomingCount: original?.dependsOn?.length ?? 0,
225
+ outgoingCount: original?.children?.length ?? 0
226
+ };
227
+ }
228
+ function layoutTreeH(measure, x, y, parentId, nodes, edges, allNodes, nodeMap, metrics) {
229
+ const nodeY = y + measure.secondary / 2 - metrics.height / 2;
230
+ const laid = placeNode(measure.node, allNodes.get(measure.node.id), x, nodeY, measure.depth, parentId, metrics);
231
+ nodes.push(laid);
232
+ nodeMap.set(laid.id, laid);
233
+ if (parentId) {
234
+ const parent = nodeMap.get(parentId);
235
+ const sx = parent.x + parent.width;
236
+ const sy = parent.y + parent.height / 2;
237
+ const tx = x;
238
+ const ty = nodeY + metrics.height / 2;
239
+ const mx = sx + metrics.gap / 2;
240
+ edges.push({
241
+ id: `${parentId}→${measure.node.id}`,
242
+ sourceId: parentId,
243
+ targetId: measure.node.id,
244
+ path: `M ${sx} ${sy} C ${mx} ${sy}, ${mx} ${ty}, ${tx} ${ty}`,
245
+ labelX: mx,
246
+ labelY: (sy + ty) / 2,
247
+ color: "var(--color-neutral-300)",
248
+ dashed: false,
249
+ isCrossRef: false,
250
+ arrow: false,
251
+ marker: "depends"
252
+ });
253
+ }
254
+ let childY = y;
255
+ for (const child of measure.children) {
256
+ layoutTreeH(child, x + metrics.width + metrics.gap, childY, measure.node.id, nodes, edges, allNodes, nodeMap, metrics);
257
+ childY += child.secondary + V_GAP;
258
+ }
259
+ }
260
+ function layoutTreeV(measure, x, y, parentId, nodes, edges, allNodes, nodeMap, metrics) {
261
+ const nodeX = x + measure.secondary / 2 - metrics.width / 2;
262
+ const laid = placeNode(measure.node, allNodes.get(measure.node.id), nodeX, y, measure.depth, parentId, metrics);
263
+ nodes.push(laid);
264
+ nodeMap.set(laid.id, laid);
265
+ if (parentId) {
266
+ const parent = nodeMap.get(parentId);
267
+ const sx = parent.x + parent.width / 2;
268
+ const sy = parent.y + parent.height;
269
+ const tx = nodeX + metrics.width / 2;
270
+ const ty = y;
271
+ const my = sy + metrics.gap / 2;
272
+ edges.push({
273
+ id: `${parentId}→${measure.node.id}`,
274
+ sourceId: parentId,
275
+ targetId: measure.node.id,
276
+ path: `M ${sx} ${sy} C ${sx} ${my}, ${tx} ${my}, ${tx} ${ty}`,
277
+ labelX: (sx + tx) / 2,
278
+ labelY: my,
279
+ color: "var(--color-neutral-300)",
280
+ dashed: false,
281
+ isCrossRef: false,
282
+ arrow: false,
283
+ marker: "depends"
284
+ });
285
+ }
286
+ let childX = x;
287
+ for (const child of measure.children) {
288
+ layoutTreeV(child, childX, y + metrics.height + metrics.gap, measure.node.id, nodes, edges, allNodes, nodeMap, metrics);
289
+ childX += child.secondary + V_GAP;
290
+ }
291
+ }
292
+ function collectAllNodes(node, map) {
293
+ if (map.has(node.id)) return;
294
+ map.set(node.id, node);
295
+ for (const child of node.children || []) collectAllNodes(child, map);
296
+ }
297
+ const push = (map, key, value) => {
298
+ const bucket = map.get(key);
299
+ if (bucket) bucket.push(value);
300
+ else map.set(key, [value]);
301
+ };
302
+ const cubicPath = (p) => `M ${p[0].x} ${p[0].y} C ${p[1].x} ${p[1].y}, ${p[2].x} ${p[2].y}, ${p[3].x} ${p[3].y}`;
303
+ function cubicAt(p, t) {
304
+ const m = 1 - t;
305
+ return {
306
+ x: m * m * m * p[0].x + 3 * m * m * t * p[1].x + 3 * m * t * t * p[2].x + t * t * t * p[3].x,
307
+ y: m * m * m * p[0].y + 3 * m * m * t * p[1].y + 3 * m * t * t * p[2].y + t * t * t * p[3].y
308
+ };
309
+ }
310
+ function crossedNodes(points, nodes, exclude) {
311
+ const hit = /* @__PURE__ */ new Map();
312
+ for (let i = 0; i <= ROUTE_SAMPLES; i++) {
313
+ const p = cubicAt(points, i / ROUTE_SAMPLES);
314
+ for (const n of nodes) {
315
+ if (exclude.has(n.id) || hit.has(n.id)) continue;
316
+ if (p.x > n.x + ROUTE_INSET && p.x < n.x + n.width - ROUTE_INSET && p.y > n.y + ROUTE_INSET && p.y < n.y + n.height - ROUTE_INSET) hit.set(n.id, n);
317
+ }
318
+ }
319
+ return [...hit.values()];
320
+ }
321
+ function directGeometry(source, target, dir) {
322
+ if (dir === "horizontal") {
323
+ const p0 = {
324
+ x: source.x + source.width,
325
+ y: source.y + source.height / 2
326
+ };
327
+ const p3 = {
328
+ x: target.x,
329
+ y: target.y + target.height / 2
330
+ };
331
+ const mx = (p0.x + p3.x) / 2;
332
+ const points = [
333
+ p0,
334
+ {
335
+ x: mx,
336
+ y: p0.y
337
+ },
338
+ {
339
+ x: mx,
340
+ y: p3.y
341
+ },
342
+ p3
343
+ ];
344
+ return {
345
+ path: cubicPath(points),
346
+ labelX: mx,
347
+ labelY: (p0.y + p3.y) / 2,
348
+ labelAnchor: "middle",
349
+ points
350
+ };
351
+ }
352
+ const p0 = {
353
+ x: source.x + source.width / 2,
354
+ y: source.y + source.height
355
+ };
356
+ const p3 = {
357
+ x: target.x + target.width / 2,
358
+ y: target.y
359
+ };
360
+ const my = (p0.y + p3.y) / 2;
361
+ const points = [
362
+ p0,
363
+ {
364
+ x: p0.x,
365
+ y: my
366
+ },
367
+ {
368
+ x: p3.x,
369
+ y: my
370
+ },
371
+ p3
372
+ ];
373
+ return {
374
+ path: cubicPath(points),
375
+ labelX: (p0.x + p3.x) / 2,
376
+ labelY: my,
377
+ labelAnchor: "middle",
378
+ points
379
+ };
380
+ }
381
+ function sideAttach(node, other, side, dir) {
382
+ const underToggle = node.outgoingCount > 0 && (dir === "horizontal" && side === "right" || dir === "vertical" && side === "below");
383
+ if (side === "right" || side === "left") {
384
+ const x = side === "right" ? node.x + node.width : node.x;
385
+ let y = node.y + node.height / 2;
386
+ if (underToggle) y += Math.sign(other.y - node.y || 1) * TOGGLE_CLEARANCE;
387
+ return {
388
+ x,
389
+ y
390
+ };
391
+ }
392
+ const y = side === "below" ? node.y + node.height : node.y;
393
+ let x = node.x + node.width / 2;
394
+ if (underToggle) x += Math.sign(other.x - node.x || 1) * TOGGLE_CLEARANCE;
395
+ return {
396
+ x,
397
+ y
398
+ };
399
+ }
400
+ function bowedGeometry(source, target, obstacles, side, dir, lane = 0, baseOverride) {
401
+ const all = [
402
+ source,
403
+ target,
404
+ ...obstacles
405
+ ];
406
+ const control = (BOW_CLEARANCE + lane * BOW_LANE_STEP) / .75;
407
+ const p0 = sideAttach(source, target, side, dir);
408
+ const p3 = sideAttach(target, source, side, dir);
409
+ const toggleSide = dir === "horizontal" ? "right" : "below";
410
+ const extent = (n) => side === toggleSide && n.outgoingCount > 0 ? TOGGLE_EXTENT : 0;
411
+ const outward = side === "below" || side === "right" ? 1 : -1;
412
+ let column;
413
+ let base;
414
+ switch (side) {
415
+ case "below":
416
+ column = Math.max(...all.map((n) => n.y + n.height));
417
+ base = Math.max(...all.map((n) => n.y + n.height + extent(n)));
418
+ break;
419
+ case "above":
420
+ column = base = Math.min(...all.map((n) => n.y));
421
+ break;
422
+ case "right":
423
+ column = Math.max(...all.map((n) => n.x + n.width));
424
+ base = Math.max(...all.map((n) => n.x + n.width + extent(n)));
425
+ break;
426
+ case "left": column = base = Math.min(...all.map((n) => n.x));
427
+ }
428
+ if (baseOverride !== void 0) base = baseOverride;
429
+ const reach = base + outward * control;
430
+ const points = side === "right" || side === "left" ? [
431
+ p0,
432
+ {
433
+ x: reach,
434
+ y: p0.y
435
+ },
436
+ {
437
+ x: reach,
438
+ y: p3.y
439
+ },
440
+ p3
441
+ ] : [
442
+ p0,
443
+ {
444
+ x: p0.x,
445
+ y: reach
446
+ },
447
+ {
448
+ x: p3.x,
449
+ y: reach
450
+ },
451
+ p3
452
+ ];
453
+ const apex = cubicAt(points, .5);
454
+ const sideways = side === "right" || side === "left";
455
+ const labelX = sideways ? apex.x + outward * EDGE_LABEL_GAP : apex.x;
456
+ const labelY = sideways ? apex.y : apex.y + outward * 8.5;
457
+ const along = sideways ? [p0.y, p3.y] : [p0.x, p3.x];
458
+ return {
459
+ path: cubicPath(points),
460
+ labelX,
461
+ labelY,
462
+ labelAnchor: sideways ? outward > 0 ? "start" : "end" : "middle",
463
+ points,
464
+ bow: {
465
+ side,
466
+ column,
467
+ base,
468
+ apex: side === "right" || side === "left" ? apex.x : apex.y,
469
+ lo: Math.min(...along),
470
+ hi: Math.max(...along),
471
+ source,
472
+ target,
473
+ obstacles,
474
+ dir
475
+ }
476
+ };
477
+ }
478
+ function requiredGap(nodes, edges, dir, metrics, labelsShown) {
479
+ const along = dir === "horizontal" ? {
480
+ start: (n) => n.x,
481
+ end: (n) => n.x + n.width,
482
+ out: "right",
483
+ back: "left"
484
+ } : {
485
+ start: (n) => n.y,
486
+ end: (n) => n.y + n.height,
487
+ out: "below",
488
+ back: "above"
489
+ };
490
+ const first = Math.min(...nodes.map(along.start));
491
+ const last = Math.max(...nodes.map(along.end));
492
+ let need = metrics.gap;
493
+ for (const { bow, label } of edges) {
494
+ if (!bow) continue;
495
+ const shown = labelsShown && label;
496
+ const room = dir === "horizontal" ? shown ? EDGE_LABEL_GAP + edgeLabelWidth(metrics.measure, label) : 0 : shown ? 13 : 0;
497
+ if (bow.side === along.out && bow.column < last) need = Math.max(need, bow.apex - bow.column + room + BOW_LABEL_MARGIN);
498
+ else if (bow.side === along.back && bow.column > first) need = Math.max(need, bow.column - bow.apex + room + BOW_LABEL_MARGIN);
499
+ }
500
+ return Math.ceil(need);
501
+ }
502
+ const acrossSides = (dir) => dir === "horizontal" ? ["below", "above"] : ["right", "left"];
503
+ const alongSides = (dir) => dir === "horizontal" ? ["right", "left"] : ["below", "above"];
504
+ function routeCrossRef(source, target, dir, nodes) {
505
+ const exclude = /* @__PURE__ */ new Set([source.id, target.id]);
506
+ const [s0, s1] = dir === "horizontal" ? [source.x, source.x + source.width] : [source.y, source.y + source.height];
507
+ const [t0, t1] = dir === "horizontal" ? [target.x, target.x + target.width] : [target.y, target.y + target.height];
508
+ const ahead = t0 >= s1;
509
+ const behind = t1 <= s0;
510
+ let best = null;
511
+ let bestCount = Infinity;
512
+ let obstacles;
513
+ let sides;
514
+ if (ahead) {
515
+ const direct = directGeometry(source, target, dir);
516
+ obstacles = crossedNodes(direct.points, nodes, exclude);
517
+ if (!obstacles.length) return direct;
518
+ best = direct;
519
+ bestCount = obstacles.length;
520
+ sides = [...acrossSides(dir), ...alongSides(dir)];
521
+ } else {
522
+ const c0 = {
523
+ x: source.x + source.width / 2,
524
+ y: source.y + source.height / 2
525
+ };
526
+ const c1 = {
527
+ x: target.x + target.width / 2,
528
+ y: target.y + target.height / 2
529
+ };
530
+ obstacles = crossedNodes([
531
+ c0,
532
+ c0,
533
+ c1,
534
+ c1
535
+ ], nodes, exclude);
536
+ sides = behind ? [...acrossSides(dir), ...alongSides(dir)] : alongSides(dir);
537
+ }
538
+ for (const side of sides) {
539
+ const candidate = bowedGeometry(source, target, obstacles, side, dir);
540
+ const count = crossedNodes(candidate.points, nodes, exclude).length;
541
+ if (count < bestCount) {
542
+ best = candidate;
543
+ bestCount = count;
544
+ if (count === 0) break;
545
+ }
546
+ }
547
+ return best ?? bowedGeometry(source, target, obstacles, sides[0], dir);
548
+ }
549
+ function spreadBows(edges) {
550
+ const groups = /* @__PURE__ */ new Map();
551
+ for (const edge of edges) if (edge.bow) push(groups, `${edge.bow.side}@${Math.round(edge.bow.column)}`, {
552
+ edge,
553
+ bow: edge.bow
554
+ });
555
+ for (const group of groups.values()) {
556
+ if (group.length < 2) continue;
557
+ group.sort((a, b) => a.bow.hi - a.bow.lo - (b.bow.hi - b.bow.lo));
558
+ const side = group[0].bow.side;
559
+ const base = side === "below" || side === "right" ? Math.max(...group.map((g) => g.bow.base)) : Math.min(...group.map((g) => g.bow.base));
560
+ const placed = [];
561
+ for (const { edge, bow } of group) {
562
+ const taken = new Set(placed.filter((p) => p.lo < bow.hi && bow.lo < p.hi).map((p) => p.lane));
563
+ let lane = 0;
564
+ while (taken.has(lane)) lane++;
565
+ placed.push({
566
+ lo: bow.lo,
567
+ hi: bow.hi,
568
+ lane
569
+ });
570
+ if (lane === 0 && base === bow.base) continue;
571
+ const geo = bowedGeometry(bow.source, bow.target, bow.obstacles, bow.side, bow.dir, lane, base);
572
+ edge.path = geo.path;
573
+ edge.labelX = geo.labelX;
574
+ edge.labelY = geo.labelY;
575
+ edge.labelAnchor = geo.labelAnchor;
576
+ edge.bow = geo.bow;
577
+ }
578
+ }
579
+ }
580
+ function resolveRelation(relation) {
581
+ return relation && RELATION_STYLES[relation] ? relation : "depends";
582
+ }
583
+ function createCrossRefEdges(nodeMap, allOriginal, dir, backEdges) {
584
+ const edges = [];
585
+ const nodes = [...nodeMap.values()];
586
+ for (const [, orig] of allOriginal) {
587
+ if (!orig.dependsOn?.length) continue;
588
+ const target = nodeMap.get(orig.id);
589
+ if (!target) continue;
590
+ for (const dep of orig.dependsOn) {
591
+ const source = nodeMap.get(dep.id);
592
+ if (!source) continue;
593
+ const relation = resolveRelation(dep.relation);
594
+ const style = RELATION_STYLES[relation];
595
+ const geo = routeCrossRef(source, target, dir, nodes);
596
+ edges.push({
597
+ id: `${dep.id}⇢${orig.id}`,
598
+ sourceId: dep.id,
599
+ targetId: orig.id,
600
+ path: geo.path,
601
+ relation: dep.relation,
602
+ label: dep.relationLabel ?? style.label,
603
+ labelX: geo.labelX,
604
+ labelY: geo.labelY,
605
+ labelAnchor: geo.labelAnchor,
606
+ color: style.color,
607
+ dashed: style.dashed,
608
+ isCrossRef: true,
609
+ arrow: true,
610
+ marker: relation,
611
+ bow: geo.bow
612
+ });
613
+ }
614
+ }
615
+ for (const back of backEdges) {
616
+ const source = nodeMap.get(back.from);
617
+ const target = nodeMap.get(back.to);
618
+ if (!source || !target) continue;
619
+ const style = RELATION_STYLES.depends;
620
+ const geo = routeCrossRef(source, target, dir, nodes);
621
+ edges.push({
622
+ id: `${back.from}↺${back.to}`,
623
+ sourceId: back.from,
624
+ targetId: back.to,
625
+ path: geo.path,
626
+ labelX: geo.labelX,
627
+ labelY: geo.labelY,
628
+ labelAnchor: geo.labelAnchor,
629
+ color: style.color,
630
+ dashed: true,
631
+ isCrossRef: true,
632
+ arrow: true,
633
+ marker: "depends",
634
+ bow: geo.bow
635
+ });
636
+ }
637
+ spreadBows(edges);
638
+ return edges;
639
+ }
640
+ function collectGraph(roots) {
641
+ const nodes = /* @__PURE__ */ new Map();
642
+ const order = [];
643
+ const edges = /* @__PURE__ */ new Map();
644
+ const walk = (node) => {
645
+ if (!nodes.has(node.id)) {
646
+ nodes.set(node.id, node);
647
+ order.push(node.id);
648
+ }
649
+ for (const child of node.children || []) {
650
+ const fresh = !nodes.has(child.id);
651
+ if (node.id !== child.id) edges.set(`${node.id}→${child.id}`, {
652
+ from: node.id,
653
+ to: child.id,
654
+ structural: true,
655
+ back: false
656
+ });
657
+ if (fresh) walk(child);
658
+ }
659
+ };
660
+ for (const root of roots) walk(root);
661
+ for (const id of order) for (const dep of nodes.get(id)?.dependsOn || []) {
662
+ if (dep.id === id || !nodes.has(dep.id)) continue;
663
+ const style = RELATION_STYLES[resolveRelation(dep.relation)];
664
+ edges.set(`${dep.id}→${id}`, {
665
+ from: dep.id,
666
+ to: id,
667
+ relation: dep.relation,
668
+ label: dep.relationLabel ?? style.label,
669
+ structural: false,
670
+ back: false
671
+ });
672
+ }
673
+ return {
674
+ order,
675
+ nodes,
676
+ edges: [...edges.values()]
677
+ };
678
+ }
679
+ function assignLayers(order, edges) {
680
+ const out = /* @__PURE__ */ new Map();
681
+ for (const edge of edges) push(out, edge.from, edge);
682
+ const UNSEEN = 0, ON_STACK = 1, DONE = 2;
683
+ const state = /* @__PURE__ */ new Map();
684
+ for (const start of order) {
685
+ if (state.get(start)) continue;
686
+ state.set(start, ON_STACK);
687
+ const stack = [{
688
+ id: start,
689
+ next: 0
690
+ }];
691
+ while (stack.length) {
692
+ const frame = stack[stack.length - 1];
693
+ const outgoing = out.get(frame.id) ?? [];
694
+ if (frame.next >= outgoing.length) {
695
+ state.set(frame.id, DONE);
696
+ stack.pop();
697
+ continue;
698
+ }
699
+ const edge = outgoing[frame.next++];
700
+ const seen = state.get(edge.to) ?? UNSEEN;
701
+ if (seen === ON_STACK) edge.back = true;
702
+ if (seen !== UNSEEN) continue;
703
+ state.set(edge.to, ON_STACK);
704
+ stack.push({
705
+ id: edge.to,
706
+ next: 0
707
+ });
708
+ }
709
+ }
710
+ const indegree = new Map(order.map((id) => [id, 0]));
711
+ for (const edge of edges) if (!edge.back) indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1);
712
+ const layer = new Map(order.map((id) => [id, 0]));
713
+ const queue = order.filter((id) => !indegree.get(id));
714
+ for (let i = 0; i < queue.length; i++) for (const edge of out.get(queue[i]) ?? []) {
715
+ if (edge.back) continue;
716
+ layer.set(edge.to, Math.max(layer.get(edge.to) ?? 0, (layer.get(queue[i]) ?? 0) + 1));
717
+ const remaining = (indegree.get(edge.to) ?? 0) - 1;
718
+ indegree.set(edge.to, remaining);
719
+ if (!remaining) queue.push(edge.to);
720
+ }
721
+ return layer;
722
+ }
723
+ function median(values) {
724
+ if (!values.length) return -1;
725
+ const sorted = [...values].sort((a, b) => a - b);
726
+ const mid = sorted.length >> 1;
727
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
728
+ }
729
+ function positionIndex(layers) {
730
+ const index = /* @__PURE__ */ new Map();
731
+ for (const layer of layers) layer.forEach((id, i) => index.set(id, i));
732
+ return index;
733
+ }
734
+ function countCrossings(layers, edges, layerOf) {
735
+ const index = positionIndex(layers);
736
+ const groups = /* @__PURE__ */ new Map();
737
+ for (const edge of edges) {
738
+ if (edge.back) continue;
739
+ const from = index.get(edge.from);
740
+ const to = index.get(edge.to);
741
+ if (from === void 0 || to === void 0) continue;
742
+ push(groups, `${layerOf.get(edge.from)}:${layerOf.get(edge.to)}`, [from, to]);
743
+ }
744
+ let crossings = 0;
745
+ for (const pairs of groups.values()) for (let i = 0; i < pairs.length; i++) for (let j = i + 1; j < pairs.length; j++) if ((pairs[i][0] - pairs[j][0]) * (pairs[i][1] - pairs[j][1]) < 0) crossings++;
746
+ return crossings;
747
+ }
748
+ const ORDER_SWEEPS = 8;
749
+ function orderLayers(layers, edges, layerOf) {
750
+ const predecessors = /* @__PURE__ */ new Map();
751
+ const successors = /* @__PURE__ */ new Map();
752
+ for (const edge of edges) {
753
+ if (edge.back) continue;
754
+ push(predecessors, edge.to, edge.from);
755
+ push(successors, edge.from, edge.to);
756
+ }
757
+ const current = layers.map((layer) => [...layer]);
758
+ let best = current.map((layer) => [...layer]);
759
+ let bestCrossings = countCrossings(current, edges, layerOf);
760
+ for (let sweep = 0; sweep < ORDER_SWEEPS && bestCrossings > 0; sweep++) {
761
+ const downward = sweep % 2 === 0;
762
+ const reference = downward ? predecessors : successors;
763
+ const index = positionIndex(current);
764
+ const targets = current.map((_, i) => i);
765
+ for (const i of downward ? targets.slice(1) : targets.slice(0, -1).reverse()) current[i] = [...current[i]].map((id, row) => {
766
+ const m = median((reference.get(id) ?? []).map((n) => index.get(n)).filter((p) => p !== void 0));
767
+ return {
768
+ id,
769
+ row,
770
+ key: m < 0 ? row : m
771
+ };
772
+ }).sort((a, b) => a.key - b.key || a.row - b.row).map((entry) => entry.id);
773
+ const crossings = countCrossings(current, edges, layerOf);
774
+ if (crossings < bestCrossings) {
775
+ bestCrossings = crossings;
776
+ best = current.map((layer) => [...layer]);
777
+ }
778
+ }
779
+ return best;
780
+ }
781
+ const ALIGN_PASSES = 4;
782
+ function alignSecondary(layers, edges, step) {
783
+ const predecessors = /* @__PURE__ */ new Map();
784
+ const successors = /* @__PURE__ */ new Map();
785
+ for (const edge of edges) {
786
+ if (edge.back) continue;
787
+ push(predecessors, edge.to, edge.from);
788
+ push(successors, edge.from, edge.to);
789
+ }
790
+ const pos = /* @__PURE__ */ new Map();
791
+ for (const layer of layers) layer.forEach((id, i) => pos.set(id, i * step));
792
+ for (let pass = 0; pass < ALIGN_PASSES; pass++) {
793
+ const downward = pass % 2 === 0;
794
+ const reference = downward ? predecessors : successors;
795
+ const indices = layers.map((_, i) => i);
796
+ for (const i of downward ? indices.slice(1) : indices.slice(0, -1).reverse()) {
797
+ const layer = layers[i];
798
+ if (!layer.length) continue;
799
+ const wanted = layer.map((id) => {
800
+ const neighbours = (reference.get(id) ?? []).map((n) => pos.get(n)).filter((p) => p !== void 0);
801
+ return neighbours.length ? median(neighbours) : pos.get(id) ?? 0;
802
+ });
803
+ const placed = [];
804
+ for (let k = 0; k < layer.length; k++) placed[k] = k === 0 ? wanted[k] : Math.max(wanted[k], placed[k - 1] + step);
805
+ const drift = placed.reduce((sum, p, k) => sum + (p - wanted[k]), 0) / placed.length;
806
+ layer.forEach((id, k) => pos.set(id, placed[k] - drift));
807
+ }
808
+ }
809
+ const min = Math.min(...pos.values());
810
+ for (const [id, value] of pos) pos.set(id, value - min);
811
+ return pos;
812
+ }
813
+ function layoutLayered(roots, dir, allNodes, metrics) {
814
+ const { order, nodes: originals, edges } = collectGraph(roots);
815
+ if (!order.length) return {
816
+ nodes: [],
817
+ edges: [],
818
+ nodeMap: /* @__PURE__ */ new Map(),
819
+ width: 0,
820
+ height: 0
821
+ };
822
+ const layerOf = assignLayers(order, edges);
823
+ const depth = Math.max(...layerOf.values());
824
+ const layers = Array.from({ length: depth + 1 }, () => []);
825
+ for (const id of order) layers[layerOf.get(id) ?? 0].push(id);
826
+ const ordered = orderLayers(layers, edges, layerOf);
827
+ const primarySize = dir === "horizontal" ? metrics.width : metrics.height;
828
+ const secondarySize = dir === "horizontal" ? metrics.height : metrics.width;
829
+ const secondary = alignSecondary(ordered, edges, secondarySize + V_GAP);
830
+ const nodes = [];
831
+ const nodeMap = /* @__PURE__ */ new Map();
832
+ for (const layer of ordered) for (const id of layer) {
833
+ const source = originals.get(id);
834
+ if (!source) continue;
835
+ const primary = (layerOf.get(id) ?? 0) * (primarySize + metrics.gap);
836
+ const across = secondary.get(id) ?? 0;
837
+ const laid = placeNode(source, allNodes.get(id), dir === "horizontal" ? primary : across, dir === "horizontal" ? across : primary, layerOf.get(id) ?? 0, null, metrics);
838
+ nodes.push(laid);
839
+ nodeMap.set(id, laid);
840
+ }
841
+ const laidOut = [...nodeMap.values()];
842
+ const layoutEdges = [];
843
+ for (const edge of edges) {
844
+ const source = nodeMap.get(edge.from);
845
+ const target = nodeMap.get(edge.to);
846
+ if (!source || !target) continue;
847
+ const relation = resolveRelation(edge.relation);
848
+ const style = RELATION_STYLES[relation];
849
+ const geo = routeCrossRef(source, target, dir, laidOut);
850
+ layoutEdges.push({
851
+ id: `${edge.from}${edge.back ? "↺" : "⇢"}${edge.to}`,
852
+ sourceId: edge.from,
853
+ targetId: edge.to,
854
+ path: geo.path,
855
+ relation: edge.relation,
856
+ label: edge.label,
857
+ labelX: geo.labelX,
858
+ labelY: geo.labelY,
859
+ labelAnchor: geo.labelAnchor,
860
+ color: edge.structural ? "var(--color-neutral-400)" : style.color,
861
+ dashed: edge.back || !edge.structural && style.dashed,
862
+ isCrossRef: edge.back,
863
+ arrow: true,
864
+ marker: relation,
865
+ bow: geo.bow
866
+ });
867
+ }
868
+ spreadBows(layoutEdges);
869
+ const width = (depth + 1) * primarySize + depth * metrics.gap;
870
+ const across = Math.max(...laidOut.map((n) => dir === "horizontal" ? n.y : n.x)) + secondarySize;
871
+ return {
872
+ nodes,
873
+ edges: layoutEdges,
874
+ nodeMap,
875
+ width: dir === "horizontal" ? width : across,
876
+ height: dir === "horizontal" ? across : width
877
+ };
878
+ }
879
+ const STATUS_COLORS = {
880
+ default: {
881
+ bg: "var(--color-neutral-50)",
882
+ border: "var(--color-neutral-300)",
883
+ text: "var(--color-text-primary)"
884
+ },
885
+ active: {
886
+ bg: "var(--color-primary-50)",
887
+ border: "var(--color-primary-400)",
888
+ text: "var(--color-text-primary)"
889
+ },
890
+ success: {
891
+ bg: "var(--color-success-50, #f0fdf4)",
892
+ border: "var(--color-success-default)",
893
+ text: "var(--color-text-primary)"
894
+ },
895
+ warning: {
896
+ bg: "var(--color-warning-50, #fffbeb)",
897
+ border: "var(--color-warning-default)",
898
+ text: "var(--color-text-primary)"
899
+ },
900
+ error: {
901
+ bg: "var(--color-error-50, #fef2f2)",
902
+ border: "var(--color-error-default)",
903
+ text: "var(--color-text-primary)"
904
+ },
905
+ muted: {
906
+ bg: "var(--color-neutral-100)",
907
+ border: "var(--color-neutral-200)",
908
+ text: "var(--color-text-tertiary)"
909
+ }
910
+ };
911
+ function parseRgb(color) {
912
+ const hex = color.trim().match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
913
+ if (hex) {
914
+ const h = hex[1];
915
+ const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
916
+ return [
917
+ 0,
918
+ 2,
919
+ 4
920
+ ].map((i) => parseInt(full.slice(i, i + 2), 16));
921
+ }
922
+ const rgb = color.match(/^rgba?\(([^)]+)\)/i);
923
+ if (rgb) {
924
+ const p = rgb[1].split(",").map((s) => parseFloat(s));
925
+ if (p.length >= 3 && p.every((n) => !Number.isNaN(n))) return [
926
+ p[0],
927
+ p[1],
928
+ p[2]
929
+ ];
930
+ }
931
+ return null;
932
+ }
933
+ function readableInk(color) {
934
+ const rgb = parseRgb(color);
935
+ if (!rgb) return "var(--color-text-primary)";
936
+ const [r, g, b] = rgb.map((c) => {
937
+ const s = c / 255;
938
+ return s <= .03928 ? s / 12.92 : Math.pow((s + .055) / 1.055, 2.4);
939
+ });
940
+ return .2126 * r + .7152 * g + .0722 * b > .4 ? "#111827" : "#f9fafb";
941
+ }
942
+ var DependencyViewerComponent = class DependencyViewerComponent {
943
+ root = input.required(...ngDevMode ? [{ debugName: "root" }] : /* istanbul ignore next */ []);
944
+ direction = input("horizontal", ...ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []);
945
+ height = input("500px", ...ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []);
946
+ layout = input("tree", ...ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []);
947
+ showToolbar = input(true, ...ngDevMode ? [{ debugName: "showToolbar" }] : /* istanbul ignore next */ []);
948
+ showEdgeLabels = input(true, ...ngDevMode ? [{ debugName: "showEdgeLabels" }] : /* istanbul ignore next */ []);
949
+ edgeWidth = input(1.5, ...ngDevMode ? [{ debugName: "edgeWidth" }] : /* istanbul ignore next */ []);
950
+ autoFit = input(false, ...ngDevMode ? [{ debugName: "autoFit" }] : /* istanbul ignore next */ []);
951
+ fitMode = input(null, ...ngDevMode ? [{ debugName: "fitMode" }] : /* istanbul ignore next */ []);
952
+ minNodeSize = input(null, ...ngDevMode ? [{ debugName: "minNodeSize" }] : /* istanbul ignore next */ []);
953
+ interactive = input(true, ...ngDevMode ? [{ debugName: "interactive" }] : /* istanbul ignore next */ []);
954
+ anchorNodeId = input(null, ...ngDevMode ? [{ debugName: "anchorNodeId" }] : /* istanbul ignore next */ []);
955
+ typeColors = input({}, ...ngDevMode ? [{ debugName: "typeColors" }] : /* istanbul ignore next */ []);
956
+ hiddenRelations = input([], ...ngDevMode ? [{ debugName: "hiddenRelations" }] : /* istanbul ignore next */ []);
957
+ hiddenTypes = input([], ...ngDevMode ? [{ debugName: "hiddenTypes" }] : /* istanbul ignore next */ []);
958
+ zoomInLabel = input("Zoom in", ...ngDevMode ? [{ debugName: "zoomInLabel" }] : /* istanbul ignore next */ []);
959
+ zoomOutLabel = input("Zoom out", ...ngDevMode ? [{ debugName: "zoomOutLabel" }] : /* istanbul ignore next */ []);
960
+ resetZoomLabel = input("Reset", ...ngDevMode ? [{ debugName: "resetZoomLabel" }] : /* istanbul ignore next */ []);
961
+ depthLabel = input("Depth:", ...ngDevMode ? [{ debugName: "depthLabel" }] : /* istanbul ignore next */ []);
962
+ childrenLabel = input("Children:", ...ngDevMode ? [{ debugName: "childrenLabel" }] : /* istanbul ignore next */ []);
963
+ dependsOnLabel = input("Depends on:", ...ngDevMode ? [{ debugName: "dependsOnLabel" }] : /* istanbul ignore next */ []);
964
+ dependenciesLabel = input("Dependencies:", ...ngDevMode ? [{ debugName: "dependenciesLabel" }] : /* istanbul ignore next */ []);
965
+ nodeSelect = output();
966
+ nodeExpand = output();
967
+ zoom = signal(100, ...ngDevMode ? [{ debugName: "zoom" }] : /* istanbul ignore next */ []);
968
+ panX = signal(40, ...ngDevMode ? [{ debugName: "panX" }] : /* istanbul ignore next */ []);
969
+ panY = signal(40, ...ngDevMode ? [{ debugName: "panY" }] : /* istanbul ignore next */ []);
970
+ selectedNodeId = signal(null, ...ngDevMode ? [{ debugName: "selectedNodeId" }] : /* istanbul ignore next */ []);
971
+ collapsedIds = signal(/* @__PURE__ */ new Set(), ...ngDevMode ? [{ debugName: "collapsedIds" }] : /* istanbul ignore next */ []);
972
+ isPanning = false;
973
+ lastMouseX = 0;
974
+ lastMouseY = 0;
975
+ hostEl = inject(ElementRef);
976
+ canvasRef = viewChild("canvas", ...ngDevMode ? [{ debugName: "canvasRef" }] : /* istanbul ignore next */ []);
977
+ anchorPos = null;
978
+ lineHeight = LABEL_LINE_HEIGHT;
979
+ baselineShift = LABEL_BASELINE_SHIFT;
980
+ textMeasure = null;
981
+ measureText() {
982
+ if (!this.textMeasure) {
983
+ let family = "";
984
+ if (typeof getComputedStyle === "function") family = getComputedStyle(this.hostEl.nativeElement).fontFamily;
985
+ this.textMeasure = createTextMeasurer(family || "sans-serif", LABEL_FONT_SIZE, LABEL_FONT_WEIGHT);
986
+ }
987
+ return this.textMeasure;
988
+ }
989
+ roots = computed(() => {
990
+ const root = this.root();
991
+ return Array.isArray(root) ? root : [root];
992
+ }, ...ngDevMode ? [{ debugName: "roots" }] : /* istanbul ignore next */ []);
993
+ effectiveRoots = computed(() => {
994
+ const collapsed = this.collapsedIds();
995
+ const visited = /* @__PURE__ */ new Set();
996
+ return this.roots().map((root) => this.pruneCollapsed(root, collapsed, visited));
997
+ }, ...ngDevMode ? [{ debugName: "effectiveRoots" }] : /* istanbul ignore next */ []);
998
+ allOriginalNodes = computed(() => {
999
+ const map = /* @__PURE__ */ new Map();
1000
+ for (const root of this.roots()) collectAllNodes(root, map);
1001
+ return map;
1002
+ }, ...ngDevMode ? [{ debugName: "allOriginalNodes" }] : /* istanbul ignore next */ []);
1003
+ nodeMetrics = computed(() => measureNodes(this.allOriginalNodes().values(), this.measureText()), ...ngDevMode ? [{ debugName: "nodeMetrics" }] : /* istanbul ignore next */ []);
1004
+ graph = computed(() => {
1005
+ const dir = this.direction();
1006
+ const hiddenTypes = new Set(this.hiddenTypes());
1007
+ const hiddenRelations = new Set(this.hiddenRelations());
1008
+ const allNodes = this.allOriginalNodes();
1009
+ const place = (metrics) => this.layout() === "layered" ? layoutLayered(this.effectiveRoots(), dir, allNodes, metrics) : this.layoutTree(dir, allNodes, metrics);
1010
+ const metrics = this.nodeMetrics();
1011
+ let placed = place(metrics);
1012
+ const gap = requiredGap(placed.nodes, placed.edges, dir, metrics, this.showEdgeLabels());
1013
+ if (gap > metrics.gap) placed = place({
1014
+ ...metrics,
1015
+ gap
1016
+ });
1017
+ const edges = placed.edges.filter((e) => !(e.relation && hiddenRelations.has(e.relation)));
1018
+ const visibleNodes = hiddenTypes.size ? placed.nodes.filter((n) => !(n.type && hiddenTypes.has(n.type))) : placed.nodes;
1019
+ const visibleIds = new Set(visibleNodes.map((n) => n.id));
1020
+ return {
1021
+ nodes: visibleNodes,
1022
+ edges: hiddenTypes.size ? edges.filter((e) => visibleIds.has(e.sourceId) && visibleIds.has(e.targetId)) : edges,
1023
+ nodeMap: placed.nodeMap,
1024
+ width: placed.width,
1025
+ height: placed.height
1026
+ };
1027
+ }, ...ngDevMode ? [{ debugName: "graph" }] : /* istanbul ignore next */ []);
1028
+ layoutTree(dir, allNodes, metrics) {
1029
+ const backEdges = [];
1030
+ const visited = /* @__PURE__ */ new Set();
1031
+ const measured = this.effectiveRoots().map((root) => measureTree(root, 0, dir, visited, backEdges, metrics));
1032
+ const nodes = [];
1033
+ const nodeMap = /* @__PURE__ */ new Map();
1034
+ const treeEdges = [];
1035
+ let offset = 0;
1036
+ for (const measure of measured) {
1037
+ if (dir === "horizontal") layoutTreeH(measure, 0, offset, null, nodes, treeEdges, allNodes, nodeMap, metrics);
1038
+ else layoutTreeV(measure, offset, 0, null, nodes, treeEdges, allNodes, nodeMap, metrics);
1039
+ offset += measure.secondary + V_GAP;
1040
+ }
1041
+ const primary = measured.length ? Math.max(...measured.map((m) => m.primary)) : 0;
1042
+ const secondary = Math.max(0, offset - V_GAP);
1043
+ return {
1044
+ nodes,
1045
+ edges: [...treeEdges, ...createCrossRefEdges(nodeMap, allNodes, dir, backEdges)],
1046
+ nodeMap,
1047
+ width: dir === "horizontal" ? primary : secondary,
1048
+ height: dir === "horizontal" ? secondary : primary
1049
+ };
1050
+ }
1051
+ contentHeight = signal(null, ...ngDevMode ? [{ debugName: "contentHeight" }] : /* istanbul ignore next */ []);
1052
+ effectiveFitMode = computed(() => this.fitMode() ?? (this.autoFit() ? "contain" : "none"), ...ngDevMode ? [{ debugName: "effectiveFitMode" }] : /* istanbul ignore next */ []);
1053
+ hostHeight = computed(() => this.contentHeight() === null ? this.height() : "auto", ...ngDevMode ? [{ debugName: "hostHeight" }] : /* istanbul ignore next */ []);
1054
+ minFitScale = computed(() => {
1055
+ const min = this.minNodeSize();
1056
+ if (!min || min <= 0) return MIN_FIT_SCALE;
1057
+ return Math.min(MAX_FIT_SCALE, Math.max(MIN_FIT_SCALE, min / this.nodeMetrics().width));
1058
+ }, ...ngDevMode ? [{ debugName: "minFitScale" }] : /* istanbul ignore next */ []);
1059
+ constructor() {
1060
+ effect(() => {
1061
+ const nodeMap = this.graph().nodeMap;
1062
+ const anchorId = this.anchorNodeId() ?? this.selectedNodeId();
1063
+ if (this.effectiveFitMode() !== "none" || !anchorId) {
1064
+ this.anchorPos = null;
1065
+ return;
1066
+ }
1067
+ const node = nodeMap.get(anchorId);
1068
+ if (!node) {
1069
+ this.anchorPos = null;
1070
+ return;
1071
+ }
1072
+ const prev = this.anchorPos;
1073
+ if (prev && prev.id === anchorId && (prev.x !== node.x || prev.y !== node.y)) {
1074
+ const dx = node.x - prev.x;
1075
+ const dy = node.y - prev.y;
1076
+ untracked(() => {
1077
+ const z = this.zoom() / 100;
1078
+ this.panX.set(this.panX() - dx * z);
1079
+ this.panY.set(this.panY() - dy * z);
1080
+ });
1081
+ }
1082
+ this.anchorPos = {
1083
+ id: anchorId,
1084
+ x: node.x,
1085
+ y: node.y
1086
+ };
1087
+ });
1088
+ effect(() => {
1089
+ if (this.effectiveFitMode() === "none") {
1090
+ untracked(() => this.contentHeight.set(null));
1091
+ return;
1092
+ }
1093
+ if (!this.canvasRef()) return;
1094
+ this.graph();
1095
+ this.minFitScale();
1096
+ untracked(() => this.fit());
1097
+ });
1098
+ effect((onCleanup) => {
1099
+ const el = this.canvasRef()?.nativeElement;
1100
+ if (this.effectiveFitMode() === "none" || !el || typeof ResizeObserver === "undefined") return;
1101
+ const observer = new ResizeObserver(() => this.fit());
1102
+ observer.observe(el);
1103
+ onCleanup(() => observer.disconnect());
1104
+ });
1105
+ }
1106
+ svgWidth = computed(() => this.graph().width + 80, ...ngDevMode ? [{ debugName: "svgWidth" }] : /* istanbul ignore next */ []);
1107
+ svgHeight = computed(() => this.graph().height + 80, ...ngDevMode ? [{ debugName: "svgHeight" }] : /* istanbul ignore next */ []);
1108
+ viewBox = computed(() => `0 0 ${this.svgWidth()} ${this.svgHeight()}`, ...ngDevMode ? [{ debugName: "viewBox" }] : /* istanbul ignore next */ []);
1109
+ transform = computed(() => {
1110
+ const z = this.zoom() / 100;
1111
+ return `translate(${this.panX()}px, ${this.panY()}px) scale(${z})`;
1112
+ }, ...ngDevMode ? [{ debugName: "transform" }] : /* istanbul ignore next */ []);
1113
+ zoomLabel = computed(() => Math.round(this.zoom()), ...ngDevMode ? [{ debugName: "zoomLabel" }] : /* istanbul ignore next */ []);
1114
+ selectedNode = computed(() => {
1115
+ const id = this.selectedNodeId();
1116
+ if (!id) return null;
1117
+ return this.graph().nodes.find((n) => n.id === id) ?? null;
1118
+ }, ...ngDevMode ? [{ debugName: "selectedNode" }] : /* istanbul ignore next */ []);
1119
+ selectedDependsOn = computed(() => {
1120
+ const id = this.selectedNodeId();
1121
+ if (!id) return [];
1122
+ return this.allOriginalNodes().get(id)?.dependsOn ?? [];
1123
+ }, ...ngDevMode ? [{ debugName: "selectedDependsOn" }] : /* istanbul ignore next */ []);
1124
+ legendItems = computed(() => {
1125
+ const seen = /* @__PURE__ */ new Map();
1126
+ for (const edge of this.graph().edges) {
1127
+ if (!edge.label || seen.has(edge.label)) continue;
1128
+ seen.set(edge.label, {
1129
+ label: edge.label,
1130
+ color: edge.color,
1131
+ dashed: edge.dashed
1132
+ });
1133
+ }
1134
+ return Array.from(seen.values());
1135
+ }, ...ngDevMode ? [{ debugName: "legendItems" }] : /* istanbul ignore next */ []);
1136
+ typeLegendItems = computed(() => {
1137
+ const colors = this.typeColors();
1138
+ const seen = /* @__PURE__ */ new Map();
1139
+ for (const node of this.graph().nodes) {
1140
+ if (!node.type || seen.has(node.type) || !colors[node.type]) continue;
1141
+ seen.set(node.type, {
1142
+ type: node.type,
1143
+ color: colors[node.type]
1144
+ });
1145
+ }
1146
+ return Array.from(seen.values());
1147
+ }, ...ngDevMode ? [{ debugName: "typeLegendItems" }] : /* istanbul ignore next */ []);
1148
+ hasChildren(nodeId) {
1149
+ return !!this.allOriginalNodes().get(nodeId)?.children?.length;
1150
+ }
1151
+ isCollapsed(nodeId) {
1152
+ return this.collapsedIds().has(nodeId);
1153
+ }
1154
+ getRelationLabel(relation) {
1155
+ return RELATION_STYLES[relation]?.label ?? relation;
1156
+ }
1157
+ pruneCollapsed(node, collapsed, visited) {
1158
+ if (visited.has(node.id) || collapsed.has(node.id) || !node.children?.length) return {
1159
+ ...node,
1160
+ children: []
1161
+ };
1162
+ visited.add(node.id);
1163
+ return {
1164
+ ...node,
1165
+ children: node.children.map((c) => this.pruneCollapsed(c, collapsed, visited))
1166
+ };
1167
+ }
1168
+ selectNode(id, event) {
1169
+ event.stopPropagation();
1170
+ const next = this.selectedNodeId() === id ? null : id;
1171
+ this.selectedNodeId.set(next);
1172
+ if (!next) return;
1173
+ const original = this.allOriginalNodes().get(id);
1174
+ if (original) this.nodeSelect.emit(original);
1175
+ }
1176
+ expandNode(id, event) {
1177
+ event.stopPropagation();
1178
+ this.selectedNodeId.set(id);
1179
+ const original = this.allOriginalNodes().get(id);
1180
+ if (original) this.nodeExpand.emit(original);
1181
+ }
1182
+ toggleCollapse(id, event) {
1183
+ event.stopPropagation();
1184
+ this.collapsedIds.update((set) => {
1185
+ const next = new Set(set);
1186
+ if (next.has(id)) next.delete(id);
1187
+ else next.add(id);
1188
+ return next;
1189
+ });
1190
+ }
1191
+ deselectNode() {
1192
+ this.selectedNodeId.set(null);
1193
+ }
1194
+ zoomIn() {
1195
+ this.zoom.update((z) => Math.min(z + 25, 300));
1196
+ }
1197
+ zoomOut() {
1198
+ this.zoom.update((z) => Math.max(z - 25, 25));
1199
+ }
1200
+ resetZoom() {
1201
+ this.resetView();
1202
+ }
1203
+ focusNode(id) {
1204
+ const node = this.graph().nodeMap.get(id);
1205
+ if (!node) return;
1206
+ const z = this.zoom() / 100;
1207
+ const el = this.canvasEl();
1208
+ const viewW = el?.clientWidth ?? 0;
1209
+ const viewH = el?.clientHeight ?? 0;
1210
+ this.panX.set(viewW / 2 - (node.x + node.width / 2) * z);
1211
+ this.panY.set(viewH / 2 - (node.y + node.height / 2) * z);
1212
+ this.anchorPos = {
1213
+ id,
1214
+ x: node.x,
1215
+ y: node.y
1216
+ };
1217
+ }
1218
+ fit() {
1219
+ const mode = this.effectiveFitMode();
1220
+ if (mode === "none") return;
1221
+ const el = this.canvasEl();
1222
+ const viewW = el?.clientWidth ?? 0;
1223
+ const viewH = el?.clientHeight ?? 0;
1224
+ if (!viewW || !viewH) return;
1225
+ const box = this.contentBox();
1226
+ if (box.width <= 0 || box.height <= 0) return;
1227
+ const natural = mode === "fit-width" ? viewW / box.width : Math.min(viewW / box.width, viewH / box.height);
1228
+ const scale = Math.min(MAX_FIT_SCALE, Math.max(this.minFitScale(), natural));
1229
+ this.zoom.set(scale * 100);
1230
+ this.panX.set((viewW - box.width * scale) / 2 - box.x * scale);
1231
+ const scaledHeight = box.height * scale;
1232
+ if (mode === "fit-width") {
1233
+ this.contentHeight.set(Math.ceil(scaledHeight));
1234
+ this.panY.set(-box.y * scale);
1235
+ } else {
1236
+ this.contentHeight.set(null);
1237
+ this.panY.set((viewH - scaledHeight) / 2 - box.y * scale);
1238
+ }
1239
+ this.anchorPos = null;
1240
+ }
1241
+ resetView() {
1242
+ if (this.effectiveFitMode() !== "none") {
1243
+ this.fit();
1244
+ return;
1245
+ }
1246
+ this.zoom.set(100);
1247
+ this.panX.set(40);
1248
+ this.panY.set(40);
1249
+ }
1250
+ expand(id) {
1251
+ this.collapsedIds.update((set) => {
1252
+ if (!set.has(id)) return set;
1253
+ const next = new Set(set);
1254
+ next.delete(id);
1255
+ return next;
1256
+ });
1257
+ }
1258
+ collapse(id) {
1259
+ this.collapsedIds.update((set) => {
1260
+ if (set.has(id)) return set;
1261
+ const next = new Set(set);
1262
+ next.add(id);
1263
+ return next;
1264
+ });
1265
+ }
1266
+ expandAll() {
1267
+ this.collapsedIds.set(/* @__PURE__ */ new Set());
1268
+ }
1269
+ collapseAll() {
1270
+ const ids = /* @__PURE__ */ new Set();
1271
+ for (const [id, node] of this.allOriginalNodes()) if (node.children?.length) ids.add(id);
1272
+ this.collapsedIds.set(ids);
1273
+ }
1274
+ canvasEl() {
1275
+ return this.canvasRef()?.nativeElement ?? this.hostEl.nativeElement.querySelector(".dep-viewer__canvas");
1276
+ }
1277
+ contentBox() {
1278
+ const { nodes, edges } = this.graph();
1279
+ if (!nodes.length) return {
1280
+ x: 0,
1281
+ y: 0,
1282
+ width: 0,
1283
+ height: 0
1284
+ };
1285
+ let minX = Infinity;
1286
+ let minY = Infinity;
1287
+ let maxX = -Infinity;
1288
+ let maxY = -Infinity;
1289
+ for (const n of nodes) {
1290
+ minX = Math.min(minX, n.x);
1291
+ minY = Math.min(minY, n.y);
1292
+ maxX = Math.max(maxX, n.x + n.width);
1293
+ maxY = Math.max(maxY, n.y + n.height);
1294
+ }
1295
+ const measure = this.nodeMetrics().measure;
1296
+ const labelsShown = this.showEdgeLabels();
1297
+ for (const e of edges) {
1298
+ const w = labelsShown ? edgeLabelWidth(measure, e.label) : 0;
1299
+ const before = e.labelAnchor === "start" ? 0 : e.labelAnchor === "end" ? w : w / 2;
1300
+ minX = Math.min(minX, e.labelX - before);
1301
+ maxX = Math.max(maxX, e.labelX - before + w);
1302
+ minY = Math.min(minY, e.labelY - EDGE_LABEL_FONT_SIZE / 2);
1303
+ maxY = Math.max(maxY, e.labelY + EDGE_LABEL_FONT_SIZE / 2);
1304
+ }
1305
+ return {
1306
+ x: minX - FIT_PADDING,
1307
+ y: minY - FIT_PADDING,
1308
+ width: maxX - minX + 48,
1309
+ height: maxY - minY + 48
1310
+ };
1311
+ }
1312
+ onMouseDown(event) {
1313
+ if (!this.interactive() || event.button !== 0) return;
1314
+ this.isPanning = true;
1315
+ this.lastMouseX = event.clientX;
1316
+ this.lastMouseY = event.clientY;
1317
+ }
1318
+ onMouseMove(event) {
1319
+ if (!this.isPanning) return;
1320
+ this.panX.update((x) => x + event.clientX - this.lastMouseX);
1321
+ this.panY.update((y) => y + event.clientY - this.lastMouseY);
1322
+ this.lastMouseX = event.clientX;
1323
+ this.lastMouseY = event.clientY;
1324
+ }
1325
+ onMouseUp() {
1326
+ this.isPanning = false;
1327
+ }
1328
+ onWheel(event) {
1329
+ if (!this.interactive()) return;
1330
+ event.preventDefault();
1331
+ this.zoom.update((z) => event.deltaY < 0 ? Math.min(z + 10, 300) : Math.max(z - 10, 25));
1332
+ }
1333
+ getNodeBg(node) {
1334
+ return (node.type ? this.typeColors()[node.type] : void 0) ?? STATUS_COLORS[node.status].bg;
1335
+ }
1336
+ getNodeBorder(node) {
1337
+ return (node.type ? this.typeColors()[node.type] : void 0) ?? STATUS_COLORS[node.status].border;
1338
+ }
1339
+ getNodeText(node) {
1340
+ const typeColor = node.type ? this.typeColors()[node.type] : void 0;
1341
+ return typeColor ? readableInk(typeColor) : STATUS_COLORS[node.status].text;
1342
+ }
1343
+ static ɵfac = i0.ɵɵngDeclareFactory({
1344
+ minVersion: "12.0.0",
1345
+ version: "22.2.2",
1346
+ ngImport: i0,
1347
+ type: DependencyViewerComponent,
1348
+ deps: [],
1349
+ target: i0.ɵɵFactoryTarget.Component
1350
+ });
1351
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1352
+ minVersion: "17.0.0",
1353
+ version: "22.2.2",
1354
+ type: DependencyViewerComponent,
1355
+ isStandalone: true,
1356
+ selector: "lc-dependency-viewer",
1357
+ inputs: {
1358
+ root: {
1359
+ classPropertyName: "root",
1360
+ publicName: "root",
1361
+ isSignal: true,
1362
+ isRequired: true,
1363
+ transformFunction: null
1364
+ },
1365
+ direction: {
1366
+ classPropertyName: "direction",
1367
+ publicName: "direction",
1368
+ isSignal: true,
1369
+ isRequired: false,
1370
+ transformFunction: null
1371
+ },
1372
+ height: {
1373
+ classPropertyName: "height",
1374
+ publicName: "height",
1375
+ isSignal: true,
1376
+ isRequired: false,
1377
+ transformFunction: null
1378
+ },
1379
+ layout: {
1380
+ classPropertyName: "layout",
1381
+ publicName: "layout",
1382
+ isSignal: true,
1383
+ isRequired: false,
1384
+ transformFunction: null
1385
+ },
1386
+ showToolbar: {
1387
+ classPropertyName: "showToolbar",
1388
+ publicName: "showToolbar",
1389
+ isSignal: true,
1390
+ isRequired: false,
1391
+ transformFunction: null
1392
+ },
1393
+ showEdgeLabels: {
1394
+ classPropertyName: "showEdgeLabels",
1395
+ publicName: "showEdgeLabels",
1396
+ isSignal: true,
1397
+ isRequired: false,
1398
+ transformFunction: null
1399
+ },
1400
+ edgeWidth: {
1401
+ classPropertyName: "edgeWidth",
1402
+ publicName: "edgeWidth",
1403
+ isSignal: true,
1404
+ isRequired: false,
1405
+ transformFunction: null
1406
+ },
1407
+ autoFit: {
1408
+ classPropertyName: "autoFit",
1409
+ publicName: "autoFit",
1410
+ isSignal: true,
1411
+ isRequired: false,
1412
+ transformFunction: null
1413
+ },
1414
+ fitMode: {
1415
+ classPropertyName: "fitMode",
1416
+ publicName: "fitMode",
1417
+ isSignal: true,
1418
+ isRequired: false,
1419
+ transformFunction: null
1420
+ },
1421
+ minNodeSize: {
1422
+ classPropertyName: "minNodeSize",
1423
+ publicName: "minNodeSize",
1424
+ isSignal: true,
1425
+ isRequired: false,
1426
+ transformFunction: null
1427
+ },
1428
+ interactive: {
1429
+ classPropertyName: "interactive",
1430
+ publicName: "interactive",
1431
+ isSignal: true,
1432
+ isRequired: false,
1433
+ transformFunction: null
1434
+ },
1435
+ anchorNodeId: {
1436
+ classPropertyName: "anchorNodeId",
1437
+ publicName: "anchorNodeId",
1438
+ isSignal: true,
1439
+ isRequired: false,
1440
+ transformFunction: null
1441
+ },
1442
+ typeColors: {
1443
+ classPropertyName: "typeColors",
1444
+ publicName: "typeColors",
1445
+ isSignal: true,
1446
+ isRequired: false,
1447
+ transformFunction: null
1448
+ },
1449
+ hiddenRelations: {
1450
+ classPropertyName: "hiddenRelations",
1451
+ publicName: "hiddenRelations",
1452
+ isSignal: true,
1453
+ isRequired: false,
1454
+ transformFunction: null
1455
+ },
1456
+ hiddenTypes: {
1457
+ classPropertyName: "hiddenTypes",
1458
+ publicName: "hiddenTypes",
1459
+ isSignal: true,
1460
+ isRequired: false,
1461
+ transformFunction: null
1462
+ },
1463
+ zoomInLabel: {
1464
+ classPropertyName: "zoomInLabel",
1465
+ publicName: "zoomInLabel",
1466
+ isSignal: true,
1467
+ isRequired: false,
1468
+ transformFunction: null
1469
+ },
1470
+ zoomOutLabel: {
1471
+ classPropertyName: "zoomOutLabel",
1472
+ publicName: "zoomOutLabel",
1473
+ isSignal: true,
1474
+ isRequired: false,
1475
+ transformFunction: null
1476
+ },
1477
+ resetZoomLabel: {
1478
+ classPropertyName: "resetZoomLabel",
1479
+ publicName: "resetZoomLabel",
1480
+ isSignal: true,
1481
+ isRequired: false,
1482
+ transformFunction: null
1483
+ },
1484
+ depthLabel: {
1485
+ classPropertyName: "depthLabel",
1486
+ publicName: "depthLabel",
1487
+ isSignal: true,
1488
+ isRequired: false,
1489
+ transformFunction: null
1490
+ },
1491
+ childrenLabel: {
1492
+ classPropertyName: "childrenLabel",
1493
+ publicName: "childrenLabel",
1494
+ isSignal: true,
1495
+ isRequired: false,
1496
+ transformFunction: null
1497
+ },
1498
+ dependsOnLabel: {
1499
+ classPropertyName: "dependsOnLabel",
1500
+ publicName: "dependsOnLabel",
1501
+ isSignal: true,
1502
+ isRequired: false,
1503
+ transformFunction: null
1504
+ },
1505
+ dependenciesLabel: {
1506
+ classPropertyName: "dependenciesLabel",
1507
+ publicName: "dependenciesLabel",
1508
+ isSignal: true,
1509
+ isRequired: false,
1510
+ transformFunction: null
1511
+ }
1512
+ },
1513
+ outputs: {
1514
+ nodeSelect: "nodeSelect",
1515
+ nodeExpand: "nodeExpand"
1516
+ },
1517
+ host: {
1518
+ listeners: {
1519
+ "document:mousemove": "onMouseMove($event)",
1520
+ "document:mouseup": "onMouseUp()"
1521
+ },
1522
+ properties: {
1523
+ "class": "\"dep-viewer\"",
1524
+ "style.height": "hostHeight()"
1525
+ }
1526
+ },
1527
+ viewQueries: [{
1528
+ propertyName: "canvasRef",
1529
+ first: true,
1530
+ predicate: ["canvas"],
1531
+ descendants: true,
1532
+ isSignal: true
1533
+ }],
1534
+ ngImport: i0,
1535
+ template: "<!-- Toolbar. The zoom cluster is navigation, so it goes with `interactive`; the\n direction indicator is a read-out and stays. -->\n@if (showToolbar()) {\n <div class=\"dep-viewer__toolbar\">\n @if (interactive()) {\n <button class=\"dep-viewer__btn\" (click)=\"zoomIn()\" [attr.title]=\"zoomInLabel()\" [attr.aria-label]=\"zoomInLabel()\">+</button>\n <span class=\"dep-viewer__zoom\">{{ zoomLabel() }}%</span>\n <button class=\"dep-viewer__btn\" (click)=\"zoomOut()\" [attr.title]=\"zoomOutLabel()\" [attr.aria-label]=\"zoomOutLabel()\">−</button>\n <button class=\"dep-viewer__btn dep-viewer__btn--reset\" (click)=\"resetZoom()\" [attr.title]=\"resetZoomLabel()\" [attr.aria-label]=\"resetZoomLabel()\">⟲</button>\n }\n <span class=\"dep-viewer__direction-label\">{{ direction() === 'horizontal' ? '→' : '↓' }}</span>\n </div>\n}\n\n<!-- Canvas -->\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- background click clears the pointer selection; node selection is pointer-only in this component (known gap) -->\n<div\n #canvas\n class=\"dep-viewer__canvas\"\n [class.dep-viewer__canvas--static]=\"!interactive()\"\n [class.dep-viewer__canvas--sized]=\"contentHeight() !== null\"\n [style.height.px]=\"contentHeight()\"\n (mousedown)=\"onMouseDown($event)\"\n (wheel)=\"onWheel($event)\"\n (click)=\"deselectNode()\"\n>\n <svg\n [attr.width]=\"svgWidth()\"\n [attr.height]=\"svgHeight()\"\n [attr.viewBox]=\"viewBox()\"\n [style.transform]=\"transform()\"\n class=\"dep-viewer__svg\"\n >\n <!-- Arrow markers for cross-reference edges -->\n <defs>\n <marker id=\"arrow-default\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-neutral-400)\"/></marker>\n <marker id=\"arrow-blocks\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-error-default)\"/></marker>\n <marker id=\"arrow-references\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-info-default, #3b82f6)\"/></marker>\n <marker id=\"arrow-requires\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-warning-default)\"/></marker>\n <marker id=\"arrow-extends\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-primary-400)\"/></marker>\n <marker id=\"arrow-implements\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-success-default)\"/></marker>\n <marker id=\"arrow-uses\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-neutral-300)\"/></marker>\n <marker id=\"arrow-depends\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-neutral-400)\"/></marker>\n </defs>\n\n <!-- Edges. Their labels are deliberately NOT drawn here — see below. -->\n @for (edge of graph().edges; track edge.id) {\n <path\n [attr.d]=\"edge.path\"\n [attr.stroke]=\"edge.color\"\n [attr.stroke-width]=\"edgeWidth()\"\n [attr.stroke-dasharray]=\"edge.dashed ? '6 3' : 'none'\"\n [attr.marker-end]=\"edge.arrow ? 'url(#arrow-' + edge.marker + ')' : ''\"\n fill=\"none\"\n class=\"dep-viewer__edge\"\n [class.dep-viewer__edge--cross-ref]=\"edge.isCrossRef\"\n />\n }\n\n <!-- Nodes -->\n @for (node of graph().nodes; track node.id) {\n <g\n class=\"dep-viewer__node\"\n [class.dep-viewer__node--selected]=\"selectedNodeId() === node.id\"\n (click)=\"selectNode(node.id, $event)\"\n (dblclick)=\"expandNode(node.id, $event)\"\n >\n <!-- A label the box couldn't hold in full is offered whole as a tooltip. -->\n @if (node.truncated) {\n <title>{{ node.label }}</title>\n }\n <!-- Opaque backdrop. The status fills are translucent tints (in the dark\n theme --color-success-50 & co. resolve to rgba(…, 0.18)), so without\n something solid beneath them the edges routed under a node show\n straight through it. This keeps the tint compositing against the\n viewer's own surface instead of against whatever passes behind. -->\n <rect\n [attr.x]=\"node.x\"\n [attr.y]=\"node.y\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n rx=\"6\" ry=\"6\"\n class=\"dep-viewer__node-backdrop\"\n />\n <rect\n class=\"dep-viewer__node-fill\"\n [attr.x]=\"node.x\"\n [attr.y]=\"node.y\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n rx=\"6\" ry=\"6\"\n [attr.fill]=\"getNodeBg(node)\"\n [attr.stroke]=\"selectedNodeId() === node.id ? 'var(--color-primary-500)' : getNodeBorder(node)\"\n stroke-width=\"1.5\"\n />\n <!-- One <tspan> per wrapped line, each restarting at the box's centre; the\n block of lines is centred on the box vertically. No whitespace between\n the spans — it would end up in the text. -->\n <text\n [attr.x]=\"node.x + node.width / 2\"\n [attr.y]=\"node.y + node.height / 2 + baselineShift - ((node.lines.length - 1) * lineHeight) / 2\"\n text-anchor=\"middle\"\n [attr.fill]=\"getNodeText(node)\"\n class=\"dep-viewer__node-label\"\n >@for (line of node.lines; track $index) {<tspan [attr.x]=\"node.x + node.width / 2\" [attr.dy]=\"$first ? 0 : lineHeight\">{{ line }}</tspan>}</text>\n\n <!-- \"+N\" marker: this node has more neighbours than are shown -->\n @if (node.moreCount) {\n <g class=\"dep-viewer__more\">\n <rect\n [attr.x]=\"node.x + node.width - 26\"\n [attr.y]=\"node.y - 8\"\n width=\"32\" height=\"16\" rx=\"8\" ry=\"8\"\n />\n <text\n [attr.x]=\"node.x + node.width - 10\"\n [attr.y]=\"node.y + 3\"\n text-anchor=\"middle\"\n >+{{ node.moreCount }}</text>\n </g>\n }\n\n <!-- Collapse/expand toggle -->\n @if (hasChildren(node.id)) {\n <g\n class=\"dep-viewer__toggle\"\n (click)=\"toggleCollapse(node.id, $event)\"\n >\n @if (direction() === 'horizontal') {\n <circle\n [attr.cx]=\"node.x + node.width + 10\"\n [attr.cy]=\"node.y + node.height / 2\"\n r=\"8\"\n fill=\"var(--color-neutral-100)\" stroke=\"var(--color-neutral-300)\" stroke-width=\"1\"\n />\n <text\n [attr.x]=\"node.x + node.width + 10\"\n [attr.y]=\"node.y + node.height / 2 + 4\"\n text-anchor=\"middle\"\n class=\"dep-viewer__toggle-text\"\n >{{ isCollapsed(node.id) ? '+' : '−' }}</text>\n } @else {\n <circle\n [attr.cx]=\"node.x + node.width / 2\"\n [attr.cy]=\"node.y + node.height + 10\"\n r=\"8\"\n fill=\"var(--color-neutral-100)\" stroke=\"var(--color-neutral-300)\" stroke-width=\"1\"\n />\n <text\n [attr.x]=\"node.x + node.width / 2\"\n [attr.y]=\"node.y + node.height + 14\"\n text-anchor=\"middle\"\n class=\"dep-viewer__toggle-text\"\n >{{ isCollapsed(node.id) ? '+' : '−' }}</text>\n }\n </g>\n }\n </g>\n }\n\n <!-- Edge labels last: SVG paints in document order, so anything drawn before\n the nodes is covered by them. A label sits at the midpoint of its edge,\n which frequently lands on a node — it has to come after. The halo (see\n the stylesheet) keeps it legible over whatever it lands on. -->\n @if (showEdgeLabels()) {\n @for (edge of graph().edges; track edge.id) {\n @if (edge.label) {\n <text\n [attr.x]=\"edge.labelX\"\n [attr.y]=\"edge.labelY\"\n class=\"dep-viewer__edge-label\"\n [attr.fill]=\"edge.color\"\n [attr.text-anchor]=\"edge.labelAnchor ?? 'middle'\"\n >{{ edge.label }}</text>\n }\n }\n }\n </svg>\n</div>\n\n<!-- Legend -->\n@if (legendItems().length || typeLegendItems().length) {\n <div class=\"dep-viewer__legend\">\n @for (item of legendItems(); track item.label) {\n <span class=\"dep-viewer__legend-item\">\n <svg width=\"24\" height=\"10\">\n <line\n x1=\"0\" y1=\"5\" x2=\"24\" y2=\"5\"\n [attr.stroke]=\"item.color\"\n stroke-width=\"2\"\n [attr.stroke-dasharray]=\"item.dashed ? '4 2' : 'none'\"\n />\n </svg>\n <span class=\"dep-viewer__legend-text\">{{ item.label }}</span>\n </span>\n }\n @for (item of typeLegendItems(); track item.type) {\n <span class=\"dep-viewer__legend-item\">\n <svg width=\"10\" height=\"10\">\n <rect width=\"10\" height=\"10\" rx=\"2\" ry=\"2\" [attr.fill]=\"item.color\" />\n </svg>\n <span class=\"dep-viewer__legend-text\">{{ item.type }}</span>\n </span>\n }\n </div>\n}\n\n<!-- Detail panel -->\n@if (selectedNode(); as node) {\n <div class=\"dep-viewer__detail\">\n <div class=\"dep-viewer__detail-header\">\n <span class=\"dep-viewer__detail-status dep-viewer__detail-status--{{ node.status }}\">●</span>\n <strong>{{ node.label }}</strong>\n @if (node.type) {\n <span class=\"dep-viewer__detail-type\">{{ node.type }}</span>\n }\n </div>\n @if (node.description) {\n <p class=\"dep-viewer__detail-desc\">{{ node.description }}</p>\n }\n <div class=\"dep-viewer__detail-meta\">\n <span>{{ depthLabel() }} {{ node.depth }}</span>\n <span>{{ childrenLabel() }} {{ node.outgoingCount }}</span>\n <span>{{ dependsOnLabel() }} {{ node.incomingCount }}</span>\n </div>\n @if (selectedDependsOn().length) {\n <div class=\"dep-viewer__detail-deps\">\n <strong>{{ dependenciesLabel() }}</strong>\n <ul>\n @for (dep of selectedDependsOn(); track dep.id) {\n <li>\n <span class=\"dep-viewer__dep-relation\">{{\n dep.relationLabel || getRelationLabel(dep.relation || 'depends')\n }}</span>\n → {{ dep.id }}\n </li>\n }\n </ul>\n </div>\n }\n </div>\n}\n",
1536
+ styles: [":host{display:flex;flex-direction:column;position:relative;overflow:hidden;border:1px solid var(--color-border);border-radius:8px;background:var(--color-surface)}.dep-viewer__toolbar{display:flex;align-items:center;gap:4px;padding:8px 12px;border-bottom:1px solid var(--color-border);background:var(--color-surface-2);-webkit-user-select:none;user-select:none}.dep-viewer__btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--color-border);border-radius:4px;background:var(--color-surface);color:var(--color-text-secondary);cursor:pointer;font-size:14px;line-height:1}.dep-viewer__btn:hover{background:var(--color-surface-hover)}.dep-viewer__btn--reset{margin-left:4px}.dep-viewer__zoom{font-size:12px;min-width:40px;text-align:center;color:var(--color-text-secondary)}.dep-viewer__direction-label{margin-left:8px;font-size:14px;color:var(--color-text-tertiary)}.dep-viewer__canvas{cursor:grab;overflow:hidden;width:100%;flex:1 1 auto;min-height:0}.dep-viewer__canvas:active{cursor:grabbing}.dep-viewer__canvas--static,.dep-viewer__canvas--static:active{cursor:default}.dep-viewer__canvas--sized{flex:0 0 auto}.dep-viewer__svg{transform-origin:0 0;transition:transform .1s ease-out;overflow:visible}.dep-viewer__edge{pointer-events:none;transition:opacity .15s}.dep-viewer__edge--cross-ref{opacity:.8}.dep-viewer__edge-label{font-size:9px;font-weight:500;pointer-events:none;-webkit-user-select:none;user-select:none;dominant-baseline:central;paint-order:stroke;stroke:var(--color-surface);stroke-width:3px;stroke-linejoin:round}.dep-viewer__node{cursor:pointer;transition:filter .15s}.dep-viewer__node:hover{filter:brightness(.96)}.dep-viewer__node--selected rect{stroke-width:2.5}.dep-viewer__node-backdrop{fill:var(--color-surface)}.dep-viewer__node-label{font-size:12px;font-weight:500;pointer-events:none;-webkit-user-select:none;user-select:none}.dep-viewer__toggle{cursor:pointer}.dep-viewer__toggle:hover circle{fill:var(--color-surface-hover)}.dep-viewer__more{pointer-events:none}.dep-viewer__more rect{fill:var(--color-surface-2);stroke:var(--color-border-strong);stroke-width:1}.dep-viewer__more text{font-size:9px;font-weight:600;fill:var(--color-text-secondary);-webkit-user-select:none;user-select:none}.dep-viewer__toggle-text{font-size:11px;font-weight:600;fill:var(--color-text-secondary);pointer-events:none;-webkit-user-select:none;user-select:none}.dep-viewer__legend{display:flex;flex-wrap:wrap;gap:12px;padding:6px 12px;border-top:1px solid var(--color-border);background:var(--color-surface-2)}.dep-viewer__legend-item{display:flex;align-items:center;gap:4px}.dep-viewer__legend-text{font-size:11px;color:var(--color-text-secondary)}.dep-viewer__detail{position:absolute;bottom:12px;right:12px;width:240px;padding:12px;background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:8px;box-shadow:var(--elevation-1);font-size:12px;z-index:10}.dep-viewer__detail-header{display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:13px}.dep-viewer__detail-type{margin-left:auto;padding:1px 6px;border-radius:3px;background:var(--color-surface-hover);color:var(--color-text-secondary);font-size:10px;font-weight:500}.dep-viewer__detail-status{font-size:10px}.dep-viewer__detail-status--default{color:var(--color-text-tertiary)}.dep-viewer__detail-status--active{color:var(--color-primary-400)}.dep-viewer__detail-status--success{color:var(--color-success-default)}.dep-viewer__detail-status--warning{color:var(--color-warning-default)}.dep-viewer__detail-status--error{color:var(--color-error-default)}.dep-viewer__detail-status--muted{color:var(--color-text-disabled)}.dep-viewer__detail-desc{color:var(--color-text-secondary);margin:0 0 6px;line-height:1.4}.dep-viewer__detail-meta{display:flex;flex-wrap:wrap;gap:8px;color:var(--color-text-tertiary);font-size:11px}.dep-viewer__detail-deps{margin-top:8px;padding-top:8px;border-top:1px solid var(--color-border)}.dep-viewer__detail-deps ul{list-style:none;margin:4px 0 0;padding:0}.dep-viewer__detail-deps li{padding:2px 0;color:var(--color-text-secondary)}.dep-viewer__dep-relation{display:inline-block;padding:1px 4px;background:var(--color-surface-hover);border-radius:3px;font-size:10px;font-weight:500;color:var(--color-text-secondary)}\n"],
1537
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
1538
+ });
1539
+ };
1540
+ i0.ɵɵngDeclareClassMetadata({
1541
+ minVersion: "12.0.0",
1542
+ version: "22.2.2",
1543
+ ngImport: i0,
1544
+ type: DependencyViewerComponent,
1545
+ decorators: [{
1546
+ type: Component,
1547
+ args: [{
1548
+ selector: "lc-dependency-viewer",
1549
+ standalone: true,
1550
+ changeDetection: ChangeDetectionStrategy.OnPush,
1551
+ host: {
1552
+ "[class]": "\"dep-viewer\"",
1553
+ "[style.height]": "hostHeight()"
1554
+ },
1555
+ template: "<!-- Toolbar. The zoom cluster is navigation, so it goes with `interactive`; the\n direction indicator is a read-out and stays. -->\n@if (showToolbar()) {\n <div class=\"dep-viewer__toolbar\">\n @if (interactive()) {\n <button class=\"dep-viewer__btn\" (click)=\"zoomIn()\" [attr.title]=\"zoomInLabel()\" [attr.aria-label]=\"zoomInLabel()\">+</button>\n <span class=\"dep-viewer__zoom\">{{ zoomLabel() }}%</span>\n <button class=\"dep-viewer__btn\" (click)=\"zoomOut()\" [attr.title]=\"zoomOutLabel()\" [attr.aria-label]=\"zoomOutLabel()\">−</button>\n <button class=\"dep-viewer__btn dep-viewer__btn--reset\" (click)=\"resetZoom()\" [attr.title]=\"resetZoomLabel()\" [attr.aria-label]=\"resetZoomLabel()\">⟲</button>\n }\n <span class=\"dep-viewer__direction-label\">{{ direction() === 'horizontal' ? '→' : '↓' }}</span>\n </div>\n}\n\n<!-- Canvas -->\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- background click clears the pointer selection; node selection is pointer-only in this component (known gap) -->\n<div\n #canvas\n class=\"dep-viewer__canvas\"\n [class.dep-viewer__canvas--static]=\"!interactive()\"\n [class.dep-viewer__canvas--sized]=\"contentHeight() !== null\"\n [style.height.px]=\"contentHeight()\"\n (mousedown)=\"onMouseDown($event)\"\n (wheel)=\"onWheel($event)\"\n (click)=\"deselectNode()\"\n>\n <svg\n [attr.width]=\"svgWidth()\"\n [attr.height]=\"svgHeight()\"\n [attr.viewBox]=\"viewBox()\"\n [style.transform]=\"transform()\"\n class=\"dep-viewer__svg\"\n >\n <!-- Arrow markers for cross-reference edges -->\n <defs>\n <marker id=\"arrow-default\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-neutral-400)\"/></marker>\n <marker id=\"arrow-blocks\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-error-default)\"/></marker>\n <marker id=\"arrow-references\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-info-default, #3b82f6)\"/></marker>\n <marker id=\"arrow-requires\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-warning-default)\"/></marker>\n <marker id=\"arrow-extends\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-primary-400)\"/></marker>\n <marker id=\"arrow-implements\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-success-default)\"/></marker>\n <marker id=\"arrow-uses\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-neutral-300)\"/></marker>\n <marker id=\"arrow-depends\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6 Z\" fill=\"var(--color-neutral-400)\"/></marker>\n </defs>\n\n <!-- Edges. Their labels are deliberately NOT drawn here — see below. -->\n @for (edge of graph().edges; track edge.id) {\n <path\n [attr.d]=\"edge.path\"\n [attr.stroke]=\"edge.color\"\n [attr.stroke-width]=\"edgeWidth()\"\n [attr.stroke-dasharray]=\"edge.dashed ? '6 3' : 'none'\"\n [attr.marker-end]=\"edge.arrow ? 'url(#arrow-' + edge.marker + ')' : ''\"\n fill=\"none\"\n class=\"dep-viewer__edge\"\n [class.dep-viewer__edge--cross-ref]=\"edge.isCrossRef\"\n />\n }\n\n <!-- Nodes -->\n @for (node of graph().nodes; track node.id) {\n <g\n class=\"dep-viewer__node\"\n [class.dep-viewer__node--selected]=\"selectedNodeId() === node.id\"\n (click)=\"selectNode(node.id, $event)\"\n (dblclick)=\"expandNode(node.id, $event)\"\n >\n <!-- A label the box couldn't hold in full is offered whole as a tooltip. -->\n @if (node.truncated) {\n <title>{{ node.label }}</title>\n }\n <!-- Opaque backdrop. The status fills are translucent tints (in the dark\n theme --color-success-50 & co. resolve to rgba(…, 0.18)), so without\n something solid beneath them the edges routed under a node show\n straight through it. This keeps the tint compositing against the\n viewer's own surface instead of against whatever passes behind. -->\n <rect\n [attr.x]=\"node.x\"\n [attr.y]=\"node.y\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n rx=\"6\" ry=\"6\"\n class=\"dep-viewer__node-backdrop\"\n />\n <rect\n class=\"dep-viewer__node-fill\"\n [attr.x]=\"node.x\"\n [attr.y]=\"node.y\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n rx=\"6\" ry=\"6\"\n [attr.fill]=\"getNodeBg(node)\"\n [attr.stroke]=\"selectedNodeId() === node.id ? 'var(--color-primary-500)' : getNodeBorder(node)\"\n stroke-width=\"1.5\"\n />\n <!-- One <tspan> per wrapped line, each restarting at the box's centre; the\n block of lines is centred on the box vertically. No whitespace between\n the spans — it would end up in the text. -->\n <text\n [attr.x]=\"node.x + node.width / 2\"\n [attr.y]=\"node.y + node.height / 2 + baselineShift - ((node.lines.length - 1) * lineHeight) / 2\"\n text-anchor=\"middle\"\n [attr.fill]=\"getNodeText(node)\"\n class=\"dep-viewer__node-label\"\n >@for (line of node.lines; track $index) {<tspan [attr.x]=\"node.x + node.width / 2\" [attr.dy]=\"$first ? 0 : lineHeight\">{{ line }}</tspan>}</text>\n\n <!-- \"+N\" marker: this node has more neighbours than are shown -->\n @if (node.moreCount) {\n <g class=\"dep-viewer__more\">\n <rect\n [attr.x]=\"node.x + node.width - 26\"\n [attr.y]=\"node.y - 8\"\n width=\"32\" height=\"16\" rx=\"8\" ry=\"8\"\n />\n <text\n [attr.x]=\"node.x + node.width - 10\"\n [attr.y]=\"node.y + 3\"\n text-anchor=\"middle\"\n >+{{ node.moreCount }}</text>\n </g>\n }\n\n <!-- Collapse/expand toggle -->\n @if (hasChildren(node.id)) {\n <g\n class=\"dep-viewer__toggle\"\n (click)=\"toggleCollapse(node.id, $event)\"\n >\n @if (direction() === 'horizontal') {\n <circle\n [attr.cx]=\"node.x + node.width + 10\"\n [attr.cy]=\"node.y + node.height / 2\"\n r=\"8\"\n fill=\"var(--color-neutral-100)\" stroke=\"var(--color-neutral-300)\" stroke-width=\"1\"\n />\n <text\n [attr.x]=\"node.x + node.width + 10\"\n [attr.y]=\"node.y + node.height / 2 + 4\"\n text-anchor=\"middle\"\n class=\"dep-viewer__toggle-text\"\n >{{ isCollapsed(node.id) ? '+' : '−' }}</text>\n } @else {\n <circle\n [attr.cx]=\"node.x + node.width / 2\"\n [attr.cy]=\"node.y + node.height + 10\"\n r=\"8\"\n fill=\"var(--color-neutral-100)\" stroke=\"var(--color-neutral-300)\" stroke-width=\"1\"\n />\n <text\n [attr.x]=\"node.x + node.width / 2\"\n [attr.y]=\"node.y + node.height + 14\"\n text-anchor=\"middle\"\n class=\"dep-viewer__toggle-text\"\n >{{ isCollapsed(node.id) ? '+' : '−' }}</text>\n }\n </g>\n }\n </g>\n }\n\n <!-- Edge labels last: SVG paints in document order, so anything drawn before\n the nodes is covered by them. A label sits at the midpoint of its edge,\n which frequently lands on a node — it has to come after. The halo (see\n the stylesheet) keeps it legible over whatever it lands on. -->\n @if (showEdgeLabels()) {\n @for (edge of graph().edges; track edge.id) {\n @if (edge.label) {\n <text\n [attr.x]=\"edge.labelX\"\n [attr.y]=\"edge.labelY\"\n class=\"dep-viewer__edge-label\"\n [attr.fill]=\"edge.color\"\n [attr.text-anchor]=\"edge.labelAnchor ?? 'middle'\"\n >{{ edge.label }}</text>\n }\n }\n }\n </svg>\n</div>\n\n<!-- Legend -->\n@if (legendItems().length || typeLegendItems().length) {\n <div class=\"dep-viewer__legend\">\n @for (item of legendItems(); track item.label) {\n <span class=\"dep-viewer__legend-item\">\n <svg width=\"24\" height=\"10\">\n <line\n x1=\"0\" y1=\"5\" x2=\"24\" y2=\"5\"\n [attr.stroke]=\"item.color\"\n stroke-width=\"2\"\n [attr.stroke-dasharray]=\"item.dashed ? '4 2' : 'none'\"\n />\n </svg>\n <span class=\"dep-viewer__legend-text\">{{ item.label }}</span>\n </span>\n }\n @for (item of typeLegendItems(); track item.type) {\n <span class=\"dep-viewer__legend-item\">\n <svg width=\"10\" height=\"10\">\n <rect width=\"10\" height=\"10\" rx=\"2\" ry=\"2\" [attr.fill]=\"item.color\" />\n </svg>\n <span class=\"dep-viewer__legend-text\">{{ item.type }}</span>\n </span>\n }\n </div>\n}\n\n<!-- Detail panel -->\n@if (selectedNode(); as node) {\n <div class=\"dep-viewer__detail\">\n <div class=\"dep-viewer__detail-header\">\n <span class=\"dep-viewer__detail-status dep-viewer__detail-status--{{ node.status }}\">●</span>\n <strong>{{ node.label }}</strong>\n @if (node.type) {\n <span class=\"dep-viewer__detail-type\">{{ node.type }}</span>\n }\n </div>\n @if (node.description) {\n <p class=\"dep-viewer__detail-desc\">{{ node.description }}</p>\n }\n <div class=\"dep-viewer__detail-meta\">\n <span>{{ depthLabel() }} {{ node.depth }}</span>\n <span>{{ childrenLabel() }} {{ node.outgoingCount }}</span>\n <span>{{ dependsOnLabel() }} {{ node.incomingCount }}</span>\n </div>\n @if (selectedDependsOn().length) {\n <div class=\"dep-viewer__detail-deps\">\n <strong>{{ dependenciesLabel() }}</strong>\n <ul>\n @for (dep of selectedDependsOn(); track dep.id) {\n <li>\n <span class=\"dep-viewer__dep-relation\">{{\n dep.relationLabel || getRelationLabel(dep.relation || 'depends')\n }}</span>\n → {{ dep.id }}\n </li>\n }\n </ul>\n </div>\n }\n </div>\n}\n",
1556
+ styles: [":host{display:flex;flex-direction:column;position:relative;overflow:hidden;border:1px solid var(--color-border);border-radius:8px;background:var(--color-surface)}.dep-viewer__toolbar{display:flex;align-items:center;gap:4px;padding:8px 12px;border-bottom:1px solid var(--color-border);background:var(--color-surface-2);-webkit-user-select:none;user-select:none}.dep-viewer__btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--color-border);border-radius:4px;background:var(--color-surface);color:var(--color-text-secondary);cursor:pointer;font-size:14px;line-height:1}.dep-viewer__btn:hover{background:var(--color-surface-hover)}.dep-viewer__btn--reset{margin-left:4px}.dep-viewer__zoom{font-size:12px;min-width:40px;text-align:center;color:var(--color-text-secondary)}.dep-viewer__direction-label{margin-left:8px;font-size:14px;color:var(--color-text-tertiary)}.dep-viewer__canvas{cursor:grab;overflow:hidden;width:100%;flex:1 1 auto;min-height:0}.dep-viewer__canvas:active{cursor:grabbing}.dep-viewer__canvas--static,.dep-viewer__canvas--static:active{cursor:default}.dep-viewer__canvas--sized{flex:0 0 auto}.dep-viewer__svg{transform-origin:0 0;transition:transform .1s ease-out;overflow:visible}.dep-viewer__edge{pointer-events:none;transition:opacity .15s}.dep-viewer__edge--cross-ref{opacity:.8}.dep-viewer__edge-label{font-size:9px;font-weight:500;pointer-events:none;-webkit-user-select:none;user-select:none;dominant-baseline:central;paint-order:stroke;stroke:var(--color-surface);stroke-width:3px;stroke-linejoin:round}.dep-viewer__node{cursor:pointer;transition:filter .15s}.dep-viewer__node:hover{filter:brightness(.96)}.dep-viewer__node--selected rect{stroke-width:2.5}.dep-viewer__node-backdrop{fill:var(--color-surface)}.dep-viewer__node-label{font-size:12px;font-weight:500;pointer-events:none;-webkit-user-select:none;user-select:none}.dep-viewer__toggle{cursor:pointer}.dep-viewer__toggle:hover circle{fill:var(--color-surface-hover)}.dep-viewer__more{pointer-events:none}.dep-viewer__more rect{fill:var(--color-surface-2);stroke:var(--color-border-strong);stroke-width:1}.dep-viewer__more text{font-size:9px;font-weight:600;fill:var(--color-text-secondary);-webkit-user-select:none;user-select:none}.dep-viewer__toggle-text{font-size:11px;font-weight:600;fill:var(--color-text-secondary);pointer-events:none;-webkit-user-select:none;user-select:none}.dep-viewer__legend{display:flex;flex-wrap:wrap;gap:12px;padding:6px 12px;border-top:1px solid var(--color-border);background:var(--color-surface-2)}.dep-viewer__legend-item{display:flex;align-items:center;gap:4px}.dep-viewer__legend-text{font-size:11px;color:var(--color-text-secondary)}.dep-viewer__detail{position:absolute;bottom:12px;right:12px;width:240px;padding:12px;background:var(--color-surface-2);border:1px solid var(--color-border);border-radius:8px;box-shadow:var(--elevation-1);font-size:12px;z-index:10}.dep-viewer__detail-header{display:flex;align-items:center;gap:6px;margin-bottom:4px;font-size:13px}.dep-viewer__detail-type{margin-left:auto;padding:1px 6px;border-radius:3px;background:var(--color-surface-hover);color:var(--color-text-secondary);font-size:10px;font-weight:500}.dep-viewer__detail-status{font-size:10px}.dep-viewer__detail-status--default{color:var(--color-text-tertiary)}.dep-viewer__detail-status--active{color:var(--color-primary-400)}.dep-viewer__detail-status--success{color:var(--color-success-default)}.dep-viewer__detail-status--warning{color:var(--color-warning-default)}.dep-viewer__detail-status--error{color:var(--color-error-default)}.dep-viewer__detail-status--muted{color:var(--color-text-disabled)}.dep-viewer__detail-desc{color:var(--color-text-secondary);margin:0 0 6px;line-height:1.4}.dep-viewer__detail-meta{display:flex;flex-wrap:wrap;gap:8px;color:var(--color-text-tertiary);font-size:11px}.dep-viewer__detail-deps{margin-top:8px;padding-top:8px;border-top:1px solid var(--color-border)}.dep-viewer__detail-deps ul{list-style:none;margin:4px 0 0;padding:0}.dep-viewer__detail-deps li{padding:2px 0;color:var(--color-text-secondary)}.dep-viewer__dep-relation{display:inline-block;padding:1px 4px;background:var(--color-surface-hover);border-radius:3px;font-size:10px;font-weight:500;color:var(--color-text-secondary)}\n"]
1557
+ }]
1558
+ }],
1559
+ ctorParameters: () => [],
1560
+ propDecorators: {
1561
+ root: [{
1562
+ type: i0.Input,
1563
+ args: [{
1564
+ isSignal: true,
1565
+ alias: "root",
1566
+ required: true
1567
+ }]
1568
+ }],
1569
+ direction: [{
1570
+ type: i0.Input,
1571
+ args: [{
1572
+ isSignal: true,
1573
+ alias: "direction",
1574
+ required: false
1575
+ }]
1576
+ }],
1577
+ height: [{
1578
+ type: i0.Input,
1579
+ args: [{
1580
+ isSignal: true,
1581
+ alias: "height",
1582
+ required: false
1583
+ }]
1584
+ }],
1585
+ layout: [{
1586
+ type: i0.Input,
1587
+ args: [{
1588
+ isSignal: true,
1589
+ alias: "layout",
1590
+ required: false
1591
+ }]
1592
+ }],
1593
+ showToolbar: [{
1594
+ type: i0.Input,
1595
+ args: [{
1596
+ isSignal: true,
1597
+ alias: "showToolbar",
1598
+ required: false
1599
+ }]
1600
+ }],
1601
+ showEdgeLabels: [{
1602
+ type: i0.Input,
1603
+ args: [{
1604
+ isSignal: true,
1605
+ alias: "showEdgeLabels",
1606
+ required: false
1607
+ }]
1608
+ }],
1609
+ edgeWidth: [{
1610
+ type: i0.Input,
1611
+ args: [{
1612
+ isSignal: true,
1613
+ alias: "edgeWidth",
1614
+ required: false
1615
+ }]
1616
+ }],
1617
+ autoFit: [{
1618
+ type: i0.Input,
1619
+ args: [{
1620
+ isSignal: true,
1621
+ alias: "autoFit",
1622
+ required: false
1623
+ }]
1624
+ }],
1625
+ fitMode: [{
1626
+ type: i0.Input,
1627
+ args: [{
1628
+ isSignal: true,
1629
+ alias: "fitMode",
1630
+ required: false
1631
+ }]
1632
+ }],
1633
+ minNodeSize: [{
1634
+ type: i0.Input,
1635
+ args: [{
1636
+ isSignal: true,
1637
+ alias: "minNodeSize",
1638
+ required: false
1639
+ }]
1640
+ }],
1641
+ interactive: [{
1642
+ type: i0.Input,
1643
+ args: [{
1644
+ isSignal: true,
1645
+ alias: "interactive",
1646
+ required: false
1647
+ }]
1648
+ }],
1649
+ anchorNodeId: [{
1650
+ type: i0.Input,
1651
+ args: [{
1652
+ isSignal: true,
1653
+ alias: "anchorNodeId",
1654
+ required: false
1655
+ }]
1656
+ }],
1657
+ typeColors: [{
1658
+ type: i0.Input,
1659
+ args: [{
1660
+ isSignal: true,
1661
+ alias: "typeColors",
1662
+ required: false
1663
+ }]
1664
+ }],
1665
+ hiddenRelations: [{
1666
+ type: i0.Input,
1667
+ args: [{
1668
+ isSignal: true,
1669
+ alias: "hiddenRelations",
1670
+ required: false
1671
+ }]
1672
+ }],
1673
+ hiddenTypes: [{
1674
+ type: i0.Input,
1675
+ args: [{
1676
+ isSignal: true,
1677
+ alias: "hiddenTypes",
1678
+ required: false
1679
+ }]
1680
+ }],
1681
+ zoomInLabel: [{
1682
+ type: i0.Input,
1683
+ args: [{
1684
+ isSignal: true,
1685
+ alias: "zoomInLabel",
1686
+ required: false
1687
+ }]
1688
+ }],
1689
+ zoomOutLabel: [{
1690
+ type: i0.Input,
1691
+ args: [{
1692
+ isSignal: true,
1693
+ alias: "zoomOutLabel",
1694
+ required: false
1695
+ }]
1696
+ }],
1697
+ resetZoomLabel: [{
1698
+ type: i0.Input,
1699
+ args: [{
1700
+ isSignal: true,
1701
+ alias: "resetZoomLabel",
1702
+ required: false
1703
+ }]
1704
+ }],
1705
+ depthLabel: [{
1706
+ type: i0.Input,
1707
+ args: [{
1708
+ isSignal: true,
1709
+ alias: "depthLabel",
1710
+ required: false
1711
+ }]
1712
+ }],
1713
+ childrenLabel: [{
1714
+ type: i0.Input,
1715
+ args: [{
1716
+ isSignal: true,
1717
+ alias: "childrenLabel",
1718
+ required: false
1719
+ }]
1720
+ }],
1721
+ dependsOnLabel: [{
1722
+ type: i0.Input,
1723
+ args: [{
1724
+ isSignal: true,
1725
+ alias: "dependsOnLabel",
1726
+ required: false
1727
+ }]
1728
+ }],
1729
+ dependenciesLabel: [{
1730
+ type: i0.Input,
1731
+ args: [{
1732
+ isSignal: true,
1733
+ alias: "dependenciesLabel",
1734
+ required: false
1735
+ }]
1736
+ }],
1737
+ nodeSelect: [{
1738
+ type: i0.Output,
1739
+ args: ["nodeSelect"]
1740
+ }],
1741
+ nodeExpand: [{
1742
+ type: i0.Output,
1743
+ args: ["nodeExpand"]
1744
+ }],
1745
+ canvasRef: [{
1746
+ type: i0.ViewChild,
1747
+ args: ["canvas", { isSignal: true }]
1748
+ }],
1749
+ onMouseMove: [{
1750
+ type: HostListener,
1751
+ args: ["document:mousemove", ["$event"]]
1752
+ }],
1753
+ onMouseUp: [{
1754
+ type: HostListener,
1755
+ args: ["document:mouseup"]
1756
+ }]
1757
+ }
1758
+ });
1759
+ export { DependencyViewerComponent };
1760
+
1761
+ //# sourceMappingURL=lifecorner-angular-ui-kit-dependency-viewer.mjs.map