@govbr-ds/webcomponents 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (686) hide show
  1. package/cem/custom-elements.json +4228 -996
  2. package/cem/webcomponents.html-custom-data.json +354 -48
  3. package/dist/cjs/br-avatar.cjs.entry.js +2 -2
  4. package/dist/cjs/br-breadcrumb-item.cjs.entry.js +1 -1
  5. package/dist/cjs/br-breadcrumb.cjs.entry.js +11 -11
  6. package/dist/cjs/br-button_2.cjs.entry.js +5 -5
  7. package/dist/cjs/br-card.cjs.entry.js +2 -2
  8. package/dist/cjs/br-carousel-page.cjs.entry.js +2 -2
  9. package/dist/cjs/br-carousel.cjs.entry.js +5 -5
  10. package/dist/cjs/br-checkbox-group.cjs.entry.js +2 -2
  11. package/dist/cjs/br-checkbox.cjs.entry.js +2 -2
  12. package/dist/cjs/br-checkgroup.cjs.entry.js +1 -1
  13. package/dist/cjs/br-collapse_2.cjs.entry.js +8 -8
  14. package/dist/cjs/br-cookiebar-cookie.cjs.entry.js +2 -2
  15. package/dist/cjs/br-cookiebar-group.cjs.entry.js +4 -4
  16. package/dist/cjs/br-cookiebar-header.cjs.entry.js +2 -2
  17. package/dist/cjs/br-cookiebar-link.cjs.entry.js +3 -3
  18. package/dist/cjs/br-cookiebar-note-group.cjs.entry.js +3 -3
  19. package/dist/cjs/br-cookiebar-note.cjs.entry.js +2 -2
  20. package/dist/cjs/br-cookiebar.cjs.entry.js +5 -5
  21. package/dist/cjs/br-crumb.cjs.entry.js +1 -1
  22. package/dist/cjs/br-date-picker_3.cjs.entry.js +14 -14
  23. package/dist/cjs/br-datetime-picker.cjs.entry.js +6 -23
  24. package/dist/cjs/br-divider.cjs.entry.js +2 -2
  25. package/dist/cjs/br-dropdown.cjs.entry.js +677 -0
  26. package/dist/cjs/br-footer-category.cjs.entry.js +2 -2
  27. package/dist/cjs/br-footer-item.cjs.entry.js +2 -2
  28. package/dist/cjs/br-footer-legal.cjs.entry.js +2 -2
  29. package/dist/cjs/br-footer-logo.cjs.entry.js +2 -2
  30. package/dist/cjs/br-footer-social.cjs.entry.js +3 -3
  31. package/dist/cjs/br-footer.cjs.entry.js +2 -2
  32. package/dist/cjs/br-header-function.cjs.entry.js +2 -2
  33. package/dist/cjs/br-header-link.cjs.entry.js +2 -2
  34. package/dist/cjs/br-header-list.cjs.entry.js +4 -4
  35. package/dist/cjs/br-header-logo.cjs.entry.js +2 -2
  36. package/dist/cjs/br-header.cjs.entry.js +6 -6
  37. package/dist/cjs/br-icon.cjs.entry.js +172 -158
  38. package/dist/cjs/br-input_2.cjs.entry.js +1427 -0
  39. package/dist/cjs/br-item.cjs.entry.js +2 -2
  40. package/dist/cjs/br-link.cjs.entry.js +2 -2
  41. package/dist/cjs/br-magic-button.cjs.entry.js +11 -12
  42. package/dist/cjs/br-menu-group.cjs.entry.js +2 -2
  43. package/dist/cjs/br-menu-header.cjs.entry.js +3 -3
  44. package/dist/cjs/br-menu-info.cjs.entry.js +2 -2
  45. package/dist/cjs/br-menu-item.cjs.entry.js +3 -3
  46. package/dist/cjs/br-menu-link.cjs.entry.js +3 -3
  47. package/dist/cjs/br-menu-list.cjs.entry.js +2 -2
  48. package/dist/cjs/br-menu-logo.cjs.entry.js +2 -2
  49. package/dist/cjs/br-menu-social.cjs.entry.js +2 -2
  50. package/dist/cjs/br-menu.cjs.entry.js +5 -5
  51. package/dist/cjs/br-modal.cjs.entry.js +2 -2
  52. package/dist/cjs/br-notification-body.cjs.entry.js +2 -2
  53. package/dist/cjs/br-notification-header.cjs.entry.js +2 -2
  54. package/dist/cjs/br-notification-item.cjs.entry.js +2 -2
  55. package/dist/cjs/br-notification.cjs.entry.js +2 -2
  56. package/dist/cjs/{br-dropdown_2.cjs.entry.js → br-pagination_2.cjs.entry.js} +812 -557
  57. package/dist/cjs/br-radio-group.cjs.entry.js +2 -2
  58. package/dist/cjs/br-radio.cjs.entry.js +2 -2
  59. package/dist/cjs/br-scrim.cjs.entry.js +2 -2
  60. package/dist/cjs/br-select-input_3.cjs.entry.js +16 -93
  61. package/dist/cjs/br-sign-in.cjs.entry.js +3 -3
  62. package/dist/cjs/br-skip-link-item.cjs.entry.js +1 -1
  63. package/dist/cjs/br-skip-link.cjs.entry.js +2 -2
  64. package/dist/cjs/br-skiplink-item.cjs.entry.js +2 -2
  65. package/dist/cjs/br-slider.cjs.entry.js +3 -3
  66. package/dist/cjs/br-step_2.cjs.entry.js +3 -3
  67. package/dist/cjs/br-switch.cjs.entry.js +2 -2
  68. package/dist/cjs/br-tab-item.cjs.entry.js +3 -3
  69. package/dist/cjs/br-tab.cjs.entry.js +7 -7
  70. package/dist/cjs/br-table-action_6.cjs.entry.js +1500 -0
  71. package/dist/cjs/br-table-body.cjs.entry.js +4 -16
  72. package/dist/cjs/br-table-header.cjs.entry.js +4 -16
  73. package/dist/cjs/br-table.cjs.entry.js +2616 -433
  74. package/dist/cjs/br-tag.cjs.entry.js +4 -4
  75. package/dist/cjs/br-textarea.cjs.entry.js +3 -3
  76. package/dist/cjs/br-tooltip.cjs.entry.js +5 -29
  77. package/dist/cjs/br-upload.cjs.entry.js +4 -4
  78. package/dist/cjs/br-wizard-panel.cjs.entry.js +3 -3
  79. package/dist/cjs/br-wizard.cjs.entry.js +3 -3
  80. package/dist/cjs/helpers-DkkDubv1.js +28 -0
  81. package/dist/cjs/{icon.utils-DF6kMskA.js → icon.utils-CMs0ukvR.js} +1 -1
  82. package/dist/cjs/{index-Bc30P_6z.js → index-BP8UIQro.js} +34 -34
  83. package/dist/cjs/loader.cjs.js +2 -2
  84. package/dist/cjs/table.utils-De-9_NgJ.js +749 -0
  85. package/dist/cjs/webcomponents.cjs.js +2 -2
  86. package/dist/collection/collection-manifest.json +3 -0
  87. package/dist/collection/components/avatar/avatar.css +1 -1
  88. package/dist/collection/components/breadcrumb/breadcrumb.css +1 -1
  89. package/dist/collection/components/breadcrumb/breadcrumb.js +9 -9
  90. package/dist/collection/components/button/button.css +1 -1
  91. package/dist/collection/components/button/button.js +2 -2
  92. package/dist/collection/components/card/card.css +1 -1
  93. package/dist/collection/components/carousel/carousel-page/carousel-page.css +1 -1
  94. package/dist/collection/components/carousel/carousel.css +1 -1
  95. package/dist/collection/components/carousel/carousel.js +3 -3
  96. package/dist/collection/components/checkbox/checkbox.css +1 -1
  97. package/dist/collection/components/checkbox-group/checkbox-group.css +1 -1
  98. package/dist/collection/components/collapse/collapse.css +1 -1
  99. package/dist/collection/components/collapse/collapse.js +9 -9
  100. package/dist/collection/components/cookiebar/cookiebar-cookie/cookiebar-cookie.css +1 -1
  101. package/dist/collection/components/cookiebar/cookiebar-group/cookiebar-group.css +1 -1
  102. package/dist/collection/components/cookiebar/cookiebar-group/cookiebar-group.js +2 -2
  103. package/dist/collection/components/cookiebar/cookiebar-header/cookiebar-header.css +1 -1
  104. package/dist/collection/components/cookiebar/cookiebar-link/cookiebar-link.css +1 -1
  105. package/dist/collection/components/cookiebar/cookiebar-link/cookiebar-link.js +1 -1
  106. package/dist/collection/components/cookiebar/cookiebar-note/cookiebar-note.css +1 -1
  107. package/dist/collection/components/cookiebar/cookiebar-note-group/cookiebar-note-group.css +1 -1
  108. package/dist/collection/components/cookiebar/cookiebar-note-group/cookiebar-note-group.js +1 -1
  109. package/dist/collection/components/cookiebar/cookiebar.css +1 -1
  110. package/dist/collection/components/cookiebar/cookiebar.js +3 -3
  111. package/dist/collection/components/datetime-picker/date-picker/date-picker.css +1 -1
  112. package/dist/collection/components/datetime-picker/date-picker/date-picker.js +4 -4
  113. package/dist/collection/components/datetime-picker/datetime-input/datetime-input.css +1 -1
  114. package/dist/collection/components/datetime-picker/datetime-input/datetime-input.js +3 -3
  115. package/dist/collection/components/datetime-picker/datetime-picker.css +1 -1
  116. package/dist/collection/components/datetime-picker/datetime-picker.utils.js +6 -6
  117. package/dist/collection/components/datetime-picker/time-picker/time-picker.css +1 -1
  118. package/dist/collection/components/datetime-picker/time-picker/time-picker.js +3 -3
  119. package/dist/collection/components/divider/divider.css +1 -1
  120. package/dist/collection/components/dropdown/dropdown.css +1 -1
  121. package/dist/collection/components/dropdown/dropdown.js +6 -8
  122. package/dist/collection/components/footer/footer-category/footer-category.css +1 -1
  123. package/dist/collection/components/footer/footer-item/footer-item.css +1 -1
  124. package/dist/collection/components/footer/footer-legal/footer-legal.css +1 -1
  125. package/dist/collection/components/footer/footer-logo/footer-logo.css +1 -1
  126. package/dist/collection/components/footer/footer-social/footer-social.css +1 -1
  127. package/dist/collection/components/footer/footer-social/footer-social.js +2 -2
  128. package/dist/collection/components/footer/footer.css +1 -1
  129. package/dist/collection/components/header/header-function/header-function.css +1 -1
  130. package/dist/collection/components/header/header-link/header-link.css +1 -1
  131. package/dist/collection/components/header/header-list/header-list.css +1 -1
  132. package/dist/collection/components/header/header-list/header-list.js +2 -2
  133. package/dist/collection/components/header/header-logo/header-logo.css +1 -1
  134. package/dist/collection/components/header/header.css +1 -1
  135. package/dist/collection/components/header/header.js +4 -4
  136. package/dist/collection/components/icon/default-icons-cache.js +159 -146
  137. package/dist/collection/components/icon/icon.css +1 -1
  138. package/dist/collection/components/icon/icon.js +17 -13
  139. package/dist/collection/components/icon/icon.utils.js +1 -1
  140. package/dist/collection/components/input/input.css +1 -1
  141. package/dist/collection/components/input/input.js +120 -2
  142. package/dist/collection/components/item/item.css +1 -1
  143. package/dist/collection/components/link/link.css +1 -1
  144. package/dist/collection/components/list/list.css +1 -1
  145. package/dist/collection/components/loading/loading.css +1 -1
  146. package/dist/collection/components/magic-button/magic-button.css +1 -1
  147. package/dist/collection/components/magic-button/magic-button.js +11 -12
  148. package/dist/collection/components/menu/menu-group/menu-group.css +1 -1
  149. package/dist/collection/components/menu/menu-header/menu-header.css +1 -1
  150. package/dist/collection/components/menu/menu-header/menu-header.js +1 -1
  151. package/dist/collection/components/menu/menu-info/menu-info.css +1 -1
  152. package/dist/collection/components/menu/menu-item/menu-item.css +1 -1
  153. package/dist/collection/components/menu/menu-item/menu-item.js +1 -1
  154. package/dist/collection/components/menu/menu-link/menu-link.css +1 -1
  155. package/dist/collection/components/menu/menu-link/menu-link.js +1 -1
  156. package/dist/collection/components/menu/menu-list/menu-list.css +1 -1
  157. package/dist/collection/components/menu/menu-logo/menu-logo.css +1 -1
  158. package/dist/collection/components/menu/menu-social/menu-social.css +1 -1
  159. package/dist/collection/components/menu/menu-social/menu-social.js +1 -1
  160. package/dist/collection/components/menu/menu.css +1 -1
  161. package/dist/collection/components/menu/menu.js +3 -3
  162. package/dist/collection/components/message/message.css +1 -1
  163. package/dist/collection/components/modal/modal.css +1 -1
  164. package/dist/collection/components/notification/notification-body/notification-body.css +1 -1
  165. package/dist/collection/components/notification/notification-header/notification-header.css +1 -1
  166. package/dist/collection/components/notification/notification-item/notification-item.css +1 -1
  167. package/dist/collection/components/notification/notification.css +1 -1
  168. package/dist/collection/components/pagination/pagination.css +1 -1
  169. package/dist/collection/components/pagination/pagination.js +4 -4
  170. package/dist/collection/components/radio/radio.css +1 -1
  171. package/dist/collection/components/radio-group/radio-group.css +1 -1
  172. package/dist/collection/components/scrim/scrim.css +1 -1
  173. package/dist/collection/components/select/select-input/select-input.css +1 -1
  174. package/dist/collection/components/select/select-input/select-input.js +6 -84
  175. package/dist/collection/components/select/select-list/select-list.css +1 -1
  176. package/dist/collection/components/select/select-option/select-option.css +1 -1
  177. package/dist/collection/components/select/select-option/select-option.js +8 -7
  178. package/dist/collection/components/select/select.css +1 -1
  179. package/dist/collection/components/select/select.js +22 -6
  180. package/dist/collection/components/sign-in/sign-in.css +1 -1
  181. package/dist/collection/components/sign-in/sign-in.js +1 -1
  182. package/dist/collection/components/skip-link/skip-link-item/skip-link-item.css +1 -1
  183. package/dist/collection/components/skip-link/skip-link.css +1 -1
  184. package/dist/collection/components/slider/slider.css +1 -1
  185. package/dist/collection/components/slider/slider.js +4 -4
  186. package/dist/collection/components/step/step-item/step-item.css +1 -1
  187. package/dist/collection/components/step/step.css +1 -1
  188. package/dist/collection/components/switch/switch.css +1 -1
  189. package/dist/collection/components/tab/tab-item/tab-item.css +1 -1
  190. package/dist/collection/components/tab/tab-item/tab-item.js +2 -2
  191. package/dist/collection/components/tab/tab.css +1 -1
  192. package/dist/collection/components/tab/tab.js +4 -4
  193. package/dist/collection/components/table/table-action/table-action.css +1 -0
  194. package/dist/collection/components/table/table-action/table-action.js +349 -0
  195. package/dist/collection/components/table/table-bar/table-bar.css +1 -0
  196. package/dist/collection/components/table/table-bar/table-bar.js +652 -0
  197. package/dist/collection/components/table/table-body/table-body.css +1 -1
  198. package/dist/collection/components/table/table-body/table-body.js +12 -17
  199. package/dist/collection/components/table/table-cell/table-cell.css +1 -1
  200. package/dist/collection/components/table/table-cell/table-cell.js +556 -83
  201. package/dist/collection/components/table/table-footer/table-footer.css +1 -0
  202. package/dist/collection/components/table/table-footer/table-footer.js +233 -0
  203. package/dist/collection/components/table/table-header/table-header.css +1 -1
  204. package/dist/collection/components/table/table-header/table-header.js +11 -17
  205. package/dist/collection/components/table/table-header-cell/table-header-cell.css +1 -1
  206. package/dist/collection/components/table/table-header-cell/table-header-cell.js +287 -86
  207. package/dist/collection/components/table/table-row/table-row.css +1 -1
  208. package/dist/collection/components/table/table-row/table-row.js +312 -57
  209. package/dist/collection/components/table/table.actions-tooltip.js +33 -0
  210. package/dist/collection/components/table/{table-constants.js → table.constants.js} +54 -77
  211. package/dist/collection/components/table/table.css +1 -1
  212. package/dist/collection/components/table/table.data.js +461 -0
  213. package/dist/collection/components/table/table.expansion.elements.js +70 -0
  214. package/dist/collection/components/table/table.expansion.js +179 -0
  215. package/dist/collection/components/table/table.grouping.js +97 -0
  216. package/dist/collection/components/table/table.header-height.js +47 -0
  217. package/dist/collection/components/table/table.js +2499 -618
  218. package/dist/collection/components/table/table.keyboard.js +340 -0
  219. package/dist/collection/components/table/table.scroll-shadows.js +36 -0
  220. package/dist/collection/components/table/table.selection.elements.js +63 -0
  221. package/dist/collection/components/table/table.selection.js +239 -0
  222. package/dist/collection/components/table/table.tokens.js +28 -0
  223. package/dist/collection/components/table/table.types.js +1 -0
  224. package/dist/collection/components/table/table.utils.js +75 -0
  225. package/dist/collection/components/table/table.virtual-list.js +342 -0
  226. package/dist/collection/components/tag/tag.css +1 -1
  227. package/dist/collection/components/tag/tag.js +2 -2
  228. package/dist/collection/components/textarea/textarea.css +1 -1
  229. package/dist/collection/components/textarea/textarea.js +1 -1
  230. package/dist/collection/components/tooltip/tooltip.css +1 -1
  231. package/dist/collection/components/tooltip/tooltip.js +3 -27
  232. package/dist/collection/components/upload/upload.css +1 -1
  233. package/dist/collection/components/upload/upload.js +2 -2
  234. package/dist/collection/components/wizard/wizard-panel/wizard-panel.css +1 -1
  235. package/dist/collection/components/wizard/wizard-panel/wizard-panel.js +1 -1
  236. package/dist/collection/components/wizard/wizard.css +1 -1
  237. package/dist/collection/components/wizard/wizard.js +1 -1
  238. package/dist/collection/pages/scripts/code-editor.js +28 -3
  239. package/dist/collection/pages/scripts/pageLoader.js +286 -20
  240. package/dist/collection/pages/scripts/pageloader-preview.js +3 -1
  241. package/dist/components/br-avatar.js +1 -1
  242. package/dist/components/br-breadcrumb-item.js +1 -1
  243. package/dist/components/br-breadcrumb.js +1 -1
  244. package/dist/components/br-button.js +1 -1
  245. package/dist/components/br-card.js +1 -1
  246. package/dist/components/br-carousel-page.js +1 -1
  247. package/dist/components/br-carousel.js +1 -1
  248. package/dist/components/br-checkbox-group.js +1 -1
  249. package/dist/components/br-checkbox.js +1 -1
  250. package/dist/components/br-checkgroup.js +1 -1
  251. package/dist/components/br-collapse.js +1 -1
  252. package/dist/components/br-cookiebar-cookie.js +1 -1
  253. package/dist/components/br-cookiebar-group.js +1 -1
  254. package/dist/components/br-cookiebar-header.js +1 -1
  255. package/dist/components/br-cookiebar-link.js +1 -1
  256. package/dist/components/br-cookiebar-note-group.js +1 -1
  257. package/dist/components/br-cookiebar-note.js +1 -1
  258. package/dist/components/br-cookiebar.js +1 -1
  259. package/dist/components/br-crumb.js +1 -1
  260. package/dist/components/br-date-picker.js +1 -1
  261. package/dist/components/br-datetime-input.js +1 -1
  262. package/dist/components/br-datetime-picker.js +1 -1
  263. package/dist/components/br-divider.js +1 -1
  264. package/dist/components/br-dropdown.js +1 -1
  265. package/dist/components/br-footer-category.js +1 -1
  266. package/dist/components/br-footer-item.js +1 -1
  267. package/dist/components/br-footer-legal.js +1 -1
  268. package/dist/components/br-footer-logo.js +1 -1
  269. package/dist/components/br-footer-social.js +1 -1
  270. package/dist/components/br-footer.js +1 -1
  271. package/dist/components/br-header-function.js +1 -1
  272. package/dist/components/br-header-link.js +1 -1
  273. package/dist/components/br-header-list.js +1 -1
  274. package/dist/components/br-header-logo.js +1 -1
  275. package/dist/components/br-header.js +1 -1
  276. package/dist/components/br-icon.js +1 -1
  277. package/dist/components/br-input.js +1 -1
  278. package/dist/components/br-item.js +1 -1
  279. package/dist/components/br-link.js +1 -1
  280. package/dist/components/br-list.js +1 -1
  281. package/dist/components/br-loading.js +1 -1
  282. package/dist/components/br-magic-button.js +1 -1
  283. package/dist/components/br-menu-group.js +1 -1
  284. package/dist/components/br-menu-header.js +1 -1
  285. package/dist/components/br-menu-info.js +1 -1
  286. package/dist/components/br-menu-item.js +1 -1
  287. package/dist/components/br-menu-link.js +1 -1
  288. package/dist/components/br-menu-list.js +1 -1
  289. package/dist/components/br-menu-logo.js +1 -1
  290. package/dist/components/br-menu-social.js +1 -1
  291. package/dist/components/br-menu.js +1 -1
  292. package/dist/components/br-message.js +1 -1
  293. package/dist/components/br-modal.js +1 -1
  294. package/dist/components/br-notification-body.js +1 -1
  295. package/dist/components/br-notification-header.js +1 -1
  296. package/dist/components/br-notification-item.js +1 -1
  297. package/dist/components/br-notification.js +1 -1
  298. package/dist/components/br-pagination.js +1 -1
  299. package/dist/components/br-radio-group.js +1 -1
  300. package/dist/components/br-radio.js +1 -1
  301. package/dist/components/br-scrim.js +1 -1
  302. package/dist/components/br-select-input.js +1 -1
  303. package/dist/components/br-select-list.js +1 -1
  304. package/dist/components/br-select-option.js +1 -1
  305. package/dist/components/br-select.js +1 -1
  306. package/dist/components/br-sign-in.js +1 -1
  307. package/dist/components/br-skip-link-item.js +1 -1
  308. package/dist/components/br-skip-link.js +1 -1
  309. package/dist/components/br-skiplink-item.js +1 -1
  310. package/dist/components/br-slider.js +1 -1
  311. package/dist/components/br-step-item.js +1 -1
  312. package/dist/components/br-step.js +1 -1
  313. package/dist/components/br-switch.js +1 -1
  314. package/dist/components/br-tab-item.js +1 -1
  315. package/dist/components/br-tab.js +1 -1
  316. package/dist/components/br-table-action.d.ts +11 -0
  317. package/dist/components/br-table-action.js +5 -0
  318. package/dist/components/br-table-bar.d.ts +11 -0
  319. package/dist/components/br-table-bar.js +5 -0
  320. package/dist/components/br-table-body.js +1 -1
  321. package/dist/components/br-table-cell.js +1 -1
  322. package/dist/components/br-table-footer.d.ts +11 -0
  323. package/dist/components/br-table-footer.js +5 -0
  324. package/dist/components/br-table-header-cell.js +1 -1
  325. package/dist/components/br-table-header.js +1 -1
  326. package/dist/components/br-table-row.js +1 -1
  327. package/dist/components/br-table.js +1 -1
  328. package/dist/components/br-tag.js +1 -1
  329. package/dist/components/br-textarea.js +1 -1
  330. package/dist/components/br-time-picker.js +1 -1
  331. package/dist/components/br-tooltip.js +1 -1
  332. package/dist/components/br-upload.js +1 -1
  333. package/dist/components/br-wizard-panel.js +1 -1
  334. package/dist/components/br-wizard.js +1 -1
  335. package/dist/components/index.d.ts +6 -0
  336. package/dist/components/index.js +1 -1
  337. package/dist/components/p-082jxuTj.js +5 -0
  338. package/dist/components/p-381n6AwK.js +5 -0
  339. package/dist/components/{p-CyXVsiz9.js → p-B5_zbRAr.js} +1 -1
  340. package/dist/components/p-BE1gDPwC.js +5 -0
  341. package/dist/components/p-BV-c2pxt.js +5 -0
  342. package/dist/components/p-BfFbYAuJ.js +5 -0
  343. package/dist/components/{p-DcMjwTqu.js → p-Bi2E_w9Q.js} +1 -1
  344. package/dist/components/p-Bk8YcMql.js +5 -0
  345. package/dist/components/p-C3ISxUGw.js +5 -0
  346. package/dist/components/p-C3J0TVQO.js +5 -0
  347. package/dist/components/p-C6m13lCc.js +5 -0
  348. package/dist/components/{p-DBmwzG9E.js → p-CCWJ-H33.js} +1 -1
  349. package/dist/components/p-CJuHirYK.js +5 -0
  350. package/dist/components/{p-SWQlgYWR.js → p-CKS7ggLM.js} +1 -1
  351. package/dist/components/p-COSFBwu9.js +5 -0
  352. package/dist/components/p-CWPrXYam.js +5 -0
  353. package/dist/components/p-Ca89D_0s.js +5 -0
  354. package/dist/components/p-CbN58CFi.js +5 -0
  355. package/dist/components/p-CjjxTkKb.js +5 -0
  356. package/dist/components/p-Ck9t4WSb.js +5 -0
  357. package/dist/components/p-CvfVwD6_.js +5 -0
  358. package/dist/components/p-D-1sfjhG.js +5 -0
  359. package/dist/components/p-D-p4vLlP.js +5 -0
  360. package/dist/components/p-D6DArHGH.js +5 -0
  361. package/dist/components/p-DD3BItoS.js +5 -0
  362. package/dist/components/{p-448Z5r2f.js → p-DEIKwFIf.js} +1 -1
  363. package/dist/components/p-DHHAIESt.js +5 -0
  364. package/dist/components/{p-Jk_KQE5V.js → p-DMj5iO7_.js} +1 -1
  365. package/dist/components/p-DUI-S07G.js +5 -0
  366. package/dist/components/p-D_K9JH6J.js +5 -0
  367. package/dist/components/p-DiQp2Lap.js +5 -0
  368. package/dist/components/{p-DJKZ8ktB.js → p-Dvbqhybt.js} +1 -1
  369. package/dist/components/p-Dy7MSvt-.js +5 -0
  370. package/dist/components/p-DywTXNHQ.js +5 -0
  371. package/dist/components/p-Ft_P7Roz.js +5 -0
  372. package/dist/components/p-KuiFoKDl.js +5 -0
  373. package/dist/components/p-MiiczSWA.js +5 -0
  374. package/dist/components/p-Um3K2SHu.js +5 -0
  375. package/dist/components/p-YxddSP6q.js +5 -0
  376. package/dist/components/p-Zk91ebVT.js +5 -0
  377. package/dist/components/p-jv2oG0vH.js +5 -0
  378. package/dist/components/p-nrG_Gd0c.js +5 -0
  379. package/dist/components/p-syLEZrcg.js +5 -0
  380. package/dist/components/{p-jvKQA6x7.js → p-ydfWTgrA.js} +1 -1
  381. package/dist/esm/br-avatar.entry.js +3 -3
  382. package/dist/esm/br-breadcrumb-item.entry.js +1 -1
  383. package/dist/esm/br-breadcrumb.entry.js +12 -12
  384. package/dist/esm/br-button_2.entry.js +6 -6
  385. package/dist/esm/br-card.entry.js +2 -2
  386. package/dist/esm/br-carousel-page.entry.js +2 -2
  387. package/dist/esm/br-carousel.entry.js +6 -6
  388. package/dist/esm/br-checkbox-group.entry.js +3 -3
  389. package/dist/esm/br-checkbox.entry.js +3 -3
  390. package/dist/esm/br-checkgroup.entry.js +1 -1
  391. package/dist/esm/br-collapse_2.entry.js +9 -9
  392. package/dist/esm/br-cookiebar-cookie.entry.js +2 -2
  393. package/dist/esm/br-cookiebar-group.entry.js +4 -4
  394. package/dist/esm/br-cookiebar-header.entry.js +2 -2
  395. package/dist/esm/br-cookiebar-link.entry.js +4 -4
  396. package/dist/esm/br-cookiebar-note-group.entry.js +3 -3
  397. package/dist/esm/br-cookiebar-note.entry.js +2 -2
  398. package/dist/esm/br-cookiebar.entry.js +6 -6
  399. package/dist/esm/br-crumb.entry.js +1 -1
  400. package/dist/esm/br-date-picker_3.entry.js +14 -14
  401. package/dist/esm/br-datetime-picker.entry.js +5 -22
  402. package/dist/esm/br-divider.entry.js +3 -3
  403. package/dist/esm/br-dropdown.entry.js +675 -0
  404. package/dist/esm/br-footer-category.entry.js +2 -2
  405. package/dist/esm/br-footer-item.entry.js +3 -3
  406. package/dist/esm/br-footer-legal.entry.js +2 -2
  407. package/dist/esm/br-footer-logo.entry.js +3 -3
  408. package/dist/esm/br-footer-social.entry.js +4 -4
  409. package/dist/esm/br-footer.entry.js +3 -3
  410. package/dist/esm/br-header-function.entry.js +3 -3
  411. package/dist/esm/br-header-link.entry.js +3 -3
  412. package/dist/esm/br-header-list.entry.js +4 -4
  413. package/dist/esm/br-header-logo.entry.js +3 -3
  414. package/dist/esm/br-header.entry.js +7 -7
  415. package/dist/esm/br-icon.entry.js +173 -159
  416. package/dist/esm/br-input_2.entry.js +1424 -0
  417. package/dist/esm/br-item.entry.js +3 -3
  418. package/dist/esm/br-link.entry.js +3 -3
  419. package/dist/esm/br-magic-button.entry.js +12 -13
  420. package/dist/esm/br-menu-group.entry.js +2 -2
  421. package/dist/esm/br-menu-header.entry.js +3 -3
  422. package/dist/esm/br-menu-info.entry.js +2 -2
  423. package/dist/esm/br-menu-item.entry.js +4 -4
  424. package/dist/esm/br-menu-link.entry.js +4 -4
  425. package/dist/esm/br-menu-list.entry.js +2 -2
  426. package/dist/esm/br-menu-logo.entry.js +2 -2
  427. package/dist/esm/br-menu-social.entry.js +3 -3
  428. package/dist/esm/br-menu.entry.js +6 -6
  429. package/dist/esm/br-modal.entry.js +3 -3
  430. package/dist/esm/br-notification-body.entry.js +2 -2
  431. package/dist/esm/br-notification-header.entry.js +2 -2
  432. package/dist/esm/br-notification-item.entry.js +3 -3
  433. package/dist/esm/br-notification.entry.js +3 -3
  434. package/dist/esm/{br-dropdown_2.entry.js → br-pagination_2.entry.js} +813 -558
  435. package/dist/esm/br-radio-group.entry.js +3 -3
  436. package/dist/esm/br-radio.entry.js +3 -3
  437. package/dist/esm/br-scrim.entry.js +3 -3
  438. package/dist/esm/br-select-input_3.entry.js +17 -94
  439. package/dist/esm/br-sign-in.entry.js +4 -4
  440. package/dist/esm/br-skip-link-item.entry.js +1 -1
  441. package/dist/esm/br-skip-link.entry.js +3 -3
  442. package/dist/esm/br-skiplink-item.entry.js +3 -3
  443. package/dist/esm/br-slider.entry.js +4 -4
  444. package/dist/esm/br-step_2.entry.js +4 -4
  445. package/dist/esm/br-switch.entry.js +3 -3
  446. package/dist/esm/br-tab-item.entry.js +4 -4
  447. package/dist/esm/br-tab.entry.js +8 -8
  448. package/dist/esm/br-table-action_6.entry.js +1493 -0
  449. package/dist/esm/br-table-body.entry.js +4 -16
  450. package/dist/esm/br-table-header.entry.js +4 -16
  451. package/dist/esm/br-table.entry.js +2591 -408
  452. package/dist/esm/br-tag.entry.js +5 -5
  453. package/dist/esm/br-textarea.entry.js +4 -4
  454. package/dist/esm/br-tooltip.entry.js +6 -30
  455. package/dist/esm/br-upload.entry.js +5 -5
  456. package/dist/esm/br-wizard-panel.entry.js +3 -3
  457. package/dist/esm/br-wizard.entry.js +4 -4
  458. package/dist/esm/helpers-BNW9pAhl.js +26 -0
  459. package/dist/esm/{icon.utils-zlORkiHQ.js → icon.utils-CXDYKUBz.js} +1 -1
  460. package/dist/esm/{index-ConyRdJe.js → index-CwL52661.js} +34 -35
  461. package/dist/esm/loader.js +3 -3
  462. package/dist/esm/{props-D07GjR4_.js → props-BbxNgEcJ.js} +1 -1
  463. package/dist/esm/table.utils-CtVdlcgI.js +706 -0
  464. package/dist/esm/webcomponents.js +3 -3
  465. package/dist/hydrate/index.js +5269 -1302
  466. package/dist/hydrate/index.mjs +5269 -1302
  467. package/dist/types/components/collapse/collapse.d.ts +2 -2
  468. package/dist/types/components/footer/footer-social/footer-social.d.ts +2 -3
  469. package/dist/types/components/icon/icon.d.ts +6 -6
  470. package/dist/types/components/icon/icon.utils.d.ts +1 -1
  471. package/dist/types/components/input/input.d.ts +7 -1
  472. package/dist/types/components/input/input.types.d.ts +18 -0
  473. package/dist/types/components/magic-button/magic-button.d.ts +7 -8
  474. package/dist/types/components/menu/menu-social/menu-social.d.ts +2 -3
  475. package/dist/types/components/select/select-input/select-input.d.ts +1 -4
  476. package/dist/types/components/select/select-option/select-option.d.ts +3 -1
  477. package/dist/types/components/slider/slider.d.ts +4 -4
  478. package/dist/types/components/tab/tab-item/tab-item.d.ts +2 -2
  479. package/dist/types/components/tab/tab.d.ts +1 -1
  480. package/dist/types/components/table/table-action/table-action.d.ts +107 -0
  481. package/dist/types/components/table/table-bar/table-bar.d.ts +193 -0
  482. package/dist/types/components/table/table-body/table-body.d.ts +11 -16
  483. package/dist/types/components/table/table-cell/table-cell.d.ts +178 -38
  484. package/dist/types/components/table/table-footer/table-footer.d.ts +40 -0
  485. package/dist/types/components/table/table-footer/table-footer.types.d.ts +12 -0
  486. package/dist/types/components/table/table-header/table-header.d.ts +10 -16
  487. package/dist/types/components/table/table-header-cell/table-header-cell.d.ts +102 -53
  488. package/dist/types/components/table/table-row/table-row.d.ts +88 -29
  489. package/dist/types/components/table/table.actions-tooltip.d.ts +11 -0
  490. package/dist/types/components/table/{table-constants.d.ts → table.constants.d.ts} +50 -77
  491. package/dist/types/components/table/table.d.ts +601 -222
  492. package/dist/types/components/table/table.data.d.ts +78 -0
  493. package/dist/types/components/table/table.expansion.d.ts +65 -0
  494. package/dist/types/components/table/table.expansion.elements.d.ts +30 -0
  495. package/dist/types/components/table/table.grouping.d.ts +25 -0
  496. package/dist/types/components/table/table.header-height.d.ts +17 -0
  497. package/dist/types/components/table/table.keyboard.d.ts +53 -0
  498. package/dist/types/components/table/table.scroll-shadows.d.ts +11 -0
  499. package/dist/types/components/table/table.selection.d.ts +84 -0
  500. package/dist/types/components/table/table.selection.elements.d.ts +42 -0
  501. package/dist/types/components/table/table.tokens.d.ts +24 -0
  502. package/dist/types/components/table/table.types.d.ts +199 -0
  503. package/dist/types/components/table/table.utils.d.ts +52 -0
  504. package/dist/types/components/table/table.virtual-list.d.ts +96 -0
  505. package/dist/types/components.d.ts +1401 -279
  506. package/dist/webcomponents/{p-85c8d060.entry.js → p-07e80bf8.entry.js} +1 -1
  507. package/dist/webcomponents/p-10d81622.entry.js +5 -0
  508. package/dist/webcomponents/{p-a9f16a65.entry.js → p-12d5f533.entry.js} +1 -1
  509. package/dist/webcomponents/p-15699e8a.entry.js +5 -0
  510. package/dist/webcomponents/{p-bbcde1ea.entry.js → p-15e2f5cc.entry.js} +1 -1
  511. package/dist/webcomponents/{p-5528b466.entry.js → p-16d27d5c.entry.js} +1 -1
  512. package/dist/webcomponents/p-18d3fab8.entry.js +5 -0
  513. package/dist/webcomponents/p-23c916d9.entry.js +5 -0
  514. package/dist/webcomponents/p-2aee69fd.entry.js +5 -0
  515. package/dist/webcomponents/p-2d3db296.entry.js +5 -0
  516. package/dist/webcomponents/p-2ed6afdd.entry.js +5 -0
  517. package/dist/webcomponents/{p-bbf47e78.entry.js → p-30c865e6.entry.js} +1 -1
  518. package/dist/webcomponents/p-32afb78c.entry.js +5 -0
  519. package/dist/webcomponents/p-33d24cbd.entry.js +5 -0
  520. package/dist/webcomponents/p-35d63edd.entry.js +5 -0
  521. package/dist/webcomponents/p-3b1ff55e.entry.js +5 -0
  522. package/dist/webcomponents/p-3c7246cf.entry.js +5 -0
  523. package/dist/webcomponents/{p-11d4edc5.entry.js → p-407e7b69.entry.js} +1 -1
  524. package/dist/webcomponents/{p-53550e8c.entry.js → p-41b12e3c.entry.js} +1 -1
  525. package/dist/webcomponents/p-47adc17f.entry.js +5 -0
  526. package/dist/webcomponents/{p-21e10074.entry.js → p-48fc8e56.entry.js} +1 -1
  527. package/dist/webcomponents/p-4a44c8b8.entry.js +5 -0
  528. package/dist/webcomponents/{p-6d58ab4f.entry.js → p-4b0f3701.entry.js} +1 -1
  529. package/dist/webcomponents/{p-84dfbfdd.entry.js → p-4b66200c.entry.js} +1 -1
  530. package/dist/webcomponents/{p-324afbce.entry.js → p-4c0a1c05.entry.js} +1 -1
  531. package/dist/webcomponents/p-4c72d706.entry.js +5 -0
  532. package/dist/webcomponents/p-505173e0.entry.js +5 -0
  533. package/dist/webcomponents/p-50caea68.entry.js +5 -0
  534. package/dist/webcomponents/p-5419fd2c.entry.js +5 -0
  535. package/dist/webcomponents/{p-ed3fa8ec.entry.js → p-5693e0e7.entry.js} +1 -1
  536. package/dist/webcomponents/p-58247764.entry.js +5 -0
  537. package/dist/webcomponents/{p-3926cc91.entry.js → p-5d0f4851.entry.js} +1 -1
  538. package/dist/webcomponents/{p-39a7826d.entry.js → p-60c949c8.entry.js} +1 -1
  539. package/dist/webcomponents/p-61b84035.entry.js +5 -0
  540. package/dist/webcomponents/{p-e121429a.entry.js → p-62a74e0a.entry.js} +1 -1
  541. package/dist/webcomponents/p-6450913e.entry.js +5 -0
  542. package/dist/webcomponents/p-66c8b8d9.entry.js +5 -0
  543. package/dist/webcomponents/{p-c6f2f17b.entry.js → p-67281ef1.entry.js} +1 -1
  544. package/dist/webcomponents/{p-087ed5e7.entry.js → p-6e128c7a.entry.js} +1 -1
  545. package/dist/webcomponents/p-725e92ab.entry.js +5 -0
  546. package/dist/webcomponents/{p-19b4b1b7.entry.js → p-74726f20.entry.js} +1 -1
  547. package/dist/webcomponents/{p-975ea5c7.entry.js → p-75bd655b.entry.js} +1 -1
  548. package/dist/webcomponents/p-7bf78e48.entry.js +5 -0
  549. package/dist/webcomponents/p-7cc28ecf.entry.js +5 -0
  550. package/dist/webcomponents/{p-913d6f28.entry.js → p-7ec01a99.entry.js} +1 -1
  551. package/dist/webcomponents/{p-d205f3fd.entry.js → p-7f17dbca.entry.js} +1 -1
  552. package/dist/webcomponents/{p-152482f9.entry.js → p-8120f3ce.entry.js} +1 -1
  553. package/dist/webcomponents/p-8ded7870.entry.js +5 -0
  554. package/dist/webcomponents/p-9ab989d1.entry.js +5 -0
  555. package/dist/webcomponents/p-9be642ff.entry.js +5 -0
  556. package/dist/webcomponents/p-9d41995a.entry.js +5 -0
  557. package/dist/webcomponents/{p-EbtQZm5s.js → p-CjVabz-h.js} +1 -1
  558. package/dist/webcomponents/{p-ConyRdJe.js → p-CwL52661.js} +2 -2
  559. package/dist/webcomponents/p-Zk91ebVT.js +5 -0
  560. package/dist/webcomponents/p-_BMaB_68.js +5 -0
  561. package/dist/webcomponents/p-a150b61d.entry.js +5 -0
  562. package/dist/webcomponents/{p-55e0822d.entry.js → p-a264acf6.entry.js} +1 -1
  563. package/dist/webcomponents/p-a5616523.entry.js +5 -0
  564. package/dist/webcomponents/{p-eb5806c7.entry.js → p-ae3dfb9c.entry.js} +1 -1
  565. package/dist/webcomponents/p-b1aeb805.entry.js +5 -0
  566. package/dist/webcomponents/p-b8eea3ef.entry.js +5 -0
  567. package/dist/webcomponents/p-c6952f8d.entry.js +5 -0
  568. package/dist/webcomponents/p-c743e5c5.entry.js +5 -0
  569. package/dist/webcomponents/p-d0c659c3.entry.js +5 -0
  570. package/dist/webcomponents/p-d3dec923.entry.js +5 -0
  571. package/dist/webcomponents/{p-12dd22af.entry.js → p-d5405bbe.entry.js} +1 -1
  572. package/dist/webcomponents/{p-c29268b5.entry.js → p-d6d3a552.entry.js} +1 -1
  573. package/dist/webcomponents/p-dab66328.entry.js +5 -0
  574. package/dist/webcomponents/{p-cb1e08b1.entry.js → p-db02533d.entry.js} +1 -1
  575. package/dist/webcomponents/p-dda22999.entry.js +5 -0
  576. package/dist/webcomponents/p-e2a46f44.entry.js +5 -0
  577. package/dist/webcomponents/{p-e0ccf189.entry.js → p-e3680ff8.entry.js} +1 -1
  578. package/dist/webcomponents/p-e5b9652d.entry.js +5 -0
  579. package/dist/webcomponents/p-e7f02302.entry.js +5 -0
  580. package/dist/webcomponents/p-f0720e23.entry.js +5 -0
  581. package/dist/webcomponents/p-f244009d.entry.js +5 -0
  582. package/dist/webcomponents/p-f32c40ee.entry.js +5 -0
  583. package/dist/webcomponents/{p-e4b968b5.entry.js → p-f697abbd.entry.js} +1 -1
  584. package/dist/webcomponents/p-f7ed35ef.entry.js +5 -0
  585. package/dist/webcomponents/p-f8576e0a.entry.js +5 -0
  586. package/dist/webcomponents/p-fcc62731.entry.js +5 -0
  587. package/dist/webcomponents/webcomponents.esm.js +1 -1
  588. package/package.json +1 -1
  589. package/dist/cjs/br-input.cjs.entry.js +0 -763
  590. package/dist/cjs/br-loading.cjs.entry.js +0 -567
  591. package/dist/cjs/br-pagination.cjs.entry.js +0 -916
  592. package/dist/cjs/br-table-cell.cjs.entry.js +0 -201
  593. package/dist/cjs/br-table-header-cell.cjs.entry.js +0 -189
  594. package/dist/cjs/br-table-row.cjs.entry.js +0 -95
  595. package/dist/cjs/table-constants-BOPSay0B.js +0 -183
  596. package/dist/collection/components/table/table-tokens.js +0 -50
  597. package/dist/collection/components/table/table-utils.js +0 -44
  598. package/dist/components/p-AhfgJCUp.js +0 -5
  599. package/dist/components/p-AoNL6BaW.js +0 -5
  600. package/dist/components/p-B468MCYC.js +0 -5
  601. package/dist/components/p-B985Ov_x.js +0 -5
  602. package/dist/components/p-BOWQIHQA.js +0 -5
  603. package/dist/components/p-BPQrgCRr.js +0 -5
  604. package/dist/components/p-BwQT0fOJ.js +0 -5
  605. package/dist/components/p-CAgbUwsx.js +0 -5
  606. package/dist/components/p-CFXey8i8.js +0 -5
  607. package/dist/components/p-CW8xwk6J.js +0 -5
  608. package/dist/components/p-CXMwM9m4.js +0 -5
  609. package/dist/components/p-CYZVdKeO.js +0 -5
  610. package/dist/components/p-CeWbZN7V.js +0 -5
  611. package/dist/components/p-DDe0tQEO.js +0 -5
  612. package/dist/components/p-DRsZ9GNg.js +0 -5
  613. package/dist/components/p-DU54cqCf.js +0 -5
  614. package/dist/components/p-DVJlmlEX.js +0 -5
  615. package/dist/components/p-Dd1qCWAK.js +0 -5
  616. package/dist/components/p-DiLI514I.js +0 -5
  617. package/dist/components/p-DoWy_P8b.js +0 -5
  618. package/dist/components/p-HbhTnepI.js +0 -5
  619. package/dist/components/p-Or3FLzbz.js +0 -5
  620. package/dist/components/p-Zb9nyfTY.js +0 -5
  621. package/dist/components/p-pQb-3jFY.js +0 -5
  622. package/dist/components/p-qX6sHxOk.js +0 -5
  623. package/dist/esm/br-input.entry.js +0 -761
  624. package/dist/esm/br-loading.entry.js +0 -565
  625. package/dist/esm/br-pagination.entry.js +0 -914
  626. package/dist/esm/br-table-cell.entry.js +0 -199
  627. package/dist/esm/br-table-header-cell.entry.js +0 -187
  628. package/dist/esm/br-table-row.entry.js +0 -93
  629. package/dist/esm/table-constants-CXMwM9m4.js +0 -170
  630. package/dist/types/components/table/table-tokens.d.ts +0 -46
  631. package/dist/types/components/table/table-types.d.ts +0 -107
  632. package/dist/types/components/table/table-utils.d.ts +0 -47
  633. package/dist/webcomponents/p-031a2256.entry.js +0 -5
  634. package/dist/webcomponents/p-0602e5b1.entry.js +0 -5
  635. package/dist/webcomponents/p-079d5f69.entry.js +0 -5
  636. package/dist/webcomponents/p-0d5a9ebf.entry.js +0 -5
  637. package/dist/webcomponents/p-105b4d06.entry.js +0 -5
  638. package/dist/webcomponents/p-14aedf0d.entry.js +0 -5
  639. package/dist/webcomponents/p-1cd1126e.entry.js +0 -5
  640. package/dist/webcomponents/p-2271ea84.entry.js +0 -5
  641. package/dist/webcomponents/p-271b1ede.entry.js +0 -5
  642. package/dist/webcomponents/p-28f732fc.entry.js +0 -5
  643. package/dist/webcomponents/p-2971d38a.entry.js +0 -5
  644. package/dist/webcomponents/p-2ac48875.entry.js +0 -5
  645. package/dist/webcomponents/p-2b1a919c.entry.js +0 -5
  646. package/dist/webcomponents/p-2da57966.entry.js +0 -5
  647. package/dist/webcomponents/p-2e81b0b3.entry.js +0 -5
  648. package/dist/webcomponents/p-2eececed.entry.js +0 -5
  649. package/dist/webcomponents/p-2f904c4a.entry.js +0 -5
  650. package/dist/webcomponents/p-32414f1c.entry.js +0 -5
  651. package/dist/webcomponents/p-32ea6342.entry.js +0 -5
  652. package/dist/webcomponents/p-330ec8ab.entry.js +0 -5
  653. package/dist/webcomponents/p-374f83b1.entry.js +0 -5
  654. package/dist/webcomponents/p-3bcc2c58.entry.js +0 -5
  655. package/dist/webcomponents/p-3c7ce0e4.entry.js +0 -5
  656. package/dist/webcomponents/p-467842ca.entry.js +0 -5
  657. package/dist/webcomponents/p-53e71a8a.entry.js +0 -5
  658. package/dist/webcomponents/p-58bacbe1.entry.js +0 -5
  659. package/dist/webcomponents/p-5a5ed7d8.entry.js +0 -5
  660. package/dist/webcomponents/p-621f0fa8.entry.js +0 -5
  661. package/dist/webcomponents/p-6514a75d.entry.js +0 -5
  662. package/dist/webcomponents/p-678b43a6.entry.js +0 -5
  663. package/dist/webcomponents/p-6b6be415.entry.js +0 -5
  664. package/dist/webcomponents/p-6ff9b26e.entry.js +0 -5
  665. package/dist/webcomponents/p-992167bc.entry.js +0 -5
  666. package/dist/webcomponents/p-CXMwM9m4.js +0 -5
  667. package/dist/webcomponents/p-a21872bf.entry.js +0 -5
  668. package/dist/webcomponents/p-b8d4ace3.entry.js +0 -5
  669. package/dist/webcomponents/p-bf35e506.entry.js +0 -5
  670. package/dist/webcomponents/p-c09af3cd.entry.js +0 -5
  671. package/dist/webcomponents/p-c3e61c39.entry.js +0 -5
  672. package/dist/webcomponents/p-c6b2545a.entry.js +0 -5
  673. package/dist/webcomponents/p-cae39e13.entry.js +0 -5
  674. package/dist/webcomponents/p-cb690a87.entry.js +0 -5
  675. package/dist/webcomponents/p-d0be7243.entry.js +0 -5
  676. package/dist/webcomponents/p-d191c6e3.entry.js +0 -5
  677. package/dist/webcomponents/p-d3bd2c40.entry.js +0 -5
  678. package/dist/webcomponents/p-dbeea64e.entry.js +0 -5
  679. package/dist/webcomponents/p-df475129.entry.js +0 -5
  680. package/dist/webcomponents/p-e661c024.entry.js +0 -5
  681. package/dist/webcomponents/p-e6c6f305.entry.js +0 -5
  682. package/dist/webcomponents/p-e8291be2.entry.js +0 -5
  683. package/dist/webcomponents/p-f9084f16.entry.js +0 -5
  684. package/dist/webcomponents/p-fad3aa61.entry.js +0 -5
  685. /package/dist/collection/components/table/{table-types.js → table-footer/table-footer.types.js} +0 -0
  686. /package/dist/webcomponents/{p-zlORkiHQ.js → p-CXDYKUBz.js} +0 -0
