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