@caribeng/ui 22.2.0 → 22.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 (285) hide show
  1. package/README.md +311 -231
  2. package/fesm2022/caribeng-ui-accordion.mjs +2 -2
  3. package/fesm2022/caribeng-ui-account-picker.mjs +533 -0
  4. package/fesm2022/caribeng-ui-aging.mjs +488 -0
  5. package/fesm2022/{caribeng-ui-caribe-alert.mjs → caribeng-ui-alert.mjs} +45 -45
  6. package/fesm2022/caribeng-ui-amount.mjs +249 -0
  7. package/fesm2022/caribeng-ui-anchor.mjs +2 -2
  8. package/fesm2022/{caribeng-ui-caribe-animation-lottie.mjs → caribeng-ui-animation-lottie.mjs} +41 -41
  9. package/fesm2022/caribeng-ui-audit-log.mjs +323 -0
  10. package/fesm2022/caribeng-ui-avatar.mjs +4 -4
  11. package/fesm2022/caribeng-ui-badge.mjs +8 -2
  12. package/fesm2022/caribeng-ui-breadcrumb.mjs +26 -9
  13. package/fesm2022/{caribeng-ui-caribe-button-group.mjs → caribeng-ui-button-group.mjs} +15 -15
  14. package/fesm2022/caribeng-ui-button.mjs +2 -2
  15. package/fesm2022/{caribeng-ui-caribe-card-content.mjs → caribeng-ui-card-content.mjs} +39 -39
  16. package/fesm2022/{caribeng-ui-caribe-card-move.mjs → caribeng-ui-card-move.mjs} +65 -65
  17. package/fesm2022/{caribeng-ui-caribe-card-primary.mjs → caribeng-ui-card-primary.mjs} +31 -31
  18. package/fesm2022/{caribeng-ui-caribe-card-select.mjs → caribeng-ui-card-select.mjs} +67 -67
  19. package/fesm2022/caribeng-ui-carousel.mjs +2 -2
  20. package/fesm2022/caribeng-ui-cascadeselect.mjs +45 -9
  21. package/fesm2022/caribeng-ui-chart.mjs +8 -5
  22. package/fesm2022/caribeng-ui-chat.mjs +1303 -0
  23. package/fesm2022/{caribeng-ui-caribe-coachmark.mjs → caribeng-ui-coachmark.mjs} +85 -85
  24. package/fesm2022/caribeng-ui-code-block.mjs +332 -0
  25. package/fesm2022/caribeng-ui-colorpicker.mjs +99 -5
  26. package/fesm2022/caribeng-ui-command-palette.mjs +476 -0
  27. package/fesm2022/caribeng-ui-comments.mjs +864 -0
  28. package/fesm2022/caribeng-ui-confirmdialog.mjs +78 -13
  29. package/fesm2022/caribeng-ui-confirmpopup.mjs +91 -16
  30. package/fesm2022/caribeng-ui-contextmenu.mjs +8 -4
  31. package/fesm2022/caribeng-ui-copy-button.mjs +230 -0
  32. package/fesm2022/caribeng-ui-datagrid.mjs +1635 -0
  33. package/fesm2022/caribeng-ui-dataview.mjs +6 -3
  34. package/fesm2022/caribeng-ui-datepicker.mjs +2 -2
  35. package/fesm2022/caribeng-ui-dock.mjs +52 -12
  36. package/fesm2022/caribeng-ui-document.mjs +495 -0
  37. package/fesm2022/{caribeng-ui-caribe-dots-indicator.mjs → caribeng-ui-dots-indicator.mjs} +41 -41
  38. package/fesm2022/caribeng-ui-drawer.mjs +9 -4
  39. package/fesm2022/caribeng-ui-dynamic-form.mjs +1581 -0
  40. package/fesm2022/caribeng-ui-editor.mjs +2324 -1311
  41. package/fesm2022/{caribeng-ui-caribe-expansion-panel.mjs → caribeng-ui-expansion-panel.mjs} +39 -39
  42. package/fesm2022/{caribeng-ui-caribe-fab-menu.mjs → caribeng-ui-fab-menu.mjs} +75 -75
  43. package/fesm2022/caribeng-ui-fieldset.mjs +2 -2
  44. package/fesm2022/caribeng-ui-file-card.mjs +134 -17
  45. package/fesm2022/{caribeng-ui-caribe-file-download.mjs → caribeng-ui-file-download.mjs} +63 -63
  46. package/fesm2022/caribeng-ui-financial-report.mjs +380 -0
  47. package/fesm2022/{caribeng-ui-caribe-float-menu.mjs → caribeng-ui-float-menu.mjs} +31 -31
  48. package/fesm2022/caribeng-ui-floatlabel.mjs +2 -2
  49. package/fesm2022/caribeng-ui-flow.mjs +1508 -0
  50. package/fesm2022/caribeng-ui-folder-card.mjs +122 -12
  51. package/fesm2022/{caribeng-ui-caribe-footer.mjs → caribeng-ui-footer.mjs} +19 -19
  52. package/fesm2022/caribeng-ui-gantt.mjs +1094 -0
  53. package/fesm2022/{caribeng-ui-caribe-header.mjs → caribeng-ui-header.mjs} +49 -49
  54. package/fesm2022/{caribeng-ui-caribe-icon-button.mjs → caribeng-ui-icon-button.mjs} +23 -23
  55. package/fesm2022/caribeng-ui-image-cropper.mjs +671 -0
  56. package/fesm2022/caribeng-ui-import-wizard.mjs +746 -0
  57. package/fesm2022/caribeng-ui-infinite-scroll.mjs +226 -0
  58. package/fesm2022/caribeng-ui-inlinemessage.mjs +2 -2
  59. package/fesm2022/caribeng-ui-input-number.mjs +22 -6
  60. package/fesm2022/{caribeng-ui-caribe-input-search.mjs → caribeng-ui-input-search.mjs} +65 -65
  61. package/fesm2022/{caribeng-ui-caribe-input-token.mjs → caribeng-ui-input-token.mjs} +59 -59
  62. package/fesm2022/caribeng-ui-inputmask.mjs +8 -2
  63. package/fesm2022/caribeng-ui-inputotp.mjs +2 -2
  64. package/fesm2022/caribeng-ui-journal-entry.mjs +340 -0
  65. package/fesm2022/caribeng-ui-kanban.mjs +4612 -0
  66. package/fesm2022/caribeng-ui-kbd.mjs +122 -0
  67. package/fesm2022/caribeng-ui-kpi.mjs +189 -0
  68. package/fesm2022/{caribeng-ui-caribe-link.mjs → caribeng-ui-link.mjs} +37 -37
  69. package/fesm2022/caribeng-ui-masonry.mjs +93 -0
  70. package/fesm2022/caribeng-ui-media-player.mjs +821 -0
  71. package/fesm2022/caribeng-ui-megamenu.mjs +13 -9
  72. package/fesm2022/caribeng-ui-mentions.mjs +495 -0
  73. package/fesm2022/caribeng-ui-menu.mjs +8 -4
  74. package/fesm2022/caribeng-ui-menubar.mjs +9 -5
  75. package/fesm2022/caribeng-ui-message.mjs +6 -3
  76. package/fesm2022/caribeng-ui-notification-center.mjs +636 -0
  77. package/fesm2022/{caribeng-ui-caribe-off-canvas.mjs → caribeng-ui-off-canvas.mjs} +55 -55
  78. package/fesm2022/{caribeng-ui-caribe-onboarding.mjs → caribeng-ui-onboarding.mjs} +105 -105
  79. package/fesm2022/caribeng-ui-orderlist.mjs +2 -2
  80. package/fesm2022/caribeng-ui-organizationchart.mjs +6 -10
  81. package/fesm2022/caribeng-ui-panel.mjs +6 -6
  82. package/fesm2022/caribeng-ui-panelmenu.mjs +9 -6
  83. package/fesm2022/caribeng-ui-pdfviewer.mjs +1755 -25
  84. package/fesm2022/caribeng-ui-period-picker.mjs +637 -0
  85. package/fesm2022/caribeng-ui-phone-input.mjs +688 -0
  86. package/fesm2022/caribeng-ui-picklist.mjs +2 -2
  87. package/fesm2022/caribeng-ui-pivot.mjs +419 -0
  88. package/fesm2022/caribeng-ui-pricing.mjs +263 -69
  89. package/fesm2022/caribeng-ui-qrcode.mjs +564 -0
  90. package/fesm2022/caribeng-ui-rating.mjs +14 -17
  91. package/fesm2022/caribeng-ui-reconciliation.mjs +386 -0
  92. package/fesm2022/caribeng-ui-ripple.mjs +2 -0
  93. package/fesm2022/caribeng-ui-scheduler.mjs +1027 -0
  94. package/fesm2022/caribeng-ui-scrolltop.mjs +3 -1
  95. package/fesm2022/caribeng-ui-select.mjs +2 -2
  96. package/fesm2022/{caribeng-ui-caribe-shortcut.mjs → caribeng-ui-shortcut.mjs} +29 -29
  97. package/fesm2022/caribeng-ui-sidebar.mjs +573 -0
  98. package/fesm2022/caribeng-ui-signature-pad.mjs +654 -0
  99. package/fesm2022/{caribeng-ui-caribe-status.mjs → caribeng-ui-status.mjs} +11 -11
  100. package/fesm2022/{caribeng-ui-caribe-step-indicator.mjs → caribeng-ui-step-indicator.mjs} +53 -53
  101. package/fesm2022/caribeng-ui-stepper.mjs +12 -5
  102. package/fesm2022/caribeng-ui-steps.mjs +2 -2
  103. package/fesm2022/caribeng-ui-table.mjs +333 -19
  104. package/fesm2022/caribeng-ui-tabmenu.mjs +10 -6
  105. package/fesm2022/caribeng-ui-tabs.mjs +2 -2
  106. package/fesm2022/{caribeng-ui-caribe-tag-button.mjs → caribeng-ui-tag-button.mjs} +25 -25
  107. package/fesm2022/caribeng-ui-tag.mjs +2 -2
  108. package/fesm2022/caribeng-ui-tieredmenu.mjs +111 -21
  109. package/fesm2022/{caribeng-ui-caribe-tracker.mjs → caribeng-ui-tracker.mjs} +29 -29
  110. package/fesm2022/{caribeng-ui-caribe-transaction-status.mjs → caribeng-ui-transaction-status.mjs} +11 -11
  111. package/fesm2022/caribeng-ui-treeselect.mjs +44 -9
  112. package/fesm2022/caribeng-ui-treetable.mjs +236 -17
  113. package/fesm2022/{caribeng-ui-caribe-voucher.mjs → caribeng-ui-voucher.mjs} +45 -45
  114. package/fesm2022/caribeng-ui-xlsx.mjs +486 -0
  115. package/fesm2022/caribeng-ui.mjs +1568 -1
  116. package/package.json +258 -178
  117. package/schematics/collection.json +5 -0
  118. package/schematics/migrate-from-primeng/core-icons.json +1 -0
  119. package/schematics/migrate-from-primeng/icons.js +269 -0
  120. package/schematics/migrate-from-primeng/index.js +290 -0
  121. package/schematics/migrate-from-primeng/mappings/button.js +93 -0
  122. package/schematics/migrate-from-primeng/mappings/card.js +33 -0
  123. package/schematics/migrate-from-primeng/mappings/checkbox.js +44 -0
  124. package/schematics/migrate-from-primeng/mappings/confirm.js +221 -0
  125. package/schematics/migrate-from-primeng/mappings/datepicker.js +121 -0
  126. package/schematics/migrate-from-primeng/mappings/dialog.js +84 -0
  127. package/schematics/migrate-from-primeng/mappings/index.js +88 -0
  128. package/schematics/migrate-from-primeng/mappings/inputnumber.js +62 -0
  129. package/schematics/migrate-from-primeng/mappings/inputtext.js +60 -0
  130. package/schematics/migrate-from-primeng/mappings/menu.js +468 -0
  131. package/schematics/migrate-from-primeng/mappings/multiselect.js +49 -0
  132. package/schematics/migrate-from-primeng/mappings/radiobutton.js +22 -0
  133. package/schematics/migrate-from-primeng/mappings/rules.js +206 -0
  134. package/schematics/migrate-from-primeng/mappings/select.js +97 -0
  135. package/schematics/migrate-from-primeng/mappings/service-calls.js +100 -0
  136. package/schematics/migrate-from-primeng/mappings/table.js +613 -0
  137. package/schematics/migrate-from-primeng/mappings/tabs.js +225 -0
  138. package/schematics/migrate-from-primeng/mappings/tag.js +29 -0
  139. package/schematics/migrate-from-primeng/mappings/textarea.js +44 -0
  140. package/schematics/migrate-from-primeng/mappings/toast.js +173 -0
  141. package/schematics/migrate-from-primeng/mappings/toggleswitch.js +37 -0
  142. package/schematics/migrate-from-primeng/mappings/tooltip.js +44 -0
  143. package/schematics/migrate-from-primeng/mappings/types.js +10 -0
  144. package/schematics/migrate-from-primeng/report.js +79 -0
  145. package/schematics/migrate-from-primeng/schema.js +2 -0
  146. package/schematics/migrate-from-primeng/schema.json +34 -0
  147. package/schematics/migrate-from-primeng/template.js +387 -0
  148. package/schematics/migrate-from-primeng/todo.js +5 -0
  149. package/schematics/migrate-from-primeng/typescript.js +442 -0
  150. package/schematics/migrate-from-primeng/workspace.js +117 -0
  151. package/schematics/ng-add/index.js +16 -1
  152. package/types/caribeng-ui-account-picker.d.ts +142 -0
  153. package/types/caribeng-ui-aging.d.ts +123 -0
  154. package/types/{caribeng-ui-caribe-alert.d.ts → caribeng-ui-alert.d.ts} +2 -2
  155. package/types/caribeng-ui-amount.d.ts +82 -0
  156. package/types/{caribeng-ui-caribe-animation-lottie.d.ts → caribeng-ui-animation-lottie.d.ts} +2 -2
  157. package/types/caribeng-ui-audit-log.d.ts +86 -0
  158. package/types/caribeng-ui-badge.d.ts +3 -1
  159. package/types/caribeng-ui-breadcrumb.d.ts +9 -1
  160. package/types/{caribeng-ui-caribe-button-group.d.ts → caribeng-ui-button-group.d.ts} +2 -2
  161. package/types/{caribeng-ui-caribe-card-content.d.ts → caribeng-ui-card-content.d.ts} +2 -2
  162. package/types/{caribeng-ui-caribe-card-move.d.ts → caribeng-ui-card-move.d.ts} +1 -1
  163. package/types/{caribeng-ui-caribe-card-primary.d.ts → caribeng-ui-card-primary.d.ts} +2 -2
  164. package/types/{caribeng-ui-caribe-card-select.d.ts → caribeng-ui-card-select.d.ts} +2 -2
  165. package/types/caribeng-ui-cascadeselect.d.ts +6 -0
  166. package/types/caribeng-ui-chart.d.ts +3 -1
  167. package/types/caribeng-ui-chat.d.ts +299 -0
  168. package/types/{caribeng-ui-caribe-coachmark.d.ts → caribeng-ui-coachmark.d.ts} +2 -2
  169. package/types/caribeng-ui-code-block.d.ts +65 -0
  170. package/types/caribeng-ui-colorpicker.d.ts +5 -1
  171. package/types/caribeng-ui-command-palette.d.ts +133 -0
  172. package/types/caribeng-ui-comments.d.ts +214 -0
  173. package/types/caribeng-ui-confirmdialog.d.ts +34 -2
  174. package/types/caribeng-ui-confirmpopup.d.ts +39 -2
  175. package/types/caribeng-ui-contextmenu.d.ts +7 -0
  176. package/types/caribeng-ui-copy-button.d.ts +90 -0
  177. package/types/caribeng-ui-datagrid.d.ts +269 -0
  178. package/types/caribeng-ui-dataview.d.ts +2 -0
  179. package/types/caribeng-ui-dock.d.ts +13 -1
  180. package/types/caribeng-ui-document.d.ts +138 -0
  181. package/types/{caribeng-ui-caribe-dots-indicator.d.ts → caribeng-ui-dots-indicator.d.ts} +2 -2
  182. package/types/caribeng-ui-drawer.d.ts +3 -1
  183. package/types/caribeng-ui-dynamic-form.d.ts +409 -0
  184. package/types/caribeng-ui-editor.d.ts +110 -12
  185. package/types/{caribeng-ui-caribe-expansion-panel.d.ts → caribeng-ui-expansion-panel.d.ts} +1 -1
  186. package/types/{caribeng-ui-caribe-fab-menu.d.ts → caribeng-ui-fab-menu.d.ts} +2 -2
  187. package/types/caribeng-ui-file-card.d.ts +27 -2
  188. package/types/{caribeng-ui-caribe-file-download.d.ts → caribeng-ui-file-download.d.ts} +1 -1
  189. package/types/caribeng-ui-financial-report.d.ts +102 -0
  190. package/types/{caribeng-ui-caribe-float-menu.d.ts → caribeng-ui-float-menu.d.ts} +2 -2
  191. package/types/caribeng-ui-flow.d.ts +228 -0
  192. package/types/caribeng-ui-folder-card.d.ts +27 -5
  193. package/types/{caribeng-ui-caribe-footer.d.ts → caribeng-ui-footer.d.ts} +2 -2
  194. package/types/caribeng-ui-gantt.d.ts +244 -0
  195. package/types/{caribeng-ui-caribe-header.d.ts → caribeng-ui-header.d.ts} +2 -2
  196. package/types/{caribeng-ui-caribe-icon-button.d.ts → caribeng-ui-icon-button.d.ts} +2 -2
  197. package/types/{caribeng-ui-caribe-illustration.d.ts → caribeng-ui-illustration.d.ts} +1 -1
  198. package/types/caribeng-ui-image-cropper.d.ts +169 -0
  199. package/types/caribeng-ui-import-wizard.d.ts +149 -0
  200. package/types/caribeng-ui-infinite-scroll.d.ts +75 -0
  201. package/types/caribeng-ui-input-number.d.ts +1 -1
  202. package/types/{caribeng-ui-caribe-input-search.d.ts → caribeng-ui-input-search.d.ts} +2 -2
  203. package/types/{caribeng-ui-caribe-input-token.d.ts → caribeng-ui-input-token.d.ts} +2 -2
  204. package/types/caribeng-ui-inputmask.d.ts +3 -1
  205. package/types/caribeng-ui-journal-entry.d.ts +110 -0
  206. package/types/caribeng-ui-kanban.d.ts +783 -0
  207. package/types/caribeng-ui-kbd.d.ts +36 -0
  208. package/types/caribeng-ui-kpi.d.ts +64 -0
  209. package/types/{caribeng-ui-caribe-link.d.ts → caribeng-ui-link.d.ts} +2 -2
  210. package/types/{caribeng-ui-caribe-logo.d.ts → caribeng-ui-logo.d.ts} +1 -1
  211. package/types/caribeng-ui-masonry.d.ts +32 -0
  212. package/types/caribeng-ui-media-player.d.ts +140 -0
  213. package/types/caribeng-ui-megamenu.d.ts +11 -0
  214. package/types/caribeng-ui-mentions.d.ts +127 -0
  215. package/types/caribeng-ui-menu.d.ts +7 -0
  216. package/types/caribeng-ui-menubar.d.ts +7 -0
  217. package/types/caribeng-ui-message.d.ts +2 -0
  218. package/types/caribeng-ui-notification-center.d.ts +153 -0
  219. package/types/{caribeng-ui-caribe-off-canvas.d.ts → caribeng-ui-off-canvas.d.ts} +2 -2
  220. package/types/{caribeng-ui-caribe-onboarding.d.ts → caribeng-ui-onboarding.d.ts} +2 -2
  221. package/types/caribeng-ui-panelmenu.d.ts +7 -0
  222. package/types/caribeng-ui-pdfviewer.d.ts +245 -5
  223. package/types/caribeng-ui-period-picker.d.ts +148 -0
  224. package/types/caribeng-ui-phone-input.d.ts +168 -0
  225. package/types/caribeng-ui-pivot.d.ts +116 -0
  226. package/types/caribeng-ui-pricing.d.ts +41 -4
  227. package/types/caribeng-ui-qrcode.d.ts +88 -0
  228. package/types/caribeng-ui-reconciliation.d.ts +109 -0
  229. package/types/caribeng-ui-scheduler.d.ts +188 -0
  230. package/types/{caribeng-ui-caribe-shortcut.d.ts → caribeng-ui-shortcut.d.ts} +2 -2
  231. package/types/caribeng-ui-sidebar.d.ts +167 -0
  232. package/types/caribeng-ui-signature-pad.d.ts +151 -0
  233. package/types/{caribeng-ui-caribe-status.d.ts → caribeng-ui-status.d.ts} +2 -2
  234. package/types/{caribeng-ui-caribe-step-indicator.d.ts → caribeng-ui-step-indicator.d.ts} +2 -2
  235. package/types/caribeng-ui-stepper.d.ts +2 -0
  236. package/types/caribeng-ui-table.d.ts +67 -3
  237. package/types/caribeng-ui-tabmenu.d.ts +7 -0
  238. package/types/{caribeng-ui-caribe-tag-button.d.ts → caribeng-ui-tag-button.d.ts} +2 -2
  239. package/types/caribeng-ui-tieredmenu.d.ts +17 -1
  240. package/types/{caribeng-ui-caribe-tracker.d.ts → caribeng-ui-tracker.d.ts} +2 -2
  241. package/types/{caribeng-ui-caribe-transaction-status.d.ts → caribeng-ui-transaction-status.d.ts} +2 -2
  242. package/types/caribeng-ui-treeselect.d.ts +6 -0
  243. package/types/caribeng-ui-treetable.d.ts +67 -2
  244. package/types/{caribeng-ui-caribe-voucher.d.ts → caribeng-ui-voucher.d.ts} +2 -2
  245. package/types/caribeng-ui-xlsx.d.ts +79 -0
  246. package/types/caribeng-ui.d.ts +985 -2
  247. package/fesm2022/caribeng-ui-caribe-calendar.mjs +0 -92
  248. package/fesm2022/caribeng-ui-caribe-circle-loading.mjs +0 -130
  249. package/fesm2022/caribeng-ui-caribe-data-table.mjs +0 -94
  250. package/fesm2022/caribeng-ui-caribe-file-select.mjs +0 -88
  251. package/fesm2022/caribeng-ui-caribe-inline-alert.mjs +0 -100
  252. package/fesm2022/caribeng-ui-caribe-input-date.mjs +0 -138
  253. package/fesm2022/caribeng-ui-caribe-input-select.mjs +0 -154
  254. package/fesm2022/caribeng-ui-caribe-loader.mjs +0 -48
  255. package/fesm2022/caribeng-ui-caribe-modal.mjs +0 -119
  256. package/fesm2022/caribeng-ui-caribe-pictogram.mjs +0 -52
  257. package/fesm2022/caribeng-ui-caribe-pop-over.mjs +0 -104
  258. package/fesm2022/caribeng-ui-caribe-preloader.mjs +0 -57
  259. package/fesm2022/caribeng-ui-caribe-progress-bar.mjs +0 -84
  260. package/fesm2022/caribeng-ui-caribe-stroke.mjs +0 -69
  261. package/fesm2022/caribeng-ui-caribe-switch.mjs +0 -182
  262. package/styles/caribeng.css +0 -380
  263. package/styles/scss/_mixins.scss +0 -46
  264. package/styles/scss/_overlay.scss +0 -15
  265. package/styles/scss/_tokens.scss +0 -267
  266. package/styles/scss/_utilities.scss +0 -73
  267. package/styles/scss/_variables.scss +0 -33
  268. package/styles/scss/index.scss +0 -16
  269. package/types/caribeng-ui-caribe-calendar.d.ts +0 -27
  270. package/types/caribeng-ui-caribe-circle-loading.d.ts +0 -28
  271. package/types/caribeng-ui-caribe-data-table.d.ts +0 -26
  272. package/types/caribeng-ui-caribe-file-select.d.ts +0 -31
  273. package/types/caribeng-ui-caribe-inline-alert.d.ts +0 -28
  274. package/types/caribeng-ui-caribe-input-date.d.ts +0 -40
  275. package/types/caribeng-ui-caribe-input-select.d.ts +0 -47
  276. package/types/caribeng-ui-caribe-loader.d.ts +0 -22
  277. package/types/caribeng-ui-caribe-modal.d.ts +0 -21
  278. package/types/caribeng-ui-caribe-pictogram.d.ts +0 -15
  279. package/types/caribeng-ui-caribe-pop-over.d.ts +0 -17
  280. package/types/caribeng-ui-caribe-preloader.d.ts +0 -24
  281. package/types/caribeng-ui-caribe-progress-bar.d.ts +0 -28
  282. package/types/caribeng-ui-caribe-stroke.d.ts +0 -17
  283. package/types/caribeng-ui-caribe-switch.d.ts +0 -55
  284. /package/fesm2022/{caribeng-ui-caribe-illustration.mjs → caribeng-ui-illustration.mjs} +0 -0
  285. /package/fesm2022/{caribeng-ui-caribe-logo.mjs → caribeng-ui-logo.mjs} +0 -0