@@ -2,331 +2,2498 @@
2
2
  * Construído por SERPRO
3
3
  * © https://serpro.gov.br/ - MIT License.
4
4
  */
5
- import { r as registerInstance, h, H as Host, g as getElement } from './index-ConyRdJe.js';
6
- import { g as generateUniqueId } from './id-BeJxz5TQ.js';
5
+ import { r as registerInstance, c as createEvent, f as forceUpdate, h, F as Fragment, H as Host, g as getElement } from './index-CwL52661.js';
6
+ import { H as Helpers } from './helpers-BNW9pAhl.js';
7
7
  import { f as findComposedOwner } from './ownership-CDtFCbKp.js';
8
- import { r as reportInvalidPropValue, c as clearInvalidPropWarning } from './prop-warning-BlGV-x0w.js';
9
- import { r as resolveAllowedPropValue, a as resolveDensity } from './props-D07GjR4_.js';
10
- import { b as TABLE_OVERFLOW, a as TABLE_TOOLTIP_STATE, C as COLUMN_WIDTH_MAP, c as COLUMN_WIDTH_SEMANTICS, d as TABLE_ALIGNMENT_MAP, e as TABLE_ALIGNMENT, f as TABLE_OVERFLOW_MAP, T as TABLE_TOOLTIP_MODE, g as TABLE_DENSITY_MAP, h as TABLE_DENSITY, i as TABLE_DIVIDER_STYLE_MAP, j as TABLE_DIVIDER_STYLE } from './table-constants-CXMwM9m4.js';
8
+ import { g as getTableRowGroups, a as getTableLeafHeaders, T as TABLE_SELECTION_GENERATED_ATTR, b as TABLE_EXPANSION_GENERATED_ATTR, c as getTablePlacements, r as resolveTableSpan, d as applyTablePlacements, e as TABLE_EXPANSION_COLUMN_ATTR, f as TABLE_EXPANSION_COLUMN_WIDTH, h as TABLE_ALIGNMENT, i as TABLE_EXPANSION_ACTION_ATTR, j as TABLE_ROW_EXPANSION, k as TABLE_SELECTION_CHECKBOX_ATTR, l as TABLE_SELECTION_COLUMN_ATTR, m as TABLE_SELECTION_COLUMN_WIDTH, n as expandTableGroupRange, o as TABLE_SORT_MODE, p as TABLE_SORT_STRATEGY, q as TABLE_OVERFLOW, s as TABLE_TOOLTIP_STATE, t as TableKeyboardController, u as TableScrollShadows, v as resolveTokenValue, w as TABLE_SORT_DIRECTION, x as isHydrationClassMutation, y as resolveTableDensityFromElement, z as applyTableHeaderLayout, C as COLUMN_WIDTH_MAP, A as COLUMN_WIDTH_SEMANTICS, B as TABLE_TOKENS, D as TABLE_ALIGNMENT_MAP, E as TABLE_OVERFLOW_MAP, F as TABLE_DENSITY, G as TABLE_DENSITY_MAP, H as TABLE_BAR_PADDING_MAP, I as TABLE_DIVIDER_STYLE_MAP, J as TABLE_DIVIDER_STYLE, K as positivePxValidator, L as positiveFrValidator } from './table.utils-CtVdlcgI.js';
9
+ import { g as getDeepActiveElement } from './focus-CNwZRgyL.js';
10
+ import './format-bytes-B7bNfmgh.js';
11
+ import './id-BeJxz5TQ.js';
11
12
 
