@malva-ui/core 0.1.13 → 0.1.14

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 (1618) hide show
  1. package/AGENTS.md +4 -1
  2. package/README.md +15 -0
  3. package/docs/ai/avatar.md +2 -0
  4. package/docs/ai/breadcrumb.md +67 -7
  5. package/docs/ai/button.md +74 -19
  6. package/docs/ai/card.md +8 -6
  7. package/docs/ai/chat.md +59 -45
  8. package/docs/ai/checkbox.md +12 -0
  9. package/docs/ai/combobox.md +18 -2
  10. package/docs/ai/copy-to-clipboard.md +1 -1
  11. package/docs/ai/core.md +15 -0
  12. package/docs/ai/data-table.md +89 -54
  13. package/docs/ai/dialog.md +76 -67
  14. package/docs/ai/drawer.md +15 -12
  15. package/docs/ai/dropdown.md +24 -19
  16. package/docs/ai/empty-state.md +3 -3
  17. package/docs/ai/filter.md +24 -5
  18. package/docs/ai/form-utils.md +160 -5
  19. package/docs/ai/icon-toggle.md +160 -0
  20. package/docs/ai/input.md +30 -0
  21. package/docs/ai/layout.md +23 -0
  22. package/docs/ai/list.md +10 -6
  23. package/docs/ai/menu.md +75 -1
  24. package/docs/ai/page.md +220 -60
  25. package/docs/ai/radio.md +9 -0
  26. package/docs/ai/scrollbar.md +30 -8
  27. package/docs/ai/segmented.md +35 -35
  28. package/docs/ai/select.md +30 -5
  29. package/docs/ai/sidebar.md +45 -27
  30. package/docs/ai/switch.md +114 -19
  31. package/docs/ai/table.md +69 -0
  32. package/docs/ai/tabs.md +2 -1
  33. package/docs/ai/tile.md +311 -85
  34. package/docs/ai/timeline.md +63 -39
  35. package/docs/ai/tokenizer.md +21 -5
  36. package/docs/ai/tooltip.md +5 -5
  37. package/docs/ai/view-variant.md +75 -0
  38. package/fesm2022/malva-ui-core-accordion.mjs +167 -0
  39. package/fesm2022/malva-ui-core-accordion.mjs.map +1 -0
  40. package/fesm2022/malva-ui-core-action-bar.mjs +111 -0
  41. package/fesm2022/malva-ui-core-action-bar.mjs.map +1 -0
  42. package/fesm2022/malva-ui-core-alert.mjs +173 -0
  43. package/fesm2022/malva-ui-core-alert.mjs.map +1 -0
  44. package/fesm2022/malva-ui-core-autocomplete.mjs +775 -0
  45. package/fesm2022/malva-ui-core-autocomplete.mjs.map +1 -0
  46. package/fesm2022/malva-ui-core-avatar-group.mjs +224 -0
  47. package/fesm2022/malva-ui-core-avatar-group.mjs.map +1 -0
  48. package/fesm2022/malva-ui-core-avatar.mjs +247 -0
  49. package/fesm2022/malva-ui-core-avatar.mjs.map +1 -0
  50. package/fesm2022/malva-ui-core-badge.mjs +122 -0
  51. package/fesm2022/malva-ui-core-badge.mjs.map +1 -0
  52. package/fesm2022/malva-ui-core-bottom-nav.mjs +161 -0
  53. package/fesm2022/malva-ui-core-bottom-nav.mjs.map +1 -0
  54. package/fesm2022/malva-ui-core-breadcrumb.mjs +494 -0
  55. package/fesm2022/malva-ui-core-breadcrumb.mjs.map +1 -0
  56. package/fesm2022/malva-ui-core-button.mjs +406 -0
  57. package/fesm2022/malva-ui-core-button.mjs.map +1 -0
  58. package/fesm2022/malva-ui-core-calendar.mjs +938 -0
  59. package/fesm2022/malva-ui-core-calendar.mjs.map +1 -0
  60. package/fesm2022/malva-ui-core-card.mjs +164 -0
  61. package/fesm2022/malva-ui-core-card.mjs.map +1 -0
  62. package/fesm2022/malva-ui-core-chat.mjs +825 -0
  63. package/fesm2022/malva-ui-core-chat.mjs.map +1 -0
  64. package/fesm2022/malva-ui-core-checkbox.mjs +272 -0
  65. package/fesm2022/malva-ui-core-checkbox.mjs.map +1 -0
  66. package/fesm2022/malva-ui-core-chip.mjs +176 -0
  67. package/fesm2022/malva-ui-core-chip.mjs.map +1 -0
  68. package/fesm2022/malva-ui-core-color-picker.mjs +1204 -0
  69. package/fesm2022/malva-ui-core-color-picker.mjs.map +1 -0
  70. package/fesm2022/malva-ui-core-combobox.mjs +945 -0
  71. package/fesm2022/malva-ui-core-combobox.mjs.map +1 -0
  72. package/fesm2022/malva-ui-core-copy-to-clipboard.mjs +255 -0
  73. package/fesm2022/malva-ui-core-copy-to-clipboard.mjs.map +1 -0
  74. package/fesm2022/malva-ui-core-data-table.mjs +2696 -0
  75. package/fesm2022/malva-ui-core-data-table.mjs.map +1 -0
  76. package/fesm2022/malva-ui-core-date-range-picker.mjs +276 -0
  77. package/fesm2022/malva-ui-core-date-range-picker.mjs.map +1 -0
  78. package/fesm2022/malva-ui-core-day-picker.mjs +131 -0
  79. package/fesm2022/malva-ui-core-day-picker.mjs.map +1 -0
  80. package/fesm2022/malva-ui-core-dialog-routable-dialog-CvjXMtlD.mjs +94 -0
  81. package/fesm2022/malva-ui-core-dialog-routable-dialog-CvjXMtlD.mjs.map +1 -0
  82. package/fesm2022/malva-ui-core-dialog.mjs +1223 -0
  83. package/fesm2022/malva-ui-core-dialog.mjs.map +1 -0
  84. package/fesm2022/malva-ui-core-divider.mjs +80 -0
  85. package/fesm2022/malva-ui-core-divider.mjs.map +1 -0
  86. package/fesm2022/malva-ui-core-drawer-routable-drawer-qUk6Etnx.mjs +94 -0
  87. package/fesm2022/malva-ui-core-drawer-routable-drawer-qUk6Etnx.mjs.map +1 -0
  88. package/fesm2022/malva-ui-core-drawer.mjs +814 -0
  89. package/fesm2022/malva-ui-core-drawer.mjs.map +1 -0
  90. package/fesm2022/malva-ui-core-dropdown.mjs +994 -0
  91. package/fesm2022/malva-ui-core-dropdown.mjs.map +1 -0
  92. package/fesm2022/malva-ui-core-empty-state.mjs +50 -0
  93. package/fesm2022/malva-ui-core-empty-state.mjs.map +1 -0
  94. package/fesm2022/malva-ui-core-expand.mjs +130 -0
  95. package/fesm2022/malva-ui-core-expand.mjs.map +1 -0
  96. package/fesm2022/malva-ui-core-file-upload.mjs +451 -0
  97. package/fesm2022/malva-ui-core-file-upload.mjs.map +1 -0
  98. package/fesm2022/malva-ui-core-filter.mjs +1627 -0
  99. package/fesm2022/malva-ui-core-filter.mjs.map +1 -0
  100. package/fesm2022/malva-ui-core-form-utils-testing.mjs +39 -0
  101. package/fesm2022/malva-ui-core-form-utils-testing.mjs.map +1 -0
  102. package/fesm2022/malva-ui-core-form-utils.mjs +977 -0
  103. package/fesm2022/malva-ui-core-form-utils.mjs.map +1 -0
  104. package/fesm2022/malva-ui-core-form.mjs +283 -0
  105. package/fesm2022/malva-ui-core-form.mjs.map +1 -0
  106. package/fesm2022/malva-ui-core-icon-toggle.mjs +120 -0
  107. package/fesm2022/malva-ui-core-icon-toggle.mjs.map +1 -0
  108. package/fesm2022/malva-ui-core-input.mjs +375 -0
  109. package/fesm2022/malva-ui-core-input.mjs.map +1 -0
  110. package/fesm2022/malva-ui-core-kbd.mjs +131 -0
  111. package/fesm2022/malva-ui-core-kbd.mjs.map +1 -0
  112. package/fesm2022/malva-ui-core-layout.mjs +212 -0
  113. package/fesm2022/malva-ui-core-layout.mjs.map +1 -0
  114. package/fesm2022/malva-ui-core-link.mjs +89 -0
  115. package/fesm2022/malva-ui-core-link.mjs.map +1 -0
  116. package/fesm2022/malva-ui-core-list.mjs +413 -0
  117. package/fesm2022/malva-ui-core-list.mjs.map +1 -0
  118. package/fesm2022/malva-ui-core-loader.mjs +141 -0
  119. package/fesm2022/malva-ui-core-loader.mjs.map +1 -0
  120. package/fesm2022/malva-ui-core-menu.mjs +2540 -0
  121. package/fesm2022/malva-ui-core-menu.mjs.map +1 -0
  122. package/fesm2022/malva-ui-core-notification.mjs +201 -0
  123. package/fesm2022/malva-ui-core-notification.mjs.map +1 -0
  124. package/fesm2022/malva-ui-core-number-input.mjs +404 -0
  125. package/fesm2022/malva-ui-core-number-input.mjs.map +1 -0
  126. package/fesm2022/malva-ui-core-page.mjs +1898 -0
  127. package/fesm2022/malva-ui-core-page.mjs.map +1 -0
  128. package/fesm2022/malva-ui-core-pagination.mjs +458 -0
  129. package/fesm2022/malva-ui-core-pagination.mjs.map +1 -0
  130. package/fesm2022/malva-ui-core-pin-input.mjs +405 -0
  131. package/fesm2022/malva-ui-core-pin-input.mjs.map +1 -0
  132. package/fesm2022/malva-ui-core-popup.mjs +1488 -0
  133. package/fesm2022/malva-ui-core-popup.mjs.map +1 -0
  134. package/fesm2022/malva-ui-core-progress.mjs +109 -0
  135. package/fesm2022/malva-ui-core-progress.mjs.map +1 -0
  136. package/fesm2022/malva-ui-core-radio.mjs +317 -0
  137. package/fesm2022/malva-ui-core-radio.mjs.map +1 -0
  138. package/fesm2022/malva-ui-core-rating.mjs +236 -0
  139. package/fesm2022/malva-ui-core-rating.mjs.map +1 -0
  140. package/fesm2022/malva-ui-core-scrollbar.mjs +430 -0
  141. package/fesm2022/malva-ui-core-scrollbar.mjs.map +1 -0
  142. package/fesm2022/malva-ui-core-search-field.mjs +578 -0
  143. package/fesm2022/malva-ui-core-search-field.mjs.map +1 -0
  144. package/fesm2022/malva-ui-core-segmented.mjs +458 -0
  145. package/fesm2022/malva-ui-core-segmented.mjs.map +1 -0
  146. package/fesm2022/malva-ui-core-select.mjs +855 -0
  147. package/fesm2022/malva-ui-core-select.mjs.map +1 -0
  148. package/fesm2022/malva-ui-core-sidebar.mjs +1504 -0
  149. package/fesm2022/malva-ui-core-sidebar.mjs.map +1 -0
  150. package/fesm2022/malva-ui-core-skeleton.mjs +85 -0
  151. package/fesm2022/malva-ui-core-skeleton.mjs.map +1 -0
  152. package/fesm2022/malva-ui-core-slider.mjs +514 -0
  153. package/fesm2022/malva-ui-core-slider.mjs.map +1 -0
  154. package/fesm2022/malva-ui-core-split-pane.mjs +359 -0
  155. package/fesm2022/malva-ui-core-split-pane.mjs.map +1 -0
  156. package/fesm2022/malva-ui-core-status-indicator.mjs +78 -0
  157. package/fesm2022/malva-ui-core-status-indicator.mjs.map +1 -0
  158. package/fesm2022/malva-ui-core-stepper.mjs +332 -0
  159. package/fesm2022/malva-ui-core-stepper.mjs.map +1 -0
  160. package/fesm2022/malva-ui-core-switch.mjs +272 -0
  161. package/fesm2022/malva-ui-core-switch.mjs.map +1 -0
  162. package/fesm2022/malva-ui-core-table.mjs +79 -0
  163. package/fesm2022/malva-ui-core-table.mjs.map +1 -0
  164. package/fesm2022/malva-ui-core-tabs.mjs +794 -0
  165. package/fesm2022/malva-ui-core-tabs.mjs.map +1 -0
  166. package/fesm2022/malva-ui-core-textarea.mjs +201 -0
  167. package/fesm2022/malva-ui-core-textarea.mjs.map +1 -0
  168. package/fesm2022/malva-ui-core-tile.mjs +1404 -0
  169. package/fesm2022/malva-ui-core-tile.mjs.map +1 -0
  170. package/fesm2022/malva-ui-core-time-picker.mjs +533 -0
  171. package/fesm2022/malva-ui-core-time-picker.mjs.map +1 -0
  172. package/fesm2022/malva-ui-core-timeline.mjs +216 -0
  173. package/fesm2022/malva-ui-core-timeline.mjs.map +1 -0
  174. package/fesm2022/malva-ui-core-title.mjs +178 -0
  175. package/fesm2022/malva-ui-core-title.mjs.map +1 -0
  176. package/fesm2022/malva-ui-core-toast.mjs +749 -0
  177. package/fesm2022/malva-ui-core-toast.mjs.map +1 -0
  178. package/fesm2022/malva-ui-core-tokenizer.mjs +502 -0
  179. package/fesm2022/malva-ui-core-tokenizer.mjs.map +1 -0
  180. package/fesm2022/malva-ui-core-toolbar.mjs +141 -0
  181. package/fesm2022/malva-ui-core-toolbar.mjs.map +1 -0
  182. package/fesm2022/malva-ui-core-tooltip.mjs +432 -0
  183. package/fesm2022/malva-ui-core-tooltip.mjs.map +1 -0
  184. package/fesm2022/malva-ui-core-tree.mjs +505 -0
  185. package/fesm2022/malva-ui-core-tree.mjs.map +1 -0
  186. package/fesm2022/malva-ui-core-view-variant.mjs +292 -0
  187. package/fesm2022/malva-ui-core-view-variant.mjs.map +1 -0
  188. package/fesm2022/malva-ui-core.mjs +77 -0
  189. package/fesm2022/malva-ui-core.mjs.map +1 -0
  190. package/package.json +179 -156
  191. package/styles/malva-ui.css +253 -220
  192. package/styles/tokens.md +174 -173
  193. package/table/README.md +46 -0
  194. package/types/malva-ui-core-accordion.d.ts +121 -0
  195. package/types/malva-ui-core-action-bar.d.ts +82 -0
  196. package/types/malva-ui-core-alert.d.ts +131 -0
  197. package/types/malva-ui-core-autocomplete.d.ts +301 -0
  198. package/types/malva-ui-core-avatar-group.d.ts +119 -0
  199. package/types/malva-ui-core-avatar.d.ts +156 -0
  200. package/types/malva-ui-core-badge.d.ts +97 -0
  201. package/types/malva-ui-core-bottom-nav.d.ts +104 -0
  202. package/types/malva-ui-core-breadcrumb.d.ts +308 -0
  203. package/types/malva-ui-core-button.d.ts +194 -0
  204. package/types/malva-ui-core-calendar.d.ts +339 -0
  205. package/types/malva-ui-core-card.d.ts +88 -0
  206. package/types/malva-ui-core-chat.d.ts +375 -0
  207. package/types/malva-ui-core-checkbox.d.ts +158 -0
  208. package/types/malva-ui-core-chip.d.ts +128 -0
  209. package/types/malva-ui-core-color-picker.d.ts +442 -0
  210. package/types/malva-ui-core-combobox.d.ts +419 -0
  211. package/types/malva-ui-core-copy-to-clipboard.d.ts +148 -0
  212. package/types/malva-ui-core-data-table.d.ts +1074 -0
  213. package/types/malva-ui-core-date-range-picker.d.ts +149 -0
  214. package/types/malva-ui-core-day-picker.d.ts +55 -0
  215. package/types/malva-ui-core-dialog.d.ts +597 -0
  216. package/types/malva-ui-core-divider.d.ts +68 -0
  217. package/types/malva-ui-core-drawer.d.ts +333 -0
  218. package/types/malva-ui-core-dropdown.d.ts +592 -0
  219. package/types/malva-ui-core-empty-state.d.ts +37 -0
  220. package/types/malva-ui-core-expand.d.ts +102 -0
  221. package/types/malva-ui-core-file-upload.d.ts +267 -0
  222. package/types/malva-ui-core-filter.d.ts +552 -0
  223. package/types/malva-ui-core-form-utils-testing.d.ts +50 -0
  224. package/types/malva-ui-core-form-utils.d.ts +579 -0
  225. package/types/malva-ui-core-form.d.ts +176 -0
  226. package/types/malva-ui-core-icon-toggle.d.ts +80 -0
  227. package/types/malva-ui-core-input.d.ts +262 -0
  228. package/types/malva-ui-core-kbd.d.ts +56 -0
  229. package/types/malva-ui-core-layout.d.ts +70 -0
  230. package/types/malva-ui-core-link.d.ts +28 -0
  231. package/types/malva-ui-core-list.d.ts +252 -0
  232. package/types/malva-ui-core-loader.d.ts +89 -0
  233. package/types/malva-ui-core-menu.d.ts +954 -0
  234. package/types/malva-ui-core-notification.d.ts +122 -0
  235. package/types/malva-ui-core-number-input.d.ts +167 -0
  236. package/types/malva-ui-core-page.d.ts +799 -0
  237. package/types/malva-ui-core-pagination.d.ts +261 -0
  238. package/types/malva-ui-core-pin-input.d.ts +203 -0
  239. package/types/malva-ui-core-popup.d.ts +834 -0
  240. package/types/malva-ui-core-progress.d.ts +73 -0
  241. package/types/malva-ui-core-radio.d.ts +130 -0
  242. package/types/malva-ui-core-rating.d.ts +115 -0
  243. package/types/malva-ui-core-scrollbar.d.ts +203 -0
  244. package/types/malva-ui-core-search-field.d.ts +408 -0
  245. package/types/malva-ui-core-segmented.d.ts +206 -0
  246. package/types/malva-ui-core-select.d.ts +456 -0
  247. package/types/malva-ui-core-sidebar.d.ts +698 -0
  248. package/types/malva-ui-core-skeleton.d.ts +64 -0
  249. package/types/malva-ui-core-slider.d.ts +219 -0
  250. package/types/malva-ui-core-split-pane.d.ts +149 -0
  251. package/types/malva-ui-core-status-indicator.d.ts +65 -0
  252. package/types/malva-ui-core-stepper.d.ts +168 -0
  253. package/types/malva-ui-core-switch.d.ts +146 -0
  254. package/types/malva-ui-core-table.d.ts +37 -0
  255. package/types/malva-ui-core-tabs.d.ts +339 -0
  256. package/types/malva-ui-core-textarea.d.ts +79 -0
  257. package/types/malva-ui-core-tile.d.ts +373 -0
  258. package/types/malva-ui-core-time-picker.d.ts +141 -0
  259. package/types/malva-ui-core-timeline.d.ts +188 -0
  260. package/types/malva-ui-core-title.d.ts +66 -0
  261. package/types/malva-ui-core-toast.d.ts +432 -0
  262. package/types/malva-ui-core-tokenizer.d.ts +217 -0
  263. package/types/malva-ui-core-toolbar.d.ts +91 -0
  264. package/types/malva-ui-core-tooltip.d.ts +200 -0
  265. package/types/malva-ui-core-tree.d.ts +289 -0
  266. package/types/malva-ui-core-view-variant.d.ts +207 -0
  267. package/types/malva-ui-core.d.ts +72 -0
  268. package/view-variant/README.md +3 -0
  269. package/accordion/index.d.ts +0 -3
  270. package/accordion/lib/accordion/accordion.d.ts +0 -47
  271. package/accordion/lib/accordion-item/accordion-header.d.ts +0 -22
  272. package/accordion/lib/accordion-item/accordion-item.d.ts +0 -49
  273. package/accordion/malva-ui-core-accordion.d.ts +0 -5
  274. package/action-bar/index.d.ts +0 -4
  275. package/action-bar/lib/action-bar/action-bar.d.ts +0 -59
  276. package/action-bar/lib/action-bar/components/action-bar-actions.d.ts +0 -9
  277. package/action-bar/lib/action-bar/components/action-bar-logo.d.ts +0 -5
  278. package/action-bar/lib/action-bar/components/action-bar-spacer.d.ts +0 -5
  279. package/action-bar/malva-ui-core-action-bar.d.ts +0 -5
  280. package/alert/index.d.ts +0 -2
  281. package/alert/lib/alert/alert.d.ts +0 -84
  282. package/alert/lib/alert/alert.directives.d.ts +0 -44
  283. package/alert/malva-ui-core-alert.d.ts +0 -5
  284. package/autocomplete/index.d.ts +0 -1
  285. package/autocomplete/lib/autocomplete/autocomplete.d.ts +0 -296
  286. package/autocomplete/malva-ui-core-autocomplete.d.ts +0 -5
  287. package/avatar/index.d.ts +0 -2
  288. package/avatar/lib/avatar/avatar.d.ts +0 -125
  289. package/avatar/lib/color-from-text.pipe.d.ts +0 -21
  290. package/avatar/malva-ui-core-avatar.d.ts +0 -5
  291. package/avatar-group/index.d.ts +0 -1
  292. package/avatar-group/lib/avatar-group/avatar-group.d.ts +0 -115
  293. package/avatar-group/malva-ui-core-avatar-group.d.ts +0 -5
  294. package/badge/index.d.ts +0 -2
  295. package/badge/lib/badge/badge.d.ts +0 -59
  296. package/badge/lib/badge-icon.d.ts +0 -35
  297. package/badge/malva-ui-core-badge.d.ts +0 -5
  298. package/bottom-nav/index.d.ts +0 -1
  299. package/bottom-nav/lib/bottom-nav/bottom-nav.d.ts +0 -99
  300. package/bottom-nav/malva-ui-core-bottom-nav.d.ts +0 -5
  301. package/breadcrumb/index.d.ts +0 -5
  302. package/breadcrumb/lib/breadcrumb/breadcrumb-item-host.d.ts +0 -32
  303. package/breadcrumb/lib/breadcrumb/breadcrumb-item.d.ts +0 -41
  304. package/breadcrumb/lib/breadcrumb/breadcrumb-separator.d.ts +0 -31
  305. package/breadcrumb/lib/breadcrumb/breadcrumb.d.ts +0 -151
  306. package/breadcrumb/lib/breadcrumb/breadcrumb.types.d.ts +0 -26
  307. package/breadcrumb/malva-ui-core-breadcrumb.d.ts +0 -5
  308. package/button/index.d.ts +0 -7
  309. package/button/lib/button/button.d.ts +0 -61
  310. package/button/lib/button-close/button-close.d.ts +0 -24
  311. package/button/lib/button-group/button-group.d.ts +0 -21
  312. package/button/lib/button-split/button-split.d.ts +0 -21
  313. package/button/lib/button-toggle/button-toggle.d.ts +0 -33
  314. package/button/lib/button-variant.token.d.ts +0 -13
  315. package/button/lib/button.directives.d.ts +0 -14
  316. package/button/lib/button.types.d.ts +0 -8
  317. package/button/malva-ui-core-button.d.ts +0 -5
  318. package/calendar/index.d.ts +0 -3
  319. package/calendar/lib/calendar/calendar.d.ts +0 -182
  320. package/calendar/lib/date-provider/date-adapter.d.ts +0 -92
  321. package/calendar/lib/date-provider/native-date-adapter.d.ts +0 -60
  322. package/calendar/malva-ui-core-calendar.d.ts +0 -5
  323. package/card/index.d.ts +0 -5
  324. package/card/lib/card/card.d.ts +0 -43
  325. package/card/lib/card-actions-def.d.ts +0 -10
  326. package/card/lib/card-footer-def.d.ts +0 -13
  327. package/card/lib/card-header-def.d.ts +0 -10
  328. package/card/lib/card-subheader-def.d.ts +0 -16
  329. package/card/malva-ui-core-card.d.ts +0 -5
  330. package/chat/index.d.ts +0 -9
  331. package/chat/lib/chat/chat.d.ts +0 -133
  332. package/chat/lib/chat-audio/chat-audio.d.ts +0 -51
  333. package/chat/lib/chat-audio/chat-audio.service.d.ts +0 -21
  334. package/chat/lib/chat-date/chat-date.d.ts +0 -16
  335. package/chat/lib/chat-format.d.ts +0 -5
  336. package/chat/lib/chat-media-grid/chat-media-grid.d.ts +0 -32
  337. package/chat/lib/chat-message/chat-message.d.ts +0 -45
  338. package/chat/lib/chat-render-list.d.ts +0 -16
  339. package/chat/lib/chat-tokens.d.ts +0 -25
  340. package/chat/lib/chat-typing/chat-typing.d.ts +0 -16
  341. package/chat/lib/chat.types.d.ts +0 -80
  342. package/chat/lib/defs/chat-author-def.d.ts +0 -30
  343. package/chat/lib/defs/chat-date-def.d.ts +0 -22
  344. package/chat/lib/defs/chat-message-def.d.ts +0 -23
  345. package/chat/malva-ui-core-chat.d.ts +0 -5
  346. package/checkbox/index.d.ts +0 -3
  347. package/checkbox/lib/checkbox/checkbox.d.ts +0 -129
  348. package/checkbox/lib/checkbox-group/checkbox-group.d.ts +0 -24
  349. package/checkbox/lib/checkbox-group-token.d.ts +0 -6
  350. package/checkbox/malva-ui-core-checkbox.d.ts +0 -5
  351. package/chip/index.d.ts +0 -2
  352. package/chip/lib/chip/chip.d.ts +0 -107
  353. package/chip/lib/chip/chip.directives.d.ts +0 -18
  354. package/chip/malva-ui-core-chip.d.ts +0 -5
  355. package/color-picker/index.d.ts +0 -3
  356. package/color-picker/lib/color-picker/color-picker.d.ts +0 -188
  357. package/color-picker/lib/color-picker-popup/color-picker-popup.d.ts +0 -151
  358. package/color-picker/lib/color-utils/color-utils.d.ts +0 -102
  359. package/color-picker/malva-ui-core-color-picker.d.ts +0 -5
  360. package/combobox/index.d.ts +0 -2
  361. package/combobox/lib/combobox/combobox.d.ts +0 -400
  362. package/combobox/lib/combobox-template.directives.d.ts +0 -10
  363. package/combobox/malva-ui-core-combobox.d.ts +0 -5
  364. package/copy-to-clipboard/index.d.ts +0 -1
  365. package/copy-to-clipboard/lib/copy-to-clipboard/copy-to-clipboard.d.ts +0 -130
  366. package/copy-to-clipboard/malva-ui-core-copy-to-clipboard.d.ts +0 -5
  367. package/data-table/index.d.ts +0 -8
  368. package/data-table/lib/data-source.d.ts +0 -5
  369. package/data-table/lib/data-table/data-table-layout.d.ts +0 -31
  370. package/data-table/lib/data-table/data-table.d.ts +0 -699
  371. package/data-table/lib/data-table/services/data-table-column-visibility.service.d.ts +0 -19
  372. package/data-table/lib/data-table/services/data-table-editing.service.d.ts +0 -37
  373. package/data-table/lib/data-table/services/data-table-pinning.service.d.ts +0 -37
  374. package/data-table/lib/data-table-cell.d.ts +0 -44
  375. package/data-table/lib/data-table-edit-cell.d.ts +0 -44
  376. package/data-table/lib/data-table-error.d.ts +0 -37
  377. package/data-table/lib/data-table-footer.d.ts +0 -26
  378. package/data-table/lib/data-table-no-data.d.ts +0 -19
  379. package/data-table/lib/filter-dropdown/filter-dropdown.d.ts +0 -54
  380. package/data-table/lib/types.d.ts +0 -134
  381. package/data-table/malva-ui-core-data-table.d.ts +0 -5
  382. package/date-range-picker/index.d.ts +0 -1
  383. package/date-range-picker/lib/date-range-picker/date-range-picker.d.ts +0 -145
  384. package/date-range-picker/malva-ui-core-date-range-picker.d.ts +0 -5
  385. package/day-picker/index.d.ts +0 -1
  386. package/day-picker/lib/day-picker/day-picker.d.ts +0 -51
  387. package/day-picker/malva-ui-core-day-picker.d.ts +0 -5
  388. package/dialog/index.d.ts +0 -11
  389. package/dialog/lib/confirm-dialog-options.d.ts +0 -41
  390. package/dialog/lib/confirm-dialog.d.ts +0 -52
  391. package/dialog/lib/dialog/dialog.d.ts +0 -22
  392. package/dialog/lib/dialog-body.d.ts +0 -9
  393. package/dialog/lib/dialog-close.d.ts +0 -27
  394. package/dialog/lib/dialog-config.d.ts +0 -112
  395. package/dialog/lib/dialog-container.d.ts +0 -40
  396. package/dialog/lib/dialog-footer.d.ts +0 -13
  397. package/dialog/lib/dialog-header.d.ts +0 -74
  398. package/dialog/lib/dialog-ref.d.ts +0 -95
  399. package/dialog/lib/dialog-template.d.ts +0 -65
  400. package/dialog/lib/dialog-text-content.d.ts +0 -24
  401. package/dialog/lib/dialog.service.d.ts +0 -63
  402. package/dialog/lib/generate-routable-dialog-route.d.ts +0 -49
  403. package/dialog/lib/inject-dialog-ref.d.ts +0 -8
  404. package/dialog/lib/routable-dialog.d.ts +0 -30
  405. package/dialog/malva-ui-core-dialog.d.ts +0 -5
  406. package/divider/index.d.ts +0 -1
  407. package/divider/lib/divider/divider.d.ts +0 -64
  408. package/divider/malva-ui-core-divider.d.ts +0 -5
  409. package/drawer/index.d.ts +0 -11
  410. package/drawer/lib/drawer/drawer.d.ts +0 -106
  411. package/drawer/lib/drawer-body.d.ts +0 -8
  412. package/drawer/lib/drawer-content.d.ts +0 -6
  413. package/drawer/lib/drawer-footer.d.ts +0 -5
  414. package/drawer/lib/drawer-header.d.ts +0 -5
  415. package/drawer/lib/drawer-ref.d.ts +0 -29
  416. package/drawer/lib/drawer-resize.d.ts +0 -65
  417. package/drawer/lib/drawer-section/drawer-section.d.ts +0 -15
  418. package/drawer/lib/drawer-sections/drawer-sections.d.ts +0 -22
  419. package/drawer/lib/drawer-sections.service.d.ts +0 -42
  420. package/drawer/lib/drawer.service.d.ts +0 -66
  421. package/drawer/lib/generate-routable-drawer-route.d.ts +0 -42
  422. package/drawer/lib/routable-drawer.d.ts +0 -30
  423. package/drawer/malva-ui-core-drawer.d.ts +0 -5
  424. package/dropdown/index.d.ts +0 -9
  425. package/dropdown/lib/active-descendant.d.ts +0 -64
  426. package/dropdown/lib/dropdown-panel/dropdown-panel.d.ts +0 -178
  427. package/dropdown/lib/highlight-match.pipe.d.ts +0 -27
  428. package/dropdown/lib/option-matcher.d.ts +0 -87
  429. package/dropdown/lib/options-adapter.d.ts +0 -142
  430. package/dropdown/lib/options-result.d.ts +0 -6
  431. package/dropdown/lib/reconciliation.d.ts +0 -19
  432. package/dropdown/lib/select-data-source.d.ts +0 -18
  433. package/dropdown/lib/select-option.d.ts +0 -37
  434. package/dropdown/malva-ui-core-dropdown.d.ts +0 -5
  435. package/empty-state/index.d.ts +0 -1
  436. package/empty-state/lib/empty-state/empty-state.d.ts +0 -34
  437. package/empty-state/malva-ui-core-empty-state.d.ts +0 -5
  438. package/esm2022/accordion/index.js +0 -4
  439. package/esm2022/accordion/index.js.map +0 -1
  440. package/esm2022/accordion/lib/accordion/accordion.js +0 -65
  441. package/esm2022/accordion/lib/accordion/accordion.js.map +0 -1
  442. package/esm2022/accordion/lib/accordion-item/accordion-header.js +0 -30
  443. package/esm2022/accordion/lib/accordion-item/accordion-header.js.map +0 -1
  444. package/esm2022/accordion/lib/accordion-item/accordion-item.js +0 -70
  445. package/esm2022/accordion/lib/accordion-item/accordion-item.js.map +0 -1
  446. package/esm2022/accordion/malva-ui-core-accordion.js +0 -5
  447. package/esm2022/accordion/malva-ui-core-accordion.js.map +0 -1
  448. package/esm2022/action-bar/index.js +0 -5
  449. package/esm2022/action-bar/index.js.map +0 -1
  450. package/esm2022/action-bar/lib/action-bar/action-bar.js +0 -64
  451. package/esm2022/action-bar/lib/action-bar/action-bar.js.map +0 -1
  452. package/esm2022/action-bar/lib/action-bar/components/action-bar-actions.js +0 -20
  453. package/esm2022/action-bar/lib/action-bar/components/action-bar-actions.js.map +0 -1
  454. package/esm2022/action-bar/lib/action-bar/components/action-bar-logo.js +0 -13
  455. package/esm2022/action-bar/lib/action-bar/components/action-bar-logo.js.map +0 -1
  456. package/esm2022/action-bar/lib/action-bar/components/action-bar-spacer.js +0 -13
  457. package/esm2022/action-bar/lib/action-bar/components/action-bar-spacer.js.map +0 -1
  458. package/esm2022/action-bar/malva-ui-core-action-bar.js +0 -5
  459. package/esm2022/action-bar/malva-ui-core-action-bar.js.map +0 -1
  460. package/esm2022/alert/index.js +0 -3
  461. package/esm2022/alert/index.js.map +0 -1
  462. package/esm2022/alert/lib/alert/alert.directives.js +0 -53
  463. package/esm2022/alert/lib/alert/alert.directives.js.map +0 -1
  464. package/esm2022/alert/lib/alert/alert.js +0 -118
  465. package/esm2022/alert/lib/alert/alert.js.map +0 -1
  466. package/esm2022/alert/malva-ui-core-alert.js +0 -5
  467. package/esm2022/alert/malva-ui-core-alert.js.map +0 -1
  468. package/esm2022/autocomplete/index.js +0 -2
  469. package/esm2022/autocomplete/index.js.map +0 -1
  470. package/esm2022/autocomplete/lib/autocomplete/autocomplete.js +0 -765
  471. package/esm2022/autocomplete/lib/autocomplete/autocomplete.js.map +0 -1
  472. package/esm2022/autocomplete/malva-ui-core-autocomplete.js +0 -5
  473. package/esm2022/autocomplete/malva-ui-core-autocomplete.js.map +0 -1
  474. package/esm2022/avatar/index.js +0 -3
  475. package/esm2022/avatar/index.js.map +0 -1
  476. package/esm2022/avatar/lib/avatar/avatar.js +0 -192
  477. package/esm2022/avatar/lib/avatar/avatar.js.map +0 -1
  478. package/esm2022/avatar/lib/color-from-text.pipe.js +0 -39
  479. package/esm2022/avatar/lib/color-from-text.pipe.js.map +0 -1
  480. package/esm2022/avatar/malva-ui-core-avatar.js +0 -5
  481. package/esm2022/avatar/malva-ui-core-avatar.js.map +0 -1
  482. package/esm2022/avatar-group/index.js +0 -2
  483. package/esm2022/avatar-group/index.js.map +0 -1
  484. package/esm2022/avatar-group/lib/avatar-group/avatar-group.js +0 -217
  485. package/esm2022/avatar-group/lib/avatar-group/avatar-group.js.map +0 -1
  486. package/esm2022/avatar-group/malva-ui-core-avatar-group.js +0 -5
  487. package/esm2022/avatar-group/malva-ui-core-avatar-group.js.map +0 -1
  488. package/esm2022/badge/index.js +0 -3
  489. package/esm2022/badge/index.js.map +0 -1
  490. package/esm2022/badge/lib/badge/badge.js +0 -71
  491. package/esm2022/badge/lib/badge/badge.js.map +0 -1
  492. package/esm2022/badge/lib/badge-icon.js +0 -47
  493. package/esm2022/badge/lib/badge-icon.js.map +0 -1
  494. package/esm2022/badge/malva-ui-core-badge.js +0 -5
  495. package/esm2022/badge/malva-ui-core-badge.js.map +0 -1
  496. package/esm2022/bottom-nav/index.js +0 -2
  497. package/esm2022/bottom-nav/index.js.map +0 -1
  498. package/esm2022/bottom-nav/lib/bottom-nav/bottom-nav.js +0 -155
  499. package/esm2022/bottom-nav/lib/bottom-nav/bottom-nav.js.map +0 -1
  500. package/esm2022/bottom-nav/malva-ui-core-bottom-nav.js +0 -5
  501. package/esm2022/bottom-nav/malva-ui-core-bottom-nav.js.map +0 -1
  502. package/esm2022/breadcrumb/index.js +0 -6
  503. package/esm2022/breadcrumb/index.js.map +0 -1
  504. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-item-host.js +0 -43
  505. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-item-host.js.map +0 -1
  506. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-item.js +0 -110
  507. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-item.js.map +0 -1
  508. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-separator.js +0 -38
  509. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb-separator.js.map +0 -1
  510. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb.js +0 -284
  511. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb.js.map +0 -1
  512. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb.types.js +0 -1
  513. package/esm2022/breadcrumb/lib/breadcrumb/breadcrumb.types.js.map +0 -1
  514. package/esm2022/breadcrumb/malva-ui-core-breadcrumb.js +0 -5
  515. package/esm2022/breadcrumb/malva-ui-core-breadcrumb.js.map +0 -1
  516. package/esm2022/button/index.js +0 -8
  517. package/esm2022/button/index.js.map +0 -1
  518. package/esm2022/button/lib/button/button.js +0 -137
  519. package/esm2022/button/lib/button/button.js.map +0 -1
  520. package/esm2022/button/lib/button-close/button-close.js +0 -52
  521. package/esm2022/button/lib/button-close/button-close.js.map +0 -1
  522. package/esm2022/button/lib/button-group/button-group.js +0 -44
  523. package/esm2022/button/lib/button-group/button-group.js.map +0 -1
  524. package/esm2022/button/lib/button-split/button-split.js +0 -44
  525. package/esm2022/button/lib/button-split/button-split.js.map +0 -1
  526. package/esm2022/button/lib/button-toggle/button-toggle.js +0 -94
  527. package/esm2022/button/lib/button-toggle/button-toggle.js.map +0 -1
  528. package/esm2022/button/lib/button-variant.token.js +0 -4
  529. package/esm2022/button/lib/button-variant.token.js.map +0 -1
  530. package/esm2022/button/lib/button.directives.js +0 -37
  531. package/esm2022/button/lib/button.directives.js.map +0 -1
  532. package/esm2022/button/lib/button.types.js +0 -1
  533. package/esm2022/button/lib/button.types.js.map +0 -1
  534. package/esm2022/button/malva-ui-core-button.js +0 -5
  535. package/esm2022/button/malva-ui-core-button.js.map +0 -1
  536. package/esm2022/calendar/index.js +0 -4
  537. package/esm2022/calendar/index.js.map +0 -1
  538. package/esm2022/calendar/lib/calendar/calendar.js +0 -672
  539. package/esm2022/calendar/lib/calendar/calendar.js.map +0 -1
  540. package/esm2022/calendar/lib/date-provider/date-adapter.js +0 -111
  541. package/esm2022/calendar/lib/date-provider/date-adapter.js.map +0 -1
  542. package/esm2022/calendar/lib/date-provider/native-date-adapter.js +0 -151
  543. package/esm2022/calendar/lib/date-provider/native-date-adapter.js.map +0 -1
  544. package/esm2022/calendar/malva-ui-core-calendar.js +0 -5
  545. package/esm2022/calendar/malva-ui-core-calendar.js.map +0 -1
  546. package/esm2022/card/index.js +0 -6
  547. package/esm2022/card/index.js.map +0 -1
  548. package/esm2022/card/lib/card/card.js +0 -54
  549. package/esm2022/card/lib/card/card.js.map +0 -1
  550. package/esm2022/card/lib/card-actions-def.js +0 -27
  551. package/esm2022/card/lib/card-actions-def.js.map +0 -1
  552. package/esm2022/card/lib/card-footer-def.js +0 -32
  553. package/esm2022/card/lib/card-footer-def.js.map +0 -1
  554. package/esm2022/card/lib/card-header-def.js +0 -27
  555. package/esm2022/card/lib/card-header-def.js.map +0 -1
  556. package/esm2022/card/lib/card-subheader-def.js +0 -33
  557. package/esm2022/card/lib/card-subheader-def.js.map +0 -1
  558. package/esm2022/card/malva-ui-core-card.js +0 -5
  559. package/esm2022/card/malva-ui-core-card.js.map +0 -1
  560. package/esm2022/chat/index.js +0 -10
  561. package/esm2022/chat/index.js.map +0 -1
  562. package/esm2022/chat/lib/chat/chat.js +0 -326
  563. package/esm2022/chat/lib/chat/chat.js.map +0 -1
  564. package/esm2022/chat/lib/chat-audio/chat-audio.js +0 -110
  565. package/esm2022/chat/lib/chat-audio/chat-audio.js.map +0 -1
  566. package/esm2022/chat/lib/chat-audio/chat-audio.service.js +0 -28
  567. package/esm2022/chat/lib/chat-audio/chat-audio.service.js.map +0 -1
  568. package/esm2022/chat/lib/chat-date/chat-date.js +0 -46
  569. package/esm2022/chat/lib/chat-date/chat-date.js.map +0 -1
  570. package/esm2022/chat/lib/chat-format.js +0 -11
  571. package/esm2022/chat/lib/chat-format.js.map +0 -1
  572. package/esm2022/chat/lib/chat-media-grid/chat-media-grid.js +0 -53
  573. package/esm2022/chat/lib/chat-media-grid/chat-media-grid.js.map +0 -1
  574. package/esm2022/chat/lib/chat-message/chat-message.js +0 -86
  575. package/esm2022/chat/lib/chat-message/chat-message.js.map +0 -1
  576. package/esm2022/chat/lib/chat-render-list.js +0 -55
  577. package/esm2022/chat/lib/chat-render-list.js.map +0 -1
  578. package/esm2022/chat/lib/chat-tokens.js +0 -9
  579. package/esm2022/chat/lib/chat-tokens.js.map +0 -1
  580. package/esm2022/chat/lib/chat-typing/chat-typing.js +0 -50
  581. package/esm2022/chat/lib/chat-typing/chat-typing.js.map +0 -1
  582. package/esm2022/chat/lib/chat.types.js +0 -1
  583. package/esm2022/chat/lib/chat.types.js.map +0 -1
  584. package/esm2022/chat/lib/defs/chat-author-def.js +0 -27
  585. package/esm2022/chat/lib/defs/chat-author-def.js.map +0 -1
  586. package/esm2022/chat/lib/defs/chat-date-def.js +0 -24
  587. package/esm2022/chat/lib/defs/chat-date-def.js.map +0 -1
  588. package/esm2022/chat/lib/defs/chat-message-def.js +0 -30
  589. package/esm2022/chat/lib/defs/chat-message-def.js.map +0 -1
  590. package/esm2022/chat/malva-ui-core-chat.js +0 -5
  591. package/esm2022/chat/malva-ui-core-chat.js.map +0 -1
  592. package/esm2022/checkbox/index.js +0 -4
  593. package/esm2022/checkbox/index.js.map +0 -1
  594. package/esm2022/checkbox/lib/checkbox/checkbox.js +0 -201
  595. package/esm2022/checkbox/lib/checkbox/checkbox.js.map +0 -1
  596. package/esm2022/checkbox/lib/checkbox-group/checkbox-group.js +0 -68
  597. package/esm2022/checkbox/lib/checkbox-group/checkbox-group.js.map +0 -1
  598. package/esm2022/checkbox/lib/checkbox-group-token.js +0 -3
  599. package/esm2022/checkbox/lib/checkbox-group-token.js.map +0 -1
  600. package/esm2022/checkbox/malva-ui-core-checkbox.js +0 -5
  601. package/esm2022/checkbox/malva-ui-core-checkbox.js.map +0 -1
  602. package/esm2022/chip/index.js +0 -3
  603. package/esm2022/chip/index.js.map +0 -1
  604. package/esm2022/chip/lib/chip/chip.directives.js +0 -32
  605. package/esm2022/chip/lib/chip/chip.directives.js.map +0 -1
  606. package/esm2022/chip/lib/chip/chip.js +0 -140
  607. package/esm2022/chip/lib/chip/chip.js.map +0 -1
  608. package/esm2022/chip/malva-ui-core-chip.js +0 -5
  609. package/esm2022/chip/malva-ui-core-chip.js.map +0 -1
  610. package/esm2022/color-picker/index.js +0 -4
  611. package/esm2022/color-picker/index.js.map +0 -1
  612. package/esm2022/color-picker/lib/color-picker/color-picker.js +0 -530
  613. package/esm2022/color-picker/lib/color-picker/color-picker.js.map +0 -1
  614. package/esm2022/color-picker/lib/color-picker-popup/color-picker-popup.js +0 -419
  615. package/esm2022/color-picker/lib/color-picker-popup/color-picker-popup.js.map +0 -1
  616. package/esm2022/color-picker/lib/color-utils/color-utils.js +0 -256
  617. package/esm2022/color-picker/lib/color-utils/color-utils.js.map +0 -1
  618. package/esm2022/color-picker/malva-ui-core-color-picker.js +0 -5
  619. package/esm2022/color-picker/malva-ui-core-color-picker.js.map +0 -1
  620. package/esm2022/combobox/index.js +0 -3
  621. package/esm2022/combobox/index.js.map +0 -1
  622. package/esm2022/combobox/lib/combobox/combobox.js +0 -911
  623. package/esm2022/combobox/lib/combobox/combobox.js.map +0 -1
  624. package/esm2022/combobox/lib/combobox-template.directives.js +0 -24
  625. package/esm2022/combobox/lib/combobox-template.directives.js.map +0 -1
  626. package/esm2022/combobox/malva-ui-core-combobox.js +0 -5
  627. package/esm2022/combobox/malva-ui-core-combobox.js.map +0 -1
  628. package/esm2022/copy-to-clipboard/index.js +0 -2
  629. package/esm2022/copy-to-clipboard/index.js.map +0 -1
  630. package/esm2022/copy-to-clipboard/lib/copy-to-clipboard/copy-to-clipboard.js +0 -201
  631. package/esm2022/copy-to-clipboard/lib/copy-to-clipboard/copy-to-clipboard.js.map +0 -1
  632. package/esm2022/copy-to-clipboard/malva-ui-core-copy-to-clipboard.js +0 -5
  633. package/esm2022/copy-to-clipboard/malva-ui-core-copy-to-clipboard.js.map +0 -1
  634. package/esm2022/data-table/index.js +0 -9
  635. package/esm2022/data-table/index.js.map +0 -1
  636. package/esm2022/data-table/lib/data-source.js +0 -6
  637. package/esm2022/data-table/lib/data-source.js.map +0 -1
  638. package/esm2022/data-table/lib/data-table/data-table-layout.js +0 -84
  639. package/esm2022/data-table/lib/data-table/data-table-layout.js.map +0 -1
  640. package/esm2022/data-table/lib/data-table/data-table.js +0 -1846
  641. package/esm2022/data-table/lib/data-table/data-table.js.map +0 -1
  642. package/esm2022/data-table/lib/data-table/services/data-table-column-visibility.service.js +0 -37
  643. package/esm2022/data-table/lib/data-table/services/data-table-column-visibility.service.js.map +0 -1
  644. package/esm2022/data-table/lib/data-table/services/data-table-editing.service.js +0 -63
  645. package/esm2022/data-table/lib/data-table/services/data-table-editing.service.js.map +0 -1
  646. package/esm2022/data-table/lib/data-table/services/data-table-pinning.service.js +0 -68
  647. package/esm2022/data-table/lib/data-table/services/data-table-pinning.service.js.map +0 -1
  648. package/esm2022/data-table/lib/data-table-cell.js +0 -46
  649. package/esm2022/data-table/lib/data-table-cell.js.map +0 -1
  650. package/esm2022/data-table/lib/data-table-edit-cell.js +0 -46
  651. package/esm2022/data-table/lib/data-table-edit-cell.js.map +0 -1
  652. package/esm2022/data-table/lib/data-table-error.js +0 -37
  653. package/esm2022/data-table/lib/data-table-error.js.map +0 -1
  654. package/esm2022/data-table/lib/data-table-footer.js +0 -33
  655. package/esm2022/data-table/lib/data-table-footer.js.map +0 -1
  656. package/esm2022/data-table/lib/data-table-no-data.js +0 -26
  657. package/esm2022/data-table/lib/data-table-no-data.js.map +0 -1
  658. package/esm2022/data-table/lib/filter-dropdown/filter-dropdown.js +0 -224
  659. package/esm2022/data-table/lib/filter-dropdown/filter-dropdown.js.map +0 -1
  660. package/esm2022/data-table/lib/types.js +0 -1
  661. package/esm2022/data-table/lib/types.js.map +0 -1
  662. package/esm2022/data-table/malva-ui-core-data-table.js +0 -5
  663. package/esm2022/data-table/malva-ui-core-data-table.js.map +0 -1
  664. package/esm2022/date-range-picker/index.js +0 -2
  665. package/esm2022/date-range-picker/index.js.map +0 -1
  666. package/esm2022/date-range-picker/lib/date-range-picker/date-range-picker.js +0 -269
  667. package/esm2022/date-range-picker/lib/date-range-picker/date-range-picker.js.map +0 -1
  668. package/esm2022/date-range-picker/malva-ui-core-date-range-picker.js +0 -5
  669. package/esm2022/date-range-picker/malva-ui-core-date-range-picker.js.map +0 -1
  670. package/esm2022/day-picker/index.js +0 -2
  671. package/esm2022/day-picker/index.js.map +0 -1
  672. package/esm2022/day-picker/lib/day-picker/day-picker.js +0 -124
  673. package/esm2022/day-picker/lib/day-picker/day-picker.js.map +0 -1
  674. package/esm2022/day-picker/malva-ui-core-day-picker.js +0 -5
  675. package/esm2022/day-picker/malva-ui-core-day-picker.js.map +0 -1
  676. package/esm2022/dialog/index.js +0 -12
  677. package/esm2022/dialog/index.js.map +0 -1
  678. package/esm2022/dialog/lib/confirm-dialog-options.js +0 -1
  679. package/esm2022/dialog/lib/confirm-dialog-options.js.map +0 -1
  680. package/esm2022/dialog/lib/confirm-dialog.js +0 -155
  681. package/esm2022/dialog/lib/confirm-dialog.js.map +0 -1
  682. package/esm2022/dialog/lib/dialog/dialog.js +0 -40
  683. package/esm2022/dialog/lib/dialog/dialog.js.map +0 -1
  684. package/esm2022/dialog/lib/dialog-body.js +0 -33
  685. package/esm2022/dialog/lib/dialog-body.js.map +0 -1
  686. package/esm2022/dialog/lib/dialog-close.js +0 -45
  687. package/esm2022/dialog/lib/dialog-close.js.map +0 -1
  688. package/esm2022/dialog/lib/dialog-config.js +0 -23
  689. package/esm2022/dialog/lib/dialog-config.js.map +0 -1
  690. package/esm2022/dialog/lib/dialog-container.js +0 -69
  691. package/esm2022/dialog/lib/dialog-container.js.map +0 -1
  692. package/esm2022/dialog/lib/dialog-footer.js +0 -29
  693. package/esm2022/dialog/lib/dialog-footer.js.map +0 -1
  694. package/esm2022/dialog/lib/dialog-header.js +0 -181
  695. package/esm2022/dialog/lib/dialog-header.js.map +0 -1
  696. package/esm2022/dialog/lib/dialog-ref.js +0 -167
  697. package/esm2022/dialog/lib/dialog-ref.js.map +0 -1
  698. package/esm2022/dialog/lib/dialog-template.js +0 -136
  699. package/esm2022/dialog/lib/dialog-template.js.map +0 -1
  700. package/esm2022/dialog/lib/dialog-text-content.js +0 -59
  701. package/esm2022/dialog/lib/dialog-text-content.js.map +0 -1
  702. package/esm2022/dialog/lib/dialog.service.js +0 -205
  703. package/esm2022/dialog/lib/dialog.service.js.map +0 -1
  704. package/esm2022/dialog/lib/generate-routable-dialog-route.js +0 -59
  705. package/esm2022/dialog/lib/generate-routable-dialog-route.js.map +0 -1
  706. package/esm2022/dialog/lib/inject-dialog-ref.js +0 -16
  707. package/esm2022/dialog/lib/inject-dialog-ref.js.map +0 -1
  708. package/esm2022/dialog/lib/routable-dialog.js +0 -91
  709. package/esm2022/dialog/lib/routable-dialog.js.map +0 -1
  710. package/esm2022/dialog/malva-ui-core-dialog.js +0 -5
  711. package/esm2022/dialog/malva-ui-core-dialog.js.map +0 -1
  712. package/esm2022/divider/index.js +0 -2
  713. package/esm2022/divider/index.js.map +0 -1
  714. package/esm2022/divider/lib/divider/divider.js +0 -73
  715. package/esm2022/divider/lib/divider/divider.js.map +0 -1
  716. package/esm2022/divider/malva-ui-core-divider.js +0 -5
  717. package/esm2022/divider/malva-ui-core-divider.js.map +0 -1
  718. package/esm2022/drawer/index.js +0 -12
  719. package/esm2022/drawer/index.js.map +0 -1
  720. package/esm2022/drawer/lib/drawer/drawer.js +0 -180
  721. package/esm2022/drawer/lib/drawer/drawer.js.map +0 -1
  722. package/esm2022/drawer/lib/drawer-body.js +0 -32
  723. package/esm2022/drawer/lib/drawer-body.js.map +0 -1
  724. package/esm2022/drawer/lib/drawer-content.js +0 -14
  725. package/esm2022/drawer/lib/drawer-content.js.map +0 -1
  726. package/esm2022/drawer/lib/drawer-footer.js +0 -14
  727. package/esm2022/drawer/lib/drawer-footer.js.map +0 -1
  728. package/esm2022/drawer/lib/drawer-header.js +0 -14
  729. package/esm2022/drawer/lib/drawer-header.js.map +0 -1
  730. package/esm2022/drawer/lib/drawer-ref.js +0 -31
  731. package/esm2022/drawer/lib/drawer-ref.js.map +0 -1
  732. package/esm2022/drawer/lib/drawer-resize.js +0 -243
  733. package/esm2022/drawer/lib/drawer-resize.js.map +0 -1
  734. package/esm2022/drawer/lib/drawer-section/drawer-section.js +0 -26
  735. package/esm2022/drawer/lib/drawer-section/drawer-section.js.map +0 -1
  736. package/esm2022/drawer/lib/drawer-sections/drawer-sections.js +0 -58
  737. package/esm2022/drawer/lib/drawer-sections/drawer-sections.js.map +0 -1
  738. package/esm2022/drawer/lib/drawer-sections.service.js +0 -83
  739. package/esm2022/drawer/lib/drawer-sections.service.js.map +0 -1
  740. package/esm2022/drawer/lib/drawer.service.js +0 -86
  741. package/esm2022/drawer/lib/drawer.service.js.map +0 -1
  742. package/esm2022/drawer/lib/generate-routable-drawer-route.js +0 -52
  743. package/esm2022/drawer/lib/generate-routable-drawer-route.js.map +0 -1
  744. package/esm2022/drawer/lib/routable-drawer.js +0 -91
  745. package/esm2022/drawer/lib/routable-drawer.js.map +0 -1
  746. package/esm2022/drawer/malva-ui-core-drawer.js +0 -5
  747. package/esm2022/drawer/malva-ui-core-drawer.js.map +0 -1
  748. package/esm2022/dropdown/index.js +0 -10
  749. package/esm2022/dropdown/index.js.map +0 -1
  750. package/esm2022/dropdown/lib/active-descendant.js +0 -92
  751. package/esm2022/dropdown/lib/active-descendant.js.map +0 -1
  752. package/esm2022/dropdown/lib/dropdown-panel/dropdown-panel.js +0 -295
  753. package/esm2022/dropdown/lib/dropdown-panel/dropdown-panel.js.map +0 -1
  754. package/esm2022/dropdown/lib/highlight-match.pipe.js +0 -36
  755. package/esm2022/dropdown/lib/highlight-match.pipe.js.map +0 -1
  756. package/esm2022/dropdown/lib/option-matcher.js +0 -124
  757. package/esm2022/dropdown/lib/option-matcher.js.map +0 -1
  758. package/esm2022/dropdown/lib/options-adapter.js +0 -356
  759. package/esm2022/dropdown/lib/options-adapter.js.map +0 -1
  760. package/esm2022/dropdown/lib/options-result.js +0 -11
  761. package/esm2022/dropdown/lib/options-result.js.map +0 -1
  762. package/esm2022/dropdown/lib/reconciliation.js +0 -32
  763. package/esm2022/dropdown/lib/reconciliation.js.map +0 -1
  764. package/esm2022/dropdown/lib/select-data-source.js +0 -21
  765. package/esm2022/dropdown/lib/select-data-source.js.map +0 -1
  766. package/esm2022/dropdown/lib/select-option.js +0 -25
  767. package/esm2022/dropdown/lib/select-option.js.map +0 -1
  768. package/esm2022/dropdown/malva-ui-core-dropdown.js +0 -5
  769. package/esm2022/dropdown/malva-ui-core-dropdown.js.map +0 -1
  770. package/esm2022/empty-state/index.js +0 -2
  771. package/esm2022/empty-state/index.js.map +0 -1
  772. package/esm2022/empty-state/lib/empty-state/empty-state.js +0 -43
  773. package/esm2022/empty-state/lib/empty-state/empty-state.js.map +0 -1
  774. package/esm2022/empty-state/malva-ui-core-empty-state.js +0 -5
  775. package/esm2022/empty-state/malva-ui-core-empty-state.js.map +0 -1
  776. package/esm2022/expand/index.js +0 -3
  777. package/esm2022/expand/index.js.map +0 -1
  778. package/esm2022/expand/lib/expand/expand-content.js +0 -33
  779. package/esm2022/expand/lib/expand/expand-content.js.map +0 -1
  780. package/esm2022/expand/lib/expand/expand.js +0 -93
  781. package/esm2022/expand/lib/expand/expand.js.map +0 -1
  782. package/esm2022/expand/malva-ui-core-expand.js +0 -5
  783. package/esm2022/expand/malva-ui-core-expand.js.map +0 -1
  784. package/esm2022/file-upload/index.js +0 -5
  785. package/esm2022/file-upload/index.js.map +0 -1
  786. package/esm2022/file-upload/lib/file-upload/file-upload.js +0 -324
  787. package/esm2022/file-upload/lib/file-upload/file-upload.js.map +0 -1
  788. package/esm2022/file-upload/lib/file-upload/file-upload.types.js +0 -1
  789. package/esm2022/file-upload/lib/file-upload/file-upload.types.js.map +0 -1
  790. package/esm2022/file-upload/lib/file-upload-action.js +0 -65
  791. package/esm2022/file-upload/lib/file-upload-action.js.map +0 -1
  792. package/esm2022/file-upload/lib/file-upload-item/file-upload-item.js +0 -55
  793. package/esm2022/file-upload/lib/file-upload-item/file-upload-item.js.map +0 -1
  794. package/esm2022/file-upload/malva-ui-core-file-upload.js +0 -5
  795. package/esm2022/file-upload/malva-ui-core-file-upload.js.map +0 -1
  796. package/esm2022/filter/index.js +0 -4
  797. package/esm2022/filter/index.js.map +0 -1
  798. package/esm2022/filter/lib/filter/filter.js +0 -552
  799. package/esm2022/filter/lib/filter/filter.js.map +0 -1
  800. package/esm2022/filter/lib/filter.types.js +0 -1
  801. package/esm2022/filter/lib/filter.types.js.map +0 -1
  802. package/esm2022/filter/lib/smart-filter-bar/smart-filter-bar.js +0 -518
  803. package/esm2022/filter/lib/smart-filter-bar/smart-filter-bar.js.map +0 -1
  804. package/esm2022/filter/malva-ui-core-filter.js +0 -5
  805. package/esm2022/filter/malva-ui-core-filter.js.map +0 -1
  806. package/esm2022/form/index.js +0 -7
  807. package/esm2022/form/index.js.map +0 -1
  808. package/esm2022/form/lib/fieldset/fieldset.js +0 -101
  809. package/esm2022/form/lib/fieldset/fieldset.js.map +0 -1
  810. package/esm2022/form/lib/fieldset-span.js +0 -49
  811. package/esm2022/form/lib/fieldset-span.js.map +0 -1
  812. package/esm2022/form/lib/form/form.js +0 -60
  813. package/esm2022/form/lib/form/form.js.map +0 -1
  814. package/esm2022/form/lib/form-actions.js +0 -34
  815. package/esm2022/form/lib/form-actions.js.map +0 -1
  816. package/esm2022/form/lib/form-gap.js +0 -15
  817. package/esm2022/form/lib/form-gap.js.map +0 -1
  818. package/esm2022/form/lib/form-header.js +0 -27
  819. package/esm2022/form/lib/form-header.js.map +0 -1
  820. package/esm2022/form/lib/form.types.js +0 -1
  821. package/esm2022/form/lib/form.types.js.map +0 -1
  822. package/esm2022/form/malva-ui-core-form.js +0 -5
  823. package/esm2022/form/malva-ui-core-form.js.map +0 -1
  824. package/esm2022/form-utils/index.js +0 -16
  825. package/esm2022/form-utils/index.js.map +0 -1
  826. package/esm2022/form-utils/lib/aria-value-bridge.js +0 -57
  827. package/esm2022/form-utils/lib/aria-value-bridge.js.map +0 -1
  828. package/esm2022/form-utils/lib/description/description.js +0 -24
  829. package/esm2022/form-utils/lib/description/description.js.map +0 -1
  830. package/esm2022/form-utils/lib/focusable-group-base.js +0 -87
  831. package/esm2022/form-utils/lib/focusable-group-base.js.map +0 -1
  832. package/esm2022/form-utils/lib/form-control-base/signal-form-control-base.js +0 -192
  833. package/esm2022/form-utils/lib/form-control-base/signal-form-control-base.js.map +0 -1
  834. package/esm2022/form-utils/lib/form-control-sides.js +0 -34
  835. package/esm2022/form-utils/lib/form-control-sides.js.map +0 -1
  836. package/esm2022/form-utils/lib/form-control-wrapper/form-control-wrapper-control.js +0 -14
  837. package/esm2022/form-utils/lib/form-control-wrapper/form-control-wrapper-control.js.map +0 -1
  838. package/esm2022/form-utils/lib/form-control-wrapper/form-control-wrapper.js +0 -47
  839. package/esm2022/form-utils/lib/form-control-wrapper/form-control-wrapper.js.map +0 -1
  840. package/esm2022/form-utils/lib/form-field/form-field.js +0 -245
  841. package/esm2022/form-utils/lib/form-field/form-field.js.map +0 -1
  842. package/esm2022/form-utils/lib/hint/hint.js +0 -11
  843. package/esm2022/form-utils/lib/hint/hint.js.map +0 -1
  844. package/esm2022/form-utils/lib/label/label.js +0 -55
  845. package/esm2022/form-utils/lib/label/label.js.map +0 -1
  846. package/esm2022/form-utils/lib/message/message.js +0 -20
  847. package/esm2022/form-utils/lib/message/message.js.map +0 -1
  848. package/esm2022/form-utils/lib/models/error-display-strategy.js +0 -1
  849. package/esm2022/form-utils/lib/models/error-display-strategy.js.map +0 -1
  850. package/esm2022/form-utils/lib/models/form-control-connector.js +0 -3
  851. package/esm2022/form-utils/lib/models/form-control-connector.js.map +0 -1
  852. package/esm2022/form-utils/lib/models/form-state.js +0 -1
  853. package/esm2022/form-utils/lib/models/form-state.js.map +0 -1
  854. package/esm2022/form-utils/lib/selection.service.js +0 -81
  855. package/esm2022/form-utils/lib/selection.service.js.map +0 -1
  856. package/esm2022/form-utils/malva-ui-core-form-utils.js +0 -5
  857. package/esm2022/form-utils/malva-ui-core-form-utils.js.map +0 -1
  858. package/esm2022/form-utils/testing/index.js +0 -2
  859. package/esm2022/form-utils/testing/index.js.map +0 -1
  860. package/esm2022/form-utils/testing/lib/forms-binding-matrix.js +0 -32
  861. package/esm2022/form-utils/testing/lib/forms-binding-matrix.js.map +0 -1
  862. package/esm2022/form-utils/testing/malva-ui-core-form-utils-testing.js +0 -5
  863. package/esm2022/form-utils/testing/malva-ui-core-form-utils-testing.js.map +0 -1
  864. package/esm2022/index.js +0 -70
  865. package/esm2022/index.js.map +0 -1
  866. package/esm2022/input/index.js +0 -4
  867. package/esm2022/input/index.js.map +0 -1
  868. package/esm2022/input/lib/input/input-native.js +0 -49
  869. package/esm2022/input/lib/input/input-native.js.map +0 -1
  870. package/esm2022/input/lib/input/input-value-accessor.js +0 -4
  871. package/esm2022/input/lib/input/input-value-accessor.js.map +0 -1
  872. package/esm2022/input/lib/input/input.js +0 -277
  873. package/esm2022/input/lib/input/input.js.map +0 -1
  874. package/esm2022/input/lib/input/password-strength.js +0 -46
  875. package/esm2022/input/lib/input/password-strength.js.map +0 -1
  876. package/esm2022/input/malva-ui-core-input.js +0 -5
  877. package/esm2022/input/malva-ui-core-input.js.map +0 -1
  878. package/esm2022/kbd/index.js +0 -2
  879. package/esm2022/kbd/index.js.map +0 -1
  880. package/esm2022/kbd/lib/kbd/kbd.js +0 -124
  881. package/esm2022/kbd/lib/kbd/kbd.js.map +0 -1
  882. package/esm2022/kbd/malva-ui-core-kbd.js +0 -5
  883. package/esm2022/kbd/malva-ui-core-kbd.js.map +0 -1
  884. package/esm2022/layout/index.js +0 -5
  885. package/esm2022/layout/index.js.map +0 -1
  886. package/esm2022/layout/lib/layout/directives/MlvLayoutSide.js +0 -14
  887. package/esm2022/layout/lib/layout/directives/MlvLayoutSide.js.map +0 -1
  888. package/esm2022/layout/lib/layout/directives/MlvLayoutTop.js +0 -14
  889. package/esm2022/layout/lib/layout/directives/MlvLayoutTop.js.map +0 -1
  890. package/esm2022/layout/lib/layout/layout.js +0 -43
  891. package/esm2022/layout/lib/layout/layout.js.map +0 -1
  892. package/esm2022/layout/lib/layout/services/theme.service.js +0 -121
  893. package/esm2022/layout/lib/layout/services/theme.service.js.map +0 -1
  894. package/esm2022/layout/malva-ui-core-layout.js +0 -5
  895. package/esm2022/layout/malva-ui-core-layout.js.map +0 -1
  896. package/esm2022/link/index.js +0 -3
  897. package/esm2022/link/index.js.map +0 -1
  898. package/esm2022/link/lib/link/link.directives.js +0 -24
  899. package/esm2022/link/lib/link/link.directives.js.map +0 -1
  900. package/esm2022/link/lib/link/link.js +0 -61
  901. package/esm2022/link/lib/link/link.js.map +0 -1
  902. package/esm2022/link/malva-ui-core-link.js +0 -5
  903. package/esm2022/link/malva-ui-core-link.js.map +0 -1
  904. package/esm2022/list/index.js +0 -14
  905. package/esm2022/list/index.js.map +0 -1
  906. package/esm2022/list/lib/list/list.js +0 -28
  907. package/esm2022/list/lib/list/list.js.map +0 -1
  908. package/esm2022/list/lib/list-item/list-item.js +0 -125
  909. package/esm2022/list/lib/list-item/list-item.js.map +0 -1
  910. package/esm2022/list/lib/list-item-actions.js +0 -23
  911. package/esm2022/list/lib/list-item-actions.js.map +0 -1
  912. package/esm2022/list/lib/list-item-byline.js +0 -13
  913. package/esm2022/list/lib/list-item-byline.js.map +0 -1
  914. package/esm2022/list/lib/list-item-group/list-item-group.js +0 -25
  915. package/esm2022/list/lib/list-item-group/list-item-group.js.map +0 -1
  916. package/esm2022/list/lib/list-item-link/list-item-link.js +0 -20
  917. package/esm2022/list/lib/list-item-link/list-item-link.js.map +0 -1
  918. package/esm2022/list/lib/list-item-media.js +0 -13
  919. package/esm2022/list/lib/list-item-media.js.map +0 -1
  920. package/esm2022/list/lib/list-item-meta.js +0 -13
  921. package/esm2022/list/lib/list-item-meta.js.map +0 -1
  922. package/esm2022/list/lib/list-item-prefix.js +0 -13
  923. package/esm2022/list/lib/list-item-prefix.js.map +0 -1
  924. package/esm2022/list/lib/list-item-suffix.js +0 -13
  925. package/esm2022/list/lib/list-item-suffix.js.map +0 -1
  926. package/esm2022/list/lib/list-item-template.js +0 -14
  927. package/esm2022/list/lib/list-item-template.js.map +0 -1
  928. package/esm2022/list/lib/list-item-title.js +0 -13
  929. package/esm2022/list/lib/list-item-title.js.map +0 -1
  930. package/esm2022/list/lib/list-selectable.js +0 -116
  931. package/esm2022/list/lib/list-selectable.js.map +0 -1
  932. package/esm2022/list/malva-ui-core-list.js +0 -5
  933. package/esm2022/list/malva-ui-core-list.js.map +0 -1
  934. package/esm2022/loader/index.js +0 -2
  935. package/esm2022/loader/index.js.map +0 -1
  936. package/esm2022/loader/lib/loader/loader.js +0 -134
  937. package/esm2022/loader/lib/loader/loader.js.map +0 -1
  938. package/esm2022/loader/malva-ui-core-loader.js +0 -5
  939. package/esm2022/loader/malva-ui-core-loader.js.map +0 -1
  940. package/esm2022/malva-ui-core.js +0 -5
  941. package/esm2022/malva-ui-core.js.map +0 -1
  942. package/esm2022/menu/index.js +0 -10
  943. package/esm2022/menu/index.js.map +0 -1
  944. package/esm2022/menu/lib/menu/menu-group-label.js +0 -35
  945. package/esm2022/menu/lib/menu/menu-group-label.js.map +0 -1
  946. package/esm2022/menu/lib/menu/menu-group.js +0 -44
  947. package/esm2022/menu/lib/menu/menu-group.js.map +0 -1
  948. package/esm2022/menu/lib/menu/menu-item.js +0 -117
  949. package/esm2022/menu/lib/menu/menu-item.js.map +0 -1
  950. package/esm2022/menu/lib/menu/menu-separator.js +0 -41
  951. package/esm2022/menu/lib/menu/menu-separator.js.map +0 -1
  952. package/esm2022/menu/lib/menu/menu-trigger.js +0 -653
  953. package/esm2022/menu/lib/menu/menu-trigger.js.map +0 -1
  954. package/esm2022/menu/lib/menu/menu.js +0 -308
  955. package/esm2022/menu/lib/menu/menu.js.map +0 -1
  956. package/esm2022/menu/lib/menu/menu.types.js +0 -4
  957. package/esm2022/menu/lib/menu/menu.types.js.map +0 -1
  958. package/esm2022/menu/lib/menu/menubar.js +0 -257
  959. package/esm2022/menu/lib/menu/menubar.js.map +0 -1
  960. package/esm2022/menu/lib/menu/menubar.types.js +0 -4
  961. package/esm2022/menu/lib/menu/menubar.types.js.map +0 -1
  962. package/esm2022/menu/lib/menu/submenu-aim.js +0 -30
  963. package/esm2022/menu/lib/menu/submenu-aim.js.map +0 -1
  964. package/esm2022/menu/malva-ui-core-menu.js +0 -5
  965. package/esm2022/menu/malva-ui-core-menu.js.map +0 -1
  966. package/esm2022/notification/index.js +0 -5
  967. package/esm2022/notification/index.js.map +0 -1
  968. package/esm2022/notification/lib/notification-item/notification-item.js +0 -65
  969. package/esm2022/notification/lib/notification-item/notification-item.js.map +0 -1
  970. package/esm2022/notification/lib/notification-ref.js +0 -13
  971. package/esm2022/notification/lib/notification-ref.js.map +0 -1
  972. package/esm2022/notification/lib/notification.service.js +0 -118
  973. package/esm2022/notification/lib/notification.service.js.map +0 -1
  974. package/esm2022/notification/lib/notification.types.js +0 -6
  975. package/esm2022/notification/lib/notification.types.js.map +0 -1
  976. package/esm2022/notification/malva-ui-core-notification.js +0 -5
  977. package/esm2022/notification/malva-ui-core-notification.js.map +0 -1
  978. package/esm2022/number-input/index.js +0 -2
  979. package/esm2022/number-input/index.js.map +0 -1
  980. package/esm2022/number-input/lib/number-input/number-input.js +0 -395
  981. package/esm2022/number-input/lib/number-input/number-input.js.map +0 -1
  982. package/esm2022/number-input/malva-ui-core-number-input.js +0 -5
  983. package/esm2022/number-input/malva-ui-core-number-input.js.map +0 -1
  984. package/esm2022/page/index.js +0 -15
  985. package/esm2022/page/index.js.map +0 -1
  986. package/esm2022/page/lib/page/page-scroll.token.js +0 -9
  987. package/esm2022/page/lib/page/page-scroll.token.js.map +0 -1
  988. package/esm2022/page/lib/page/page-snap-controller.js +0 -170
  989. package/esm2022/page/lib/page/page-snap-controller.js.map +0 -1
  990. package/esm2022/page/lib/page/page-snap.directive.js +0 -65
  991. package/esm2022/page/lib/page/page-snap.directive.js.map +0 -1
  992. package/esm2022/page/lib/page/page.js +0 -173
  993. package/esm2022/page/lib/page/page.js.map +0 -1
  994. package/esm2022/page/lib/page-content/page-aside.js +0 -13
  995. package/esm2022/page/lib/page-content/page-aside.js.map +0 -1
  996. package/esm2022/page/lib/page-content/page-content.js +0 -72
  997. package/esm2022/page/lib/page-content/page-content.js.map +0 -1
  998. package/esm2022/page/lib/page-dock/page-dock.js +0 -128
  999. package/esm2022/page/lib/page-dock/page-dock.js.map +0 -1
  1000. package/esm2022/page/lib/page-dock/page-dock.slots.js +0 -39
  1001. package/esm2022/page/lib/page-dock/page-dock.slots.js.map +0 -1
  1002. package/esm2022/page/lib/page-header/page-header.directives.js +0 -88
  1003. package/esm2022/page/lib/page-header/page-header.directives.js.map +0 -1
  1004. package/esm2022/page/lib/page-header/page-header.js +0 -124
  1005. package/esm2022/page/lib/page-header/page-header.js.map +0 -1
  1006. package/esm2022/page/lib/page-shell/page-shell-color.js +0 -193
  1007. package/esm2022/page/lib/page-shell/page-shell-color.js.map +0 -1
  1008. package/esm2022/page/lib/page-shell/page-shell-css-color.js +0 -207
  1009. package/esm2022/page/lib/page-shell/page-shell-css-color.js.map +0 -1
  1010. package/esm2022/page/lib/page-shell/page-shell.js +0 -131
  1011. package/esm2022/page/lib/page-shell/page-shell.js.map +0 -1
  1012. package/esm2022/page/lib/page-shell/page-shell.slots.js +0 -41
  1013. package/esm2022/page/lib/page-shell/page-shell.slots.js.map +0 -1
  1014. package/esm2022/page/lib/page-summary/page-summary-item.js +0 -26
  1015. package/esm2022/page/lib/page-summary/page-summary-item.js.map +0 -1
  1016. package/esm2022/page/lib/page-summary/page-summary.js +0 -87
  1017. package/esm2022/page/lib/page-summary/page-summary.js.map +0 -1
  1018. package/esm2022/page/malva-ui-core-page.js +0 -5
  1019. package/esm2022/page/malva-ui-core-page.js.map +0 -1
  1020. package/esm2022/pagination/index.js +0 -5
  1021. package/esm2022/pagination/index.js.map +0 -1
  1022. package/esm2022/pagination/lib/pagination/pagination.directives.js +0 -58
  1023. package/esm2022/pagination/lib/pagination/pagination.directives.js.map +0 -1
  1024. package/esm2022/pagination/lib/pagination/pagination.js +0 -293
  1025. package/esm2022/pagination/lib/pagination/pagination.js.map +0 -1
  1026. package/esm2022/pagination/lib/pagination/pagination.model.js +0 -1
  1027. package/esm2022/pagination/lib/pagination/pagination.model.js.map +0 -1
  1028. package/esm2022/pagination/lib/pagination/pagination.service.js +0 -108
  1029. package/esm2022/pagination/lib/pagination/pagination.service.js.map +0 -1
  1030. package/esm2022/pagination/malva-ui-core-pagination.js +0 -5
  1031. package/esm2022/pagination/malva-ui-core-pagination.js.map +0 -1
  1032. package/esm2022/pin-input/index.js +0 -3
  1033. package/esm2022/pin-input/index.js.map +0 -1
  1034. package/esm2022/pin-input/lib/pin-input/pin-input-separator.js +0 -31
  1035. package/esm2022/pin-input/lib/pin-input/pin-input-separator.js.map +0 -1
  1036. package/esm2022/pin-input/lib/pin-input/pin-input.js +0 -365
  1037. package/esm2022/pin-input/lib/pin-input/pin-input.js.map +0 -1
  1038. package/esm2022/pin-input/malva-ui-core-pin-input.js +0 -5
  1039. package/esm2022/pin-input/malva-ui-core-pin-input.js.map +0 -1
  1040. package/esm2022/popup/index.js +0 -10
  1041. package/esm2022/popup/index.js.map +0 -1
  1042. package/esm2022/popup/lib/popup/popup.js +0 -500
  1043. package/esm2022/popup/lib/popup/popup.js.map +0 -1
  1044. package/esm2022/popup/lib/popup-container/popup-container.js +0 -169
  1045. package/esm2022/popup/lib/popup-container/popup-container.js.map +0 -1
  1046. package/esm2022/popup/lib/popup-container/popup-container.token.js +0 -9
  1047. package/esm2022/popup/lib/popup-container/popup-container.token.js.map +0 -1
  1048. package/esm2022/popup/lib/popup-content.js +0 -14
  1049. package/esm2022/popup/lib/popup-content.js.map +0 -1
  1050. package/esm2022/popup/lib/popup-header-content.js +0 -26
  1051. package/esm2022/popup/lib/popup-header-content.js.map +0 -1
  1052. package/esm2022/popup/lib/popup-pinned-content.js +0 -25
  1053. package/esm2022/popup/lib/popup-pinned-content.js.map +0 -1
  1054. package/esm2022/popup/lib/popup-positions.js +0 -252
  1055. package/esm2022/popup/lib/popup-positions.js.map +0 -1
  1056. package/esm2022/popup/lib/popup-trigger/popup-trigger.js +0 -308
  1057. package/esm2022/popup/lib/popup-trigger/popup-trigger.js.map +0 -1
  1058. package/esm2022/popup/lib/popup.service.js +0 -188
  1059. package/esm2022/popup/lib/popup.service.js.map +0 -1
  1060. package/esm2022/popup/malva-ui-core-popup.js +0 -5
  1061. package/esm2022/popup/malva-ui-core-popup.js.map +0 -1
  1062. package/esm2022/progress/index.js +0 -2
  1063. package/esm2022/progress/index.js.map +0 -1
  1064. package/esm2022/progress/lib/progress/progress.js +0 -102
  1065. package/esm2022/progress/lib/progress/progress.js.map +0 -1
  1066. package/esm2022/progress/malva-ui-core-progress.js +0 -5
  1067. package/esm2022/progress/malva-ui-core-progress.js.map +0 -1
  1068. package/esm2022/radio/index.js +0 -3
  1069. package/esm2022/radio/index.js.map +0 -1
  1070. package/esm2022/radio/lib/radio/radio.js +0 -134
  1071. package/esm2022/radio/lib/radio/radio.js.map +0 -1
  1072. package/esm2022/radio/lib/radio-group/radio-group.js +0 -176
  1073. package/esm2022/radio/lib/radio-group/radio-group.js.map +0 -1
  1074. package/esm2022/radio/lib/radio-group-token.js +0 -3
  1075. package/esm2022/radio/lib/radio-group-token.js.map +0 -1
  1076. package/esm2022/radio/malva-ui-core-radio.js +0 -5
  1077. package/esm2022/radio/malva-ui-core-radio.js.map +0 -1
  1078. package/esm2022/rating/index.js +0 -2
  1079. package/esm2022/rating/index.js.map +0 -1
  1080. package/esm2022/rating/lib/rating/rating.js +0 -208
  1081. package/esm2022/rating/lib/rating/rating.js.map +0 -1
  1082. package/esm2022/rating/malva-ui-core-rating.js +0 -5
  1083. package/esm2022/rating/malva-ui-core-rating.js.map +0 -1
  1084. package/esm2022/scrollbar/index.js +0 -2
  1085. package/esm2022/scrollbar/index.js.map +0 -1
  1086. package/esm2022/scrollbar/lib/scrollbar/scrollbar.js +0 -388
  1087. package/esm2022/scrollbar/lib/scrollbar/scrollbar.js.map +0 -1
  1088. package/esm2022/scrollbar/malva-ui-core-scrollbar.js +0 -5
  1089. package/esm2022/scrollbar/malva-ui-core-scrollbar.js.map +0 -1
  1090. package/esm2022/search-field/index.js +0 -3
  1091. package/esm2022/search-field/index.js.map +0 -1
  1092. package/esm2022/search-field/lib/search-field/search-field.js +0 -535
  1093. package/esm2022/search-field/lib/search-field/search-field.js.map +0 -1
  1094. package/esm2022/search-field/lib/search-field/search-overlay-content.js +0 -35
  1095. package/esm2022/search-field/lib/search-field/search-overlay-content.js.map +0 -1
  1096. package/esm2022/search-field/malva-ui-core-search-field.js +0 -5
  1097. package/esm2022/search-field/malva-ui-core-search-field.js.map +0 -1
  1098. package/esm2022/segmented/index.js +0 -5
  1099. package/esm2022/segmented/index.js.map +0 -1
  1100. package/esm2022/segmented/lib/segmented/segmented.js +0 -248
  1101. package/esm2022/segmented/lib/segmented/segmented.js.map +0 -1
  1102. package/esm2022/segmented/lib/segmented-item/segmented-item.js +0 -194
  1103. package/esm2022/segmented/lib/segmented-item/segmented-item.js.map +0 -1
  1104. package/esm2022/segmented/lib/segmented-token.js +0 -4
  1105. package/esm2022/segmented/lib/segmented-token.js.map +0 -1
  1106. package/esm2022/segmented/lib/segmented.types.js +0 -1
  1107. package/esm2022/segmented/lib/segmented.types.js.map +0 -1
  1108. package/esm2022/segmented/malva-ui-core-segmented.js +0 -5
  1109. package/esm2022/segmented/malva-ui-core-segmented.js.map +0 -1
  1110. package/esm2022/select/index.js +0 -4
  1111. package/esm2022/select/index.js.map +0 -1
  1112. package/esm2022/select/lib/select/select.js +0 -685
  1113. package/esm2022/select/lib/select/select.js.map +0 -1
  1114. package/esm2022/select/lib/select-option.js +0 -2
  1115. package/esm2022/select/lib/select-option.js.map +0 -1
  1116. package/esm2022/select/lib/select-template.directives.js +0 -34
  1117. package/esm2022/select/lib/select-template.directives.js.map +0 -1
  1118. package/esm2022/select/malva-ui-core-select.js +0 -5
  1119. package/esm2022/select/malva-ui-core-select.js.map +0 -1
  1120. package/esm2022/sidebar/index.js +0 -16
  1121. package/esm2022/sidebar/index.js.map +0 -1
  1122. package/esm2022/sidebar/lib/sidebar/sidebar.js +0 -251
  1123. package/esm2022/sidebar/lib/sidebar/sidebar.js.map +0 -1
  1124. package/esm2022/sidebar/lib/sidebar-content.js +0 -37
  1125. package/esm2022/sidebar/lib/sidebar-content.js.map +0 -1
  1126. package/esm2022/sidebar/lib/sidebar-context.js +0 -3
  1127. package/esm2022/sidebar/lib/sidebar-context.js.map +0 -1
  1128. package/esm2022/sidebar/lib/sidebar-footer.js +0 -20
  1129. package/esm2022/sidebar/lib/sidebar-footer.js.map +0 -1
  1130. package/esm2022/sidebar/lib/sidebar-group/sidebar-group.js +0 -341
  1131. package/esm2022/sidebar/lib/sidebar-group/sidebar-group.js.map +0 -1
  1132. package/esm2022/sidebar/lib/sidebar-header.js +0 -20
  1133. package/esm2022/sidebar/lib/sidebar-header.js.map +0 -1
  1134. package/esm2022/sidebar/lib/sidebar-item/sidebar-item.js +0 -216
  1135. package/esm2022/sidebar/lib/sidebar-item/sidebar-item.js.map +0 -1
  1136. package/esm2022/sidebar/lib/sidebar-item-host.js +0 -39
  1137. package/esm2022/sidebar/lib/sidebar-item-host.js.map +0 -1
  1138. package/esm2022/sidebar/lib/sidebar-item-icon.js +0 -14
  1139. package/esm2022/sidebar/lib/sidebar-item-icon.js.map +0 -1
  1140. package/esm2022/sidebar/lib/sidebar-mode.js +0 -1
  1141. package/esm2022/sidebar/lib/sidebar-mode.js.map +0 -1
  1142. package/esm2022/sidebar/lib/sidebar-rail/sidebar-rail.js +0 -202
  1143. package/esm2022/sidebar/lib/sidebar-rail/sidebar-rail.js.map +0 -1
  1144. package/esm2022/sidebar/lib/sidebar-trigger/sidebar-trigger.js +0 -159
  1145. package/esm2022/sidebar/lib/sidebar-trigger/sidebar-trigger.js.map +0 -1
  1146. package/esm2022/sidebar/lib/sidebar-workspace/sidebar-workspace.directives.js +0 -35
  1147. package/esm2022/sidebar/lib/sidebar-workspace/sidebar-workspace.directives.js.map +0 -1
  1148. package/esm2022/sidebar/lib/sidebar-workspace/sidebar-workspace.js +0 -107
  1149. package/esm2022/sidebar/lib/sidebar-workspace/sidebar-workspace.js.map +0 -1
  1150. package/esm2022/sidebar/lib/sidebar-workspace/sidebar-workspace.types.js +0 -1
  1151. package/esm2022/sidebar/lib/sidebar-workspace/sidebar-workspace.types.js.map +0 -1
  1152. package/esm2022/sidebar/malva-ui-core-sidebar.js +0 -5
  1153. package/esm2022/sidebar/malva-ui-core-sidebar.js.map +0 -1
  1154. package/esm2022/skeleton/index.js +0 -2
  1155. package/esm2022/skeleton/index.js.map +0 -1
  1156. package/esm2022/skeleton/lib/skeleton/skeleton.js +0 -78
  1157. package/esm2022/skeleton/lib/skeleton/skeleton.js.map +0 -1
  1158. package/esm2022/skeleton/malva-ui-core-skeleton.js +0 -5
  1159. package/esm2022/skeleton/malva-ui-core-skeleton.js.map +0 -1
  1160. package/esm2022/slider/index.js +0 -3
  1161. package/esm2022/slider/index.js.map +0 -1
  1162. package/esm2022/slider/lib/slider/slider-tooltip-def.js +0 -31
  1163. package/esm2022/slider/lib/slider/slider-tooltip-def.js.map +0 -1
  1164. package/esm2022/slider/lib/slider/slider.js +0 -468
  1165. package/esm2022/slider/lib/slider/slider.js.map +0 -1
  1166. package/esm2022/slider/malva-ui-core-slider.js +0 -5
  1167. package/esm2022/slider/malva-ui-core-slider.js.map +0 -1
  1168. package/esm2022/split-pane/index.js +0 -4
  1169. package/esm2022/split-pane/index.js.map +0 -1
  1170. package/esm2022/split-pane/lib/split-pane/split-pane-panel.js +0 -49
  1171. package/esm2022/split-pane/lib/split-pane/split-pane-panel.js.map +0 -1
  1172. package/esm2022/split-pane/lib/split-pane/split-pane.js +0 -290
  1173. package/esm2022/split-pane/lib/split-pane/split-pane.js.map +0 -1
  1174. package/esm2022/split-pane/lib/split-pane/split-pane.types.js +0 -1
  1175. package/esm2022/split-pane/lib/split-pane/split-pane.types.js.map +0 -1
  1176. package/esm2022/split-pane/malva-ui-core-split-pane.js +0 -5
  1177. package/esm2022/split-pane/malva-ui-core-split-pane.js.map +0 -1
  1178. package/esm2022/status-indicator/index.js +0 -2
  1179. package/esm2022/status-indicator/index.js.map +0 -1
  1180. package/esm2022/status-indicator/lib/status-indicator/status-indicator.js +0 -71
  1181. package/esm2022/status-indicator/lib/status-indicator/status-indicator.js.map +0 -1
  1182. package/esm2022/status-indicator/malva-ui-core-status-indicator.js +0 -5
  1183. package/esm2022/status-indicator/malva-ui-core-status-indicator.js.map +0 -1
  1184. package/esm2022/stepper/index.js +0 -5
  1185. package/esm2022/stepper/index.js.map +0 -1
  1186. package/esm2022/stepper/lib/stepper/step-header.js +0 -46
  1187. package/esm2022/stepper/lib/stepper/step-header.js.map +0 -1
  1188. package/esm2022/stepper/lib/stepper/step.js +0 -65
  1189. package/esm2022/stepper/lib/stepper/step.js.map +0 -1
  1190. package/esm2022/stepper/lib/stepper/stepper-token.js +0 -4
  1191. package/esm2022/stepper/lib/stepper/stepper-token.js.map +0 -1
  1192. package/esm2022/stepper/lib/stepper/stepper.js +0 -216
  1193. package/esm2022/stepper/lib/stepper/stepper.js.map +0 -1
  1194. package/esm2022/stepper/lib/stepper/stepper.types.js +0 -1
  1195. package/esm2022/stepper/lib/stepper/stepper.types.js.map +0 -1
  1196. package/esm2022/stepper/malva-ui-core-stepper.js +0 -5
  1197. package/esm2022/stepper/malva-ui-core-stepper.js.map +0 -1
  1198. package/esm2022/switch/index.js +0 -3
  1199. package/esm2022/switch/index.js.map +0 -1
  1200. package/esm2022/switch/lib/switch/switch.js +0 -190
  1201. package/esm2022/switch/lib/switch/switch.js.map +0 -1
  1202. package/esm2022/switch/lib/switch-group/switch-group.js +0 -68
  1203. package/esm2022/switch/lib/switch-group/switch-group.js.map +0 -1
  1204. package/esm2022/switch/lib/switch-group-token.js +0 -3
  1205. package/esm2022/switch/lib/switch-group-token.js.map +0 -1
  1206. package/esm2022/switch/malva-ui-core-switch.js +0 -5
  1207. package/esm2022/switch/malva-ui-core-switch.js.map +0 -1
  1208. package/esm2022/tabs/index.js +0 -9
  1209. package/esm2022/tabs/index.js.map +0 -1
  1210. package/esm2022/tabs/lib/tab/tab.js +0 -72
  1211. package/esm2022/tabs/lib/tab/tab.js.map +0 -1
  1212. package/esm2022/tabs/lib/tab-content/tab-content.js +0 -19
  1213. package/esm2022/tabs/lib/tab-content/tab-content.js.map +0 -1
  1214. package/esm2022/tabs/lib/tab-content-def.js +0 -14
  1215. package/esm2022/tabs/lib/tab-content-def.js.map +0 -1
  1216. package/esm2022/tabs/lib/tab-def.js +0 -17
  1217. package/esm2022/tabs/lib/tab-def.js.map +0 -1
  1218. package/esm2022/tabs/lib/tab-group-token.js +0 -3
  1219. package/esm2022/tabs/lib/tab-group-token.js.map +0 -1
  1220. package/esm2022/tabs/lib/tab-item/tab-item.js +0 -44
  1221. package/esm2022/tabs/lib/tab-item/tab-item.js.map +0 -1
  1222. package/esm2022/tabs/lib/tabs/tabs.js +0 -542
  1223. package/esm2022/tabs/lib/tabs/tabs.js.map +0 -1
  1224. package/esm2022/tabs/lib/tabs.service.js +0 -83
  1225. package/esm2022/tabs/lib/tabs.service.js.map +0 -1
  1226. package/esm2022/tabs/malva-ui-core-tabs.js +0 -5
  1227. package/esm2022/tabs/malva-ui-core-tabs.js.map +0 -1
  1228. package/esm2022/textarea/index.js +0 -2
  1229. package/esm2022/textarea/index.js.map +0 -1
  1230. package/esm2022/textarea/lib/textarea/textarea.js +0 -194
  1231. package/esm2022/textarea/lib/textarea/textarea.js.map +0 -1
  1232. package/esm2022/textarea/malva-ui-core-textarea.js +0 -5
  1233. package/esm2022/textarea/malva-ui-core-textarea.js.map +0 -1
  1234. package/esm2022/tile/index.js +0 -3
  1235. package/esm2022/tile/index.js.map +0 -1
  1236. package/esm2022/tile/lib/tile/tile.js +0 -39
  1237. package/esm2022/tile/lib/tile/tile.js.map +0 -1
  1238. package/esm2022/tile/lib/tile-header.js +0 -14
  1239. package/esm2022/tile/lib/tile-header.js.map +0 -1
  1240. package/esm2022/tile/malva-ui-core-tile.js +0 -5
  1241. package/esm2022/tile/malva-ui-core-tile.js.map +0 -1
  1242. package/esm2022/time-picker/index.js +0 -2
  1243. package/esm2022/time-picker/index.js.map +0 -1
  1244. package/esm2022/time-picker/lib/time-picker/time-picker.js +0 -310
  1245. package/esm2022/time-picker/lib/time-picker/time-picker.js.map +0 -1
  1246. package/esm2022/time-picker/lib/time-picker-column/time-picker-column.js +0 -216
  1247. package/esm2022/time-picker/lib/time-picker-column/time-picker-column.js.map +0 -1
  1248. package/esm2022/time-picker/malva-ui-core-time-picker.js +0 -5
  1249. package/esm2022/time-picker/malva-ui-core-time-picker.js.map +0 -1
  1250. package/esm2022/timeline/index.js +0 -6
  1251. package/esm2022/timeline/index.js.map +0 -1
  1252. package/esm2022/timeline/lib/timeline/timeline-item-icon.js +0 -31
  1253. package/esm2022/timeline/lib/timeline/timeline-item-icon.js.map +0 -1
  1254. package/esm2022/timeline/lib/timeline/timeline-item-meta.js +0 -31
  1255. package/esm2022/timeline/lib/timeline/timeline-item-meta.js.map +0 -1
  1256. package/esm2022/timeline/lib/timeline/timeline-item.js +0 -69
  1257. package/esm2022/timeline/lib/timeline/timeline-item.js.map +0 -1
  1258. package/esm2022/timeline/lib/timeline/timeline.js +0 -36
  1259. package/esm2022/timeline/lib/timeline/timeline.js.map +0 -1
  1260. package/esm2022/timeline/lib/timeline/timeline.types.js +0 -1
  1261. package/esm2022/timeline/lib/timeline/timeline.types.js.map +0 -1
  1262. package/esm2022/timeline/malva-ui-core-timeline.js +0 -5
  1263. package/esm2022/timeline/malva-ui-core-timeline.js.map +0 -1
  1264. package/esm2022/title/index.js +0 -2
  1265. package/esm2022/title/index.js.map +0 -1
  1266. package/esm2022/title/lib/title/title.js +0 -171
  1267. package/esm2022/title/lib/title/title.js.map +0 -1
  1268. package/esm2022/title/malva-ui-core-title.js +0 -5
  1269. package/esm2022/title/malva-ui-core-title.js.map +0 -1
  1270. package/esm2022/toast/index.js +0 -13
  1271. package/esm2022/toast/index.js.map +0 -1
  1272. package/esm2022/toast/lib/abstract-toast-container.js +0 -50
  1273. package/esm2022/toast/lib/abstract-toast-container.js.map +0 -1
  1274. package/esm2022/toast/lib/abstract-toast-item.js +0 -75
  1275. package/esm2022/toast/lib/abstract-toast-item.js.map +0 -1
  1276. package/esm2022/toast/lib/abstract-toast.service.js +0 -176
  1277. package/esm2022/toast/lib/abstract-toast.service.js.map +0 -1
  1278. package/esm2022/toast/lib/toast-container/toast-container.js +0 -61
  1279. package/esm2022/toast/lib/toast-container/toast-container.js.map +0 -1
  1280. package/esm2022/toast/lib/toast-item/toast-item.js +0 -62
  1281. package/esm2022/toast/lib/toast-item/toast-item.js.map +0 -1
  1282. package/esm2022/toast/lib/toast-ref.js +0 -54
  1283. package/esm2022/toast/lib/toast-ref.js.map +0 -1
  1284. package/esm2022/toast/lib/toast-timer.js +0 -37
  1285. package/esm2022/toast/lib/toast-timer.js.map +0 -1
  1286. package/esm2022/toast/lib/toast.directives.js +0 -76
  1287. package/esm2022/toast/lib/toast.directives.js.map +0 -1
  1288. package/esm2022/toast/lib/toast.service.js +0 -127
  1289. package/esm2022/toast/lib/toast.service.js.map +0 -1
  1290. package/esm2022/toast/lib/toast.types.js +0 -39
  1291. package/esm2022/toast/lib/toast.types.js.map +0 -1
  1292. package/esm2022/toast/malva-ui-core-toast.js +0 -5
  1293. package/esm2022/toast/malva-ui-core-toast.js.map +0 -1
  1294. package/esm2022/tokenizer/index.js +0 -4
  1295. package/esm2022/tokenizer/index.js.map +0 -1
  1296. package/esm2022/tokenizer/lib/token/token.js +0 -123
  1297. package/esm2022/tokenizer/lib/token/token.js.map +0 -1
  1298. package/esm2022/tokenizer/lib/token-template.js +0 -23
  1299. package/esm2022/tokenizer/lib/token-template.js.map +0 -1
  1300. package/esm2022/tokenizer/lib/tokenizer/tokenizer.js +0 -324
  1301. package/esm2022/tokenizer/lib/tokenizer/tokenizer.js.map +0 -1
  1302. package/esm2022/tokenizer/malva-ui-core-tokenizer.js +0 -5
  1303. package/esm2022/tokenizer/malva-ui-core-tokenizer.js.map +0 -1
  1304. package/esm2022/toolbar/index.js +0 -4
  1305. package/esm2022/toolbar/index.js.map +0 -1
  1306. package/esm2022/toolbar/lib/toolbar/toolbar-spacer.js +0 -13
  1307. package/esm2022/toolbar/lib/toolbar/toolbar-spacer.js.map +0 -1
  1308. package/esm2022/toolbar/lib/toolbar/toolbar-widget.js +0 -106
  1309. package/esm2022/toolbar/lib/toolbar/toolbar-widget.js.map +0 -1
  1310. package/esm2022/toolbar/lib/toolbar/toolbar.js +0 -19
  1311. package/esm2022/toolbar/lib/toolbar/toolbar.js.map +0 -1
  1312. package/esm2022/toolbar/malva-ui-core-toolbar.js +0 -5
  1313. package/esm2022/toolbar/malva-ui-core-toolbar.js.map +0 -1
  1314. package/esm2022/tooltip/index.js +0 -4
  1315. package/esm2022/tooltip/index.js.map +0 -1
  1316. package/esm2022/tooltip/lib/tooltip/tooltip-panel.js +0 -69
  1317. package/esm2022/tooltip/lib/tooltip/tooltip-panel.js.map +0 -1
  1318. package/esm2022/tooltip/lib/tooltip/tooltip.js +0 -352
  1319. package/esm2022/tooltip/lib/tooltip/tooltip.js.map +0 -1
  1320. package/esm2022/tooltip/lib/tooltip/tooltip.types.js +0 -1
  1321. package/esm2022/tooltip/lib/tooltip/tooltip.types.js.map +0 -1
  1322. package/esm2022/tooltip/malva-ui-core-tooltip.js +0 -5
  1323. package/esm2022/tooltip/malva-ui-core-tooltip.js.map +0 -1
  1324. package/esm2022/tree/index.js +0 -5
  1325. package/esm2022/tree/index.js.map +0 -1
  1326. package/esm2022/tree/lib/tree/tree-context.js +0 -7
  1327. package/esm2022/tree/lib/tree/tree-context.js.map +0 -1
  1328. package/esm2022/tree/lib/tree/tree-node-def.js +0 -34
  1329. package/esm2022/tree/lib/tree/tree-node-def.js.map +0 -1
  1330. package/esm2022/tree/lib/tree/tree-node.js +0 -1
  1331. package/esm2022/tree/lib/tree/tree-node.js.map +0 -1
  1332. package/esm2022/tree/lib/tree/tree-subtree.js +0 -107
  1333. package/esm2022/tree/lib/tree/tree-subtree.js.map +0 -1
  1334. package/esm2022/tree/lib/tree/tree.js +0 -362
  1335. package/esm2022/tree/lib/tree/tree.js.map +0 -1
  1336. package/esm2022/tree/malva-ui-core-tree.js +0 -5
  1337. package/esm2022/tree/malva-ui-core-tree.js.map +0 -1
  1338. package/expand/index.d.ts +0 -2
  1339. package/expand/lib/expand/expand-content.d.ts +0 -26
  1340. package/expand/lib/expand/expand.d.ts +0 -74
  1341. package/expand/malva-ui-core-expand.d.ts +0 -5
  1342. package/file-upload/index.d.ts +0 -4
  1343. package/file-upload/lib/file-upload/file-upload.d.ts +0 -138
  1344. package/file-upload/lib/file-upload/file-upload.types.d.ts +0 -42
  1345. package/file-upload/lib/file-upload-action.d.ts +0 -53
  1346. package/file-upload/lib/file-upload-item/file-upload-item.d.ts +0 -30
  1347. package/file-upload/malva-ui-core-file-upload.d.ts +0 -5
  1348. package/filter/index.d.ts +0 -3
  1349. package/filter/lib/filter/filter.d.ts +0 -156
  1350. package/filter/lib/filter.types.d.ts +0 -75
  1351. package/filter/lib/smart-filter-bar/smart-filter-bar.d.ts +0 -153
  1352. package/filter/malva-ui-core-filter.d.ts +0 -5
  1353. package/form/index.d.ts +0 -6
  1354. package/form/lib/fieldset/fieldset.d.ts +0 -58
  1355. package/form/lib/fieldset-span.d.ts +0 -28
  1356. package/form/lib/form/form.d.ts +0 -37
  1357. package/form/lib/form-actions.d.ts +0 -20
  1358. package/form/lib/form-gap.d.ts +0 -5
  1359. package/form/lib/form-header.d.ts +0 -18
  1360. package/form/lib/form.types.d.ts +0 -13
  1361. package/form/malva-ui-core-form.d.ts +0 -5
  1362. package/form-utils/index.d.ts +0 -15
  1363. package/form-utils/lib/aria-value-bridge.d.ts +0 -45
  1364. package/form-utils/lib/description/description.d.ts +0 -16
  1365. package/form-utils/lib/focusable-group-base.d.ts +0 -76
  1366. package/form-utils/lib/form-control-base/signal-form-control-base.d.ts +0 -159
  1367. package/form-utils/lib/form-control-sides.d.ts +0 -20
  1368. package/form-utils/lib/form-control-wrapper/form-control-wrapper-control.d.ts +0 -6
  1369. package/form-utils/lib/form-control-wrapper/form-control-wrapper.d.ts +0 -20
  1370. package/form-utils/lib/form-field/form-field.d.ts +0 -68
  1371. package/form-utils/lib/hint/hint.d.ts +0 -5
  1372. package/form-utils/lib/label/label.d.ts +0 -22
  1373. package/form-utils/lib/message/message.d.ts +0 -7
  1374. package/form-utils/lib/models/error-display-strategy.d.ts +0 -1
  1375. package/form-utils/lib/models/form-control-connector.d.ts +0 -41
  1376. package/form-utils/lib/models/form-state.d.ts +0 -1
  1377. package/form-utils/lib/selection.service.d.ts +0 -27
  1378. package/form-utils/malva-ui-core-form-utils.d.ts +0 -5
  1379. package/form-utils/testing/index.d.ts +0 -1
  1380. package/form-utils/testing/lib/forms-binding-matrix.d.ts +0 -47
  1381. package/form-utils/testing/malva-ui-core-form-utils-testing.d.ts +0 -5
  1382. package/index.d.ts +0 -69
  1383. package/input/index.d.ts +0 -3
  1384. package/input/lib/input/input-native.d.ts +0 -36
  1385. package/input/lib/input/input-value-accessor.d.ts +0 -11
  1386. package/input/lib/input/input.d.ts +0 -189
  1387. package/input/lib/input/password-strength.d.ts +0 -34
  1388. package/input/malva-ui-core-input.d.ts +0 -5
  1389. package/kbd/index.d.ts +0 -1
  1390. package/kbd/lib/kbd/kbd.d.ts +0 -52
  1391. package/kbd/malva-ui-core-kbd.d.ts +0 -5
  1392. package/layout/index.d.ts +0 -4
  1393. package/layout/lib/layout/directives/MlvLayoutSide.d.ts +0 -6
  1394. package/layout/lib/layout/directives/MlvLayoutTop.d.ts +0 -6
  1395. package/layout/lib/layout/layout.d.ts +0 -20
  1396. package/layout/lib/layout/services/theme.service.d.ts +0 -33
  1397. package/layout/malva-ui-core-layout.d.ts +0 -5
  1398. package/link/index.d.ts +0 -2
  1399. package/link/lib/link/link.d.ts +0 -15
  1400. package/link/lib/link/link.directives.d.ts +0 -10
  1401. package/link/malva-ui-core-link.d.ts +0 -5
  1402. package/list/index.d.ts +0 -13
  1403. package/list/lib/list/list.d.ts +0 -25
  1404. package/list/lib/list-item/list-item.d.ts +0 -67
  1405. package/list/lib/list-item-actions.d.ts +0 -12
  1406. package/list/lib/list-item-byline.d.ts +0 -5
  1407. package/list/lib/list-item-group/list-item-group.d.ts +0 -11
  1408. package/list/lib/list-item-link/list-item-link.d.ts +0 -8
  1409. package/list/lib/list-item-media.d.ts +0 -5
  1410. package/list/lib/list-item-meta.d.ts +0 -5
  1411. package/list/lib/list-item-prefix.d.ts +0 -5
  1412. package/list/lib/list-item-suffix.d.ts +0 -5
  1413. package/list/lib/list-item-template.d.ts +0 -10
  1414. package/list/lib/list-item-title.d.ts +0 -5
  1415. package/list/lib/list-selectable.d.ts +0 -73
  1416. package/list/malva-ui-core-list.d.ts +0 -5
  1417. package/loader/index.d.ts +0 -1
  1418. package/loader/lib/loader/loader.d.ts +0 -84
  1419. package/loader/malva-ui-core-loader.d.ts +0 -5
  1420. package/malva-ui-core.d.ts +0 -5
  1421. package/menu/index.d.ts +0 -9
  1422. package/menu/lib/menu/menu-group-label.d.ts +0 -22
  1423. package/menu/lib/menu/menu-group.d.ts +0 -27
  1424. package/menu/lib/menu/menu-item.d.ts +0 -76
  1425. package/menu/lib/menu/menu-separator.d.ts +0 -18
  1426. package/menu/lib/menu/menu-trigger.d.ts +0 -255
  1427. package/menu/lib/menu/menu.d.ts +0 -149
  1428. package/menu/lib/menu/menu.types.d.ts +0 -13
  1429. package/menu/lib/menu/menubar.d.ts +0 -131
  1430. package/menu/lib/menu/menubar.types.d.ts +0 -82
  1431. package/menu/lib/menu/submenu-aim.d.ts +0 -10
  1432. package/menu/malva-ui-core-menu.d.ts +0 -5
  1433. package/notification/index.d.ts +0 -4
  1434. package/notification/lib/notification-item/notification-item.d.ts +0 -20
  1435. package/notification/lib/notification-ref.d.ts +0 -12
  1436. package/notification/lib/notification.service.d.ts +0 -43
  1437. package/notification/lib/notification.types.d.ts +0 -52
  1438. package/notification/malva-ui-core-notification.d.ts +0 -5
  1439. package/number-input/index.d.ts +0 -1
  1440. package/number-input/lib/number-input/number-input.d.ts +0 -162
  1441. package/number-input/malva-ui-core-number-input.d.ts +0 -5
  1442. package/page/index.d.ts +0 -14
  1443. package/page/lib/page/page-scroll.token.d.ts +0 -19
  1444. package/page/lib/page/page-snap-controller.d.ts +0 -87
  1445. package/page/lib/page/page-snap.directive.d.ts +0 -40
  1446. package/page/lib/page/page.d.ts +0 -74
  1447. package/page/lib/page-content/page-aside.d.ts +0 -7
  1448. package/page/lib/page-content/page-content.d.ts +0 -37
  1449. package/page/lib/page-dock/page-dock.d.ts +0 -50
  1450. package/page/lib/page-dock/page-dock.slots.d.ts +0 -16
  1451. package/page/lib/page-header/page-header.d.ts +0 -77
  1452. package/page/lib/page-header/page-header.directives.d.ts +0 -50
  1453. package/page/lib/page-shell/page-shell-color.d.ts +0 -48
  1454. package/page/lib/page-shell/page-shell-css-color.d.ts +0 -20
  1455. package/page/lib/page-shell/page-shell.d.ts +0 -44
  1456. package/page/lib/page-shell/page-shell.slots.d.ts +0 -16
  1457. package/page/lib/page-summary/page-summary-item.d.ts +0 -11
  1458. package/page/lib/page-summary/page-summary.d.ts +0 -36
  1459. package/page/malva-ui-core-page.d.ts +0 -5
  1460. package/pagination/index.d.ts +0 -4
  1461. package/pagination/lib/pagination/pagination.d.ts +0 -182
  1462. package/pagination/lib/pagination/pagination.directives.d.ts +0 -44
  1463. package/pagination/lib/pagination/pagination.model.d.ts +0 -6
  1464. package/pagination/lib/pagination/pagination.service.d.ts +0 -26
  1465. package/pagination/malva-ui-core-pagination.d.ts +0 -5
  1466. package/pin-input/index.d.ts +0 -2
  1467. package/pin-input/lib/pin-input/pin-input-separator.d.ts +0 -24
  1468. package/pin-input/lib/pin-input/pin-input.d.ts +0 -176
  1469. package/pin-input/malva-ui-core-pin-input.d.ts +0 -5
  1470. package/popup/index.d.ts +0 -9
  1471. package/popup/lib/popup/popup.d.ts +0 -343
  1472. package/popup/lib/popup-container/popup-container.d.ts +0 -61
  1473. package/popup/lib/popup-container/popup-container.token.d.ts +0 -34
  1474. package/popup/lib/popup-content.d.ts +0 -6
  1475. package/popup/lib/popup-header-content.d.ts +0 -18
  1476. package/popup/lib/popup-pinned-content.d.ts +0 -17
  1477. package/popup/lib/popup-positions.d.ts +0 -105
  1478. package/popup/lib/popup-trigger/popup-trigger.d.ts +0 -102
  1479. package/popup/lib/popup.service.d.ts +0 -159
  1480. package/popup/malva-ui-core-popup.d.ts +0 -5
  1481. package/progress/index.d.ts +0 -1
  1482. package/progress/lib/progress/progress.d.ts +0 -69
  1483. package/progress/malva-ui-core-progress.d.ts +0 -5
  1484. package/radio/index.d.ts +0 -2
  1485. package/radio/lib/radio/radio.d.ts +0 -87
  1486. package/radio/lib/radio-group/radio-group.d.ts +0 -35
  1487. package/radio/lib/radio-group-token.d.ts +0 -7
  1488. package/radio/malva-ui-core-radio.d.ts +0 -5
  1489. package/rating/index.d.ts +0 -1
  1490. package/rating/lib/rating/rating.d.ts +0 -100
  1491. package/rating/malva-ui-core-rating.d.ts +0 -5
  1492. package/scrollbar/index.d.ts +0 -1
  1493. package/scrollbar/lib/scrollbar/scrollbar.d.ts +0 -166
  1494. package/scrollbar/malva-ui-core-scrollbar.d.ts +0 -5
  1495. package/search-field/index.d.ts +0 -2
  1496. package/search-field/lib/search-field/search-field.d.ts +0 -347
  1497. package/search-field/lib/search-field/search-overlay-content.d.ts +0 -59
  1498. package/search-field/malva-ui-core-search-field.d.ts +0 -5
  1499. package/segmented/index.d.ts +0 -4
  1500. package/segmented/lib/segmented/segmented.d.ts +0 -80
  1501. package/segmented/lib/segmented-item/segmented-item.d.ts +0 -89
  1502. package/segmented/lib/segmented-token.d.ts +0 -22
  1503. package/segmented/lib/segmented.types.d.ts +0 -9
  1504. package/segmented/malva-ui-core-segmented.d.ts +0 -5
  1505. package/select/index.d.ts +0 -3
  1506. package/select/lib/select/select.d.ts +0 -379
  1507. package/select/lib/select-option.d.ts +0 -1
  1508. package/select/lib/select-template.directives.d.ts +0 -14
  1509. package/select/malva-ui-core-select.d.ts +0 -5
  1510. package/sidebar/index.d.ts +0 -15
  1511. package/sidebar/lib/sidebar/sidebar.d.ts +0 -134
  1512. package/sidebar/lib/sidebar-content.d.ts +0 -11
  1513. package/sidebar/lib/sidebar-context.d.ts +0 -23
  1514. package/sidebar/lib/sidebar-footer.d.ts +0 -9
  1515. package/sidebar/lib/sidebar-group/sidebar-group.d.ts +0 -127
  1516. package/sidebar/lib/sidebar-header.d.ts +0 -9
  1517. package/sidebar/lib/sidebar-item/sidebar-item.d.ts +0 -104
  1518. package/sidebar/lib/sidebar-item-host.d.ts +0 -18
  1519. package/sidebar/lib/sidebar-item-icon.d.ts +0 -6
  1520. package/sidebar/lib/sidebar-mode.d.ts +0 -2
  1521. package/sidebar/lib/sidebar-rail/sidebar-rail.d.ts +0 -54
  1522. package/sidebar/lib/sidebar-trigger/sidebar-trigger.d.ts +0 -67
  1523. package/sidebar/lib/sidebar-workspace/sidebar-workspace.d.ts +0 -54
  1524. package/sidebar/lib/sidebar-workspace/sidebar-workspace.directives.d.ts +0 -19
  1525. package/sidebar/lib/sidebar-workspace/sidebar-workspace.types.d.ts +0 -20
  1526. package/sidebar/malva-ui-core-sidebar.d.ts +0 -5
  1527. package/skeleton/index.d.ts +0 -1
  1528. package/skeleton/lib/skeleton/skeleton.d.ts +0 -60
  1529. package/skeleton/malva-ui-core-skeleton.d.ts +0 -5
  1530. package/slider/index.d.ts +0 -2
  1531. package/slider/lib/slider/slider-tooltip-def.d.ts +0 -39
  1532. package/slider/lib/slider/slider.d.ts +0 -171
  1533. package/slider/malva-ui-core-slider.d.ts +0 -5
  1534. package/split-pane/index.d.ts +0 -3
  1535. package/split-pane/lib/split-pane/split-pane-panel.d.ts +0 -34
  1536. package/split-pane/lib/split-pane/split-pane.d.ts +0 -98
  1537. package/split-pane/lib/split-pane/split-pane.types.d.ts +0 -7
  1538. package/split-pane/malva-ui-core-split-pane.d.ts +0 -5
  1539. package/status-indicator/index.d.ts +0 -1
  1540. package/status-indicator/lib/status-indicator/status-indicator.d.ts +0 -61
  1541. package/status-indicator/malva-ui-core-status-indicator.d.ts +0 -5
  1542. package/stepper/index.d.ts +0 -4
  1543. package/stepper/lib/stepper/step-header.d.ts +0 -34
  1544. package/stepper/lib/stepper/step.d.ts +0 -51
  1545. package/stepper/lib/stepper/stepper-token.d.ts +0 -13
  1546. package/stepper/lib/stepper/stepper.d.ts +0 -98
  1547. package/stepper/lib/stepper/stepper.types.d.ts +0 -4
  1548. package/stepper/malva-ui-core-stepper.d.ts +0 -5
  1549. package/switch/index.d.ts +0 -2
  1550. package/switch/lib/switch/switch.d.ts +0 -118
  1551. package/switch/lib/switch-group/switch-group.d.ts +0 -24
  1552. package/switch/lib/switch-group-token.d.ts +0 -6
  1553. package/switch/malva-ui-core-switch.d.ts +0 -5
  1554. package/tabs/index.d.ts +0 -8
  1555. package/tabs/lib/tab/tab.d.ts +0 -46
  1556. package/tabs/lib/tab-content/tab-content.d.ts +0 -11
  1557. package/tabs/lib/tab-content-def.d.ts +0 -6
  1558. package/tabs/lib/tab-def.d.ts +0 -11
  1559. package/tabs/lib/tab-group-token.d.ts +0 -10
  1560. package/tabs/lib/tab-item/tab-item.d.ts +0 -28
  1561. package/tabs/lib/tabs/tabs.d.ts +0 -202
  1562. package/tabs/lib/tabs.service.d.ts +0 -24
  1563. package/tabs/malva-ui-core-tabs.d.ts +0 -5
  1564. package/textarea/index.d.ts +0 -1
  1565. package/textarea/lib/textarea/textarea.d.ts +0 -77
  1566. package/textarea/malva-ui-core-textarea.d.ts +0 -5
  1567. package/tile/index.d.ts +0 -2
  1568. package/tile/lib/tile/tile.d.ts +0 -20
  1569. package/tile/lib/tile-header.d.ts +0 -6
  1570. package/tile/malva-ui-core-tile.d.ts +0 -5
  1571. package/time-picker/index.d.ts +0 -1
  1572. package/time-picker/lib/time-picker/time-picker.d.ts +0 -135
  1573. package/time-picker/lib/time-picker-column/time-picker-column.d.ts +0 -111
  1574. package/time-picker/malva-ui-core-time-picker.d.ts +0 -5
  1575. package/timeline/index.d.ts +0 -5
  1576. package/timeline/lib/timeline/timeline-item-icon.d.ts +0 -24
  1577. package/timeline/lib/timeline/timeline-item-meta.d.ts +0 -24
  1578. package/timeline/lib/timeline/timeline-item.d.ts +0 -52
  1579. package/timeline/lib/timeline/timeline.d.ts +0 -27
  1580. package/timeline/lib/timeline/timeline.types.d.ts +0 -18
  1581. package/timeline/malva-ui-core-timeline.d.ts +0 -5
  1582. package/title/index.d.ts +0 -1
  1583. package/title/lib/title/title.d.ts +0 -63
  1584. package/title/malva-ui-core-title.d.ts +0 -5
  1585. package/toast/index.d.ts +0 -10
  1586. package/toast/lib/abstract-toast-container.d.ts +0 -29
  1587. package/toast/lib/abstract-toast-item.d.ts +0 -44
  1588. package/toast/lib/abstract-toast.service.d.ts +0 -75
  1589. package/toast/lib/toast-container/toast-container.d.ts +0 -23
  1590. package/toast/lib/toast-item/toast-item.d.ts +0 -25
  1591. package/toast/lib/toast-ref.d.ts +0 -33
  1592. package/toast/lib/toast-timer.d.ts +0 -24
  1593. package/toast/lib/toast.directives.d.ts +0 -13
  1594. package/toast/lib/toast.service.d.ts +0 -41
  1595. package/toast/lib/toast.types.d.ts +0 -139
  1596. package/toast/malva-ui-core-toast.d.ts +0 -5
  1597. package/tokenizer/index.d.ts +0 -3
  1598. package/tokenizer/lib/token/token.d.ts +0 -60
  1599. package/tokenizer/lib/token-template.d.ts +0 -29
  1600. package/tokenizer/lib/tokenizer/tokenizer.d.ts +0 -109
  1601. package/tokenizer/malva-ui-core-tokenizer.d.ts +0 -5
  1602. package/toolbar/index.d.ts +0 -3
  1603. package/toolbar/lib/toolbar/toolbar-spacer.d.ts +0 -5
  1604. package/toolbar/lib/toolbar/toolbar-widget.d.ts +0 -75
  1605. package/toolbar/lib/toolbar/toolbar.d.ts +0 -8
  1606. package/toolbar/malva-ui-core-toolbar.d.ts +0 -5
  1607. package/tooltip/index.d.ts +0 -3
  1608. package/tooltip/lib/tooltip/tooltip-panel.d.ts +0 -26
  1609. package/tooltip/lib/tooltip/tooltip.d.ts +0 -148
  1610. package/tooltip/lib/tooltip/tooltip.types.d.ts +0 -17
  1611. package/tooltip/malva-ui-core-tooltip.d.ts +0 -5
  1612. package/tree/index.d.ts +0 -4
  1613. package/tree/lib/tree/tree-context.d.ts +0 -62
  1614. package/tree/lib/tree/tree-node-def.d.ts +0 -33
  1615. package/tree/lib/tree/tree-node.d.ts +0 -45
  1616. package/tree/lib/tree/tree-subtree.d.ts +0 -63
  1617. package/tree/lib/tree/tree.d.ts +0 -156
  1618. package/tree/malva-ui-core-tree.d.ts +0 -5
@@ -0,0 +1,2696 @@
1
+ import { MlvDataSource, MlvArrayDataSource } from '@malva-ui/cdk/data-source';
2
+ export * from '@malva-ui/cdk/data-source';
3
+ import * as i0 from '@angular/core';
4
+ import { input, inject, TemplateRef, Directive, signal, Injectable, model, output, ElementRef, computed, effect, untracked, afterNextRender, ChangeDetectionStrategy, ViewEncapsulation, Component, numberAttribute, contentChildren, contentChild, viewChild, viewChildren, DestroyRef, Injector, NgZone } from '@angular/core';
5
+ import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
6
+ import { Grid, GridRow, GridCell, GridCellWidget } from '@angular/aria/grid';
7
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
+ import * as i2 from '@angular/cdk/scrolling';
9
+ import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
10
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
11
+ import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
12
+ import { LucideX, LucideArrowUp, LucideArrowDown, LucideChevronsUpDown, LucideChevronRight, LucideFilter, LucideTable2, LucidePencil, LucideCheck, LucidePlus, LucidePin, LucidePinOff, LucideEye, LucideTriangleAlert, LucideArrowUpDown, LucideFunnel } from '@lucide/angular';
13
+ import { MlvLoader } from '@malva-ui/core/loader';
14
+ import { MlvCheckbox } from '@malva-ui/core/checkbox';
15
+ import { MlvPagination } from '@malva-ui/core/pagination';
16
+ import { MlvSearchField } from '@malva-ui/core/search-field';
17
+ import { MlvResizeObserverService, MlvRtlService } from '@malva-ui/cdk/utils';
18
+ import { MlvInfiniteScroll } from '@malva-ui/cdk/infinite-scroll';
19
+ import { MlvButton, MlvButtonIcon } from '@malva-ui/core/button';
20
+ import { MlvListItem } from '@malva-ui/core/list';
21
+ import { MlvMenu, MlvMenuItem, MlvMenuTrigger } from '@malva-ui/core/menu';
22
+ import { MlvBadge } from '@malva-ui/core/badge';
23
+ import { MlvEmptyState } from '@malva-ui/core/empty-state';
24
+ import * as i1$1 from '@malva-ui/cdk/density';
25
+ import { MLV_DENSITY_ELEMENT, MlvDensityDirective } from '@malva-ui/cdk/density';
26
+ import { MLV_DATA_TABLE_I18N, MLV_FILTER_I18N, MlvI18nResolverService } from '@malva-ui/i18n';
27
+ import * as i1 from '@angular/forms';
28
+ import { FormsModule } from '@angular/forms';
29
+ import { MlvInput } from '@malva-ui/core/input';
30
+ import { MlvSelect } from '@malva-ui/core/select';
31
+ import { MlvPopupTrigger, MlvPopup, MlvPopupContent } from '@malva-ui/core/popup';
32
+
33
+ /**
34
+ * Compat re-export — the data source primitives now live in
35
+ * `@malva-ui/cdk/data-source` so option controls can share them.
36
+ */
37
+
38
+ /**
39
+ * Structural directive for providing custom cell templates with full type inference.
40
+ *
41
+ * Usage (asterisk shorthand — preferred):
42
+ * ```html
43
+ * <mlv-data-table [data]="employees" [columns]="columns">
44
+ * <span *mlvDataTableCell="'salary'; let row from employees">
45
+ * {{ row.salary.toLocaleString() }}
46
+ * </span>
47
+ * </mlv-data-table>
48
+ * ```
49
+ *
50
+ * Usage (explicit ng-template):
51
+ * ```html
52
+ * <ng-template mlvDataTableCell="salary" [mlvDataTableCellFrom]="employees" let-row>
53
+ * <span>{{ row.salary.toLocaleString() }}</span>
54
+ * </ng-template>
55
+ * ```
56
+ */
57
+ class MlvDataTableCell {
58
+ /** Column key this template applies to — typed as `keyof T` when `from` is provided. */
59
+ columnKey = input.required({ ...(ngDevMode ? { debugName: "columnKey" } : /* istanbul ignore next */ {}), alias: 'mlvDataTableCell' });
60
+ /**
61
+ * Pass the same value as `[data]` on the parent `mlv-data-table`.
62
+ * Angular uses this to infer `T` and type `let-row` in the template.
63
+ */
64
+ from = input(undefined, { ...(ngDevMode ? { debugName: "from" } : /* istanbul ignore next */ {}), alias: 'mlvDataTableCellFrom' });
65
+ templateRef = inject(TemplateRef);
66
+ /** Narrows the template context to `MlvDataTableCellContext<T>` for type-safe `let-row`. */
67
+ static ngTemplateContextGuard(_dir, _ctx) {
68
+ return true;
69
+ }
70
+ /** Enables `*mlvDataTableCell="'key'; let row from data"` microsyntax. */
71
+ static ngTemplateGuard_mlvDataTableCellFrom;
72
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableCell, deps: [], target: i0.ɵɵFactoryTarget.Directive });
73
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: MlvDataTableCell, isStandalone: true, selector: "[mlvDataTableCell]", inputs: { columnKey: { classPropertyName: "columnKey", publicName: "mlvDataTableCell", isSignal: true, isRequired: true, transformFunction: null }, from: { classPropertyName: "from", publicName: "mlvDataTableCellFrom", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
74
+ }
75
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableCell, decorators: [{
76
+ type: Directive,
77
+ args: [{
78
+ selector: '[mlvDataTableCell]',
79
+ }]
80
+ }], propDecorators: { columnKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "mlvDataTableCell", required: true }] }], from: [{ type: i0.Input, args: [{ isSignal: true, alias: "mlvDataTableCellFrom", required: false }] }] } });
81
+
82
+ /**
83
+ * Structural directive for providing custom edit-mode cell templates.
84
+ *
85
+ * When the table is in editable mode and a row enters editing, this template
86
+ * replaces the display template for the given column key.
87
+ *
88
+ * Usage (asterisk shorthand):
89
+ * ```html
90
+ * <mlv-input *mlvDataTableEditCell="'name'; let row from employees"
91
+ * [ngModel]="row.name" (ngModelChange)="row.name = $event" />
92
+ * ```
93
+ *
94
+ * Usage (explicit ng-template):
95
+ * ```html
96
+ * <ng-template mlvDataTableEditCell="name" [mlvDataTableEditCellFrom]="employees" let-row>
97
+ * <mlv-input [ngModel]="row.name" (ngModelChange)="row.name = $event" />
98
+ * </ng-template>
99
+ * ```
100
+ */
101
+ class MlvDataTableEditCell {
102
+ /** Column key this edit template applies to. */
103
+ columnKey = input.required({ ...(ngDevMode ? { debugName: "columnKey" } : /* istanbul ignore next */ {}), alias: 'mlvDataTableEditCell' });
104
+ /**
105
+ * Pass the same value as `[data]` on the parent `mlv-data-table`.
106
+ * Angular uses this to infer `T` and type `let-row` in the template.
107
+ */
108
+ from = input(undefined, { ...(ngDevMode ? { debugName: "from" } : /* istanbul ignore next */ {}), alias: 'mlvDataTableEditCellFrom' });
109
+ templateRef = inject(TemplateRef);
110
+ /** Narrows the template context to `MlvDataTableEditCellContext<T>` for type-safe `let-row`. */
111
+ static ngTemplateContextGuard(_dir, _ctx) {
112
+ return true;
113
+ }
114
+ /** Enables `*mlvDataTableEditCell="'key'; let row from data"` microsyntax. */
115
+ static ngTemplateGuard_mlvDataTableEditCellFrom;
116
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableEditCell, deps: [], target: i0.ɵɵFactoryTarget.Directive });
117
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: MlvDataTableEditCell, isStandalone: true, selector: "[mlvDataTableEditCell]", inputs: { columnKey: { classPropertyName: "columnKey", publicName: "mlvDataTableEditCell", isSignal: true, isRequired: true, transformFunction: null }, from: { classPropertyName: "from", publicName: "mlvDataTableEditCellFrom", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
118
+ }
119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableEditCell, decorators: [{
120
+ type: Directive,
121
+ args: [{
122
+ selector: '[mlvDataTableEditCell]',
123
+ }]
124
+ }], propDecorators: { columnKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "mlvDataTableEditCell", required: true }] }], from: [{ type: i0.Input, args: [{ isSignal: true, alias: "mlvDataTableEditCellFrom", required: false }] }] } });
125
+
126
+ /**
127
+ * Directive for the "no data" slot.
128
+ *
129
+ * Usage:
130
+ * ```html
131
+ * <mlv-data-table ...>
132
+ * <ng-template mlvDataTableNoData>
133
+ * <p>No records found.</p>
134
+ * </ng-template>
135
+ * </mlv-data-table>
136
+ * ```
137
+ */
138
+ class MlvDataTableNoData {
139
+ templateRef = inject(TemplateRef);
140
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableNoData, deps: [], target: i0.ɵɵFactoryTarget.Directive });
141
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: MlvDataTableNoData, isStandalone: true, selector: "[mlvDataTableNoData]", ngImport: i0 });
142
+ }
143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableNoData, decorators: [{
144
+ type: Directive,
145
+ args: [{
146
+ selector: '[mlvDataTableNoData]',
147
+ }]
148
+ }] });
149
+
150
+ /**
151
+ * Directive for the "request failed" slot. Rendered in place of the table body
152
+ * whenever `[error]` is truthy and the table is not loading, so a failed request
153
+ * is never mistaken for an empty result set.
154
+ *
155
+ * Usage:
156
+ * ```html
157
+ * <mlv-data-table [data]="rows()" [columns]="columns" [error]="error()" (retry)="reload()">
158
+ * <ng-template mlvDataTableError let-message let-retry="retry">
159
+ * <p>{{ message }}</p>
160
+ * <button mlvButton variant="secondary" type="button" (click)="retry()">Try again</button>
161
+ * </ng-template>
162
+ * </mlv-data-table>
163
+ * ```
164
+ */
165
+ class MlvDataTableError {
166
+ /** The projected template rendered instead of the default error block. */
167
+ templateRef = inject((TemplateRef));
168
+ /**
169
+ * Type guard so Angular narrows `let-message` / `let-retry="retry"` to
170
+ * {@link MlvDataTableErrorContext} in strict templates.
171
+ */
172
+ static ngTemplateContextGuard(_dir, _ctx) {
173
+ return true;
174
+ }
175
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableError, deps: [], target: i0.ɵɵFactoryTarget.Directive });
176
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: MlvDataTableError, isStandalone: true, selector: "[mlvDataTableError]", ngImport: i0 });
177
+ }
178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableError, decorators: [{
179
+ type: Directive,
180
+ args: [{
181
+ selector: '[mlvDataTableError]',
182
+ }]
183
+ }] });
184
+
185
+ /**
186
+ * Directive for the footer summary row slot.
187
+ *
188
+ * The template context provides `{ $implicit: columns }` where `columns`
189
+ * is the current visible column list.
190
+ *
191
+ * Usage:
192
+ * ```html
193
+ * <mlv-data-table ...>
194
+ * <ng-template mlvDataTableFooter let-cols>
195
+ * <th scope="row" [attr.colspan]="cols.length - 1">Total</th>
196
+ * <td>...</td>
197
+ * </ng-template>
198
+ * </mlv-data-table>
199
+ * ```
200
+ *
201
+ * Direct `th` and `td` children receive the table's density, divider, sticky
202
+ * surface, and bordered-cell styling without private component classes.
203
+ */
204
+ class MlvDataTableFooter {
205
+ templateRef = inject(TemplateRef);
206
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableFooter, deps: [], target: i0.ɵɵFactoryTarget.Directive });
207
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: MlvDataTableFooter, isStandalone: true, selector: "[mlvDataTableFooter]", ngImport: i0 });
208
+ }
209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableFooter, decorators: [{
210
+ type: Directive,
211
+ args: [{
212
+ selector: '[mlvDataTableFooter]',
213
+ }]
214
+ }] });
215
+
216
+ /**
217
+ * Optional host-owned actions projected into the Data Table's single toolbar.
218
+ * The template renders after all table-owned controls.
219
+ */
220
+ class MlvDataTableToolbarActions {
221
+ /** Projected toolbar-actions template rendered by the owning Data Table. */
222
+ templateRef = inject(TemplateRef);
223
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableToolbarActions, deps: [], target: i0.ɵɵFactoryTarget.Directive });
224
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: MlvDataTableToolbarActions, isStandalone: true, selector: "ng-template[mlvDataTableToolbarActions]", ngImport: i0 });
225
+ }
226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableToolbarActions, decorators: [{
227
+ type: Directive,
228
+ args: [{ selector: 'ng-template[mlvDataTableToolbarActions]' }]
229
+ }] });
230
+
231
+ /**
232
+ * Component-scoped editing state for `mlv-data-table`. Holds the per-row
233
+ * snapshot map used for rollback on cancel and tracks whether a given row
234
+ * index is currently in edit mode. The component delegates `startEdit` /
235
+ * `saveEdit` / `cancelEdit` to this service and emits the matching outputs
236
+ * itself.
237
+ *
238
+ * Provided per-component via `providers: [MlvDataTableEditingService]` so each
239
+ * `mlv-data-table` instance has its own isolated editing state.
240
+ */
241
+ class MlvDataTableEditingService {
242
+ /** @private Map of row-index → original row snapshot (for rollback). */
243
+ _editingRows = signal(new Map(), /* @ts-ignore */
244
+ ...(ngDevMode ? [{ debugName: "_editingRows" }] : /* istanbul ignore next */ []));
245
+ /** Whether any row is currently being edited. */
246
+ isEditing(index) {
247
+ return this._editingRows().has(index);
248
+ }
249
+ /** Whether at least one row is currently being edited. */
250
+ hasActiveEdit() {
251
+ return this._editingRows().size > 0;
252
+ }
253
+ /**
254
+ * Begin editing the given row. Stores a shallow clone in the rollback map.
255
+ * Returns the cloned snapshot for the caller to emit on `rowEditStart`.
256
+ */
257
+ start(row, index) {
258
+ const snapshot = { ...row };
259
+ const map = new Map(this._editingRows());
260
+ map.set(index, snapshot);
261
+ this._editingRows.set(map);
262
+ return snapshot;
263
+ }
264
+ /**
265
+ * Confirm edits for the given row. Returns the original snapshot (or the
266
+ * row itself if no snapshot was stored) so the caller can include it on
267
+ * the `rowEditSave` payload.
268
+ */
269
+ save(row, index) {
270
+ const original = this._editingRows().get(index) ?? row;
271
+ const map = new Map(this._editingRows());
272
+ map.delete(index);
273
+ this._editingRows.set(map);
274
+ return original;
275
+ }
276
+ /**
277
+ * Cancel editing the given row. Drops the snapshot. The caller is
278
+ * responsible for restoring the row data if it wants rollback semantics.
279
+ */
280
+ cancel(index) {
281
+ const map = new Map(this._editingRows());
282
+ map.delete(index);
283
+ this._editingRows.set(map);
284
+ }
285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableEditingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
286
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableEditingService });
287
+ }
288
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableEditingService, decorators: [{
289
+ type: Injectable
290
+ }] });
291
+
292
+ /**
293
+ * Tracks the user-toggled column hidden set for `mlv-data-table`.
294
+ * The component reads `isHidden(key)` while building `visibleColumns`
295
+ * and calls `toggle(key)` when the user clicks the column-visibility
296
+ * popup checkbox.
297
+ */
298
+ class MlvDataTableColumnVisibilityService {
299
+ /** @private Set of currently-hidden column keys. */
300
+ _hiddenColumns = signal(new Set(), /* @ts-ignore */
301
+ ...(ngDevMode ? [{ debugName: "_hiddenColumns" }] : /* istanbul ignore next */ []));
302
+ /** Read-only signal exposing the hidden-set for `effect()` consumers. */
303
+ hiddenColumns = this._hiddenColumns.asReadonly();
304
+ /** Whether a column is currently hidden by the user. */
305
+ isHidden(key) {
306
+ return this._hiddenColumns().has(key);
307
+ }
308
+ /** Toggle visibility of a hideable column. */
309
+ toggle(key) {
310
+ const current = this._hiddenColumns();
311
+ const next = new Set(current);
312
+ if (next.has(key)) {
313
+ next.delete(key);
314
+ }
315
+ else {
316
+ next.add(key);
317
+ }
318
+ this._hiddenColumns.set(next);
319
+ }
320
+ /** Replaces the hidden set with a cloned, pre-normalized key collection. */
321
+ replaceHiddenColumns(keys) {
322
+ this._hiddenColumns.set(new Set(keys));
323
+ }
324
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableColumnVisibilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
325
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableColumnVisibilityService });
326
+ }
327
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTableColumnVisibilityService, decorators: [{
328
+ type: Injectable
329
+ }] });
330
+
331
+ /**
332
+ * Component-scoped pin-state service for `mlv-data-table`. Holds the
333
+ * user-driven pin/unpin overrides keyed by column key. The component
334
+ * delegates `togglePin`/`pinTo`/`unpin` and the read-side queries to
335
+ * this service while continuing to compute layout offsets internally.
336
+ */
337
+ class MlvDataTablePinningService {
338
+ /** @private Map of column key → user-applied pin override. */
339
+ _overrides = signal(new Map(), /* @ts-ignore */
340
+ ...(ngDevMode ? [{ debugName: "_overrides" }] : /* istanbul ignore next */ []));
341
+ /** Read-only signal exposing the override map for `effect()` consumers. */
342
+ overrides = this._overrides.asReadonly();
343
+ /**
344
+ * Returns the list of sides the user may pin a column to, based on
345
+ * `col.pinnable`.
346
+ */
347
+ getPinnableSides(col) {
348
+ const p = col.pinnable;
349
+ if (!p)
350
+ return [];
351
+ if (p === true)
352
+ return ['left', 'right'];
353
+ if (typeof p === 'string')
354
+ return [p];
355
+ return p.slice();
356
+ }
357
+ /** Pin a column to the given side, or unpin if it is already pinned. */
358
+ togglePin(col, side = 'left') {
359
+ const map = new Map(this._overrides());
360
+ const current = map.get(col.key);
361
+ const effectivePinned = current ? current.pinned : !!col.pinned;
362
+ map.set(col.key, { pinned: !effectivePinned, pinSide: side });
363
+ this._overrides.set(map);
364
+ }
365
+ /** Pin a column to a specific side. */
366
+ pinTo(col, side) {
367
+ const map = new Map(this._overrides());
368
+ map.set(col.key, { pinned: true, pinSide: side });
369
+ this._overrides.set(map);
370
+ }
371
+ /** Explicitly unpin a column. */
372
+ unpin(col) {
373
+ const map = new Map(this._overrides());
374
+ map.set(col.key, { pinned: false, pinSide: col.pinSide ?? 'left' });
375
+ this._overrides.set(map);
376
+ }
377
+ /** Replaces component-scoped overrides with cloned, normalized entries. */
378
+ replaceOverrides(entries) {
379
+ this._overrides.set(new Map(entries.map(({ key, pinned, pinSide }) => [key, { pinned, pinSide }])));
380
+ }
381
+ /** Whether a column is currently pinned (accounting for overrides). */
382
+ isPinned(col) {
383
+ const override = this._overrides().get(col.key);
384
+ return override ? override.pinned : !!col.pinned;
385
+ }
386
+ /** Pin side for a column (considering overrides) or null. */
387
+ getPinSide(col) {
388
+ const override = this._overrides().get(col.key);
389
+ const pinned = override ? override.pinned : !!col.pinned;
390
+ if (!pinned)
391
+ return null;
392
+ return override ? override.pinSide : (col.pinSide ?? 'left');
393
+ }
394
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTablePinningService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
395
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTablePinningService });
396
+ }
397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTablePinningService, decorators: [{
398
+ type: Injectable
399
+ }] });
400
+
401
+ const DEFAULT_TEXT_OPERATORS = [
402
+ 'contains',
403
+ 'not-contains',
404
+ 'equals',
405
+ 'not-equals',
406
+ ];
407
+ /** Operators whose operand is the checkbox editor's selected-value array. */
408
+ const DEFAULT_OPTION_OPERATORS = [
409
+ 'in',
410
+ 'not-in',
411
+ ];
412
+ /** Returns whether an operator consumes an array of option values. */
413
+ function isOptionOperator(operator) {
414
+ return operator === 'in' || operator === 'not-in';
415
+ }
416
+ /** Copies a filter deeply enough that draft arrays never alias committed state. */
417
+ function cloneFilter(filter) {
418
+ return {
419
+ ...filter,
420
+ value: Array.isArray(filter.value) ? [...filter.value] : filter.value,
421
+ };
422
+ }
423
+ class MlvFilterDropdown {
424
+ columns = input.required(/* @ts-ignore */
425
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
426
+ activeFilters = model([], /* @ts-ignore */
427
+ ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
428
+ closed = output();
429
+ /** @protected Injected i18n translations for the data table. */
430
+ _i18n = inject(MLV_DATA_TABLE_I18N);
431
+ /** @protected Shared operator and filter-action translations. */
432
+ _filterI18n = inject(MLV_FILTER_I18N);
433
+ /** @private Resolver for ICU parameterized i18n strings. */
434
+ _resolver = inject(MlvI18nResolverService);
435
+ /** @private Host used to place focus in the first editor after overlay creation. */
436
+ _host = inject(ElementRef);
437
+ /** @protected Transform mapping a `MlvDataSourceFilterOperator` to a `MlvSelectOption` for the operator dropdown. */
438
+ operatorTransform = (op) => ({
439
+ label: this._operatorLabel(op),
440
+ value: op,
441
+ });
442
+ /** @protected The subset of columns that are marked filterable. */
443
+ filterableColumns = computed(() => this.columns().filter((c) => c.filterable), /* @ts-ignore */
444
+ ...(ngDevMode ? [{ debugName: "filterableColumns" }] : /* istanbul ignore next */ []));
445
+ /** @private Working copy of in-progress filter edits, keyed by column key. */
446
+ _localFilters = signal(new Map(), /* @ts-ignore */
447
+ ...(ngDevMode ? [{ debugName: "_localFilters" }] : /* istanbul ignore next */ []));
448
+ constructor() {
449
+ effect(() => {
450
+ const allowedKeys = new Set(this.filterableColumns().map((column) => column.key));
451
+ const committed = this.activeFilters();
452
+ const next = new Map();
453
+ for (const filter of committed) {
454
+ if (allowedKeys.has(filter.key)) {
455
+ next.set(filter.key, cloneFilter(filter));
456
+ }
457
+ }
458
+ untracked(() => this._localFilters.set(next));
459
+ });
460
+ // The popup service stamps this component into a detached overlay portal.
461
+ // Move focus directly into its first field so keyboard users do not have to
462
+ // tab through the underlying page to reach the non-modal dialog.
463
+ afterNextRender(() => {
464
+ const editor = this._host.nativeElement.querySelector('.mlv-dt-filter-dropdown__body [role="combobox"], .mlv-dt-filter-dropdown__body input:not([disabled])');
465
+ editor?.focus();
466
+ });
467
+ }
468
+ /** @protected Returns the allowed operators for a column, falling back to the defaults. */
469
+ operators(col) {
470
+ const configured = col.filterConfig?.operators;
471
+ if (this.options(col).length > 0) {
472
+ const compatible = configured?.filter(isOptionOperator) ?? [];
473
+ return compatible.length > 0 ? compatible : DEFAULT_OPTION_OPERATORS;
474
+ }
475
+ return configured?.length ? configured : DEFAULT_TEXT_OPERATORS;
476
+ }
477
+ /** @protected Returns the configured filter options for a column, or an empty list. */
478
+ options(col) {
479
+ return col.filterConfig?.options ?? [];
480
+ }
481
+ /** @protected Returns the working filter state for a column key, creating a default if absent. */
482
+ getFilter(key) {
483
+ return (this._localFilters().get(key) ?? {
484
+ key,
485
+ operator: this._defaultOperator(key),
486
+ value: '',
487
+ });
488
+ }
489
+ /** @protected Updates the operator of the working filter for a column key. */
490
+ setOperator(key, operator) {
491
+ const current = this.getFilter(key);
492
+ let value = current.value;
493
+ if (isOptionOperator(operator) && !Array.isArray(value)) {
494
+ value =
495
+ value === '' || value === null || value === undefined ? [] : [value];
496
+ }
497
+ else if (!isOptionOperator(operator) && Array.isArray(value)) {
498
+ value = value[0] ?? '';
499
+ }
500
+ const updated = new Map(this._localFilters());
501
+ updated.set(key, { ...current, operator, value });
502
+ this._localFilters.set(updated);
503
+ }
504
+ /** @protected Updates the value of the working filter for a column key. */
505
+ setValue(key, value) {
506
+ const current = this.getFilter(key);
507
+ const updated = new Map(this._localFilters());
508
+ updated.set(key, { ...current, value });
509
+ this._localFilters.set(updated);
510
+ }
511
+ /** @protected Commits non-empty working filters to `activeFilters` and closes the dropdown. */
512
+ apply() {
513
+ const editedKeys = new Set(this.filterableColumns().map((column) => column.key));
514
+ const filters = this.activeFilters().filter((filter) => !editedKeys.has(filter.key));
515
+ this._localFilters().forEach((f) => {
516
+ if (f.value !== '' &&
517
+ f.value !== null &&
518
+ f.value !== undefined &&
519
+ !(Array.isArray(f.value) && f.value.length === 0)) {
520
+ filters.push(cloneFilter(f));
521
+ }
522
+ });
523
+ this.activeFilters.set(filters);
524
+ this.closed.emit();
525
+ }
526
+ /** @protected Clears all working and active filters, then closes the dropdown. */
527
+ clear() {
528
+ this._localFilters.set(new Map());
529
+ const editedKeys = new Set(this.filterableColumns().map((column) => column.key));
530
+ this.activeFilters.set(this.activeFilters().filter((filter) => !editedKeys.has(filter.key)));
531
+ this.closed.emit();
532
+ }
533
+ /** @protected Discards draft edits and asks the owning popup to close. */
534
+ cancel() {
535
+ const allowedKeys = new Set(this.filterableColumns().map((column) => column.key));
536
+ const restored = new Map();
537
+ for (const filter of this.activeFilters()) {
538
+ if (allowedKeys.has(filter.key))
539
+ restored.set(filter.key, cloneFilter(filter));
540
+ }
541
+ this._localFilters.set(restored);
542
+ this.closed.emit();
543
+ }
544
+ /** @protected Toggles a value in a multi-select (array) filter for a column key. */
545
+ toggleInArray(key, value) {
546
+ const current = this.getFilter(key);
547
+ const arr = Array.isArray(current.value) ? [...current.value] : [];
548
+ const idx = arr.indexOf(value);
549
+ if (idx >= 0)
550
+ arr.splice(idx, 1);
551
+ else
552
+ arr.push(value);
553
+ const updated = new Map(this._localFilters());
554
+ updated.set(key, {
555
+ key,
556
+ operator: isOptionOperator(current.operator)
557
+ ? current.operator
558
+ : this._defaultOperator(key),
559
+ value: arr,
560
+ });
561
+ this._localFilters.set(updated);
562
+ }
563
+ /** @protected Returns whether a value is currently selected in a column's array filter. */
564
+ isInArray(key, value) {
565
+ const current = this.getFilter(key);
566
+ return Array.isArray(current.value) && current.value.includes(value);
567
+ }
568
+ /** @protected Resolves the filterByColumn ICU string for a given column name. */
569
+ resolveFilterPlaceholder(columnName) {
570
+ return this._resolver.resolve(this._i18n(), 'filterByColumn', { column: columnName });
571
+ }
572
+ /** @protected Localized accessible name for one column's operator selector. */
573
+ resolveOperatorLabel(col) {
574
+ return `${this._operatorLabel(this.getFilter(col.key).operator)}: ${col.title ?? col.key}`;
575
+ }
576
+ /** @private Operator used when a field has no committed or draft value. */
577
+ _defaultOperator(key) {
578
+ const column = this.filterableColumns().find((item) => item.key === key);
579
+ return column ? (this.operators(column)[0] ?? 'contains') : 'contains';
580
+ }
581
+ /** @private Resolves one operator key through the shared filter translations. */
582
+ _operatorLabel(operator) {
583
+ const labels = this._filterI18n();
584
+ switch (operator) {
585
+ case 'contains':
586
+ return labels.contains;
587
+ case 'not-contains':
588
+ return labels.notContains;
589
+ case 'equals':
590
+ return labels.equals;
591
+ case 'not-equals':
592
+ return labels.notEquals;
593
+ case 'in':
594
+ return labels.in;
595
+ case 'not-in':
596
+ return labels.notIn;
597
+ }
598
+ }
599
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvFilterDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
600
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MlvFilterDropdown, isStandalone: true, selector: "mlv-dt-filter-dropdown", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, activeFilters: { classPropertyName: "activeFilters", publicName: "activeFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeFilters: "activeFiltersChange", closed: "closed" }, host: { classAttribute: "mlv-dt-filter-dropdown" }, ngImport: i0, template: "<div class=\"mlv-dt-filter-dropdown__panel\">\n <div class=\"mlv-dt-filter-dropdown__header\">\n <span class=\"mlv-dt-filter-dropdown__title\">{{ _i18n().filters }}</span>\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"cancel()\"\n [attr.aria-label]=\"_i18n().closeFilters\"\n >\n <svg lucideX mlvButtonIcon [size]=\"16\" />\n </button>\n </div>\n\n <div class=\"mlv-dt-filter-dropdown__body\">\n @for (col of filterableColumns(); track col.key) {\n <div class=\"mlv-dt-filter-dropdown__group\">\n <span class=\"mlv-dt-filter-dropdown__label\"\n >{{ col.title ?? col.key }}</span\n >\n\n @if (options(col).length > 0) {\n <mlv-select\n class=\"mlv-dt-filter-dropdown__option-operator\"\n [options]=\"operators(col)\"\n [toOption]=\"operatorTransform\"\n [ariaLabel]=\"resolveOperatorLabel(col)\"\n [ngModel]=\"getFilter(col.key).operator\"\n (ngModelChange)=\"setOperator(col.key, $event)\"\n />\n <div class=\"mlv-dt-filter-dropdown__options\">\n @for (opt of options(col); track opt.value) {\n <div class=\"mlv-dt-filter-dropdown__option\">\n <mlv-checkbox\n [checked]=\"isInArray(col.key, opt.value)\"\n [ariaLabel]=\"opt.label\"\n (checkedChange)=\"toggleInArray(col.key, opt.value)\"\n >{{ opt.label }}</mlv-checkbox\n >\n </div>\n }\n </div>\n } @else {\n <div class=\"mlv-dt-filter-dropdown__row\">\n <mlv-select\n class=\"mlv-dt-filter-dropdown__operator\"\n [options]=\"operators(col)\"\n [toOption]=\"operatorTransform\"\n [ariaLabel]=\"resolveOperatorLabel(col)\"\n [ngModel]=\"getFilter(col.key).operator\"\n (ngModelChange)=\"setOperator(col.key, $event)\"\n />\n <mlv-input\n class=\"mlv-dt-filter-dropdown__text-input\"\n [placeholder]=\"resolveFilterPlaceholder(col.title ?? col.key)\"\n [ariaLabel]=\"resolveFilterPlaceholder(col.title ?? col.key)\"\n [ngModel]=\"$any(getFilter(col.key).value)\"\n (ngModelChange)=\"setValue(col.key, $event)\"\n />\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"mlv-dt-filter-dropdown__footer\">\n <button\n mlvButton\n variant=\"secondary\"\n mlvDensity=\"compact\"\n type=\"button\"\n (click)=\"clear()\"\n >\n {{ _i18n().clearAll }}\n </button>\n <button mlvButton mlvDensity=\"compact\" type=\"button\" (click)=\"apply()\">\n {{ _i18n().apply }}\n </button>\n </div>\n</div>\n", styles: ["@layer mlv.components{.mlv-dt-filter-dropdown{box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-font-size-m)}.mlv-dt-filter-dropdown *{box-sizing:border-box}.mlv-dt-filter-dropdown{position:relative}.mlv-dt-filter-dropdown__panel{width:20rem;display:flex;flex-direction:column;border-radius:var(--mlv-radius-l)}.mlv-dt-filter-dropdown__header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:.0625rem solid var(--mlv-border-subtle)}.mlv-dt-filter-dropdown__title{font-size:var(--mlv-font-size-m);font-weight:var(--mlv-font-weight-medium);color:var(--mlv-text-primary)}.mlv-dt-filter-dropdown__body{padding:.75rem 1rem;display:flex;flex-direction:column;gap:1rem;max-height:20rem;overflow-y:auto}.mlv-dt-filter-dropdown__group{display:flex;flex-direction:column;gap:.375rem}.mlv-dt-filter-dropdown__label{font-size:var(--mlv-font-size-xs);font-weight:var(--mlv-font-weight-medium);color:var(--mlv-text-secondary);letter-spacing:.01em}.mlv-dt-filter-dropdown__row{display:flex;gap:.5rem;align-items:flex-start}.mlv-dt-filter-dropdown__operator{flex:0 0 auto;min-width:8rem}.mlv-dt-filter-dropdown__option-operator{width:100%}.mlv-dt-filter-dropdown__text-input{flex:1;min-width:0}.mlv-dt-filter-dropdown__options{display:flex;flex-direction:column;gap:.25rem}.mlv-dt-filter-dropdown__option{display:flex;align-items:center;gap:.5rem;font-size:var(--mlv-font-size-m);color:var(--mlv-text-primary);cursor:pointer;transition:color var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-dt-filter-dropdown__option:hover{color:var(--mlv-text-action)}.mlv-dt-filter-dropdown__footer{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;padding:.75rem 1rem;border-top:.0625rem solid var(--mlv-border-subtle)}@media(prefers-reduced-motion:reduce){.mlv-dt-filter-dropdown,.mlv-dt-filter-dropdown *,.mlv-dt-filter-dropdown:before,.mlv-dt-filter-dropdown:after,[class^=mlv-dt-filter-dropdown__],[class*=\" mlv-dt-filter-dropdown__\"],[class^=mlv-dt-filter-dropdown--],[class*=\" mlv-dt-filter-dropdown--\"]{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:var(--mlv-duration-instant)!important}}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MlvButton, selector: "button[mlvButton], a[mlvButton]", inputs: ["variant", "shape", "disabled", "loading", "selected"] }, { kind: "directive", type: MlvButtonIcon, selector: "[mlvButtonIcon]" }, { kind: "component", type: MlvCheckbox, selector: "mlv-checkbox", inputs: ["ariaLabelledBy", "checked", "indeterminate", "tabbable"], outputs: ["checkedChange"] }, { kind: "component", type: MlvInput, selector: "mlv-input", inputs: ["type", "placeholder", "autocomplete", "inputMode", "maxLength", "minLength", "pattern", "name", "autofocus", "min", "max", "step", "bare", "projectControl", "role", "ariaExpanded", "ariaHasPopup", "ariaAutocomplete", "ariaControls", "ariaActiveDescendant", "ariaDescribedBy", "value"], outputs: ["valueChange", "inputFocus", "inputBlur"] }, { kind: "component", type: MlvSelect, selector: "mlv-select", inputs: ["value", "options", "searchFn", "searchDebounce", "multiple", "native", "placeholder", "toOption", "compareWith", "searchable", "searchPlaceholder", "matcher", "mobileMode", "mlvDensity", "mobileTitle"], outputs: ["valueChange"] }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
601
+ }
602
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvFilterDropdown, decorators: [{
603
+ type: Component,
604
+ args: [{ selector: 'mlv-dt-filter-dropdown', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
605
+ FormsModule,
606
+ MlvButton,
607
+ MlvButtonIcon,
608
+ MlvCheckbox,
609
+ MlvInput,
610
+ MlvSelect,
611
+ LucideX,
612
+ ], host: { class: 'mlv-dt-filter-dropdown' }, template: "<div class=\"mlv-dt-filter-dropdown__panel\">\n <div class=\"mlv-dt-filter-dropdown__header\">\n <span class=\"mlv-dt-filter-dropdown__title\">{{ _i18n().filters }}</span>\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"cancel()\"\n [attr.aria-label]=\"_i18n().closeFilters\"\n >\n <svg lucideX mlvButtonIcon [size]=\"16\" />\n </button>\n </div>\n\n <div class=\"mlv-dt-filter-dropdown__body\">\n @for (col of filterableColumns(); track col.key) {\n <div class=\"mlv-dt-filter-dropdown__group\">\n <span class=\"mlv-dt-filter-dropdown__label\"\n >{{ col.title ?? col.key }}</span\n >\n\n @if (options(col).length > 0) {\n <mlv-select\n class=\"mlv-dt-filter-dropdown__option-operator\"\n [options]=\"operators(col)\"\n [toOption]=\"operatorTransform\"\n [ariaLabel]=\"resolveOperatorLabel(col)\"\n [ngModel]=\"getFilter(col.key).operator\"\n (ngModelChange)=\"setOperator(col.key, $event)\"\n />\n <div class=\"mlv-dt-filter-dropdown__options\">\n @for (opt of options(col); track opt.value) {\n <div class=\"mlv-dt-filter-dropdown__option\">\n <mlv-checkbox\n [checked]=\"isInArray(col.key, opt.value)\"\n [ariaLabel]=\"opt.label\"\n (checkedChange)=\"toggleInArray(col.key, opt.value)\"\n >{{ opt.label }}</mlv-checkbox\n >\n </div>\n }\n </div>\n } @else {\n <div class=\"mlv-dt-filter-dropdown__row\">\n <mlv-select\n class=\"mlv-dt-filter-dropdown__operator\"\n [options]=\"operators(col)\"\n [toOption]=\"operatorTransform\"\n [ariaLabel]=\"resolveOperatorLabel(col)\"\n [ngModel]=\"getFilter(col.key).operator\"\n (ngModelChange)=\"setOperator(col.key, $event)\"\n />\n <mlv-input\n class=\"mlv-dt-filter-dropdown__text-input\"\n [placeholder]=\"resolveFilterPlaceholder(col.title ?? col.key)\"\n [ariaLabel]=\"resolveFilterPlaceholder(col.title ?? col.key)\"\n [ngModel]=\"$any(getFilter(col.key).value)\"\n (ngModelChange)=\"setValue(col.key, $event)\"\n />\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"mlv-dt-filter-dropdown__footer\">\n <button\n mlvButton\n variant=\"secondary\"\n mlvDensity=\"compact\"\n type=\"button\"\n (click)=\"clear()\"\n >\n {{ _i18n().clearAll }}\n </button>\n <button mlvButton mlvDensity=\"compact\" type=\"button\" (click)=\"apply()\">\n {{ _i18n().apply }}\n </button>\n </div>\n</div>\n", styles: ["@layer mlv.components{.mlv-dt-filter-dropdown{box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-font-size-m)}.mlv-dt-filter-dropdown *{box-sizing:border-box}.mlv-dt-filter-dropdown{position:relative}.mlv-dt-filter-dropdown__panel{width:20rem;display:flex;flex-direction:column;border-radius:var(--mlv-radius-l)}.mlv-dt-filter-dropdown__header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-bottom:.0625rem solid var(--mlv-border-subtle)}.mlv-dt-filter-dropdown__title{font-size:var(--mlv-font-size-m);font-weight:var(--mlv-font-weight-medium);color:var(--mlv-text-primary)}.mlv-dt-filter-dropdown__body{padding:.75rem 1rem;display:flex;flex-direction:column;gap:1rem;max-height:20rem;overflow-y:auto}.mlv-dt-filter-dropdown__group{display:flex;flex-direction:column;gap:.375rem}.mlv-dt-filter-dropdown__label{font-size:var(--mlv-font-size-xs);font-weight:var(--mlv-font-weight-medium);color:var(--mlv-text-secondary);letter-spacing:.01em}.mlv-dt-filter-dropdown__row{display:flex;gap:.5rem;align-items:flex-start}.mlv-dt-filter-dropdown__operator{flex:0 0 auto;min-width:8rem}.mlv-dt-filter-dropdown__option-operator{width:100%}.mlv-dt-filter-dropdown__text-input{flex:1;min-width:0}.mlv-dt-filter-dropdown__options{display:flex;flex-direction:column;gap:.25rem}.mlv-dt-filter-dropdown__option{display:flex;align-items:center;gap:.5rem;font-size:var(--mlv-font-size-m);color:var(--mlv-text-primary);cursor:pointer;transition:color var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-dt-filter-dropdown__option:hover{color:var(--mlv-text-action)}.mlv-dt-filter-dropdown__footer{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;padding:.75rem 1rem;border-top:.0625rem solid var(--mlv-border-subtle)}@media(prefers-reduced-motion:reduce){.mlv-dt-filter-dropdown,.mlv-dt-filter-dropdown *,.mlv-dt-filter-dropdown:before,.mlv-dt-filter-dropdown:after,[class^=mlv-dt-filter-dropdown__],[class*=\" mlv-dt-filter-dropdown__\"],[class^=mlv-dt-filter-dropdown--],[class*=\" mlv-dt-filter-dropdown--\"]{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:var(--mlv-duration-instant)!important}}}\n"] }]
613
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], activeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFilters", required: false }] }, { type: i0.Output, args: ["activeFiltersChange"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
614
+
615
+ /** Returns the original row reference used for expansion identity. */
616
+ function originalRow(row) {
617
+ return row['_mlvRef'] ?? row;
618
+ }
619
+ /** Recursively flattens expanded tree rows into render order. */
620
+ function flattenRows(rows, expanded, depth = 0) {
621
+ const result = [];
622
+ for (const row of rows) {
623
+ const original = originalRow(row);
624
+ result.push({ ...row, _mlvDepth: depth, _mlvRef: original });
625
+ const children = original['_mlvChildren'];
626
+ if (expanded.has(original) && children?.length) {
627
+ result.push(...flattenRows(children, expanded, depth + 1));
628
+ }
629
+ }
630
+ return result;
631
+ }
632
+ /** Resolves responsive column visibility at the supplied container width. */
633
+ function isColumnVisible(column, containerWidth) {
634
+ if (!column.responsive || containerWidth === 0)
635
+ return true;
636
+ const breakpoints = Object.keys(column.responsive)
637
+ .map(Number)
638
+ .filter(Number.isFinite)
639
+ .sort((a, b) => a - b);
640
+ let visibility = null;
641
+ for (const breakpoint of breakpoints) {
642
+ if (containerWidth >= breakpoint) {
643
+ visibility = column.responsive[breakpoint];
644
+ }
645
+ }
646
+ if (visibility === null) {
647
+ const fallback = Object.keys(column.responsive).find((key) => !Number.isFinite(Number(key)));
648
+ if (fallback)
649
+ visibility = column.responsive[fallback];
650
+ }
651
+ return visibility !== 'hidden';
652
+ }
653
+ /**
654
+ * Parses a complete, non-negative CSS pixel width.
655
+ *
656
+ * Other CSS units deliberately return `undefined`; treating `12rem` or `50%`
657
+ * as `12px`/`50px` would corrupt resize bounds and pinned-column offsets.
658
+ */
659
+ function parsePixelWidth(width) {
660
+ if (!width)
661
+ return undefined;
662
+ const match = width.trim().match(/^(?:\d+(?:\.\d+)?|\.\d+)px$/i);
663
+ if (!match)
664
+ return undefined;
665
+ const parsed = Number.parseFloat(match[0]);
666
+ return Number.isFinite(parsed) ? parsed : undefined;
667
+ }
668
+ /** Builds stable width styles for a table column. */
669
+ function columnWidthStyles(column) {
670
+ const styles = {};
671
+ if (column._currentWidth !== undefined) {
672
+ styles['width'] = `${column._currentWidth}px`;
673
+ styles['min-width'] = `${column._currentWidth}px`;
674
+ styles['max-width'] = `${column._currentWidth}px`;
675
+ return styles;
676
+ }
677
+ if (column.width)
678
+ styles['width'] = column.width;
679
+ if (column.minWidth)
680
+ styles['min-width'] = column.minWidth;
681
+ if (column.maxWidth)
682
+ styles['max-width'] = column.maxWidth;
683
+ return styles;
684
+ }
685
+ /** Adds sticky pin offsets to the base column width styles. */
686
+ function columnCellStyles(column, offsets) {
687
+ const styles = columnWidthStyles(column);
688
+ if (!column.pinned)
689
+ return styles;
690
+ styles['position'] = 'sticky';
691
+ styles['z-index'] = '2';
692
+ const side = column.pinSide === 'right' ? 'right' : 'left';
693
+ const offset = offsets.get(`${column.key}_${side}`) ?? '0px';
694
+ styles[side] =
695
+ `calc(${offset} + var(--mlv-dt-pinned-${side}-correction, 0px))`;
696
+ return styles;
697
+ }
698
+
699
+ const DEFAULT_COLUMN_WIDTH = 150;
700
+ const DEFAULT_COLUMN_MIN_WIDTH = 60;
701
+ const DEFAULT_COLUMN_MAX_WIDTH = 2000;
702
+ const DEFAULT_SELECTION_COLUMN_WIDTH = 40;
703
+ const DEFAULT_ACTIONS_COLUMN_WIDTH = 80;
704
+ const COLUMN_RESIZE_KEYBOARD_STEP = 8;
705
+ const COLUMN_RESIZE_KEYBOARD_LARGE_STEP = 32;
706
+ class MlvDataTable {
707
+ /** @protected Injected i18n translations for the data table. */
708
+ _i18n = inject(MLV_DATA_TABLE_I18N);
709
+ // ---- Inputs ----------------------------------------------------------------
710
+ columns = input.required(/* @ts-ignore */
711
+ ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
712
+ data = input(undefined, /* @ts-ignore */
713
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
714
+ rowHeight = input(40, /* @ts-ignore */
715
+ ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
716
+ /** Enable CDK virtual scroll for large datasets. */
717
+ virtualScroll = input(false, { ...(ngDevMode ? { debugName: "virtualScroll" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
718
+ /** Alternating row shading. */
719
+ striped = input(false, { ...(ngDevMode ? { debugName: "striped" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
720
+ /** Cell border lines. */
721
+ bordered = input(false, { ...(ngDevMode ? { debugName: "bordered" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
722
+ /** Sticky table header on scroll. */
723
+ stickyHeader = input(true, { ...(ngDevMode ? { debugName: "stickyHeader" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
724
+ /** Maximum height of the scrollable table area (e.g. `'28rem'`, `'400px'`). Enables vertical scroll. */
725
+ maxHeight = input(undefined, /* @ts-ignore */
726
+ ...(ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []));
727
+ /** Column group definitions for multi-row headers. */
728
+ columnGroups = input([], /* @ts-ignore */
729
+ ...(ngDevMode ? [{ debugName: "columnGroups" }] : /* istanbul ignore next */ []));
730
+ /** Enable editable mode on the table. */
731
+ editable = input(false, { ...(ngDevMode ? { debugName: "editable" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
732
+ /** Edit granularity: `'row'` edits entire rows, `'cell'` edits individual cells. */
733
+ editMode = input('row', /* @ts-ignore */
734
+ ...(ngDevMode ? [{ debugName: "editMode" }] : /* istanbul ignore next */ []));
735
+ /** Show an "Add row" button in the toolbar when editable. */
736
+ addRow = input(false, { ...(ngDevMode ? { debugName: "addRow" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
737
+ /** Show a loading overlay on top of the table. */
738
+ loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
739
+ /**
740
+ * Failed-request state. `false` (default) renders normally; `true` renders the
741
+ * error block with the localized default message; a non-empty string renders
742
+ * that string as the message.
743
+ *
744
+ * While set — and while {@link loading} is falsy — the error block replaces the
745
+ * table body, taking precedence over both the rows and the `mlvDataTableNoData`
746
+ * template so a failed request is never mistaken for an empty result set.
747
+ * Project `<ng-template mlvDataTableError>` to replace the default block.
748
+ */
749
+ error = input(false, /* @ts-ignore */
750
+ ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
751
+ /** Row selection mode: `'single'`, `'multi'`, or `false` to disable. */
752
+ selectable = input(false, /* @ts-ignore */
753
+ ...(ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []));
754
+ /**
755
+ * Accessible name for the trailing actions column header (rendered when
756
+ * {@link editable} is on). The actions `<th>` has no visible label, so this
757
+ * string is exposed to assistive tech via visually-hidden text to satisfy the
758
+ * `empty-table-header` requirement. Defaults to `'Actions'`.
759
+ *
760
+ * NB: this is a plain English default input rather than a `MLV_DATA_TABLE_I18N`
761
+ * token entry — adding an i18n string is a follow-up (see `libs-data-table.md`).
762
+ */
763
+ actionsHeaderLabel = input('Actions', /* @ts-ignore */
764
+ ...(ngDevMode ? [{ debugName: "actionsHeaderLabel" }] : /* istanbul ignore next */ []));
765
+ /**
766
+ * **Experimental.** Opt into full cell-level keyboard navigation backed by the
767
+ * `@angular/aria` grid pattern (`ngGrid`/`ngGridRow`/`ngGridCell`/`ngGridCellWidget`).
768
+ *
769
+ * When `false` (default), the table keeps its stable **row-level** roving
770
+ * navigation (ArrowUp/Down move between rows, Home/End jump, Space/Enter toggle
771
+ * row selection). When `true`, arrow keys move focus between individual **cells**
772
+ * (Arrow keys in both axes, Home/End within a row), interactive cells expose an
773
+ * `ngGridCellWidget` so Enter pauses grid navigation to interact (edit inputs,
774
+ * action buttons), and Escape returns to grid navigation.
775
+ *
776
+ * Limitations of the current prototype (see `libs-data-table.md`):
777
+ * - **Requires non-virtual mode.** Cell navigation is inert while
778
+ * {@link virtualScroll} is `true` — CDK row recycling and the split
779
+ * header/body/footer tables are incompatible with the grid's DOM-registered
780
+ * cell/row collection. `virtualScroll` wins; the table falls back to
781
+ * row-level roving.
782
+ * - Row selection stays row-level (via the checkbox widget); the aria grid's
783
+ * own cell-selection model is intentionally not wired.
784
+ */
785
+ cellNavigation = input(false, { ...(ngDevMode ? { debugName: "cellNavigation" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
786
+ /**
787
+ * Pagination strategy.
788
+ * - `'paged'` (default) — renders the classic paginator footer and swaps rows per page.
789
+ * - `'infinite'` — hides the paginator and emits `loadMore` when the user scrolls near the bottom of the scroll container. Consumers should append the new page's rows to the existing data source.
790
+ */
791
+ paginationMode = input('paged', /* @ts-ignore */
792
+ ...(ngDevMode ? [{ debugName: "paginationMode" }] : /* istanbul ignore next */ []));
793
+ /**
794
+ * Whether more data is available to load. Only consulted in `paginationMode: 'infinite'`.
795
+ * Bind this to the consumer's own "has more pages" flag to stop the directive from
796
+ * firing once the backing data source has been exhausted.
797
+ */
798
+ hasMore = input(true, { ...(ngDevMode ? { debugName: "hasMore" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
799
+ /**
800
+ * Distance in px from the bottom of the scrollable area at which `loadMore` fires.
801
+ * Only consulted in `paginationMode: 'infinite'`. Defaults to `200`.
802
+ */
803
+ infiniteScrollThreshold = input(200, /* @ts-ignore */
804
+ ...(ngDevMode ? [{ debugName: "infiniteScrollThreshold" }] : /* istanbul ignore next */ []));
805
+ /** Where table-owned filter controls are displayed. */
806
+ filterDisplay = input('toolbar', /* @ts-ignore */
807
+ ...(ngDevMode ? [{ debugName: "filterDisplay" }] : /* istanbul ignore next */ []));
808
+ /** Whether the built-in global-search field is rendered in the toolbar. */
809
+ showSearch = input(true, { ...(ngDevMode ? { debugName: "showSearch" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
810
+ /** Whether the generic Sort menu is rendered when sortable columns exist. */
811
+ showSortMenu = input(false, { ...(ngDevMode ? { debugName: "showSortMenu" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
812
+ /** Whether global search executes as the user types or only on submit. */
813
+ searchTrigger = input('live', /* @ts-ignore */
814
+ ...(ngDevMode ? [{ debugName: "searchTrigger" }] : /* istanbul ignore next */ []));
815
+ /** Delay in milliseconds used by live global search. */
816
+ searchDebounce = input(200, { ...(ngDevMode ? { debugName: "searchDebounce" } : /* istanbul ignore next */ {}), transform: (value) => Math.max(0, numberAttribute(value, 200)) });
817
+ // ---- Outputs ----------------------------------------------------------------
818
+ /** Emits when a row enters edit mode. */
819
+ rowEditStart = output();
820
+ /** Emits when the user confirms edits on a row. */
821
+ rowEditSave = output();
822
+ /** Emits when the user cancels editing a row. */
823
+ rowEditCancel = output();
824
+ /** Emits when the user clicks "Add row". Consumer is responsible for adding the row. */
825
+ rowAdd = output();
826
+ /** Emits when the user clicks a data row. */
827
+ rowClick = output();
828
+ /** Emits when the row selection changes. */
829
+ selectionChange = output();
830
+ /**
831
+ * Emits when the user activates the error block's retry control (the default
832
+ * "Retry" button, or `retry()` from a custom `mlvDataTableError` template).
833
+ * The consumer owns the refetch and is responsible for clearing {@link error}.
834
+ */
835
+ retry = output();
836
+ /**
837
+ * Emits after a pointer or keyboard interaction commits a column width, or
838
+ * after a reset removes a user width override.
839
+ */
840
+ columnResize = output();
841
+ /**
842
+ * Emits a complete normalized durable presentation snapshot after a user
843
+ * changes sorting, column visibility, pinning, committed widths, or page size.
844
+ * Programmatic {@link applyPresentationState} calls deliberately do not emit.
845
+ */
846
+ presentationStateChange = output();
847
+ /**
848
+ * Emits in `paginationMode: 'infinite'` when the user scrolls near the bottom
849
+ * of the scroll container. The payload carries the next page number,
850
+ * current per-page size, and remaining scroll distance.
851
+ */
852
+ loadMore = output();
853
+ /** Two-way bindable set of selected rows. */
854
+ selectedRows = model(new Set(), /* @ts-ignore */
855
+ ...(ngDevMode ? [{ debugName: "selectedRows" }] : /* istanbul ignore next */ []));
856
+ /** Applied global-search query. Submit-mode drafts are committed here on search. */
857
+ searchQuery = model('', /* @ts-ignore */
858
+ ...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
859
+ // ---- Content children -------------------------------------------------------
860
+ cellTemplates = contentChildren(MlvDataTableCell, { ...(ngDevMode ? { debugName: "cellTemplates" } : /* istanbul ignore next */ {}), descendants: true });
861
+ editCellTemplates = contentChildren(MlvDataTableEditCell, { ...(ngDevMode ? { debugName: "editCellTemplates" } : /* istanbul ignore next */ {}), descendants: true });
862
+ noDataTemplate = contentChildren(MlvDataTableNoData, { ...(ngDevMode ? { debugName: "noDataTemplate" } : /* istanbul ignore next */ {}), descendants: true });
863
+ errorTemplate = contentChildren(MlvDataTableError, { ...(ngDevMode ? { debugName: "errorTemplate" } : /* istanbul ignore next */ {}), descendants: true });
864
+ footerTemplate = contentChildren(MlvDataTableFooter, { ...(ngDevMode ? { debugName: "footerTemplate" } : /* istanbul ignore next */ {}), descendants: true });
865
+ /** @protected Optional host-owned actions rendered last in the table toolbar. */
866
+ _toolbarActions = contentChild(MlvDataTableToolbarActions, /* @ts-ignore */
867
+ ...(ngDevMode ? [{ debugName: "_toolbarActions" }] : /* istanbul ignore next */ []));
868
+ // ---- View children ----------------------------------------------------------
869
+ tableWrapperRef = viewChild('tableWrapper', /* @ts-ignore */
870
+ ...(ngDevMode ? [{ debugName: "tableWrapperRef" }] : /* istanbul ignore next */ []));
871
+ tableRef = viewChild('tableEl', /* @ts-ignore */
872
+ ...(ngDevMode ? [{ debugName: "tableRef" }] : /* istanbul ignore next */ []));
873
+ /**
874
+ * @private Rendered resize separators. Used after rendering to measure
875
+ * non-pixel CSS widths for accurate initial ARIA values.
876
+ */
877
+ _resizeHandleRefs = viewChildren('resizeHandle', /* @ts-ignore */
878
+ ...(ngDevMode ? [{ debugName: "_resizeHandleRefs" }] : /* istanbul ignore next */ []));
879
+ /**
880
+ * @private Toolbar "Filters" trigger button. Focus is returned here when the
881
+ * filter dialog popup closes, matching the overlay focus-restore pattern.
882
+ */
883
+ _filterTriggerRef = viewChild('filterBtn', { ...(ngDevMode ? { debugName: "_filterTriggerRef" } : /* istanbul ignore next */ {}), read: ElementRef });
884
+ /** @private CDK virtual-scroll viewport (only present in virtual-scroll mode). */
885
+ _virtualViewportRef = viewChild(CdkVirtualScrollViewport, /* @ts-ignore */
886
+ ...(ngDevMode ? [{ debugName: "_virtualViewportRef" }] : /* istanbul ignore next */ []));
887
+ // ---- Services ---------------------------------------------------------------
888
+ /** @private DestroyRef used for observable cleanup. */
889
+ _destroyRef = inject(DestroyRef);
890
+ /** @private Shared resize-observer service used to track the host width. */
891
+ _resizeService = inject(MlvResizeObserverService);
892
+ _rtlService = inject(MlvRtlService);
893
+ /** @private Owning document for pointer fallback listeners and DOM queries. */
894
+ _document = inject(DOCUMENT);
895
+ /** @private Host element ref, observed for width and used for row focus queries. */
896
+ _el = inject(ElementRef);
897
+ /** @private Injector used to schedule `afterNextRender` from imperative handlers. */
898
+ _injector = inject(Injector);
899
+ /** @private Angular zone — column-resize drag listeners run outside it so pointer moves don't trigger a full CD tick per event (see {@link onResizeStart}). */
900
+ _ngZone = inject(NgZone);
901
+ /** @private Resolver for ICU parameterized i18n strings. */
902
+ _resolver = inject(MlvI18nResolverService);
903
+ /**
904
+ * @protected Flat-rows index of the data row that currently owns the roving
905
+ * `tabindex="0"`. All other data rows are `tabindex="-1"`, giving the row grid
906
+ * a single tab stop. Clamped in a constructor effect when `flatRows` changes.
907
+ */
908
+ _focusedRowIndex = signal(0, /* @ts-ignore */
909
+ ...(ngDevMode ? [{ debugName: "_focusedRowIndex" }] : /* istanbul ignore next */ []));
910
+ // ---- Internal state ---------------------------------------------------------
911
+ containerWidth = signal(0, /* @ts-ignore */
912
+ ...(ngDevMode ? [{ debugName: "containerWidth" }] : /* istanbul ignore next */ []));
913
+ activeFilters = model([], /* @ts-ignore */
914
+ ...(ngDevMode ? [{ debugName: "activeFilters" }] : /* istanbul ignore next */ []));
915
+ /** @protected Search text currently shown in the toolbar, including submit-mode drafts. */
916
+ _searchDraft = signal('', /* @ts-ignore */
917
+ ...(ngDevMode ? [{ debugName: "_searchDraft" }] : /* istanbul ignore next */ []));
918
+ currentSort = signal(null, /* @ts-ignore */
919
+ ...(ngDevMode ? [{ debugName: "currentSort" }] : /* istanbul ignore next */ []));
920
+ currentPage = signal(1, /* @ts-ignore */
921
+ ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
922
+ currentPerPage = signal(10, /* @ts-ignore */
923
+ ...(ngDevMode ? [{ debugName: "currentPerPage" }] : /* istanbul ignore next */ []));
924
+ /**
925
+ * Captures durable user-controlled table presentation in declaration order.
926
+ * The returned object is safe to persist and excludes transient page state.
927
+ */
928
+ getPresentationState() {
929
+ const columns = this.columns();
930
+ const sort = this.currentSort();
931
+ const widths = this._columnWidths();
932
+ const columnWidths = {};
933
+ const visibleColumnKeys = [];
934
+ const pinnedStartColumnKeys = [];
935
+ const pinnedEndColumnKeys = [];
936
+ for (const column of columns) {
937
+ if (!this._visibility.isHidden(column.key)) {
938
+ visibleColumnKeys.push(column.key);
939
+ }
940
+ const pinSide = this._pinning.getPinSide(column);
941
+ if (pinSide === 'left')
942
+ pinnedStartColumnKeys.push(column.key);
943
+ if (pinSide === 'right')
944
+ pinnedEndColumnKeys.push(column.key);
945
+ const width = widths.get(column.key);
946
+ if (width !== undefined)
947
+ columnWidths[column.key] = width;
948
+ }
949
+ return {
950
+ sort: sort ? { ...sort } : null,
951
+ visibleColumnKeys,
952
+ pinnedStartColumnKeys,
953
+ pinnedEndColumnKeys,
954
+ columnWidths,
955
+ perPage: this._normalizePerPage(this.currentPerPage()),
956
+ };
957
+ }
958
+ /**
959
+ * Applies only the supplied durable presentation fields after filtering stale
960
+ * keys and normalizing widths and page size. Applying a snapshot always
961
+ * returns the transient current page to one and never emits an echo event.
962
+ */
963
+ applyPresentationState(state) {
964
+ const columns = this.columns();
965
+ const columnKeys = new Set(columns.map((column) => column.key));
966
+ if (state.sort !== undefined) {
967
+ this.currentSort.set(this._normalizePresentationSort(state.sort, columns));
968
+ }
969
+ if (state.visibleColumnKeys !== undefined) {
970
+ const visible = this._knownPresentationKeys(state.visibleColumnKeys, columnKeys);
971
+ for (const column of columns) {
972
+ if (!column.hideable)
973
+ visible.add(column.key);
974
+ }
975
+ this._visibility.replaceHiddenColumns(new Set(columns
976
+ .filter((column) => column.hideable && !visible.has(column.key))
977
+ .map((column) => column.key)));
978
+ }
979
+ if (state.pinnedStartColumnKeys !== undefined ||
980
+ state.pinnedEndColumnKeys !== undefined) {
981
+ const start = state.pinnedStartColumnKeys === undefined
982
+ ? undefined
983
+ : this._knownPresentationKeys(state.pinnedStartColumnKeys, columnKeys);
984
+ const end = state.pinnedEndColumnKeys === undefined
985
+ ? undefined
986
+ : this._knownPresentationKeys(state.pinnedEndColumnKeys, columnKeys);
987
+ this._pinning.replaceOverrides(columns.map((column) => {
988
+ let pinSide = this._pinning.getPinSide(column);
989
+ if (start !== undefined) {
990
+ pinSide = start.has(column.key)
991
+ ? 'left'
992
+ : pinSide === 'left'
993
+ ? null
994
+ : pinSide;
995
+ }
996
+ if (end !== undefined) {
997
+ pinSide = end.has(column.key)
998
+ ? 'right'
999
+ : pinSide === 'right'
1000
+ ? null
1001
+ : pinSide;
1002
+ }
1003
+ return {
1004
+ key: column.key,
1005
+ pinned: pinSide !== null,
1006
+ pinSide: pinSide ?? column.pinSide ?? 'left',
1007
+ };
1008
+ }));
1009
+ }
1010
+ if (state.columnWidths !== undefined) {
1011
+ const widths = new Map();
1012
+ for (const column of columns) {
1013
+ const width = state.columnWidths[column.key];
1014
+ if (typeof width !== 'number')
1015
+ continue;
1016
+ widths.set(column.key, this._normalizeColumnWidth(width, this._columnResizeBounds(column)));
1017
+ }
1018
+ this._columnWidths.set(widths);
1019
+ }
1020
+ if (state.perPage !== undefined) {
1021
+ this.currentPerPage.set(this._normalizePerPage(state.perPage));
1022
+ }
1023
+ this.currentPage.set(1);
1024
+ afterNextRender(() => this._measureHeaderWidths(), {
1025
+ injector: this._injector,
1026
+ });
1027
+ }
1028
+ /** @private Set of currently expanded tree rows (by original row reference). */
1029
+ _expanded = signal(new Set(), /* @ts-ignore */
1030
+ ...(ngDevMode ? [{ debugName: "_expanded" }] : /* istanbul ignore next */ []));
1031
+ /** @private User-resized column widths keyed by column key (px). Committed once per completed pointer drag. */
1032
+ _columnWidths = signal(new Map(), /* @ts-ignore */
1033
+ ...(ngDevMode ? [{ debugName: "_columnWidths" }] : /* istanbul ignore next */ []));
1034
+ /**
1035
+ * @private Live width (px) of the column currently being drag-resized, applied
1036
+ * optimistically during the drag before the committed {@link _columnWidths} map is
1037
+ * updated on pointer release. `null` when no resize is in progress. Kept separate from
1038
+ * {@link _columnWidths} so a move updates a single lightweight signal instead of
1039
+ * cloning the whole widths map every frame.
1040
+ */
1041
+ _liveResize = signal(null, /* @ts-ignore */
1042
+ ...(ngDevMode ? [{ debugName: "_liveResize" }] : /* istanbul ignore next */ []));
1043
+ /**
1044
+ * @private Last DOM-resolved bounds for each resize handle. CSS lengths such
1045
+ * as `rem` can be resolved to pixels from the rendered header during an
1046
+ * interaction and then reused by the separator's ARIA attributes.
1047
+ */
1048
+ _resolvedResizeBounds = signal(new Map(), /* @ts-ignore */
1049
+ ...(ngDevMode ? [{ debugName: "_resolvedResizeBounds" }] : /* istanbul ignore next */ []));
1050
+ /**
1051
+ * @private Rendered header widths keyed by column. This supplies accurate
1052
+ * separator values when a column's declared width uses `rem`, `%`, or layout.
1053
+ */
1054
+ _measuredColumnWidths = signal(new Map(), /* @ts-ignore */
1055
+ ...(ngDevMode ? [{ debugName: "_measuredColumnWidths" }] : /* istanbul ignore next */ []));
1056
+ /** @private Rendered widths of the optional selection and actions columns. */
1057
+ _measuredAuxiliaryWidths = signal({}, /* @ts-ignore */
1058
+ ...(ngDevMode ? [{ debugName: "_measuredAuxiliaryWidths" }] : /* istanbul ignore next */ []));
1059
+ /** @protected Native vertical-scrollbar width inside the virtual viewport. */
1060
+ _virtualScrollbarGutter = signal(0, /* @ts-ignore */
1061
+ ...(ngDevMode ? [{ debugName: "_virtualScrollbarGutter" }] : /* istanbul ignore next */ []));
1062
+ /**
1063
+ * @protected Inert outer scroll width that reproduces the virtual viewport's
1064
+ * native horizontal range without changing any split table's layout.
1065
+ */
1066
+ _virtualHorizontalScrollExtent = signal(0, /* @ts-ignore */
1067
+ ...(ngDevMode ? [{ debugName: "_virtualHorizontalScrollExtent" }] : /* istanbul ignore next */ []));
1068
+ /** @private Whether table geometry is currently frozen to explicit pixel widths. */
1069
+ _columnLayoutFrozen = computed(() => this._liveResize() !== null || this._columnWidths().size > 0, /* @ts-ignore */
1070
+ ...(ngDevMode ? [{ debugName: "_columnLayoutFrozen" }] : /* istanbul ignore next */ []));
1071
+ /**
1072
+ * @private Exact measured utility-column styles used once data columns are
1073
+ * frozen. Keeping selection/actions cells and their `<col>` elements on the
1074
+ * same widths prevents fixed table layout from redistributing data columns.
1075
+ */
1076
+ _auxiliaryColumnStyles = computed(() => {
1077
+ const measured = this._measuredAuxiliaryWidths();
1078
+ if (!this._columnLayoutFrozen()) {
1079
+ return { selection: null, actions: null };
1080
+ }
1081
+ return {
1082
+ selection: this._fixedColumnWidthStyles(measured.selection),
1083
+ actions: this._fixedColumnWidthStyles(measured.actions),
1084
+ };
1085
+ }, /* @ts-ignore */
1086
+ ...(ngDevMode ? [{ debugName: "_auxiliaryColumnStyles" }] : /* istanbul ignore next */ []));
1087
+ /**
1088
+ * @private Per-row cache of the cell-template `ngTemplateOutletContext`, keyed by the
1089
+ * flattened row object identity (see {@link getCellContext}). A `WeakMap` so entries
1090
+ * for rows dropped by a `flatRows()` recompute are reclaimed automatically.
1091
+ */
1092
+ _cellContextCache = new WeakMap();
1093
+ /** @private Stable one-column arrays used by repeated header filter editors. */
1094
+ _columnFilterLists = new Map();
1095
+ /** @private Editing state moved to MlvDataTableEditingService. */
1096
+ _editing = inject((MlvDataTableEditingService));
1097
+ /** @private Column visibility state moved to MlvDataTableColumnVisibilityService. */
1098
+ _visibility = inject(MlvDataTableColumnVisibilityService);
1099
+ /** @private Pin override state moved to MlvDataTablePinningService. */
1100
+ _pinning = inject(MlvDataTablePinningService);
1101
+ // ---- Derived state ----------------------------------------------------------
1102
+ effectiveDataSource = computed(() => {
1103
+ const d = this.data();
1104
+ if (d instanceof MlvDataSource) {
1105
+ return d;
1106
+ }
1107
+ const rows = Array.isArray(d) ? d : [];
1108
+ return new MlvArrayDataSource(rows);
1109
+ }, /* @ts-ignore */
1110
+ ...(ngDevMode ? [{ debugName: "effectiveDataSource" }] : /* istanbul ignore next */ []));
1111
+ displayRows = computed(() => {
1112
+ const ds = this.effectiveDataSource();
1113
+ return ds.connect()();
1114
+ }, /* @ts-ignore */
1115
+ ...(ngDevMode ? [{ debugName: "displayRows" }] : /* istanbul ignore next */ []));
1116
+ flatRows = computed(() => {
1117
+ const rows = this.displayRows();
1118
+ const expanded = this._expanded();
1119
+ return flattenRows(rows, expanded);
1120
+ }, /* @ts-ignore */
1121
+ ...(ngDevMode ? [{ debugName: "flatRows" }] : /* istanbul ignore next */ []));
1122
+ totalItems = computed(() => this.effectiveDataSource().totalItems(), /* @ts-ignore */
1123
+ ...(ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []));
1124
+ shownItems = computed(() => this.flatRows().length, /* @ts-ignore */
1125
+ ...(ngDevMode ? [{ debugName: "shownItems" }] : /* istanbul ignore next */ []));
1126
+ visibleColumns = computed(() => {
1127
+ const cols = this.columns();
1128
+ const containerW = this.containerWidth();
1129
+ const widths = this._columnWidths();
1130
+ const live = this._liveResize();
1131
+ const measured = this._measuredColumnWidths();
1132
+ const freezeLayout = this._columnLayoutFrozen();
1133
+ const pinOverrides = this._pinning.overrides();
1134
+ const hidden = this._visibility.hiddenColumns();
1135
+ return cols
1136
+ .map((col) => {
1137
+ const visible = isColumnVisible(col, containerW);
1138
+ // During a drag the live width wins over the committed map value so the
1139
+ // column tracks the pointer before the map is updated on pointer release.
1140
+ const w = live && live.key === col.key ? live.width : widths.get(col.key);
1141
+ const override = pinOverrides.get(col.key);
1142
+ return {
1143
+ ...col,
1144
+ pinned: override ? override.pinned : col.pinned,
1145
+ pinSide: override ? override.pinSide : col.pinSide,
1146
+ _currentWidth: w ??
1147
+ (freezeLayout
1148
+ ? (measured.get(col.key) ?? parsePixelWidth(col.width))
1149
+ : undefined),
1150
+ _visible: visible,
1151
+ };
1152
+ })
1153
+ .filter((c) => c._visible !== false && !hidden.has(c.key))
1154
+ .sort((a, b) => {
1155
+ const order = (col) => {
1156
+ if (col.pinned && col.pinSide !== 'right')
1157
+ return 0;
1158
+ if (!col.pinned)
1159
+ return 1;
1160
+ return 2; // pinned right
1161
+ };
1162
+ return order(a) - order(b);
1163
+ });
1164
+ }, /* @ts-ignore */
1165
+ ...(ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []));
1166
+ pinnedLeftColumns = computed(() => this.visibleColumns().filter((c) => c.pinned && c.pinSide !== 'right'), /* @ts-ignore */
1167
+ ...(ngDevMode ? [{ debugName: "pinnedLeftColumns" }] : /* istanbul ignore next */ []));
1168
+ pinnedRightColumns = computed(() => this.visibleColumns().filter((c) => c.pinned && c.pinSide === 'right'), /* @ts-ignore */
1169
+ ...(ngDevMode ? [{ debugName: "pinnedRightColumns" }] : /* istanbul ignore next */ []));
1170
+ columnOffsets = computed(() => {
1171
+ const map = new Map();
1172
+ const leftWidths = [];
1173
+ for (const col of this.pinnedLeftColumns()) {
1174
+ map.set(col.key + '_left', this._sumCssLengths(leftWidths));
1175
+ leftWidths.push(this._columnOffsetWidth(col));
1176
+ }
1177
+ const rightWidths = [];
1178
+ const rightCols = [...this.pinnedRightColumns()].reverse();
1179
+ for (const col of rightCols) {
1180
+ map.set(col.key + '_right', this._sumCssLengths(rightWidths));
1181
+ rightWidths.push(this._columnOffsetWidth(col));
1182
+ }
1183
+ return map;
1184
+ }, /* @ts-ignore */
1185
+ ...(ngDevMode ? [{ debugName: "columnOffsets" }] : /* istanbul ignore next */ []));
1186
+ /**
1187
+ * Exact table width used while at least one column has a live or committed
1188
+ * user override. Freezing every measured column and the table to the same
1189
+ * pixel sum prevents `width: 100%` table layout from redistributing the
1190
+ * committed width. All virtual split tables and their viewport consume this
1191
+ * same value.
1192
+ */
1193
+ resizedTableWidth = computed(() => {
1194
+ if (!this._columnLayoutFrozen())
1195
+ return null;
1196
+ const measured = this._measuredColumnWidths();
1197
+ const auxiliary = this._measuredAuxiliaryWidths();
1198
+ let total = 0;
1199
+ for (const col of this.visibleColumns()) {
1200
+ total +=
1201
+ col._currentWidth ??
1202
+ measured.get(col.key) ??
1203
+ parsePixelWidth(col.width) ??
1204
+ DEFAULT_COLUMN_WIDTH;
1205
+ }
1206
+ if (this.selectable()) {
1207
+ total += auxiliary.selection ?? DEFAULT_SELECTION_COLUMN_WIDTH;
1208
+ }
1209
+ if (this.editable()) {
1210
+ total += auxiliary.actions ?? DEFAULT_ACTIONS_COLUMN_WIDTH;
1211
+ }
1212
+ return this._roundColumnWidth(total);
1213
+ }, /* @ts-ignore */
1214
+ ...(ngDevMode ? [{ debugName: "resizedTableWidth" }] : /* istanbul ignore next */ []));
1215
+ /**
1216
+ * @private Memoized inline `[style]` object per visible column, keyed by column key.
1217
+ * Rebuilt only when {@link visibleColumns} or {@link columnOffsets} change (width /
1218
+ * pin / visibility / responsive / live-resize changes). Cell `[style]` bindings read
1219
+ * this map through {@link getCellStyle} so they receive a *stable* object reference
1220
+ * across change-detection cycles instead of a freshly allocated `Record` per cell per
1221
+ * CD; the header and body cells of a column share one object.
1222
+ */
1223
+ _columnStyles = computed(() => {
1224
+ const offsets = this.columnOffsets();
1225
+ const map = new Map();
1226
+ for (const col of this.visibleColumns()) {
1227
+ map.set(col.key, columnCellStyles(col, offsets));
1228
+ }
1229
+ return map;
1230
+ }, /* @ts-ignore */
1231
+ ...(ngDevMode ? [{ debugName: "_columnStyles" }] : /* istanbul ignore next */ []));
1232
+ /**
1233
+ * @private Display cell templates resolved to a `Map<columnKey, TemplateRef>`, rebuilt
1234
+ * only when the projected {@link cellTemplates} set changes. Replaces a per-cell
1235
+ * `Array.find()` on every CD ({@link getTemplate}). First registration wins for
1236
+ * duplicate keys, preserving the previous `find()` (first-match) semantics.
1237
+ */
1238
+ _cellTemplateMap = computed(() => {
1239
+ const map = new Map();
1240
+ for (const t of this.cellTemplates()) {
1241
+ const key = t.columnKey();
1242
+ if (!map.has(key))
1243
+ map.set(key, t.templateRef);
1244
+ }
1245
+ return map;
1246
+ }, /* @ts-ignore */
1247
+ ...(ngDevMode ? [{ debugName: "_cellTemplateMap" }] : /* istanbul ignore next */ []));
1248
+ /**
1249
+ * @private Edit-mode cell templates resolved to a `Map<columnKey, TemplateRef>`,
1250
+ * rebuilt only when the projected {@link editCellTemplates} set changes. Replaces a
1251
+ * per-cell `Array.find()` on every CD ({@link getEditTemplate}). First registration
1252
+ * wins for duplicate keys.
1253
+ */
1254
+ _editCellTemplateMap = computed(() => {
1255
+ const map = new Map();
1256
+ for (const t of this.editCellTemplates()) {
1257
+ const key = t.columnKey();
1258
+ if (!map.has(key))
1259
+ map.set(key, t.templateRef);
1260
+ }
1261
+ return map;
1262
+ }, /* @ts-ignore */
1263
+ ...(ngDevMode ? [{ debugName: "_editCellTemplateMap" }] : /* istanbul ignore next */ []));
1264
+ /**
1265
+ * @protected Whether the experimental aria cell-level grid navigation is
1266
+ * active. Gated to non-virtual mode: `virtualScroll` recycles rows out of the
1267
+ * DOM, which the aria grid's DOM-registered row/cell collection cannot track,
1268
+ * so cell navigation yields to the stable row-roving path when virtual scroll
1269
+ * is on.
1270
+ */
1271
+ _cellNav = computed(() => this.cellNavigation() && !this.virtualScroll(), /* @ts-ignore */
1272
+ ...(ngDevMode ? [{ debugName: "_cellNav" }] : /* istanbul ignore next */ []));
1273
+ /**
1274
+ * Whether the error block replaces the table body. An in-flight refetch wins:
1275
+ * while `loading` is truthy the previous error is suppressed so the loader is
1276
+ * not competing with a stale failure message.
1277
+ */
1278
+ showError = computed(() => {
1279
+ const error = this.error();
1280
+ if (this.loading())
1281
+ return false;
1282
+ return typeof error === 'string' ? error.trim().length > 0 : error === true;
1283
+ }, /* @ts-ignore */
1284
+ ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
1285
+ /**
1286
+ * Message rendered by the error block: the `error` string when one was
1287
+ * supplied, otherwise the localized `errorMessage` default.
1288
+ */
1289
+ errorMessage = computed(() => {
1290
+ const error = this.error();
1291
+ return typeof error === 'string' && error.trim().length > 0
1292
+ ? error
1293
+ : this._i18n().errorMessage;
1294
+ }, /* @ts-ignore */
1295
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
1296
+ /**
1297
+ * @private Stable `retry()` callback handed to the `mlvDataTableError`
1298
+ * template context, so the context object identity only changes with the
1299
+ * message.
1300
+ */
1301
+ _emitRetry = () => this.onRetry();
1302
+ /**
1303
+ * @protected `ngTemplateOutletContext` for a projected `mlvDataTableError`
1304
+ * template.
1305
+ */
1306
+ _errorContext = computed(() => ({
1307
+ $implicit: this.errorMessage(),
1308
+ retry: this._emitRetry,
1309
+ }), /* @ts-ignore */
1310
+ ...(ngDevMode ? [{ debugName: "_errorContext" }] : /* istanbul ignore next */ []));
1311
+ /**
1312
+ * @private Per-column raw-value → label lookup, memoized from
1313
+ * `visibleColumns()`. Falls back to `filterConfig.options` when a column
1314
+ * declares no explicit `valueLabels`. Keys are stringified raw values.
1315
+ */
1316
+ _columnValueLabels = computed(() => {
1317
+ const map = new Map();
1318
+ for (const col of this.visibleColumns()) {
1319
+ const source = col.valueLabels ?? col.filterConfig?.options;
1320
+ if (!source)
1321
+ continue;
1322
+ const labels = new Map();
1323
+ if (Array.isArray(source)) {
1324
+ for (const option of source) {
1325
+ labels.set(String(option.value), option.label);
1326
+ }
1327
+ }
1328
+ else {
1329
+ for (const [value, label] of Object.entries(source)) {
1330
+ labels.set(value, label);
1331
+ }
1332
+ }
1333
+ if (labels.size > 0)
1334
+ map.set(col.key, labels);
1335
+ }
1336
+ return map;
1337
+ }, /* @ts-ignore */
1338
+ ...(ngDevMode ? [{ debugName: "_columnValueLabels" }] : /* istanbul ignore next */ []));
1339
+ hasFilters = computed(() => this.activeFilters().length > 0, /* @ts-ignore */
1340
+ ...(ngDevMode ? [{ debugName: "hasFilters" }] : /* istanbul ignore next */ []));
1341
+ /** Columns included in the global query, independent of responsive visibility. */
1342
+ searchableColumns = computed(() => this.columns().filter((column) => column.searchable), /* @ts-ignore */
1343
+ ...(ngDevMode ? [{ debugName: "searchableColumns" }] : /* istanbul ignore next */ []));
1344
+ /** Stable key list passed to the data source for OR-across-columns search. */
1345
+ searchableColumnKeys = computed(() => this.searchableColumns().map((column) => column.key), /* @ts-ignore */
1346
+ ...(ngDevMode ? [{ debugName: "searchableColumnKeys" }] : /* istanbul ignore next */ []));
1347
+ /** Whether a global search field belongs in the toolbar. */
1348
+ hasSearchableColumns = computed(() => this.searchableColumns().length > 0, /* @ts-ignore */
1349
+ ...(ngDevMode ? [{ debugName: "hasSearchableColumns" }] : /* istanbul ignore next */ []));
1350
+ /** Whether any configured column supports filtering. */
1351
+ hasFilterableColumns = computed(() => this.columns().some((column) => column.filterable), /* @ts-ignore */
1352
+ ...(ngDevMode ? [{ debugName: "hasFilterableColumns" }] : /* istanbul ignore next */ []));
1353
+ /** Whether any configured column supports sorting. */
1354
+ hasSortableColumns = computed(() => this.columns().some((column) => column.sortable), /* @ts-ignore */
1355
+ ...(ngDevMode ? [{ debugName: "hasSortableColumns" }] : /* istanbul ignore next */ []));
1356
+ /** Localized active-filter summary announced when the committed set changes. */
1357
+ activeFilterLabel = computed(() => this._resolver.resolve(this._i18n(), 'activeFilterCount', { count: this.activeFilters().length }), /* @ts-ignore */
1358
+ ...(ngDevMode ? [{ debugName: "activeFilterLabel" }] : /* istanbul ignore next */ []));
1359
+ /** Total number of rendered columns (visible + selection checkbox + actions). */
1360
+ totalColumnCount = computed(() => {
1361
+ let count = this.visibleColumns().length;
1362
+ if (this.selectable())
1363
+ count++;
1364
+ if (this.editable())
1365
+ count++;
1366
+ return count;
1367
+ }, /* @ts-ignore */
1368
+ ...(ngDevMode ? [{ debugName: "totalColumnCount" }] : /* istanbul ignore next */ []));
1369
+ /**
1370
+ * Pixel/CSS height applied to the `cdk-virtual-scroll-viewport` when `virtualScroll` is on.
1371
+ * Falls back to `'24rem'` if `maxHeight` is not provided. The viewport requires an explicit
1372
+ * height because `cdk-virtual-scroll-viewport` does not derive its size from its content.
1373
+ */
1374
+ virtualViewportHeight = computed(() => this.maxHeight() ?? '24rem', /* @ts-ignore */
1375
+ ...(ngDevMode ? [{ debugName: "virtualViewportHeight" }] : /* istanbul ignore next */ []));
1376
+ /** Whether any column has `hideable: true`. */
1377
+ hasHideableColumns = computed(() => this.columns().some((c) => c.hideable), /* @ts-ignore */
1378
+ ...(ngDevMode ? [{ debugName: "hasHideableColumns" }] : /* istanbul ignore next */ []));
1379
+ /** Whether the toolbar has a visible control or table-owned status to render. */
1380
+ hasToolbarContent = computed(() => (this.showSearch() && this.hasSearchableColumns()) ||
1381
+ (this.filterDisplay() !== 'none' && this.hasFilters()) ||
1382
+ (this.editable() && this.addRow()) ||
1383
+ (this.showSortMenu() && this.hasSortableColumns()) ||
1384
+ this.hasHideableColumns() ||
1385
+ (this.filterDisplay() === 'toolbar' && this.hasFilterableColumns()) ||
1386
+ !!this._toolbarActions(), /* @ts-ignore */
1387
+ ...(ngDevMode ? [{ debugName: "hasToolbarContent" }] : /* istanbul ignore next */ []));
1388
+ /** All columns (for column visibility popup). */
1389
+ allColumns = computed(() => this.columns(), /* @ts-ignore */
1390
+ ...(ngDevMode ? [{ debugName: "allColumns" }] : /* istanbul ignore next */ []));
1391
+ /** Whether all visible rows are selected. */
1392
+ allRowsSelected = computed(() => {
1393
+ const rows = this.flatRows();
1394
+ const selected = this.selectedRows();
1395
+ return rows.length > 0 && rows.every((r) => selected.has(this._ref(r)));
1396
+ }, /* @ts-ignore */
1397
+ ...(ngDevMode ? [{ debugName: "allRowsSelected" }] : /* istanbul ignore next */ []));
1398
+ /** Whether some (but not all) rows are selected. */
1399
+ someRowsSelected = computed(() => {
1400
+ const rows = this.flatRows();
1401
+ const selected = this.selectedRows();
1402
+ const count = rows.filter((r) => selected.has(this._ref(r))).length;
1403
+ return count > 0 && count < rows.length;
1404
+ }, /* @ts-ignore */
1405
+ ...(ngDevMode ? [{ debugName: "someRowsSelected" }] : /* istanbul ignore next */ []));
1406
+ /** Whether the table has multi-row column groups defined. */
1407
+ hasColumnGroups = computed(() => this.columnGroups().length > 0, /* @ts-ignore */
1408
+ ...(ngDevMode ? [{ debugName: "hasColumnGroups" }] : /* istanbul ignore next */ []));
1409
+ /**
1410
+ * Computes the group header row layout.
1411
+ * Columns covered by a group get colspan in the group row.
1412
+ * Standalone columns (not in any group) get rowspan="2" in the main header row.
1413
+ */
1414
+ headerLayout = computed(() => {
1415
+ const groups = this.columnGroups();
1416
+ const visible = this.visibleColumns();
1417
+ if (groups.length === 0)
1418
+ return null;
1419
+ const groupedKeys = new Set(groups.flatMap((g) => g.columns));
1420
+ // Build group header cells
1421
+ const groupCells = [];
1422
+ const standaloneKeys = new Set();
1423
+ // Track which visible columns belong to which group
1424
+ let colIndex = 0;
1425
+ while (colIndex < visible.length) {
1426
+ const col = visible[colIndex];
1427
+ const group = groups.find((g) => g.columns.includes(col.key));
1428
+ if (group) {
1429
+ // Count how many consecutive visible columns belong to this group
1430
+ const span = visible.filter((c) => group.columns.includes(c.key)).length;
1431
+ groupCells.push({ type: 'group', group, colspan: span });
1432
+ // Skip all columns in this group
1433
+ colIndex += span;
1434
+ }
1435
+ else {
1436
+ standaloneKeys.add(col.key);
1437
+ colIndex++;
1438
+ }
1439
+ }
1440
+ return { groupCells, standaloneKeys, groupedKeys };
1441
+ }, /* @ts-ignore */
1442
+ ...(ngDevMode ? [{ debugName: "headerLayout" }] : /* istanbul ignore next */ []));
1443
+ // ---- Lifecycle --------------------------------------------------------------
1444
+ constructor() {
1445
+ // Detach any in-flight column-resize drag listeners if the table is destroyed
1446
+ // mid-drag (e.g. a route change while the user is resizing a column) so the dead
1447
+ // component's document listeners can't keep firing.
1448
+ this._destroyRef.onDestroy(() => this._cleanupResize());
1449
+ effect(() => {
1450
+ const ds = this.effectiveDataSource();
1451
+ ds.setSort(this.currentSort());
1452
+ });
1453
+ effect(() => {
1454
+ const ds = this.effectiveDataSource();
1455
+ const filters = this.activeFilters();
1456
+ ds.setFilters(filters);
1457
+ untracked(() => {
1458
+ if (this.currentPage() !== 1)
1459
+ this.currentPage.set(1);
1460
+ });
1461
+ });
1462
+ effect(() => {
1463
+ const ds = this.effectiveDataSource();
1464
+ const query = this.searchQuery();
1465
+ const keys = this.searchableColumnKeys();
1466
+ ds.setSearch(query.trim() && keys.length ? { query, keys } : null);
1467
+ untracked(() => {
1468
+ if (this._searchDraft() !== query)
1469
+ this._searchDraft.set(query);
1470
+ if (this.currentPage() !== 1)
1471
+ this.currentPage.set(1);
1472
+ });
1473
+ });
1474
+ effect(() => {
1475
+ const ds = this.effectiveDataSource();
1476
+ // In infinite or virtual-scroll mode the consumer hands over the entire
1477
+ // row set up front, so the internal data source must stay on page 1 at
1478
+ // all times — pagination is disabled in both modes.
1479
+ const unpaged = this.paginationMode() === 'infinite' || this.virtualScroll();
1480
+ ds.setPage(unpaged ? 1 : this.currentPage());
1481
+ });
1482
+ effect(() => {
1483
+ const ds = this.effectiveDataSource();
1484
+ // In infinite or virtual-scroll mode disable internal per-page slicing
1485
+ // so every row the consumer has provided gets rendered. Virtual scroll
1486
+ // then renders only the visible slice of that full list via CDK.
1487
+ const unpaged = this.paginationMode() === 'infinite' || this.virtualScroll();
1488
+ ds.setPerPage(unpaged ? Number.MAX_SAFE_INTEGER : this.currentPerPage());
1489
+ });
1490
+ // Keep the roving row index in range as the visible rows change
1491
+ // (filtering, sorting, paging, tree expand/collapse, data replacement).
1492
+ effect(() => {
1493
+ const count = this.flatRows().length;
1494
+ const current = untracked(this._focusedRowIndex);
1495
+ if (count === 0) {
1496
+ if (current !== 0)
1497
+ this._focusedRowIndex.set(0);
1498
+ }
1499
+ else if (current > count - 1) {
1500
+ this._focusedRowIndex.set(count - 1);
1501
+ }
1502
+ });
1503
+ effect(() => {
1504
+ const handles = this._resizeHandleRefs();
1505
+ if (!handles.length)
1506
+ return;
1507
+ afterNextRender(() => this._measureHeaderWidths(), {
1508
+ injector: this._injector,
1509
+ });
1510
+ });
1511
+ effect((onCleanup) => {
1512
+ if (!this.virtualScroll())
1513
+ return;
1514
+ const wrapper = this.tableWrapperRef()?.nativeElement;
1515
+ const viewport = this._virtualViewportRef()?.elementRef.nativeElement;
1516
+ if (!wrapper || !viewport)
1517
+ return;
1518
+ let synchronizing = false;
1519
+ const measureVirtualGeometry = () => {
1520
+ this._updateVirtualScrollGeometry(wrapper, viewport);
1521
+ };
1522
+ const syncFromWrapper = () => {
1523
+ if (synchronizing || viewport.scrollLeft === wrapper.scrollLeft)
1524
+ return;
1525
+ synchronizing = true;
1526
+ try {
1527
+ viewport.scrollLeft = wrapper.scrollLeft;
1528
+ }
1529
+ finally {
1530
+ synchronizing = false;
1531
+ }
1532
+ };
1533
+ const syncFromViewport = () => {
1534
+ if (synchronizing || wrapper.scrollLeft === viewport.scrollLeft)
1535
+ return;
1536
+ synchronizing = true;
1537
+ try {
1538
+ wrapper.scrollLeft = viewport.scrollLeft;
1539
+ const acceptedScrollLeft = wrapper.scrollLeft;
1540
+ if (viewport.scrollLeft !== acceptedScrollLeft) {
1541
+ viewport.scrollLeft = acceptedScrollLeft;
1542
+ }
1543
+ }
1544
+ finally {
1545
+ synchronizing = false;
1546
+ }
1547
+ };
1548
+ this._ngZone.runOutsideAngular(() => {
1549
+ wrapper.addEventListener('scroll', syncFromWrapper, {
1550
+ passive: true,
1551
+ });
1552
+ viewport.addEventListener('scroll', syncFromViewport, {
1553
+ passive: true,
1554
+ });
1555
+ measureVirtualGeometry();
1556
+ syncFromWrapper();
1557
+ });
1558
+ const viewportResize = this._resizeService
1559
+ .observe(viewport)
1560
+ .subscribe(() => {
1561
+ measureVirtualGeometry();
1562
+ syncFromWrapper();
1563
+ });
1564
+ onCleanup(() => {
1565
+ wrapper.removeEventListener('scroll', syncFromWrapper);
1566
+ viewport.removeEventListener('scroll', syncFromViewport);
1567
+ viewportResize.unsubscribe();
1568
+ });
1569
+ });
1570
+ effect(() => {
1571
+ if (!this.virtualScroll())
1572
+ return;
1573
+ this.resizedTableWidth();
1574
+ this.visibleColumns();
1575
+ this._virtualScrollbarGutter();
1576
+ afterNextRender(() => this._syncVirtualHorizontalScroll(), {
1577
+ injector: this._injector,
1578
+ });
1579
+ });
1580
+ afterNextRender(() => {
1581
+ const el = this._el.nativeElement;
1582
+ this._resizeService
1583
+ .observe(el)
1584
+ .pipe(takeUntilDestroyed(this._destroyRef))
1585
+ .subscribe((entries) => {
1586
+ const width = entries[0]?.contentRect?.width ?? el.offsetWidth;
1587
+ this.containerWidth.set(width);
1588
+ afterNextRender(() => this._measureHeaderWidths(), {
1589
+ injector: this._injector,
1590
+ });
1591
+ });
1592
+ this.containerWidth.set(el.offsetWidth);
1593
+ this._measureHeaderWidths();
1594
+ });
1595
+ }
1596
+ // ---- Template helpers -------------------------------------------------------
1597
+ /** Resolves the custom display template for a column key (if any). */
1598
+ getTemplate(key) {
1599
+ return this._cellTemplateMap().get(key) ?? null;
1600
+ }
1601
+ getNoDataTemplate() {
1602
+ const list = this.noDataTemplate();
1603
+ return list.length > 0 ? list[0].templateRef : null;
1604
+ }
1605
+ /**
1606
+ * `ngTemplateOutletContext` for a data cell's custom/edit template. Returns a
1607
+ * *stable* per-row object so the outlet's context does not churn (fresh object +
1608
+ * `NgTemplateOutlet.ngOnChanges`) every change-detection cycle. `flatRows()` rebuilds
1609
+ * its row objects on every data / sort / filter / expand change, so a cached entry's
1610
+ * `index` always matches that row's current position and stale entries (whose row
1611
+ * objects are no longer referenced) are garbage-collected.
1612
+ */
1613
+ getCellContext(row, index) {
1614
+ let ctx = this._cellContextCache.get(row);
1615
+ if (!ctx) {
1616
+ ctx = { $implicit: row, row, index };
1617
+ this._cellContextCache.set(row, ctx);
1618
+ }
1619
+ return ctx;
1620
+ }
1621
+ getCellValue(row, key) {
1622
+ return row[key];
1623
+ }
1624
+ /**
1625
+ * Value rendered by the **default** cell renderer. Maps the raw value through
1626
+ * the column's `valueLabels` (or its `filterConfig.options` fallback) when a
1627
+ * label exists; otherwise returns the raw value unchanged. Custom
1628
+ * `mlvDataTableCell` templates bypass this entirely.
1629
+ */
1630
+ getCellDisplayValue(row, col) {
1631
+ const raw = this.getCellValue(row, col.key);
1632
+ if (raw === null || raw === undefined)
1633
+ return raw;
1634
+ const labels = this._columnValueLabels().get(col.key);
1635
+ if (!labels)
1636
+ return raw;
1637
+ return labels.get(String(raw)) ?? raw;
1638
+ }
1639
+ /**
1640
+ * Resolves the semantic tone for one default-rendered cell. Returns `null`
1641
+ * when the column declares no `tone` (or its resolver opted this row out), in
1642
+ * which case the cell renders as plain text instead of a badge.
1643
+ */
1644
+ getCellTone(row, col) {
1645
+ const tone = col.tone;
1646
+ if (!tone)
1647
+ return null;
1648
+ if (typeof tone === 'function') {
1649
+ return tone(row) ?? null;
1650
+ }
1651
+ return tone;
1652
+ }
1653
+ /** Retrieves the projected error template, if the consumer supplied one. */
1654
+ getErrorTemplate() {
1655
+ const list = this.errorTemplate();
1656
+ return list.length > 0 ? list[0].templateRef : null;
1657
+ }
1658
+ /** Emits `retry` so the consumer can refetch the failed request. */
1659
+ onRetry() {
1660
+ this.retry.emit();
1661
+ }
1662
+ /** Resolves the edit-mode template for a column key (if any). */
1663
+ getEditTemplate(key) {
1664
+ return this._editCellTemplateMap().get(key) ?? null;
1665
+ }
1666
+ /** Whether a given row index is currently being edited. */
1667
+ isEditing(index) {
1668
+ return this._editing.isEditing(index);
1669
+ }
1670
+ /** Enter edit mode for a row. Clones the row for rollback. */
1671
+ startEdit(row, index) {
1672
+ this._editing.start(row, index);
1673
+ this.rowEditStart.emit({ row, index });
1674
+ }
1675
+ /** Confirm edits for a row. Emits save event with original and modified row. */
1676
+ saveEdit(row, index) {
1677
+ const originalRow = this._editing.save(row, index);
1678
+ this.rowEditSave.emit({ row, index, originalRow });
1679
+ }
1680
+ /** Cancel editing. Emits cancel event. */
1681
+ cancelEdit(row, index) {
1682
+ this._editing.cancel(index);
1683
+ this.rowEditCancel.emit({ row, index });
1684
+ }
1685
+ /** Emit add-row event. Consumer is responsible for appending the new row. */
1686
+ onAddRow() {
1687
+ this.rowAdd.emit();
1688
+ }
1689
+ // ---- Row click ---------------------------------------------------------------
1690
+ /** Handle click on a data row. */
1691
+ onRowClick(row, index, event) {
1692
+ this._focusedRowIndex.set(index);
1693
+ this.rowClick.emit({ row, index, event });
1694
+ }
1695
+ // ---- Row keyboard navigation (grid row-focus model) --------------------------
1696
+ /**
1697
+ * @protected Roving tabindex for a data row: `0` for the focused row, `-1`
1698
+ * otherwise, so the row grid exposes a single tab stop.
1699
+ */
1700
+ _rowTabIndex(index) {
1701
+ return index === this._focusedRowIndex() ? 0 : -1;
1702
+ }
1703
+ /**
1704
+ * @protected Sync the roving row index when a row receives focus (via Tab or
1705
+ * a click that focuses the `<tr>`).
1706
+ */
1707
+ _onRowFocus(index) {
1708
+ this._focusedRowIndex.set(index);
1709
+ }
1710
+ /**
1711
+ * @protected Row-level keyboard navigation for the `role="grid"` table.
1712
+ * Active only when the `<tr>` itself holds focus — keys originating from an
1713
+ * interactive cell widget (checkbox, button, edit input) are left alone.
1714
+ *
1715
+ * - `ArrowUp` / `ArrowDown` — move row focus by one (clamped)
1716
+ * - `Home` / `End` — jump to the first / last row
1717
+ * - `Space` / `Enter` — toggle selection of the focused row when selectable
1718
+ */
1719
+ _onRowKeydown(index, row, event) {
1720
+ if (event.target !== event.currentTarget)
1721
+ return;
1722
+ const lastIndex = this.flatRows().length - 1;
1723
+ switch (this._rtlService.normalizeArrowKey(event) ?? event.key) {
1724
+ case DOWN_ARROW:
1725
+ event.preventDefault();
1726
+ this._moveRowFocus(Math.min(index + 1, lastIndex));
1727
+ break;
1728
+ case UP_ARROW:
1729
+ event.preventDefault();
1730
+ this._moveRowFocus(Math.max(index - 1, 0));
1731
+ break;
1732
+ case 'Home':
1733
+ event.preventDefault();
1734
+ this._moveRowFocus(0);
1735
+ break;
1736
+ case 'End':
1737
+ event.preventDefault();
1738
+ this._moveRowFocus(lastIndex);
1739
+ break;
1740
+ case ' ':
1741
+ case 'Enter':
1742
+ if (this.selectable()) {
1743
+ event.preventDefault();
1744
+ this.toggleRowSelection(row);
1745
+ }
1746
+ break;
1747
+ }
1748
+ }
1749
+ /**
1750
+ * @private Move the roving tabindex and DOM focus to the row at `targetIndex`.
1751
+ * In virtual-scroll mode the target may be recycled out of the DOM, so it is
1752
+ * scrolled into view first and focused after the next render.
1753
+ */
1754
+ _moveRowFocus(targetIndex) {
1755
+ if (targetIndex < 0)
1756
+ return;
1757
+ this._focusedRowIndex.set(targetIndex);
1758
+ if (this.virtualScroll()) {
1759
+ this._virtualViewportRef()?.scrollToIndex(targetIndex, 'smooth');
1760
+ }
1761
+ afterNextRender(() => this._focusRowElement(targetIndex), {
1762
+ injector: this._injector,
1763
+ });
1764
+ }
1765
+ /** @private Focus the rendered `<tr>` for the given flat-rows index, if present. */
1766
+ _focusRowElement(index) {
1767
+ const host = this._el.nativeElement;
1768
+ const rowEl = host.querySelector(`[data-row-index="${index}"]`);
1769
+ rowEl?.focus();
1770
+ }
1771
+ // ---- Infinite scroll ---------------------------------------------------------
1772
+ /**
1773
+ * Handler wired to `MlvInfiniteScroll.loadMore` when `paginationMode === 'infinite'`.
1774
+ * Increments the tracked page counter and emits a table-level `MlvLoadMoreEvent`
1775
+ * whose `page` field tells the consumer which page to fetch next.
1776
+ */
1777
+ onInfiniteScrollLoadMore(trigger) {
1778
+ const nextPage = this.currentPage() + 1;
1779
+ this.currentPage.set(nextPage);
1780
+ this.loadMore.emit({
1781
+ page: nextPage,
1782
+ perPage: this.currentPerPage(),
1783
+ distance: trigger.distance,
1784
+ });
1785
+ }
1786
+ /** @internal Applies a transient paginator page change without a snapshot. */
1787
+ _onPageChange(page) {
1788
+ this.currentPage.set(Math.max(1, Math.floor(page)));
1789
+ }
1790
+ /** Applies a durable paginator page-size change and emits one snapshot. */
1791
+ _onPerPageChange(perPage) {
1792
+ this.currentPerPage.set(this._normalizePerPage(perPage));
1793
+ this.currentPage.set(1);
1794
+ this._emitPresentationStateChange();
1795
+ }
1796
+ // ---- Row selection -----------------------------------------------------------
1797
+ /** Whether a specific row is currently selected. */
1798
+ isRowSelected(row) {
1799
+ return this.selectedRows().has(this._ref(row));
1800
+ }
1801
+ /** Toggle selection for a single row. */
1802
+ toggleRowSelection(row) {
1803
+ const ref = this._ref(row);
1804
+ const current = this.selectedRows();
1805
+ const next = new Set(current);
1806
+ const mode = this.selectable();
1807
+ if (mode === 'single') {
1808
+ if (next.has(ref)) {
1809
+ next.clear();
1810
+ }
1811
+ else {
1812
+ next.clear();
1813
+ next.add(ref);
1814
+ }
1815
+ }
1816
+ else if (mode === 'multi') {
1817
+ if (next.has(ref)) {
1818
+ next.delete(ref);
1819
+ }
1820
+ else {
1821
+ next.add(ref);
1822
+ }
1823
+ }
1824
+ this.selectedRows.set(next);
1825
+ this.selectionChange.emit({ selectedRows: next, row: ref });
1826
+ }
1827
+ /** Toggle select-all / deselect-all. */
1828
+ toggleSelectAll() {
1829
+ const rows = this.flatRows();
1830
+ const allSelected = this.allRowsSelected();
1831
+ const next = new Set();
1832
+ if (!allSelected) {
1833
+ for (const row of rows) {
1834
+ next.add(this._ref(row));
1835
+ }
1836
+ }
1837
+ this.selectedRows.set(next);
1838
+ this.selectionChange.emit({ selectedRows: next });
1839
+ }
1840
+ // ---- Column visibility -------------------------------------------------------
1841
+ /** Whether a column is currently hidden by the user. */
1842
+ isColumnHidden(key) {
1843
+ return this._visibility.isHidden(key);
1844
+ }
1845
+ /** Toggle visibility of a hideable column. */
1846
+ toggleColumnVisibility(key) {
1847
+ this._visibility.toggle(key);
1848
+ this._emitPresentationStateChange();
1849
+ }
1850
+ /**
1851
+ * @protected Returns focus to the toolbar "Filters" trigger when the filter
1852
+ * dialog popup closes (Apply / Clear / Escape / backdrop), so keyboard focus
1853
+ * is never stranded on a destroyed overlay control.
1854
+ */
1855
+ _onFiltersClosed() {
1856
+ this._filterTriggerRef()?.nativeElement.focus();
1857
+ }
1858
+ /** Commits a search-field event and resets table pagination. */
1859
+ onSearch(query) {
1860
+ this.searchQuery.set(query);
1861
+ this.currentPage.set(1);
1862
+ }
1863
+ /** Whether a column currently has a committed filter. */
1864
+ isColumnFiltered(key) {
1865
+ return this.activeFilters().some((filter) => filter.key === key);
1866
+ }
1867
+ /** Accessible label for a column filter trigger. */
1868
+ getFilterLabel(col) {
1869
+ return this._resolver.resolve(this._i18n(), this.isColumnFiltered(col.key) ? 'filterColumnActive' : 'filterColumn', { column: col.title ?? col.key });
1870
+ }
1871
+ /**
1872
+ * Merges a scoped editor result against the table's current committed state.
1873
+ * The table remains authoritative here because an overlay may hold an older
1874
+ * input snapshot while another column is committed.
1875
+ */
1876
+ onColumnFiltersChange(key, scopedFilters) {
1877
+ this.activeFilters.update((current) => [
1878
+ ...current.filter((filter) => filter.key !== key),
1879
+ ...scopedFilters
1880
+ .filter((filter) => filter.key === key)
1881
+ .map((filter) => ({
1882
+ ...filter,
1883
+ value: Array.isArray(filter.value) ? [...filter.value] : filter.value,
1884
+ })),
1885
+ ]);
1886
+ }
1887
+ /** Single-column list consumed by the scoped filter editor. */
1888
+ getColumnFilterColumns(col) {
1889
+ const cached = this._columnFilterLists.get(col.key);
1890
+ if (cached?.[0] === col)
1891
+ return cached;
1892
+ const next = [col];
1893
+ this._columnFilterLists.set(col.key, next);
1894
+ return next;
1895
+ }
1896
+ /** Restores focus to the header filter trigger for a popup that just closed. */
1897
+ focusColumnFilterTrigger(key) {
1898
+ const host = this._el.nativeElement;
1899
+ const triggers = host.querySelectorAll('.mlv-data-table__column-filter');
1900
+ for (const trigger of triggers) {
1901
+ if (trigger.dataset['columnKey'] === key) {
1902
+ trigger.focus();
1903
+ return;
1904
+ }
1905
+ }
1906
+ }
1907
+ // ---- Footer template ----------------------------------------------------------
1908
+ /** Retrieves the footer summary template. */
1909
+ getFooterTemplate() {
1910
+ const list = this.footerTemplate();
1911
+ return list.length > 0 ? list[0].templateRef : null;
1912
+ }
1913
+ // ---- Pin/Unpin ---------------------------------------------------------------
1914
+ /**
1915
+ * Returns the list of sides the user may pin a column to, based on `col.pinnable`.
1916
+ * - `true` → `['left', 'right']`
1917
+ * - `'left'` / `'right'` → single-element list
1918
+ * - `MlvPinSide[]` → the list as provided (duplicates preserved by caller)
1919
+ * - falsy → `[]` (not user-pinnable)
1920
+ */
1921
+ getPinnableSides(col) {
1922
+ return this._pinning.getPinnableSides(col);
1923
+ }
1924
+ /** Pin a column to the given side, or unpin if it is already pinned. */
1925
+ togglePin(col, side = 'left') {
1926
+ this._pinning.togglePin(col, side);
1927
+ this._emitPresentationStateChange();
1928
+ }
1929
+ /** Pin a column to a specific side, overriding any current pin state. */
1930
+ pinTo(col, side) {
1931
+ this._pinning.pinTo(col, side);
1932
+ this._emitPresentationStateChange();
1933
+ }
1934
+ /** Explicitly unpin a column, regardless of its current side. */
1935
+ unpin(col) {
1936
+ this._pinning.unpin(col);
1937
+ this._emitPresentationStateChange();
1938
+ }
1939
+ /** Whether a column is currently pinned (accounting for overrides). */
1940
+ isColumnPinned(col) {
1941
+ return this._pinning.isPinned(col);
1942
+ }
1943
+ /** Returns the current pin side for a column (considering overrides), or `null` if it is not pinned. */
1944
+ getColumnPinSide(col) {
1945
+ return this._pinning.getPinSide(col);
1946
+ }
1947
+ isRowExpanded(row) {
1948
+ return this._expanded().has(this._ref(row));
1949
+ }
1950
+ hasChildren(row) {
1951
+ const original = this._ref(row);
1952
+ return (Array.isArray(original['_mlvChildren']) &&
1953
+ original['_mlvChildren'].length > 0);
1954
+ }
1955
+ getDepth(row) {
1956
+ return row['_mlvDepth'] ?? 0;
1957
+ }
1958
+ toggleExpand(row, event) {
1959
+ event.stopPropagation();
1960
+ const original = this._ref(row);
1961
+ const current = this._expanded();
1962
+ const next = new Set(current);
1963
+ if (next.has(original)) {
1964
+ next.delete(original);
1965
+ }
1966
+ else {
1967
+ next.add(original);
1968
+ }
1969
+ this._expanded.set(next);
1970
+ }
1971
+ // ---- Sorting ----------------------------------------------------------------
1972
+ onSortClick(col) {
1973
+ if (!col.sortable)
1974
+ return;
1975
+ const current = this.currentSort();
1976
+ if (!current || current.key !== col.key) {
1977
+ this.currentSort.set({ key: col.key, direction: 'asc' });
1978
+ }
1979
+ else if (current.direction === 'asc') {
1980
+ this.currentSort.set({ key: col.key, direction: 'desc' });
1981
+ }
1982
+ else {
1983
+ this.currentSort.set(null);
1984
+ }
1985
+ this.currentPage.set(1);
1986
+ this._emitPresentationStateChange();
1987
+ }
1988
+ /**
1989
+ * @protected Applies a Sort-menu action, resets pagination, and emits exactly
1990
+ * one presentation snapshot. Programmatic snapshot application remains silent.
1991
+ */
1992
+ _applyMenuSort(column, direction) {
1993
+ if (!column.sortable)
1994
+ return;
1995
+ this.currentSort.set(direction === null ? null : { key: column.key, direction });
1996
+ this.currentPage.set(1);
1997
+ this._emitPresentationStateChange();
1998
+ }
1999
+ getSortDirection(col) {
2000
+ const s = this.currentSort();
2001
+ return s && s.key === col.key ? s.direction : null;
2002
+ }
2003
+ /**
2004
+ * Accessible label for a sortable column header button. Resolves the
2005
+ * `sortByColumn` ICU string ("Sort by {column}") — describing intent rather
2006
+ * than a mouse-specific "click to sort" instruction.
2007
+ */
2008
+ getSortLabel(col) {
2009
+ return this._resolver.resolve(this._i18n(), 'sortByColumn', { column: col.title ?? col.key });
2010
+ }
2011
+ // ---- Column styles ----------------------------------------------------------
2012
+ getColStyle(col) {
2013
+ return columnWidthStyles(col);
2014
+ }
2015
+ /**
2016
+ * Returns the value to apply to a `<col>` element's `width` style.
2017
+ * Used by the shared `<colgroup>` template to keep column widths in sync between the
2018
+ * three split tables in virtual scroll mode (header / body / footer).
2019
+ */
2020
+ getColWidth(col) {
2021
+ if (col._currentWidth !== undefined)
2022
+ return col._currentWidth + 'px';
2023
+ if (col.width)
2024
+ return col.width;
2025
+ return null;
2026
+ }
2027
+ /** Exact frozen width styles for a selection or actions utility column. */
2028
+ getAuxiliaryColumnStyle(kind) {
2029
+ return this._auxiliaryColumnStyles()[kind];
2030
+ }
2031
+ /** Exact frozen `<col>` width for a selection or actions utility column. */
2032
+ getAuxiliaryColumnWidth(kind) {
2033
+ return this._auxiliaryColumnStyles()[kind]?.['width'] ?? null;
2034
+ }
2035
+ /**
2036
+ * trackBy used by `*cdkVirtualFor` in virtual scroll mode. Falls back to the row index
2037
+ * for plain row references and to `_mlvRef` identity for tree rows so expanded children
2038
+ * are reconciled correctly when the user scrolls.
2039
+ */
2040
+ trackByRow = (index, row) => {
2041
+ return row['_mlvRef'] ?? index;
2042
+ };
2043
+ /**
2044
+ * Inline `[style]` object (width / min-width, plus sticky offsets for pinned columns)
2045
+ * for a column's header and body cells. Reads the memoized {@link _columnStyles} map
2046
+ * so the returned reference is stable across change-detection cycles (no per-cell
2047
+ * allocation). Every visible column is present in the map; the on-the-fly fallback is
2048
+ * a defensive path for a column outside the current visible set.
2049
+ */
2050
+ getCellStyle(col) {
2051
+ return (this._columnStyles().get(col.key) ??
2052
+ columnCellStyles(col, this.columnOffsets()));
2053
+ }
2054
+ getAlignClass(col) {
2055
+ return col.align ? `mlv-data-table__cell--align-${col.align}` : '';
2056
+ }
2057
+ // ---- Column resize ----------------------------------------------------------
2058
+ /**
2059
+ * @private In-flight pointer resize state. The originating pointer id prevents
2060
+ * secondary touches or unrelated pointers from moving or ending the drag.
2061
+ */
2062
+ _resizeState = null;
2063
+ /**
2064
+ * @private rAF handle coalescing live-width signal writes to one per frame
2065
+ * during a pointer drag.
2066
+ */
2067
+ _resizeRafId = 0;
2068
+ /**
2069
+ * @private Bound pointer-move handler retained so add/removeEventListener use
2070
+ * the same function reference.
2071
+ */
2072
+ _onResizeMoveBound = (event) => {
2073
+ this._onResizeMove(event);
2074
+ };
2075
+ /**
2076
+ * @private Bound pointer-up handler retained so add/removeEventListener use
2077
+ * the same function reference.
2078
+ */
2079
+ _onResizeEndBound = (event) => {
2080
+ this._onResizeEnd(event);
2081
+ };
2082
+ /**
2083
+ * @private Bound pointer-cancel handler. Cancellation restores the previously
2084
+ * committed width and never emits a commit event.
2085
+ */
2086
+ _onResizeCancelBound = (event) => {
2087
+ this._onResizeCancel(event);
2088
+ };
2089
+ /**
2090
+ * @private Cancels an active drag if the browser unexpectedly revokes the
2091
+ * initiating handle's pointer capture.
2092
+ */
2093
+ _onResizeLostCaptureBound = (event) => {
2094
+ this._onResizeLostCapture(event);
2095
+ };
2096
+ /**
2097
+ * Starts a column resize with Pointer Events and captures the initiating
2098
+ * pointer on the separator. The rendered header width is measured instead of
2099
+ * trusting the declared CSS width, so `rem`, `%`, and flex/table layout widths
2100
+ * begin without a jump.
2101
+ */
2102
+ onResizeStart(col, event) {
2103
+ if (event.button !== 0 || this._resizeState)
2104
+ return;
2105
+ const target = event.currentTarget;
2106
+ if (!(target instanceof HTMLElement))
2107
+ return;
2108
+ event.preventDefault();
2109
+ this._measureHeaderWidths();
2110
+ const bounds = this._resolveColumnResizeBounds(col, target);
2111
+ this._cacheColumnResizeBounds(col.key, bounds);
2112
+ const startWidth = this._clampColumnWidth(this._measureHeaderWidth(col, target), bounds);
2113
+ this._resizeState = {
2114
+ key: col.key,
2115
+ pointerId: event.pointerId,
2116
+ target,
2117
+ startX: event.clientX,
2118
+ startWidth,
2119
+ latestWidth: startWidth,
2120
+ moved: false,
2121
+ ...bounds,
2122
+ };
2123
+ this._ngZone.runOutsideAngular(() => {
2124
+ this._document.addEventListener('pointermove', this._onResizeMoveBound);
2125
+ this._document.addEventListener('pointerup', this._onResizeEndBound);
2126
+ this._document.addEventListener('pointercancel', this._onResizeCancelBound);
2127
+ target.addEventListener('lostpointercapture', this._onResizeLostCaptureBound);
2128
+ if (typeof target.setPointerCapture === 'function') {
2129
+ try {
2130
+ target.setPointerCapture(event.pointerId);
2131
+ }
2132
+ catch {
2133
+ // Document listeners preserve drag/end behavior when capture is
2134
+ // unavailable, rejected, or exercised by a synthetic event.
2135
+ }
2136
+ }
2137
+ });
2138
+ }
2139
+ /**
2140
+ * Handles keyboard resizing for the focusable separator. ArrowLeft/ArrowRight
2141
+ * use an 8px step (32px with Shift); Home/End jump to the resolved bounds.
2142
+ */
2143
+ onColumnResizeKeydown(col, event) {
2144
+ if (event.key === 'Enter') {
2145
+ event.preventDefault();
2146
+ this.resetColumnWidth(col.key);
2147
+ return;
2148
+ }
2149
+ const key = this._rtlService.normalizeArrowKey(event);
2150
+ const supported = key === LEFT_ARROW ||
2151
+ key === RIGHT_ARROW ||
2152
+ event.key === 'Home' ||
2153
+ event.key === 'End';
2154
+ if (!supported)
2155
+ return;
2156
+ const target = event.currentTarget instanceof HTMLElement
2157
+ ? event.currentTarget
2158
+ : undefined;
2159
+ this._measureHeaderWidths();
2160
+ const bounds = this._resolveColumnResizeBounds(col, target);
2161
+ this._cacheColumnResizeBounds(col.key, bounds);
2162
+ const currentWidth = this._clampColumnWidth(this._measureHeaderWidth(col, target), bounds);
2163
+ const step = event.shiftKey
2164
+ ? COLUMN_RESIZE_KEYBOARD_LARGE_STEP
2165
+ : COLUMN_RESIZE_KEYBOARD_STEP;
2166
+ let nextWidth = currentWidth;
2167
+ if (event.key === 'Home')
2168
+ nextWidth = bounds.min;
2169
+ if (event.key === 'End')
2170
+ nextWidth = bounds.max;
2171
+ if (key === LEFT_ARROW)
2172
+ nextWidth = currentWidth - step;
2173
+ if (key === RIGHT_ARROW)
2174
+ nextWidth = currentWidth + step;
2175
+ event.preventDefault();
2176
+ this._commitColumnWidth(col.key, this._clampColumnWidth(nextWidth, bounds), 'keyboard');
2177
+ }
2178
+ /** Localized accessible name for a column's resize separator. */
2179
+ getColumnResizeLabel(col) {
2180
+ return this._resolver.resolve(this._i18n(), 'resizeColumn', { column: col.title ?? col.key });
2181
+ }
2182
+ /** Current separator value in CSS pixels for ARIA. */
2183
+ getColumnResizeValue(col) {
2184
+ const bounds = this._columnResizeBounds(col);
2185
+ const active = this._resizeState?.key === col.key
2186
+ ? this._resizeState.latestWidth
2187
+ : undefined;
2188
+ const measured = this._measuredColumnWidths().get(col.key);
2189
+ return this._normalizeColumnWidth(active ??
2190
+ col._currentWidth ??
2191
+ measured ??
2192
+ parsePixelWidth(col.width) ??
2193
+ DEFAULT_COLUMN_WIDTH, bounds);
2194
+ }
2195
+ /** Minimum separator value in CSS pixels for ARIA and Home. */
2196
+ getColumnResizeMin(col) {
2197
+ return this._roundColumnWidth(this._columnResizeBounds(col).min);
2198
+ }
2199
+ /** Maximum separator value in CSS pixels for ARIA and End. */
2200
+ getColumnResizeMax(col) {
2201
+ return this._roundColumnWidth(this._columnResizeBounds(col).max);
2202
+ }
2203
+ /** Localized text alternative that makes the separator's pixel unit explicit. */
2204
+ getColumnResizeValueText(col) {
2205
+ return this._resolver.resolve(this._i18n(), 'columnWidthPixels', { width: this.getColumnResizeValue(col) });
2206
+ }
2207
+ /**
2208
+ * Removes committed user widths. Passing a key resets that column and emits a
2209
+ * reset even when no override exists (useful for clearing persisted state);
2210
+ * omitting it resets every currently overridden column.
2211
+ */
2212
+ resetColumnWidth(key) {
2213
+ const active = this._resizeState;
2214
+ if (active && (key === undefined || active.key === key)) {
2215
+ this._cleanupResize();
2216
+ this._liveResize.set(null);
2217
+ }
2218
+ const widths = this._columnWidths();
2219
+ if (key !== undefined) {
2220
+ if (!this.columns().some((column) => column.key === key))
2221
+ return;
2222
+ if (widths.has(key)) {
2223
+ const updated = new Map(widths);
2224
+ updated.delete(key);
2225
+ this._columnWidths.set(updated);
2226
+ }
2227
+ this.columnResize.emit({ key, width: null, source: 'reset' });
2228
+ this._emitPresentationStateChange();
2229
+ afterNextRender(() => this._measureHeaderWidths(), {
2230
+ injector: this._injector,
2231
+ });
2232
+ return;
2233
+ }
2234
+ const resetKeys = [...widths.keys()];
2235
+ if (!resetKeys.length)
2236
+ return;
2237
+ this._columnWidths.set(new Map());
2238
+ for (const resetKey of resetKeys) {
2239
+ this.columnResize.emit({
2240
+ key: resetKey,
2241
+ width: null,
2242
+ source: 'reset',
2243
+ });
2244
+ }
2245
+ this._emitPresentationStateChange();
2246
+ afterNextRender(() => this._measureHeaderWidths(), {
2247
+ injector: this._injector,
2248
+ });
2249
+ }
2250
+ /**
2251
+ * @private Pointer-move handler (outside Angular). It synchronously updates
2252
+ * the latest bounded value, then publishes at most one live signal update per
2253
+ * animation frame.
2254
+ */
2255
+ _onResizeMove(event) {
2256
+ const state = this._resizeState;
2257
+ if (!state || event.pointerId !== state.pointerId)
2258
+ return;
2259
+ const delta = event.clientX - state.startX;
2260
+ if (delta !== 0)
2261
+ state.moved = true;
2262
+ state.latestWidth = this._clampColumnWidth(state.startWidth + delta, state);
2263
+ if (!state.moved)
2264
+ return;
2265
+ if (this._resizeRafId)
2266
+ return;
2267
+ this._resizeRafId = requestAnimationFrame(() => {
2268
+ this._resizeRafId = 0;
2269
+ const s = this._resizeState;
2270
+ if (!s || s.pointerId !== event.pointerId)
2271
+ return;
2272
+ this._ngZone.run(() => this._liveResize.set({ key: s.key, width: s.latestWidth }));
2273
+ });
2274
+ }
2275
+ /**
2276
+ * @private Pointer-up handler that commits exactly once for the initiating
2277
+ * pointer. A press/release without movement remains a no-op, which keeps a
2278
+ * double-click reset from producing intermediate resize commits.
2279
+ */
2280
+ _onResizeEnd(event) {
2281
+ const state = this._resizeState;
2282
+ if (!state || event.pointerId !== state.pointerId)
2283
+ return;
2284
+ this._cleanupResize();
2285
+ if (!state.moved) {
2286
+ this._ngZone.run(() => this._liveResize.set(null));
2287
+ return;
2288
+ }
2289
+ this._commitColumnWidth(state.key, state.latestWidth, 'pointer');
2290
+ }
2291
+ /**
2292
+ * @private Cancels only the matching active pointer, dropping the optimistic
2293
+ * live width while preserving the last committed map entry.
2294
+ */
2295
+ _onResizeCancel(event) {
2296
+ const state = this._resizeState;
2297
+ if (!state || event.pointerId !== state.pointerId)
2298
+ return;
2299
+ this._cleanupResize();
2300
+ this._ngZone.run(() => this._liveResize.set(null));
2301
+ }
2302
+ /**
2303
+ * @private Treats unexpected capture loss as cancellation. Normal cleanup
2304
+ * removes this listener before explicitly releasing capture, so pointer-up
2305
+ * commits cannot be mistaken for cancellation.
2306
+ */
2307
+ _onResizeLostCapture(event) {
2308
+ const state = this._resizeState;
2309
+ if (!state || event.pointerId !== state.pointerId)
2310
+ return;
2311
+ this._cleanupResize();
2312
+ this._ngZone.run(() => this._liveResize.set(null));
2313
+ }
2314
+ /**
2315
+ * @private Commits a bounded pixel width with one map clone and emits the
2316
+ * public persistence event in the same Angular-zone turn.
2317
+ */
2318
+ _commitColumnWidth(key, width, source) {
2319
+ const col = this.columns().find((column) => column.key === key);
2320
+ const bounds = col
2321
+ ? this._columnResizeBounds(col)
2322
+ : {
2323
+ min: DEFAULT_COLUMN_MIN_WIDTH,
2324
+ max: DEFAULT_COLUMN_MAX_WIDTH,
2325
+ };
2326
+ const committedWidth = this._normalizeColumnWidth(width, bounds);
2327
+ this._ngZone.run(() => {
2328
+ const updated = new Map(this._columnWidths());
2329
+ updated.set(key, committedWidth);
2330
+ this._columnWidths.set(updated);
2331
+ this._liveResize.set(null);
2332
+ this.columnResize.emit({ key, width: committedWidth, source });
2333
+ this._emitPresentationStateChange();
2334
+ });
2335
+ }
2336
+ /**
2337
+ * @private Returns the latest DOM-resolved bounds when available, otherwise
2338
+ * resolves strict pixel metadata with safe finite defaults.
2339
+ */
2340
+ _columnResizeBounds(col) {
2341
+ return (this._resolvedResizeBounds().get(col.key) ??
2342
+ this._resolveColumnResizeBounds(col));
2343
+ }
2344
+ /** @private Stores DOM-resolved bounds with a signal-safe map replacement. */
2345
+ _cacheColumnResizeBounds(key, bounds) {
2346
+ this._resolvedResizeBounds.update((current) => {
2347
+ const updated = new Map(current);
2348
+ updated.set(key, bounds);
2349
+ return updated;
2350
+ });
2351
+ }
2352
+ /**
2353
+ * @private Resolves resize bounds. Non-pixel metadata is read back from the
2354
+ * rendered header's computed style where the browser exposes a pixel value.
2355
+ */
2356
+ _resolveColumnResizeBounds(col, target) {
2357
+ const headerCell = target?.closest('th');
2358
+ let min = this._resolveColumnBound(col.minWidth, headerCell);
2359
+ let max = this._resolveColumnBound(col.maxWidth, headerCell);
2360
+ if (headerCell &&
2361
+ ((col.minWidth && min === undefined) ||
2362
+ (col.maxWidth && max === undefined))) {
2363
+ const computedStyle = headerCell.ownerDocument.defaultView?.getComputedStyle(headerCell);
2364
+ if (computedStyle && col.minWidth && min === undefined) {
2365
+ min = parsePixelWidth(computedStyle.minWidth);
2366
+ }
2367
+ if (computedStyle && col.maxWidth && max === undefined) {
2368
+ max = parsePixelWidth(computedStyle.maxWidth);
2369
+ }
2370
+ }
2371
+ const resolvedMin = this._roundColumnWidth(min ?? DEFAULT_COLUMN_MIN_WIDTH);
2372
+ const resolvedMax = this._roundColumnWidth(Math.max(resolvedMin, max ?? DEFAULT_COLUMN_MAX_WIDTH));
2373
+ return { min: resolvedMin, max: resolvedMax };
2374
+ }
2375
+ /**
2376
+ * @private Resolves a declared bound to CSS pixels. Complete pixel values are
2377
+ * direct; complete percentages use the rendered header table width, matching
2378
+ * the containing table against which cell percentages are laid out.
2379
+ */
2380
+ _resolveColumnBound(value, headerCell) {
2381
+ const pixels = parsePixelWidth(value);
2382
+ if (pixels !== undefined)
2383
+ return pixels;
2384
+ const percentage = this._parseCssPercentage(value);
2385
+ if (percentage === undefined || !headerCell)
2386
+ return undefined;
2387
+ const table = headerCell.closest('table');
2388
+ const tableRectWidth = table?.getBoundingClientRect().width ?? 0;
2389
+ const referenceWidth = tableRectWidth > 0 ? tableRectWidth : (table?.clientWidth ?? 0);
2390
+ if (!Number.isFinite(referenceWidth) || referenceWidth <= 0) {
2391
+ return undefined;
2392
+ }
2393
+ return this._roundColumnWidth(referenceWidth * percentage);
2394
+ }
2395
+ /** @private Parses a complete, non-negative CSS percentage as a fraction. */
2396
+ _parseCssPercentage(value) {
2397
+ if (!value)
2398
+ return undefined;
2399
+ const match = value.trim().match(/^(?:\d+(?:\.\d+)?|\.\d+)%$/);
2400
+ if (!match)
2401
+ return undefined;
2402
+ const parsed = Number.parseFloat(match[0]);
2403
+ return Number.isFinite(parsed) ? parsed / 100 : undefined;
2404
+ }
2405
+ /**
2406
+ * @private Re-applies outer horizontal position after virtual DOM/geometry
2407
+ * changes that do not themselves emit another wrapper scroll event.
2408
+ */
2409
+ _syncVirtualHorizontalScroll() {
2410
+ const wrapper = this.tableWrapperRef()?.nativeElement;
2411
+ const viewport = this._virtualViewportRef()?.elementRef.nativeElement;
2412
+ if (!wrapper || !viewport)
2413
+ return;
2414
+ if (viewport.scrollLeft !== wrapper.scrollLeft) {
2415
+ viewport.scrollLeft = wrapper.scrollLeft;
2416
+ }
2417
+ this._updateVirtualScrollGeometry(wrapper, viewport);
2418
+ }
2419
+ /**
2420
+ * @private Publishes both the native vertical-scrollbar width and an inert
2421
+ * outer extent whose maximum scroll position exactly matches the viewport.
2422
+ */
2423
+ _updateVirtualScrollGeometry(wrapper, viewport) {
2424
+ const gutter = Math.max(0, viewport.offsetWidth - viewport.clientWidth);
2425
+ const horizontalRange = Math.max(0, viewport.scrollWidth - viewport.clientWidth);
2426
+ const extent = wrapper.clientWidth + horizontalRange;
2427
+ const gutterChanged = gutter !== untracked(this._virtualScrollbarGutter);
2428
+ const extentChanged = extent !== untracked(this._virtualHorizontalScrollExtent);
2429
+ if (!gutterChanged && !extentChanged)
2430
+ return;
2431
+ this._ngZone.run(() => {
2432
+ if (gutterChanged)
2433
+ this._virtualScrollbarGutter.set(gutter);
2434
+ if (extentChanged)
2435
+ this._virtualHorizontalScrollExtent.set(extent);
2436
+ });
2437
+ }
2438
+ /**
2439
+ * @private Measures the actual rendered header cell width and falls back to
2440
+ * the current strict-pixel state only in non-layout environments such as
2441
+ * server rendering and jsdom.
2442
+ */
2443
+ _measureHeaderWidth(col, target) {
2444
+ const headerCell = target?.closest('th');
2445
+ const rectWidth = headerCell?.getBoundingClientRect().width ?? 0;
2446
+ if (Number.isFinite(rectWidth) && rectWidth > 0)
2447
+ return rectWidth;
2448
+ const offsetWidth = headerCell?.offsetWidth ?? 0;
2449
+ if (offsetWidth > 0)
2450
+ return offsetWidth;
2451
+ return (col._currentWidth ?? parsePixelWidth(col.width) ?? DEFAULT_COLUMN_WIDTH);
2452
+ }
2453
+ /**
2454
+ * @private Measures the rendered header once per layout change. Before the
2455
+ * first user override these values track responsive/table layout; while the
2456
+ * table is frozen, existing baselines are preserved so reset restores the
2457
+ * original widths rather than another column's resized layout.
2458
+ */
2459
+ _measureHeaderWidths() {
2460
+ const host = this._el.nativeElement;
2461
+ const header = host.querySelector('thead');
2462
+ if (!header)
2463
+ return;
2464
+ const preserveBaseline = this._liveResize() !== null || this._columnWidths().size > 0;
2465
+ const measured = preserveBaseline
2466
+ ? new Map(this._measuredColumnWidths())
2467
+ : new Map();
2468
+ const resolvedBounds = preserveBaseline
2469
+ ? new Map(this._resolvedResizeBounds())
2470
+ : new Map();
2471
+ for (const cell of header.querySelectorAll('th[data-mlv-column-key]')) {
2472
+ const key = cell.getAttribute('data-mlv-column-key');
2473
+ if (!key)
2474
+ continue;
2475
+ const width = cell.getBoundingClientRect().width;
2476
+ if ((!preserveBaseline || !measured.has(key)) &&
2477
+ Number.isFinite(width) &&
2478
+ width > 0) {
2479
+ measured.set(key, this._roundColumnWidth(width));
2480
+ }
2481
+ const column = this.columns().find((candidate) => candidate.key === key);
2482
+ if (column?.resizable) {
2483
+ resolvedBounds.set(key, this._resolveColumnResizeBounds(column, cell));
2484
+ }
2485
+ }
2486
+ const selectionWidth = header
2487
+ .querySelector('.mlv-data-table__cell--select')
2488
+ ?.getBoundingClientRect().width;
2489
+ const actionsWidth = header
2490
+ .querySelector('.mlv-data-table__cell--actions')
2491
+ ?.getBoundingClientRect().width;
2492
+ const auxiliary = preserveBaseline
2493
+ ? { ...this._measuredAuxiliaryWidths() }
2494
+ : {};
2495
+ if (selectionWidth !== undefined &&
2496
+ Number.isFinite(selectionWidth) &&
2497
+ selectionWidth > 0) {
2498
+ auxiliary.selection = this._roundColumnWidth(selectionWidth);
2499
+ }
2500
+ if (actionsWidth !== undefined &&
2501
+ Number.isFinite(actionsWidth) &&
2502
+ actionsWidth > 0) {
2503
+ auxiliary.actions = this._roundColumnWidth(actionsWidth);
2504
+ }
2505
+ this._measuredColumnWidths.set(measured);
2506
+ this._resolvedResizeBounds.set(resolvedBounds);
2507
+ this._measuredAuxiliaryWidths.set(auxiliary);
2508
+ }
2509
+ /**
2510
+ * @private CSS length used by a sticky offset. A rendered measurement is more
2511
+ * accurate than declared CSS under table redistribution; the declaration
2512
+ * remains the pre-render/SSR fallback.
2513
+ */
2514
+ _columnOffsetWidth(col) {
2515
+ if (col._currentWidth !== undefined)
2516
+ return `${col._currentWidth}px`;
2517
+ const measured = this._measuredColumnWidths().get(col.key);
2518
+ if (measured !== undefined)
2519
+ return `${this._roundColumnWidth(measured)}px`;
2520
+ if (col.width)
2521
+ return col.width;
2522
+ return `${DEFAULT_COLUMN_WIDTH}px`;
2523
+ }
2524
+ /** @private Adds heterogeneous CSS lengths without converting their units. */
2525
+ _sumCssLengths(widths) {
2526
+ if (!widths.length)
2527
+ return '0px';
2528
+ if (widths.length === 1)
2529
+ return widths[0];
2530
+ return `calc(${widths.join(' + ')})`;
2531
+ }
2532
+ /** @private Rounds pixel values to hundredths without changing their bounds. */
2533
+ _roundColumnWidth(width) {
2534
+ return Math.round(width * 100) / 100;
2535
+ }
2536
+ /** @private Creates immutable exact width/min/max styles for a measured column. */
2537
+ _fixedColumnWidthStyles(width) {
2538
+ if (width === undefined || !Number.isFinite(width) || width < 0)
2539
+ return null;
2540
+ const value = `${this._roundColumnWidth(width)}px`;
2541
+ return {
2542
+ width: value,
2543
+ 'min-width': value,
2544
+ 'max-width': value,
2545
+ };
2546
+ }
2547
+ /** @private Rounds and clamps a width against normalized finite bounds. */
2548
+ _normalizeColumnWidth(width, bounds) {
2549
+ return this._clampColumnWidth(this._roundColumnWidth(width), bounds);
2550
+ }
2551
+ /** @private Returns a positive whole-number page size or the all-items sentinel. */
2552
+ _normalizePerPage(perPage) {
2553
+ if (perPage === Infinity)
2554
+ return Infinity;
2555
+ return Number.isFinite(perPage) ? Math.max(1, Math.floor(perPage)) : 1;
2556
+ }
2557
+ /** @private Keeps only declared keys while preserving input-order uniqueness. */
2558
+ _knownPresentationKeys(keys, knownKeys) {
2559
+ return new Set(keys.filter((key) => knownKeys.has(key)));
2560
+ }
2561
+ /** @private Clones only a known sortable sort state. */
2562
+ _normalizePresentationSort(sort, columns) {
2563
+ if (!sort ||
2564
+ (sort.direction !== 'asc' && sort.direction !== 'desc') ||
2565
+ !columns.some((column) => column.key === sort.key && column.sortable)) {
2566
+ return null;
2567
+ }
2568
+ return { key: sort.key, direction: sort.direction };
2569
+ }
2570
+ /** @private Emits one fresh normalized snapshot after a durable user gesture. */
2571
+ _emitPresentationStateChange() {
2572
+ this.presentationStateChange.emit(this.getPresentationState());
2573
+ }
2574
+ /** @private Clamps a width to finite normalized resize bounds. */
2575
+ _clampColumnWidth(width, bounds) {
2576
+ const finiteWidth = Number.isFinite(width) ? width : DEFAULT_COLUMN_WIDTH;
2577
+ return Math.min(bounds.max, Math.max(bounds.min, finiteWidth));
2578
+ }
2579
+ /**
2580
+ * @private Detaches active pointer listeners, releases capture, cancels a
2581
+ * pending animation frame, and clears the drag state. Idempotent for pointer
2582
+ * up, pointer cancel, reset, and component destruction.
2583
+ */
2584
+ _cleanupResize() {
2585
+ const state = this._resizeState;
2586
+ if (state) {
2587
+ this._document.removeEventListener('pointermove', this._onResizeMoveBound);
2588
+ this._document.removeEventListener('pointerup', this._onResizeEndBound);
2589
+ this._document.removeEventListener('pointercancel', this._onResizeCancelBound);
2590
+ state.target.removeEventListener('lostpointercapture', this._onResizeLostCaptureBound);
2591
+ const canRelease = typeof state.target.hasPointerCapture !== 'function' ||
2592
+ state.target.hasPointerCapture(state.pointerId);
2593
+ if (canRelease &&
2594
+ typeof state.target.releasePointerCapture === 'function') {
2595
+ try {
2596
+ state.target.releasePointerCapture(state.pointerId);
2597
+ }
2598
+ catch {
2599
+ // Capture may already have been released implicitly by the browser.
2600
+ }
2601
+ }
2602
+ }
2603
+ if (this._resizeRafId) {
2604
+ cancelAnimationFrame(this._resizeRafId);
2605
+ this._resizeRafId = 0;
2606
+ }
2607
+ this._resizeState = null;
2608
+ }
2609
+ // ---- Private helpers --------------------------------------------------------
2610
+ /** Returns the original (pre-spread) row reference for expand tracking. */
2611
+ _ref(row) {
2612
+ return originalRow(row);
2613
+ }
2614
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
2615
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MlvDataTable, isStandalone: true, selector: "mlv-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, columnGroups: { classPropertyName: "columnGroups", publicName: "columnGroups", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, editMode: { classPropertyName: "editMode", publicName: "editMode", isSignal: true, isRequired: false, transformFunction: null }, addRow: { classPropertyName: "addRow", publicName: "addRow", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, actionsHeaderLabel: { classPropertyName: "actionsHeaderLabel", publicName: "actionsHeaderLabel", isSignal: true, isRequired: false, transformFunction: null }, cellNavigation: { classPropertyName: "cellNavigation", publicName: "cellNavigation", isSignal: true, isRequired: false, transformFunction: null }, paginationMode: { classPropertyName: "paginationMode", publicName: "paginationMode", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null }, infiniteScrollThreshold: { classPropertyName: "infiniteScrollThreshold", publicName: "infiniteScrollThreshold", isSignal: true, isRequired: false, transformFunction: null }, filterDisplay: { classPropertyName: "filterDisplay", publicName: "filterDisplay", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, showSortMenu: { classPropertyName: "showSortMenu", publicName: "showSortMenu", isSignal: true, isRequired: false, transformFunction: null }, searchTrigger: { classPropertyName: "searchTrigger", publicName: "searchTrigger", isSignal: true, isRequired: false, transformFunction: null }, searchDebounce: { classPropertyName: "searchDebounce", publicName: "searchDebounce", isSignal: true, isRequired: false, transformFunction: null }, selectedRows: { classPropertyName: "selectedRows", publicName: "selectedRows", isSignal: true, isRequired: false, transformFunction: null }, searchQuery: { classPropertyName: "searchQuery", publicName: "searchQuery", isSignal: true, isRequired: false, transformFunction: null }, activeFilters: { classPropertyName: "activeFilters", publicName: "activeFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowEditStart: "rowEditStart", rowEditSave: "rowEditSave", rowEditCancel: "rowEditCancel", rowAdd: "rowAdd", rowClick: "rowClick", selectionChange: "selectionChange", retry: "retry", columnResize: "columnResize", presentationStateChange: "presentationStateChange", loadMore: "loadMore", selectedRows: "selectedRowsChange", searchQuery: "searchQueryChange", activeFilters: "activeFiltersChange" }, host: { classAttribute: "mlv-data-table" }, providers: [
2616
+ { provide: MLV_DENSITY_ELEMENT, useValue: 'data-table' },
2617
+ MlvDataTableEditingService,
2618
+ MlvDataTableColumnVisibilityService,
2619
+ MlvDataTablePinningService,
2620
+ ], queries: [{ propertyName: "cellTemplates", predicate: MlvDataTableCell, descendants: true, isSignal: true }, { propertyName: "editCellTemplates", predicate: MlvDataTableEditCell, descendants: true, isSignal: true }, { propertyName: "noDataTemplate", predicate: MlvDataTableNoData, descendants: true, isSignal: true }, { propertyName: "errorTemplate", predicate: MlvDataTableError, descendants: true, isSignal: true }, { propertyName: "footerTemplate", predicate: MlvDataTableFooter, descendants: true, isSignal: true }, { propertyName: "_toolbarActions", first: true, predicate: MlvDataTableToolbarActions, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "tableWrapperRef", first: true, predicate: ["tableWrapper"], descendants: true, isSignal: true }, { propertyName: "tableRef", first: true, predicate: ["tableEl"], descendants: true, isSignal: true }, { propertyName: "_resizeHandleRefs", predicate: ["resizeHandle"], descendants: true, isSignal: true }, { propertyName: "_filterTriggerRef", first: true, predicate: ["filterBtn"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_virtualViewportRef", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.MlvDensityDirective, inputs: ["mlvDensity", "mlvDensity"] }], ngImport: i0, template: "@if (hasToolbarContent()) {\n<div class=\"mlv-data-table__toolbar\">\n @if (showSearch() && hasSearchableColumns()) {\n <mlv-search-field\n class=\"mlv-data-table__search\"\n [value]=\"_searchDraft()\"\n (valueChange)=\"_searchDraft.set($event)\"\n [trigger]=\"searchTrigger()\"\n [debounce]=\"searchDebounce()\"\n [loading]=\"loading()\"\n [placeholder]=\"_i18n().searchPlaceholder\"\n [ariaLabel]=\"_i18n().searchLabel\"\n (search)=\"onSearch($event)\"\n />\n } @if (filterDisplay() !== 'none' && hasFilters()) {\n <span class=\"mlv-data-table__filter-badge\" aria-live=\"polite\">\n {{ activeFilterLabel() }}\n </span>\n }\n <div class=\"mlv-data-table__toolbar-actions\">\n @if (editable() && addRow()) {\n <button\n mlvButton\n variant=\"secondary\"\n mlvDensity=\"compact\"\n type=\"button\"\n (click)=\"onAddRow()\"\n [attr.aria-label]=\"_i18n().addNewRow\"\n >\n <svg lucidePlus mlvButtonIcon [size]=\"14\" />\n {{ _i18n().addRow }}\n </button>\n } @if (showSortMenu() && hasSortableColumns()) {\n <button\n mlvButton\n variant=\"secondary\"\n mlvDensity=\"compact\"\n type=\"button\"\n data-mlv-table-sort-trigger\n [mlvMenuTrigger]=\"sortMenu\"\n [attr.aria-label]=\"_i18n().sortMenu\"\n >\n <svg mlvButtonIcon lucideArrowUpDown [size]=\"14\" />\n {{ _i18n().sort }}\n </button>\n <mlv-menu #sortMenu [label]=\"_i18n().sortMenu\" mlvDensity=\"compact\">\n @for (column of columns(); track column.key) { @if (column.sortable) { @if\n (currentSort()?.key === column.key) {\n <mlv-list-item\n mlvMenuItem\n [mlvMenuTrigger]=\"directionMenu\"\n [isSubmenuTrigger]=\"true\"\n >\n {{ column.title ?? column.key }}\n </mlv-list-item>\n <mlv-menu\n #directionMenu\n [label]=\"getSortLabel(column)\"\n mlvDensity=\"compact\"\n >\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, 'asc')\">\n {{ _i18n().ascending }}\n </mlv-list-item>\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, 'desc')\">\n {{ _i18n().descending }}\n </mlv-list-item>\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, null)\">\n {{ _i18n().clearSort }}\n </mlv-list-item>\n </mlv-menu>\n } @else {\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, 'asc')\">\n {{ column.title ?? column.key }}\n </mlv-list-item>\n } } }\n </mlv-menu>\n } @if (hasHideableColumns()) {\n <button\n mlvButton\n [variant]=\"columnsPopup.opened() ? 'primary' : 'secondary'\"\n mlvDensity=\"compact\"\n type=\"button\"\n [mlvPopupTrigger]=\"columnsPopup\"\n #columnsTrigger=\"mlvPopupTrigger\"\n [attr.aria-label]=\"_i18n().toggleColumnVisibility\"\n >\n <svg mlvButtonIcon lucideEye [size]=\"14\" />\n {{ _i18n().columns }}\n </button>\n\n <mlv-popup #columnsPopup>\n <div *mlvPopupContent class=\"mlv-data-table__columns-dropdown\">\n @for (col of allColumns(); track col.key) { @if (col.hideable) {\n <div class=\"mlv-data-table__columns-item\">\n <mlv-checkbox\n [checked]=\"!isColumnHidden(col.key)\"\n [ariaLabel]=\"col.title ?? col.key\"\n (checkedChange)=\"toggleColumnVisibility(col.key)\"\n />\n <span>{{ col.title ?? col.key }}</span>\n </div>\n } }\n </div>\n </mlv-popup>\n } @if (filterDisplay() === 'toolbar' && hasFilterableColumns()) {\n <button\n #filterBtn\n mlvButton\n [variant]=\"filtersPopup.opened() ? 'primary' : 'secondary'\"\n mlvDensity=\"compact\"\n type=\"button\"\n [mlvPopupTrigger]=\"filtersPopup\"\n #trigger=\"mlvPopupTrigger\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"_i18n().toggleFilters\"\n >\n <svg lucideFilter mlvButtonIcon [size]=\"14\" />\n {{ _i18n().filters }} @if (hasFilters()) {\n <mlv-badge tone=\"primary\" rounded>{{ activeFilters().length }}</mlv-badge>\n }\n </button>\n\n <mlv-popup\n #filtersPopup\n panelRole=\"dialog\"\n [ariaLabel]=\"_i18n().filters\"\n (afterClosed)=\"_onFiltersClosed()\"\n >\n <mlv-dt-filter-dropdown\n *mlvPopupContent\n [columns]=\"columns()\"\n [(activeFilters)]=\"activeFilters\"\n (closed)=\"trigger.close()\"\n />\n </mlv-popup>\n } @if (_toolbarActions(); as actions) {\n <ng-container [ngTemplateOutlet]=\"actions.templateRef\" />\n }\n </div>\n</div>\n}\n\n<div\n class=\"mlv-data-table__wrapper\"\n [class.mlv-data-table__wrapper--virtual]=\"virtualScroll()\"\n [style.max-height]=\"virtualScroll() ? null : maxHeight()\"\n [style.--mlv-dt-virtual-scrollbar-gutter]=\"\n virtualScroll() ? _virtualScrollbarGutter() + 'px' : null\n \"\n #tableWrapper\n mlvInfiniteScroll\n [disabled]=\"paginationMode() !== 'infinite' || virtualScroll()\"\n [threshold]=\"infiniteScrollThreshold()\"\n [loading]=\"!!loading()\"\n [hasMore]=\"!!hasMore()\"\n (loadMore)=\"onInfiniteScrollLoadMore($event)\"\n>\n @if (virtualScroll()) {\n <!-- ==================== Virtual scroll mode ==================== -->\n <!-- Header table \u2014 sits naturally at the top of the wrapper, outside the viewport -->\n <table\n class=\"mlv-data-table__table mlv-data-table__table--virtual mlv-data-table__table--virtual-header\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.flex]=\"resizedTableWidth() === null ? null : '0 0 auto'\"\n role=\"grid\"\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <thead class=\"mlv-data-table__head\">\n <ng-container [ngTemplateOutlet]=\"headRowsTpl\" />\n </thead>\n </table>\n\n <!-- CDK virtual scroll viewport \u2014 owns the only vertical scroll surface in this mode.\n Infinite scroll is intentionally disabled in virtual mode: virtual scrolling is the\n rendering optimisation for already-loaded data, and the two strategies are mutually\n exclusive in this component. -->\n <cdk-virtual-scroll-viewport\n class=\"mlv-data-table__virtual-viewport\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"virtualViewportHeight()\"\n >\n <table\n class=\"mlv-data-table__table mlv-data-table__table--virtual mlv-data-table__table--virtual-body\"\n [class.mlv-data-table__table--striped]=\"striped()\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n role=\"presentation\"\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <tbody class=\"mlv-data-table__body\">\n @if (showError()) {\n <ng-container [ngTemplateOutlet]=\"errorRowTpl\" />\n } @else if (flatRows().length === 0) {\n <ng-container [ngTemplateOutlet]=\"noDataRowTpl\" />\n } @else {\n <tr\n *cdkVirtualFor=\"\n let row of flatRows();\n let i = index;\n trackBy: trackByRow\n \"\n class=\"mlv-data-table__row mlv-data-table__row--data\"\n [class.mlv-data-table__row--expanded]=\"isRowExpanded(row)\"\n [class.mlv-data-table__row--editing]=\"isEditing(i)\"\n [class.mlv-data-table__row--selected]=\"isRowSelected(row)\"\n [style.height.px]=\"rowHeight()\"\n [attr.aria-level]=\"getDepth(row) > 0 ? getDepth(row) + 1 : null\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row) : null\"\n [attr.tabindex]=\"_rowTabIndex(i)\"\n [attr.data-row-index]=\"i\"\n (click)=\"onRowClick(row, i, $event)\"\n (focus)=\"_onRowFocus(i)\"\n (keydown)=\"_onRowKeydown(i, row, $event)\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowCellsTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n </tr>\n }\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n <!-- Footer summary table \u2014 only when a footer template is projected -->\n @if (getFooterTemplate(); as footerTpl) {\n <table\n class=\"mlv-data-table__table mlv-data-table__table--virtual mlv-data-table__table--virtual-footer\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.flex]=\"resizedTableWidth() === null ? null : '0 0 auto'\"\n role=\"presentation\"\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <tfoot class=\"mlv-data-table__foot\">\n <tr class=\"mlv-data-table__row mlv-data-table__row--footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: visibleColumns() }\"\n />\n </tr>\n </tfoot>\n </table>\n }\n\n <!-- Extends only the outer horizontal scroll range to match the viewport's\n native range, including a classic vertical scrollbar gutter. -->\n <div\n class=\"mlv-data-table__virtual-horizontal-sizer\"\n [style.width.px]=\"_virtualHorizontalScrollExtent()\"\n aria-hidden=\"true\"\n ></div>\n } @else if (_cellNav()) {\n <!-- ========= Experimental cell-level grid navigation (aria ngGrid) ========= -->\n <!--\n Opt-in via [cellNavigation]=\"true\" (non-virtual only). The aria Grid pattern owns\n roving focus, arrow/Home/End navigation across cells, and aria-activedescendant.\n Only the data <tbody> rows/cells are registered as grid rows/cells; header cells\n stay outside grid navigation. Interactive cells (edit inputs, action buttons)\n expose an ngGridCellWidget so Enter pauses grid nav to interact and Escape resumes.\n -->\n <table\n ngGrid\n rowWrap=\"nowrap\"\n colWrap=\"nowrap\"\n class=\"mlv-data-table__table\"\n [class.mlv-data-table__table--striped]=\"striped()\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.table-layout]=\"resizedTableWidth() === null ? null : 'fixed'\"\n role=\"grid\"\n #tableEl\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <thead\n class=\"mlv-data-table__head\"\n [class.mlv-data-table__head--sticky]=\"stickyHeader()\"\n >\n <ng-container [ngTemplateOutlet]=\"headRowsTpl\" />\n </thead>\n\n <tbody class=\"mlv-data-table__body\">\n @if (showError()) {\n <ng-container [ngTemplateOutlet]=\"errorRowTpl\" />\n } @else if (flatRows().length === 0) {\n <ng-container [ngTemplateOutlet]=\"noDataRowTpl\" />\n } @else { @for (row of flatRows(); track $index; let i = $index) {\n <tr\n ngGridRow\n class=\"mlv-data-table__row mlv-data-table__row--data\"\n [class.mlv-data-table__row--expanded]=\"isRowExpanded(row)\"\n [class.mlv-data-table__row--editing]=\"isEditing(i)\"\n [class.mlv-data-table__row--selected]=\"isRowSelected(row)\"\n [attr.aria-level]=\"getDepth(row) > 0 ? getDepth(row) + 1 : null\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row) : null\"\n [attr.data-row-index]=\"i\"\n (click)=\"onRowClick(row, i, $event)\"\n >\n @if (selectable()) {\n <td\n ngGridCell\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n >\n <mlv-checkbox\n [checked]=\"isRowSelected(row)\"\n [tabbable]=\"false\"\n (checkedChange)=\"toggleRowSelection(row)\"\n (click)=\"$event.stopPropagation()\"\n [ariaLabel]=\"'Select row ' + (i + 1)\"\n />\n </td>\n } @for (col of visibleColumns(); track col.key; let ci = $index) {\n <td\n ngGridCell\n class=\"mlv-data-table__cell mlv-data-table__cell--data\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n >\n @if ( editable() && isEditing(i) && getEditTemplate(col.key); as\n editTpl ) {\n <div\n ngGridCellWidget\n widgetType=\"editable\"\n class=\"mlv-data-table__cell-content\"\n >\n <ng-container\n [ngTemplateOutlet]=\"editTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n </div>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"cellContentTpl\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n col: col,\n ci: ci,\n }\"\n />\n }\n </td>\n } @if (editable()) {\n <td\n ngGridCell\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n >\n <div\n ngGridCellWidget\n widgetType=\"complex\"\n class=\"mlv-data-table__cell-content mlv-data-table__actions\"\n >\n <ng-container\n [ngTemplateOutlet]=\"actionsButtonsTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n </td>\n }\n </tr>\n } }\n </tbody>\n\n @if (getFooterTemplate(); as footerTpl) {\n <tfoot\n class=\"mlv-data-table__foot\"\n [class.mlv-data-table__foot--sticky]=\"stickyHeader()\"\n >\n <tr class=\"mlv-data-table__row mlv-data-table__row--footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: visibleColumns() }\"\n />\n </tr>\n </tfoot>\n }\n </table>\n\n @if (paginationMode() === 'infinite' && loading()) {\n <div\n class=\"mlv-data-table__loading-bottom\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <mlv-loader\n variant=\"circle\"\n [indeterminate]=\"true\"\n [size]=\"24\"\n ariaLabel=\"Loading more rows\"\n />\n </div>\n } } @else {\n <!-- ==================== Standard (non-virtual) mode ==================== -->\n <table\n class=\"mlv-data-table__table\"\n [class.mlv-data-table__table--striped]=\"striped()\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.table-layout]=\"resizedTableWidth() === null ? null : 'fixed'\"\n role=\"grid\"\n #tableEl\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <thead\n class=\"mlv-data-table__head\"\n [class.mlv-data-table__head--sticky]=\"stickyHeader()\"\n >\n <ng-container [ngTemplateOutlet]=\"headRowsTpl\" />\n </thead>\n\n <tbody class=\"mlv-data-table__body\">\n @if (showError()) {\n <ng-container [ngTemplateOutlet]=\"errorRowTpl\" />\n } @else if (flatRows().length === 0) {\n <ng-container [ngTemplateOutlet]=\"noDataRowTpl\" />\n } @else { @for (row of flatRows(); track $index; let i = $index) {\n <tr\n class=\"mlv-data-table__row mlv-data-table__row--data\"\n [class.mlv-data-table__row--expanded]=\"isRowExpanded(row)\"\n [class.mlv-data-table__row--editing]=\"isEditing(i)\"\n [class.mlv-data-table__row--selected]=\"isRowSelected(row)\"\n [attr.aria-level]=\"getDepth(row) > 0 ? getDepth(row) + 1 : null\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row) : null\"\n [attr.tabindex]=\"_rowTabIndex(i)\"\n [attr.data-row-index]=\"i\"\n (click)=\"onRowClick(row, i, $event)\"\n (focus)=\"_onRowFocus(i)\"\n (keydown)=\"_onRowKeydown(i, row, $event)\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowCellsTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n </tr>\n } }\n </tbody>\n\n @if (getFooterTemplate(); as footerTpl) {\n <tfoot\n class=\"mlv-data-table__foot\"\n [class.mlv-data-table__foot--sticky]=\"stickyHeader()\"\n >\n <tr class=\"mlv-data-table__row mlv-data-table__row--footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: visibleColumns() }\"\n />\n </tr>\n </tfoot>\n }\n </table>\n\n @if (paginationMode() === 'infinite' && loading()) {\n <div\n class=\"mlv-data-table__loading-bottom\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <mlv-loader\n variant=\"circle\"\n [indeterminate]=\"true\"\n [size]=\"24\"\n ariaLabel=\"Loading more rows\"\n />\n </div>\n } }\n</div>\n\n@if (paginationMode() === 'paged' && !virtualScroll()) {\n<div class=\"mlv-data-table__footer\">\n <mlv-pagination\n [totalItems]=\"totalItems()\"\n [currentPage]=\"currentPage()\"\n [itemsPerPage]=\"currentPerPage()\"\n (currentPageChange)=\"_onPageChange($event)\"\n (itemsPerPageChange)=\"_onPerPageChange($event)\"\n />\n</div>\n} @if (paginationMode() === 'paged' && loading()) {\n<div\n class=\"mlv-data-table__loading-overlay\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n>\n <mlv-loader\n variant=\"circle\"\n [indeterminate]=\"true\"\n [size]=\"48\"\n ariaLabel=\"Loading table data\"\n />\n</div>\n}\n\n<!-- ==================== Reusable templates ==================== -->\n\n<!--\n Shared <colgroup> template \u2014 used by both the standard table and the three split tables in\n virtual mode (header / body / footer). Keeping the colgroup definitions identical and combining\n it with `table-layout: fixed` keeps column widths in sync between the split tables in virtual mode.\n-->\n<ng-template #colgroupTpl>\n <colgroup>\n @if (selectable() === 'multi' || selectable() === 'single') {\n <col\n class=\"mlv-data-table__col--select\"\n [style.width]=\"getAuxiliaryColumnWidth('selection')\"\n />\n } @for (col of visibleColumns(); track col.key) {\n <col [style.width]=\"getColWidth(col)\" />\n } @if (editable()) {\n <col\n class=\"mlv-data-table__col--actions\"\n [style.width]=\"getAuxiliaryColumnWidth('actions')\"\n />\n }\n </colgroup>\n</ng-template>\n\n<!-- Header rows \u2014 emits the same content the original `<thead>` did. -->\n<ng-template #headRowsTpl>\n @if (hasColumnGroups()) {\n <!-- Group header row -->\n <tr class=\"mlv-data-table__row mlv-data-table__row--group-header\">\n @if (selectable() === 'multi') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n rowspan=\"2\"\n >\n <mlv-checkbox\n [checked]=\"allRowsSelected()\"\n [indeterminate]=\"someRowsSelected()\"\n (checkedChange)=\"toggleSelectAll()\"\n [ariaLabel]=\"_i18n().selectAllRows\"\n />\n </th>\n } @else if (selectable() === 'single') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n rowspan=\"2\"\n ></th>\n } @for (col of visibleColumns(); track col.key) { @if (headerLayout(); as\n layout) { @if (layout.standaloneKeys.has(col.key)) {\n <!-- Standalone column spans both header rows -->\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--standalone\"\n [class.mlv-data-table__cell--sortable]=\"col.sortable\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n [attr.data-mlv-column-key]=\"col.key\"\n rowspan=\"2\"\n scope=\"col\"\n [attr.aria-sort]=\"\n col.sortable\n ? getSortDirection(col) === 'asc'\n ? 'ascending'\n : getSortDirection(col) === 'desc'\n ? 'descending'\n : 'none'\n : null\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"headerCellInnerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n </th>\n } @else {\n <!-- Check if this column is the first column of a group -->\n @for (group of columnGroups(); track group.title) { @if (group.columns[0]\n === col.key) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--group-header\"\n [class.mlv-data-table__cell--align-left]=\"\n group.align === 'left'\n \"\n [class.mlv-data-table__cell--align-center]=\"\n group.align === 'center' || !group.align\n \"\n [class.mlv-data-table__cell--align-right]=\"\n group.align === 'right'\n \"\n [attr.colspan]=\"group.columns.length\"\n scope=\"colgroup\"\n >\n {{ group.title }}\n </th>\n } } } } } @if (editable()) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n rowspan=\"2\"\n >\n <span class=\"mlv-data-table__visually-hidden\"\n >{{ actionsHeaderLabel() }}</span\n >\n </th>\n }\n </tr>\n <!-- Sub-header row for grouped columns -->\n <tr class=\"mlv-data-table__row mlv-data-table__row--header\">\n @for (col of visibleColumns(); track col.key) { @if (headerLayout(); as\n layout) { @if (layout.groupedKeys.has(col.key)) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header\"\n [class.mlv-data-table__cell--sortable]=\"col.sortable\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n [attr.data-mlv-column-key]=\"col.key\"\n scope=\"col\"\n [attr.aria-sort]=\"\n col.sortable\n ? getSortDirection(col) === 'asc'\n ? 'ascending'\n : getSortDirection(col) === 'desc'\n ? 'descending'\n : 'none'\n : null\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"headerCellInnerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n </th>\n } } }\n </tr>\n } @else {\n <!-- Standard single-row header -->\n <tr class=\"mlv-data-table__row mlv-data-table__row--header\">\n @if (selectable() === 'multi') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n >\n <mlv-checkbox\n [checked]=\"allRowsSelected()\"\n [indeterminate]=\"someRowsSelected()\"\n (checkedChange)=\"toggleSelectAll()\"\n [ariaLabel]=\"_i18n().selectAllRows\"\n />\n </th>\n } @else if (selectable() === 'single') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n ></th>\n } @for (col of visibleColumns(); track col.key) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header\"\n [class.mlv-data-table__cell--sortable]=\"col.sortable\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n [attr.data-mlv-column-key]=\"col.key\"\n [attr.aria-sort]=\"\n col.sortable\n ? getSortDirection(col) === 'asc'\n ? 'ascending'\n : getSortDirection(col) === 'desc'\n ? 'descending'\n : 'none'\n : null\n \"\n scope=\"col\"\n >\n <ng-container\n [ngTemplateOutlet]=\"headerCellInnerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n </th>\n } @if (editable()) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n >\n <span class=\"mlv-data-table__visually-hidden\"\n >{{ actionsHeaderLabel() }}</span\n >\n </th>\n }\n </tr>\n }\n</ng-template>\n\n<!--\n Shared inner content for a single header cell. Context: { $implicit: col }.\n Sortable columns wrap the label + sort icon in ONE native <button> (APG grid\n sort pattern) so the <th> stays a non-interactive cell carrying only aria-sort;\n the pin button is a sibling of the sort button, never nested inside it, so no\n interactive control is nested within another (avoids axe `nested-interactive`).\n-->\n<ng-template #headerCellInnerTpl let-col>\n <div class=\"mlv-data-table__cell-inner\">\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"mlv-data-table__sort-button\"\n [attr.aria-label]=\"getSortLabel(col)\"\n (click)=\"onSortClick(col)\"\n >\n <span class=\"mlv-data-table__header-title\"\n >{{ col.title ?? col.key }}</span\n >\n <span class=\"mlv-data-table__sort-icon\" aria-hidden=\"true\">\n @if (getSortDirection(col) === 'asc') {\n <svg lucideArrowUp />\n } @else if (getSortDirection(col) === 'desc') {\n <svg lucideArrowDown />\n } @else {\n <svg lucideChevronsUpDown class=\"mlv-data-table__sort-icon--inactive\" />\n }\n </span>\n </button>\n } @else {\n <span class=\"mlv-data-table__header-title\">{{ col.title ?? col.key }}</span>\n } @if (col.pinnable) {\n <ng-container\n [ngTemplateOutlet]=\"pinButtonTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n } @if (filterDisplay() === 'column' && col.filterable) {\n <button\n mlvButton\n class=\"mlv-data-table__column-filter\"\n [class.mlv-data-table__column-filter--active]=\"\n isColumnFiltered(col.key)\n \"\n [variant]=\"\n columnFilterPopup.opened() || isColumnFiltered(col.key)\n ? 'primary'\n : 'transparent'\n \"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n [attr.data-column-key]=\"col.key\"\n [mlvPopupTrigger]=\"columnFilterPopup\"\n #columnFilterTrigger=\"mlvPopupTrigger\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"getFilterLabel(col)\"\n >\n <svg lucideFunnel mlvButtonIcon [size]=\"14\" />\n </button>\n\n <mlv-popup\n #columnFilterPopup\n panelRole=\"dialog\"\n [ariaLabel]=\"getFilterLabel(col)\"\n (afterClosed)=\"focusColumnFilterTrigger(col.key)\"\n >\n <mlv-dt-filter-dropdown\n *mlvPopupContent\n [columns]=\"getColumnFilterColumns(col)\"\n [activeFilters]=\"activeFilters()\"\n (activeFiltersChange)=\"onColumnFiltersChange(col.key, $event)\"\n (closed)=\"columnFilterTrigger.close()\"\n />\n </mlv-popup>\n }\n </div>\n @if (col.resizable) {\n <div\n #resizeHandle\n class=\"mlv-data-table__resize-handle\"\n [attr.data-column-key]=\"col.key\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"getColumnResizeLabel(col)\"\n [attr.aria-valuenow]=\"getColumnResizeValue(col)\"\n [attr.aria-valuemin]=\"getColumnResizeMin(col)\"\n [attr.aria-valuemax]=\"getColumnResizeMax(col)\"\n [attr.aria-valuetext]=\"getColumnResizeValueText(col)\"\n (pointerdown)=\"onResizeStart(col, $event)\"\n (keydown)=\"onColumnResizeKeydown(col, $event)\"\n (dblclick)=\"resetColumnWidth(col.key)\"\n ></div>\n }\n</ng-template>\n\n<!-- No-data fallback row, used by both rendering paths. -->\n<ng-template #noDataRowTpl>\n <tr class=\"mlv-data-table__row mlv-data-table__row--no-data\">\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--no-data\"\n [attr.colspan]=\"totalColumnCount()\"\n >\n @if (getNoDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"getNoDataTemplate()!\" />\n } @else {\n <div class=\"mlv-data-table__no-data-default\">\n <svg lucideTable2 [size]=\"40\" aria-hidden=\"true\" />\n <span>No data available</span>\n </div>\n }\n </td>\n </tr>\n</ng-template>\n\n<!--\n Failed-request row, used by all three rendering paths. Takes precedence over both the\n data rows and #noDataRowTpl so a failed request never reads as an empty result set.\n The region is announced as an alert; the default block is an mlv-empty-state with a\n danger-toned icon and a Retry button wired to the (retry) output.\n-->\n<ng-template #errorRowTpl>\n <tr class=\"mlv-data-table__row mlv-data-table__row--error\">\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--error\"\n [attr.colspan]=\"totalColumnCount()\"\n >\n <div class=\"mlv-data-table__error\" role=\"alert\" aria-live=\"assertive\">\n @if (getErrorTemplate(); as errorTpl) {\n <ng-container\n [ngTemplateOutlet]=\"errorTpl\"\n [ngTemplateOutletContext]=\"_errorContext()\"\n />\n } @else {\n <mlv-empty-state>\n <svg\n mlvEmptyStateIcon\n lucideTriangleAlert\n class=\"mlv-data-table__error-icon\"\n [size]=\"40\"\n aria-hidden=\"true\"\n />\n <span mlvEmptyStateTitle>{{ _i18n().errorTitle }}</span>\n <span mlvEmptyStateDescription>{{ errorMessage() }}</span>\n <button\n mlvEmptyStateActions\n mlvButton\n variant=\"secondary\"\n type=\"button\"\n class=\"mlv-data-table__error-retry\"\n (click)=\"onRetry()\"\n >\n {{ _i18n().retry }}\n </button>\n </mlv-empty-state>\n }\n </div>\n </td>\n </tr>\n</ng-template>\n\n<!--\n Per-row data cells. Emits the selection cell, the data cells, and the actions cell.\n The owning <tr> stays at the consumer site (either inside `@for` for the standard mode\n or `*cdkVirtualFor` inside the CDK viewport in virtual mode), so each rendering path can\n control its own row-level host bindings.\n-->\n<ng-template #rowCellsTpl let-row let-i=\"index\">\n @if (selectable()) {\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n >\n <!--\n [tabbable]=\"false\" keeps this checkbox out of the tab order so the row is\n the single tab stop: the row's Space/Enter toggles selection, and the\n checkbox stays operable via the mouse. Avoids a per-row double tab stop.\n -->\n <mlv-checkbox\n [checked]=\"isRowSelected(row)\"\n [tabbable]=\"false\"\n (checkedChange)=\"toggleRowSelection(row)\"\n (click)=\"$event.stopPropagation()\"\n [ariaLabel]=\"'Select row ' + (i + 1)\"\n />\n </td>\n } @for (col of visibleColumns(); track col.key; let ci = $index) {\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--data\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n >\n <ng-container\n [ngTemplateOutlet]=\"cellContentTpl\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n col: col,\n ci: ci,\n }\"\n />\n </td>\n } @if (editable()) {\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n >\n <div class=\"mlv-data-table__cell-content mlv-data-table__actions\">\n <ng-container\n [ngTemplateOutlet]=\"actionsButtonsTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n </td>\n }\n</ng-template>\n\n<!--\n Shared edit/save/cancel action buttons for the actions column. Context: { $implicit: row, index: i }.\n-->\n<ng-template #actionsButtonsTpl let-row let-i=\"index\">\n @if (isEditing(i)) {\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"saveEdit(row, i)\"\n [attr.aria-label]=\"_i18n().saveChanges\"\n >\n <svg lucideCheck mlvButtonIcon />\n </button>\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"cancelEdit(row, i)\"\n [attr.aria-label]=\"_i18n().cancelEditing\"\n >\n <svg lucideX mlvButtonIcon />\n </button>\n } @else {\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"startEdit(row, i)\"\n [attr.aria-label]=\"_i18n().editRow\"\n >\n <svg lucidePencil mlvButtonIcon />\n </button>\n }\n</ng-template>\n\n<!--\n Shared inner content of a data cell (indent, expand button, edit/display template, raw value).\n Extracted so both the standard `#rowCellsTpl` `<td>` and the experimental cell-navigation grid\n `<td ngGridCell>` render identical content. Purely presentational \u2014 contains no aria grid\n directives \u2014 so it is safe to project via ngTemplateOutlet across the grid-cell boundary.\n Context: { $implicit: row, index: i, col, ci }.\n-->\n<ng-template #cellContentTpl let-row let-i=\"index\" let-col=\"col\" let-ci=\"ci\">\n <div class=\"mlv-data-table__cell-content\">\n @if (ci === 0 && getDepth(row) > 0) {\n <span\n class=\"mlv-data-table__indent\"\n [style.padding-left.rem]=\"getDepth(row) * 1.25\"\n aria-hidden=\"true\"\n ></span>\n } @if (ci === 0 && hasChildren(row)) {\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n class=\"mlv-data-table__expand-btn\"\n (click)=\"toggleExpand(row, $event)\"\n [attr.aria-expanded]=\"isRowExpanded(row)\"\n [attr.aria-label]=\"\n isRowExpanded(row) ? _i18n().collapseRow : _i18n().expandRow\n \"\n >\n <svg\n lucideChevronRight\n mlvButtonIcon\n class=\"mlv-data-table__expand-icon\"\n [class.mlv-data-table__expand-icon--open]=\"isRowExpanded(row)\"\n />\n </button>\n } @if (editable() && isEditing(i) && getEditTemplate(col.key); as editTpl) {\n <ng-container\n [ngTemplateOutlet]=\"editTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n } @else if (getTemplate(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n } @else {\n <!--\n Default cell renderer. `valueLabels` (or the `filterConfig.options` fallback)\n maps the raw value to a label; `tone` promotes the cell to a muted badge.\n -->\n @if (getCellTone(row, col); as tone) {\n <mlv-badge [tone]=\"tone\" muted\n >{{ getCellDisplayValue(row, col) }}</mlv-badge\n >\n } @else { {{ getCellDisplayValue(row, col) }} } }\n </div>\n</ng-template>\n\n<!-- Reusable pin button template. Rendered via ngTemplateOutlet from every header cell that supports pinning. -->\n<ng-template #pinButtonTpl let-col>\n @if (getPinnableSides(col); as sides) { @if (sides.length > 1) {\n <button\n class=\"mlv-data-table__pin-btn\"\n [class.mlv-data-table__pin-btn--active]=\"isColumnPinned(col)\"\n type=\"button\"\n [mlvPopupTrigger]=\"pinPopup\"\n #pinTrigger=\"mlvPopupTrigger\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"\n isColumnPinned(col) ? _i18n().changePinSide : _i18n().pinColumn\n \"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"pinPopup.opened()\"\n [attr.aria-pressed]=\"isColumnPinned(col)\"\n >\n @if (isColumnPinned(col)) {\n <svg lucidePinOff />\n } @else {\n <svg lucidePin />\n }\n </button>\n <mlv-popup #pinPopup>\n <div *mlvPopupContent class=\"mlv-data-table__pin-popup\" role=\"menu\">\n @for (side of sides; track side) {\n <button\n type=\"button\"\n role=\"menuitemradio\"\n class=\"mlv-data-table__pin-popup-item\"\n [class.mlv-data-table__pin-popup-item--active]=\"\n getColumnPinSide(col) === side\n \"\n [attr.aria-checked]=\"getColumnPinSide(col) === side\"\n (click)=\"\n pinTo(col, side); pinTrigger.close(); $event.stopPropagation()\n \"\n >\n <svg lucidePin [size]=\"14\" />\n @if (side === 'left') {\n <span>Pin left</span>\n } @else {\n <span>Pin right</span>\n }\n </button>\n } @if (isColumnPinned(col)) {\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"mlv-data-table__pin-popup-item mlv-data-table__pin-popup-item--unpin\"\n (click)=\"unpin(col); pinTrigger.close(); $event.stopPropagation()\"\n >\n <svg lucidePinOff [size]=\"14\" />\n <span>{{ _i18n().unpin }}</span>\n </button>\n }\n </div>\n </mlv-popup>\n } @else {\n <button\n class=\"mlv-data-table__pin-btn\"\n [class.mlv-data-table__pin-btn--active]=\"isColumnPinned(col)\"\n type=\"button\"\n (click)=\"togglePin(col, sides[0]); $event.stopPropagation()\"\n [attr.aria-label]=\"\n isColumnPinned(col) ? _i18n().unpinColumn : _i18n().pinColumn\n \"\n [attr.aria-pressed]=\"isColumnPinned(col)\"\n >\n @if (isColumnPinned(col)) {\n <svg lucidePinOff />\n } @else {\n <svg lucidePin />\n }\n </button>\n } }\n</ng-template>\n", styles: ["@layer mlv.components{.mlv-data-table{box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-dt-font-size)}.mlv-data-table *{box-sizing:border-box}.mlv-data-table{--mlv-dt-row-height: calc(var(--mlv-height-m) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1.25rem;--mlv-dt-header-height: 3rem;--mlv-dt-font-size: var(--mlv-font-size-m);--mlv-dt-header-font-size: var(--mlv-font-size-m);--mlv-dt-icon-size: 1rem;--mlv-dt-toolbar-gap: .5rem;--mlv-dt-toolbar-padding: .75rem 0;display:flex;flex-direction:column;width:100%;position:relative;color:var(--mlv-text-primary)}[class*=--tight] .mlv-data-table:not([class*=--compact],[class*=--comfortable],[class*=--spacious],[class*=--airy]),.mlv-data-table[class*=--tight]{--mlv-dt-row-height: calc(var(--mlv-height-xs) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: .75rem;--mlv-dt-header-height: 2.25rem;--mlv-dt-font-size: var(--mlv-font-size-s);--mlv-dt-header-font-size: var(--mlv-font-size-s);--mlv-dt-icon-size: .75rem;--mlv-dt-toolbar-gap: .25rem;--mlv-dt-toolbar-padding: .375rem 0}[class*=--compact] .mlv-data-table:not([class*=--tight],[class*=--comfortable],[class*=--spacious],[class*=--airy]),.mlv-data-table[class*=--compact]{--mlv-dt-row-height: calc(var(--mlv-height-s) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1rem;--mlv-dt-header-height: 2.5rem;--mlv-dt-font-size: var(--mlv-font-size-s);--mlv-dt-header-font-size: var(--mlv-font-size-s);--mlv-dt-icon-size: .875rem;--mlv-dt-toolbar-gap: .375rem;--mlv-dt-toolbar-padding: .5rem 0}[class*=--spacious] .mlv-data-table:not([class*=--tight],[class*=--compact],[class*=--comfortable],[class*=--airy]),.mlv-data-table[class*=--spacious]{--mlv-dt-row-height: calc(var(--mlv-height-l) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1.5rem;--mlv-dt-header-height: 3.25rem;--mlv-dt-font-size: var(--mlv-font-size-l);--mlv-dt-header-font-size: var(--mlv-font-size-l);--mlv-dt-icon-size: 1.125rem;--mlv-dt-toolbar-gap: .75rem;--mlv-dt-toolbar-padding: .75rem 0}[class*=--airy] .mlv-data-table:not([class*=--tight],[class*=--compact],[class*=--comfortable],[class*=--spacious]),.mlv-data-table[class*=--airy]{--mlv-dt-row-height: calc(var(--mlv-height-xl) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1.75rem;--mlv-dt-header-height: 3.75rem;--mlv-dt-font-size: var(--mlv-font-size-l);--mlv-dt-header-font-size: var(--mlv-font-size-l);--mlv-dt-icon-size: 1.25rem;--mlv-dt-toolbar-gap: 1rem;--mlv-dt-toolbar-padding: 1rem 0}.mlv-data-table__toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:var(--mlv-dt-toolbar-gap);padding:var(--mlv-dt-toolbar-padding);position:relative}.mlv-data-table__search{flex:1 1 16rem;width:min(100%,24rem);max-width:24rem}.mlv-data-table__toolbar-actions{display:flex;gap:var(--mlv-dt-toolbar-gap);margin-inline-start:auto}.mlv-data-table__filter-badge{font-size:var(--mlv-dt-font-size);color:var(--mlv-text-secondary)}.mlv-data-table__wrapper{width:100%;overflow-x:auto;overflow-y:auto;position:relative}.mlv-data-table__wrapper--virtual{overflow-y:visible;display:flex;flex-direction:column}.mlv-data-table__virtual-viewport{display:block;width:100%;min-width:0;max-width:100%;flex:0 0 auto;position:sticky;inset-inline-start:0;border-bottom:.0625rem solid var(--mlv-border-subtle)}.mlv-data-table__virtual-viewport.cdk-virtual-scrollable{overflow-x:hidden;overflow-y:auto}.mlv-data-table__virtual-horizontal-sizer{width:0;height:0;min-height:0;flex:0 0 0;align-self:flex-start;pointer-events:none}.mlv-data-table__table--virtual-header,.mlv-data-table__table--virtual-footer{--mlv-dt-pinned-right-correction: var( --mlv-dt-virtual-scrollbar-gutter, 0px )}.mlv-data-table__loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--mlv-background-base) 70%,transparent);-webkit-backdrop-filter:blur(.0625rem);backdrop-filter:blur(.0625rem);z-index:20;pointer-events:all}.mlv-data-table__loading-bottom{display:flex;align-items:center;justify-content:center;padding:1rem 0;color:var(--mlv-text-secondary)}.mlv-data-table__table{width:100%;border-collapse:collapse;table-layout:auto;font-size:var(--mlv-dt-font-size);color:var(--mlv-text-primary)}.mlv-data-table__table--striped .mlv-data-table__row--data:nth-child(2n){background:var(--mlv-background-sunken)}.mlv-data-table__table--striped .mlv-data-table__row--data:nth-child(2n) .mlv-data-table__cell--pinned{background:var(--mlv-background-sunken)}.mlv-data-table__table--bordered .mlv-data-table__cell{border-inline-end:.0625rem solid var(--mlv-border-subtle)}.mlv-data-table__table--bordered .mlv-data-table__cell:last-child{border-inline-end:none}.mlv-data-table__table--virtual{table-layout:fixed}.mlv-data-table__head--sticky{position:sticky;top:var(--mlv-dt-sticky-top, 0);z-index:3;background:var(--mlv-background-base)}.mlv-data-table__head--sticky .mlv-data-table__cell--pinned{z-index:4}.mlv-data-table__cell{padding:0;border-bottom:.0625rem solid var(--mlv-border-subtle);vertical-align:middle;background:inherit}.mlv-data-table__cell-content{display:flex;align-items:center;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mlv-data-table__cell--header{font-weight:var(--mlv-font-weight-medium);font-size:var(--mlv-dt-header-font-size);color:color-mix(in srgb,var(--mlv-text-action) 65%,var(--mlv-text-secondary));position:relative;-webkit-user-select:none;user-select:none;border-bottom:.0625rem solid var(--mlv-border-normal)}.mlv-data-table__cell--sortable{cursor:pointer}.mlv-data-table__cell--sortable:hover .mlv-data-table__cell-inner{color:var(--mlv-text-action)}.mlv-data-table__cell--data{padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-row-height);font-size:var(--mlv-dt-font-size)}.mlv-data-table__cell--pinned{background:var(--mlv-background-base);z-index:1;transition:background var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__cell--pinned:after{content:\"\";position:absolute;top:0;bottom:0;width:.5rem;pointer-events:none}.mlv-data-table__cell--pinned-left:after{inset-inline-end:-.5rem;background:linear-gradient(to right,rgba(0,0,0,.04),transparent)}.mlv-data-table__cell--pinned-right:after{inset-inline-start:-.5rem;background:linear-gradient(to left,rgba(0,0,0,.04),transparent)}.mlv-data-table__cell--no-data,.mlv-data-table__cell--error{padding:3rem var(--mlv-dt-cell-padding-x);text-align:center}.mlv-data-table__cell--align-left{text-align:start}.mlv-data-table__cell--align-center{text-align:center}.mlv-data-table__cell--align-right{text-align:end}.mlv-data-table__cell-inner{display:flex;align-items:center;gap:.375rem;padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-header-height);transition:color var(--mlv-duration-normal) var(--mlv-ease-default);border-radius:var(--mlv-radius-s)}.mlv-data-table__sort-button{display:inline-flex;align-items:center;gap:.375rem;flex:1;min-width:0;margin:0;padding:0;border:none;background:none;font:inherit;color:inherit;text-align:start;cursor:pointer;border-radius:var(--mlv-radius-s)}.mlv-data-table__sort-button:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-focus-ring-offset)}.mlv-data-table__visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;padding:0;margin:-1px}.mlv-data-table__header-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start}.mlv-data-table__column-filter{flex:0 0 auto}.mlv-data-table__column-filter--active{color:var(--mlv-text-action)}.mlv-data-table__sort-icon{display:inline-flex;flex-shrink:0;color:var(--mlv-text-action)}.mlv-data-table__sort-icon svg{width:var(--mlv-dt-icon-size);height:var(--mlv-dt-icon-size)}.mlv-data-table__sort-icon--inactive{opacity:0;transition:opacity var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__cell--sortable:hover .mlv-data-table__sort-icon--inactive{opacity:.5}.mlv-data-table__pin-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;background:none;cursor:pointer;color:var(--mlv-text-tertiary);opacity:0;transition:opacity var(--mlv-duration-normal) var(--mlv-ease-default),color var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__pin-btn svg{width:var(--mlv-dt-icon-size);height:var(--mlv-dt-icon-size)}.mlv-data-table__cell--header:hover .mlv-data-table__pin-btn{opacity:.6}.mlv-data-table__pin-btn:hover{opacity:1!important;color:var(--mlv-text-action)}.mlv-data-table__pin-btn--active{opacity:1;color:var(--mlv-text-action)}.mlv-data-table__cell--header:hover .mlv-data-table__pin-btn--active{opacity:1}.mlv-data-table__resize-handle{position:absolute;top:0;inset-inline-end:-.5rem;width:1rem;height:100%;cursor:col-resize;background:transparent;z-index:5;touch-action:none;-webkit-user-select:none;user-select:none}.mlv-data-table__resize-handle:after{content:\"\";position:absolute;top:.75rem;bottom:.75rem;left:50%;width:.0625rem;border-radius:var(--mlv-radius-full);background-color:var(--mlv-text-tertiary);transform:translate(-50%);transition:background-color var(--mlv-duration-fast) var(--mlv-ease-default),width var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-data-table__resize-handle:hover:after{width:.125rem;background-color:var(--mlv-background-accent-1)}.mlv-data-table__resize-handle:active:after,.mlv-data-table__resize-handle:focus-visible:after{width:.125rem;background-color:var(--mlv-background-accent-1)}.mlv-data-table__resize-handle:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:calc(var(--mlv-focus-ring-offset) * -1)}@media(pointer:coarse){.mlv-data-table__resize-handle{inset-inline-end:-.75rem;width:1.5rem}}.mlv-data-table__row{transition:background var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__row--data:hover,.mlv-data-table__row--data:hover .mlv-data-table__cell--pinned{background:var(--mlv-background-neutral-1-hover)}.mlv-data-table__row--expanded,.mlv-data-table__row--expanded .mlv-data-table__cell--pinned{background:var(--mlv-background-sunken)}.mlv-data-table__indent{display:inline-block}.mlv-data-table__expand-btn{margin-inline-end:.25rem;vertical-align:middle;flex-shrink:0}.mlv-data-table__expand-icon{width:var(--mlv-dt-icon-size);height:var(--mlv-dt-icon-size);transition:transform var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__expand-icon--open{transform:rotate(90deg)}.mlv-data-table__no-data-default{display:flex;flex-direction:column;align-items:center;gap:.75rem;padding:3rem 0;color:var(--mlv-text-secondary)}.mlv-data-table__no-data-default svg{opacity:.2}.mlv-data-table__no-data-default span{font-size:var(--mlv-dt-font-size)}.mlv-data-table__error{display:block;text-align:initial}.mlv-data-table__error-icon{color:var(--mlv-text-negative)}.mlv-data-table__row--group-header .mlv-data-table__cell--group-header{font-weight:var(--mlv-font-weight-medium);font-size:var(--mlv-dt-header-font-size);color:color-mix(in srgb,var(--mlv-text-action) 65%,var(--mlv-text-secondary));text-align:center;padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-header-height);border-bottom:.0625rem solid var(--mlv-border-subtle);vertical-align:middle}.mlv-data-table__row--group-header .mlv-data-table__cell--standalone{vertical-align:middle}.mlv-data-table__cell--actions{width:1%;white-space:nowrap;padding:0 var(--mlv-dt-cell-padding-x)!important}.mlv-data-table__actions{display:flex;align-items:center;gap:.25rem;justify-content:flex-end}.mlv-data-table__row--editing,.mlv-data-table__row--editing .mlv-data-table__cell--pinned{background:var(--mlv-background-sunken)}.mlv-data-table__cell--select{width:2.5rem;min-width:2.5rem;max-width:2.5rem;padding:0 .5rem!important;text-align:center}.mlv-data-table__col--select{width:2.5rem}.mlv-data-table__col--actions{width:5rem}.mlv-data-table__row--selected,.mlv-data-table__row--selected .mlv-data-table__cell--pinned{background:color-mix(in srgb,var(--mlv-background-accent-1) 8%,var(--mlv-background-base))}.mlv-data-table__pin-popup{display:flex;flex-direction:column;gap:.125rem;padding:.25rem;min-width:8rem}.mlv-data-table__pin-popup-item{display:flex;align-items:center;gap:.5rem;padding:.375rem .5rem;border:none;background:none;border-radius:var(--mlv-radius-s);cursor:pointer;font:inherit;font-size:var(--mlv-dt-font-size);color:var(--mlv-text-primary);text-align:start}.mlv-data-table__pin-popup-item svg{color:var(--mlv-text-secondary);flex-shrink:0}.mlv-data-table__pin-popup-item:hover{background:var(--mlv-background-sunken)}.mlv-data-table__pin-popup-item--active{color:var(--mlv-text-action)}.mlv-data-table__pin-popup-item--active svg{color:var(--mlv-text-action)}.mlv-data-table__pin-popup-item--unpin{color:var(--mlv-text-negative);border-top:.0625rem solid var(--mlv-border-subtle);margin-top:.125rem;padding-top:.5rem;border-radius:0 0 var(--mlv-radius-s) var(--mlv-radius-s)}.mlv-data-table__pin-popup-item--unpin svg{color:var(--mlv-text-negative)}.mlv-data-table__pin-popup-item--unpin:hover{background:color-mix(in srgb,var(--mlv-text-negative) 8%,transparent)}.mlv-data-table__columns-dropdown{display:flex;flex-direction:column;gap:.25rem;padding:.5rem;min-width:10rem}.mlv-data-table__columns-item{display:flex;align-items:center;gap:.5rem;padding:.25rem .5rem;border-radius:var(--mlv-radius-s);cursor:pointer;font-size:var(--mlv-dt-font-size)}.mlv-data-table__columns-item:hover{background:var(--mlv-background-sunken)}.mlv-data-table__foot{font-weight:var(--mlv-font-weight-medium);font-size:var(--mlv-dt-font-size);background:var(--mlv-background-base)}.mlv-data-table__foot--sticky{position:sticky;bottom:0;z-index:3}.mlv-data-table__foot .mlv-data-table__cell--pinned,.mlv-data-table__row--footer{background:inherit}.mlv-data-table__row--footer>:where(td,th){box-sizing:border-box;padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-header-height);border-top:.125rem solid var(--mlv-border-normal);border-bottom:0;vertical-align:middle;background:inherit;font-size:inherit;font-weight:inherit}.mlv-data-table__table--bordered .mlv-data-table__row--footer>:where(td,th){border-inline-end:.0625rem solid var(--mlv-border-subtle)}.mlv-data-table__table--bordered .mlv-data-table__row--footer>:where(td,th):last-child{border-inline-end:none}.mlv-data-table__footer{padding-top:.75rem}@media(prefers-reduced-motion:reduce){.mlv-data-table,.mlv-data-table *,.mlv-data-table:before,.mlv-data-table:after,[class^=mlv-data-table__],[class*=\" mlv-data-table__\"],[class^=mlv-data-table--],[class*=\" mlv-data-table--\"]{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:var(--mlv-duration-instant)!important}}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: MlvPagination, selector: "mlv-pagination", inputs: ["id", "mobile", "totalItems", "itemsPerPage", "perPageOptions", "displayTotalItems", "currentPage", "mlvDensity"], outputs: ["itemsPerPageChange", "currentPageChange"] }, { kind: "component", type: MlvSearchField, selector: "mlv-search-field", inputs: ["value", "trigger", "debounce", "placeholder", "ariaLabel", "disabled", "loading", "showSubmit", "clearable", "commitOnClear", "presentation", "overlay", "role", "ariaControls", "ariaActiveDescendant", "ariaAutocomplete", "ariaExpanded"], outputs: ["valueChange", "search", "navigate", "commit"] }, { kind: "component", type: MlvFilterDropdown, selector: "mlv-dt-filter-dropdown", inputs: ["columns", "activeFilters"], outputs: ["activeFiltersChange", "closed"] }, { kind: "component", type: MlvButton, selector: "button[mlvButton], a[mlvButton]", inputs: ["variant", "shape", "disabled", "loading", "selected"] }, { kind: "component", type: MlvBadge, selector: "mlv-badge", inputs: ["tone", "rounded", "muted"] }, { kind: "component", type: LucideArrowUp, selector: "svg[lucideArrowUp]" }, { kind: "component", type: LucideArrowDown, selector: "svg[lucideArrowDown]" }, { kind: "component", type: LucideChevronsUpDown, selector: "svg[lucideChevronsUpDown]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "component", type: LucideFilter, selector: "svg[lucideFunnel], svg[lucideFilter]" }, { kind: "component", type: LucideTable2, selector: "svg[lucideTable2]" }, { kind: "component", type: LucidePencil, selector: "svg[lucidePencil]" }, { kind: "component", type: LucideCheck, selector: "svg[lucideCheck]" }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucidePlus, selector: "svg[lucidePlus]" }, { kind: "component", type: LucidePin, selector: "svg[lucidePin]" }, { kind: "component", type: LucidePinOff, selector: "svg[lucidePinOff]" }, { kind: "component", type: LucideEye, selector: "svg[lucideEye]" }, { kind: "component", type: LucideTriangleAlert, selector: "svg[lucideTriangleAlert], svg[lucideAlertTriangle]" }, { kind: "component", type: LucideArrowUpDown, selector: "svg[lucideArrowUpDown]" }, { kind: "component", type: MlvEmptyState, selector: "mlv-empty-state" }, { kind: "component", type: MlvLoader, selector: "mlv-loader", inputs: ["variant", "tone", "value", "max", "indeterminate", "size", "strokeWidth", "ariaLabel", "showHint", "color", "trackColor", "glow"] }, { kind: "component", type: MlvCheckbox, selector: "mlv-checkbox", inputs: ["ariaLabelledBy", "checked", "indeterminate", "tabbable"], outputs: ["checkedChange"] }, { kind: "directive", type: MlvPopupTrigger, selector: "[mlvPopupTrigger]", inputs: ["mlvPopupTrigger", "triggerOn", "ariaHasPopup"], exportAs: ["mlvPopupTrigger"] }, { kind: "component", type: MlvPopup, selector: "mlv-popup", inputs: ["position", "positions", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "hasArrow", "hasShadow", "class", "mlvDensity", "flexibleDimensions", "scrollStrategy", "hasBackdrop", "restrictPosition", "panelRole", "modal", "ariaLabel", "dismissExcludeElements", "mobileMode", "mobileBreakpoint", "mobileTitle", "mobileCloseLabel", "opened"], outputs: ["openedChange", "afterOpened", "afterClosed"] }, { kind: "directive", type: MlvPopupContent, selector: "[mlvPopupContent]" }, { kind: "directive", type: MlvInfiniteScroll, selector: "[mlvInfiniteScroll]", inputs: ["threshold", "loading", "hasMore", "disabled", "orientation", "scrollContainer"], outputs: ["loadMore"], exportAs: ["mlvInfiniteScroll"] }, { kind: "directive", type: MlvButtonIcon, selector: "[mlvButtonIcon]" }, { kind: "directive", type: Grid, selector: "[ngGrid]", inputs: ["enableSelection", "disabled", "softDisabled", "focusMode", "rowWrap", "colWrap", "multi", "selectionMode", "tabindex"], exportAs: ["ngGrid"] }, { kind: "directive", type: GridRow, selector: "[ngGridRow]", inputs: ["rowIndex"], exportAs: ["ngGridRow"] }, { kind: "directive", type: GridCell, selector: "[ngGridCell]", inputs: ["id", "role", "rowSpan", "colSpan", "rowIndex", "colIndex", "disabled", "selected", "selectable", "tabindex"], outputs: ["selectedChange"], exportAs: ["ngGridCell"] }, { kind: "directive", type: GridCellWidget, selector: "[ngGridCellWidget]", inputs: ["id", "widgetType", "disabled", "focusTarget", "tabindex"], outputs: ["activated", "deactivated"], exportAs: ["ngGridCellWidget"] }, { kind: "component", type: MlvListItem, selector: "mlv-list-item", inputs: ["itemRole", "unread", "accent"] }, { kind: "component", type: MlvMenu, selector: "mlv-menu", inputs: ["label", "mlvDensity", "dataSource"], outputs: ["closed"] }, { kind: "directive", type: MlvMenuItem, selector: "mlv-list-item[mlvMenuItem]", inputs: ["disabled"], outputs: ["itemClick"] }, { kind: "directive", type: MlvMenuTrigger, selector: "[mlvMenuTrigger]", inputs: ["mlvMenuTrigger", "isSubmenuTrigger", "menuTriggerDisabled"], outputs: ["menuOpened", "menuClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2621
+ }
2622
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvDataTable, decorators: [{
2623
+ type: Component,
2624
+ args: [{ selector: 'mlv-data-table', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2625
+ NgTemplateOutlet,
2626
+ ScrollingModule,
2627
+ MlvPagination,
2628
+ MlvSearchField,
2629
+ MlvFilterDropdown,
2630
+ MlvButton,
2631
+ MlvBadge,
2632
+ LucideArrowUp,
2633
+ LucideArrowDown,
2634
+ LucideChevronsUpDown,
2635
+ LucideChevronRight,
2636
+ LucideFilter,
2637
+ LucideTable2,
2638
+ LucideFunnel,
2639
+ LucidePencil,
2640
+ LucideCheck,
2641
+ LucideX,
2642
+ LucidePlus,
2643
+ LucidePin,
2644
+ LucidePinOff,
2645
+ LucideEye,
2646
+ LucideTriangleAlert,
2647
+ LucideArrowUpDown,
2648
+ MlvEmptyState,
2649
+ MlvLoader,
2650
+ MlvCheckbox,
2651
+ MlvPopupTrigger,
2652
+ MlvPopup,
2653
+ MlvPopupContent,
2654
+ MlvInfiniteScroll,
2655
+ MlvButtonIcon,
2656
+ Grid,
2657
+ GridRow,
2658
+ GridCell,
2659
+ GridCellWidget,
2660
+ MlvListItem,
2661
+ MlvMenu,
2662
+ MlvMenuItem,
2663
+ MlvMenuTrigger,
2664
+ ], providers: [
2665
+ { provide: MLV_DENSITY_ELEMENT, useValue: 'data-table' },
2666
+ MlvDataTableEditingService,
2667
+ MlvDataTableColumnVisibilityService,
2668
+ MlvDataTablePinningService,
2669
+ ], hostDirectives: [
2670
+ {
2671
+ directive: MlvDensityDirective,
2672
+ inputs: ['mlvDensity'],
2673
+ },
2674
+ ], host: {
2675
+ class: 'mlv-data-table',
2676
+ }, template: "@if (hasToolbarContent()) {\n<div class=\"mlv-data-table__toolbar\">\n @if (showSearch() && hasSearchableColumns()) {\n <mlv-search-field\n class=\"mlv-data-table__search\"\n [value]=\"_searchDraft()\"\n (valueChange)=\"_searchDraft.set($event)\"\n [trigger]=\"searchTrigger()\"\n [debounce]=\"searchDebounce()\"\n [loading]=\"loading()\"\n [placeholder]=\"_i18n().searchPlaceholder\"\n [ariaLabel]=\"_i18n().searchLabel\"\n (search)=\"onSearch($event)\"\n />\n } @if (filterDisplay() !== 'none' && hasFilters()) {\n <span class=\"mlv-data-table__filter-badge\" aria-live=\"polite\">\n {{ activeFilterLabel() }}\n </span>\n }\n <div class=\"mlv-data-table__toolbar-actions\">\n @if (editable() && addRow()) {\n <button\n mlvButton\n variant=\"secondary\"\n mlvDensity=\"compact\"\n type=\"button\"\n (click)=\"onAddRow()\"\n [attr.aria-label]=\"_i18n().addNewRow\"\n >\n <svg lucidePlus mlvButtonIcon [size]=\"14\" />\n {{ _i18n().addRow }}\n </button>\n } @if (showSortMenu() && hasSortableColumns()) {\n <button\n mlvButton\n variant=\"secondary\"\n mlvDensity=\"compact\"\n type=\"button\"\n data-mlv-table-sort-trigger\n [mlvMenuTrigger]=\"sortMenu\"\n [attr.aria-label]=\"_i18n().sortMenu\"\n >\n <svg mlvButtonIcon lucideArrowUpDown [size]=\"14\" />\n {{ _i18n().sort }}\n </button>\n <mlv-menu #sortMenu [label]=\"_i18n().sortMenu\" mlvDensity=\"compact\">\n @for (column of columns(); track column.key) { @if (column.sortable) { @if\n (currentSort()?.key === column.key) {\n <mlv-list-item\n mlvMenuItem\n [mlvMenuTrigger]=\"directionMenu\"\n [isSubmenuTrigger]=\"true\"\n >\n {{ column.title ?? column.key }}\n </mlv-list-item>\n <mlv-menu\n #directionMenu\n [label]=\"getSortLabel(column)\"\n mlvDensity=\"compact\"\n >\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, 'asc')\">\n {{ _i18n().ascending }}\n </mlv-list-item>\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, 'desc')\">\n {{ _i18n().descending }}\n </mlv-list-item>\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, null)\">\n {{ _i18n().clearSort }}\n </mlv-list-item>\n </mlv-menu>\n } @else {\n <mlv-list-item mlvMenuItem (itemClick)=\"_applyMenuSort(column, 'asc')\">\n {{ column.title ?? column.key }}\n </mlv-list-item>\n } } }\n </mlv-menu>\n } @if (hasHideableColumns()) {\n <button\n mlvButton\n [variant]=\"columnsPopup.opened() ? 'primary' : 'secondary'\"\n mlvDensity=\"compact\"\n type=\"button\"\n [mlvPopupTrigger]=\"columnsPopup\"\n #columnsTrigger=\"mlvPopupTrigger\"\n [attr.aria-label]=\"_i18n().toggleColumnVisibility\"\n >\n <svg mlvButtonIcon lucideEye [size]=\"14\" />\n {{ _i18n().columns }}\n </button>\n\n <mlv-popup #columnsPopup>\n <div *mlvPopupContent class=\"mlv-data-table__columns-dropdown\">\n @for (col of allColumns(); track col.key) { @if (col.hideable) {\n <div class=\"mlv-data-table__columns-item\">\n <mlv-checkbox\n [checked]=\"!isColumnHidden(col.key)\"\n [ariaLabel]=\"col.title ?? col.key\"\n (checkedChange)=\"toggleColumnVisibility(col.key)\"\n />\n <span>{{ col.title ?? col.key }}</span>\n </div>\n } }\n </div>\n </mlv-popup>\n } @if (filterDisplay() === 'toolbar' && hasFilterableColumns()) {\n <button\n #filterBtn\n mlvButton\n [variant]=\"filtersPopup.opened() ? 'primary' : 'secondary'\"\n mlvDensity=\"compact\"\n type=\"button\"\n [mlvPopupTrigger]=\"filtersPopup\"\n #trigger=\"mlvPopupTrigger\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"_i18n().toggleFilters\"\n >\n <svg lucideFilter mlvButtonIcon [size]=\"14\" />\n {{ _i18n().filters }} @if (hasFilters()) {\n <mlv-badge tone=\"primary\" rounded>{{ activeFilters().length }}</mlv-badge>\n }\n </button>\n\n <mlv-popup\n #filtersPopup\n panelRole=\"dialog\"\n [ariaLabel]=\"_i18n().filters\"\n (afterClosed)=\"_onFiltersClosed()\"\n >\n <mlv-dt-filter-dropdown\n *mlvPopupContent\n [columns]=\"columns()\"\n [(activeFilters)]=\"activeFilters\"\n (closed)=\"trigger.close()\"\n />\n </mlv-popup>\n } @if (_toolbarActions(); as actions) {\n <ng-container [ngTemplateOutlet]=\"actions.templateRef\" />\n }\n </div>\n</div>\n}\n\n<div\n class=\"mlv-data-table__wrapper\"\n [class.mlv-data-table__wrapper--virtual]=\"virtualScroll()\"\n [style.max-height]=\"virtualScroll() ? null : maxHeight()\"\n [style.--mlv-dt-virtual-scrollbar-gutter]=\"\n virtualScroll() ? _virtualScrollbarGutter() + 'px' : null\n \"\n #tableWrapper\n mlvInfiniteScroll\n [disabled]=\"paginationMode() !== 'infinite' || virtualScroll()\"\n [threshold]=\"infiniteScrollThreshold()\"\n [loading]=\"!!loading()\"\n [hasMore]=\"!!hasMore()\"\n (loadMore)=\"onInfiniteScrollLoadMore($event)\"\n>\n @if (virtualScroll()) {\n <!-- ==================== Virtual scroll mode ==================== -->\n <!-- Header table \u2014 sits naturally at the top of the wrapper, outside the viewport -->\n <table\n class=\"mlv-data-table__table mlv-data-table__table--virtual mlv-data-table__table--virtual-header\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.flex]=\"resizedTableWidth() === null ? null : '0 0 auto'\"\n role=\"grid\"\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <thead class=\"mlv-data-table__head\">\n <ng-container [ngTemplateOutlet]=\"headRowsTpl\" />\n </thead>\n </table>\n\n <!-- CDK virtual scroll viewport \u2014 owns the only vertical scroll surface in this mode.\n Infinite scroll is intentionally disabled in virtual mode: virtual scrolling is the\n rendering optimisation for already-loaded data, and the two strategies are mutually\n exclusive in this component. -->\n <cdk-virtual-scroll-viewport\n class=\"mlv-data-table__virtual-viewport\"\n [itemSize]=\"rowHeight()\"\n [style.height]=\"virtualViewportHeight()\"\n >\n <table\n class=\"mlv-data-table__table mlv-data-table__table--virtual mlv-data-table__table--virtual-body\"\n [class.mlv-data-table__table--striped]=\"striped()\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n role=\"presentation\"\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <tbody class=\"mlv-data-table__body\">\n @if (showError()) {\n <ng-container [ngTemplateOutlet]=\"errorRowTpl\" />\n } @else if (flatRows().length === 0) {\n <ng-container [ngTemplateOutlet]=\"noDataRowTpl\" />\n } @else {\n <tr\n *cdkVirtualFor=\"\n let row of flatRows();\n let i = index;\n trackBy: trackByRow\n \"\n class=\"mlv-data-table__row mlv-data-table__row--data\"\n [class.mlv-data-table__row--expanded]=\"isRowExpanded(row)\"\n [class.mlv-data-table__row--editing]=\"isEditing(i)\"\n [class.mlv-data-table__row--selected]=\"isRowSelected(row)\"\n [style.height.px]=\"rowHeight()\"\n [attr.aria-level]=\"getDepth(row) > 0 ? getDepth(row) + 1 : null\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row) : null\"\n [attr.tabindex]=\"_rowTabIndex(i)\"\n [attr.data-row-index]=\"i\"\n (click)=\"onRowClick(row, i, $event)\"\n (focus)=\"_onRowFocus(i)\"\n (keydown)=\"_onRowKeydown(i, row, $event)\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowCellsTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n </tr>\n }\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n <!-- Footer summary table \u2014 only when a footer template is projected -->\n @if (getFooterTemplate(); as footerTpl) {\n <table\n class=\"mlv-data-table__table mlv-data-table__table--virtual mlv-data-table__table--virtual-footer\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.flex]=\"resizedTableWidth() === null ? null : '0 0 auto'\"\n role=\"presentation\"\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <tfoot class=\"mlv-data-table__foot\">\n <tr class=\"mlv-data-table__row mlv-data-table__row--footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: visibleColumns() }\"\n />\n </tr>\n </tfoot>\n </table>\n }\n\n <!-- Extends only the outer horizontal scroll range to match the viewport's\n native range, including a classic vertical scrollbar gutter. -->\n <div\n class=\"mlv-data-table__virtual-horizontal-sizer\"\n [style.width.px]=\"_virtualHorizontalScrollExtent()\"\n aria-hidden=\"true\"\n ></div>\n } @else if (_cellNav()) {\n <!-- ========= Experimental cell-level grid navigation (aria ngGrid) ========= -->\n <!--\n Opt-in via [cellNavigation]=\"true\" (non-virtual only). The aria Grid pattern owns\n roving focus, arrow/Home/End navigation across cells, and aria-activedescendant.\n Only the data <tbody> rows/cells are registered as grid rows/cells; header cells\n stay outside grid navigation. Interactive cells (edit inputs, action buttons)\n expose an ngGridCellWidget so Enter pauses grid nav to interact and Escape resumes.\n -->\n <table\n ngGrid\n rowWrap=\"nowrap\"\n colWrap=\"nowrap\"\n class=\"mlv-data-table__table\"\n [class.mlv-data-table__table--striped]=\"striped()\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.table-layout]=\"resizedTableWidth() === null ? null : 'fixed'\"\n role=\"grid\"\n #tableEl\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <thead\n class=\"mlv-data-table__head\"\n [class.mlv-data-table__head--sticky]=\"stickyHeader()\"\n >\n <ng-container [ngTemplateOutlet]=\"headRowsTpl\" />\n </thead>\n\n <tbody class=\"mlv-data-table__body\">\n @if (showError()) {\n <ng-container [ngTemplateOutlet]=\"errorRowTpl\" />\n } @else if (flatRows().length === 0) {\n <ng-container [ngTemplateOutlet]=\"noDataRowTpl\" />\n } @else { @for (row of flatRows(); track $index; let i = $index) {\n <tr\n ngGridRow\n class=\"mlv-data-table__row mlv-data-table__row--data\"\n [class.mlv-data-table__row--expanded]=\"isRowExpanded(row)\"\n [class.mlv-data-table__row--editing]=\"isEditing(i)\"\n [class.mlv-data-table__row--selected]=\"isRowSelected(row)\"\n [attr.aria-level]=\"getDepth(row) > 0 ? getDepth(row) + 1 : null\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row) : null\"\n [attr.data-row-index]=\"i\"\n (click)=\"onRowClick(row, i, $event)\"\n >\n @if (selectable()) {\n <td\n ngGridCell\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n >\n <mlv-checkbox\n [checked]=\"isRowSelected(row)\"\n [tabbable]=\"false\"\n (checkedChange)=\"toggleRowSelection(row)\"\n (click)=\"$event.stopPropagation()\"\n [ariaLabel]=\"'Select row ' + (i + 1)\"\n />\n </td>\n } @for (col of visibleColumns(); track col.key; let ci = $index) {\n <td\n ngGridCell\n class=\"mlv-data-table__cell mlv-data-table__cell--data\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n >\n @if ( editable() && isEditing(i) && getEditTemplate(col.key); as\n editTpl ) {\n <div\n ngGridCellWidget\n widgetType=\"editable\"\n class=\"mlv-data-table__cell-content\"\n >\n <ng-container\n [ngTemplateOutlet]=\"editTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n </div>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"cellContentTpl\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n col: col,\n ci: ci,\n }\"\n />\n }\n </td>\n } @if (editable()) {\n <td\n ngGridCell\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n >\n <div\n ngGridCellWidget\n widgetType=\"complex\"\n class=\"mlv-data-table__cell-content mlv-data-table__actions\"\n >\n <ng-container\n [ngTemplateOutlet]=\"actionsButtonsTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n </td>\n }\n </tr>\n } }\n </tbody>\n\n @if (getFooterTemplate(); as footerTpl) {\n <tfoot\n class=\"mlv-data-table__foot\"\n [class.mlv-data-table__foot--sticky]=\"stickyHeader()\"\n >\n <tr class=\"mlv-data-table__row mlv-data-table__row--footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: visibleColumns() }\"\n />\n </tr>\n </tfoot>\n }\n </table>\n\n @if (paginationMode() === 'infinite' && loading()) {\n <div\n class=\"mlv-data-table__loading-bottom\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <mlv-loader\n variant=\"circle\"\n [indeterminate]=\"true\"\n [size]=\"24\"\n ariaLabel=\"Loading more rows\"\n />\n </div>\n } } @else {\n <!-- ==================== Standard (non-virtual) mode ==================== -->\n <table\n class=\"mlv-data-table__table\"\n [class.mlv-data-table__table--striped]=\"striped()\"\n [class.mlv-data-table__table--bordered]=\"bordered()\"\n [style.width.px]=\"resizedTableWidth()\"\n [style.table-layout]=\"resizedTableWidth() === null ? null : 'fixed'\"\n role=\"grid\"\n #tableEl\n >\n <ng-container [ngTemplateOutlet]=\"colgroupTpl\" />\n <thead\n class=\"mlv-data-table__head\"\n [class.mlv-data-table__head--sticky]=\"stickyHeader()\"\n >\n <ng-container [ngTemplateOutlet]=\"headRowsTpl\" />\n </thead>\n\n <tbody class=\"mlv-data-table__body\">\n @if (showError()) {\n <ng-container [ngTemplateOutlet]=\"errorRowTpl\" />\n } @else if (flatRows().length === 0) {\n <ng-container [ngTemplateOutlet]=\"noDataRowTpl\" />\n } @else { @for (row of flatRows(); track $index; let i = $index) {\n <tr\n class=\"mlv-data-table__row mlv-data-table__row--data\"\n [class.mlv-data-table__row--expanded]=\"isRowExpanded(row)\"\n [class.mlv-data-table__row--editing]=\"isEditing(i)\"\n [class.mlv-data-table__row--selected]=\"isRowSelected(row)\"\n [attr.aria-level]=\"getDepth(row) > 0 ? getDepth(row) + 1 : null\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row) : null\"\n [attr.tabindex]=\"_rowTabIndex(i)\"\n [attr.data-row-index]=\"i\"\n (click)=\"onRowClick(row, i, $event)\"\n (focus)=\"_onRowFocus(i)\"\n (keydown)=\"_onRowKeydown(i, row, $event)\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowCellsTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n </tr>\n } }\n </tbody>\n\n @if (getFooterTemplate(); as footerTpl) {\n <tfoot\n class=\"mlv-data-table__foot\"\n [class.mlv-data-table__foot--sticky]=\"stickyHeader()\"\n >\n <tr class=\"mlv-data-table__row mlv-data-table__row--footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: visibleColumns() }\"\n />\n </tr>\n </tfoot>\n }\n </table>\n\n @if (paginationMode() === 'infinite' && loading()) {\n <div\n class=\"mlv-data-table__loading-bottom\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n >\n <mlv-loader\n variant=\"circle\"\n [indeterminate]=\"true\"\n [size]=\"24\"\n ariaLabel=\"Loading more rows\"\n />\n </div>\n } }\n</div>\n\n@if (paginationMode() === 'paged' && !virtualScroll()) {\n<div class=\"mlv-data-table__footer\">\n <mlv-pagination\n [totalItems]=\"totalItems()\"\n [currentPage]=\"currentPage()\"\n [itemsPerPage]=\"currentPerPage()\"\n (currentPageChange)=\"_onPageChange($event)\"\n (itemsPerPageChange)=\"_onPerPageChange($event)\"\n />\n</div>\n} @if (paginationMode() === 'paged' && loading()) {\n<div\n class=\"mlv-data-table__loading-overlay\"\n aria-live=\"polite\"\n aria-busy=\"true\"\n>\n <mlv-loader\n variant=\"circle\"\n [indeterminate]=\"true\"\n [size]=\"48\"\n ariaLabel=\"Loading table data\"\n />\n</div>\n}\n\n<!-- ==================== Reusable templates ==================== -->\n\n<!--\n Shared <colgroup> template \u2014 used by both the standard table and the three split tables in\n virtual mode (header / body / footer). Keeping the colgroup definitions identical and combining\n it with `table-layout: fixed` keeps column widths in sync between the split tables in virtual mode.\n-->\n<ng-template #colgroupTpl>\n <colgroup>\n @if (selectable() === 'multi' || selectable() === 'single') {\n <col\n class=\"mlv-data-table__col--select\"\n [style.width]=\"getAuxiliaryColumnWidth('selection')\"\n />\n } @for (col of visibleColumns(); track col.key) {\n <col [style.width]=\"getColWidth(col)\" />\n } @if (editable()) {\n <col\n class=\"mlv-data-table__col--actions\"\n [style.width]=\"getAuxiliaryColumnWidth('actions')\"\n />\n }\n </colgroup>\n</ng-template>\n\n<!-- Header rows \u2014 emits the same content the original `<thead>` did. -->\n<ng-template #headRowsTpl>\n @if (hasColumnGroups()) {\n <!-- Group header row -->\n <tr class=\"mlv-data-table__row mlv-data-table__row--group-header\">\n @if (selectable() === 'multi') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n rowspan=\"2\"\n >\n <mlv-checkbox\n [checked]=\"allRowsSelected()\"\n [indeterminate]=\"someRowsSelected()\"\n (checkedChange)=\"toggleSelectAll()\"\n [ariaLabel]=\"_i18n().selectAllRows\"\n />\n </th>\n } @else if (selectable() === 'single') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n rowspan=\"2\"\n ></th>\n } @for (col of visibleColumns(); track col.key) { @if (headerLayout(); as\n layout) { @if (layout.standaloneKeys.has(col.key)) {\n <!-- Standalone column spans both header rows -->\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--standalone\"\n [class.mlv-data-table__cell--sortable]=\"col.sortable\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n [attr.data-mlv-column-key]=\"col.key\"\n rowspan=\"2\"\n scope=\"col\"\n [attr.aria-sort]=\"\n col.sortable\n ? getSortDirection(col) === 'asc'\n ? 'ascending'\n : getSortDirection(col) === 'desc'\n ? 'descending'\n : 'none'\n : null\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"headerCellInnerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n </th>\n } @else {\n <!-- Check if this column is the first column of a group -->\n @for (group of columnGroups(); track group.title) { @if (group.columns[0]\n === col.key) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--group-header\"\n [class.mlv-data-table__cell--align-left]=\"\n group.align === 'left'\n \"\n [class.mlv-data-table__cell--align-center]=\"\n group.align === 'center' || !group.align\n \"\n [class.mlv-data-table__cell--align-right]=\"\n group.align === 'right'\n \"\n [attr.colspan]=\"group.columns.length\"\n scope=\"colgroup\"\n >\n {{ group.title }}\n </th>\n } } } } } @if (editable()) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n rowspan=\"2\"\n >\n <span class=\"mlv-data-table__visually-hidden\"\n >{{ actionsHeaderLabel() }}</span\n >\n </th>\n }\n </tr>\n <!-- Sub-header row for grouped columns -->\n <tr class=\"mlv-data-table__row mlv-data-table__row--header\">\n @for (col of visibleColumns(); track col.key) { @if (headerLayout(); as\n layout) { @if (layout.groupedKeys.has(col.key)) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header\"\n [class.mlv-data-table__cell--sortable]=\"col.sortable\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n [attr.data-mlv-column-key]=\"col.key\"\n scope=\"col\"\n [attr.aria-sort]=\"\n col.sortable\n ? getSortDirection(col) === 'asc'\n ? 'ascending'\n : getSortDirection(col) === 'desc'\n ? 'descending'\n : 'none'\n : null\n \"\n >\n <ng-container\n [ngTemplateOutlet]=\"headerCellInnerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n </th>\n } } }\n </tr>\n } @else {\n <!-- Standard single-row header -->\n <tr class=\"mlv-data-table__row mlv-data-table__row--header\">\n @if (selectable() === 'multi') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n >\n <mlv-checkbox\n [checked]=\"allRowsSelected()\"\n [indeterminate]=\"someRowsSelected()\"\n (checkedChange)=\"toggleSelectAll()\"\n [ariaLabel]=\"_i18n().selectAllRows\"\n />\n </th>\n } @else if (selectable() === 'single') {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n ></th>\n } @for (col of visibleColumns(); track col.key) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header\"\n [class.mlv-data-table__cell--sortable]=\"col.sortable\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n [attr.data-mlv-column-key]=\"col.key\"\n [attr.aria-sort]=\"\n col.sortable\n ? getSortDirection(col) === 'asc'\n ? 'ascending'\n : getSortDirection(col) === 'desc'\n ? 'descending'\n : 'none'\n : null\n \"\n scope=\"col\"\n >\n <ng-container\n [ngTemplateOutlet]=\"headerCellInnerTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n </th>\n } @if (editable()) {\n <th\n class=\"mlv-data-table__cell mlv-data-table__cell--header mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n >\n <span class=\"mlv-data-table__visually-hidden\"\n >{{ actionsHeaderLabel() }}</span\n >\n </th>\n }\n </tr>\n }\n</ng-template>\n\n<!--\n Shared inner content for a single header cell. Context: { $implicit: col }.\n Sortable columns wrap the label + sort icon in ONE native <button> (APG grid\n sort pattern) so the <th> stays a non-interactive cell carrying only aria-sort;\n the pin button is a sibling of the sort button, never nested inside it, so no\n interactive control is nested within another (avoids axe `nested-interactive`).\n-->\n<ng-template #headerCellInnerTpl let-col>\n <div class=\"mlv-data-table__cell-inner\">\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"mlv-data-table__sort-button\"\n [attr.aria-label]=\"getSortLabel(col)\"\n (click)=\"onSortClick(col)\"\n >\n <span class=\"mlv-data-table__header-title\"\n >{{ col.title ?? col.key }}</span\n >\n <span class=\"mlv-data-table__sort-icon\" aria-hidden=\"true\">\n @if (getSortDirection(col) === 'asc') {\n <svg lucideArrowUp />\n } @else if (getSortDirection(col) === 'desc') {\n <svg lucideArrowDown />\n } @else {\n <svg lucideChevronsUpDown class=\"mlv-data-table__sort-icon--inactive\" />\n }\n </span>\n </button>\n } @else {\n <span class=\"mlv-data-table__header-title\">{{ col.title ?? col.key }}</span>\n } @if (col.pinnable) {\n <ng-container\n [ngTemplateOutlet]=\"pinButtonTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\"\n />\n } @if (filterDisplay() === 'column' && col.filterable) {\n <button\n mlvButton\n class=\"mlv-data-table__column-filter\"\n [class.mlv-data-table__column-filter--active]=\"\n isColumnFiltered(col.key)\n \"\n [variant]=\"\n columnFilterPopup.opened() || isColumnFiltered(col.key)\n ? 'primary'\n : 'transparent'\n \"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n [attr.data-column-key]=\"col.key\"\n [mlvPopupTrigger]=\"columnFilterPopup\"\n #columnFilterTrigger=\"mlvPopupTrigger\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"getFilterLabel(col)\"\n >\n <svg lucideFunnel mlvButtonIcon [size]=\"14\" />\n </button>\n\n <mlv-popup\n #columnFilterPopup\n panelRole=\"dialog\"\n [ariaLabel]=\"getFilterLabel(col)\"\n (afterClosed)=\"focusColumnFilterTrigger(col.key)\"\n >\n <mlv-dt-filter-dropdown\n *mlvPopupContent\n [columns]=\"getColumnFilterColumns(col)\"\n [activeFilters]=\"activeFilters()\"\n (activeFiltersChange)=\"onColumnFiltersChange(col.key, $event)\"\n (closed)=\"columnFilterTrigger.close()\"\n />\n </mlv-popup>\n }\n </div>\n @if (col.resizable) {\n <div\n #resizeHandle\n class=\"mlv-data-table__resize-handle\"\n [attr.data-column-key]=\"col.key\"\n role=\"separator\"\n tabindex=\"0\"\n aria-orientation=\"vertical\"\n [attr.aria-label]=\"getColumnResizeLabel(col)\"\n [attr.aria-valuenow]=\"getColumnResizeValue(col)\"\n [attr.aria-valuemin]=\"getColumnResizeMin(col)\"\n [attr.aria-valuemax]=\"getColumnResizeMax(col)\"\n [attr.aria-valuetext]=\"getColumnResizeValueText(col)\"\n (pointerdown)=\"onResizeStart(col, $event)\"\n (keydown)=\"onColumnResizeKeydown(col, $event)\"\n (dblclick)=\"resetColumnWidth(col.key)\"\n ></div>\n }\n</ng-template>\n\n<!-- No-data fallback row, used by both rendering paths. -->\n<ng-template #noDataRowTpl>\n <tr class=\"mlv-data-table__row mlv-data-table__row--no-data\">\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--no-data\"\n [attr.colspan]=\"totalColumnCount()\"\n >\n @if (getNoDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"getNoDataTemplate()!\" />\n } @else {\n <div class=\"mlv-data-table__no-data-default\">\n <svg lucideTable2 [size]=\"40\" aria-hidden=\"true\" />\n <span>No data available</span>\n </div>\n }\n </td>\n </tr>\n</ng-template>\n\n<!--\n Failed-request row, used by all three rendering paths. Takes precedence over both the\n data rows and #noDataRowTpl so a failed request never reads as an empty result set.\n The region is announced as an alert; the default block is an mlv-empty-state with a\n danger-toned icon and a Retry button wired to the (retry) output.\n-->\n<ng-template #errorRowTpl>\n <tr class=\"mlv-data-table__row mlv-data-table__row--error\">\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--error\"\n [attr.colspan]=\"totalColumnCount()\"\n >\n <div class=\"mlv-data-table__error\" role=\"alert\" aria-live=\"assertive\">\n @if (getErrorTemplate(); as errorTpl) {\n <ng-container\n [ngTemplateOutlet]=\"errorTpl\"\n [ngTemplateOutletContext]=\"_errorContext()\"\n />\n } @else {\n <mlv-empty-state>\n <svg\n mlvEmptyStateIcon\n lucideTriangleAlert\n class=\"mlv-data-table__error-icon\"\n [size]=\"40\"\n aria-hidden=\"true\"\n />\n <span mlvEmptyStateTitle>{{ _i18n().errorTitle }}</span>\n <span mlvEmptyStateDescription>{{ errorMessage() }}</span>\n <button\n mlvEmptyStateActions\n mlvButton\n variant=\"secondary\"\n type=\"button\"\n class=\"mlv-data-table__error-retry\"\n (click)=\"onRetry()\"\n >\n {{ _i18n().retry }}\n </button>\n </mlv-empty-state>\n }\n </div>\n </td>\n </tr>\n</ng-template>\n\n<!--\n Per-row data cells. Emits the selection cell, the data cells, and the actions cell.\n The owning <tr> stays at the consumer site (either inside `@for` for the standard mode\n or `*cdkVirtualFor` inside the CDK viewport in virtual mode), so each rendering path can\n control its own row-level host bindings.\n-->\n<ng-template #rowCellsTpl let-row let-i=\"index\">\n @if (selectable()) {\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--select\"\n [style]=\"getAuxiliaryColumnStyle('selection')\"\n >\n <!--\n [tabbable]=\"false\" keeps this checkbox out of the tab order so the row is\n the single tab stop: the row's Space/Enter toggles selection, and the\n checkbox stays operable via the mouse. Avoids a per-row double tab stop.\n -->\n <mlv-checkbox\n [checked]=\"isRowSelected(row)\"\n [tabbable]=\"false\"\n (checkedChange)=\"toggleRowSelection(row)\"\n (click)=\"$event.stopPropagation()\"\n [ariaLabel]=\"'Select row ' + (i + 1)\"\n />\n </td>\n } @for (col of visibleColumns(); track col.key; let ci = $index) {\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--data\"\n [class.mlv-data-table__cell--pinned]=\"col.pinned\"\n [class.mlv-data-table__cell--pinned-left]=\"\n col.pinned && col.pinSide !== 'right'\n \"\n [class.mlv-data-table__cell--pinned-right]=\"\n col.pinned && col.pinSide === 'right'\n \"\n [class]=\"getAlignClass(col)\"\n [style]=\"getCellStyle(col)\"\n >\n <ng-container\n [ngTemplateOutlet]=\"cellContentTpl\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n col: col,\n ci: ci,\n }\"\n />\n </td>\n } @if (editable()) {\n <td\n class=\"mlv-data-table__cell mlv-data-table__cell--data mlv-data-table__cell--actions\"\n [style]=\"getAuxiliaryColumnStyle('actions')\"\n >\n <div class=\"mlv-data-table__cell-content mlv-data-table__actions\">\n <ng-container\n [ngTemplateOutlet]=\"actionsButtonsTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n </td>\n }\n</ng-template>\n\n<!--\n Shared edit/save/cancel action buttons for the actions column. Context: { $implicit: row, index: i }.\n-->\n<ng-template #actionsButtonsTpl let-row let-i=\"index\">\n @if (isEditing(i)) {\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"saveEdit(row, i)\"\n [attr.aria-label]=\"_i18n().saveChanges\"\n >\n <svg lucideCheck mlvButtonIcon />\n </button>\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"cancelEdit(row, i)\"\n [attr.aria-label]=\"_i18n().cancelEditing\"\n >\n <svg lucideX mlvButtonIcon />\n </button>\n } @else {\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n (click)=\"startEdit(row, i)\"\n [attr.aria-label]=\"_i18n().editRow\"\n >\n <svg lucidePencil mlvButtonIcon />\n </button>\n }\n</ng-template>\n\n<!--\n Shared inner content of a data cell (indent, expand button, edit/display template, raw value).\n Extracted so both the standard `#rowCellsTpl` `<td>` and the experimental cell-navigation grid\n `<td ngGridCell>` render identical content. Purely presentational \u2014 contains no aria grid\n directives \u2014 so it is safe to project via ngTemplateOutlet across the grid-cell boundary.\n Context: { $implicit: row, index: i, col, ci }.\n-->\n<ng-template #cellContentTpl let-row let-i=\"index\" let-col=\"col\" let-ci=\"ci\">\n <div class=\"mlv-data-table__cell-content\">\n @if (ci === 0 && getDepth(row) > 0) {\n <span\n class=\"mlv-data-table__indent\"\n [style.padding-left.rem]=\"getDepth(row) * 1.25\"\n aria-hidden=\"true\"\n ></span>\n } @if (ci === 0 && hasChildren(row)) {\n <button\n mlvButton\n variant=\"transparent\"\n shape=\"square\"\n mlvDensity=\"tight\"\n type=\"button\"\n class=\"mlv-data-table__expand-btn\"\n (click)=\"toggleExpand(row, $event)\"\n [attr.aria-expanded]=\"isRowExpanded(row)\"\n [attr.aria-label]=\"\n isRowExpanded(row) ? _i18n().collapseRow : _i18n().expandRow\n \"\n >\n <svg\n lucideChevronRight\n mlvButtonIcon\n class=\"mlv-data-table__expand-icon\"\n [class.mlv-data-table__expand-icon--open]=\"isRowExpanded(row)\"\n />\n </button>\n } @if (editable() && isEditing(i) && getEditTemplate(col.key); as editTpl) {\n <ng-container\n [ngTemplateOutlet]=\"editTpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n } @else if (getTemplate(col.key); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"getCellContext(row, i)\"\n />\n } @else {\n <!--\n Default cell renderer. `valueLabels` (or the `filterConfig.options` fallback)\n maps the raw value to a label; `tone` promotes the cell to a muted badge.\n -->\n @if (getCellTone(row, col); as tone) {\n <mlv-badge [tone]=\"tone\" muted\n >{{ getCellDisplayValue(row, col) }}</mlv-badge\n >\n } @else { {{ getCellDisplayValue(row, col) }} } }\n </div>\n</ng-template>\n\n<!-- Reusable pin button template. Rendered via ngTemplateOutlet from every header cell that supports pinning. -->\n<ng-template #pinButtonTpl let-col>\n @if (getPinnableSides(col); as sides) { @if (sides.length > 1) {\n <button\n class=\"mlv-data-table__pin-btn\"\n [class.mlv-data-table__pin-btn--active]=\"isColumnPinned(col)\"\n type=\"button\"\n [mlvPopupTrigger]=\"pinPopup\"\n #pinTrigger=\"mlvPopupTrigger\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"\n isColumnPinned(col) ? _i18n().changePinSide : _i18n().pinColumn\n \"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"pinPopup.opened()\"\n [attr.aria-pressed]=\"isColumnPinned(col)\"\n >\n @if (isColumnPinned(col)) {\n <svg lucidePinOff />\n } @else {\n <svg lucidePin />\n }\n </button>\n <mlv-popup #pinPopup>\n <div *mlvPopupContent class=\"mlv-data-table__pin-popup\" role=\"menu\">\n @for (side of sides; track side) {\n <button\n type=\"button\"\n role=\"menuitemradio\"\n class=\"mlv-data-table__pin-popup-item\"\n [class.mlv-data-table__pin-popup-item--active]=\"\n getColumnPinSide(col) === side\n \"\n [attr.aria-checked]=\"getColumnPinSide(col) === side\"\n (click)=\"\n pinTo(col, side); pinTrigger.close(); $event.stopPropagation()\n \"\n >\n <svg lucidePin [size]=\"14\" />\n @if (side === 'left') {\n <span>Pin left</span>\n } @else {\n <span>Pin right</span>\n }\n </button>\n } @if (isColumnPinned(col)) {\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"mlv-data-table__pin-popup-item mlv-data-table__pin-popup-item--unpin\"\n (click)=\"unpin(col); pinTrigger.close(); $event.stopPropagation()\"\n >\n <svg lucidePinOff [size]=\"14\" />\n <span>{{ _i18n().unpin }}</span>\n </button>\n }\n </div>\n </mlv-popup>\n } @else {\n <button\n class=\"mlv-data-table__pin-btn\"\n [class.mlv-data-table__pin-btn--active]=\"isColumnPinned(col)\"\n type=\"button\"\n (click)=\"togglePin(col, sides[0]); $event.stopPropagation()\"\n [attr.aria-label]=\"\n isColumnPinned(col) ? _i18n().unpinColumn : _i18n().pinColumn\n \"\n [attr.aria-pressed]=\"isColumnPinned(col)\"\n >\n @if (isColumnPinned(col)) {\n <svg lucidePinOff />\n } @else {\n <svg lucidePin />\n }\n </button>\n } }\n</ng-template>\n", styles: ["@layer mlv.components{.mlv-data-table{box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-dt-font-size)}.mlv-data-table *{box-sizing:border-box}.mlv-data-table{--mlv-dt-row-height: calc(var(--mlv-height-m) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1.25rem;--mlv-dt-header-height: 3rem;--mlv-dt-font-size: var(--mlv-font-size-m);--mlv-dt-header-font-size: var(--mlv-font-size-m);--mlv-dt-icon-size: 1rem;--mlv-dt-toolbar-gap: .5rem;--mlv-dt-toolbar-padding: .75rem 0;display:flex;flex-direction:column;width:100%;position:relative;color:var(--mlv-text-primary)}[class*=--tight] .mlv-data-table:not([class*=--compact],[class*=--comfortable],[class*=--spacious],[class*=--airy]),.mlv-data-table[class*=--tight]{--mlv-dt-row-height: calc(var(--mlv-height-xs) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: .75rem;--mlv-dt-header-height: 2.25rem;--mlv-dt-font-size: var(--mlv-font-size-s);--mlv-dt-header-font-size: var(--mlv-font-size-s);--mlv-dt-icon-size: .75rem;--mlv-dt-toolbar-gap: .25rem;--mlv-dt-toolbar-padding: .375rem 0}[class*=--compact] .mlv-data-table:not([class*=--tight],[class*=--comfortable],[class*=--spacious],[class*=--airy]),.mlv-data-table[class*=--compact]{--mlv-dt-row-height: calc(var(--mlv-height-s) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1rem;--mlv-dt-header-height: 2.5rem;--mlv-dt-font-size: var(--mlv-font-size-s);--mlv-dt-header-font-size: var(--mlv-font-size-s);--mlv-dt-icon-size: .875rem;--mlv-dt-toolbar-gap: .375rem;--mlv-dt-toolbar-padding: .5rem 0}[class*=--spacious] .mlv-data-table:not([class*=--tight],[class*=--compact],[class*=--comfortable],[class*=--airy]),.mlv-data-table[class*=--spacious]{--mlv-dt-row-height: calc(var(--mlv-height-l) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1.5rem;--mlv-dt-header-height: 3.25rem;--mlv-dt-font-size: var(--mlv-font-size-l);--mlv-dt-header-font-size: var(--mlv-font-size-l);--mlv-dt-icon-size: 1.125rem;--mlv-dt-toolbar-gap: .75rem;--mlv-dt-toolbar-padding: .75rem 0}[class*=--airy] .mlv-data-table:not([class*=--tight],[class*=--compact],[class*=--comfortable],[class*=--spacious]),.mlv-data-table[class*=--airy]{--mlv-dt-row-height: calc(var(--mlv-height-xl) + var(--mlv-spacing-4));--mlv-dt-cell-padding-x: 1.75rem;--mlv-dt-header-height: 3.75rem;--mlv-dt-font-size: var(--mlv-font-size-l);--mlv-dt-header-font-size: var(--mlv-font-size-l);--mlv-dt-icon-size: 1.25rem;--mlv-dt-toolbar-gap: 1rem;--mlv-dt-toolbar-padding: 1rem 0}.mlv-data-table__toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:var(--mlv-dt-toolbar-gap);padding:var(--mlv-dt-toolbar-padding);position:relative}.mlv-data-table__search{flex:1 1 16rem;width:min(100%,24rem);max-width:24rem}.mlv-data-table__toolbar-actions{display:flex;gap:var(--mlv-dt-toolbar-gap);margin-inline-start:auto}.mlv-data-table__filter-badge{font-size:var(--mlv-dt-font-size);color:var(--mlv-text-secondary)}.mlv-data-table__wrapper{width:100%;overflow-x:auto;overflow-y:auto;position:relative}.mlv-data-table__wrapper--virtual{overflow-y:visible;display:flex;flex-direction:column}.mlv-data-table__virtual-viewport{display:block;width:100%;min-width:0;max-width:100%;flex:0 0 auto;position:sticky;inset-inline-start:0;border-bottom:.0625rem solid var(--mlv-border-subtle)}.mlv-data-table__virtual-viewport.cdk-virtual-scrollable{overflow-x:hidden;overflow-y:auto}.mlv-data-table__virtual-horizontal-sizer{width:0;height:0;min-height:0;flex:0 0 0;align-self:flex-start;pointer-events:none}.mlv-data-table__table--virtual-header,.mlv-data-table__table--virtual-footer{--mlv-dt-pinned-right-correction: var( --mlv-dt-virtual-scrollbar-gutter, 0px )}.mlv-data-table__loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--mlv-background-base) 70%,transparent);-webkit-backdrop-filter:blur(.0625rem);backdrop-filter:blur(.0625rem);z-index:20;pointer-events:all}.mlv-data-table__loading-bottom{display:flex;align-items:center;justify-content:center;padding:1rem 0;color:var(--mlv-text-secondary)}.mlv-data-table__table{width:100%;border-collapse:collapse;table-layout:auto;font-size:var(--mlv-dt-font-size);color:var(--mlv-text-primary)}.mlv-data-table__table--striped .mlv-data-table__row--data:nth-child(2n){background:var(--mlv-background-sunken)}.mlv-data-table__table--striped .mlv-data-table__row--data:nth-child(2n) .mlv-data-table__cell--pinned{background:var(--mlv-background-sunken)}.mlv-data-table__table--bordered .mlv-data-table__cell{border-inline-end:.0625rem solid var(--mlv-border-subtle)}.mlv-data-table__table--bordered .mlv-data-table__cell:last-child{border-inline-end:none}.mlv-data-table__table--virtual{table-layout:fixed}.mlv-data-table__head--sticky{position:sticky;top:var(--mlv-dt-sticky-top, 0);z-index:3;background:var(--mlv-background-base)}.mlv-data-table__head--sticky .mlv-data-table__cell--pinned{z-index:4}.mlv-data-table__cell{padding:0;border-bottom:.0625rem solid var(--mlv-border-subtle);vertical-align:middle;background:inherit}.mlv-data-table__cell-content{display:flex;align-items:center;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mlv-data-table__cell--header{font-weight:var(--mlv-font-weight-medium);font-size:var(--mlv-dt-header-font-size);color:color-mix(in srgb,var(--mlv-text-action) 65%,var(--mlv-text-secondary));position:relative;-webkit-user-select:none;user-select:none;border-bottom:.0625rem solid var(--mlv-border-normal)}.mlv-data-table__cell--sortable{cursor:pointer}.mlv-data-table__cell--sortable:hover .mlv-data-table__cell-inner{color:var(--mlv-text-action)}.mlv-data-table__cell--data{padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-row-height);font-size:var(--mlv-dt-font-size)}.mlv-data-table__cell--pinned{background:var(--mlv-background-base);z-index:1;transition:background var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__cell--pinned:after{content:\"\";position:absolute;top:0;bottom:0;width:.5rem;pointer-events:none}.mlv-data-table__cell--pinned-left:after{inset-inline-end:-.5rem;background:linear-gradient(to right,rgba(0,0,0,.04),transparent)}.mlv-data-table__cell--pinned-right:after{inset-inline-start:-.5rem;background:linear-gradient(to left,rgba(0,0,0,.04),transparent)}.mlv-data-table__cell--no-data,.mlv-data-table__cell--error{padding:3rem var(--mlv-dt-cell-padding-x);text-align:center}.mlv-data-table__cell--align-left{text-align:start}.mlv-data-table__cell--align-center{text-align:center}.mlv-data-table__cell--align-right{text-align:end}.mlv-data-table__cell-inner{display:flex;align-items:center;gap:.375rem;padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-header-height);transition:color var(--mlv-duration-normal) var(--mlv-ease-default);border-radius:var(--mlv-radius-s)}.mlv-data-table__sort-button{display:inline-flex;align-items:center;gap:.375rem;flex:1;min-width:0;margin:0;padding:0;border:none;background:none;font:inherit;color:inherit;text-align:start;cursor:pointer;border-radius:var(--mlv-radius-s)}.mlv-data-table__sort-button:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:var(--mlv-focus-ring-offset)}.mlv-data-table__visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;padding:0;margin:-1px}.mlv-data-table__header-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:start}.mlv-data-table__column-filter{flex:0 0 auto}.mlv-data-table__column-filter--active{color:var(--mlv-text-action)}.mlv-data-table__sort-icon{display:inline-flex;flex-shrink:0;color:var(--mlv-text-action)}.mlv-data-table__sort-icon svg{width:var(--mlv-dt-icon-size);height:var(--mlv-dt-icon-size)}.mlv-data-table__sort-icon--inactive{opacity:0;transition:opacity var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__cell--sortable:hover .mlv-data-table__sort-icon--inactive{opacity:.5}.mlv-data-table__pin-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;background:none;cursor:pointer;color:var(--mlv-text-tertiary);opacity:0;transition:opacity var(--mlv-duration-normal) var(--mlv-ease-default),color var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__pin-btn svg{width:var(--mlv-dt-icon-size);height:var(--mlv-dt-icon-size)}.mlv-data-table__cell--header:hover .mlv-data-table__pin-btn{opacity:.6}.mlv-data-table__pin-btn:hover{opacity:1!important;color:var(--mlv-text-action)}.mlv-data-table__pin-btn--active{opacity:1;color:var(--mlv-text-action)}.mlv-data-table__cell--header:hover .mlv-data-table__pin-btn--active{opacity:1}.mlv-data-table__resize-handle{position:absolute;top:0;inset-inline-end:-.5rem;width:1rem;height:100%;cursor:col-resize;background:transparent;z-index:5;touch-action:none;-webkit-user-select:none;user-select:none}.mlv-data-table__resize-handle:after{content:\"\";position:absolute;top:.75rem;bottom:.75rem;left:50%;width:.0625rem;border-radius:var(--mlv-radius-full);background-color:var(--mlv-text-tertiary);transform:translate(-50%);transition:background-color var(--mlv-duration-fast) var(--mlv-ease-default),width var(--mlv-duration-fast) var(--mlv-ease-default)}.mlv-data-table__resize-handle:hover:after{width:.125rem;background-color:var(--mlv-background-accent-1)}.mlv-data-table__resize-handle:active:after,.mlv-data-table__resize-handle:focus-visible:after{width:.125rem;background-color:var(--mlv-background-accent-1)}.mlv-data-table__resize-handle:focus-visible{outline:var(--mlv-stroke-width-medium) solid var(--mlv-border-focus);outline-offset:calc(var(--mlv-focus-ring-offset) * -1)}@media(pointer:coarse){.mlv-data-table__resize-handle{inset-inline-end:-.75rem;width:1.5rem}}.mlv-data-table__row{transition:background var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__row--data:hover,.mlv-data-table__row--data:hover .mlv-data-table__cell--pinned{background:var(--mlv-background-neutral-1-hover)}.mlv-data-table__row--expanded,.mlv-data-table__row--expanded .mlv-data-table__cell--pinned{background:var(--mlv-background-sunken)}.mlv-data-table__indent{display:inline-block}.mlv-data-table__expand-btn{margin-inline-end:.25rem;vertical-align:middle;flex-shrink:0}.mlv-data-table__expand-icon{width:var(--mlv-dt-icon-size);height:var(--mlv-dt-icon-size);transition:transform var(--mlv-duration-normal) var(--mlv-ease-default)}.mlv-data-table__expand-icon--open{transform:rotate(90deg)}.mlv-data-table__no-data-default{display:flex;flex-direction:column;align-items:center;gap:.75rem;padding:3rem 0;color:var(--mlv-text-secondary)}.mlv-data-table__no-data-default svg{opacity:.2}.mlv-data-table__no-data-default span{font-size:var(--mlv-dt-font-size)}.mlv-data-table__error{display:block;text-align:initial}.mlv-data-table__error-icon{color:var(--mlv-text-negative)}.mlv-data-table__row--group-header .mlv-data-table__cell--group-header{font-weight:var(--mlv-font-weight-medium);font-size:var(--mlv-dt-header-font-size);color:color-mix(in srgb,var(--mlv-text-action) 65%,var(--mlv-text-secondary));text-align:center;padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-header-height);border-bottom:.0625rem solid var(--mlv-border-subtle);vertical-align:middle}.mlv-data-table__row--group-header .mlv-data-table__cell--standalone{vertical-align:middle}.mlv-data-table__cell--actions{width:1%;white-space:nowrap;padding:0 var(--mlv-dt-cell-padding-x)!important}.mlv-data-table__actions{display:flex;align-items:center;gap:.25rem;justify-content:flex-end}.mlv-data-table__row--editing,.mlv-data-table__row--editing .mlv-data-table__cell--pinned{background:var(--mlv-background-sunken)}.mlv-data-table__cell--select{width:2.5rem;min-width:2.5rem;max-width:2.5rem;padding:0 .5rem!important;text-align:center}.mlv-data-table__col--select{width:2.5rem}.mlv-data-table__col--actions{width:5rem}.mlv-data-table__row--selected,.mlv-data-table__row--selected .mlv-data-table__cell--pinned{background:color-mix(in srgb,var(--mlv-background-accent-1) 8%,var(--mlv-background-base))}.mlv-data-table__pin-popup{display:flex;flex-direction:column;gap:.125rem;padding:.25rem;min-width:8rem}.mlv-data-table__pin-popup-item{display:flex;align-items:center;gap:.5rem;padding:.375rem .5rem;border:none;background:none;border-radius:var(--mlv-radius-s);cursor:pointer;font:inherit;font-size:var(--mlv-dt-font-size);color:var(--mlv-text-primary);text-align:start}.mlv-data-table__pin-popup-item svg{color:var(--mlv-text-secondary);flex-shrink:0}.mlv-data-table__pin-popup-item:hover{background:var(--mlv-background-sunken)}.mlv-data-table__pin-popup-item--active{color:var(--mlv-text-action)}.mlv-data-table__pin-popup-item--active svg{color:var(--mlv-text-action)}.mlv-data-table__pin-popup-item--unpin{color:var(--mlv-text-negative);border-top:.0625rem solid var(--mlv-border-subtle);margin-top:.125rem;padding-top:.5rem;border-radius:0 0 var(--mlv-radius-s) var(--mlv-radius-s)}.mlv-data-table__pin-popup-item--unpin svg{color:var(--mlv-text-negative)}.mlv-data-table__pin-popup-item--unpin:hover{background:color-mix(in srgb,var(--mlv-text-negative) 8%,transparent)}.mlv-data-table__columns-dropdown{display:flex;flex-direction:column;gap:.25rem;padding:.5rem;min-width:10rem}.mlv-data-table__columns-item{display:flex;align-items:center;gap:.5rem;padding:.25rem .5rem;border-radius:var(--mlv-radius-s);cursor:pointer;font-size:var(--mlv-dt-font-size)}.mlv-data-table__columns-item:hover{background:var(--mlv-background-sunken)}.mlv-data-table__foot{font-weight:var(--mlv-font-weight-medium);font-size:var(--mlv-dt-font-size);background:var(--mlv-background-base)}.mlv-data-table__foot--sticky{position:sticky;bottom:0;z-index:3}.mlv-data-table__foot .mlv-data-table__cell--pinned,.mlv-data-table__row--footer{background:inherit}.mlv-data-table__row--footer>:where(td,th){box-sizing:border-box;padding:0 var(--mlv-dt-cell-padding-x);height:var(--mlv-dt-header-height);border-top:.125rem solid var(--mlv-border-normal);border-bottom:0;vertical-align:middle;background:inherit;font-size:inherit;font-weight:inherit}.mlv-data-table__table--bordered .mlv-data-table__row--footer>:where(td,th){border-inline-end:.0625rem solid var(--mlv-border-subtle)}.mlv-data-table__table--bordered .mlv-data-table__row--footer>:where(td,th):last-child{border-inline-end:none}.mlv-data-table__footer{padding-top:.75rem}@media(prefers-reduced-motion:reduce){.mlv-data-table,.mlv-data-table *,.mlv-data-table:before,.mlv-data-table:after,[class^=mlv-data-table__],[class*=\" mlv-data-table__\"],[class^=mlv-data-table--],[class*=\" mlv-data-table--\"]{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:var(--mlv-duration-instant)!important}}}\n"] }]
2677
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], columnGroups: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnGroups", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], editMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editMode", required: false }] }], addRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "addRow", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], actionsHeaderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsHeaderLabel", required: false }] }], cellNavigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellNavigation", required: false }] }], paginationMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationMode", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], infiniteScrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "infiniteScrollThreshold", required: false }] }], filterDisplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterDisplay", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], showSortMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSortMenu", required: false }] }], searchTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTrigger", required: false }] }], searchDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchDebounce", required: false }] }], rowEditStart: [{ type: i0.Output, args: ["rowEditStart"] }], rowEditSave: [{ type: i0.Output, args: ["rowEditSave"] }], rowEditCancel: [{ type: i0.Output, args: ["rowEditCancel"] }], rowAdd: [{ type: i0.Output, args: ["rowAdd"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], retry: [{ type: i0.Output, args: ["retry"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], presentationStateChange: [{ type: i0.Output, args: ["presentationStateChange"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], selectedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedRows", required: false }] }, { type: i0.Output, args: ["selectedRowsChange"] }], searchQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchQuery", required: false }] }, { type: i0.Output, args: ["searchQueryChange"] }], cellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvDataTableCell), { ...{
2678
+ descendants: true,
2679
+ }, isSignal: true }] }], editCellTemplates: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvDataTableEditCell), { ...{
2680
+ descendants: true,
2681
+ }, isSignal: true }] }], noDataTemplate: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvDataTableNoData), { ...{
2682
+ descendants: true,
2683
+ }, isSignal: true }] }], errorTemplate: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvDataTableError), { ...{
2684
+ descendants: true,
2685
+ }, isSignal: true }] }], footerTemplate: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MlvDataTableFooter), { ...{
2686
+ descendants: true,
2687
+ }, isSignal: true }] }], _toolbarActions: [{ type: i0.ContentChild, args: [i0.forwardRef(() => MlvDataTableToolbarActions), { isSignal: true }] }], tableWrapperRef: [{ type: i0.ViewChild, args: ['tableWrapper', { isSignal: true }] }], tableRef: [{ type: i0.ViewChild, args: ['tableEl', { isSignal: true }] }], _resizeHandleRefs: [{ type: i0.ViewChildren, args: ['resizeHandle', { isSignal: true }] }], _filterTriggerRef: [{ type: i0.ViewChild, args: ['filterBtn', { ...{
2688
+ read: ElementRef,
2689
+ }, isSignal: true }] }], _virtualViewportRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], activeFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeFilters", required: false }] }, { type: i0.Output, args: ["activeFiltersChange"] }] } });
2690
+
2691
+ /**
2692
+ * Generated bundle index. Do not edit.
2693
+ */
2694
+
2695
+ export { MlvDataTable, MlvDataTableCell, MlvDataTableEditCell, MlvDataTableError, MlvDataTableFooter, MlvDataTableNoData, MlvDataTableToolbarActions };
2696
+ //# sourceMappingURL=malva-ui-core-data-table.mjs.map