@@ -0,0 +1,1094 @@
1
+ import * as i0 from '@angular/core';
2
+ import { afterNextRender, inject, Injector, ElementRef, model, input, booleanAttribute, output, signal, viewChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { cbFormat, injectCbTranslation } from '@caribeng/ui';
4
+ import { CbIcon } from '@caribeng/ui/icon';
5
+
6
+ /**
7
+ * Modelo del diagrama de Gantt: fechas, árbol de tareas, grupos calculados,
8
+ * dependencias (fin → inicio) y planificación automática. Funciones puras: el
9
+ * componente las usa y los tests las prueban sin DOM.
10
+ */
11
+ // --- Fechas -------------------------------------------------------------------------------
12
+ function toDay(value) {
13
+ if (value instanceof Date)
14
+ return isNaN(value.getTime()) ? null : new Date(value.getFullYear(), value.getMonth(), value.getDate());
15
+ if (typeof value !== 'string' || !value)
16
+ return null;
17
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(value);
18
+ const date = m ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : new Date(value);
19
+ return isNaN(date.getTime()) ? null : new Date(date.getFullYear(), date.getMonth(), date.getDate());
20
+ }
21
+ function isoDay(date) {
22
+ const pad = (n) => String(n).padStart(2, '0');
23
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
24
+ }
25
+ function addDays(date, days) {
26
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
27
+ }
28
+ /** Días de calendario entre `a` y `b` (`b` − `a`). */
29
+ function dayDiff(a, b) {
30
+ return Math.round((Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()) - Date.UTC(a.getFullYear(), a.getMonth(), a.getDate())) / 86_400_000);
31
+ }
32
+ /** Lunes de la semana de `date` (semana ISO). */
33
+ function startOfWeek(date) {
34
+ return addDays(date, -((date.getDay() + 6) % 7));
35
+ }
36
+ /** Número de semana ISO. */
37
+ function isoWeek(date) {
38
+ const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
39
+ const day = d.getUTCDay() || 7;
40
+ d.setUTCDate(d.getUTCDate() + 4 - day);
41
+ const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
42
+ return Math.ceil(((d.getTime() - yearStart.getTime()) / 86_400_000 + 1) / 7);
43
+ }
44
+ /** Resuelve fechas y avance (los grupos abarcan a sus tareas y promedian su avance por duración). */
45
+ function resolveTasks(tasks) {
46
+ const byId = new Map(tasks.map((t) => [t.id, t]));
47
+ const children = new Map();
48
+ for (const t of tasks) {
49
+ if (t.parent && byId.has(t.parent) && t.parent !== t.id) {
50
+ const list = children.get(t.parent) ?? [];
51
+ list.push(t.id);
52
+ children.set(t.parent, list);
53
+ }
54
+ }
55
+ const out = new Map();
56
+ const visiting = new Set();
57
+ const level = (t) => {
58
+ let n = 0;
59
+ const seen = new Set();
60
+ for (let p = t.parent; p && byId.has(p) && !seen.has(p); p = byId.get(p).parent) {
61
+ seen.add(p);
62
+ n++;
63
+ }
64
+ return n;
65
+ };
66
+ const resolve = (id) => {
67
+ const done = out.get(id);
68
+ if (done)
69
+ return done;
70
+ const task = byId.get(id);
71
+ if (!task || visiting.has(id))
72
+ return null;
73
+ visiting.add(id);
74
+ const kids = children.get(id) ?? [];
75
+ const isGroup = task.type === 'group' || kids.length > 0;
76
+ let start = toDay(task.start);
77
+ let end = toDay(task.end) ?? start;
78
+ let progress = clampProgress(task.progress ?? 0);
79
+ if (isGroup && kids.length) {
80
+ const resolved = kids.map(resolve).filter((r) => !!r);
81
+ if (resolved.length) {
82
+ start = new Date(Math.min(...resolved.map((r) => r.start.getTime())));
83
+ end = new Date(Math.max(...resolved.map((r) => r.end.getTime())));
84
+ const weights = resolved.map((r) => Math.max(1, dayDiff(r.start, r.end) + 1));
85
+ const total = weights.reduce((a, b) => a + b, 0);
86
+ progress = Math.round(resolved.reduce((sum, r, i) => sum + r.progress * weights[i], 0) / total);
87
+ }
88
+ }
89
+ visiting.delete(id);
90
+ if (!start)
91
+ return null;
92
+ if (!end || end < start)
93
+ end = start;
94
+ const isMilestone = task.type === 'milestone' && !isGroup;
95
+ if (isMilestone)
96
+ end = start;
97
+ const result = { task, start, end, progress, level: level(task), isGroup, isMilestone, children: kids };
98
+ out.set(id, result);
99
+ return result;
100
+ };
101
+ for (const t of tasks)
102
+ resolve(t.id);
103
+ return out;
104
+ }
105
+ function clampProgress(value) {
106
+ return Math.max(0, Math.min(100, Math.round(Number(value) || 0)));
107
+ }
108
+ /** Filas visibles: el árbol en orden, sin los hijos de los grupos plegados. */
109
+ function visibleRows(tasks, resolved, collapsed) {
110
+ const rows = [];
111
+ const ids = new Set(tasks.map((t) => t.id));
112
+ const walk = (parent) => {
113
+ for (const t of tasks) {
114
+ const p = t.parent && ids.has(t.parent) && t.parent !== t.id ? t.parent : null;
115
+ if (p !== parent)
116
+ continue;
117
+ const r = resolved.get(t.id);
118
+ if (!r)
119
+ continue;
120
+ rows.push(r);
121
+ if (r.children.length && !collapsed.has(t.id))
122
+ walk(t.id);
123
+ }
124
+ };
125
+ walk(null);
126
+ return rows;
127
+ }
128
+ /** Ids de todas las tareas dentro de un grupo (a cualquier nivel). */
129
+ function descendants(tasks, id) {
130
+ const out = [];
131
+ const queue = [id];
132
+ while (queue.length) {
133
+ const current = queue.shift();
134
+ for (const t of tasks) {
135
+ if (t.parent === current && !out.includes(t.id)) {
136
+ out.push(t.id);
137
+ queue.push(t.id);
138
+ }
139
+ }
140
+ }
141
+ return out;
142
+ }
143
+ // --- Dependencias ---------------------------------------------------------------------------
144
+ /** ¿`to` depende (directa o indirectamente) de `from`? Evita crear ciclos. */
145
+ function dependsOn(tasks, to, from) {
146
+ const byId = new Map(tasks.map((t) => [t.id, t]));
147
+ const seen = new Set();
148
+ const stack = [to];
149
+ while (stack.length) {
150
+ const id = stack.pop();
151
+ if (id === from)
152
+ return true;
153
+ if (seen.has(id))
154
+ continue;
155
+ seen.add(id);
156
+ stack.push(...(byId.get(id)?.dependencies ?? []));
157
+ }
158
+ return false;
159
+ }
160
+ /** ¿Se puede crear la dependencia `from` → `to`? (sin repetir, sin ciclos ni grupos que se contienen). */
161
+ function canLink(tasks, from, to) {
162
+ if (from === to)
163
+ return false;
164
+ const target = tasks.find((t) => t.id === to);
165
+ if (!target || !tasks.some((t) => t.id === from))
166
+ return false;
167
+ if (target.dependencies?.includes(from))
168
+ return false;
169
+ if (descendants(tasks, from).includes(to) || descendants(tasks, to).includes(from))
170
+ return false;
171
+ return !dependsOn(tasks, from, to);
172
+ }
173
+ /**
174
+ * Planificación automática: cada tarea empieza como pronto el día siguiente al
175
+ * fin de sus predecesoras; si no, se desplaza conservando su duración. Devuelve
176
+ * las tareas cambiadas (las de grupos se resuelven con sus hijas).
177
+ */
178
+ function autoSchedule(tasks) {
179
+ let current = [...tasks];
180
+ for (let pass = 0; pass < tasks.length + 1; pass++) {
181
+ const resolved = resolveTasks(current);
182
+ let changed = false;
183
+ current = current.map((t) => {
184
+ if (!t.dependencies?.length)
185
+ return t;
186
+ const self = resolved.get(t.id);
187
+ if (!self || self.isGroup)
188
+ return t;
189
+ const ends = t.dependencies.map((d) => resolved.get(d)?.end).filter((d) => !!d);
190
+ if (!ends.length)
191
+ return t;
192
+ const earliest = addDays(new Date(Math.max(...ends.map((d) => d.getTime()))), 1);
193
+ if (self.start >= earliest)
194
+ return t;
195
+ const shift = dayDiff(self.start, earliest);
196
+ changed = true;
197
+ return { ...t, start: isoDay(addDays(self.start, shift)), end: isoDay(addDays(self.end, shift)) };
198
+ });
199
+ if (!changed)
200
+ break;
201
+ }
202
+ return current;
203
+ }
204
+
205
+ /** Alto de cada fila (px), igual que en el CSS. */
206
+ const ROW = 40;
207
+ /** Píxeles por día según la escala. */
208
+ const DAY_WIDTH = { day: 36, week: 14, month: 4 };
209
+ let nextUid = 0;
210
+ /**
211
+ * Diagrama de Gantt de CaribeNG: tabla de tareas en árbol (grupos plegables) y
212
+ * barras en el tiempo, con escalas de día, semana y mes.
213
+ *
214
+ * - Arrastra una barra para moverla, sus bordes para cambiar inicio o fin, el
215
+ * tirador inferior para el avance y el punto de la derecha hasta otra tarea
216
+ * para crear una dependencia (fin → inicio).
217
+ * - Con `autoSchedule`, al retrasar una tarea se desplazan las que dependen de ella.
218
+ * - Los grupos abarcan a sus tareas y promedian su avance; los hitos son rombos.
219
+ * - Con el teclado, cada barra es un botón: flechas mueven, Mayús + flechas cambian
220
+ * el fin, Alt + flechas el inicio, + / − el avance, Supr quita sus dependencias
221
+ * y Enter abre la tarea. Cada cambio se anuncia.
222
+ *
223
+ * @example
224
+ * ```html
225
+ * <cb-gantt [(tasks)]="tareas" [(scale)]="escala" (taskChange)="guardar($event)" />
226
+ * ```
227
+ */
228
+ class CbGantt {
229
+ x(date) {
230
+ return dayDiff(this.range().start, date) * this.dayWidth();
231
+ }
232
+ // --- Textos ---------------------------------------------------------------------------
233
+ scaleLabel(s) {
234
+ const t = this.t();
235
+ return s === 'day' ? t.ganttDay : s === 'week' ? t.ganttWeek : t.ganttMonth;
236
+ }
237
+ columnLabel(col) {
238
+ const t = this.t();
239
+ return { name: t.ganttTask, start: t.ganttStart, end: t.ganttEnd, duration: t.ganttDuration, progress: t.ganttProgress, assignee: t.ganttAssignee }[col];
240
+ }
241
+ dateText(d) {
242
+ return new Intl.DateTimeFormat(this.t().intlLocale, { day: 'numeric', month: 'short' }).format(d);
243
+ }
244
+ cellText(r, col) {
245
+ switch (col) {
246
+ case 'start':
247
+ return this.dateText(r.start);
248
+ case 'end':
249
+ return this.dateText(r.end);
250
+ case 'duration':
251
+ return r.isMilestone ? '—' : cbFormat(this.t().ganttDays, dayDiff(r.start, r.end) + 1);
252
+ case 'progress':
253
+ return r.isMilestone ? '—' : `${r.progress} %`;
254
+ case 'assignee':
255
+ return r.task.assignee ?? '';
256
+ default:
257
+ return r.task.name;
258
+ }
259
+ }
260
+ barLabel(b) {
261
+ const t = this.t();
262
+ const deps = (b.row.task.dependencies ?? []).map((id) => this.resolved().get(id)?.task.name).filter(Boolean);
263
+ const after = deps.length ? `. ${cbFormat(t.ganttDependsOn, deps.join(', '))}` : '';
264
+ if (b.row.isMilestone)
265
+ return cbFormat(t.ganttMilestoneLabel, b.row.task.name, this.dateText(b.start)) + after;
266
+ const range = `${this.dateText(b.start)} – ${this.dateText(b.end)}`;
267
+ return cbFormat(b.row.isGroup ? t.ganttGroupLabel : t.ganttBarLabel, b.row.task.name, range, b.progress) + after;
268
+ }
269
+ // --- Árbol ---------------------------------------------------------------------------------
270
+ toggle(id) {
271
+ this.collapsed.update((set) => {
272
+ const next = new Set(set);
273
+ if (next.has(id))
274
+ next.delete(id);
275
+ else
276
+ next.add(id);
277
+ return next;
278
+ });
279
+ }
280
+ /** Selecciona la tarea, lleva su barra a la vista y le da el foco. */
281
+ focusBar(id) {
282
+ this.selected.set(id);
283
+ afterNextRender(() => {
284
+ const bar = this.barEl(id);
285
+ const scroller = this.scroller()?.nativeElement;
286
+ if (!bar || !scroller)
287
+ return;
288
+ const grid = scroller.querySelector('.cb-gantt__grid')?.offsetWidth ?? 0;
289
+ const left = bar.offsetLeft + grid;
290
+ if (left < scroller.scrollLeft + grid || left + bar.offsetWidth > scroller.scrollLeft + scroller.clientWidth) {
291
+ scroller.scrollLeft = Math.max(0, left - grid - 48);
292
+ }
293
+ bar.focus({ preventScroll: true });
294
+ }, { injector: this.injector });
295
+ }
296
+ /** Desplaza el diagrama hasta hoy (centrado en la parte visible). */
297
+ scrollToToday(smooth = true) {
298
+ const x = this.todayX();
299
+ const scroller = this.scroller()?.nativeElement;
300
+ if (x === null || !scroller)
301
+ return;
302
+ const grid = scroller.querySelector('.cb-gantt__grid')?.offsetWidth ?? 0;
303
+ scroller.scrollTo?.({ left: Math.max(0, x - (scroller.clientWidth - grid) / 3), behavior: smooth ? 'smooth' : 'auto' });
304
+ }
305
+ constructor() {
306
+ /** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
307
+ this.t = injectCbTranslation();
308
+ this.fmt = cbFormat;
309
+ this.injector = inject(Injector);
310
+ this.host = inject(ElementRef);
311
+ this.uid = `cb-gantt-${++nextUid}`;
312
+ this.row = ROW;
313
+ this.scales = ['day', 'week', 'month'];
314
+ /** Tareas (bidireccional: se actualiza al arrastrar, con el teclado y al planificar). */
315
+ this.tasks = model([], /* @ts-ignore */
316
+ ...(ngDevMode ? [{ debugName: "tasks" }] : /* istanbul ignore next */ []));
317
+ /** Escala: un día, una semana o un mes por columna. */
318
+ this.scale = model('day', /* @ts-ignore */
319
+ ...(ngDevMode ? [{ debugName: "scale" }] : /* istanbul ignore next */ []));
320
+ /** Columnas de la tabla de la izquierda y su orden. */
321
+ this.columns = input(['name', 'start', 'end', 'duration', 'progress'], /* @ts-ignore */
322
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
323
+ /** Ancho de la tabla de la izquierda; por defecto, el de sus columnas (como mucho, el 60 % del componente). */
324
+ this.gridWidth = input('', /* @ts-ignore */
325
+ ...(ngDevMode ? [{ debugName: "gridWidth" }] : /* istanbul ignore next */ []));
326
+ /** Alto del componente (con scroll). */
327
+ this.height = input('28rem', /* @ts-ignore */
328
+ ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
329
+ /** Al retrasar una tarea, desplaza las que dependen de ella (fin → inicio). */
330
+ this.autoSchedule = input(true, { ...(ngDevMode ? { debugName: "autoSchedule" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
331
+ /** Sin edición: no se arrastra ni se crean dependencias. */
332
+ this.readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
333
+ /** Barra con la escala y el botón Hoy. */
334
+ this.showToolbar = input(true, { ...(ngDevMode ? { debugName: "showToolbar" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
335
+ /** Texto sin tareas. Por defecto, "Sin datos". */
336
+ this.emptyMessage = input(undefined, /* @ts-ignore */
337
+ ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
338
+ this.ariaLabel = input('', /* @ts-ignore */
339
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
340
+ /** Una tarea cambió de fechas o de avance (también las desplazadas por la planificación). */
341
+ this.taskChange = output();
342
+ /** Doble clic o Enter sobre una tarea. */
343
+ this.taskOpen = output();
344
+ /** Dependencia creada (`to` depende de `from`). */
345
+ this.linkAdd = output();
346
+ /** Dependencia quitada. */
347
+ this.linkRemove = output();
348
+ this.collapsed = signal(new Set(), /* @ts-ignore */
349
+ ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
350
+ this.selected = signal(null, /* @ts-ignore */
351
+ ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
352
+ this.selectedLink = signal(null, /* @ts-ignore */
353
+ ...(ngDevMode ? [{ debugName: "selectedLink" }] : /* istanbul ignore next */ []));
354
+ this.preview = signal(null, /* @ts-ignore */
355
+ ...(ngDevMode ? [{ debugName: "preview" }] : /* istanbul ignore next */ []));
356
+ this.announcement = signal('', /* @ts-ignore */
357
+ ...(ngDevMode ? [{ debugName: "announcement" }] : /* istanbul ignore next */ []));
358
+ this.drag = null;
359
+ this.scroller = viewChild('scroller', /* @ts-ignore */
360
+ ...(ngDevMode ? [{ debugName: "scroller" }] : /* istanbul ignore next */ []));
361
+ this.chart = viewChild('chart', /* @ts-ignore */
362
+ ...(ngDevMode ? [{ debugName: "chart" }] : /* istanbul ignore next */ []));
363
+ this.resolved = computed(() => resolveTasks(this.tasks()), /* @ts-ignore */
364
+ ...(ngDevMode ? [{ debugName: "resolved" }] : /* istanbul ignore next */ []));
365
+ /** Ancho de la tabla: el indicado o el nombre (14rem) más el de cada columna. */
366
+ this.gridSize = computed(() => {
367
+ if (this.gridWidth())
368
+ return this.gridWidth();
369
+ const widths = { name: 14, start: 4.5, end: 4.5, duration: 4.5, progress: 4, assignee: 6.5 };
370
+ return `${this.columns().reduce((sum, c) => sum + widths[c], 0)}rem`;
371
+ }, /* @ts-ignore */
372
+ ...(ngDevMode ? [{ debugName: "gridSize" }] : /* istanbul ignore next */ []));
373
+ this.rows = computed(() => visibleRows(this.tasks(), this.resolved(), this.collapsed()), /* @ts-ignore */
374
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
375
+ this.dayWidth = computed(() => DAY_WIDTH[this.scale()], /* @ts-ignore */
376
+ ...(ngDevMode ? [{ debugName: "dayWidth" }] : /* istanbul ignore next */ []));
377
+ /** Primer y último día del diagrama (con margen, alineados a la unidad de la escala). */
378
+ this.range = computed(() => {
379
+ const all = [...this.resolved().values()];
380
+ const today = toDay(new Date());
381
+ let min = all.length ? new Date(Math.min(...all.map((r) => r.start.getTime()))) : today;
382
+ let max = all.length ? new Date(Math.max(...all.map((r) => r.end.getTime()))) : addDays(today, 30);
383
+ const scale = this.scale();
384
+ if (scale === 'day') {
385
+ min = addDays(min, -3);
386
+ max = addDays(max, 10);
387
+ }
388
+ else if (scale === 'week') {
389
+ min = startOfWeek(addDays(min, -7));
390
+ max = addDays(startOfWeek(addDays(max, 14)), 6);
391
+ }
392
+ else {
393
+ min = new Date(min.getFullYear(), min.getMonth() - 1, 1);
394
+ max = new Date(max.getFullYear(), max.getMonth() + 2, 0);
395
+ }
396
+ return { start: min, end: max, days: dayDiff(min, max) + 1 };
397
+ }, /* @ts-ignore */
398
+ ...(ngDevMode ? [{ debugName: "range" }] : /* istanbul ignore next */ []));
399
+ this.chartWidth = computed(() => this.range().days * this.dayWidth(), /* @ts-ignore */
400
+ ...(ngDevMode ? [{ debugName: "chartWidth" }] : /* istanbul ignore next */ []));
401
+ /** Unidades de la escala (fila inferior de la cabecera y columnas del fondo). */
402
+ this.units = computed(() => {
403
+ const { start, days } = this.range();
404
+ const locale = this.t().intlLocale;
405
+ const scale = this.scale();
406
+ const w = this.dayWidth();
407
+ const units = [];
408
+ if (scale === 'day') {
409
+ const weekday = new Intl.DateTimeFormat(locale, { weekday: 'narrow' });
410
+ for (let i = 0; i < days; i++) {
411
+ const d = addDays(start, i);
412
+ units.push({ key: isoDay(d), label: `${weekday.format(d)} ${d.getDate()}`, x: i * w, width: w, weekend: d.getDay() === 0 || d.getDay() === 6 });
413
+ }
414
+ }
415
+ else if (scale === 'week') {
416
+ const day = new Intl.DateTimeFormat(locale, { day: 'numeric', month: 'short' });
417
+ for (let i = 0; i < days; i += 7) {
418
+ const d = addDays(start, i);
419
+ units.push({ key: isoDay(d), label: `${cbFormat(this.t().ganttWeekShort, isoWeek(d))} · ${day.format(d)}`, x: i * w, width: 7 * w });
420
+ }
421
+ }
422
+ else {
423
+ const month = new Intl.DateTimeFormat(locale, { month: 'short' });
424
+ for (let d = new Date(start); d <= this.range().end; d = new Date(d.getFullYear(), d.getMonth() + 1, 1)) {
425
+ const next = new Date(d.getFullYear(), d.getMonth() + 1, 1);
426
+ units.push({ key: isoDay(d), label: month.format(d), x: this.x(d), width: dayDiff(d, next) * w });
427
+ }
428
+ }
429
+ return units;
430
+ }, /* @ts-ignore */
431
+ ...(ngDevMode ? [{ debugName: "units" }] : /* istanbul ignore next */ []));
432
+ /** Fila superior de la cabecera: meses (día y semana) o años (mes). */
433
+ this.topUnits = computed(() => {
434
+ const { start, end } = this.range();
435
+ const locale = this.t().intlLocale;
436
+ const units = [];
437
+ if (this.scale() === 'month') {
438
+ for (let y = start.getFullYear(); y <= end.getFullYear(); y++) {
439
+ const from = new Date(Math.max(start.getTime(), new Date(y, 0, 1).getTime()));
440
+ const to = new Date(Math.min(addDays(end, 1).getTime(), new Date(y + 1, 0, 1).getTime()));
441
+ units.push({ key: String(y), label: String(y), x: this.x(from), width: dayDiff(from, to) * this.dayWidth() });
442
+ }
443
+ return units;
444
+ }
445
+ const format = new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' });
446
+ for (let d = new Date(start.getFullYear(), start.getMonth(), 1); d <= end; d = new Date(d.getFullYear(), d.getMonth() + 1, 1)) {
447
+ const from = d < start ? start : d;
448
+ const next = new Date(d.getFullYear(), d.getMonth() + 1, 1);
449
+ const to = next > addDays(end, 1) ? addDays(end, 1) : next;
450
+ const label = format.format(d);
451
+ // Solo la primera letra en mayúscula ("Noviembre de 2026", no "Noviembre De 2026").
452
+ units.push({ key: isoDay(d), label: label.charAt(0).toUpperCase() + label.slice(1), x: this.x(from), width: dayDiff(from, to) * this.dayWidth() });
453
+ }
454
+ return units;
455
+ }, /* @ts-ignore */
456
+ ...(ngDevMode ? [{ debugName: "topUnits" }] : /* istanbul ignore next */ []));
457
+ this.todayX = computed(() => {
458
+ const today = toDay(new Date());
459
+ const { start, end } = this.range();
460
+ return today < start || today > end ? null : this.x(today) + this.dayWidth() / 2;
461
+ }, /* @ts-ignore */
462
+ ...(ngDevMode ? [{ debugName: "todayX" }] : /* istanbul ignore next */ []));
463
+ /** Geometría de las barras (con la vista previa del arrastre). */
464
+ this.bars = computed(() => {
465
+ const preview = this.preview();
466
+ const moving = preview && preview.mode === 'move' ? new Set([preview.id, ...descendants(this.tasks(), preview.id)]) : null;
467
+ const w = this.dayWidth();
468
+ return this.rows().map((r, index) => {
469
+ let start = r.start;
470
+ let end = r.end;
471
+ let progress = r.progress;
472
+ if (preview && moving?.has(r.task.id)) {
473
+ start = addDays(start, preview.delta);
474
+ end = addDays(end, preview.delta);
475
+ }
476
+ else if (preview?.id === r.task.id) {
477
+ if (preview.mode === 'start')
478
+ start = addDays(start, Math.min(preview.delta, dayDiff(start, end)));
479
+ if (preview.mode === 'end')
480
+ end = addDays(end, Math.max(preview.delta, -dayDiff(start, end)));
481
+ if (preview.mode === 'progress')
482
+ progress = preview.progress;
483
+ }
484
+ if (moving && r.isGroup && !moving.has(r.task.id)) {
485
+ // Un grupo que contiene la tarea movida se recalcula en la vista previa.
486
+ const kids = descendants(this.tasks(), r.task.id).filter((id) => moving.has(id));
487
+ if (kids.length) {
488
+ const resolved = this.resolved();
489
+ const spans = descendants(this.tasks(), r.task.id)
490
+ .map((id) => resolved.get(id))
491
+ .filter((k) => !!k && !k.isGroup)
492
+ .map((k) => (moving.has(k.task.id) ? [addDays(k.start, preview.delta), addDays(k.end, preview.delta)] : [k.start, k.end]));
493
+ if (spans.length) {
494
+ start = new Date(Math.min(...spans.map((s) => s[0].getTime())));
495
+ end = new Date(Math.max(...spans.map((s) => s[1].getTime())));
496
+ }
497
+ }
498
+ }
499
+ const x = this.x(start);
500
+ const width = r.isMilestone ? Math.max(18, w) : (dayDiff(start, end) + 1) * w;
501
+ return { row: r, index, x: r.isMilestone ? x + w / 2 - 9 : x, width: r.isMilestone ? 18 : width, y: index * ROW, start, end, progress };
502
+ });
503
+ }, /* @ts-ignore */
504
+ ...(ngDevMode ? [{ debugName: "bars" }] : /* istanbul ignore next */ []));
505
+ /** Flechas de dependencias entre barras visibles. */
506
+ this.links = computed(() => {
507
+ const bars = new Map(this.bars().map((b) => [b.row.task.id, b]));
508
+ const out = [];
509
+ for (const b of this.bars()) {
510
+ for (const dep of b.row.task.dependencies ?? []) {
511
+ const from = bars.get(dep);
512
+ if (!from)
513
+ continue;
514
+ const x1 = from.x + from.width;
515
+ const y1 = from.y + ROW / 2;
516
+ const x2 = b.x;
517
+ const y2 = b.y + ROW / 2;
518
+ let path;
519
+ if (x2 - x1 >= 16) {
520
+ const mx = x1 + 8;
521
+ path = `M${x1} ${y1} H${mx} V${y2} H${x2 - 1}`;
522
+ }
523
+ else {
524
+ const midY = y2 > y1 ? b.y : b.y + ROW;
525
+ path = `M${x1} ${y1} H${x1 + 8} V${midY} H${x2 - 10} V${y2} H${x2 - 1}`;
526
+ }
527
+ out.push({ key: `${dep}>${b.row.task.id}`, from: dep, to: b.row.task.id, fromName: from.row.task.name, toName: b.row.task.name, path, mid: { x: x1 + 8, y: (y1 + y2) / 2 } });
528
+ }
529
+ }
530
+ return out;
531
+ }, /* @ts-ignore */
532
+ ...(ngDevMode ? [{ debugName: "links" }] : /* istanbul ignore next */ []));
533
+ /** Línea provisional al crear una dependencia. */
534
+ this.linkLine = computed(() => {
535
+ const p = this.preview();
536
+ if (p?.mode !== 'link' || !p.point)
537
+ return null;
538
+ const from = this.bars().find((b) => b.row.task.id === p.id);
539
+ if (!from)
540
+ return null;
541
+ return `M${from.x + from.width} ${from.y + ROW / 2} L${p.point.x} ${p.point.y}`;
542
+ }, /* @ts-ignore */
543
+ ...(ngDevMode ? [{ debugName: "linkLine" }] : /* istanbul ignore next */ []));
544
+ // Al abrir, el diagrama empieza cerca de hoy.
545
+ afterNextRender(() => this.scrollToToday(false));
546
+ }
547
+ barEl(id) {
548
+ return Array.from(this.host.nativeElement.querySelectorAll('.cb-gantt__bar')).find((b) => b.dataset['ganttId'] === id) ?? null;
549
+ }
550
+ // --- Cambios ---------------------------------------------------------------------------------
551
+ /** Aplica un cambio a una tarea (y a las desplazadas por la planificación) y lo emite. */
552
+ apply(id, mode, delta, progress) {
553
+ const tasks = this.tasks();
554
+ const resolved = this.resolved();
555
+ const target = resolved.get(id);
556
+ if (!target)
557
+ return;
558
+ const shift = (t, d) => {
559
+ const r = resolved.get(t.id);
560
+ return { ...t, start: isoDay(addDays(r.start, d)), end: isoDay(addDays(r.end, d)) };
561
+ };
562
+ let next;
563
+ if (mode === 'move') {
564
+ if (!delta)
565
+ return;
566
+ const moved = new Set([id, ...descendants(tasks, id)]);
567
+ next = tasks.map((t) => (moved.has(t.id) && !resolved.get(t.id)?.isGroup ? shift(t, delta) : t));
568
+ }
569
+ else if (mode === 'progress') {
570
+ const value = clampProgress(progress ?? 0);
571
+ if (value === target.progress || target.isGroup)
572
+ return;
573
+ next = tasks.map((t) => (t.id === id ? { ...t, progress: value } : t));
574
+ }
575
+ else {
576
+ if (!delta || target.isGroup || target.isMilestone)
577
+ return;
578
+ const length = dayDiff(target.start, target.end);
579
+ next = tasks.map((t) => {
580
+ if (t.id !== id)
581
+ return t;
582
+ return mode === 'start'
583
+ ? { ...t, start: isoDay(addDays(target.start, Math.min(delta, length))) }
584
+ : { ...t, end: isoDay(addDays(target.end, Math.max(delta, -length))) };
585
+ });
586
+ }
587
+ if (this.autoSchedule())
588
+ next = autoSchedule(next);
589
+ this.commit(tasks, next, id, mode === 'progress' ? 'progress' : mode === 'move' ? 'move' : 'resize');
590
+ }
591
+ commit(before, after, id, reason) {
592
+ const prev = new Map(before.map((t) => [t.id, t]));
593
+ this.tasks.set(after);
594
+ const own = new Set([id, ...descendants(before, id)]);
595
+ const changes = [];
596
+ for (const t of after) {
597
+ const p = prev.get(t.id);
598
+ if (!p || p === t)
599
+ continue;
600
+ if (p.start === t.start && p.end === t.end && p.progress === t.progress && p.dependencies === t.dependencies)
601
+ continue;
602
+ changes.push({ task: t, previous: p, reason: own.has(t.id) ? reason : 'schedule' });
603
+ }
604
+ // Primero las replanificadas; al final, la tarea que cambió el usuario.
605
+ changes.sort((a, b) => Number(a.reason !== 'schedule') - Number(b.reason !== 'schedule'));
606
+ for (const change of changes)
607
+ this.taskChange.emit(change);
608
+ const r = this.resolveFresh(id);
609
+ if (r) {
610
+ const text = reason === 'progress'
611
+ ? cbFormat(this.t().ganttProgressChanged, r.task.name, r.progress)
612
+ : cbFormat(this.t().ganttMoved, r.task.name, `${this.dateText(r.start)} – ${this.dateText(r.end)}`);
613
+ this.announcement.set(text);
614
+ }
615
+ }
616
+ resolveFresh(id) {
617
+ return this.resolved().get(id);
618
+ }
619
+ /** Crea la dependencia `from` → `to` (si no forma un ciclo). */
620
+ addLink(from, to) {
621
+ const tasks = this.tasks();
622
+ if (!canLink(tasks, from, to))
623
+ return false;
624
+ let next = tasks.map((t) => (t.id === to ? { ...t, dependencies: [...(t.dependencies ?? []), from] } : t));
625
+ if (this.autoSchedule())
626
+ next = autoSchedule(next);
627
+ this.commit(tasks, next, to, 'schedule');
628
+ this.linkAdd.emit({ from, to });
629
+ const names = [from, to].map((id) => this.resolved().get(id)?.task.name ?? id);
630
+ this.announcement.set(cbFormat(this.t().ganttLinkAdded, names[0], names[1]));
631
+ return true;
632
+ }
633
+ /** Quita la dependencia `from` → `to`. */
634
+ removeLink(from, to) {
635
+ const tasks = this.tasks();
636
+ const target = tasks.find((t) => t.id === to);
637
+ if (!target?.dependencies?.includes(from))
638
+ return;
639
+ this.tasks.set(tasks.map((t) => (t.id === to ? { ...t, dependencies: t.dependencies.filter((d) => d !== from) } : t)));
640
+ this.selectedLink.set(null);
641
+ this.linkRemove.emit({ from, to });
642
+ this.announcement.set(this.t().ganttLinkRemoved);
643
+ }
644
+ selectLink(link) {
645
+ if (this.readonly())
646
+ return;
647
+ this.selectedLink.set(this.selectedLink()?.key === link.key ? null : link);
648
+ }
649
+ // --- Arrastre --------------------------------------------------------------------------------
650
+ onPointerDown(event, bar) {
651
+ this.selected.set(bar.row.task.id);
652
+ this.selectedLink.set(null);
653
+ if (this.readonly() || event.button !== 0)
654
+ return;
655
+ const target = event.target;
656
+ let mode = target.dataset['mode'] ?? 'move';
657
+ if (bar.row.isMilestone && mode !== 'link')
658
+ mode = 'move';
659
+ if (bar.row.isGroup && mode !== 'move' && mode !== 'link')
660
+ return;
661
+ event.preventDefault();
662
+ this.drag = { id: bar.row.task.id, mode, x: event.clientX, y: event.clientY, startProgress: bar.progress, width: bar.width, moved: false };
663
+ event.currentTarget.setPointerCapture?.(event.pointerId);
664
+ }
665
+ onPointerMove(event) {
666
+ const drag = this.drag;
667
+ if (!drag)
668
+ return;
669
+ const dx = event.clientX - drag.x;
670
+ if (!drag.moved && Math.abs(dx) < 3 && Math.abs(event.clientY - drag.y) < 3)
671
+ return;
672
+ drag.moved = true;
673
+ if (drag.mode === 'link') {
674
+ const rect = this.chart()?.nativeElement.getBoundingClientRect();
675
+ this.preview.set({ id: drag.id, mode: 'link', delta: 0, progress: 0, point: rect ? { x: event.clientX - rect.left, y: event.clientY - rect.top } : null });
676
+ return;
677
+ }
678
+ if (drag.mode === 'progress') {
679
+ const value = clampProgress(drag.startProgress + (dx / Math.max(1, drag.width)) * 100);
680
+ this.preview.set({ id: drag.id, mode: 'progress', delta: 0, progress: value, point: null });
681
+ return;
682
+ }
683
+ this.preview.set({ id: drag.id, mode: drag.mode, delta: Math.round(dx / this.dayWidth()), progress: 0, point: null });
684
+ }
685
+ onPointerUp(event) {
686
+ const drag = this.drag;
687
+ const preview = this.preview();
688
+ this.drag = null;
689
+ this.preview.set(null);
690
+ if (!drag?.moved || !preview)
691
+ return;
692
+ if (drag.mode === 'link') {
693
+ const doc = this.host.nativeElement.ownerDocument;
694
+ const under = doc.elementFromPoint?.(event.clientX, event.clientY);
695
+ const to = under?.closest('.cb-gantt__bar')?.dataset['ganttId'];
696
+ if (to)
697
+ this.addLink(drag.id, to);
698
+ return;
699
+ }
700
+ this.apply(drag.id, drag.mode, preview.delta, preview.progress);
701
+ }
702
+ cancelDrag() {
703
+ this.drag = null;
704
+ this.preview.set(null);
705
+ }
706
+ // --- Teclado ---------------------------------------------------------------------------------
707
+ onBarKeydown(event, r) {
708
+ if (event.key === 'Enter') {
709
+ event.preventDefault();
710
+ this.taskOpen.emit(r.task);
711
+ return;
712
+ }
713
+ if (event.key === 'Escape' && this.drag) {
714
+ this.cancelDrag();
715
+ return;
716
+ }
717
+ if (this.readonly())
718
+ return;
719
+ const id = r.task.id;
720
+ const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
721
+ if (step) {
722
+ event.preventDefault();
723
+ const mode = event.shiftKey ? 'end' : event.altKey ? 'start' : 'move';
724
+ if (mode !== 'move' && (r.isGroup || r.isMilestone))
725
+ return;
726
+ this.apply(id, mode, step);
727
+ this.focusBar(id);
728
+ }
729
+ else if (['+', '=', '-', 'PageUp', 'PageDown'].includes(event.key) && !r.isGroup && !r.isMilestone) {
730
+ event.preventDefault();
731
+ const up = event.key === '+' || event.key === '=' || event.key === 'PageUp';
732
+ this.apply(id, 'progress', 0, r.progress + (up ? 10 : -10));
733
+ this.focusBar(id);
734
+ }
735
+ else if ((event.key === 'Delete' || event.key === 'Backspace') && r.task.dependencies?.length) {
736
+ event.preventDefault();
737
+ for (const from of [...r.task.dependencies])
738
+ this.removeLink(from, id);
739
+ this.focusBar(id);
740
+ }
741
+ }
742
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbGantt, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
743
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbGantt, isStandalone: true, selector: "cb-gantt", inputs: { tasks: { classPropertyName: "tasks", publicName: "tasks", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, gridWidth: { classPropertyName: "gridWidth", publicName: "gridWidth", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, autoSchedule: { classPropertyName: "autoSchedule", publicName: "autoSchedule", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tasks: "tasksChange", scale: "scaleChange", taskChange: "taskChange", taskOpen: "taskOpen", linkAdd: "linkAdd", linkRemove: "linkRemove" }, host: { properties: { "class.cb-gantt--readonly": "readonly()" }, classAttribute: "cb-gantt" }, viewQueries: [{ propertyName: "scroller", first: true, predicate: ["scroller"], descendants: true, isSignal: true }, { propertyName: "chart", first: true, predicate: ["chart"], descendants: true, isSignal: true }], ngImport: i0, template: `
744
+ @if (showToolbar()) {
745
+ <div class="cb-gantt__toolbar">
746
+ <div class="cb-gantt__scales" role="group" [attr.aria-label]="t().ganttScale">
747
+ @for (s of scales; track s) {
748
+ <button type="button" class="cb-gantt__scale" [attr.aria-pressed]="scale() === s" (click)="scale.set(s)">{{ scaleLabel(s) }}</button>
749
+ }
750
+ </div>
751
+ <button type="button" class="cb-gantt__btn" (click)="scrollToToday()">{{ t().today }}</button>
752
+ </div>
753
+ }
754
+
755
+ <div #scroller class="cb-gantt__scroller" [style.height]="height()" (pointermove)="onPointerMove($event)" (pointerup)="onPointerUp($event)" (pointercancel)="cancelDrag()">
756
+ <div class="cb-gantt__inner" [style.--cb-gantt-grid]="gridSize()">
757
+ <!-- Cabecera: columnas de la tabla y escala de tiempo -->
758
+ <div class="cb-gantt__head">
759
+ <div class="cb-gantt__head-grid" aria-hidden="true">
760
+ @for (col of columns(); track col) {
761
+ <span class="cb-gantt__head-cell" [class]="'cb-gantt__head-cell cb-gantt__col-' + col">{{ columnLabel(col) }}</span>
762
+ }
763
+ </div>
764
+ <div class="cb-gantt__head-scale" [style.width.px]="chartWidth()" aria-hidden="true">
765
+ <div class="cb-gantt__head-row">
766
+ @for (u of topUnits(); track u.key) {
767
+ <span class="cb-gantt__unit cb-gantt__unit--top" [style.left.px]="u.x" [style.width.px]="u.width">{{ u.label }}</span>
768
+ }
769
+ </div>
770
+ <div class="cb-gantt__head-row">
771
+ @for (u of units(); track u.key) {
772
+ <span class="cb-gantt__unit" [class.cb-gantt__unit--weekend]="u.weekend" [style.left.px]="u.x" [style.width.px]="u.width">{{ u.label }}</span>
773
+ }
774
+ </div>
775
+ </div>
776
+ </div>
777
+
778
+ <div class="cb-gantt__body" [style.height.px]="rows().length * row">
779
+ <!-- Tabla de tareas (árbol) -->
780
+ <div class="cb-gantt__grid" role="treegrid" [attr.aria-label]="ariaLabel() || t().ganttChart" [attr.aria-rowcount]="rows().length">
781
+ @for (r of rows(); track r.task.id; let i = $index) {
782
+ <div
783
+ class="cb-gantt__row"
784
+ role="row"
785
+ [class.cb-is-selected]="selected() === r.task.id"
786
+ [attr.aria-level]="r.level + 1"
787
+ [attr.aria-expanded]="r.children.length ? !collapsed().has(r.task.id) : null"
788
+ [attr.aria-rowindex]="i + 1"
789
+ [attr.aria-selected]="selected() === r.task.id"
790
+ >
791
+ @for (col of columns(); track col) {
792
+ @if (col === 'name') {
793
+ <span class="cb-gantt__cell cb-gantt__col-name" role="gridcell" [style.padding-left]="0.5 + r.level * 1.1 + 'rem'">
794
+ @if (r.children.length) {
795
+ <button
796
+ type="button"
797
+ class="cb-gantt__toggle"
798
+ [attr.aria-label]="fmt(collapsed().has(r.task.id) ? t().ganttExpand : t().ganttCollapse, r.task.name)"
799
+ [attr.aria-expanded]="!collapsed().has(r.task.id)"
800
+ (click)="toggle(r.task.id)"
801
+ >
802
+ <cb-icon [name]="collapsed().has(r.task.id) ? 'chevron-right' : 'chevron-down'" [size]="14" aria-hidden="true" />
803
+ </button>
804
+ } @else {
805
+ <span class="cb-gantt__toggle-space" aria-hidden="true"></span>
806
+ }
807
+ <button type="button" class="cb-gantt__name" [class.cb-gantt__name--group]="r.isGroup" (click)="focusBar(r.task.id)" (dblclick)="taskOpen.emit(r.task)">
808
+ @if (r.isMilestone) {
809
+ <span class="cb-gantt__diamond-mini" aria-hidden="true"></span>
810
+ }
811
+ {{ r.task.name }}
812
+ </button>
813
+ </span>
814
+ } @else {
815
+ <span [class]="'cb-gantt__cell cb-gantt__col-' + col" role="gridcell">{{ cellText(r, col) }}</span>
816
+ }
817
+ }
818
+ </div>
819
+ }
820
+ </div>
821
+
822
+ <!-- Diagrama -->
823
+ <div #chart class="cb-gantt__chart" [style.width.px]="chartWidth()">
824
+ @for (u of units(); track u.key) {
825
+ <span class="cb-gantt__col" [class.cb-gantt__col--weekend]="u.weekend" [style.left.px]="u.x" [style.width.px]="u.width" aria-hidden="true"></span>
826
+ }
827
+ @for (r of rows(); track r.task.id; let i = $index) {
828
+ <span class="cb-gantt__stripe" [class.cb-is-selected]="selected() === r.task.id" [style.top.px]="i * row" aria-hidden="true"></span>
829
+ }
830
+ @if (todayX() !== null) {
831
+ <span class="cb-gantt__today" [style.left.px]="todayX()" aria-hidden="true"></span>
832
+ }
833
+
834
+ <svg class="cb-gantt__links" [attr.width]="chartWidth()" [attr.height]="rows().length * row" aria-hidden="true">
835
+ <defs>
836
+ <marker [attr.id]="uid + '-arrow'" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
837
+ <path d="M0 0 L8 4 L0 8 z" />
838
+ </marker>
839
+ </defs>
840
+ @for (l of links(); track l.key) {
841
+ <path class="cb-gantt__link-hit" [attr.d]="l.path" (click)="selectLink(l)" />
842
+ <path class="cb-gantt__link" [class.cb-is-selected]="selectedLink()?.key === l.key" [attr.d]="l.path" [attr.marker-end]="'url(#' + uid + '-arrow)'" />
843
+ }
844
+ @if (linkLine(); as line) {
845
+ <path class="cb-gantt__link cb-gantt__link--draft" [attr.d]="line" />
846
+ }
847
+ </svg>
848
+
849
+ @if (selectedLink(); as sl) {
850
+ <button
851
+ type="button"
852
+ class="cb-gantt__unlink"
853
+ [style.left.px]="sl.mid.x"
854
+ [style.top.px]="sl.mid.y"
855
+ [attr.aria-label]="fmt(t().ganttRemoveLink, sl.fromName, sl.toName)"
856
+ [attr.title]="fmt(t().ganttRemoveLink, sl.fromName, sl.toName)"
857
+ (click)="removeLink(sl.from, sl.to)"
858
+ >
859
+ <cb-icon name="x" [size]="12" aria-hidden="true" />
860
+ </button>
861
+ }
862
+
863
+ @for (b of bars(); track b.row.task.id) {
864
+ <div
865
+ class="cb-gantt__bar"
866
+ role="button"
867
+ tabindex="0"
868
+ [attr.data-gantt-id]="b.row.task.id"
869
+ [class.cb-gantt__bar--group]="b.row.isGroup"
870
+ [class.cb-gantt__bar--milestone]="b.row.isMilestone"
871
+ [class.cb-gantt__bar--short]="!b.row.isMilestone && !b.row.isGroup && b.width < 72"
872
+ [class.cb-is-selected]="selected() === b.row.task.id"
873
+ [class.cb-is-dragging]="preview()?.id === b.row.task.id"
874
+ [style.left.px]="b.x"
875
+ [style.top.px]="b.y"
876
+ [style.width.px]="b.width"
877
+ [style.--cb-gantt-color]="b.row.task.color || null"
878
+ [attr.aria-label]="barLabel(b)"
879
+ [attr.aria-describedby]="readonly() ? null : uid + '-help'"
880
+ (pointerdown)="onPointerDown($event, b)"
881
+ (keydown)="onBarKeydown($event, b.row)"
882
+ (click)="selected.set(b.row.task.id)"
883
+ (dblclick)="taskOpen.emit(b.row.task)"
884
+ >
885
+ @if (!b.row.isMilestone) {
886
+ <span class="cb-gantt__progress" [style.width.%]="b.progress" aria-hidden="true"></span>
887
+ <span class="cb-gantt__bar-label" aria-hidden="true">{{ b.row.task.name }}</span>
888
+ @if (!readonly() && !b.row.isGroup) {
889
+ <span class="cb-gantt__handle cb-gantt__handle--start" data-mode="start" aria-hidden="true"></span>
890
+ <span class="cb-gantt__handle cb-gantt__handle--end" data-mode="end" aria-hidden="true"></span>
891
+ <span class="cb-gantt__progress-handle" data-mode="progress" [style.left.%]="b.progress" aria-hidden="true"></span>
892
+ }
893
+ } @else {
894
+ <span class="cb-gantt__diamond" aria-hidden="true"></span>
895
+ <span class="cb-gantt__milestone-label" aria-hidden="true">{{ b.row.task.name }}</span>
896
+ }
897
+ @if (!readonly()) {
898
+ <span class="cb-gantt__connector" data-mode="link" aria-hidden="true"></span>
899
+ }
900
+ </div>
901
+ }
902
+ </div>
903
+ </div>
904
+ </div>
905
+ @if (!rows().length) {
906
+ <p class="cb-gantt__empty">{{ emptyMessage() ?? t().noData }}</p>
907
+ }
908
+ </div>
909
+ <p class="cb-gantt__sr" [id]="uid + '-help'">{{ t().ganttInstructions }}</p>
910
+ <div class="cb-gantt__sr" role="status">{{ announcement() }}</div>
911
+ `, isInline: true, styles: [":host{--cb-gantt-row: 40px;--cb-gantt-bar: var(--cb-color-primary-500);--cb-gantt-bar-bg: color-mix(in srgb, var(--cb-gantt-bar) 28%, var(--cb-color-surface));display:flex;flex-direction:column;gap:var(--cb-space-2, .5rem);width:100%;min-width:0;color:var(--cb-color-text);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm, .875rem)}.cb-gantt__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.cb-gantt__scales{display:inline-flex;padding:2px;border-radius:var(--cb-radius-md);background:var(--cb-color-surface-hover)}.cb-gantt__scale,.cb-gantt__btn{padding:.3rem .75rem;border:0;border-radius:calc(var(--cb-radius-md) - 2px);background:transparent;color:var(--cb-color-text-muted);font:inherit;font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-medium, 500);cursor:pointer}.cb-gantt__scale[aria-pressed=true]{background:var(--cb-color-surface-raised);color:var(--cb-color-text-strong, var(--cb-color-text));box-shadow:0 1px 2px #0f172a1f}.cb-gantt__btn{border:1px solid var(--cb-color-border-strong);color:var(--cb-color-text)}.cb-gantt__btn:hover{background:var(--cb-color-surface-hover)}:is(.cb-gantt__scale,.cb-gantt__btn,.cb-gantt__toggle,.cb-gantt__name,.cb-gantt__unlink):focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-gantt__scroller{position:relative;overflow:auto;container-type:inline-size;border:1px solid var(--cb-color-border);border-radius:var(--cb-radius-lg, 12px);background:var(--cb-color-surface)}.cb-gantt__inner{--cb-gantt-grid-w: min(var(--cb-gantt-grid, 30rem), 60cqi);position:relative;width:max-content;min-width:100%}.cb-gantt__head{position:sticky;top:0;z-index:4;display:flex;height:52px;border-bottom:1px solid var(--cb-color-border);background:var(--cb-color-surface-subtle, var(--cb-color-surface))}.cb-gantt__head-grid{position:sticky;left:0;z-index:5;display:flex;flex:none;align-items:flex-end;width:var(--cb-gantt-grid-w);padding-bottom:.45rem;border-right:1px solid var(--cb-color-border);background:inherit}.cb-gantt__head-cell{flex:0 0 auto;box-sizing:border-box;padding:0 .5rem;overflow:hidden;color:var(--cb-color-text-muted);font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}.cb-gantt__head-cell.cb-gantt__col-name{padding-left:.75rem}.cb-gantt__col-name{flex:1 1 auto!important;min-width:6rem}.cb-gantt__col-start,.cb-gantt__col-end,.cb-gantt__col-duration{width:4.5rem}.cb-gantt__col-progress{width:4rem}.cb-gantt__col-assignee{width:6.5rem}.cb-gantt__head-scale{position:relative;flex:none}.cb-gantt__head-row{position:relative;height:26px}.cb-gantt__unit{position:absolute;top:0;bottom:0;display:flex;align-items:center;justify-content:center;overflow:hidden;border-left:1px solid var(--cb-color-border);color:var(--cb-color-text-muted);font-size:.6875rem;white-space:nowrap}.cb-gantt__unit--top{justify-content:flex-start;padding-left:.5rem;color:var(--cb-color-text);font-weight:var(--cb-font-weight-semibold, 600)}.cb-gantt__unit--weekend{background:var(--cb-color-surface-hover)}@container (max-width: 40rem){.cb-gantt__col-start,.cb-gantt__col-end,.cb-gantt__col-duration,.cb-gantt__col-progress,.cb-gantt__col-assignee{display:none}.cb-gantt__head-grid,.cb-gantt__row{overflow:hidden}}.cb-gantt__body{position:relative;display:flex}.cb-gantt__grid{position:sticky;left:0;z-index:3;flex:none;width:var(--cb-gantt-grid-w);border-right:1px solid var(--cb-color-border);background:var(--cb-color-surface)}.cb-gantt__row{display:flex;align-items:center;height:var(--cb-gantt-row);border-bottom:1px solid var(--cb-color-border)}.cb-gantt__row.cb-is-selected{background:color-mix(in srgb,var(--cb-color-primary-500) 9%,var(--cb-color-surface))}.cb-gantt__cell{flex:0 0 auto;box-sizing:border-box;padding:0 .5rem;overflow:hidden;color:var(--cb-color-text-muted);font-size:var(--cb-text-xs, .75rem);font-variant-numeric:tabular-nums;text-overflow:ellipsis;white-space:nowrap}.cb-gantt__cell.cb-gantt__col-name{display:flex;align-items:center;gap:.25rem;min-width:0;color:var(--cb-color-text);font-size:var(--cb-text-sm, .875rem)}.cb-gantt__toggle,.cb-gantt__toggle-space{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.4rem;height:1.4rem}.cb-gantt__toggle{padding:0;border:0;border-radius:var(--cb-radius-sm);background:transparent;color:var(--cb-color-text-muted);cursor:pointer}.cb-gantt__toggle:hover{background:var(--cb-color-surface-hover)}.cb-gantt__name{display:inline-flex;align-items:center;gap:.4rem;min-width:0;padding:.15rem .25rem;overflow:hidden;border:0;border-radius:var(--cb-radius-sm);background:transparent;color:inherit;font:inherit;text-align:start;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.cb-gantt__name--group{font-weight:var(--cb-font-weight-semibold, 600)}.cb-gantt__diamond-mini{flex:none;width:.55rem;height:.55rem;background:var(--cb-color-warning-500, #f59e0b);transform:rotate(45deg)}.cb-gantt__chart{position:relative;flex:none}.cb-gantt__col{position:absolute;top:0;bottom:0;border-left:1px solid color-mix(in srgb,var(--cb-color-border) 60%,transparent)}.cb-gantt__col--weekend{background:color-mix(in srgb,var(--cb-color-surface-hover) 70%,transparent)}.cb-gantt__stripe{position:absolute;left:0;right:0;height:var(--cb-gantt-row);border-bottom:1px solid var(--cb-color-border)}.cb-gantt__stripe.cb-is-selected{background:color-mix(in srgb,var(--cb-color-primary-500) 7%,transparent)}.cb-gantt__today{position:absolute;top:0;bottom:0;z-index:1;width:2px;margin-left:-1px;background:var(--cb-color-danger-500, #ef4444)}.cb-gantt__links{position:absolute;inset:0;z-index:1;overflow:visible;pointer-events:none}.cb-gantt__links marker path{fill:var(--cb-color-text-muted)}.cb-gantt__link{fill:none;stroke:var(--cb-color-text-muted);stroke-width:1.5}.cb-gantt__link.cb-is-selected{stroke:var(--cb-color-primary-600, var(--cb-color-primary-500));stroke-width:2.5}.cb-gantt__link--draft{stroke:var(--cb-color-primary-500);stroke-dasharray:4 3}.cb-gantt__link-hit{fill:none;stroke:transparent;stroke-width:10;pointer-events:stroke;cursor:pointer}:host(.cb-gantt--readonly) .cb-gantt__link-hit{cursor:default}.cb-gantt__unlink{position:absolute;z-index:3;display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;margin:-.625rem 0 0 -.625rem;padding:0;border:1px solid var(--cb-color-border-strong);border-radius:50%;background:var(--cb-color-surface-raised);color:var(--cb-color-danger-600, var(--cb-color-danger));cursor:pointer}.cb-gantt__bar{position:absolute;z-index:2;box-sizing:border-box;height:24px;margin-top:8px;border-radius:6px;background:color-mix(in srgb,var(--cb-gantt-color, var(--cb-gantt-bar)) 28%,var(--cb-color-surface));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--cb-gantt-color, var(--cb-gantt-bar)) 55%,transparent);cursor:grab;touch-action:none;-webkit-user-select:none;user-select:none}:host(.cb-gantt--readonly) .cb-gantt__bar{cursor:pointer}.cb-gantt__bar:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:2px}.cb-gantt__bar.cb-is-selected{box-shadow:inset 0 0 0 2px var(--cb-gantt-color, var(--cb-gantt-bar))}.cb-gantt__bar.cb-is-dragging{cursor:grabbing;opacity:.85}.cb-gantt__progress{position:absolute;inset:0 auto 0 0;border-radius:6px 0 0 6px;background:var(--cb-gantt-color, var(--cb-gantt-bar))}.cb-gantt__bar-label{position:relative;display:block;padding:0 .5rem;overflow:hidden;color:var(--cb-color-text);font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-medium, 500);line-height:24px;text-overflow:ellipsis;white-space:nowrap;mix-blend-mode:normal}.cb-gantt__bar--short .cb-gantt__bar-label{position:absolute;top:0;left:calc(100% + 18px);padding:0;overflow:visible}.cb-gantt__handle{position:absolute;top:0;bottom:0;width:8px;cursor:ew-resize}.cb-gantt__handle--start{left:0}.cb-gantt__handle--end{right:0}.cb-gantt__progress-handle{position:absolute;bottom:-6px;width:10px;height:10px;margin-left:-5px;border:2px solid var(--cb-color-surface);border-radius:50%;background:var(--cb-gantt-color, var(--cb-gantt-bar));cursor:col-resize;opacity:0}.cb-gantt__connector{position:absolute;top:50%;right:-14px;width:10px;height:10px;margin-top:-5px;border:2px solid var(--cb-gantt-color, var(--cb-gantt-bar));border-radius:50%;background:var(--cb-color-surface);cursor:crosshair;opacity:0}.cb-gantt__bar:hover :is(.cb-gantt__progress-handle,.cb-gantt__connector),.cb-gantt__bar.cb-is-selected :is(.cb-gantt__progress-handle,.cb-gantt__connector){opacity:1}@media(hover:none){.cb-gantt__progress-handle,.cb-gantt__connector{opacity:1}}.cb-gantt__bar--group{height:12px;margin-top:14px;border-radius:2px;background:var(--cb-color-text-muted);box-shadow:none}.cb-gantt__bar--group .cb-gantt__progress{border-radius:2px 0 0 2px;background:var(--cb-color-text)}.cb-gantt__bar--group .cb-gantt__bar-label{position:absolute;bottom:12px;left:0;padding:0;line-height:1.2}.cb-gantt__bar--milestone{width:18px;height:18px;margin-top:11px;background:transparent;box-shadow:none}.cb-gantt__bar--milestone.cb-is-selected{box-shadow:none}.cb-gantt__diamond{position:absolute;inset:2px;border-radius:3px;background:var(--cb-gantt-color, var(--cb-color-warning-500, #f59e0b));transform:rotate(45deg)}.cb-gantt__bar--milestone.cb-is-selected .cb-gantt__diamond{outline:2px solid var(--cb-color-text);outline-offset:1px}.cb-gantt__milestone-label{position:absolute;top:0;left:26px;color:var(--cb-color-text);font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-medium, 500);line-height:18px;white-space:nowrap}.cb-gantt__bar--milestone .cb-gantt__connector{right:-16px}.cb-gantt__empty{margin:0;padding:2rem;color:var(--cb-color-text-muted);text-align:center}.cb-gantt__sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.cb-gantt__bar:not(.cb-is-dragging){transition:left .12s ease,width .12s ease}}@media(forced-colors:active){.cb-gantt__bar,.cb-gantt__progress{forced-color-adjust:none;border:1px solid CanvasText}}\n"], dependencies: [{ kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
912
+ }
913
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbGantt, decorators: [{
914
+ type: Component,
915
+ args: [{ selector: 'cb-gantt', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [CbIcon], host: { class: 'cb-gantt', '[class.cb-gantt--readonly]': 'readonly()' }, template: `
916
+ @if (showToolbar()) {
917
+ <div class="cb-gantt__toolbar">
918
+ <div class="cb-gantt__scales" role="group" [attr.aria-label]="t().ganttScale">
919
+ @for (s of scales; track s) {
920
+ <button type="button" class="cb-gantt__scale" [attr.aria-pressed]="scale() === s" (click)="scale.set(s)">{{ scaleLabel(s) }}</button>
921
+ }
922
+ </div>
923
+ <button type="button" class="cb-gantt__btn" (click)="scrollToToday()">{{ t().today }}</button>
924
+ </div>
925
+ }
926
+
927
+ <div #scroller class="cb-gantt__scroller" [style.height]="height()" (pointermove)="onPointerMove($event)" (pointerup)="onPointerUp($event)" (pointercancel)="cancelDrag()">
928
+ <div class="cb-gantt__inner" [style.--cb-gantt-grid]="gridSize()">
929
+ <!-- Cabecera: columnas de la tabla y escala de tiempo -->
930
+ <div class="cb-gantt__head">
931
+ <div class="cb-gantt__head-grid" aria-hidden="true">
932
+ @for (col of columns(); track col) {
933
+ <span class="cb-gantt__head-cell" [class]="'cb-gantt__head-cell cb-gantt__col-' + col">{{ columnLabel(col) }}</span>
934
+ }
935
+ </div>
936
+ <div class="cb-gantt__head-scale" [style.width.px]="chartWidth()" aria-hidden="true">
937
+ <div class="cb-gantt__head-row">
938
+ @for (u of topUnits(); track u.key) {
939
+ <span class="cb-gantt__unit cb-gantt__unit--top" [style.left.px]="u.x" [style.width.px]="u.width">{{ u.label }}</span>
940
+ }
941
+ </div>
942
+ <div class="cb-gantt__head-row">
943
+ @for (u of units(); track u.key) {
944
+ <span class="cb-gantt__unit" [class.cb-gantt__unit--weekend]="u.weekend" [style.left.px]="u.x" [style.width.px]="u.width">{{ u.label }}</span>
945
+ }
946
+ </div>
947
+ </div>
948
+ </div>
949
+
950
+ <div class="cb-gantt__body" [style.height.px]="rows().length * row">
951
+ <!-- Tabla de tareas (árbol) -->
952
+ <div class="cb-gantt__grid" role="treegrid" [attr.aria-label]="ariaLabel() || t().ganttChart" [attr.aria-rowcount]="rows().length">
953
+ @for (r of rows(); track r.task.id; let i = $index) {
954
+ <div
955
+ class="cb-gantt__row"
956
+ role="row"
957
+ [class.cb-is-selected]="selected() === r.task.id"
958
+ [attr.aria-level]="r.level + 1"
959
+ [attr.aria-expanded]="r.children.length ? !collapsed().has(r.task.id) : null"
960
+ [attr.aria-rowindex]="i + 1"
961
+ [attr.aria-selected]="selected() === r.task.id"
962
+ >
963
+ @for (col of columns(); track col) {
964
+ @if (col === 'name') {
965
+ <span class="cb-gantt__cell cb-gantt__col-name" role="gridcell" [style.padding-left]="0.5 + r.level * 1.1 + 'rem'">
966
+ @if (r.children.length) {
967
+ <button
968
+ type="button"
969
+ class="cb-gantt__toggle"
970
+ [attr.aria-label]="fmt(collapsed().has(r.task.id) ? t().ganttExpand : t().ganttCollapse, r.task.name)"
971
+ [attr.aria-expanded]="!collapsed().has(r.task.id)"
972
+ (click)="toggle(r.task.id)"
973
+ >
974
+ <cb-icon [name]="collapsed().has(r.task.id) ? 'chevron-right' : 'chevron-down'" [size]="14" aria-hidden="true" />
975
+ </button>
976
+ } @else {
977
+ <span class="cb-gantt__toggle-space" aria-hidden="true"></span>
978
+ }
979
+ <button type="button" class="cb-gantt__name" [class.cb-gantt__name--group]="r.isGroup" (click)="focusBar(r.task.id)" (dblclick)="taskOpen.emit(r.task)">
980
+ @if (r.isMilestone) {
981
+ <span class="cb-gantt__diamond-mini" aria-hidden="true"></span>
982
+ }
983
+ {{ r.task.name }}
984
+ </button>
985
+ </span>
986
+ } @else {
987
+ <span [class]="'cb-gantt__cell cb-gantt__col-' + col" role="gridcell">{{ cellText(r, col) }}</span>
988
+ }
989
+ }
990
+ </div>
991
+ }
992
+ </div>
993
+
994
+ <!-- Diagrama -->
995
+ <div #chart class="cb-gantt__chart" [style.width.px]="chartWidth()">
996
+ @for (u of units(); track u.key) {
997
+ <span class="cb-gantt__col" [class.cb-gantt__col--weekend]="u.weekend" [style.left.px]="u.x" [style.width.px]="u.width" aria-hidden="true"></span>
998
+ }
999
+ @for (r of rows(); track r.task.id; let i = $index) {
1000
+ <span class="cb-gantt__stripe" [class.cb-is-selected]="selected() === r.task.id" [style.top.px]="i * row" aria-hidden="true"></span>
1001
+ }
1002
+ @if (todayX() !== null) {
1003
+ <span class="cb-gantt__today" [style.left.px]="todayX()" aria-hidden="true"></span>
1004
+ }
1005
+
1006
+ <svg class="cb-gantt__links" [attr.width]="chartWidth()" [attr.height]="rows().length * row" aria-hidden="true">
1007
+ <defs>
1008
+ <marker [attr.id]="uid + '-arrow'" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
1009
+ <path d="M0 0 L8 4 L0 8 z" />
1010
+ </marker>
1011
+ </defs>
1012
+ @for (l of links(); track l.key) {
1013
+ <path class="cb-gantt__link-hit" [attr.d]="l.path" (click)="selectLink(l)" />
1014
+ <path class="cb-gantt__link" [class.cb-is-selected]="selectedLink()?.key === l.key" [attr.d]="l.path" [attr.marker-end]="'url(#' + uid + '-arrow)'" />
1015
+ }
1016
+ @if (linkLine(); as line) {
1017
+ <path class="cb-gantt__link cb-gantt__link--draft" [attr.d]="line" />
1018
+ }
1019
+ </svg>
1020
+
1021
+ @if (selectedLink(); as sl) {
1022
+ <button
1023
+ type="button"
1024
+ class="cb-gantt__unlink"
1025
+ [style.left.px]="sl.mid.x"
1026
+ [style.top.px]="sl.mid.y"
1027
+ [attr.aria-label]="fmt(t().ganttRemoveLink, sl.fromName, sl.toName)"
1028
+ [attr.title]="fmt(t().ganttRemoveLink, sl.fromName, sl.toName)"
1029
+ (click)="removeLink(sl.from, sl.to)"
1030
+ >
1031
+ <cb-icon name="x" [size]="12" aria-hidden="true" />
1032
+ </button>
1033
+ }
1034
+
1035
+ @for (b of bars(); track b.row.task.id) {
1036
+ <div
1037
+ class="cb-gantt__bar"
1038
+ role="button"
1039
+ tabindex="0"
1040
+ [attr.data-gantt-id]="b.row.task.id"
1041
+ [class.cb-gantt__bar--group]="b.row.isGroup"
1042
+ [class.cb-gantt__bar--milestone]="b.row.isMilestone"
1043
+ [class.cb-gantt__bar--short]="!b.row.isMilestone && !b.row.isGroup && b.width < 72"
1044
+ [class.cb-is-selected]="selected() === b.row.task.id"
1045
+ [class.cb-is-dragging]="preview()?.id === b.row.task.id"
1046
+ [style.left.px]="b.x"
1047
+ [style.top.px]="b.y"
1048
+ [style.width.px]="b.width"
1049
+ [style.--cb-gantt-color]="b.row.task.color || null"
1050
+ [attr.aria-label]="barLabel(b)"
1051
+ [attr.aria-describedby]="readonly() ? null : uid + '-help'"
1052
+ (pointerdown)="onPointerDown($event, b)"
1053
+ (keydown)="onBarKeydown($event, b.row)"
1054
+ (click)="selected.set(b.row.task.id)"
1055
+ (dblclick)="taskOpen.emit(b.row.task)"
1056
+ >
1057
+ @if (!b.row.isMilestone) {
1058
+ <span class="cb-gantt__progress" [style.width.%]="b.progress" aria-hidden="true"></span>
1059
+ <span class="cb-gantt__bar-label" aria-hidden="true">{{ b.row.task.name }}</span>
1060
+ @if (!readonly() && !b.row.isGroup) {
1061
+ <span class="cb-gantt__handle cb-gantt__handle--start" data-mode="start" aria-hidden="true"></span>
1062
+ <span class="cb-gantt__handle cb-gantt__handle--end" data-mode="end" aria-hidden="true"></span>
1063
+ <span class="cb-gantt__progress-handle" data-mode="progress" [style.left.%]="b.progress" aria-hidden="true"></span>
1064
+ }
1065
+ } @else {
1066
+ <span class="cb-gantt__diamond" aria-hidden="true"></span>
1067
+ <span class="cb-gantt__milestone-label" aria-hidden="true">{{ b.row.task.name }}</span>
1068
+ }
1069
+ @if (!readonly()) {
1070
+ <span class="cb-gantt__connector" data-mode="link" aria-hidden="true"></span>
1071
+ }
1072
+ </div>
1073
+ }
1074
+ </div>
1075
+ </div>
1076
+ </div>
1077
+ @if (!rows().length) {
1078
+ <p class="cb-gantt__empty">{{ emptyMessage() ?? t().noData }}</p>
1079
+ }
1080
+ </div>
1081
+ <p class="cb-gantt__sr" [id]="uid + '-help'">{{ t().ganttInstructions }}</p>
1082
+ <div class="cb-gantt__sr" role="status">{{ announcement() }}</div>
1083
+ `, styles: [":host{--cb-gantt-row: 40px;--cb-gantt-bar: var(--cb-color-primary-500);--cb-gantt-bar-bg: color-mix(in srgb, var(--cb-gantt-bar) 28%, var(--cb-color-surface));display:flex;flex-direction:column;gap:var(--cb-space-2, .5rem);width:100%;min-width:0;color:var(--cb-color-text);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm, .875rem)}.cb-gantt__toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.cb-gantt__scales{display:inline-flex;padding:2px;border-radius:var(--cb-radius-md);background:var(--cb-color-surface-hover)}.cb-gantt__scale,.cb-gantt__btn{padding:.3rem .75rem;border:0;border-radius:calc(var(--cb-radius-md) - 2px);background:transparent;color:var(--cb-color-text-muted);font:inherit;font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-medium, 500);cursor:pointer}.cb-gantt__scale[aria-pressed=true]{background:var(--cb-color-surface-raised);color:var(--cb-color-text-strong, var(--cb-color-text));box-shadow:0 1px 2px #0f172a1f}.cb-gantt__btn{border:1px solid var(--cb-color-border-strong);color:var(--cb-color-text)}.cb-gantt__btn:hover{background:var(--cb-color-surface-hover)}:is(.cb-gantt__scale,.cb-gantt__btn,.cb-gantt__toggle,.cb-gantt__name,.cb-gantt__unlink):focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-gantt__scroller{position:relative;overflow:auto;container-type:inline-size;border:1px solid var(--cb-color-border);border-radius:var(--cb-radius-lg, 12px);background:var(--cb-color-surface)}.cb-gantt__inner{--cb-gantt-grid-w: min(var(--cb-gantt-grid, 30rem), 60cqi);position:relative;width:max-content;min-width:100%}.cb-gantt__head{position:sticky;top:0;z-index:4;display:flex;height:52px;border-bottom:1px solid var(--cb-color-border);background:var(--cb-color-surface-subtle, var(--cb-color-surface))}.cb-gantt__head-grid{position:sticky;left:0;z-index:5;display:flex;flex:none;align-items:flex-end;width:var(--cb-gantt-grid-w);padding-bottom:.45rem;border-right:1px solid var(--cb-color-border);background:inherit}.cb-gantt__head-cell{flex:0 0 auto;box-sizing:border-box;padding:0 .5rem;overflow:hidden;color:var(--cb-color-text-muted);font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-semibold, 600);text-overflow:ellipsis;white-space:nowrap}.cb-gantt__head-cell.cb-gantt__col-name{padding-left:.75rem}.cb-gantt__col-name{flex:1 1 auto!important;min-width:6rem}.cb-gantt__col-start,.cb-gantt__col-end,.cb-gantt__col-duration{width:4.5rem}.cb-gantt__col-progress{width:4rem}.cb-gantt__col-assignee{width:6.5rem}.cb-gantt__head-scale{position:relative;flex:none}.cb-gantt__head-row{position:relative;height:26px}.cb-gantt__unit{position:absolute;top:0;bottom:0;display:flex;align-items:center;justify-content:center;overflow:hidden;border-left:1px solid var(--cb-color-border);color:var(--cb-color-text-muted);font-size:.6875rem;white-space:nowrap}.cb-gantt__unit--top{justify-content:flex-start;padding-left:.5rem;color:var(--cb-color-text);font-weight:var(--cb-font-weight-semibold, 600)}.cb-gantt__unit--weekend{background:var(--cb-color-surface-hover)}@container (max-width: 40rem){.cb-gantt__col-start,.cb-gantt__col-end,.cb-gantt__col-duration,.cb-gantt__col-progress,.cb-gantt__col-assignee{display:none}.cb-gantt__head-grid,.cb-gantt__row{overflow:hidden}}.cb-gantt__body{position:relative;display:flex}.cb-gantt__grid{position:sticky;left:0;z-index:3;flex:none;width:var(--cb-gantt-grid-w);border-right:1px solid var(--cb-color-border);background:var(--cb-color-surface)}.cb-gantt__row{display:flex;align-items:center;height:var(--cb-gantt-row);border-bottom:1px solid var(--cb-color-border)}.cb-gantt__row.cb-is-selected{background:color-mix(in srgb,var(--cb-color-primary-500) 9%,var(--cb-color-surface))}.cb-gantt__cell{flex:0 0 auto;box-sizing:border-box;padding:0 .5rem;overflow:hidden;color:var(--cb-color-text-muted);font-size:var(--cb-text-xs, .75rem);font-variant-numeric:tabular-nums;text-overflow:ellipsis;white-space:nowrap}.cb-gantt__cell.cb-gantt__col-name{display:flex;align-items:center;gap:.25rem;min-width:0;color:var(--cb-color-text);font-size:var(--cb-text-sm, .875rem)}.cb-gantt__toggle,.cb-gantt__toggle-space{display:inline-flex;flex:none;align-items:center;justify-content:center;width:1.4rem;height:1.4rem}.cb-gantt__toggle{padding:0;border:0;border-radius:var(--cb-radius-sm);background:transparent;color:var(--cb-color-text-muted);cursor:pointer}.cb-gantt__toggle:hover{background:var(--cb-color-surface-hover)}.cb-gantt__name{display:inline-flex;align-items:center;gap:.4rem;min-width:0;padding:.15rem .25rem;overflow:hidden;border:0;border-radius:var(--cb-radius-sm);background:transparent;color:inherit;font:inherit;text-align:start;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}.cb-gantt__name--group{font-weight:var(--cb-font-weight-semibold, 600)}.cb-gantt__diamond-mini{flex:none;width:.55rem;height:.55rem;background:var(--cb-color-warning-500, #f59e0b);transform:rotate(45deg)}.cb-gantt__chart{position:relative;flex:none}.cb-gantt__col{position:absolute;top:0;bottom:0;border-left:1px solid color-mix(in srgb,var(--cb-color-border) 60%,transparent)}.cb-gantt__col--weekend{background:color-mix(in srgb,var(--cb-color-surface-hover) 70%,transparent)}.cb-gantt__stripe{position:absolute;left:0;right:0;height:var(--cb-gantt-row);border-bottom:1px solid var(--cb-color-border)}.cb-gantt__stripe.cb-is-selected{background:color-mix(in srgb,var(--cb-color-primary-500) 7%,transparent)}.cb-gantt__today{position:absolute;top:0;bottom:0;z-index:1;width:2px;margin-left:-1px;background:var(--cb-color-danger-500, #ef4444)}.cb-gantt__links{position:absolute;inset:0;z-index:1;overflow:visible;pointer-events:none}.cb-gantt__links marker path{fill:var(--cb-color-text-muted)}.cb-gantt__link{fill:none;stroke:var(--cb-color-text-muted);stroke-width:1.5}.cb-gantt__link.cb-is-selected{stroke:var(--cb-color-primary-600, var(--cb-color-primary-500));stroke-width:2.5}.cb-gantt__link--draft{stroke:var(--cb-color-primary-500);stroke-dasharray:4 3}.cb-gantt__link-hit{fill:none;stroke:transparent;stroke-width:10;pointer-events:stroke;cursor:pointer}:host(.cb-gantt--readonly) .cb-gantt__link-hit{cursor:default}.cb-gantt__unlink{position:absolute;z-index:3;display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;margin:-.625rem 0 0 -.625rem;padding:0;border:1px solid var(--cb-color-border-strong);border-radius:50%;background:var(--cb-color-surface-raised);color:var(--cb-color-danger-600, var(--cb-color-danger));cursor:pointer}.cb-gantt__bar{position:absolute;z-index:2;box-sizing:border-box;height:24px;margin-top:8px;border-radius:6px;background:color-mix(in srgb,var(--cb-gantt-color, var(--cb-gantt-bar)) 28%,var(--cb-color-surface));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--cb-gantt-color, var(--cb-gantt-bar)) 55%,transparent);cursor:grab;touch-action:none;-webkit-user-select:none;user-select:none}:host(.cb-gantt--readonly) .cb-gantt__bar{cursor:pointer}.cb-gantt__bar:focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:2px}.cb-gantt__bar.cb-is-selected{box-shadow:inset 0 0 0 2px var(--cb-gantt-color, var(--cb-gantt-bar))}.cb-gantt__bar.cb-is-dragging{cursor:grabbing;opacity:.85}.cb-gantt__progress{position:absolute;inset:0 auto 0 0;border-radius:6px 0 0 6px;background:var(--cb-gantt-color, var(--cb-gantt-bar))}.cb-gantt__bar-label{position:relative;display:block;padding:0 .5rem;overflow:hidden;color:var(--cb-color-text);font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-medium, 500);line-height:24px;text-overflow:ellipsis;white-space:nowrap;mix-blend-mode:normal}.cb-gantt__bar--short .cb-gantt__bar-label{position:absolute;top:0;left:calc(100% + 18px);padding:0;overflow:visible}.cb-gantt__handle{position:absolute;top:0;bottom:0;width:8px;cursor:ew-resize}.cb-gantt__handle--start{left:0}.cb-gantt__handle--end{right:0}.cb-gantt__progress-handle{position:absolute;bottom:-6px;width:10px;height:10px;margin-left:-5px;border:2px solid var(--cb-color-surface);border-radius:50%;background:var(--cb-gantt-color, var(--cb-gantt-bar));cursor:col-resize;opacity:0}.cb-gantt__connector{position:absolute;top:50%;right:-14px;width:10px;height:10px;margin-top:-5px;border:2px solid var(--cb-gantt-color, var(--cb-gantt-bar));border-radius:50%;background:var(--cb-color-surface);cursor:crosshair;opacity:0}.cb-gantt__bar:hover :is(.cb-gantt__progress-handle,.cb-gantt__connector),.cb-gantt__bar.cb-is-selected :is(.cb-gantt__progress-handle,.cb-gantt__connector){opacity:1}@media(hover:none){.cb-gantt__progress-handle,.cb-gantt__connector{opacity:1}}.cb-gantt__bar--group{height:12px;margin-top:14px;border-radius:2px;background:var(--cb-color-text-muted);box-shadow:none}.cb-gantt__bar--group .cb-gantt__progress{border-radius:2px 0 0 2px;background:var(--cb-color-text)}.cb-gantt__bar--group .cb-gantt__bar-label{position:absolute;bottom:12px;left:0;padding:0;line-height:1.2}.cb-gantt__bar--milestone{width:18px;height:18px;margin-top:11px;background:transparent;box-shadow:none}.cb-gantt__bar--milestone.cb-is-selected{box-shadow:none}.cb-gantt__diamond{position:absolute;inset:2px;border-radius:3px;background:var(--cb-gantt-color, var(--cb-color-warning-500, #f59e0b));transform:rotate(45deg)}.cb-gantt__bar--milestone.cb-is-selected .cb-gantt__diamond{outline:2px solid var(--cb-color-text);outline-offset:1px}.cb-gantt__milestone-label{position:absolute;top:0;left:26px;color:var(--cb-color-text);font-size:var(--cb-text-xs, .75rem);font-weight:var(--cb-font-weight-medium, 500);line-height:18px;white-space:nowrap}.cb-gantt__bar--milestone .cb-gantt__connector{right:-16px}.cb-gantt__empty{margin:0;padding:2rem;color:var(--cb-color-text-muted);text-align:center}.cb-gantt__sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}@media(prefers-reduced-motion:no-preference){.cb-gantt__bar:not(.cb-is-dragging){transition:left .12s ease,width .12s ease}}@media(forced-colors:active){.cb-gantt__bar,.cb-gantt__progress{forced-color-adjust:none;border:1px solid CanvasText}}\n"] }]
1084
+ }], ctorParameters: () => [], propDecorators: { tasks: [{ type: i0.Input, args: [{ isSignal: true, alias: "tasks", required: false }] }, { type: i0.Output, args: ["tasksChange"] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }, { type: i0.Output, args: ["scaleChange"] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], gridWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "gridWidth", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], autoSchedule: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSchedule", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], taskChange: [{ type: i0.Output, args: ["taskChange"] }], taskOpen: [{ type: i0.Output, args: ["taskOpen"] }], linkAdd: [{ type: i0.Output, args: ["linkAdd"] }], linkRemove: [{ type: i0.Output, args: ["linkRemove"] }], scroller: [{ type: i0.ViewChild, args: ['scroller', { isSignal: true }] }], chart: [{ type: i0.ViewChild, args: ['chart', { isSignal: true }] }] } });
1085
+
1086
+ /*
1087
+ * Public API Surface de @caribeng/ui/gantt
1088
+ */
1089
+
1090
+ /**
1091
+ * Generated bundle index. Do not edit.
1092
+ */
1093
+
1094
+ export { CbGantt, autoSchedule as cbGanttAutoSchedule, canLink as cbGanttCanLink };