13
+ /** Modelo lógico e materializador virtual da tabela. */
12
14
  /**
13
- * Tokens CSS utilizados pela tabela.
14
- * Centralizam variáveis customizadas para controle de layout e estilo.
15
+ * Converte a representação de conteúdo da API (`TableDataContent`) em nós DOM.
16
+ *
17
+ * Comportamento importante:
18
+ * - Se um item for uma instância de `Node`, a tabela irá reutilizá-lo tal qual
19
+ * (isto é, o nó é transferido para a célula com `appendChild()`). Ou seja,
20
+ * não é feita clonagem — o elemento é removido da sua posição anterior no DOM
21
+ * e passa a pertencer à célula da tabela.
22
+ * - Se o item não for um `Node`, será convertido em `TextNode` com `String(entry)`.
23
+ *
24
+ * Riscos e observações (resumido): clonagem externa é responsabilidade do
25
+ * consumidor quando necessário; event listeners adicionados via
26
+ * `addEventListener` não são clonados automaticamente; duplicação de `id`
27
+ * deve ser evitada ao reutilizar nós em múltiplos lugares.
28
+ *
29
+ * @param content Conteúdo fornecido pelo consumidor (Node | string | array)
30
+ * @returns Array de `Node` pronto para ser anexado à célula
31
+ */
32
+ const materializeContent = (content) => {
33
+ if (content === undefined || content === null)
34
+ return [];
35
+ const entries = Array.isArray(content) ? content : [content];
36
+ return entries.map((entry) => (entry instanceof Node ? entry : document.createTextNode(String(entry))));
37
+ };
38
+ const applyOptionalAttribute = (element, name, value) => {
39
+ if (value !== undefined && value !== null)
40
+ element.setAttribute(name, value);
41
+ };
42
+ /**
43
+ * Cria um elemento `br-table-action` a partir do descriptor público `TableActionData`.
44
+ * O elemento retornado ainda não está anexado ao host — quem chamar decide o slot.
45
+ */
46
+ const createAction = (data, slot) => {
47
+ const action = document.createElement('br-table-action');
48
+ action.setAttribute('label', data.label);
49
+ if (data.iconName !== undefined)
50
+ action.setAttribute('icon-name', data.iconName);
51
+ if (data.ariaLabel !== undefined)
52
+ action.setAttribute('aria-label', data.ariaLabel);
53
+ if (slot !== undefined)
54
+ action.setAttribute('slot', slot);
55
+ return action;
56
+ };
57
+ /**
58
+ * Constrói um `br-table-cell` a partir de `TableCellData`.
59
+ *
60
+ * Observação: o conteúdo passado em `data.content` será materializado via
61
+ * `materializeContent` e, se incluir `Node`, esses nós serão transferidos
62
+ * (movidos) para a célula.
63
+ */
64
+ const createCell = (data) => {
65
+ const cell = document.createElement('br-table-cell');
66
+ cell.toggleAttribute('row-header', Boolean(data.rowHeader));
67
+ if (data.colSpan !== undefined)
68
+ cell.setAttribute('col-span', String(data.colSpan));
69
+ if (data.rowSpan !== undefined)
70
+ cell.setAttribute('row-span', String(data.rowSpan));
71
+ applyOptionalAttribute(cell, 'horizontal-alignment', data.horizontalAlignment);
72
+ applyOptionalAttribute(cell, 'vertical-alignment', data.verticalAlignment);
73
+ applyOptionalAttribute(cell, 'overflow', data.overflow);
74
+ applyOptionalAttribute(cell, 'tooltip-state', data.tooltipState);
75
+ applyOptionalAttribute(cell, 'tooltip-mode', data.tooltipMode);
76
+ if (data.cellActionsLimit !== undefined)
77
+ cell.setAttribute('cell-actions-limit', String(data.cellActionsLimit));
78
+ if (data.sortValue !== undefined)
79
+ cell.setAttribute('sort-value', String(data.sortValue));
80
+ materializeContent(data.content).forEach((node) => {
81
+ cell.appendChild(node);
82
+ });
83
+ data.actions?.forEach((action) => {
84
+ cell.appendChild(createAction(action));
85
+ });
86
+ return cell;
87
+ };
88
+ /**
89
+ * Constrói um `br-table-header-cell` a partir de `TableColumnData`.
90
+ * Conteúdo é materializado com `materializeContent`.
91
+ */
92
+ const createColumn = (data) => {
93
+ const column = document.createElement('br-table-header-cell');
94
+ if (data.colSpan !== undefined)
95
+ column.setAttribute('col-span', String(data.colSpan));
96
+ if (data.rowSpan !== undefined)
97
+ column.setAttribute('row-span', String(data.rowSpan));
98
+ applyOptionalAttribute(column, 'column-width', data.columnWidth);
99
+ applyOptionalAttribute(column, 'horizontal-alignment', data.horizontalAlignment);
100
+ applyOptionalAttribute(column, 'vertical-alignment', data.verticalAlignment);
101
+ applyOptionalAttribute(column, 'overflow', data.overflow);
102
+ applyOptionalAttribute(column, 'tooltip-state', data.tooltipState);
103
+ applyOptionalAttribute(column, 'tooltip-mode', data.tooltipMode);
104
+ column.toggleAttribute('sortable', Boolean(data.sortable));
105
+ materializeContent(data.content).forEach((node) => {
106
+ column.appendChild(node);
107
+ });
108
+ return column;
109
+ };
110
+ /**
111
+ * Constrói um `br-table-row` a partir de `TableRowData`.
112
+ *
113
+ * Notas:
114
+ * - As células são criadas com `createCell` e anexadas ao `br-table-row`.
115
+ * - `expandedContent`, quando presente, é materializado e marcado com
116
+ * `slot="expanded-content"` para posterior renderização de conteúdo
117
+ * expandido; se o conteúdo for um nó não-`HTMLElement`, ele é embrulhado
118
+ * em um `span` com o slot apropriado.
119
+ */
120
+ const createRow = (data) => {
121
+ const row = document.createElement('br-table-row');
122
+ applyOptionalAttribute(row, 'row-group', data.rowGroup);
123
+ row.toggleAttribute('selected', Boolean(data.selected));
124
+ row.toggleAttribute('disabled', Boolean(data.disabled));
125
+ row.toggleAttribute('expanded', Boolean(data.expanded));
126
+ applyOptionalAttribute(row, 'row-expansion', data.rowExpansion);
127
+ if (data.virtualExpandedContentHeight !== undefined) {
128
+ row.setAttribute('virtual-expanded-content-height', String(data.virtualExpandedContentHeight));
129
+ }
130
+ applyOptionalAttribute(row, 'horizontal-alignment', data.horizontalAlignment);
131
+ applyOptionalAttribute(row, 'vertical-alignment', data.verticalAlignment);
132
+ applyOptionalAttribute(row, 'overflow', data.overflow);
133
+ applyOptionalAttribute(row, 'tooltip-state', data.tooltipState);
134
+ applyOptionalAttribute(row, 'tooltip-mode', data.tooltipMode);
135
+ data.cells.forEach((cell) => {
136
+ row.appendChild(createCell(cell));
137
+ });
138
+ materializeContent(data.expandedContent).forEach((contentNode) => {
139
+ let node = contentNode;
140
+ if (node instanceof HTMLElement)
141
+ node.setAttribute('slot', 'expanded-content');
142
+ else {
143
+ const wrapper = document.createElement('span');
144
+ wrapper.setAttribute('slot', 'expanded-content');
145
+ wrapper.appendChild(node);
146
+ node = wrapper;
147
+ }
148
+ row.appendChild(node);
149
+ });
150
+ return row;
151
+ };
152
+ /**
153
+ * Gerencia o modelo lógico e a materialização virtual da tabela.
154
+ *
155
+ * Responsabilidades principais:
156
+ * - Capturar marcação já presente no host (`capture`).
157
+ * - Substituir o conjunto lógico por dados programáticos (`replace`).
158
+ * - Materializar a janela virtual, preservando linhas já montadas (`mount`, `renderRange`).
159
+ *
160
+ * Observação sobre materialização de conteúdo:
161
+ * - Quando `TableDataContent` contém nós (`Node`), esses nós são
162
+ * transferidos para as células usando `appendChild()` (re-anexação no DOM).
163
+ * Não há clonagem automática; consumidores que precisam preservar o
164
+ * nó original devem clonar antes de passá-lo à tabela.
165
+ */
166
+ class TableDataStore {
167
+ constructor() {
168
+ this.data = {
169
+ headerRows: [],
170
+ columns: [],
171
+ rows: [],
172
+ globalActions: [],
173
+ contextualActions: [],
174
+ };
175
+ this.body = null;
176
+ this.rowElements = [];
177
+ this.renderedRows = [];
178
+ }
179
+ /** Invalida apenas as unidades derivadas quando uma chave de grupo muda. */
180
+ invalidateGroups() {
181
+ this.itemGroups = undefined;
182
+ this.pageBoundaries = undefined;
183
+ }
184
+ getItemGroups() {
185
+ this.itemGroups ?? (this.itemGroups = getTableRowGroups(this.rowElements));
186
+ return this.itemGroups;
187
+ }
188
+ capture(host) {
189
+ const headerRows = Array.from(host.querySelectorAll('br-table-header > br-table-row'));
190
+ if (headerRows.length === 0)
191
+ headerRows.push(document.createElement('br-table-row'));
192
+ const columns = getTableLeafHeaders(headerRows)
193
+ .filter((el) => !el.hasAttribute(TABLE_SELECTION_GENERATED_ATTR) && !el.hasAttribute(TABLE_EXPANSION_GENERATED_ATTR))
194
+ .map((element) => ({ element }));
195
+ const rows = Array.from(host.querySelectorAll('br-table-row'))
196
+ .filter((row) => row.closest('br-table-header') === null)
197
+ .map((row, index) => {
198
+ row.setAttribute('data-virtual-index', String(index));
199
+ const cells = Array.from(row.querySelectorAll('br-table-cell'))
200
+ .filter((cell) => !cell.hasAttribute(TABLE_SELECTION_GENERATED_ATTR) && !cell.hasAttribute(TABLE_EXPANSION_GENERATED_ATTR))
201
+ .map((cell) => ({ element: cell }));
202
+ return {
203
+ element: row,
204
+ cells,
205
+ originalIndex: index,
206
+ };
207
+ });
208
+ const actions = Array.from(host.children).filter((el) => el.tagName.toLowerCase() === 'br-table-action');
209
+ this.data = {
210
+ headerRows,
211
+ columns,
212
+ rows,
213
+ globalActions: actions
214
+ .filter((el) => el.getAttribute('slot') === 'global-actions')
215
+ .map((element) => ({ element })),
216
+ contextualActions: actions
217
+ .filter((el) => el.getAttribute('slot') === 'contextual-actions')
218
+ .map((element) => ({ element })),
219
+ };
220
+ this.refreshRowElements();
221
+ }
222
+ replace(data) {
223
+ const rows = data.rows.map((rowData, index) => {
224
+ const element = createRow(rowData);
225
+ element.setAttribute('data-virtual-index', String(index));
226
+ return {
227
+ element,
228
+ cells: Array.from(element.querySelectorAll('br-table-cell')).map((cell) => ({
229
+ element: cell,
230
+ })),
231
+ originalIndex: index,
232
+ };
233
+ });
234
+ const headerRows = (data.headerRows?.length ? data.headerRows : [data.columns]).map((cells) => {
235
+ const row = document.createElement('br-table-row');
236
+ row.append(...cells.map(createColumn));
237
+ return row;
238
+ });
239
+ this.data = {
240
+ headerRows,
241
+ columns: getTableLeafHeaders(headerRows).map((element) => ({ element })),
242
+ rows,
243
+ globalActions: (data.globalActions ?? []).map((action) => ({ element: createAction(action, 'global-actions') })),
244
+ contextualActions: (data.contextualActions ?? []).map((action) => ({
245
+ element: createAction(action, 'contextual-actions'),
246
+ })),
247
+ };
248
+ this.refreshRowElements();
249
+ }
250
+ mount(host) {
251
+ const header = document.createElement('br-table-header');
252
+ header.setAttribute('slot', 'header');
253
+ header.append(...this.data.headerRows);
254
+ this.body = document.createElement('br-table-body');
255
+ this.body.setAttribute('slot', 'body');
256
+ this.renderedRows = [];
257
+ Array.from(host.children)
258
+ .filter((child) => {
259
+ const tag = child.tagName.toLowerCase();
260
+ const slot = child.getAttribute('slot');
261
+ return (tag === 'br-table-header' ||
262
+ tag === 'br-table-body' ||
263
+ (tag === 'br-table-action' && (slot === 'global-actions' || slot === 'contextual-actions')));
264
+ })
265
+ .forEach((child) => {
266
+ child.remove();
267
+ });
268
+ this.data.globalActions.forEach(({ element }) => {
269
+ host.appendChild(element);
270
+ });
271
+ this.data.contextualActions.forEach(({ element }) => {
272
+ host.appendChild(element);
273
+ });
274
+ host.appendChild(header);
275
+ host.appendChild(this.body);
276
+ }
277
+ /**
278
+ * Reordena o dataset lógico completo antes da materialização virtual.
279
+ * Critérios com menor `columnIndex` possuem maior prioridade no multi-sort.
280
+ */
281
+ sortRows(sorting) {
282
+ const criteria = [...sorting].sort((a, b) => a.columnIndex - b.columnIndex);
283
+ const byElement = new Map(this.data.rows.map((row) => [row.element, row]));
284
+ const groups = getTableRowGroups(this.rowElements).map((group) => group.flatMap((row) => {
285
+ const entry = byElement.get(row);
286
+ return entry ? [entry] : [];
287
+ }));
288
+ groups.sort((groupA, groupB) => {
289
+ const rowA = groupA[0];
290
+ const rowB = groupB[0];
291
+ for (const criterion of criteria) {
292
+ const valueA = this.getSortValue(rowA, criterion.columnIndex);
293
+ const valueB = this.getSortValue(rowB, criterion.columnIndex);
294
+ const comparison = this.compareSortValues(valueA, valueB);
295
+ if (comparison !== 0) {
296
+ return criterion.direction === 'asc' ? comparison : -comparison;
297
+ }
298
+ }
299
+ return rowA.originalIndex - rowB.originalIndex;
300
+ });
301
+ this.data.rows = groups.flat();
302
+ this.data.rows.forEach(({ element }, index) => {
303
+ element.setAttribute('data-virtual-index', String(index));
304
+ });
305
+ this.refreshRowElements();
306
+ }
307
+ /** Retorna as colunas lógicas, sem as colunas geradas de seleção/expansão. */
308
+ getColumns() {
309
+ return getTableLeafHeaders(this.data.headerRows).filter((cell) => !cell.hasAttribute(TABLE_SELECTION_GENERATED_ATTR) && !cell.hasAttribute(TABLE_EXPANSION_GENERATED_ATTR));
310
+ }
311
+ getSortValue(row, columnIndex) {
312
+ const cell = getTablePlacements([row.element], 'br-table-cell')
313
+ .filter(({ cell }) => !cell.hasAttribute(TABLE_SELECTION_GENERATED_ATTR) && !cell.hasAttribute(TABLE_EXPANSION_GENERATED_ATTR))
314
+ .find((entry) => {
315
+ const column = columnIndex + this.generatedColumnCount();
316
+ return column >= entry.column && column < entry.column + entry.colSpan;
317
+ })?.cell;
318
+ if (cell === undefined)
319
+ return '';
320
+ const explicitValue = cell.getAttribute('sort-value');
321
+ if (explicitValue !== null)
322
+ return explicitValue.trim();
323
+ return cell.textContent?.trim() ?? '';
324
+ }
325
+ generatedColumnCount() {
326
+ return (this.rowElements[0]?.querySelectorAll(`:scope > [${TABLE_SELECTION_GENERATED_ATTR}], :scope > [${TABLE_EXPANSION_GENERATED_ATTR}]`).length ?? 0);
327
+ }
328
+ /** Itens lógicos de paginação: grupos contíguos ou linhas independentes. */
329
+ getItemCount() {
330
+ return this.getItemGroups().length;
331
+ }
332
+ /** Limites físicos da página, sem dividir grupos. */
333
+ getPageRange(startItem, itemCount) {
334
+ if (!this.pageBoundaries) {
335
+ const boundaries = [0];
336
+ this.getItemGroups().forEach((group) => {
337
+ boundaries.push(boundaries[boundaries.length - 1] + group.length);
338
+ });
339
+ this.pageBoundaries = boundaries;
340
+ }
341
+ const count = this.pageBoundaries.length - 1;
342
+ return {
343
+ start: this.pageBoundaries[Math.min(startItem, count)],
344
+ end: this.pageBoundaries[Math.min(startItem + itemCount, count)],
345
+ };
346
+ }
347
+ compareSortValues(valueA, valueB) {
348
+ return valueA.localeCompare(valueB, 'pt-BR', {
349
+ numeric: true,
350
+ sensitivity: 'base',
351
+ });
352
+ }
353
+ renderRange(range, rows = this.data.rows, indexOffset = 0) {
354
+ const body = this.body;
355
+ if (body === null)
356
+ return;
357
+ const focused = body.contains(document.activeElement) ? getDeepActiveElement() : null;
358
+ const children = [];
359
+ const renderedRows = [];
360
+ const addSpacer = (height, position) => {
361
+ if (height <= 0)
362
+ return;
363
+ const spacer = body.querySelector(`:scope > [data-table-virtual-spacer="${position}"]`) ??
364
+ this.createSpacer(height, position);
365
+ spacer.style.height = `${height}px`;
366
+ children.push(spacer);
367
+ };
368
+ addSpacer(range.beforeHeight, 'before');
369
+ const rangeRows = rows.slice(range.start, range.end).map(({ element }) => element);
370
+ let logicalIndex = range.start;
371
+ for (const group of getTableRowGroups(rangeRows)) {
372
+ if (group.length > 1 ||
373
+ group[0].hasAttribute('row-group') ||
374
+ Array.from(group[0].children).some((cell) => resolveTableSpan(cell.getAttribute('col-span')) > 1)) {
375
+ const first = group[0];
376
+ const wrapper = first.parentElement?.hasAttribute('data-table-row-group')
377
+ ? first.parentElement
378
+ : document.createElement('div');
379
+ wrapper.setAttribute('data-table-row-group', '');
380
+ wrapper.setAttribute('role', 'presentation');
381
+ let expandedRow = group.length + 1;
382
+ group.forEach((row) => {
383
+ // Detalhes ficam após as linhas do grupo para não sobrepor suas células mescladas.
384
+ row.style.setProperty('--table-expanded-grid-row', String(expandedRow));
385
+ if (row.hasAttribute('expanded'))
386
+ expandedRow++;
387
+ });
388
+ applyTablePlacements(getTablePlacements(group, 'br-table-cell'));
389
+ group.forEach((row) => {
390
+ row.setAttribute('data-virtual-index', String(logicalIndex++ + indexOffset));
391
+ if (row.parentElement !== wrapper)
392
+ wrapper.append(row);
393
+ renderedRows.push(row);
394
+ });
395
+ children.push(wrapper);
396
+ continue;
397
+ }
398
+ const index = logicalIndex++;
399
+ const row = rows[index]?.element;
400
+ if (row === undefined)
401
+ continue;
402
+ row.style.removeProperty('--table-expanded-grid-row');
403
+ row.querySelectorAll(':scope > br-table-cell').forEach((cell) => {
404
+ cell.style.removeProperty('--table-cell-grid-column');
405
+ cell.style.removeProperty('--table-cell-grid-row');
406
+ });
407
+ row.setAttribute('data-virtual-index', String(index + indexOffset));
408
+ children.push(row);
409
+ renderedRows.push(row);
410
+ }
411
+ addSpacer(range.afterHeight, 'after');
412
+ const retained = new Set(children);
413
+ Array.from(body.children).forEach((child) => {
414
+ if (!retained.has(child))
415
+ child.remove();
416
+ });
417
+ // Preserva conexão, hover e foco das linhas que continuam na mesma posição.
418
+ let next = body.firstElementChild;
419
+ children.forEach((child) => {
420
+ if (child !== next)
421
+ body.insertBefore(child, next);
422
+ next = child.nextElementSibling;
423
+ });
424
+ this.renderedRows = renderedRows;
425
+ if (focused instanceof HTMLElement && focused.isConnected && getDeepActiveElement() !== focused) {
426
+ focused.focus({ preventScroll: true });
427
+ }
428
+ }
429
+ getRows() {
430
+ return this.rowElements.slice();
431
+ }
432
+ /** Visão interna somente leitura, estável até a ordem, os dados ou o recorte mudarem. */
433
+ getRowsView(start = 0, end = this.rowElements.length) {
434
+ if (start === 0 && end === this.rowElements.length)
435
+ return this.rowElements;
436
+ const view = this.rowView;
437
+ if (view?.source === this.rowElements && view.start === start && view.end === end)
438
+ return view.rows;
439
+ const rows = this.rowElements.slice(start, end);
440
+ this.rowView = { source: this.rowElements, start, end, rows };
441
+ return rows;
442
+ }
443
+ refreshRowElements() {
444
+ this.invalidateGroups();
445
+ this.rowElements = this.data.rows.map(({ element }) => element);
446
+ this.rowView = undefined;
447
+ }
448
+ getRow(index) {
449
+ return this.data.rows[index]?.element;
450
+ }
451
+ getRowCount() {
452
+ return this.data.rows.length;
453
+ }
454
+ getRenderedRows() {
455
+ return this.renderedRows.filter((row) => row.isConnected);
456
+ }
457
+ createSpacer(height, position) {
458
+ const spacer = document.createElement('div');
459
+ spacer.setAttribute('data-table-virtual-spacer', position);
460
+ spacer.setAttribute('role', 'presentation');
461
+ spacer.style.gridColumn = '1 / -1';
462
+ spacer.style.height = `${Math.max(0, height)}px`;
463
+ spacer.style.pointerEvents = 'none';
464
+ return spacer;
465
+ }
466
+ }
467
+
468
+ /**
469
+ * Factories dos elementos utilizados pela expansão de linhas.
470
+ *
471
+ * @module table-expansion-elements
472
+ */
473
+ /**
474
+ * Sincroniza ícone, rótulos e estado acessível da ação de expansão.
475
+ *
476
+ * @param action Componente de ação que será atualizado.
477
+ * @param expanded Estado atual da linha.
478
+ * @param rowIndex Índice da linha no corpo, começando em zero.
479
+ */
480
+ function syncExpansionAction(action, expanded, rowIndex) {
481
+ const stateLabel = expanded ? 'Recolher' : 'Expandir';
482
+ action.setAttribute('label', `${stateLabel} linha ${rowIndex + 1}`);
483
+ action.setAttribute('aria-label', `${stateLabel} linha ${rowIndex + 1}`);
484
+ action.setAttribute('icon-name', expanded ? 'fa-solid:chevron-up' : 'fa-solid:chevron-down');
485
+ action.setAttribute('aria-expanded', String(expanded));
486
+ }
487
+ /**
488
+ * Cria uma ação de expansão reutilizando `br-table-action`.
489
+ *
490
+ * @param options Estado inicial e índice da linha.
491
+ * @returns Ação identificada para consumo interno do controller.
492
+ */
493
+ function createExpansionAction({ expanded, rowIndex }) {
494
+ const action = document.createElement('br-table-action');
495
+ action.setAttribute(TABLE_EXPANSION_ACTION_ATTR, '');
496
+ syncExpansionAction(action, expanded, rowIndex);
497
+ return action;
498
+ }
499
+ /**
500
+ * Cria a célula estrutural da coluna de expansão.
501
+ *
502
+ * @param action Ação opcional; linhas desabilitadas utilizam célula vazia.
503
+ * @returns Célula marcada como gerada pelo controller de expansão.
504
+ */
505
+ function createExpansionCell(action) {
506
+ const cell = document.createElement('br-table-cell');
507
+ cell.setAttribute(TABLE_EXPANSION_COLUMN_ATTR, '');
508
+ cell.setAttribute(TABLE_EXPANSION_GENERATED_ATTR, '');
509
+ cell.setAttribute('horizontal-alignment', TABLE_ALIGNMENT.CENTER);
510
+ cell.setAttribute('vertical-alignment', TABLE_ALIGNMENT.CENTER);
511
+ if (action !== undefined)
512
+ cell.appendChild(action);
513
+ return cell;
514
+ }
515
+ /**
516
+ * Cria o cabeçalho vazio que define a coluna de expansão no grid.
517
+ *
518
+ * @param slotName Slot utilizado pelos demais cabeçalhos.
519
+ * @returns Cabeçalho com largura e alinhamentos apropriados ao chevron.
520
+ */
521
+ function createExpansionHeaderCell(slotName) {
522
+ const cell = document.createElement('br-table-header-cell');
523
+ cell.setAttribute(TABLE_EXPANSION_COLUMN_ATTR, '');
524
+ cell.setAttribute(TABLE_EXPANSION_GENERATED_ATTR, '');
525
+ cell.setAttribute('column-width', TABLE_EXPANSION_COLUMN_WIDTH);
526
+ cell.setAttribute('horizontal-alignment', TABLE_ALIGNMENT.CENTER);
527
+ cell.setAttribute('vertical-alignment', TABLE_ALIGNMENT.CENTER);
528
+ cell.setAttribute('aria-label', 'Expansão de linha');
529
+ if (slotName !== undefined)
530
+ cell.setAttribute('slot', slotName);
531
+ return cell;
532
+ }
533
+
534
+ /**
535
+ * Controller responsável pela expansão de linhas.
536
+ *
537
+ * @module table-expansion
538
+ */
539
+ /**
540
+ * Coordena a coluna, as ações e o estado de expansão das linhas.
541
+ *
542
+ * @remarks A coluna permanece estruturalmente alinhada mesmo em linhas desabilitadas.
543
+ */
544
+ class TableExpansionController {
545
+ constructor(options) {
546
+ this.options = options;
547
+ }
548
+ /**
549
+ * Sincroniza a estrutura segundo a configuração global e os overrides das linhas.
550
+ *
551
+ * @param tableEnabled Indica se a expansão está habilitada na tabela.
552
+ */
553
+ sync(tableEnabled) {
554
+ const rows = this.getBodyRows();
555
+ const hasExpandableRows = rows.some((row) => this.isRowEnabled(row, tableEnabled));
556
+ if (!hasExpandableRows) {
557
+ this.removeColumn();
558
+ return;
559
+ }
560
+ this.ensureHeaderCell();
561
+ rows.forEach((row, rowIndex) => {
562
+ this.syncRow(row, rowIndex, tableEnabled);
563
+ });
564
+ }
565
+ /**
566
+ * Consome cliques originados pelas ações internas de expansão.
567
+ *
568
+ * @param event Evento emitido por `br-table-action`.
569
+ * @returns `true` quando o evento foi tratado como expansão.
570
+ */
571
+ handleActionClick(event) {
572
+ const action = event
573
+ .composedPath()
574
+ .find((node) => node instanceof HTMLElement &&
575
+ node.tagName.toLowerCase() === 'br-table-action' &&
576
+ node.hasAttribute(TABLE_EXPANSION_ACTION_ATTR));
577
+ if (action === undefined)
578
+ return false;
579
+ const row = action.closest('br-table-row');
580
+ if (row === null)
581
+ return false;
582
+ if (row.hasAttribute('disabled'))
583
+ return true;
584
+ this.setExpanded(row, !row.hasAttribute('expanded'), 'action');
585
+ return true;
586
+ }
587
+ /**
588
+ * Define o estado de expansão de uma linha elegível.
589
+ *
590
+ * @param row Linha que receberá a mudança.
591
+ * @param expanded Novo estado de expansão.
592
+ * @param source Origem utilizada no evento público.
593
+ */
594
+ setExpanded(row, expanded, source = 'programmatic') {
595
+ if (!row.hasAttribute('data-row-expansion-enabled'))
596
+ return;
597
+ row.toggleAttribute('expanded', expanded);
598
+ row.removeAttribute('aria-expanded');
599
+ this.syncRowAction(row);
600
+ const rows = this.getBodyRows();
601
+ this.options.onChange({ row, rowIndex: rows.indexOf(row), expanded, source });
602
+ }
603
+ /**
604
+ * Recolhe todas as linhas atualmente expandidas.
605
+ */
606
+ collapseAll() {
607
+ this.getBodyRows().forEach((row) => {
608
+ if (row.hasAttribute('expanded'))
609
+ this.setExpanded(row, false);
610
+ });
611
+ }
612
+ getBodyRows() {
613
+ if (this.options.getRows !== undefined) {
614
+ return this.options.getRows();
615
+ }
616
+ return Array.from(this.options.host.querySelectorAll('br-table-row')).filter((row) => row.closest('br-table-header') === null);
617
+ }
618
+ /**
619
+ * Resolve o override declarado diretamente na linha.
620
+ */
621
+ getRowOverride(row) {
622
+ const value = row.getAttribute('row-expansion');
623
+ if (value === TABLE_ROW_EXPANSION.ENABLED)
624
+ return true;
625
+ if (value === TABLE_ROW_EXPANSION.DISABLED)
626
+ return false;
627
+ return undefined;
628
+ }
629
+ isRowEnabled(row, tableEnabled) {
630
+ const override = this.getRowOverride(row);
631
+ return override ?? tableEnabled;
632
+ }
633
+ /**
634
+ * Garante que a coluna de expansão permaneça na primeira posição.
635
+ */
636
+ ensureHeaderCell() {
637
+ const firstHeader = this.options.host.querySelector('br-table-header-cell');
638
+ if (firstHeader === null)
639
+ return;
640
+ let cell = this.options.host.querySelector(`br-table-header-cell[${TABLE_EXPANSION_GENERATED_ATTR}]`);
641
+ if (cell === null) {
642
+ const slotName = firstHeader.getAttribute('slot');
643
+ cell = createExpansionHeaderCell(slotName ?? undefined);
644
+ }
645
+ const parent = firstHeader.parentElement;
646
+ if (parent !== null && parent.firstElementChild !== cell)
647
+ parent.prepend(cell);
648
+ }
649
+ /**
650
+ * Sincroniza ação, célula estrutural e atributos de uma linha.
651
+ */
652
+ syncRow(row, rowIndex, tableEnabled) {
653
+ let cell = row.querySelector(`br-table-cell[${TABLE_EXPANSION_GENERATED_ATTR}]`);
654
+ if (!this.isRowEnabled(row, tableEnabled)) {
655
+ if (cell === null) {
656
+ cell = createExpansionCell();
657
+ row.prepend(cell);
658
+ }
659
+ else {
660
+ cell.replaceChildren();
661
+ }
662
+ row.removeAttribute('data-row-expansion-enabled');
663
+ row.removeAttribute('expanded');
664
+ row.removeAttribute('aria-expanded');
665
+ if (row.firstElementChild !== cell)
666
+ row.prepend(cell);
667
+ return;
668
+ }
669
+ row.setAttribute('data-row-expansion-enabled', '');
670
+ if (cell === null) {
671
+ const action = createExpansionAction({ expanded: row.hasAttribute('expanded'), rowIndex });
672
+ cell = createExpansionCell(action);
673
+ row.prepend(cell);
674
+ }
675
+ else if (cell.querySelector(`br-table-action[${TABLE_EXPANSION_ACTION_ATTR}]`) === null) {
676
+ cell.appendChild(createExpansionAction({ expanded: row.hasAttribute('expanded'), rowIndex }));
677
+ }
678
+ row.removeAttribute('aria-expanded');
679
+ if (row.firstElementChild !== cell)
680
+ row.prepend(cell);
681
+ this.syncRowAction(row, rowIndex);
682
+ }
683
+ /**
684
+ * Atualiza ícone e rótulos da ação pertencente à linha.
685
+ */
686
+ syncRowAction(row, rowIndex) {
687
+ const action = row.querySelector(`br-table-action[${TABLE_EXPANSION_ACTION_ATTR}]`);
688
+ if (action === null)
689
+ return;
690
+ const resolvedIndex = rowIndex ?? this.getBodyRows().indexOf(row);
691
+ syncExpansionAction(action, row.hasAttribute('expanded'), resolvedIndex);
692
+ }
693
+ /**
694
+ * Remove somente os elementos e atributos gerados pela expansão.
695
+ */
696
+ removeColumn() {
697
+ this.options.host.querySelectorAll(`[${TABLE_EXPANSION_GENERATED_ATTR}]`).forEach((node) => {
698
+ node.remove();
699
+ });
700
+ this.getBodyRows().forEach((row) => {
701
+ row.removeAttribute('data-row-expansion-enabled');
702
+ row.removeAttribute('expanded');
703
+ row.removeAttribute('aria-expanded');
704
+ });
705
+ }
706
+ }
707
+
708
+ /**
709
+ * Factories dos elementos utilizados pela seleção de linhas.
710
+ *
711
+ * @module table-selection-elements
712
+ */
713
+ /**
714
+ * Cria uma instância configurada do componente `br-checkbox`.
715
+ *
716
+ * @param options Categoria, rótulo acessível e nome do controle.
717
+ * @returns Checkbox pronto para ser anexado a uma célula.
718
+ */
719
+ function createSelectionCheckbox({ kind, label, name }) {
720
+ const checkbox = document.createElement('br-checkbox');
721
+ checkbox.setAttribute(TABLE_SELECTION_CHECKBOX_ATTR, kind);
722
+ checkbox.setAttribute('compact', '');
723
+ checkbox.setAttribute('has-hidden-label', '');
724
+ checkbox.setAttribute('label', label);
725
+ checkbox.setAttribute('name', name);
726
+ return checkbox;
727
+ }
728
+ /**
729
+ * Cria a célula estrutural de seleção de uma linha.
730
+ *
731
+ * @param checkbox Controle associado à linha.
732
+ * @returns Célula marcada como gerada pelo controller de seleção.
733
+ */
734
+ function createSelectionCell(checkbox) {
735
+ const cell = document.createElement('br-table-cell');
736
+ cell.setAttribute(TABLE_SELECTION_COLUMN_ATTR, '');
737
+ cell.setAttribute(TABLE_SELECTION_GENERATED_ATTR, '');
738
+ cell.setAttribute('horizontal-alignment', TABLE_ALIGNMENT.CENTER);
739
+ cell.setAttribute('vertical-alignment', TABLE_ALIGNMENT.CENTER);
740
+ cell.appendChild(checkbox);
741
+ return cell;
742
+ }
743
+ /**
744
+ * Cria o cabeçalho que define largura e alinhamentos da coluna de seleção.
745
+ *
746
+ * @param options Checkbox global e slot opcional do cabeçalho.
747
+ * @returns Cabeçalho configurado para participar do grid da tabela.
748
+ */
749
+ function createSelectionHeaderCell({ checkbox, slotName, }) {
750
+ const cell = document.createElement('br-table-header-cell');
751
+ cell.setAttribute(TABLE_SELECTION_COLUMN_ATTR, '');
752
+ cell.setAttribute(TABLE_SELECTION_GENERATED_ATTR, '');
753
+ cell.setAttribute('horizontal-alignment', TABLE_ALIGNMENT.CENTER);
754
+ cell.setAttribute('vertical-alignment', TABLE_ALIGNMENT.CENTER);
755
+ /*
756
+ * A tabela consulta esses atributos antes de o Custom Element necessariamente
757
+ * concluir seu upgrade; por isso a configuração inicial utiliza atributos.
758
+ */
759
+ cell.setAttribute('column-width', TABLE_SELECTION_COLUMN_WIDTH);
760
+ if (slotName !== undefined) {
761
+ cell.setAttribute('slot', slotName);
762
+ }
763
+ cell.appendChild(checkbox);
764
+ return cell;
765
+ }
766
+
767
+ /**
768
+ * Controller responsável pela seleção de linhas.
769
+ *
770
+ * @module table-selection
771
+ */
772
+ /**
773
+ * Coordena a estrutura e o estado da seleção sem acoplar regras ao componente raiz.
774
+ *
775
+ * @remarks O controller mantém checkbox, atributos da linha, ARIA e cabeçalho sincronizados.
776
+ */
777
+ class TableSelectionController {
778
+ constructor(options) {
779
+ this.options = options;
780
+ this.isSynchronizing = false;
781
+ this.checkboxDisabledStates = new WeakMap();
782
+ }
783
+ /**
784
+ * Sincroniza a coluna de seleção com a configuração atual da tabela.
785
+ *
786
+ * @param enabled Indica se a seleção está habilitada globalmente.
787
+ */
788
+ sync(enabled) {
789
+ if (!enabled) {
790
+ this.remove();
791
+ return;
792
+ }
793
+ this.ensureHeaderCell();
794
+ this.ensureRowCells();
795
+ this.syncRowsFromState();
796
+ this.syncHeaderCheckbox();
797
+ }
798
+ /**
799
+ * Processa eventos emitidos exclusivamente pelos checkboxes gerados.
800
+ *
801
+ * @param event Evento `checkedChange` recebido pela tabela.
802
+ * @returns `true` quando o evento pertencia ao subsistema de seleção.
803
+ */
804
+ handleCheckboxChange(event) {
805
+ const checkbox = this.getCheckboxFromEvent(event);
806
+ if (checkbox === null || this.isSynchronizing)
807
+ return false;
808
+ const kind = checkbox.getAttribute(TABLE_SELECTION_CHECKBOX_ATTR);
809
+ if (kind === 'all') {
810
+ this.selectAll(Boolean(event.detail), 'all');
811
+ return true;
812
+ }
813
+ if (kind !== 'row')
814
+ return false;
815
+ const row = checkbox.closest('br-table-row');
816
+ const rowIndex = row instanceof HTMLElement ? this.getBodyRows().indexOf(row) : -1;
817
+ if (row instanceof HTMLElement) {
818
+ this.applyRowState(row, Boolean(event.detail));
819
+ }
820
+ this.syncHeaderCheckbox();
821
+ this.notifyChange('row', rowIndex >= 0 ? rowIndex : undefined);
822
+ return true;
823
+ }
824
+ /**
825
+ * Retorna o estado de seleção derivado das linhas do corpo.
826
+ *
827
+ * @returns Linhas que possuem `selected` ou `data-selected`.
828
+ */
829
+ getSelectedRows() {
830
+ return this.getBodyRows().filter((row) => row.hasAttribute('selected') || row.hasAttribute('data-selected'));
831
+ }
832
+ /**
833
+ * Aplica o mesmo estado a todas as linhas selecionáveis.
834
+ *
835
+ * @param selected Novo estado das linhas.
836
+ * @param source Origem utilizada no evento de mudança.
837
+ */
838
+ selectAll(selected, source = 'programmatic') {
839
+ const entries = this.getSelectableEntries();
840
+ this.isSynchronizing = true;
841
+ entries.forEach(({ checkbox, row }) => {
842
+ checkbox.checked = selected;
843
+ this.applyRowState(row, selected);
844
+ });
845
+ this.isSynchronizing = false;
846
+ this.syncHeaderCheckbox();
847
+ this.notifyChange(source);
848
+ }
849
+ /**
850
+ * Limpa todas as linhas selecionáveis.
851
+ *
852
+ * @param source Origem utilizada no evento de mudança.
853
+ */
854
+ clear(source = 'programmatic') {
855
+ this.selectAll(false, source);
856
+ }
857
+ getCheckboxFromEvent(event) {
858
+ const target = event
859
+ .composedPath()
860
+ .find((node) => node?.tagName?.toLowerCase() === 'br-checkbox');
861
+ return target?.hasAttribute(TABLE_SELECTION_CHECKBOX_ATTR) ? target : null;
862
+ }
863
+ getBodyRows() {
864
+ if (this.options.getRows !== undefined)
865
+ return this.options.getRows();
866
+ return Array.from(this.options.host.querySelectorAll('br-table-row')).filter((row) => row.closest('br-table-header') === null);
867
+ }
868
+ getRowCheckbox(row) {
869
+ return row.querySelector(`br-checkbox[${TABLE_SELECTION_CHECKBOX_ATTR}="row"]`);
870
+ }
871
+ getSelectableEntries() {
872
+ return this.getBodyRows().flatMap((row) => {
873
+ const checkbox = this.getRowCheckbox(row);
874
+ const disabled = row.hasAttribute('disabled') || checkbox?.hasAttribute('disabled') === true;
875
+ return checkbox === null || disabled ? [] : [{ row, checkbox }];
876
+ });
877
+ }
878
+ getHeaderCheckbox() {
879
+ return this.options.host.querySelector(`br-table-header-cell[${TABLE_SELECTION_COLUMN_ATTR}] br-checkbox[${TABLE_SELECTION_CHECKBOX_ATTR}="all"]`);
880
+ }
881
+ /**
882
+ * Atualiza o estado visual e acessível de uma linha.
883
+ */
884
+ applyRowState(row, selected) {
885
+ row.toggleAttribute('selected', selected);
886
+ row.toggleAttribute('data-selected', selected);
887
+ row.setAttribute('aria-selected', String(selected));
888
+ }
889
+ syncRowsFromState() {
890
+ this.isSynchronizing = true;
891
+ this.getBodyRows().forEach((row) => {
892
+ const selected = row.hasAttribute('selected') || row.hasAttribute('data-selected');
893
+ this.applyRowState(row, selected);
894
+ const checkbox = this.getRowCheckbox(row);
895
+ if (checkbox !== null) {
896
+ checkbox.checked = selected;
897
+ this.syncCheckboxDisabledState(row, checkbox);
898
+ }
899
+ });
900
+ this.isSynchronizing = false;
901
+ }
902
+ syncCheckboxDisabledState(row, checkbox) {
903
+ const hasPreviousDisabledState = this.checkboxDisabledStates.has(checkbox);
904
+ if (row.hasAttribute('disabled')) {
905
+ if (!hasPreviousDisabledState) {
906
+ this.checkboxDisabledStates.set(checkbox, checkbox.disabled);
907
+ }
908
+ checkbox.disabled = true;
909
+ }
910
+ else if (hasPreviousDisabledState) {
911
+ checkbox.disabled = this.checkboxDisabledStates.get(checkbox) ?? false;
912
+ this.checkboxDisabledStates.delete(checkbox);
913
+ }
914
+ }
915
+ /**
916
+ * Sincroniza o checkbox global, incluindo o estado indeterminado.
917
+ */
918
+ syncHeaderCheckbox() {
919
+ const headerCheckbox = this.getHeaderCheckbox();
920
+ if (headerCheckbox === null)
921
+ return;
922
+ const entries = this.getSelectableEntries();
923
+ const checkedCount = entries.filter(({ checkbox }) => checkbox.checked).length;
924
+ this.isSynchronizing = true;
925
+ headerCheckbox.checked = entries.length > 0 && checkedCount === entries.length;
926
+ headerCheckbox.indeterminate = checkedCount > 0 && checkedCount < entries.length;
927
+ this.isSynchronizing = false;
928
+ }
929
+ /**
930
+ * Garante a existência do cabeçalho da coluna de seleção.
931
+ */
932
+ ensureHeaderCell() {
933
+ const existing = this.options.host.querySelector(`br-table-header-cell[${TABLE_SELECTION_GENERATED_ATTR}]`);
934
+ if (existing !== null)
935
+ return;
936
+ const firstHeaderCell = this.options.host.querySelector('br-table-header-cell');
937
+ if (firstHeaderCell === null)
938
+ return;
939
+ const slotName = firstHeaderCell.getAttribute('slot');
940
+ const checkbox = createSelectionCheckbox({
941
+ kind: 'all',
942
+ label: 'Selecionar todas as linhas',
943
+ name: `${this.options.idPrefix}-selection-all`,
944
+ });
945
+ const cell = createSelectionHeaderCell({
946
+ checkbox,
947
+ slotName: slotName ?? undefined,
948
+ });
949
+ firstHeaderCell.parentElement?.insertBefore(cell, firstHeaderCell);
950
+ }
951
+ /**
952
+ * Garante uma célula de seleção para cada linha do corpo.
953
+ */
954
+ ensureRowCells() {
955
+ this.getBodyRows().forEach((row, index) => {
956
+ const existingCheckbox = this.getRowCheckbox(row);
957
+ if (existingCheckbox !== null) {
958
+ existingCheckbox.setAttribute('label', `Selecionar linha ${index + 1}`);
959
+ existingCheckbox.setAttribute('name', `${this.options.idPrefix}-selection-row-${index + 1}`);
960
+ return;
961
+ }
962
+ const checkbox = createSelectionCheckbox({
963
+ kind: 'row',
964
+ label: `Selecionar linha ${index + 1}`,
965
+ name: `${this.options.idPrefix}-selection-row-${index + 1}`,
966
+ });
967
+ const cell = createSelectionCell(checkbox);
968
+ row.prepend(cell);
969
+ });
970
+ }
971
+ /**
972
+ * Remove somente os elementos e atributos gerados pela seleção.
973
+ */
974
+ remove() {
975
+ this.options.host.querySelectorAll(`[${TABLE_SELECTION_GENERATED_ATTR}]`).forEach((node) => {
976
+ node.remove();
977
+ });
978
+ // Desabilitar a UI de seleção remove os controles e a projeção ARIA.
979
+ // O estado lógico (`selected`/`data-selected`) pertence ao dataset e deve
980
+ // sobreviver à virtualização e a mudanças de `hasRowSelection`.
981
+ this.getBodyRows().forEach((row) => {
982
+ row.removeAttribute('aria-selected');
983
+ });
984
+ }
985
+ /**
986
+ * Publica um retrato consistente da seleção após uma mudança.
987
+ */
988
+ notifyChange(source, rowIndex) {
989
+ const selectedRows = this.getSelectedRows();
990
+ const allRows = this.getBodyRows();
991
+ this.options.onChange({
992
+ selectedRows,
993
+ selectedIndexes: selectedRows.map((row) => allRows.indexOf(row)),
994
+ selectedCount: selectedRows.length,
995
+ rowIndex,
996
+ source,
997
+ });
998
+ }
999
+ }
1000
+
1001
+ const VIRTUAL_BUFFER_ROWS = 4;
1002
+ /**
1003
+ * Materializa uma quantidade estável de linhas ao redor da viewport.
1004
+ *
1005
+ * @remarks
1006
+ * A quantidade de elementos montados é calculada por `visibleRows` mais um
1007
+ * buffer interno fixo de quatro linhas. A janela é ampliada aos limites dos
1008
+ * grupos contíguos, podendo exceder essa quantidade para manter mesclas íntegras.
1009
+ * Linhas expandidas alteram a altura
1010
+ * total, mas não aumentam a quantidade de `br-table-row` materializados.
1011
+ *
1012
+ * A janela só é reposicionada quando a área visível se aproxima de uma das
1013
+ * bordas do buffer. Isso reduz substituições de DOM durante o scroll.
1014
+ * As somas de alturas são reutilizadas até `reset`, `invalidateRow`, uma nova
1015
+ * sequência lógica ou uma medição diferente. Somente a faixa montada é medida.
15
1016
  */
16
- const TABLE_TOKENS = {
1017
+ class TableVirtualListController {
1018
+ constructor(options) {
1019
+ this.options = options;
1020
+ this.measuredHeights = new Map();
1021
+ this.currentRange = null;
1022
+ this.viewport = null;
1023
+ this.measurementVersion = 0;
1024
+ this.scheduleSync = () => {
1025
+ if (this.rafId !== undefined)
1026
+ return;
1027
+ this.rafId = requestAnimationFrame(() => {
1028
+ this.rafId = undefined;
1029
+ this.sync();
1030
+ });
1031
+ };
1032
+ this.handleScroll = () => this.scheduleSync();
1033
+ }
1034
+ connect() {
1035
+ const viewport = this.options.getViewport();
1036
+ if (viewport === null || viewport === this.viewport)
1037
+ return;
1038
+ this.disconnectViewport();
1039
+ this.viewport = viewport;
1040
+ viewport.style.overflowAnchor = 'none';
1041
+ viewport.addEventListener('scroll', this.handleScroll, { passive: true });
1042
+ if (typeof ResizeObserver !== 'undefined') {
1043
+ this.resizeObserver = new ResizeObserver(() => this.scheduleSync());
1044
+ this.resizeObserver.observe(viewport);
1045
+ }
1046
+ }
1047
+ disconnect() {
1048
+ this.measurementVersion += 1;
1049
+ this.pendingRevealIndex = undefined;
1050
+ this.disconnectViewport();
1051
+ if (this.rafId !== undefined)
1052
+ cancelAnimationFrame(this.rafId);
1053
+ if (this.measurementRafId !== undefined)
1054
+ cancelAnimationFrame(this.measurementRafId);
1055
+ this.rafId = undefined;
1056
+ this.measurementRafId = undefined;
1057
+ }
1058
+ reset(scrollToTop = true) {
1059
+ this.measurementVersion += 1;
1060
+ this.pendingRevealIndex = undefined;
1061
+ this.measuredHeights.clear();
1062
+ this.prefix = undefined;
1063
+ this.currentRange = null;
1064
+ if (scrollToTop && this.viewport !== null)
1065
+ this.viewport.scrollTop = 0;
1066
+ this.sync(true);
1067
+ }
1068
+ invalidateRow(index) {
1069
+ this.measurementVersion += 1;
1070
+ this.measuredHeights.delete(index);
1071
+ this.prefix = undefined;
1072
+ this.currentRange = null;
1073
+ this.scheduleSync();
1074
+ }
1075
+ /** Recalcula a área útil sem descartar alturas de linhas ou a posição do scroll. */
1076
+ refreshViewport() {
1077
+ this.scheduleSync();
1078
+ }
1079
+ /** Materializa o destino antes do foco; null representa o cabeçalho. */
1080
+ revealRow(index) {
1081
+ const viewport = this.viewport;
1082
+ if (viewport === null)
1083
+ return;
1084
+ // Uma nova tecla substitui o destino ainda pendente de medição.
1085
+ this.pendingRevealIndex = undefined;
1086
+ if (index === null) {
1087
+ viewport.scrollTop = 0;
1088
+ this.sync();
1089
+ return;
1090
+ }
1091
+ const prefix = this.getPrefix(this.options.getRows());
1092
+ const top = prefix[index];
1093
+ const bottom = prefix[index + 1];
1094
+ const viewportHeight = Math.max(1, viewport.clientHeight - this.options.getStickyHeaderHeight());
1095
+ if (top < viewport.scrollTop || bottom > viewport.scrollTop + viewportHeight) {
1096
+ this.pendingRevealIndex = index;
1097
+ viewport.scrollTop = top;
1098
+ this.sync(true);
1099
+ }
1100
+ }
1101
+ sync(force = false) {
1102
+ this.connect();
1103
+ const viewport = this.viewport;
1104
+ const rows = this.options.getRows();
1105
+ if (viewport === null)
1106
+ return;
1107
+ const prefix = this.getPrefix(rows);
1108
+ if (rows.length === 0) {
1109
+ const empty = { start: 0, end: 0, beforeHeight: 0, afterHeight: 0 };
1110
+ this.currentRange = empty;
1111
+ this.options.renderRange(empty);
1112
+ this.options.onAfterRender?.();
1113
+ return;
1114
+ }
1115
+ // Linhas ainda não hidratadas têm altura zero e podem limitar o scroll nativo.
1116
+ const scrollTop = this.pendingRevealIndex === undefined ? viewport.scrollTop : prefix[this.pendingRevealIndex];
1117
+ const headerHeight = this.options.getStickyHeaderHeight();
1118
+ const viewportHeight = Math.max(viewport.clientHeight - headerHeight, 1);
1119
+ const bufferRows = this.resolveBufferRows(rows.length);
1120
+ const visibleStart = this.findRowAtOffset(prefix, scrollTop);
1121
+ const visibleEnd = Math.min(rows.length, this.findRowAtOffset(prefix, scrollTop + viewportHeight) + 1);
1122
+ if (!force && this.canKeepCurrentRange(visibleStart, visibleEnd, bufferRows)) {
1123
+ return;
1124
+ }
1125
+ const renderedCount = this.resolveRenderedRowCount(rows.length);
1126
+ const range = this.createStableRange(prefix, rows.length, visibleStart, renderedCount, bufferRows);
1127
+ if (!force && this.isSameRange(range, this.currentRange))
1128
+ return;
1129
+ this.measurementVersion += 1;
1130
+ this.currentRange = range;
1131
+ const previousScrollTop = viewport.scrollTop;
1132
+ this.options.renderRange(range);
1133
+ // Mover as linhas para o fragmento pode limitar temporariamente o scroll nativo.
1134
+ viewport.scrollTop = previousScrollTop;
1135
+ this.options.onAfterRender?.();
1136
+ this.scheduleMeasurement();
1137
+ }
1138
+ /**
1139
+ * Resolve a quantidade total de linhas adicionais mantidas no pool virtual.
1140
+ * O buffer é fixo para tornar o custo de DOM previsível durante o scroll.
1141
+ */
1142
+ resolveBufferRows(totalRows) {
1143
+ const visibleRows = this.resolveVisibleCapacity(totalRows);
1144
+ if (visibleRows <= 0 || visibleRows >= totalRows)
1145
+ return 0;
1146
+ return Math.min(VIRTUAL_BUFFER_ROWS, totalRows - visibleRows);
1147
+ }
1148
+ /** Resolve a quantidade efetiva de linhas visíveis para o dataset atual. */
1149
+ resolveVisibleCapacity(totalRows) {
1150
+ const configuredVisibleRows = this.options.visibleRows();
1151
+ if (totalRows <= 0)
1152
+ return 0;
1153
+ const normalizedVisibleRows = Number.isFinite(configuredVisibleRows)
1154
+ ? Math.min(50, Math.max(1, Math.floor(configuredVisibleRows)))
1155
+ : 10;
1156
+ return Math.min(totalRows, normalizedVisibleRows);
1157
+ }
1158
+ /**
1159
+ * Mantém a janela atual enquanto a viewport estiver dentro de sua zona
1160
+ * segura. A troca ocorre em blocos, e não a cada nova linha visível.
1161
+ */
1162
+ canKeepCurrentRange(visibleStart, visibleEnd, bufferRows) {
1163
+ const range = this.currentRange;
1164
+ if (range === null)
1165
+ return false;
1166
+ const guard = bufferRows > 0 ? 1 : 0;
1167
+ const safeStart = range.start + guard;
1168
+ const safeEnd = range.end - guard;
1169
+ const atStart = range.start === 0;
1170
+ const atEnd = range.end === this.options.getRows().length;
1171
+ const hasSafeStart = atStart ? visibleStart >= range.start : visibleStart >= safeStart;
1172
+ const hasSafeEnd = atEnd ? visibleEnd <= range.end : visibleEnd <= safeEnd;
1173
+ return hasSafeStart && hasSafeEnd;
1174
+ }
1175
+ /**
1176
+ * Mantém uma quantidade fixa de linhas materializadas para um mesmo
1177
+ * `visibleRows`: capacidade visível + até quatro linhas de buffer.
1178
+ */
1179
+ resolveRenderedRowCount(totalRows) {
1180
+ const visibleCapacity = this.resolveVisibleCapacity(totalRows);
1181
+ if (visibleCapacity >= totalRows)
1182
+ return totalRows;
1183
+ return Math.min(totalRows, visibleCapacity + VIRTUAL_BUFFER_ROWS);
1184
+ }
1185
+ /** Centraliza a faixa ao redor do início visível sem variar seu tamanho. */
1186
+ createStableRange(prefix, totalRows, visibleStart, renderedCount, bufferRows) {
1187
+ const bufferBefore = Math.floor(bufferRows / 2);
1188
+ const desiredStart = visibleStart - bufferBefore;
1189
+ const maxStart = Math.max(0, totalRows - renderedCount);
1190
+ const initialStart = Math.min(Math.max(0, desiredStart), maxStart);
1191
+ const { start, end } = expandTableGroupRange(this.options.getRows(), initialStart, Math.min(totalRows, initialStart + renderedCount));
1192
+ return {
1193
+ start,
1194
+ end,
1195
+ beforeHeight: prefix[start],
1196
+ afterHeight: prefix[totalRows] - prefix[end],
1197
+ };
1198
+ }
1199
+ /** Reutiliza as somas enquanto a sequência lógica e suas alturas permanecem válidas. */
1200
+ getPrefix(rows) {
1201
+ if (rows !== this.indexedRows) {
1202
+ this.measurementVersion += 1;
1203
+ this.indexedRows = rows;
1204
+ this.measuredHeights.clear();
1205
+ this.prefix = undefined;
1206
+ this.currentRange = null;
1207
+ this.pendingRevealIndex = undefined;
1208
+ }
1209
+ if (this.prefix !== undefined)
1210
+ return this.prefix;
1211
+ const prefix = new Array(rows.length + 1).fill(0);
1212
+ rows.forEach((row, index) => {
1213
+ prefix[index + 1] = prefix[index] + (this.measuredHeights.get(index) ?? this.estimateHeight(row));
1214
+ });
1215
+ this.prefix = prefix;
1216
+ return prefix;
1217
+ }
1218
+ estimateHeight(row) {
1219
+ const base = Math.max(1, this.options.estimatedRowHeight());
1220
+ if (!row.hasAttribute('expanded'))
1221
+ return base;
1222
+ const rowOverride = Number(row.getAttribute('virtual-expanded-content-height'));
1223
+ const expandedHeight = Number.isFinite(rowOverride) && rowOverride > 0
1224
+ ? rowOverride
1225
+ : Math.max(0, this.options.estimatedExpandedHeight());
1226
+ return base + expandedHeight;
1227
+ }
1228
+ findRowAtOffset(prefix, offset) {
1229
+ let low = 0;
1230
+ let high = prefix.length - 1;
1231
+ const target = Math.max(0, offset);
1232
+ while (low < high) {
1233
+ const mid = Math.floor((low + high + 1) / 2);
1234
+ if (prefix[mid] <= target)
1235
+ low = mid;
1236
+ else
1237
+ high = mid - 1;
1238
+ }
1239
+ return Math.min(low, prefix.length - 2);
1240
+ }
1241
+ /**
1242
+ * Mede somente as linhas materializadas e preserva a posição visual da linha
1243
+ * âncora caso a altura de itens anteriores seja corrigida.
1244
+ */
1245
+ scheduleMeasurement() {
1246
+ if (this.measurementRafId !== undefined)
1247
+ cancelAnimationFrame(this.measurementRafId);
1248
+ const version = ++this.measurementVersion;
1249
+ this.measurementRafId = requestAnimationFrame(() => {
1250
+ this.measurementRafId = undefined;
1251
+ const viewport = this.viewport;
1252
+ const rows = this.options.getRows();
1253
+ if (viewport === null || rows.length === 0)
1254
+ return;
1255
+ const prefixBefore = this.getPrefix(rows);
1256
+ const range = this.currentRange;
1257
+ if (range === null || version !== this.measurementVersion)
1258
+ return;
1259
+ void this.measureRows(rows, range).then((measurements) => {
1260
+ if (!this.isMeasurementCurrent(version, viewport, rows, range))
1261
+ return;
1262
+ this.applyMeasurements(measurements, prefixBefore, viewport, rows);
1263
+ });
1264
+ });
1265
+ }
1266
+ isMeasurementCurrent(version, viewport, rows, range) {
1267
+ return (version === this.measurementVersion &&
1268
+ this.viewport === viewport &&
1269
+ this.currentRange === range &&
1270
+ this.options.getRows() === rows);
1271
+ }
1272
+ applyMeasurements(measurements, prefixBefore, viewport, rows) {
1273
+ const anchorIndex = this.findRowAtOffset(prefixBefore, viewport.scrollTop);
1274
+ const anchorOffset = viewport.scrollTop - prefixBefore[anchorIndex];
1275
+ const { changed, revealed } = this.updateMeasuredHeights(measurements, prefixBefore);
1276
+ if (changed)
1277
+ this.prefix = undefined;
1278
+ const prefixAfter = this.getPrefix(rows);
1279
+ if (revealed && this.pendingRevealIndex !== undefined) {
1280
+ viewport.scrollTop = prefixAfter[this.pendingRevealIndex];
1281
+ this.pendingRevealIndex = undefined;
1282
+ }
1283
+ if (!changed)
1284
+ return;
1285
+ const anchoredScrollTop = prefixAfter[anchorIndex] + anchorOffset;
1286
+ const correction = anchoredScrollTop - viewport.scrollTop;
1287
+ // Corrige somente mudanças perceptíveis. O ajuste ocorre no mesmo frame
1288
+ // da medição, evitando o salto causado pela alteração dos spacers.
1289
+ if (!revealed && Math.abs(correction) > 0.5)
1290
+ viewport.scrollTop = anchoredScrollTop;
1291
+ this.currentRange = null;
1292
+ this.scheduleSync();
1293
+ }
1294
+ updateMeasuredHeights(measurements, prefix) {
1295
+ let changed = false;
1296
+ let revealed = false;
1297
+ for (const { index, height } of measurements) {
1298
+ if (height <= 0)
1299
+ continue;
1300
+ if (index === this.pendingRevealIndex)
1301
+ revealed = true;
1302
+ const previous = prefix[index + 1] - prefix[index];
1303
+ if (Math.abs(previous - height) > 0.5) {
1304
+ this.measuredHeights.set(index, height);
1305
+ changed = true;
1306
+ }
1307
+ }
1308
+ return { changed, revealed };
1309
+ }
1310
+ async measureRows(rows, range) {
1311
+ return Promise.all(Array.from({ length: range.end - range.start }, (_, offset) => {
1312
+ const index = range.start + offset;
1313
+ const row = rows[index];
1314
+ if (!row.isConnected)
1315
+ return { index, height: 0 };
1316
+ return row.getMeasuredHeight().then((height) => ({
1317
+ index,
1318
+ height: row.isConnected ? height : 0,
1319
+ }));
1320
+ }));
1321
+ }
1322
+ disconnectViewport() {
1323
+ if (this.viewport !== null)
1324
+ this.measurementVersion += 1;
1325
+ this.viewport?.removeEventListener('scroll', this.handleScroll);
1326
+ this.resizeObserver?.disconnect();
1327
+ this.resizeObserver = undefined;
1328
+ this.viewport = null;
1329
+ }
1330
+ isSameRange(a, b) {
1331
+ return (b !== null &&
1332
+ a.start === b.start &&
1333
+ a.end === b.end &&
1334
+ Math.abs(a.beforeHeight - b.beforeHeight) < 0.5 &&
1335
+ Math.abs(a.afterHeight - b.afterHeight) < 0.5);
1336
+ }
1337
+ }
1338
+
1339
+ const tableCss = () => `*,*::before,*::after{box-sizing:border-box}:host{line-height:var(--font-line-height-medium);-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}main{display:block}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace;font-size:1em}a{background-color:rgba(0,0,0,0)}b,strong{font-weight:bolder}small{font-size:80%}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:var(--font-line-height-medium);margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{appearance:none}::-webkit-file-upload-button{appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.d-none{display:none !important}@media (min-width: 576px){.d-sm-block{display:block !important}.d-sm-flex{display:flex !important}}[data-toggle=dropdown]+*{position:absolute}.dropdown{position:relative}.dropdown [data-toggle=dropdown]+*{box-shadow:var(--surface-shadow-sm);left:0;position:absolute;top:100%}.dropdown>.br-notification{left:auto;right:0}.dropdown .br-item{--color:var(--color-light);--color-rgb:var(--color-light-rgb);--text-color:var(--color-light);--interactive:var(--interactive-light);--interactive-rgb:var(--color-rgb);--visited:var(--visited-light);--hover:var(--hover-light);--pressed:var(--pressed-light);--focus-color:var(--focus-color-light);--focus:var(--focus-color-light);--item-padding-y:var(--spacing-scale-2x);background-color:var(--background-light);color:var(--color)}.dropdown .br-item:not(:last-child){border-bottom:1px solid var(--border-color)}.dropdown .br-item.selected{--color:var(--color-dark);--color-rgb:var(--color-dark-rgb);--text-color:var(--color-dark);--interactive:var(--interactive-dark);--interactive-rgb:var(--interactive-dark-rgb);--visited:var(--visited-dark);--hover:var(--hover-dark);--pressed:var(--pressed-dark);--focus-color:var(--focus-color-dark);--focus:var(--focus-color-dark)}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.align-items-center{align-items:center !important}.col,[class*=col-]{padding-left:calc(var(--grid-gutter)*.5);padding-right:calc(var(--grid-gutter)*.5);width:100%}.col{flex:1 0 0%;min-width:8.3333333333%}.col-auto{flex:0 0 auto;width:auto}.col-2{flex-basis:16.6666666667%;max-width:16.6666666667%}.container,.container-fluid,.container-lg{--grid-margin:var(--grid-portrait-margin);--grid-maxwidth:var(--grid-portrait-maxwidth);margin-left:auto;margin-right:auto;max-width:var(--grid-maxwidth);padding-left:var(--grid-margin);padding-right:var(--grid-margin);width:100%}.row{--grid-gutter:var(--grid-portrait-gutter);display:flex;flex-wrap:wrap;margin-left:calc(var(--grid-gutter)*-0.5);margin-right:calc(var(--grid-gutter)*-0.5)}@media (min-width: 576px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-tablet-margin)}.row{--grid-gutter:var(--grid-tablet-gutter)}.container{--grid-maxwidth:calc(var(--grid-breakpoint-sm) - var(--grid-tablet-margin))}.col-sm-4{flex-basis:33.3333333333%;max-width:33.3333333333%}}@media (min-width: 992px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-tablet-margin)}.row{--grid-gutter:var(--grid-tablet-gutter)}.container{--grid-maxwidth:calc(var(--grid-breakpoint-md) - var(--grid-tablet-margin))}}@media (min-width: 1280px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-desktop-margin)}.row{--grid-gutter:var(--grid-desktop-gutter)}.container,.container-lg{--grid-maxwidth:calc(var(--grid-breakpoint-lg) - var(--grid-desktop-margin))}.col-lg-3{flex-basis:25%;max-width:25%}}@media (min-width: 1600px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-tv-margin)}.row{--grid-gutter:var(--grid-tv-gutter)}.container,.container-lg{--grid-maxwidth:calc(var(--grid-breakpoint-xl) - var(--grid-tv-margin))}}.ease{animation-timing-function:cubic-bezier(0.25, 0.1, 0.25, 1)}.ease-out{animation-timing-function:cubic-bezier(0, 0, 0.58, 1)}.ease-in-out{animation-timing-function:cubic-bezier(0.42, 0, 0.58, 1)}.fast{animation-duration:var(--duration-fast)}.slow{animation-duration:var(--duration-slow)}.mt-1{margin-top:var(--spacing-scale-half) !important}.mr-1{margin-right:var(--spacing-scale-half) !important}.mb-1{margin-bottom:var(--spacing-scale-half) !important}.ml-1{margin-left:var(--spacing-scale-half) !important}.mb-4{margin-bottom:var(--spacing-scale-3x) !important}.pt-half{padding-top:var(--spacing-scale-half) !important}.highlight{background:var(--status-highlight-background) linear-gradient(var(--status-highlight-overlay), var(--status-highlight-overlay));color:var(--status-highlight-text);padding:0 var(--spacing-scale-half)}[disabled],.disabled{cursor:not-allowed;opacity:var(--disabled)}[disabled] *,.disabled *{pointer-events:none}fieldset[disabled]{opacity:1}.text-center{text-align:center !important}.text-right{text-align:right !important}.text-nowrap{white-space:nowrap !important}.text-uppercase{text-transform:uppercase !important}.text-bold{font-weight:700 !important}.text-base{font-size:var(--font-size-scale-base) !important}.text-down-01{font-size:var(--font-size-scale-down-01) !important}@media (min-width: 576px){.text-sm-center{text-align:center !important}.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}}p{color:var(--color);font-size:var(--font-size-scale-base);font-weight:var(--font-weight-regular);line-height:var(--font-line-height-medium);margin-bottom:var(--spacing-scale-2x);margin-top:0}p a{text-decoration:underline}@media (min-width: 576px){p{font-size:var(--font-size-scale-up-01)}}a{--focus-offset:var(--spacing-scale-half)}a:focus{outline:none}a.focus-visible,a:focus-visible{outline-color:var(--focus);outline-offset:var(--focus-offset);outline-style:var(--focus-style);outline-width:var(--focus-width)}a:not(:disabled):hover{background-image:linear-gradient(rgba(var(--interactive-rgb), var(--hover)), rgba(var(--interactive-rgb), var(--hover)))}a:not(:disabled):active{background-image:linear-gradient(rgba(var(--interactive-rgb), var(--pressed)), rgba(var(--interactive-rgb), var(--pressed)))}a{color:var(--interactive);text-decoration:none}.main-content a{text-decoration:underline}button{cursor:pointer}img{max-width:100%;vertical-align:middle}h2,.h2{color:var(--color);font-size:var(--font-size-scale-up-03);font-weight:var(--font-weight-semi-bold);line-height:var(--font-line-height-low);margin-bottom:var(--spacing-scale-2xh);margin-top:var(--spacing-scale-3xh);padding-bottom:var(--spacing-scale-2xh)}@media (min-width: 576px){.h2,h2{font-size:var(--font-size-scale-up-05);font-weight:var(--font-weight-regular)}}ul,ol{margin-bottom:var(--spacing-scale-2x);margin-top:0;padding:0 0 0 var(--spacing-scale-5x)}table{--table-background:var(--background);--table-color:var(--color);--table-border-color:var(--gray-20);--table-border-style:solid;--table-border-width:1px;--table-hover:var(--color-rgb);--table-padding:var(--spacing-scale-3x);--table-font-weight:var(--font-weight-medium);--table-th-background:var(--background-alternative);--table-th-font-weight:var(--font-weight-semi-bold);--table-row-size:var(--spacing-scale-2x);border-collapse:collapse;width:100%}tr.selected,tr.is-selected{--color:var(--color-dark);--color-rgb:var(--color-dark-rgb);--text-color:var(--color-dark);--interactive:var(--interactive-dark);--interactive-rgb:var(--interactive-dark-rgb);--visited:var(--visited-dark);--hover:var(--hover-dark);--pressed:var(--pressed-dark);--focus-color:var(--focus-color-dark);--focus:var(--focus-color-dark)}label,.label{color:var(--color);font-size:var(--font-size-scale-base);font-weight:var(--font-weight-semi-bold);line-height:var(--font-line-height-medium);margin-bottom:var(--spacing-scale-half)}fieldset,.fieldset{border:var(--surface-width-none);margin-bottom:var(--spacing-scale-5x);margin-top:0;padding:0}legend,.legend{color:var(--color);font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-semi-bold);line-height:var(--font-line-height-low);margin-bottom:var(--spacing-scale-2x);margin-top:var(--spacing-scale-2x)}::placeholder,.placeholder{color:var(--color-light);font-size:var(--font-size-scale-base);font-style:italic;font-weight:var(--font-weight-regular);line-height:var(--font-line-height-medium);margin-bottom:var(--spacing-scale-half);margin-top:var(--spacing-scale-half);opacity:1}input,textarea,.input{color:var(--color-light);font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-medium);line-height:var(--font-line-height-low);margin-bottom:var(--spacing-scale-half)}pre,.pre{background:var(--gray-5);margin:var(--spacing-scale-2x) 0 var(--spacing-scale-4x);padding:var(--spacing-scale-2x)}mark,.mark{background:var(--red-warm-vivid-10);color:var(--color)}*[data-toggle=collapse]:not(:disabled):hover{background-image:linear-gradient(rgba(var(--interactive-rgb), var(--hover)), rgba(var(--interactive-rgb), var(--hover)))}*[data-toggle=collapse]:focus{outline:none}*[data-toggle=collapse].focus-visible,*[data-toggle=collapse]:focus-visible{outline-color:var(--focus);outline-offset:var(--focus-offset);outline-style:var(--focus-style);outline-width:var(--focus-width)}@media (prefers-reduced-motion: reduce){:host,:host::before,:host::after,:host *,:host *::before,:host *::after{animation:none !important;scroll-behavior:auto !important;transition:none !important}}:host-context([data-wbc-reduced-motion=true])::before,:host-context([data-wbc-reduced-motion=true])::after,:host-context([data-wbc-reduced-motion=true]) *,:host-context([data-wbc-reduced-motion=true]) *::before,:host-context([data-wbc-reduced-motion=true]) *::after{animation:none !important;scroll-behavior:auto !important;transition:none !important}:host{display:block;overflow-anchor:none;min-width:0;min-height:0;--table-row-size:var(--spacing-scale-3x);--br-table-divider-base-width:var(--surface-width-sm);--br-table-row-hover-opacity:0;--br-table-loading-opacity:0.5}:host([loading]){position:relative;isolation:isolate;min-height:220px}:host([has-row-hover]){--br-table-row-hover-opacity:var(--surface-opacity-xs)}.br-table{display:flex;overflow-anchor:none;flex:0 0 auto;flex-direction:column;width:100%;min-width:0;min-height:0;overflow:hidden}br-table-bar{flex:0 0 auto}.br-table-scroll-shell{position:relative;flex:0 0 auto;box-sizing:border-box;width:100%;min-width:0;min-height:0;overflow:hidden;contain:size;overflow-anchor:none}.br-table-scroll{position:absolute;inset:0;box-sizing:border-box;width:100%;height:100%;min-width:0;min-height:0;overflow:auto;overflow-anchor:none;overscroll-behavior-x:contain;overscroll-behavior-y:contain;-webkit-overflow-scrolling:touch}.br-table-content{display:grid;grid-template-columns:var(--br-table-column-widths);min-width:0}.br-table-scroll-shell.loading .br-table-scroll{isolation:isolate}.br-table-content.loading{opacity:var(--br-table-loading-opacity)}[part=loading]{position:absolute;z-index:var(--z-index-layer-4);inset:0;display:flex;align-items:center;justify-content:center;box-sizing:border-box;padding:var(--spacing-scale-2x);overflow:hidden;background:var(--surface-overlay-scrim);pointer-events:auto}.br-table-loading-panel{box-sizing:border-box;width:max-content;min-width:min(100%,220px);max-width:100%;max-height:100%;padding:var(--spacing-scale-3x);overflow:auto;background:var(--background);color:var(--color);box-shadow:var(--surface-shadow-sm);text-align:center}@media (width <= 991px){.br-table-content{min-width:max-content}}.br-table-scroll-shell::after{position:absolute;z-index:3;inset:0;background:linear-gradient(to bottom, rgba(0, 0, 0, 0.16), transparent) 0 var(--table-scroll-header-height, 0)/100% var(--table-scroll-shadow-top, 0),linear-gradient(to top, rgba(0, 0, 0, 0.16), transparent) bottom/100% var(--table-scroll-shadow-bottom, 0),linear-gradient(to right, rgba(0, 0, 0, 0.16), transparent) left/var(--table-scroll-shadow-left, 0) 100%,linear-gradient(to left, rgba(0, 0, 0, 0.16), transparent) right/var(--table-scroll-shadow-right, 0) 100%;background-repeat:no-repeat;content:"";pointer-events:none}.br-table-loading-panel:focus-visible{outline:var(--focus-width) var(--focus-style) var(--focus);outline-offset:var(--focus-offset)}`;
1340
+
1341
+ const MIN_VISIBLE_ROWS = 1;
1342
+ const MAX_VISIBLE_ROWS = 50;
1343
+ const DEFAULT_VISIBLE_ROWS = 10;
1344
+ const Table = class {
1345
+ constructor(hostRef) {
1346
+ registerInstance(this, hostRef);
1347
+ this.brTableActionClick = createEvent(this, "brTableActionClick", 7);
1348
+ this.brTableSelectionChange = createEvent(this, "brTableSelectionChange", 7);
1349
+ this.brTableRowExpansionChange = createEvent(this, "brTableRowExpansionChange", 7);
1350
+ this.brTableSortChange = createEvent(this, "brTableSortChange", 7);
1351
+ this.brTableSortRequest = createEvent(this, "brTableSortRequest", 7);
1352
+ this.brTablePageChange = createEvent(this, "brTablePageChange", 7);
1353
+ this.brTablePageSizeChange = createEvent(this, "brTablePageSizeChange", 7);
1354
+ this.brTableSearch = createEvent(this, "brTableSearch", 7);
1355
+ /**
1356
+ * Habilita divisores entre colunas quando `columnDivider` não é informado.
1357
+ *
1358
+ * @deprecated Use `columnDivider` instead.
1359
+ * @default false
1360
+ */
1361
+ this.hasColumnDivider = false;
1362
+ /**
1363
+ * Habilita divisores entre linhas quando `rowDivider` não é informado.
1364
+ *
1365
+ * @deprecated Use `rowDivider` instead.
1366
+ * @default false
1367
+ */
1368
+ this.hasRowDivider = false;
1369
+ /**
1370
+ * Habilita o realce visual das linhas ao passar o ponteiro.
1371
+ *
1372
+ * @default false
1373
+ */
1374
+ this.hasRowHover = false;
1375
+ /**
1376
+ * Indica que as linhas estão sendo atualizadas pelo consumidor.
1377
+ *
1378
+ * @remarks Mantém os dados anteriores, reduz sua opacidade e exibe o slot
1379
+ * `loading` em um painel central com scrim sobre toda a tabela, incluindo
1380
+ * barra de ações e paginação. O scrim fica limitado ao componente.
1381
+ * Reflete o atributo `loading` e pode ser alterada diretamente ou pelos métodos
1382
+ * `startLoading()` e `stopLoading()`. Não bloqueia o teclado nem gerencia
1383
+ * requisições, erros ou substituição dos dados.
1384
+ * @default false
1385
+ */
1386
+ this.loading = false;
1387
+ /**
1388
+ * Força a apresentação da barra contextual.
1389
+ *
1390
+ * @default false
1391
+ */
1392
+ this.showContextualBar = false;
1393
+ /**
1394
+ * Limite usado para decidir quando agrupar ações globais em um menu.
1395
+ * Quando o número de ações excede esse valor, as ações são agrupadas no
1396
+ * dropdown (atualmente todas são movidas para o menu colapsado).
1397
+ *
1398
+ * @default 4
1399
+ */
1400
+ this.headingActionsLimit = 4;
1401
+ /**
1402
+ * Limite usado para decidir quando agrupar ações contextuais em um menu.
1403
+ * Quando o número de ações excede esse valor, as ações são agrupadas no
1404
+ * dropdown (atualmente todas são movidas para o menu colapsado).
1405
+ *
1406
+ * @default 4
1407
+ */
1408
+ this.contextualActionsLimit = 4;
1409
+ /**
1410
+ * Texto do tooltip do botão de ações agrupadas na barra de título.
1411
+ * Quando vazio ou composto apenas por espaços, usa "Mais ações".
1412
+ * Não altera o nome acessível do botão nem os rótulos do menu.
1413
+ *
1414
+ * @default 'Mais ações'
1415
+ */
1416
+ this.moreActionsHeadingLabel = 'Mais ações';
1417
+ /**
1418
+ * Texto do tooltip do botão de ações agrupadas da barra contextual.
1419
+ * Quando vazio ou composto apenas por espaços, usa "Mais ações".
1420
+ * Não altera o nome acessível do botão nem os rótulos do menu.
1421
+ *
1422
+ * @default 'Mais ações'
1423
+ */
1424
+ this.moreActionsContextualLabel = 'Mais ações';
1425
+ /**
1426
+ * Limite padrão de ações exibidas em cada célula.
1427
+ *
1428
+ * @default 4
1429
+ */
1430
+ this.cellActionsLimit = 4;
1431
+ /**
1432
+ * Habilita a coluna de seleção de linhas.
1433
+ *
1434
+ * @default false
1435
+ */
1436
+ this.hasRowSelection = false;
1437
+ /**
1438
+ * Habilita a coluna de expansão de linhas.
1439
+ *
1440
+ * @default false
1441
+ */
1442
+ this.hasRowExpansion = false;
1443
+ /**
1444
+ * Disponibiliza a interface de busca, sem filtrar ou destacar o conteúdo.
1445
+ * A aplicação recebe `brTableSearch` e atualiza os dados local ou remotamente.
1446
+ *
1447
+ * @default false
1448
+ */
1449
+ this.hasSearch = false;
1450
+ /**
1451
+ * Habilita a paginação da tabela, renderizando `br-table-footer` internamente.
1452
+ *
1453
+ * @remarks A paginação define o subconjunto lógico disponível para a lista
1454
+ * virtual. `pageSize` conta linhas independentes ou grupos completos, e
1455
+ * `visibleRows` controla quantas delas cabem simultaneamente na viewport.
1456
+ * Quando os dados completos ainda não estão disponíveis localmente
1457
+ * (paginação por API), informe `totalItems` e forneça o subconjunto
1458
+ * correspondente após `brTablePageChange`.
1459
+ * @default false
1460
+ */
1461
+ this.hasPagination = false;
1462
+ /**
1463
+ * Página atual exibida pela paginação (1-indexada).
1464
+ *
1465
+ * @remarks Atualizada internamente quando `TableDataStore` já cobre a
1466
+ * página solicitada. Utilize como valor inicial ou para navegar
1467
+ * programaticamente para outra página.
1468
+ * @default 1
1469
+ */
1470
+ this.currentPage = 1;
1471
+ /**
1472
+ * Opções disponíveis de itens por página no seletor da paginação.
1473
+ *
1474
+ * @default [10, 20, 30]
1475
+ */
1476
+ this.pageSizeOptions = [10, 20, 30];
1477
+ /**
1478
+ * Define se a tabela aceita uma única coluna ordenada ou múltiplas colunas.
1479
+ * No modo `multi`, a prioridade é sempre a ordem visual da esquerda para a direita.
1480
+ *
1481
+ * @default single
1482
+ */
1483
+ this.sortMode = TABLE_SORT_MODE.SINGLE;
1484
+ /**
1485
+ * Define se a tabela ordena as linhas localmente ou deixa a aplicação aplicar
1486
+ * a ordenação solicitada. Em `manual`, a tabela mantém os indicadores e emite
1487
+ * `brTableSortChange`, mas não reordena as linhas; use `setData()` para fornecer
1488
+ * os resultados customizados ou remotos. Valores não reconhecidos usam a
1489
+ * estratégia local.
1490
+ *
1491
+ * @default local
1492
+ */
1493
+ this.sortStrategy = TABLE_SORT_STRATEGY.LOCAL;
1494
+ /**
1495
+ * Quantidade de linhas de dados visíveis simultaneamente na viewport.
1496
+ *
1497
+ * @remarks Não limita o conjunto de dados nem realiza paginação. A altura da
1498
+ * região de scroll é derivada desta quantidade e da densidade atual. Mesmo
1499
+ * com `hasPagination` habilitado, esta propriedade continua definindo
1500
+ * apenas a capacidade visual da viewport; `pageSize` define o tamanho lógico
1501
+ * da página.
1502
+ * @default 10
1503
+ */
1504
+ this.visibleRows = 10;
1505
+ /** Altura adicional estimada para conteúdo expandido ainda não medido. */
1506
+ this.virtualExpandedContentHeight = 240;
1507
+ /**
1508
+ * Estratégia padrão para conteúdos que excedem a célula.
1509
+ *
1510
+ * @default wrap
1511
+ */
1512
+ this.overflow = TABLE_OVERFLOW.WRAP;
1513
+ /**
1514
+ * Estado visual padrão dos tooltips.
1515
+ *
1516
+ * @default info
1517
+ */
1518
+ this.tooltipState = TABLE_TOOLTIP_STATE.INFO;
1519
+ this.selectedRowsCount = 0;
1520
+ this.measuredCollapsedRowHeight = null;
1521
+ this.measuredHeaderHeight = null;
1522
+ this.hasGlobalActionsContent = false;
1523
+ this.hasContextualActionsContent = false;
1524
+ this.hasScrollableContent = false;
1525
+ this.generatedHeaderPrefix = Helpers.generateUniqueId();
1526
+ this.dataStore = new TableDataStore();
1527
+ this.isRenderingData = false;
1528
+ this.selfMutationDepth = 0;
1529
+ this.viewportMeasureFrame = null;
1530
+ this.sorting = [];
1531
+ this.openDropdowns = new Set();
1532
+ this.headerHeights = new Map();
1533
+ this.handleViewportScroll = () => {
1534
+ for (const dropdown of this.openDropdowns) {
1535
+ if (dropdown.isConnected)
1536
+ void dropdown.close();
1537
+ }
1538
+ this.openDropdowns.clear();
1539
+ };
1540
+ this.handleFooterPageChange = (event) => {
1541
+ if (this.dataStore.getItemCount() >= this.resolvePaginationTotalItems()) {
1542
+ this.currentPage = event.detail.page;
1543
+ }
1544
+ this.brTablePageChange.emit(event.detail);
1545
+ };
1546
+ this.handleFooterPerPageChange = (event) => {
1547
+ this.applyFooterPerPageChange(event.detail.perPage);
1548
+ };
1549
+ /**
1550
+ * Ressincroniza todas as estruturas derivadas após uma mudança no conteúdo.
1551
+ * A ordem preserva expansão antes de seleção e ambas antes das colunas de dados.
1552
+ */
1553
+ this.handleStructureChange = () => {
1554
+ this.syncBarActionsContent();
1555
+ this.runWithoutSelfMutations(() => {
1556
+ this.syncSelectionStructure();
1557
+ this.syncExpansionStructure();
1558
+ this.syncRowHoverState();
1559
+ this.annotateBoundaries();
1560
+ this.updateColumnWidths();
1561
+ this.updateAllCellAlignments();
1562
+ this.updateAllCellOverflow();
1563
+ this.updateActionDensities();
1564
+ this.applyAriaMetadata();
1565
+ });
1566
+ this.updateSelectionCount();
1567
+ for (const entry of this.headerHeights.values())
1568
+ entry.refresh();
1569
+ this.updateHeaderHeight();
1570
+ this.virtualList.sync();
1571
+ };
1572
+ }
1573
+ handleHeaderHeight(event) {
1574
+ const { host, height } = event.detail;
1575
+ if (host.closest('br-table') !== this.el || !Number.isFinite(height) || height < 0)
1576
+ return;
1577
+ this.headerHeights.set(host, event.detail);
1578
+ this.updateHeaderHeight();
1579
+ }
1580
+ updateHeaderHeight() {
1581
+ for (const host of this.headerHeights.keys()) {
1582
+ if (host.closest('br-table') !== this.el)
1583
+ this.headerHeights.delete(host);
1584
+ }
1585
+ const multilevelHeader = this.el.querySelector('br-table-header[data-multilevel]');
1586
+ const height = multilevelHeader?.getBoundingClientRect().height ??
1587
+ Math.max(0, ...Array.from(this.headerHeights.values(), (entry) => entry.height));
1588
+ if (height === this.measuredHeaderHeight)
1589
+ return;
1590
+ this.measuredHeaderHeight = height;
1591
+ this.virtualList?.refreshViewport();
1592
+ }
1593
+ handleDropdownOpenChange(event) {
1594
+ const dropdown = event.composedPath()[0];
1595
+ if (!(dropdown instanceof HTMLElement) || dropdown.localName !== 'br-dropdown')
1596
+ return;
1597
+ if (findComposedOwner(dropdown, 'br-table') !== this.el)
1598
+ return;
1599
+ const menu = dropdown;
1600
+ if (event.detail.open)
1601
+ this.openDropdowns.add(menu);
1602
+ else
1603
+ this.openDropdowns.delete(menu);
1604
+ }
1605
+ handleCellFocusRegistration(event) {
1606
+ if (event.detail.host.closest('br-table') !== this.el)
1607
+ return;
1608
+ this.keyboard.register(event.detail);
1609
+ }
1610
+ handleGridFocusIn(event) {
1611
+ this.keyboard.focusIn(event);
1612
+ }
1613
+ handleGridFocusOut(event) {
1614
+ this.keyboard.focusOut(event);
1615
+ }
1616
+ handleGridKeyDown(event) {
1617
+ this.keyboard.keyDown(event);
1618
+ }
1619
+ applyFooterPerPageChange(perPage) {
1620
+ const nextPageSize = Math.max(1, Math.floor(perPage));
1621
+ if (nextPageSize === this.resolvePageSize())
1622
+ return;
1623
+ this.pageSize = nextPageSize;
1624
+ this.currentPage = 1;
1625
+ this.brTablePageSizeChange.emit({ pageSize: nextPageSize });
1626
+ }
1627
+ /**
1628
+ * Inicializa os controllers antes da primeira renderização completa.
1629
+ */
1630
+ componentWillLoad() {
1631
+ this.keyboard = new TableKeyboardController(this.el, () => this.getKeyboardRows(), (cell) => {
1632
+ const row = cell.closest('br-table-row');
1633
+ const index = row === null ? -1 : this.getVirtualRows().indexOf(row);
1634
+ this.virtualList.revealRow(index >= 0 ? index : null);
1635
+ }, () => this.resolveConfiguredVisibleRows());
1636
+ this.selection = new TableSelectionController({
1637
+ host: this.el,
1638
+ idPrefix: this.generatedHeaderPrefix,
1639
+ getRows: () => this.dataStore.getRows(),
1640
+ onChange: (detail) => {
1641
+ this.selectedRowsCount = detail.selectedCount;
1642
+ this.brTableSelectionChange.emit(detail);
1643
+ },
1644
+ });
1645
+ this.expansion = new TableExpansionController({
1646
+ host: this.el,
1647
+ getRows: () => this.dataStore.getRows(),
1648
+ onChange: (detail) => {
1649
+ const virtualIndex = this.getVirtualRows().indexOf(detail.row);
1650
+ if (virtualIndex >= 0)
1651
+ this.virtualList?.invalidateRow(virtualIndex);
1652
+ this.brTableRowExpansionChange.emit(detail);
1653
+ },
1654
+ });
1655
+ this.virtualList = new TableVirtualListController({
1656
+ getRows: () => this.getVirtualRows(),
1657
+ getViewport: () => this.el.shadowRoot?.querySelector('.br-table-scroll') ?? null,
1658
+ getStickyHeaderHeight: () => this.measuredHeaderHeight ?? 0,
1659
+ renderRange: (range) => {
1660
+ this.isRenderingData = true;
1661
+ const offset = this.resolveVirtualRangeOffset();
1662
+ this.runWithoutSelfMutations(() => this.dataStore.renderRange({
1663
+ ...range,
1664
+ start: range.start + offset,
1665
+ end: range.end + offset,
1666
+ }));
1667
+ this.isRenderingData = false;
1668
+ },
1669
+ visibleRows: () => this.resolveConfiguredVisibleRows(),
1670
+ estimatedRowHeight: () => this.resolveVirtualRowHeight(),
1671
+ estimatedExpandedHeight: () => this.virtualExpandedContentHeight,
1672
+ onAfterRender: () => queueMicrotask(() => this.syncRenderedRange()),
1673
+ });
1674
+ }
1675
+ /**
1676
+ * Retoma a coordenação de densidade quando a tabela é reinserida.
1677
+ */
1678
+ connectedCallback() {
1679
+ if (this.structureObserver === undefined)
1680
+ return;
1681
+ this.observeStructureChanges();
1682
+ this.updateActionDensities();
1683
+ this.syncScrollShadows();
1684
+ }
1685
+ /**
1686
+ * Monta a estrutura derivada e registra os listeners de coordenação.
1687
+ */
1688
+ componentDidLoad() {
1689
+ this.captureAndRenderInitialData();
1690
+ this.syncHeaderSortState();
1691
+ this.syncSelectionStructure();
1692
+ this.syncExpansionStructure();
1693
+ this.syncRowHoverState();
1694
+ this.virtualList.connect();
1695
+ this.virtualList.reset(false);
1696
+ this.syncBarActionsContent();
1697
+ this.annotateBoundaries();
1698
+ this.registerColumnWidthListener();
1699
+ this.registerAlignmentListener();
1700
+ this.registerOverflowListener();
1701
+ this.applyDensity();
1702
+ this.updateActionDensities();
1703
+ this.applyExpandedContentHeight();
1704
+ this.applyDividers();
1705
+ this.observeStructureChanges();
1706
+ queueMicrotask(() => {
1707
+ this.updateColumnWidths();
1708
+ this.updateAllCellAlignments();
1709
+ this.updateAllCellOverflow();
1710
+ this.applyAriaMetadata();
1711
+ this.updateSelectionCount();
1712
+ this.scheduleViewportHeightMeasurement();
1713
+ this.updateScrollableContentState();
1714
+ });
1715
+ }
1716
+ syncScrollShadows() {
1717
+ const viewport = this.el.shadowRoot?.querySelector('.br-table-scroll');
1718
+ const content = this.el.shadowRoot?.querySelector('.br-table-content');
1719
+ if (!this.scrollShadows && viewport && content && viewport.parentElement) {
1720
+ this.scrollShadows = new TableScrollShadows(viewport, content, viewport.parentElement);
1721
+ }
1722
+ this.scrollShadows?.update();
1723
+ }
1724
+ componentDidRender() {
1725
+ this.syncScrollShadows();
1726
+ this.updateScrollableContentState();
1727
+ }
1728
+ /**
1729
+ * Libera o observer quando a tabela é removida do documento.
1730
+ */
1731
+ disconnectedCallback() {
1732
+ this.scrollShadows?.disconnect();
1733
+ this.scrollShadows = undefined;
1734
+ this.openDropdowns.clear();
1735
+ this.keyboard?.disconnect();
1736
+ this.structureObserver?.disconnect();
1737
+ this.virtualList?.disconnect();
1738
+ this.headerHeights.clear();
1739
+ if (this.viewportMeasureFrame !== null)
1740
+ cancelAnimationFrame(this.viewportMeasureFrame);
1741
+ this.viewportMeasureFrame = null;
1742
+ }
1743
+ /**
1744
+ * Recalcula o grid quando a largura padrão muda.
1745
+ */
1746
+ handleTableColumnWidthChange() {
1747
+ this.updateColumnWidths();
1748
+ }
1749
+ /**
1750
+ * Reaplica os tokens e recalcula a virtualização quando a densidade muda.
1751
+ */
1752
+ handleDensityChange() {
1753
+ this.invalidateViewportMetrics();
1754
+ this.applyDensity();
1755
+ this.updateActionDensities();
1756
+ this.virtualList?.reset(false);
1757
+ this.scheduleViewportHeightMeasurement();
1758
+ }
1759
+ /**
1760
+ * Recalcula a viewport e a janela virtual quando a quantidade visível muda.
1761
+ */
1762
+ handleVisibleRowsChange() {
1763
+ this.syncVisibleRange(false);
1764
+ }
1765
+ /** Reinicia a janela virtual quando a paginação é alternada. */
1766
+ handleHasPaginationChange() {
1767
+ this.virtualList.reset(true);
1768
+ this.scheduleViewportHeightMeasurement();
1769
+ }
1770
+ /** Reinicia a janela virtual no subconjunto correspondente à página atual. */
1771
+ handleCurrentPageChange() {
1772
+ if (this.hasPagination)
1773
+ this.virtualList.reset(true);
1774
+ }
1775
+ /** Reinicia a página e a janela virtual quando o tamanho lógico da página muda. */
1776
+ handlePageSizeChange() {
1777
+ if (!this.hasPagination)
1778
+ return;
1779
+ this.currentPage = 1;
1780
+ this.virtualList.reset(true);
1781
+ this.scheduleViewportHeightMeasurement();
1782
+ }
1783
+ /** Normaliza a quantidade pública de linhas visíveis para o intervalo suportado. */
1784
+ resolveConfiguredVisibleRows() {
1785
+ if (!Number.isFinite(this.visibleRows))
1786
+ return DEFAULT_VISIBLE_ROWS;
1787
+ return Math.min(MAX_VISIBLE_ROWS, Math.max(MIN_VISIBLE_ROWS, Math.floor(this.visibleRows)));
1788
+ }
1789
+ /** Quantidade total de itens usada pela paginação, priorizando o valor explícito. */
1790
+ resolvePaginationTotalItems() {
1791
+ return this.totalItems ?? this.dataStore.getItemCount();
1792
+ }
1793
+ /** Resolve o tamanho lógico da página sem acoplá-lo à altura da viewport. */
1794
+ resolvePageSize() {
1795
+ const rawPageSize = this.pageSize ?? this.resolveConfiguredVisibleRows();
1796
+ if (!Number.isFinite(rawPageSize))
1797
+ return this.resolveConfiguredVisibleRows();
1798
+ return Math.max(1, Math.floor(rawPageSize));
1799
+ }
1800
+ /** Retorna a página normalizada para o total e o tamanho atuais. */
1801
+ resolveCurrentPage() {
1802
+ if (!this.hasPagination)
1803
+ return 1;
1804
+ const totalPages = Math.max(1, Math.ceil(this.resolvePaginationTotalItems() / this.resolvePageSize()));
1805
+ return Math.min(Math.max(1, Math.floor(this.currentPage || 1)), totalPages);
1806
+ }
1807
+ /**
1808
+ * Retorna o dataset lógico consumido pela lista virtual. Com paginação local,
1809
+ * corresponde apenas ao slice da página; com paginação remota, corresponde
1810
+ * ao subconjunto atualmente fornecido pelo consumidor.
1811
+ */
1812
+ getVirtualRows() {
1813
+ const rows = this.dataStore.getRowsView();
1814
+ if (!this.hasPagination)
1815
+ return rows;
1816
+ const totalItems = this.resolvePaginationTotalItems();
1817
+ if (this.dataStore.getItemCount() < totalItems)
1818
+ return rows;
1819
+ const pageSize = this.resolvePageSize();
1820
+ const range = this.dataStore.getPageRange((this.resolveCurrentPage() - 1) * pageSize, pageSize);
1821
+ return this.dataStore.getRowsView(range.start, range.end);
1822
+ }
1823
+ /**
1824
+ * Converte os índices locais da janela virtual para índices do dataset
1825
+ * completo quando a paginação é realizada localmente.
1826
+ *
1827
+ * Na paginação remota, o data store contém somente a página fornecida pelo
1828
+ * consumidor, portanto não há offset físico a aplicar ao renderRange.
1829
+ */
1830
+ resolveVirtualRangeOffset() {
1831
+ if (!this.hasPagination)
1832
+ return 0;
1833
+ const totalRows = this.dataStore.getItemCount();
1834
+ const totalItems = this.resolvePaginationTotalItems();
1835
+ if (totalRows < totalItems)
1836
+ return 0;
1837
+ return this.dataStore.getPageRange((this.resolveCurrentPage() - 1) * this.resolvePageSize(), this.resolvePageSize())
1838
+ .start;
1839
+ }
1840
+ /** Atualiza a janela virtual; a paginação apenas altera seu dataset de entrada. */
1841
+ syncVisibleRange(resetScroll) {
1842
+ this.virtualList.reset(resetScroll);
1843
+ }
1844
+ /**
1845
+ * Resolve a altura-base estimada da linha a partir da densidade atual.
1846
+ *
1847
+ * @remarks A célula utiliza a densidade como padding vertical. A estimativa
1848
+ * soma duas vezes esse padding a uma altura de conteúdo de uma linha (24px).
1849
+ * Após a materialização, a lista virtual substitui a estimativa pela altura
1850
+ * efetivamente medida.
1851
+ */
1852
+ resolveVirtualRowHeight() {
1853
+ const density = resolveTokenValue(this.density, {
1854
+ fallback: TABLE_DENSITY_MAP[TABLE_DENSITY.MEDIUM],
1855
+ semanticMap: TABLE_DENSITY_MAP,
1856
+ });
1857
+ const verticalPadding = Number.parseFloat(density);
1858
+ return 24 + verticalPadding * 2;
1859
+ }
1860
+ /**
1861
+ * Define a altura da região rolável pelo número de itens lógicos solicitado.
1862
+ * Grupos contam como um item, mas reservam a altura de todas as suas linhas.
1863
+ */
1864
+ resolveScrollViewportHeight() {
1865
+ const estimatedRowHeight = this.resolveVirtualRowHeight();
1866
+ const rowHeight = Math.max(this.measuredCollapsedRowHeight ?? 0, estimatedRowHeight);
1867
+ const headerHeight = Math.max(this.measuredHeaderHeight ?? 0, rowHeight);
1868
+ const rows = this.getVirtualRows();
1869
+ const configuredHeightRows = this.heightRows !== undefined && Number.isFinite(this.heightRows)
1870
+ ? Math.max(1, Math.floor(this.heightRows))
1871
+ : this.resolveConfiguredVisibleRows();
1872
+ const logicalRows = Math.min(configuredHeightRows, this.dataStore.getItemCount());
1873
+ const pageOffset = this.resolveVirtualRangeOffset();
1874
+ const physicalRange = this.dataStore.getPageRange(pageOffset, logicalRows);
1875
+ const physicalRows = rows.length === 0 ? 0 : Math.min(rows.length, physicalRange.end - pageOffset);
1876
+ const dataRowsHeight = physicalRows * rowHeight;
1877
+ return `${headerHeight + dataRowsHeight}px`;
1878
+ }
1879
+ /**
1880
+ * Reaplica os divisores após qualquer mudança relacionada.
1881
+ */
1882
+ handleDividerChange() {
1883
+ this.applyDividers();
1884
+ }
17
1885
  /**
18
- * Define o template de colunas aplicado ao grid.
1886
+ * Recalcula os alinhamentos herdados de todas as células.
19
1887
  */
20
- COLUMN_WIDTHS: '--br-table-column-widths',
1888
+ handleAlignmentChange() {
1889
+ this.updateAllCellAlignments();
1890
+ }
21
1891
  /**
22
- * Controla o espaçamento interno das células.
1892
+ * Recalcula o overflow herdado de todas as células.
23
1893
  */
24
- DENSITY: '--br-table-density',
1894
+ handleOverflowChange() {
1895
+ this.updateAllCellOverflow();
1896
+ }
1897
+ handleVirtualExpandedContentHeightChange() {
1898
+ this.applyExpandedContentHeight();
1899
+ this.syncVisibleRange(false);
1900
+ }
25
1901
  /**
26
- * Define o alinhamento horizontal do conteúdo das células.
1902
+ * Sincroniza a estrutura quando a seleção é habilitada ou desabilitada.
27
1903
  */
28
- HORIZONTAL_ALIGNMENT: '--br-table-horizontal-alignment',
1904
+ handleRowSelectionChange() {
1905
+ this.syncSelectionStructure();
1906
+ this.handleStructureChange();
1907
+ }
1908
+ /** Sincroniza a elegibilidade visual de hover das linhas. */
1909
+ handleRowHoverChange() {
1910
+ this.syncRowHoverState();
1911
+ }
29
1912
  /**
30
- * Define o alinhamento vertical do conteúdo das células.
1913
+ * Sincroniza a estrutura quando a expansão é habilitada ou desabilitada.
31
1914
  */
32
- VERTICAL_ALIGNMENT: '--br-table-vertical-alignment',
1915
+ handleRowExpansionChange() {
1916
+ this.handleStructureChange();
1917
+ }
1918
+ /** Normaliza o estado ativo quando o consumidor alterna entre multi e single-sort. */
1919
+ handleSortModeChange() {
1920
+ if (this.sortMode === TABLE_SORT_MODE.SINGLE && this.sorting.length > 1) {
1921
+ const firstCriterion = this.getSortingByColumnOrder()[0];
1922
+ this.sorting = firstCriterion === undefined ? [] : [firstCriterion];
1923
+ this.applySorting(false);
1924
+ }
1925
+ }
1926
+ /** Reaplica o estado atual quando a estratégia de ordenação muda. */
1927
+ handleSortStrategyChange() {
1928
+ if (this.dataStore.getColumns().length === 0)
1929
+ return;
1930
+ this.applySorting(false);
1931
+ }
1932
+ /** Consome solicitações emitidas pelo trigger de ordenação do cabeçalho. */
1933
+ handleSortRequest(event) {
1934
+ const header = event
1935
+ .composedPath()
1936
+ .find((node) => node instanceof HTMLElement &&
1937
+ node.tagName.toLowerCase() === 'br-table-header-cell' &&
1938
+ node.hasAttribute('sortable'));
1939
+ if (header === undefined || header.closest('br-table') !== this.el)
1940
+ return;
1941
+ const columnIndex = this.dataStore.getColumns().indexOf(header);
1942
+ if (columnIndex < 0)
1943
+ return;
1944
+ event.stopImmediatePropagation();
1945
+ const nextSorting = this.resolveNextSorting(columnIndex);
1946
+ const requestEvent = this.brTableSortRequest.emit({
1947
+ mode: this.sortMode,
1948
+ columnIndex,
1949
+ currentSorting: this.getSortingByColumnOrder().map((criterion) => ({ ...criterion })),
1950
+ nextSorting: nextSorting.map((criterion) => ({ ...criterion })),
1951
+ });
1952
+ if (requestEvent.defaultPrevented) {
1953
+ return;
1954
+ }
1955
+ this.sorting = nextSorting;
1956
+ this.applySorting(true);
1957
+ }
33
1958
  /**
34
- * Define o estilo visual das linhas divisórias.
1959
+ * Encaminha mudanças dos checkboxes ao controller de seleção.
35
1960
  */
36
- DIVIDER_STYLE: '--br-table-divider-style',
1961
+ handleSelectionCheckboxChange(event) {
1962
+ this.selection.handleCheckboxChange(event);
1963
+ }
37
1964
  /**
38
- * Controla a visibilidade/intensidade do divisor entre colunas.
1965
+ * Consome ações internas de expansão e normaliza as demais ações.
39
1966
  */
40
- COLUMN_DIVIDER_FACTOR: '--br-table-column-divider-factor',
1967
+ handleActionClick(event) {
1968
+ if (event.target === this.el) {
1969
+ return;
1970
+ }
1971
+ if (this.expansion.handleActionClick(event)) {
1972
+ event.stopImmediatePropagation();
1973
+ event.stopPropagation();
1974
+ return;
1975
+ }
1976
+ event.stopImmediatePropagation();
1977
+ event.stopPropagation();
1978
+ if (event.detail.type !== 'row') {
1979
+ this.brTableActionClick.emit(event.detail);
1980
+ return;
1981
+ }
1982
+ this.brTableActionClick.emit({
1983
+ ...event.detail,
1984
+ rowIndex: this.resolveActionRowIndex(event),
1985
+ });
1986
+ }
1987
+ /** Resolve o índice da linha associado à ação quando o contexto é `row`. */
1988
+ resolveActionRowIndex(event) {
1989
+ const row = event
1990
+ .composedPath()
1991
+ .find((node) => node instanceof HTMLElement && node.tagName.toLowerCase() === 'br-table-row');
1992
+ if (row === undefined)
1993
+ return undefined;
1994
+ const rowIndex = this.getBodyRows().indexOf(row);
1995
+ return rowIndex >= 0 ? rowIndex : undefined;
1996
+ }
1997
+ /** Inicia o estado visual de carregamento sem alterar os dados da tabela. */
1998
+ async startLoading() {
1999
+ this.loading = true;
2000
+ }
2001
+ /** Interrompe o estado visual de carregamento sem alterar os dados da tabela. */
2002
+ async stopLoading() {
2003
+ this.loading = false;
2004
+ }
41
2005
  /**
42
- * Controla a visibilidade/intensidade do divisor entre linhas.
2006
+ * Substitui os dados lógicos da tabela e reconstrói seus subcomponentes.
2007
+ *
2008
+ * @remarks Esta é a mesma estrutura interna utilizada após a ingestão dos slots.
2009
+ * @param data Colunas, linhas e ações que formarão a tabela.
2010
+ * @example
2011
+ * ```js
2012
+ * const table = document.querySelector('br-table');
2013
+ * await table.setData({
2014
+ * columns: [],
2015
+ * headerRows: [
2016
+ * [{ content: 'Unidade', rowSpan: 2 }, { content: 'Equipe', colSpan: 2 }],
2017
+ * [{ content: 'Nome', sortable: true }, { content: 'Cargo', sortable: true }],
2018
+ * ],
2019
+ * rows: [
2020
+ * { rowGroup: 'brasilia', cells: [
2021
+ * { content: 'Brasília', rowSpan: 2, rowHeader: true },
2022
+ * { content: 'Ana' }, { content: 'Analista' },
2023
+ * ] },
2024
+ * { rowGroup: 'brasilia', cells: [{ content: 'Carlos' }, { content: 'Técnico' }] },
2025
+ * ],
2026
+ * });
2027
+ * ```
43
2028
  */
44
- ROW_DIVIDER_FACTOR: '--br-table-row-divider-factor',
2029
+ async setData(data) {
2030
+ this.invalidateViewportMetrics();
2031
+ const previousSorting = this.sorting.map((criterion) => ({ ...criterion }));
2032
+ this.isRenderingData = true;
2033
+ this.dataStore.replace(data);
2034
+ this.dataStore.mount(this.el);
2035
+ this.isRenderingData = false;
2036
+ await Promise.resolve();
2037
+ this.sorting = this.resolvePreservedSorting(previousSorting);
2038
+ if (this.sorting.length > 0) {
2039
+ this.applySorting(false);
2040
+ }
2041
+ else {
2042
+ this.syncHeaderSortState();
2043
+ this.syncSelectionStructure();
2044
+ this.syncExpansionStructure();
2045
+ this.syncRowHoverState();
2046
+ this.syncVisibleRange(true);
2047
+ this.handleStructureChange();
2048
+ }
2049
+ this.scheduleViewportHeightMeasurement();
2050
+ }
2051
+ /** Preserva apenas critérios que continuam válidos no novo dataset. */
2052
+ resolvePreservedSorting(previousSorting) {
2053
+ const columns = this.dataStore.getColumns();
2054
+ const validSorting = previousSorting.filter(({ columnIndex }) => {
2055
+ if (columnIndex < 0 || columnIndex >= columns.length)
2056
+ return false;
2057
+ return columns[columnIndex]?.hasAttribute('sortable') === true;
2058
+ });
2059
+ if (this.sortMode !== TABLE_SORT_MODE.MULTI) {
2060
+ const first = validSorting[0];
2061
+ return first === undefined ? [] : [first];
2062
+ }
2063
+ return [...validSorting].sort((a, b) => a.columnIndex - b.columnIndex);
2064
+ }
45
2065
  /**
46
- * Controla o comportamento de overflow do conteúdo das células.
2066
+ * Captura a entrada declarativa inicial e a materializa a partir do modelo virtual.
47
2067
  */
48
- CELL_OVERFLOW: '--br-table-cell-overflow',
2068
+ captureAndRenderInitialData() {
2069
+ this.invalidateViewportMetrics();
2070
+ this.isRenderingData = true;
2071
+ this.dataStore.capture(this.el);
2072
+ this.dataStore.mount(this.el);
2073
+ this.isRenderingData = false;
2074
+ }
49
2075
  /**
50
- * Controla o comportamento de overflow de texto dentro das células.
2076
+ * Retorna as linhas atualmente selecionadas.
2077
+ *
2078
+ * @returns Elementos `br-table-row` selecionados no corpo.
51
2079
  */
52
- CELL_TEXT_OVERFLOW: '--br-table-cell-text-overflow',
2080
+ async getSelectedRows() {
2081
+ return this.selection.getSelectedRows();
2082
+ }
53
2083
  /**
54
- * Controla o comportamento de quebra de linha dentro das células.
2084
+ * Seleciona todas as linhas elegíveis.
55
2085
  */
56
- CELL_WHITE_SPACE: '--br-table-cell-white-space',
57
- };
58
-
59
- /**
60
- * Resolve um valor de token aplicando validação e fallback.
61
- *
62
- * @param raw Valor bruto informado.
63
- * @param options Configurações de resolução.
64
- * @param options.fallback Valor padrão utilizado quando `raw` é inválido.
65
- * @param options.semanticMap Mapa opcional de valores semânticos.
66
- * @param options.validators Lista opcional de validadores.
67
- *
68
- * @returns Valor final resolvido.
69
- *
70
- * @remarks
71
- * Ordem de resolução:
72
- * 1. Retorna fallback se `raw` for vazio ou indefinido.
73
- * 2. Retorna o valor do mapa semântico, se aplicável.
74
- * 3. Retorna `raw` se passar por algum validador.
75
- * 4. Caso contrário, retorna o fallback.
76
- */
77
- function resolveTokenValue(raw, options) {
78
- if (raw === undefined || raw === '')
79
- return options.fallback;
80
- const { semanticMap, validators = [], fallback } = options;
81
- if (semanticMap && raw in semanticMap) {
82
- return semanticMap[raw];
83
- }
84
- const isValid = validators.some((validator) => validator(raw));
85
- return isValid ? raw : fallback;
86
- }
87
- /**
88
- * Valida valores positivos em pixels.
89
- *
90
- * @example 16px
91
- */
92
- const positivePxValidator = (value) => /^\d+(\.\d+)?px$/.test(value) && parseFloat(value) > 0;
93
- /**
94
- * Valida valores positivos em frações de grid.
95
- *
96
- * @example 1fr
97
- */
98
- const positiveFrValidator = (value) => /^\d+(\.\d+)?fr$/.test(value) && parseFloat(value) > 0;
99
-
100
- const tableCss = () => `*,*::before,*::after{box-sizing:border-box}:host{line-height:var(--font-line-height-medium);-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%}main{display:block}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace;font-size:1em}a{background-color:rgba(0,0,0,0)}b,strong{font-weight:bolder}small{font-size:80%}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:var(--font-line-height-medium);margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{appearance:none}::-webkit-file-upload-button{appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}.d-none{display:none !important}@media (min-width: 576px){.d-sm-block{display:block !important}.d-sm-flex{display:flex !important}}[data-toggle=dropdown]+*{position:absolute}.dropdown{position:relative}.dropdown [data-toggle=dropdown]+*{box-shadow:var(--surface-shadow-sm);left:0;position:absolute;top:100%}.dropdown>.br-notification{left:auto;right:0}.dropdown .br-item{--color:var(--color-light);--color-rgb:var(--color-light-rgb);--text-color:var(--color-light);--interactive:var(--interactive-light);--interactive-rgb:var(--color-rgb);--visited:var(--visited-light);--hover:var(--hover-light);--pressed:var(--pressed-light);--focus-color:var(--focus-color-light);--focus:var(--focus-color-light);--item-padding-y:var(--spacing-scale-2x);background-color:var(--background-light);color:var(--color)}.dropdown .br-item:not(:last-child){border-bottom:1px solid var(--border-color)}.dropdown .br-item.selected{--color:var(--color-dark);--color-rgb:var(--color-dark-rgb);--text-color:var(--color-dark);--interactive:var(--interactive-dark);--interactive-rgb:var(--interactive-dark-rgb);--visited:var(--visited-dark);--hover:var(--hover-dark);--pressed:var(--pressed-dark);--focus-color:var(--focus-color-dark);--focus:var(--focus-color-dark)}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.align-items-center{align-items:center !important}.col,[class*=col-]{padding-left:calc(var(--grid-gutter)*.5);padding-right:calc(var(--grid-gutter)*.5);width:100%}.col{flex:1 0 0%;min-width:8.3333333333%}.col-auto{flex:0 0 auto;width:auto}.col-2{flex-basis:16.6666666667%;max-width:16.6666666667%}.container,.container-fluid,.container-lg{--grid-margin:var(--grid-portrait-margin);--grid-maxwidth:var(--grid-portrait-maxwidth);margin-left:auto;margin-right:auto;max-width:var(--grid-maxwidth);padding-left:var(--grid-margin);padding-right:var(--grid-margin);width:100%}.row{--grid-gutter:var(--grid-portrait-gutter);display:flex;flex-wrap:wrap;margin-left:calc(var(--grid-gutter)*-0.5);margin-right:calc(var(--grid-gutter)*-0.5)}@media (min-width: 576px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-tablet-margin)}.row{--grid-gutter:var(--grid-tablet-gutter)}.container{--grid-maxwidth:calc(var(--grid-breakpoint-sm) - var(--grid-tablet-margin))}.col-sm-4{flex-basis:33.3333333333%;max-width:33.3333333333%}}@media (min-width: 992px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-tablet-margin)}.row{--grid-gutter:var(--grid-tablet-gutter)}.container{--grid-maxwidth:calc(var(--grid-breakpoint-md) - var(--grid-tablet-margin))}}@media (min-width: 1280px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-desktop-margin)}.row{--grid-gutter:var(--grid-desktop-gutter)}.container,.container-lg{--grid-maxwidth:calc(var(--grid-breakpoint-lg) - var(--grid-desktop-margin))}.col-lg-3{flex-basis:25%;max-width:25%}}@media (min-width: 1600px){.container,.container-lg,.container-fluid{--grid-margin:var(--grid-tv-margin)}.row{--grid-gutter:var(--grid-tv-gutter)}.container,.container-lg{--grid-maxwidth:calc(var(--grid-breakpoint-xl) - var(--grid-tv-margin))}}.ease{animation-timing-function:cubic-bezier(0.25, 0.1, 0.25, 1)}.ease-out{animation-timing-function:cubic-bezier(0, 0, 0.58, 1)}.ease-in-out{animation-timing-function:cubic-bezier(0.42, 0, 0.58, 1)}.fast{animation-duration:var(--duration-fast)}.slow{animation-duration:var(--duration-slow)}.mt-1{margin-top:var(--spacing-scale-half) !important}.mr-1{margin-right:var(--spacing-scale-half) !important}.mb-1{margin-bottom:var(--spacing-scale-half) !important}.ml-1{margin-left:var(--spacing-scale-half) !important}.mx-3{margin-left:var(--spacing-scale-2x) !important;margin-right:var(--spacing-scale-2x) !important}.mb-4{margin-bottom:var(--spacing-scale-3x) !important}.ml-auto{margin-left:auto !important}.pt-half{padding-top:var(--spacing-scale-half) !important}@media (min-width: 576px){.ml-sm-0{margin-left:var(--spacing-scale-default) !important}}.highlight{background:var(--status-highlight-background) linear-gradient(var(--status-highlight-overlay), var(--status-highlight-overlay));color:var(--status-highlight-text);padding:0 var(--spacing-scale-half)}[disabled],.disabled{cursor:not-allowed;opacity:var(--disabled)}[disabled] *,.disabled *{pointer-events:none}fieldset[disabled]{opacity:1}.text-center{text-align:center !important}.text-right{text-align:right !important}.text-nowrap{white-space:nowrap !important}.text-uppercase{text-transform:uppercase !important}.text-bold{font-weight:700 !important}.text-base{font-size:var(--font-size-scale-base) !important}.text-down-01{font-size:var(--font-size-scale-down-01) !important}@media (min-width: 576px){.text-sm-center{text-align:center !important}.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}}p{color:var(--color);font-size:var(--font-size-scale-base);font-weight:var(--font-weight-regular);line-height:var(--font-line-height-medium);margin-bottom:var(--spacing-scale-2x);margin-top:0}p a{text-decoration:underline}@media (min-width: 576px){p{font-size:var(--font-size-scale-up-01)}}a{--focus-offset:var(--spacing-scale-half)}a:focus{outline:none}a.focus-visible,a:focus-visible{outline-color:var(--focus);outline-offset:var(--focus-offset);outline-style:var(--focus-style);outline-width:var(--focus-width)}a:not(:disabled):hover{background-image:linear-gradient(rgba(var(--interactive-rgb), var(--hover)), rgba(var(--interactive-rgb), var(--hover)))}a:not(:disabled):active{background-image:linear-gradient(rgba(var(--interactive-rgb), var(--pressed)), rgba(var(--interactive-rgb), var(--pressed)))}a{color:var(--interactive);text-decoration:none}.main-content a{text-decoration:underline}button{cursor:pointer}img{max-width:100%;vertical-align:middle}h2,.h2{color:var(--color);font-size:var(--font-size-scale-up-03);font-weight:var(--font-weight-semi-bold);line-height:var(--font-line-height-low);margin-bottom:var(--spacing-scale-2xh);margin-top:var(--spacing-scale-3xh);padding-bottom:var(--spacing-scale-2xh)}@media (min-width: 576px){.h2,h2{font-size:var(--font-size-scale-up-05);font-weight:var(--font-weight-regular)}}ul,ol{margin-bottom:var(--spacing-scale-2x);margin-top:0;padding:0 0 0 var(--spacing-scale-5x)}table{--table-background:var(--background);--table-color:var(--color);--table-border-color:var(--gray-20);--table-border-style:solid;--table-border-width:1px;--table-hover:var(--color-rgb);--table-padding:var(--spacing-scale-3x);--table-font-weight:var(--font-weight-medium);--table-th-background:var(--background-alternative);--table-th-font-weight:var(--font-weight-semi-bold);--table-row-size:var(--spacing-scale-2x);border-collapse:collapse;width:100%}tr.selected,tr.is-selected{--color:var(--color-dark);--color-rgb:var(--color-dark-rgb);--text-color:var(--color-dark);--interactive:var(--interactive-dark);--interactive-rgb:var(--interactive-dark-rgb);--visited:var(--visited-dark);--hover:var(--hover-dark);--pressed:var(--pressed-dark);--focus-color:var(--focus-color-dark);--focus:var(--focus-color-dark)}label,.label{color:var(--color);font-size:var(--font-size-scale-base);font-weight:var(--font-weight-semi-bold);line-height:var(--font-line-height-medium);margin-bottom:var(--spacing-scale-half)}fieldset,.fieldset{border:var(--surface-width-none);margin-bottom:var(--spacing-scale-5x);margin-top:0;padding:0}legend,.legend{color:var(--color);font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-semi-bold);line-height:var(--font-line-height-low);margin-bottom:var(--spacing-scale-2x);margin-top:var(--spacing-scale-2x)}::placeholder,.placeholder{color:var(--color-light);font-size:var(--font-size-scale-base);font-style:italic;font-weight:var(--font-weight-regular);line-height:var(--font-line-height-medium);margin-bottom:var(--spacing-scale-half);margin-top:var(--spacing-scale-half);opacity:1}input,textarea,.input{color:var(--color-light);font-size:var(--font-size-scale-up-01);font-weight:var(--font-weight-medium);line-height:var(--font-line-height-low);margin-bottom:var(--spacing-scale-half)}pre,.pre{background:var(--gray-5);margin:var(--spacing-scale-2x) 0 var(--spacing-scale-4x);padding:var(--spacing-scale-2x)}*[data-toggle=collapse]:not(:disabled):hover{background-image:linear-gradient(rgba(var(--interactive-rgb), var(--hover)), rgba(var(--interactive-rgb), var(--hover)))}*[data-toggle=collapse]:focus{outline:none}*[data-toggle=collapse].focus-visible,*[data-toggle=collapse]:focus-visible{outline-color:var(--focus);outline-offset:var(--focus-offset);outline-style:var(--focus-style);outline-width:var(--focus-width)}@media (prefers-reduced-motion: reduce){:host,:host::before,:host::after,:host *,:host *::before,:host *::after{animation:none !important;scroll-behavior:auto !important;transition:none !important}}:host-context([data-wbc-reduced-motion=true])::before,:host-context([data-wbc-reduced-motion=true])::after,:host-context([data-wbc-reduced-motion=true]) *,:host-context([data-wbc-reduced-motion=true]) *::before,:host-context([data-wbc-reduced-motion=true]) *::after{animation:none !important;scroll-behavior:auto !important;transition:none !important}:host{display:block;--table-row-size:var(--spacing-scale-3x);--br-table-divider-base-width:var(--surface-width-sm);--br-table-loading-opacity:0.5}.br-table{position:relative;width:100%}.br-table-content{display:grid;grid-template-columns:var(--br-table-column-widths);min-width:0}[part=loading]{position:absolute;z-index:2;inset:0;display:grid;place-items:center;pointer-events:auto}.br-table-content.loading{opacity:var(--br-table-loading-opacity)}@media (width <= 991px){.br-table{overflow-x:auto;-webkit-overflow-scrolling:touch}.br-table-content{min-width:max-content}}`;
101
-
102
- const Table = class {
103
- constructor(hostRef) {
104
- registerInstance(this, hostRef);
105
- /**
106
- * Ativa divisores verticais entre colunas.
107
- *
108
- * @default false
109
- * @deprecated Use `columnDivider`.
110
- */
111
- this.hasColumnDivider = false;
112
- /**
113
- * Ativa divisores horizontais entre linhas.
114
- *
115
- * @default false
116
- * @deprecated Use `rowDivider`.
117
- */
118
- this.hasRowDivider = false;
119
- /**
120
- * Define o comportamento de overflow para as células.
121
- *
122
- * @remarks Valores aceitos:
123
- * - truncate
124
- * - wrap
125
- *
126
- * Observação:
127
- * - O overflow é independente de `columnWidth`.
128
- * - Com `columnWidth="content"`, a coluna tende a crescer com o conteúdo (`max-content`), o que pode reduzir casos visíveis de truncagem.
129
- * - Com `columnWidth="fill"`, a coluna ocupa o espaço disponível (`1fr`), então a truncagem tende a ficar mais evidente quando não há espaço suficiente.
130
- *
131
- * @default wrap
132
- */
133
- this.overflow = TABLE_OVERFLOW.WRAP;
134
- /**
135
- * Define o estado semântico do tooltip nas células da tabela.
136
- *
137
- * @remarks Valores aceitos:
138
- * - info
139
- * - warning
140
- * - danger
141
- * - success
142
- *
143
- * @default info
144
- */
145
- this.tooltipState = TABLE_TOOLTIP_STATE.INFO;
146
- /**
147
- * Indica que as linhas estão sendo atualizadas pelo consumidor.
148
- * O componente mantém o conteúdo anterior, aplica `aria-busy="true"` e
149
- * exibe o slot `loading` sobre os dados; transporte, erro e substituição das
150
- * linhas ficam sob responsabilidade da aplicação.
151
- * A prop pode ser alterada diretamente ou pelos métodos `startLoading()` e
152
- * `stopLoading()`.
153
- * @default false
154
- */
155
- this.loading = false;
156
- this.headers = [];
157
- this.rows = [];
158
- this.cells = [];
159
- this.rowCells = new Map();
160
- this.columnIndexes = new Map();
161
- this.structureReady = false;
162
- this.structureRefreshFrame = null;
163
- this.handleColumnWidthEvent = () => {
164
- this.scheduleStructureRefresh();
165
- };
166
- this.handleAlignmentEvent = (event) => {
167
- if (!this.structureReady) {
168
- this.scheduleStructureRefresh();
2086
+ async selectAllRows() {
2087
+ this.selection.selectAll(true);
2088
+ }
2089
+ /**
2090
+ * Limpa a seleção de todas as linhas elegíveis.
2091
+ */
2092
+ async clearSelection() {
2093
+ this.selection.clear();
2094
+ }
2095
+ /** Retorna o estado atual de ordenação aplicado na tabela. */
2096
+ async getSorting() {
2097
+ return this.getSortingByColumnOrder().map((criterion) => ({ ...criterion }));
2098
+ }
2099
+ /**
2100
+ * Expande uma linha elegível do corpo.
2101
+ *
2102
+ * @param rowIndex Índice da linha, começando em zero.
2103
+ */
2104
+ async expandRow(rowIndex) {
2105
+ const row = this.getBodyRows()[rowIndex];
2106
+ if (row !== undefined)
2107
+ this.expansion.setExpanded(row, true);
2108
+ }
2109
+ /**
2110
+ * Recolhe uma linha do corpo.
2111
+ *
2112
+ * @param rowIndex Índice da linha, começando em zero.
2113
+ */
2114
+ async collapseRow(rowIndex) {
2115
+ const row = this.getBodyRows()[rowIndex];
2116
+ if (row !== undefined)
2117
+ this.expansion.setExpanded(row, false);
2118
+ }
2119
+ /**
2120
+ * Recolhe todas as linhas que estiverem expandidas.
2121
+ */
2122
+ async collapseAllRows() {
2123
+ this.expansion.collapseAll();
2124
+ }
2125
+ /** Resolve o próximo estado de ordenação para a coluna acionada. */
2126
+ resolveNextSorting(columnIndex) {
2127
+ const current = this.sorting.find((criterion) => criterion.columnIndex === columnIndex);
2128
+ const nextDirection = current === undefined
2129
+ ? TABLE_SORT_DIRECTION.ASC
2130
+ : current.direction === TABLE_SORT_DIRECTION.ASC
2131
+ ? TABLE_SORT_DIRECTION.DESC
2132
+ : undefined;
2133
+ if (this.sortMode !== TABLE_SORT_MODE.MULTI) {
2134
+ return nextDirection === undefined ? [] : [{ columnIndex, direction: nextDirection }];
2135
+ }
2136
+ const nextSorting = this.sorting.filter((criterion) => criterion.columnIndex !== columnIndex);
2137
+ if (nextDirection !== undefined)
2138
+ nextSorting.push({ columnIndex, direction: nextDirection });
2139
+ return nextSorting.sort((a, b) => a.columnIndex - b.columnIndex);
2140
+ }
2141
+ /** Mantém a prioridade do multi-sort estritamente da esquerda para a direita. */
2142
+ getSortingByColumnOrder() {
2143
+ return [...this.sorting].sort((a, b) => a.columnIndex - b.columnIndex);
2144
+ }
2145
+ /**
2146
+ * Aplica a ordenação ao dataset completo e só então reinicia a janela virtual.
2147
+ */
2148
+ applySorting(emitChange) {
2149
+ this.sorting = this.getSortingByColumnOrder();
2150
+ if (this.sortStrategy !== TABLE_SORT_STRATEGY.MANUAL) {
2151
+ this.dataStore.sortRows(this.sorting);
2152
+ }
2153
+ this.syncHeaderSortState();
2154
+ this.syncSelectionStructure();
2155
+ this.syncExpansionStructure();
2156
+ this.syncRowHoverState();
2157
+ this.syncVisibleRange(true);
2158
+ this.handleStructureChange();
2159
+ if (emitChange) {
2160
+ this.brTableSortChange.emit({
2161
+ mode: this.sortMode,
2162
+ sorting: this.sorting.map((criterion) => ({ ...criterion })),
2163
+ rows: this.dataStore.getRows(),
2164
+ });
2165
+ }
2166
+ }
2167
+ /** Reflete o estado lógico nos cabeçalhos para atualizar ícones e semântica. */
2168
+ syncHeaderSortState() {
2169
+ this.dataStore.getColumns().forEach((header, columnIndex) => {
2170
+ if (!header.hasAttribute('sortable')) {
2171
+ header.removeAttribute('sort-direction');
2172
+ header.removeAttribute('aria-sort');
169
2173
  return;
170
2174
  }
171
- this.updateAlignmentForTarget(event.target);
172
- };
173
- this.handleOverflowEvent = (event) => {
174
- if (!this.structureReady) {
175
- this.scheduleStructureRefresh();
2175
+ const criterion = this.sorting.find((entry) => entry.columnIndex === columnIndex);
2176
+ if (criterion === undefined) {
2177
+ header.removeAttribute('sort-direction');
2178
+ header.setAttribute('aria-sort', 'none');
176
2179
  return;
177
2180
  }
178
- this.updateOverflowForTarget(event.target);
179
- };
180
- this.generatedHeaderPrefix = generateUniqueId();
181
- /**
182
- * Recalcula estrutura, tokens e metadados de acessibilidade quando há mudança de slots.
183
- */
184
- this.handleStructureChange = () => {
185
- this.scheduleStructureRefresh();
186
- };
2181
+ header.setAttribute('sort-direction', criterion.direction);
2182
+ header.setAttribute('aria-sort', criterion.direction === TABLE_SORT_DIRECTION.ASC ? 'ascending' : 'descending');
2183
+ });
187
2184
  }
188
- get effectiveDividerStyle() {
189
- return resolveAllowedPropValue(this.el, 'dividerStyle', this.dividerStyle, ['solid', 'dashed'], 'solid');
2185
+ /**
2186
+ * Observa linhas adicionadas, removidas ou alteradas em tempo de execução.
2187
+ */
2188
+ observeStructureChanges() {
2189
+ this.structureObserver?.disconnect();
2190
+ this.structureObserver = new MutationObserver((mutations) => this.handleStructureMutations(mutations));
2191
+ this.structureObserver.observe(this.el, {
2192
+ attributeFilter: [
2193
+ 'row-group',
2194
+ 'row-span',
2195
+ 'col-span',
2196
+ 'selected',
2197
+ 'disabled',
2198
+ 'row-expansion',
2199
+ 'expanded',
2200
+ 'virtual-expanded-content-height',
2201
+ 'aria-label',
2202
+ 'aria-labelledby',
2203
+ 'style',
2204
+ 'class',
2205
+ ],
2206
+ attributes: true,
2207
+ attributeOldValue: true,
2208
+ childList: true,
2209
+ subtree: true,
2210
+ });
190
2211
  }
191
- get effectiveHorizontalAlignment() {
192
- return resolveAllowedPropValue(this.el, 'horizontalAlignment', this.horizontalAlignment, ['start', 'center', 'end'], undefined, { allowUndefined: true });
2212
+ /**
2213
+ * Processa mutações externas: estrutura completa quando linhas mudam e somente
2214
+ * densidade quando a herança CSS dentro da tabela pode ter mudado.
2215
+ */
2216
+ handleStructureMutations(mutations) {
2217
+ if (mutations.some((mutation) => mutation.type === 'attributes' &&
2218
+ mutation.target === this.el &&
2219
+ (mutation.attributeName === 'aria-label' || mutation.attributeName === 'aria-labelledby'))) {
2220
+ forceUpdate(this);
2221
+ }
2222
+ if (this.isRenderingData)
2223
+ return;
2224
+ if (mutations.some((mutation) => this.isRelevantStructureMutation(mutation))) {
2225
+ this.handleStructureChange();
2226
+ }
2227
+ else if (mutations.some((mutation) => (mutation.type === 'childList' ||
2228
+ mutation.attributeName === 'style' ||
2229
+ (mutation.attributeName === 'class' && !isHydrationClassMutation(mutation))) &&
2230
+ mutation.target instanceof HTMLElement &&
2231
+ mutation.target.closest('br-table') === this.el)) {
2232
+ this.updateActionDensities();
2233
+ }
193
2234
  }
194
- get effectiveVerticalAlignment() {
195
- return resolveAllowedPropValue(this.el, 'verticalAlignment', this.verticalAlignment, ['start', 'center', 'end'], undefined, { allowUndefined: true });
2235
+ /**
2236
+ * Executa escritas internas sem realimentar o observer estrutural.
2237
+ *
2238
+ * @remarks Mutações externas já pendentes são preservadas e reprocessadas;
2239
+ * somente os registros gerados durante `write` são descartados, pois quem
2240
+ * escreve já sincroniza o estado derivado.
2241
+ */
2242
+ runWithoutSelfMutations(write) {
2243
+ const observer = this.structureObserver;
2244
+ if (observer === undefined || this.selfMutationDepth > 0) {
2245
+ write();
2246
+ return;
2247
+ }
2248
+ const pending = observer.takeRecords();
2249
+ this.selfMutationDepth++;
2250
+ try {
2251
+ write();
2252
+ }
2253
+ finally {
2254
+ this.selfMutationDepth--;
2255
+ observer.takeRecords();
2256
+ if (pending.length > 0) {
2257
+ queueMicrotask(() => {
2258
+ if (this.structureObserver === observer)
2259
+ this.handleStructureMutations(pending);
2260
+ });
2261
+ }
2262
+ }
196
2263
  }
197
- get effectiveOverflow() {
198
- return resolveAllowedPropValue(this.el, 'overflow', this.overflow, ['truncate', 'wrap'], TABLE_OVERFLOW.WRAP);
2264
+ /**
2265
+ * Determina se uma mutação exige sincronização estrutural da tabela.
2266
+ */
2267
+ isRelevantStructureMutation(mutation) {
2268
+ if (mutation.type === 'attributes') {
2269
+ return this.handleRowAttributeMutation(mutation);
2270
+ }
2271
+ const changedNodes = Array.from(mutation.addedNodes).concat(Array.from(mutation.removedNodes));
2272
+ return this.hasRowChangeInNodes(changedNodes);
199
2273
  }
200
- get effectiveTooltipState() {
201
- return resolveAllowedPropValue(this.el, 'tooltipState', this.tooltipState, ['info', 'warning', 'danger', 'success'], TABLE_TOOLTIP_STATE.INFO);
2274
+ /**
2275
+ * Processa mutações de atributo aplicadas às linhas.
2276
+ */
2277
+ handleGroupingMutation(mutation, target) {
2278
+ const current = target.getAttribute(mutation.attributeName ?? '');
2279
+ const unchanged = mutation.attributeName === 'row-group'
2280
+ ? (mutation.oldValue?.trim() || '') === (current?.trim() || '')
2281
+ : resolveTableSpan(mutation.oldValue) === resolveTableSpan(current);
2282
+ if (unchanged)
2283
+ return false;
2284
+ this.dataStore.invalidateGroups();
2285
+ this.virtualList?.reset(false);
2286
+ forceUpdate(this);
2287
+ return true;
202
2288
  }
203
- get effectiveTooltipMode() {
204
- return resolveAllowedPropValue(this.el, 'tooltipMode', this.tooltipMode, [TABLE_TOOLTIP_MODE.INHERIT, TABLE_TOOLTIP_MODE.ENABLED, TABLE_TOOLTIP_MODE.DISABLED], undefined, { allowUndefined: true });
2289
+ handleRowAttributeMutation(mutation) {
2290
+ const target = mutation.target;
2291
+ if (['row-group', 'row-span', 'col-span'].includes(mutation.attributeName ?? '')) {
2292
+ return this.handleGroupingMutation(mutation, target);
2293
+ }
2294
+ if (!target.matches('br-table-row'))
2295
+ return false;
2296
+ if (mutation.attributeName === 'style' || mutation.attributeName === 'class')
2297
+ return false;
2298
+ if (mutation.attributeName === 'row-expansion' &&
2299
+ (mutation.oldValue ?? TABLE_ROW_EXPANSION.INHERIT) ===
2300
+ (target.getAttribute('row-expansion') ?? TABLE_ROW_EXPANSION.INHERIT)) {
2301
+ return false;
2302
+ }
2303
+ if (mutation.attributeName === 'expanded' || mutation.attributeName === 'virtual-expanded-content-height') {
2304
+ const logicalIndex = Number(target.getAttribute('data-virtual-index')) - this.resolveVirtualRangeOffset();
2305
+ if (Number.isInteger(logicalIndex) && this.getVirtualRows()[logicalIndex] === target) {
2306
+ this.virtualList.invalidateRow(logicalIndex);
2307
+ }
2308
+ return mutation.attributeName === 'expanded';
2309
+ }
2310
+ return true;
205
2311
  }
206
2312
  /**
207
- * Reaplica a largura das colunas quando alterada.
2313
+ * Verifica se os nós alterados impactam linhas da tabela.
208
2314
  */
209
- handleTableColumnWidthChange() {
210
- this.updateColumnWidths();
2315
+ hasRowChangeInNodes(nodes) {
2316
+ return nodes.some((node) => node instanceof HTMLElement && (node.matches('br-table-row') || node.querySelector('br-table-row') !== null));
211
2317
  }
212
2318
  /**
213
- * Reaplica o token de densidade quando alterado.
2319
+ * Detecta a presença de ações atribuídas às barras.
214
2320
  */
215
- handleDensityChange() {
216
- this.applyDensity();
2321
+ syncBarActionsContent() {
2322
+ const children = Array.from(this.el.children);
2323
+ this.hasGlobalActionsContent = children.some((child) => child.getAttribute('slot') === 'global-actions');
2324
+ this.hasContextualActionsContent = children.some((child) => child.getAttribute('slot') === 'contextual-actions');
217
2325
  }
218
2326
  /**
219
- * Atualiza os tokens de divisor quando qualquer propriedade relacionada é alterada.
2327
+ * Atualiza o estado reativo usado pela barra contextual.
220
2328
  */
221
- handleDividerChange() {
222
- this.applyDividers();
2329
+ updateSelectionCount() {
2330
+ this.selectedRowsCount = this.selection.getSelectedRows().length;
223
2331
  }
224
2332
  /**
225
- * Atualiza os tokens de alinhamento quando alterados.
2333
+ * Sincroniza células, checkboxes e estado da seleção.
226
2334
  */
227
- handleAlignmentChange() {
228
- this.updateAllCellAlignments();
2335
+ syncSelectionStructure() {
2336
+ this.selection.sync(this.hasRowSelection);
2337
+ this.updateSelectionCount();
229
2338
  }
230
2339
  /**
231
- * Atualiza os tokens de overflow quando a propriedade é alterada.
2340
+ * Sincroniza células, ações e estado da expansão.
232
2341
  */
233
- handleOverflowChange() {
234
- this.updateAllCellOverflow();
235
- }
236
- handleTooltipPropsChange() {
237
- this.validateTooltipProps();
2342
+ syncExpansionStructure() {
2343
+ this.expansion.sync(this.hasRowExpansion);
238
2344
  }
239
- validateTooltipProps() {
2345
+ /** Aplica às linhas a marca consumida pelo estilo de hover das células. */
2346
+ syncRowHoverState() {
2347
+ this.dataStore.getRows().forEach((row) => {
2348
+ row.toggleAttribute('data-row-hover-enabled', this.hasRowHover);
2349
+ });
240
2350
  }
241
2351
  /**
242
- * Ciclo de vida do componente que é chamado após o componente ser carregado no DOM.
243
- * Inicializa os tokens visuais após a montagem do componente.
2352
+ * Retorna somente as linhas pertencentes ao corpo da tabela.
244
2353
  */
245
- componentDidLoad() {
246
- this.refreshStructure();
247
- this.applyDensity();
248
- this.applyDividers();
249
- this.validateTooltipProps();
250
- // garante cálculo inicial após filhos renderizarem
251
- queueMicrotask(() => {
252
- this.updateColumnWidths();
2354
+ getBodyRows() {
2355
+ return this.dataStore.getRows();
2356
+ }
2357
+ /** Atualiza somente os elementos atualmente materializados pela lista virtual. */
2358
+ syncRenderedRange() {
2359
+ this.runWithoutSelfMutations(() => {
2360
+ this.annotateBoundaries();
253
2361
  this.updateAllCellAlignments();
254
2362
  this.updateAllCellOverflow();
2363
+ this.updateActionDensities();
255
2364
  this.applyAriaMetadata();
256
2365
  });
2366
+ this.updateScrollableContentState();
257
2367
  }
258
- connectedCallback() {
259
- this.el.addEventListener('brColumnWidthChange', this.handleColumnWidthEvent);
260
- this.el.addEventListener('brAlignmentChange', this.handleAlignmentEvent);
261
- this.el.addEventListener('brOverflowChange', this.handleOverflowEvent);
2368
+ updateActionDensities() {
2369
+ const densities = this.getAllCells().map((cell) => ({
2370
+ cell,
2371
+ density: resolveTableDensityFromElement(cell),
2372
+ }));
2373
+ densities.forEach(({ cell, density }) => {
2374
+ if (cell.getAttribute('action-density') !== density)
2375
+ cell.setAttribute('action-density', density);
2376
+ cell.querySelectorAll('br-table-action').forEach((action) => {
2377
+ if (action.getAttribute('density') !== density)
2378
+ action.setAttribute('density', density);
2379
+ });
2380
+ });
262
2381
  }
263
- disconnectedCallback() {
264
- this.el.removeEventListener('brColumnWidthChange', this.handleColumnWidthEvent);
265
- this.el.removeEventListener('brAlignmentChange', this.handleAlignmentEvent);
266
- this.el.removeEventListener('brOverflowChange', this.handleOverflowEvent);
267
- if (this.structureRefreshFrame !== null) {
268
- cancelAnimationFrame(this.structureRefreshFrame);
269
- this.structureRefreshFrame = null;
2382
+ updateScrollableContentState() {
2383
+ const viewport = this.el.shadowRoot?.querySelector('.br-table-scroll');
2384
+ const nextHasScrollableContent = viewport !== null &&
2385
+ viewport !== undefined &&
2386
+ (viewport.scrollHeight > viewport.clientHeight + 1 || viewport.scrollWidth > viewport.clientWidth + 1);
2387
+ if (this.hasScrollableContent !== nextHasScrollableContent) {
2388
+ this.hasScrollableContent = nextHasScrollableContent;
270
2389
  }
271
2390
  }
272
- /** Inicia o estado de carregamento da tabela. */
273
- async startLoading() {
274
- this.loading = true;
2391
+ /**
2392
+ * Mede cabeçalho e uma linha colapsada já renderizada para garantir que
2393
+ * `visibleRows` corresponda à quantidade real de linhas visíveis.
2394
+ * A estimativa baseada em densidade continua sendo usada somente antes da
2395
+ * primeira materialização.
2396
+ */
2397
+ /**
2398
+ * Invalida as métricas que definem a altura externa da viewport.
2399
+ *
2400
+ * @remarks A altura não deve ser recalculada durante o scroll, porque
2401
+ * diferentes janelas podem conter linhas com alturas distintas. Recalcular
2402
+ * nesse momento faria o próprio `br-table` crescer ou encolher e deslocaria
2403
+ * elementos externos à tabela.
2404
+ */
2405
+ invalidateViewportMetrics() {
2406
+ this.measuredCollapsedRowHeight = null;
275
2407
  }
276
- /** Interrompe o estado de carregamento da tabela. */
277
- async stopLoading() {
278
- this.loading = false;
2408
+ scheduleViewportHeightMeasurement() {
2409
+ if (this.measuredCollapsedRowHeight !== null && this.measuredHeaderHeight !== null)
2410
+ return;
2411
+ if (this.viewportMeasureFrame !== null)
2412
+ return;
2413
+ this.viewportMeasureFrame = requestAnimationFrame(() => {
2414
+ this.viewportMeasureFrame = null;
2415
+ for (const entry of this.headerHeights.values())
2416
+ entry.refresh();
2417
+ this.updateHeaderHeight();
2418
+ this.applyMeasuredViewportHeight();
2419
+ });
2420
+ }
2421
+ applyMeasuredViewportHeight() {
2422
+ const viewport = this.el.shadowRoot?.querySelector('.br-table-scroll');
2423
+ if (viewport === null || viewport === undefined)
2424
+ return;
2425
+ const referenceRow = this.dataStore.getRenderedRows().find((row) => !row.hasAttribute('expanded'));
2426
+ const measuredRowHeight = referenceRow === undefined
2427
+ ? 0
2428
+ : Math.max(0, ...Array.from(referenceRow.querySelectorAll('br-table-cell'))
2429
+ .filter((cell) => Number(cell.getAttribute('aria-rowspan') ?? 1) <= 1)
2430
+ .map((cell) => cell.shadowRoot?.querySelector('.br-table-cell')?.getBoundingClientRect().height ?? 0));
2431
+ const rowHeight = measuredRowHeight > 0 ? measuredRowHeight : this.resolveVirtualRowHeight();
2432
+ const rowHeightChanged = this.measuredCollapsedRowHeight !== rowHeight;
2433
+ if (rowHeightChanged)
2434
+ this.measuredCollapsedRowHeight = rowHeight;
2435
+ // O JSX usa os valores medidos por meio de resolveScrollViewportHeight().
2436
+ // Mantê-los em @State evita que uma renderização posterior restaure a
2437
+ // estimativa baseada apenas na densidade.
279
2438
  }
280
2439
  /**
281
- * Marca a última linha e a última coluna para permitir estilização condicional.
2440
+ * Marca limites de linha e coluna usados pelos estilos de divisores.
282
2441
  */
283
- refreshStructure() {
284
- this.headers = Array.from(this.el.querySelectorAll('br-table-header-cell')).filter((element) => findComposedOwner(element, 'br-table') === this.el);
285
- this.rows = Array.from(this.el.querySelectorAll('br-table-row')).filter((element) => findComposedOwner(element, 'br-table') === this.el);
286
- this.cells = [
287
- ...this.headers,
288
- ...Array.from(this.el.querySelectorAll('br-table-cell')).filter((element) => findComposedOwner(element, 'br-table') === this.el),
2442
+ /** Matriz lógica inclui células mescladas nas posições ocupadas. */
2443
+ getKeyboardRows() {
2444
+ const headerRows = Array.from(this.el.querySelectorAll('br-table-header > br-table-row'));
2445
+ const matrices = [
2446
+ getTablePlacements(headerRows, 'br-table-header-cell'),
2447
+ ...getTableRowGroups(this.getVirtualRows()).map((group) => getTablePlacements(group, 'br-table-cell')),
289
2448
  ];
290
- this.rowCells.clear();
291
- this.columnIndexes.clear();
292
- const columnCount = this.headers.length;
293
- this.headers.forEach((column, columnIndex) => {
2449
+ return matrices.flatMap((placements) => {
2450
+ const matrix = [];
2451
+ for (const { cell, row, column, rowSpan, colSpan } of placements) {
2452
+ for (let y = row; y < row + rowSpan; y++) {
2453
+ matrix[y] ?? (matrix[y] = []);
2454
+ for (let x = column; x < column + colSpan; x++)
2455
+ matrix[y][x] = cell;
2456
+ }
2457
+ }
2458
+ return matrix.filter((row) => row.length > 0);
2459
+ });
2460
+ }
2461
+ syncHeaderGrouping() {
2462
+ applyTableHeaderLayout(this.el.querySelector('br-table-header'));
2463
+ }
2464
+ annotateBoundaries() {
2465
+ this.syncHeaderGrouping();
2466
+ const columns = this.getHeaderCells();
2467
+ const columnCount = columns.length;
2468
+ const logicalLastRow = this.dataStore.getRowCount() - 1;
2469
+ columns.forEach((column, columnIndex) => {
294
2470
  if (!(column instanceof HTMLElement))
295
2471
  return;
296
- const isLastColumn = columnIndex === columnCount - 1;
297
- column.toggleAttribute('data-last-column', isLastColumn);
298
- this.columnIndexes.set(column, columnIndex);
299
- });
300
- this.rows.forEach((row, rowIndex) => {
301
- const isLastRow = rowIndex === this.rows.length - 1;
302
- const rowCells = Array.from(row.querySelectorAll('br-table-cell, br-table-header-cell')).filter((cell) => findComposedOwner(cell, 'br-table-row') === row);
303
- this.rowCells.set(row, rowCells);
304
- rowCells.forEach((cell, columnIndex) => {
2472
+ column.toggleAttribute('data-last-column', columnIndex === columnCount - 1);
2473
+ });
2474
+ this.dataStore.getRenderedRows().forEach((row) => {
2475
+ const logicalIndex = Number(row.getAttribute('data-virtual-index'));
2476
+ const isLastRow = logicalIndex === logicalLastRow;
2477
+ const cells = Array.from(row.querySelectorAll('br-table-cell'));
2478
+ cells.forEach((cell, columnIndex) => {
305
2479
  if (!(cell instanceof HTMLElement))
306
2480
  return;
307
- const isLastColumn = columnIndex === columnCount - 1;
308
2481
  cell.toggleAttribute('data-last-row', isLastRow);
309
- cell.toggleAttribute('data-last-column', isLastColumn);
310
- this.columnIndexes.set(cell, columnIndex);
2482
+ cell.toggleAttribute('data-last-column', columnIndex === columnCount - 1);
311
2483
  });
312
2484
  });
313
- this.structureReady = true;
314
2485
  }
315
- scheduleStructureRefresh() {
316
- if (this.structureRefreshFrame !== null)
317
- return;
318
- this.structureRefreshFrame = requestAnimationFrame(() => {
319
- this.structureRefreshFrame = null;
320
- this.refreshStructure();
2486
+ /**
2487
+ * Registra a coordenação de mudanças de largura emitidas pelas colunas.
2488
+ */
2489
+ registerColumnWidthListener() {
2490
+ this.el.addEventListener('brColumnWidthChange', () => {
321
2491
  this.updateColumnWidths();
322
- this.updateAllCellAlignments();
323
- this.updateAllCellOverflow();
324
2492
  this.applyAriaMetadata();
325
2493
  });
326
2494
  }
327
2495
  /**
328
- * Atualiza a largura das colunas com base nos cabeçalhos.
329
- * @returns void
2496
+ * Recalcula e aplica a definição de colunas do grid.
330
2497
  */
331
2498
  updateColumnWidths() {
332
2499
  const headers = this.getHeaderCells();
@@ -336,9 +2503,7 @@ const Table = class {
336
2503
  this.applyGridTemplate(template);
337
2504
  }
338
2505
  /**
339
- * Constrói o template de grid para a tabela com base nos cabeçalhos.
340
- * @param headers Os elementos de cabeçalho da tabela.
341
- * @returns Uma string representando o template de grid CSS.
2506
+ * Constrói o valor de `grid-template-columns` na ordem dos cabeçalhos.
342
2507
  */
343
2508
  buildGridTemplate(headers) {
344
2509
  const tableWidth = this.resolveTableColumnWidth();
@@ -346,37 +2511,22 @@ const Table = class {
346
2511
  return columnWidths.join(' ');
347
2512
  }
348
2513
  /**
349
- * Resolve a largura de uma coluna específica com base no cabeçalho e na largura global da tabela.
2514
+ * Resolve a largura padrão declarada na tabela.
350
2515
  */
351
2516
  resolveTableColumnWidth() {
352
- return this.resolveWidthToken(this.columnWidth, COLUMN_WIDTH_MAP[COLUMN_WIDTH_SEMANTICS.FILL], this.el);
2517
+ return this.resolveWidthToken(this.columnWidth, COLUMN_WIDTH_MAP[COLUMN_WIDTH_SEMANTICS.FILL]);
353
2518
  }
354
2519
  /**
355
- * Resolve a largura de uma coluna específica com base no cabeçalho e na largura global da tabela.
356
- * @param header O elemento de cabeçalho da coluna.
357
- * @param fallback A largura de fallback a ser usada caso o cabeçalho não defina uma largura.
358
- * @returns A largura resolvida da coluna.
2520
+ * Resolve a largura de uma coluna com fallback para a tabela.
359
2521
  */
360
2522
  resolveColumnWidth(header, fallback) {
361
2523
  const headerWidth = header.getAttribute('column-width');
362
- return this.resolveWidthToken(headerWidth, fallback, header);
2524
+ return this.resolveWidthToken(headerWidth, fallback);
363
2525
  }
364
2526
  /**
365
- * Aplica o template de grid à tabela definindo a propriedade CSS customizada correspondente.
366
- * @param raw O template de grid bruto a ser aplicado.
367
- * @param fallback O template de grid de fallback a ser usado caso o valor bruto seja inválido.
368
- * @return void
2527
+ * Valida e converte larguras semânticas ou valores CSS aceitos.
369
2528
  */
370
- resolveWidthToken(raw, fallback, host) {
371
- if (raw !== undefined && raw !== '') {
372
- const isValid = raw in COLUMN_WIDTH_MAP || positivePxValidator(raw) || positiveFrValidator(raw);
373
- if (!isValid) {
374
- reportInvalidPropValue(host, 'columnWidth', raw, 'Use `fill`, `content`, uma largura positiva em `px` ou uma fração positiva em `fr`.', `Aplicando fallback ${fallback}.`);
375
- }
376
- else {
377
- clearInvalidPropWarning(host, 'columnWidth');
378
- }
379
- }
2529
+ resolveWidthToken(raw, fallback) {
380
2530
  return resolveTokenValue(raw ?? undefined, {
381
2531
  fallback,
382
2532
  semanticMap: COLUMN_WIDTH_MAP,
@@ -384,14 +2534,22 @@ const Table = class {
384
2534
  });
385
2535
  }
386
2536
  /**
387
- * Aplica o template de grid à tabela definindo a propriedade CSS customizada correspondente.
388
- * @param template O template de grid a ser aplicado.
2537
+ * Publica a definição de colunas por meio do token do grid.
389
2538
  */
390
2539
  applyGridTemplate(template) {
391
2540
  this.el.style.setProperty(TABLE_TOKENS.COLUMN_WIDTHS, template);
392
2541
  }
393
2542
  /**
394
- * Atualiza o alinhamento de todas as células da tabela com base nos tokens de alinhamento.
2543
+ * Registra a coordenação de mudanças de alinhamento emitidas pelos filhos.
2544
+ */
2545
+ registerAlignmentListener() {
2546
+ this.el.addEventListener('brAlignmentChange', () => {
2547
+ this.updateAllCellAlignments();
2548
+ this.applyAriaMetadata();
2549
+ });
2550
+ }
2551
+ /**
2552
+ * Recalcula os alinhamentos efetivos de todas as células.
395
2553
  */
396
2554
  updateAllCellAlignments() {
397
2555
  const cells = this.getAllCells();
@@ -400,8 +2558,7 @@ const Table = class {
400
2558
  });
401
2559
  }
402
2560
  /**
403
- * Atualiza o alinhamento de uma célula específica com base nos tokens de alinhamento.
404
- * @param cell A célula a ser atualizada.
2561
+ * Aplica os alinhamentos efetivos como tokens locais da célula.
405
2562
  */
406
2563
  updateAlignmentForCell(cell) {
407
2564
  const horizontal = this.resolveHorizontalAlignmentForCell(cell);
@@ -410,54 +2567,43 @@ const Table = class {
410
2567
  cell.style.setProperty(TABLE_TOKENS.VERTICAL_ALIGNMENT, vertical);
411
2568
  }
412
2569
  /**
413
- * Resolve o alinhamento horizontal de uma célula específica com base nos tokens de alinhamento.
414
- * @param cell A célula a ser avaliada.
415
- * @returns O valor do token de alinhamento horizontal resolvido.
2570
+ * Resolve o alinhamento horizontal conforme a hierarquia da tabela.
416
2571
  */
417
2572
  resolveHorizontalAlignmentForCell(cell) {
418
- // Cell
419
2573
  const cellValue = cell.getAttribute('horizontal-alignment');
420
2574
  if (cellValue !== null)
421
2575
  return this.resolveAlignmentToken(cellValue);
422
- // Row
423
- const row = findComposedOwner(cell, 'br-table-row');
2576
+ const row = cell.closest('br-table-row');
424
2577
  const rowValue = row?.getAttribute('horizontal-alignment');
425
2578
  if (rowValue !== null)
426
2579
  return this.resolveAlignmentToken(rowValue);
427
- // Column (header)
428
2580
  const columnValue = this.getColumnAlignment(cell, 'horizontal-alignment');
429
2581
  if (columnValue !== null)
430
2582
  return this.resolveAlignmentToken(columnValue);
431
- // Table
432
- if (this.effectiveHorizontalAlignment !== undefined)
433
- return this.resolveAlignmentToken(this.effectiveHorizontalAlignment);
434
- // Fallback
2583
+ if (this.horizontalAlignment !== undefined)
2584
+ return this.resolveAlignmentToken(this.horizontalAlignment);
435
2585
  return TABLE_ALIGNMENT_MAP[TABLE_ALIGNMENT.START];
436
2586
  }
437
2587
  /**
438
- * Resolve o alinhamento vertical de uma célula específica com base nos tokens de alinhamento.
439
- * @param cell A célula a ser avaliada.
440
- * @returns O valor do token de alinhamento vertical resolvido.
2588
+ * Resolve o alinhamento vertical conforme a hierarquia da tabela.
441
2589
  */
442
2590
  resolveVerticalAlignmentForCell(cell) {
443
2591
  const cellValue = cell.getAttribute('vertical-alignment');
444
2592
  if (cellValue !== null)
445
2593
  return this.resolveAlignmentToken(cellValue);
446
- const row = findComposedOwner(cell, 'br-table-row');
2594
+ const row = cell.closest('br-table-row');
447
2595
  const rowValue = row?.getAttribute('vertical-alignment');
448
2596
  if (rowValue !== null)
449
2597
  return this.resolveAlignmentToken(rowValue);
450
2598
  const columnValue = this.getColumnAlignment(cell, 'vertical-alignment');
451
2599
  if (columnValue !== null)
452
2600
  return this.resolveAlignmentToken(columnValue);
453
- if (this.effectiveVerticalAlignment !== undefined)
454
- return this.resolveAlignmentToken(this.effectiveVerticalAlignment);
2601
+ if (this.verticalAlignment !== undefined)
2602
+ return this.resolveAlignmentToken(this.verticalAlignment);
455
2603
  return TABLE_ALIGNMENT_MAP[TABLE_ALIGNMENT.START];
456
2604
  }
457
2605
  /**
458
- * Resolve um valor de token de alinhamento com base no valor bruto e no mapeamento semântico definido.
459
- * @param value O valor bruto do token de alinhamento a ser resolvido.
460
- * @returns O valor do token de alinhamento resolvido, ou o valor de fallback se o valor bruto for inválido.
2606
+ * Converte um alinhamento semântico no valor CSS correspondente.
461
2607
  */
462
2608
  resolveAlignmentToken(value) {
463
2609
  return resolveTokenValue(value ?? undefined, {
@@ -466,10 +2612,7 @@ const Table = class {
466
2612
  });
467
2613
  }
468
2614
  /**
469
- * Retorna o valor do atributo de alinhamento de uma coluna específica.
470
- * @param cell A célula para a qual o alinhamento da coluna deve ser obtido.
471
- * @param attribute O atributo de alinhamento a ser obtido ('horizontal-alignment' ou 'vertical-alignment').
472
- * @returns O valor do atributo de alinhamento da coluna, ou null se não estiver definido.
2615
+ * Obtém um atributo herdável no cabeçalho da coluna correspondente.
473
2616
  */
474
2617
  getColumnAlignment(cell, attribute) {
475
2618
  const columnIndex = this.getColumnIndex(cell);
@@ -480,98 +2623,92 @@ const Table = class {
480
2623
  return header?.getAttribute(attribute) ?? null;
481
2624
  }
482
2625
  /**
483
- * Obtém o índice da coluna para uma célula específica, permitindo a associação entre células e seus respectivos cabeçalhos para herança de propriedades como alinhamento e largura.
484
- * @param cell A célula para a qual o índice da coluna deve ser obtido.
485
- * @returns O índice da coluna correspondente à célula, ou -1 se a célula não estiver dentro de uma linha válida.
2626
+ * Retorna a posição de uma célula dentro de sua linha.
486
2627
  */
487
2628
  getColumnIndex(cell) {
488
- return this.columnIndexes.get(cell) ?? -1;
2629
+ const row = cell.closest('br-table-row');
2630
+ if (row === null)
2631
+ return -1;
2632
+ const group = row.parentElement?.hasAttribute('data-table-row-group')
2633
+ ? Array.from(row.parentElement.querySelectorAll(':scope > br-table-row'))
2634
+ : [row];
2635
+ return getTablePlacements(group, 'br-table-cell').find((entry) => entry.cell === cell)?.column ?? -1;
489
2636
  }
490
2637
  /**
491
- * Constrói o template de grid para a tabela com base nos cabeçalhos.
492
- * @return Array de larguras de coluna resolvidas.
2638
+ * Retorna os cabeçalhos na ordem visual do grid.
493
2639
  */
494
2640
  getHeaderCells() {
495
- return this.headers;
2641
+ return getTableLeafHeaders(Array.from(this.el.querySelectorAll('br-table-header > br-table-row')));
496
2642
  }
497
2643
  /**
498
- * Obtém todas as células (tanto de corpo quanto de cabeçalho) da tabela, permitindo a aplicação de estilos e tokens de forma abrangente.
499
- * @returns Um array contendo todas as células da tabela.
2644
+ * Retorna células de cabeçalho e de dados.
500
2645
  */
501
2646
  getAllCells() {
502
- return this.cells;
2647
+ return Array.from(this.el.querySelectorAll('br-table-cell, br-table-header-cell'));
2648
+ }
2649
+ /**
2650
+ * Registra a coordenação de mudanças de overflow emitidas pelos filhos.
2651
+ */
2652
+ registerOverflowListener() {
2653
+ this.el.addEventListener('brOverflowChange', () => {
2654
+ this.updateAllCellOverflow();
2655
+ this.applyAriaMetadata();
2656
+ });
503
2657
  }
504
2658
  /**
505
- * Aplica metadados ARIA para melhorar a navegação por leitores de tela.
2659
+ * Aplica contagens e índices ARIA à estrutura atual.
506
2660
  */
507
2661
  applyAriaMetadata() {
508
- const rows = this.rows;
509
- const headers = this.getHeaderCells();
510
- this.el.setAttribute('aria-colcount', String(headers.length));
511
- this.el.setAttribute('aria-rowcount', String(rows.length));
512
- rows.forEach((row, rowIndex) => {
513
- row.setAttribute('aria-rowindex', String(rowIndex + 1));
514
- });
515
- headers.forEach((header, headerIndex) => {
516
- const colIndex = String(headerIndex + 1);
517
- const headerId = header.id || `${this.generatedHeaderPrefix}-${headerIndex + 1}`;
518
- header.id = headerId;
519
- header.setAttribute('aria-colindex', colIndex);
520
- });
521
- const bodyCells = this.cells.filter((cell) => cell.tagName === 'BR-TABLE-CELL');
522
- bodyCells.forEach((cell) => {
523
- const columnIndex = this.getColumnIndex(cell);
524
- if (columnIndex === -1)
525
- return;
526
- const colIndex = String(columnIndex + 1);
527
- const header = headers[columnIndex];
528
- cell.setAttribute('aria-colindex', colIndex);
529
- if (header !== undefined && header.id !== '') {
530
- cell.setAttribute('aria-labelledby', header.id);
531
- }
2662
+ this.syncHeaderGrouping();
2663
+ const headerRows = Array.from(this.el.querySelectorAll('br-table-header > br-table-row'));
2664
+ const bodyRows = this.dataStore.getRenderedRows();
2665
+ const tableGrid = this.el.shadowRoot?.querySelector('.br-table-content');
2666
+ const grouped = this.dataStore.getItemCount() !== this.dataStore.getRowCount();
2667
+ const remote = this.hasPagination && this.dataStore.getItemCount() < this.resolvePaginationTotalItems();
2668
+ const logicalRowCount = remote ? this.resolvePaginationTotalItems() : this.dataStore.getRowCount();
2669
+ tableGrid?.setAttribute('aria-colcount', String(this.getHeaderCells().length));
2670
+ tableGrid?.setAttribute('aria-rowcount', grouped && remote ? '-1' : String(logicalRowCount + headerRows.length));
2671
+ headerRows.forEach((row, index) => {
2672
+ row.setAttribute('aria-rowindex', String(index + 1));
2673
+ });
2674
+ const headerPlacements = getTablePlacements(headerRows, 'br-table-header-cell');
2675
+ headerPlacements.forEach(({ cell, column }, index) => {
2676
+ cell.id || (cell.id = `${this.generatedHeaderPrefix}-${index + 1}`);
2677
+ cell.setAttribute('aria-colindex', String(column + 1));
532
2678
  });
2679
+ bodyRows.forEach((row) => {
2680
+ const offset = remote && !grouped ? (this.resolveCurrentPage() - 1) * this.resolvePageSize() : 0;
2681
+ const logicalIndex = Number(row.getAttribute('data-virtual-index'));
2682
+ if (grouped && remote)
2683
+ row.removeAttribute('aria-rowindex');
2684
+ else
2685
+ row.setAttribute('aria-rowindex', String(logicalIndex + offset + headerRows.length + 1));
2686
+ });
2687
+ for (const group of getTableRowGroups(bodyRows)) {
2688
+ for (const { cell, column, rowSpan, colSpan } of getTablePlacements(group, 'br-table-cell')) {
2689
+ cell.setAttribute('aria-colindex', String(column + 1));
2690
+ if (rowSpan > 1)
2691
+ cell.setAttribute('aria-rowspan', String(rowSpan));
2692
+ else
2693
+ cell.removeAttribute('aria-rowspan');
2694
+ if (colSpan > 1)
2695
+ cell.setAttribute('aria-colspan', String(colSpan));
2696
+ else
2697
+ cell.removeAttribute('aria-colspan');
2698
+ }
2699
+ }
2700
+ this.keyboard?.sync();
533
2701
  }
534
2702
  /**
535
- * Atualiza os tokens de overflow para todas as células da tabela, garantindo que as mudanças na propriedade de overflow sejam refletidas dinamicamente em todas as células, controlando o comportamento de overflow, text-overflow e white-space conforme definido no token.
2703
+ * Recalcula o overflow efetivo de todas as células.
536
2704
  */
537
2705
  updateAllCellOverflow() {
538
2706
  this.getAllCells().forEach((cell) => {
539
2707
  this.updateOverflowForCell(cell);
540
2708
  });
541
2709
  }
542
- updateAlignmentForTarget(target) {
543
- if (target === null || !this.el.contains(target))
544
- return;
545
- if (target.tagName === 'BR-TABLE-CELL' || target.tagName === 'BR-TABLE-HEADER-CELL') {
546
- this.updateAlignmentForCell(target);
547
- return;
548
- }
549
- if (target.tagName === 'BR-TABLE-ROW') {
550
- this.rowCells.get(target)?.forEach((cell) => {
551
- this.updateAlignmentForCell(cell);
552
- });
553
- return;
554
- }
555
- this.updateAllCellAlignments();
556
- }
557
- updateOverflowForTarget(target) {
558
- if (target === null || !this.el.contains(target))
559
- return;
560
- if (target.tagName === 'BR-TABLE-CELL' || target.tagName === 'BR-TABLE-HEADER-CELL') {
561
- this.updateOverflowForCell(target);
562
- return;
563
- }
564
- if (target.tagName === 'BR-TABLE-ROW') {
565
- this.rowCells.get(target)?.forEach((cell) => {
566
- this.updateOverflowForCell(cell);
567
- });
568
- return;
569
- }
570
- this.updateAllCellOverflow();
571
- }
572
2710
  /**
573
- * Atualiza os tokens de overflow para uma célula específica, controlando o comportamento de overflow, text-overflow e white-space com base na resolução do token de overflow para a célula, que considera atributos específicos da célula, da linha, da coluna e da tabela para determinar o comportamento final de overflow a ser aplicado.
574
- * @param cell A célula para a qual os tokens de overflow devem ser atualizados.
2711
+ * Aplica a configuração efetiva de overflow como tokens locais.
575
2712
  */
576
2713
  updateOverflowForCell(cell) {
577
2714
  const mode = this.resolveOverflowForCell(cell);
@@ -579,26 +2716,22 @@ const Table = class {
579
2716
  cell.style.setProperty(TABLE_TOKENS.CELL_OVERFLOW, config.overflow);
580
2717
  cell.style.setProperty(TABLE_TOKENS.CELL_TEXT_OVERFLOW, config.textOverflow);
581
2718
  cell.style.setProperty(TABLE_TOKENS.CELL_WHITE_SPACE, config.whiteSpace);
582
- // O atributo 'applied-overflow' deve sempre aparecer
583
2719
  cell.setAttribute('data-applied-overflow', mode);
584
2720
  }
585
2721
  /**
586
- * Resolve o token de overflow para uma célula específica, considerando a hierarquia de atributos (célula, linha, coluna, tabela) para determinar o comportamento de overflow final a ser aplicado à célula.
587
- * @param cell A célula para a qual o token de overflow deve ser resolvido.
588
- * @returns O valor do token de overflow resolvido para a célula, determinando o comportamento de overflow a ser aplicado.
2722
+ * Resolve o overflow conforme célula, linha, coluna e tabela.
589
2723
  */
590
2724
  resolveOverflowForCell(cell) {
591
- // Resolução hierárquica: célula > linha > coluna > tabela > fallback
592
2725
  let value = cell.getAttribute('overflow');
593
2726
  if (value === null) {
594
- const row = findComposedOwner(cell, 'br-table-row');
2727
+ const row = cell.closest('br-table-row');
595
2728
  value = row?.getAttribute('overflow') ?? null;
596
2729
  }
597
2730
  if (value === null) {
598
2731
  value = this.getColumnAttribute(cell, 'overflow') ?? null;
599
2732
  }
600
2733
  if (value === null) {
601
- value = this.effectiveOverflow;
2734
+ value = this.overflow ?? null;
602
2735
  }
603
2736
  if (value === null) {
604
2737
  value = TABLE_OVERFLOW.WRAP;
@@ -606,19 +2739,14 @@ const Table = class {
606
2739
  return value === TABLE_OVERFLOW.TRUNCATE ? TABLE_OVERFLOW.TRUNCATE : TABLE_OVERFLOW.WRAP;
607
2740
  }
608
2741
  /**
609
- * Obtém o valor de um atributo específico de uma coluna para uma célula, permitindo a herança de propriedades da coluna para as células associadas com base no cabeçalho correspondente.
610
- * @param cell A célula para a qual o atributo da coluna deve ser obtido.
611
- * @param attribute O atributo específico a ser obtido da coluna (por exemplo, 'horizontal-alignment' ou 'vertical-alignment').
612
- * @returns O valor do atributo da coluna correspondente à célula, ou null se não estiver definido.
2742
+ * Obtém um atributo no cabeçalho correspondente à célula.
613
2743
  */
614
2744
  getColumnAttribute(cell, attribute) {
615
2745
  const header = this.getHeaderForCell(cell);
616
2746
  return header?.getAttribute(attribute) ?? null;
617
2747
  }
618
2748
  /**
619
- * Obtém o elemento de cabeçalho correspondente a uma célula específica, permitindo a associação entre células e seus respectivos cabeçalhos para herança de propriedades como alinhamento e largura.
620
- * @param cell A célula para a qual o cabeçalho correspondente deve ser obtido.
621
- * @returns O elemento de cabeçalho correspondente à célula, ou null se não for encontrado.
2749
+ * Localiza o cabeçalho que ocupa a mesma coluna da célula.
622
2750
  */
623
2751
  getHeaderForCell(cell) {
624
2752
  const index = this.getColumnIndex(cell);
@@ -627,23 +2755,33 @@ const Table = class {
627
2755
  const headers = this.getHeaderCells();
628
2756
  return headers[index] ?? null;
629
2757
  }
2758
+ /** Publica a altura padrão da área expandida para herança pelas linhas. */
2759
+ applyExpandedContentHeight() {
2760
+ const value = Number.isFinite(this.virtualExpandedContentHeight)
2761
+ ? Math.max(1, this.virtualExpandedContentHeight)
2762
+ : 240;
2763
+ this.el.style.setProperty(TABLE_TOKENS.EXPANDED_CONTENT_HEIGHT, `${value}px`);
2764
+ }
630
2765
  /**
631
- * Resolve e aplica o token de densidade.
2766
+ * Converte a densidade semântica em tokens de espaçamento.
632
2767
  */
633
2768
  applyDensity() {
634
- const density = resolveDensity(this.el, this.density, { allowUndefined: true });
635
- const resolved = resolveTokenValue(density ?? undefined, {
2769
+ const resolved = resolveTokenValue(this.density, {
636
2770
  fallback: TABLE_DENSITY_MAP[TABLE_DENSITY.MEDIUM],
637
2771
  semanticMap: TABLE_DENSITY_MAP,
638
2772
  });
2773
+ const resolvedToolbarPadding = resolveTokenValue(this.density, {
2774
+ fallback: TABLE_BAR_PADDING_MAP[TABLE_DENSITY.MEDIUM],
2775
+ semanticMap: TABLE_BAR_PADDING_MAP,
2776
+ });
639
2777
  this.el.style.setProperty(TABLE_TOKENS.DENSITY, resolved);
2778
+ this.el.style.setProperty(TABLE_TOKENS.BAR_PADDING, resolvedToolbarPadding);
640
2779
  }
641
2780
  /**
642
- * Resolve e aplica os tokens relacionados aos divisores
643
- * (estilo e fatores de linha/coluna).
2781
+ * Aplica estilo e fatores de visibilidade dos divisores.
644
2782
  */
645
2783
  applyDividers() {
646
- const style = resolveTokenValue(this.effectiveDividerStyle, {
2784
+ const style = resolveTokenValue(this.dividerStyle, {
647
2785
  fallback: TABLE_DIVIDER_STYLE_MAP[TABLE_DIVIDER_STYLE.SOLID],
648
2786
  semanticMap: TABLE_DIVIDER_STYLE_MAP,
649
2787
  });
@@ -654,30 +2792,51 @@ const Table = class {
654
2792
  this.el.style.setProperty(TABLE_TOKENS.COLUMN_DIVIDER_FACTOR, columnFactor);
655
2793
  }
656
2794
  /**
657
- * Retorna o mapa de classes base do componente.
2795
+ * Renderiza barras, slots e o grid principal.
658
2796
  *
659
- * @returns Um objeto representando as classes CSS a serem aplicadas ao elemento da tabela.
2797
+ * @remarks `role="grid"` fica isolado no contêiner que só possui os dois
2798
+ * elementos `role="rowgroup"` como filhos; a barra de ações e o rodapé
2799
+ * ficam fora dessa árvore para não serem contados como filhos inválidos do
2800
+ * papel `grid`. O nome acessível vai como `aria-label` (string), pois um
2801
+ * `aria-labelledby` não resolveria um id do light DOM a partir da shadow tree.
660
2802
  */
661
- getTableCssClassMap() {
662
- return {
663
- 'br-table': true,
664
- };
2803
+ renderContent(accessibleName) {
2804
+ return (h(Fragment, null, h("br-table-bar", { "prop:density": this.density ?? TABLE_DENSITY.MEDIUM, "prop:heading": this.heading ?? '', "prop:headingActionsLimit": this.headingActionsLimit, "prop:contextualActionsLimit": this.contextualActionsLimit, "prop:hasGlobalActionsContent": this.hasGlobalActionsContent, "prop:hasContextualActionsContent": this.hasContextualActionsContent, "prop:selectedRowsCount": this.selectedRowsCount, "prop:showContextualBar": this.showContextualBar || this.selectedRowsCount > 0, "prop:hasSearch": this.hasSearch, "attr:data-br-table-heading-actions-tooltip-label": this.moreActionsHeadingLabel, "attr:data-br-table-contextual-actions-tooltip-label": this.moreActionsContextualLabel, style: {
2805
+ [TABLE_TOKENS.DENSITY]: resolveTokenValue(this.density, {
2806
+ fallback: TABLE_DENSITY_MAP[TABLE_DENSITY.MEDIUM],
2807
+ semanticMap: TABLE_DENSITY_MAP,
2808
+ }),
2809
+ } }, h("slot", { name: "global-actions", slot: "global-actions" }), h("slot", { name: "contextual-actions", slot: "contextual-actions" })), h("div", { class: { 'br-table-scroll-shell': true, loading: this.loading }, style: {
2810
+ height: this.resolveScrollViewportHeight(),
2811
+ '--table-scroll-header-height': `${this.measuredHeaderHeight ?? 0}px`,
2812
+ } }, h("div", { class: "br-table-scroll", part: "scroll-container", style: { height: this.resolveScrollViewportHeight() }, onScroll: this.handleViewportScroll }, h("div", { class: { 'br-table-content': true, loading: this.loading }, role: "grid", "aria-label": accessibleName, "aria-multiselectable": this.hasRowSelection ? 'true' : null, "aria-busy": this.loading ? 'true' : null, "aria-hidden": this.loading && this.dataStore.getRowCount() === 0 && this.dataStore.getColumns().length === 0
2813
+ ? 'true'
2814
+ : null, part: "content" }, h("slot", { name: "header", onSlotchange: this.handleStructureChange }), h("slot", { name: "body", onSlotchange: this.handleStructureChange }))))));
665
2815
  }
666
- /**
667
- * Renderiza a estrutura interna da tabela (header e body).
668
- *
669
- * @returns JSX.Element representando o conteúdo da tabela, incluindo os slots para header e body.
670
- */
671
- renderContent() {
672
- return (h("div", { class: { 'br-table-content': true, loading: this.loading }, part: "content" }, h("slot", { name: "header", onSlotchange: this.handleStructureChange }), h("slot", { name: "body", onSlotchange: this.handleStructureChange })));
2816
+ /** Resolve o nome acessível do papel `grid`, sempre como texto plano. */
2817
+ resolveAccessibleGridName() {
2818
+ const explicitLabelledby = this.el.getAttribute('aria-labelledby')?.trim();
2819
+ const root = this.el.getRootNode();
2820
+ if (explicitLabelledby && (root instanceof Document || root instanceof ShadowRoot)) {
2821
+ const referencedText = explicitLabelledby
2822
+ .split(/\s+/)
2823
+ .map((id) => root.getElementById(id)?.textContent?.trim())
2824
+ .filter(Boolean)
2825
+ .join(' ')
2826
+ .replace(/\s+/g, ' ');
2827
+ if (referencedText.length > 0)
2828
+ return referencedText;
2829
+ }
2830
+ const explicitLabel = this.el.getAttribute('aria-label')?.trim();
2831
+ if (explicitLabel)
2832
+ return explicitLabel;
2833
+ return this.heading?.trim() || 'Tabela';
673
2834
  }
674
2835
  /**
675
- * Renderiza o host do componente.
676
- *
677
- * @returns JSX.Element representando o elemento host do componente, contendo a estrutura da tabela.
2836
+ * Renderiza o componente com semântica ARIA de grid.
678
2837
  */
679
2838
  render() {
680
- return (h(Host, { key: '98c729fdca76ed9a92354b8caf2c46030ea0f1e4', role: "table", "aria-busy": this.loading ? 'true' : null }, h("div", { key: 'b64e8d0e0ce41e2983b7a55fe9c5764df107db2b', class: this.getTableCssClassMap(), part: "container" }, this.renderContent(), this.loading ? (h("div", { part: "loading", role: "status", "aria-live": "polite" }, h("slot", { name: "loading" }, h("br-loading", { size: "small", label: "Carregando dados" })))) : null)));
2839
+ return (h(Host, { key: 'a8583b9c76f2d800732bae952ec638fb9960ee81', "aria-busy": this.loading ? 'true' : null }, h("div", { key: '22bce3d4db20241d4fb03e792e0b3c5ee2dabcaf', class: "br-table", part: "container" }, this.renderContent(this.resolveAccessibleGridName())), this.hasPagination && (h("br-table-footer", { key: '4bf01e2f882971c10159c5f2a9d7ce78fcd1db9a', part: "footer", "prop:currentPage": this.currentPage, "prop:pageSize": this.resolvePageSize(), pageSizeOptions: this.pageSizeOptions, "prop:totalItems": this.resolvePaginationTotalItems(), "prop:density": this.density ?? 'medium', "attr:has-scroll": this.hasScrollableContent ? '' : null, onBrInternalTableFooterPageChange: this.handleFooterPageChange, onBrInternalTableFooterPerPageChange: this.handleFooterPerPageChange })), this.loading ? (h("div", { part: "loading", role: "status", "aria-live": "polite" }, h("div", { class: "br-table-loading-panel", role: "region", "aria-label": "Carregamento da tabela", tabIndex: 0 }, h("slot", { name: "loading" }, h("br-loading", { density: "medium", label: "Carregando dados", labelPosition: "bottom" }))))) : null));
681
2840
  }
682
2841
  get el() { return getElement(this); }
683
2842
  static get watchers() { return {
@@ -687,6 +2846,18 @@ const Table = class {
687
2846
  "density": [{
688
2847
  "handleDensityChange": 0
689
2848
  }],
2849
+ "visibleRows": [{
2850
+ "handleVisibleRowsChange": 0
2851
+ }],
2852
+ "hasPagination": [{
2853
+ "handleHasPaginationChange": 0
2854
+ }],
2855
+ "currentPage": [{
2856
+ "handleCurrentPageChange": 0
2857
+ }],
2858
+ "pageSize": [{
2859
+ "handlePageSizeChange": 0
2860
+ }],
690
2861
  "hasColumnDivider": [{
691
2862
  "handleDividerChange": 0
692
2863
  }],
@@ -711,11 +2882,23 @@ const Table = class {
711
2882
  "overflow": [{
712
2883
  "handleOverflowChange": 0
713
2884
  }],
714
- "tooltipState": [{
715
- "handleTooltipPropsChange": 0
2885
+ "virtualExpandedContentHeight": [{
2886
+ "handleVirtualExpandedContentHeightChange": 0
2887
+ }],
2888
+ "hasRowSelection": [{
2889
+ "handleRowSelectionChange": 0
2890
+ }],
2891
+ "hasRowHover": [{
2892
+ "handleRowHoverChange": 0
2893
+ }],
2894
+ "hasRowExpansion": [{
2895
+ "handleRowExpansionChange": 0
2896
+ }],
2897
+ "sortMode": [{
2898
+ "handleSortModeChange": 0
716
2899
  }],
717
- "tooltipMode": [{
718
- "handleTooltipPropsChange": 0
2900
+ "sortStrategy": [{
2901
+ "handleSortStrategyChange": 0
719
2902
  }]
720
2903
  }; }
721
2904
  };