@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.
- package/cem/custom-elements.json +4228 -996
- package/cem/webcomponents.html-custom-data.json +354 -48
- package/dist/cjs/br-avatar.cjs.entry.js +2 -2
- package/dist/cjs/br-breadcrumb-item.cjs.entry.js +1 -1
- package/dist/cjs/br-breadcrumb.cjs.entry.js +11 -11
- package/dist/cjs/br-button_2.cjs.entry.js +5 -5
- package/dist/cjs/br-card.cjs.entry.js +2 -2
- package/dist/cjs/br-carousel-page.cjs.entry.js +2 -2
- package/dist/cjs/br-carousel.cjs.entry.js +5 -5
- package/dist/cjs/br-checkbox-group.cjs.entry.js +2 -2
- package/dist/cjs/br-checkbox.cjs.entry.js +2 -2
- package/dist/cjs/br-checkgroup.cjs.entry.js +1 -1
- package/dist/cjs/br-collapse_2.cjs.entry.js +8 -8
- package/dist/cjs/br-cookiebar-cookie.cjs.entry.js +2 -2
- package/dist/cjs/br-cookiebar-group.cjs.entry.js +4 -4
- package/dist/cjs/br-cookiebar-header.cjs.entry.js +2 -2
- package/dist/cjs/br-cookiebar-link.cjs.entry.js +3 -3
- package/dist/cjs/br-cookiebar-note-group.cjs.entry.js +3 -3
- package/dist/cjs/br-cookiebar-note.cjs.entry.js +2 -2
- package/dist/cjs/br-cookiebar.cjs.entry.js +5 -5
- package/dist/cjs/br-crumb.cjs.entry.js +1 -1
- package/dist/cjs/br-date-picker_3.cjs.entry.js +14 -14
- package/dist/cjs/br-datetime-picker.cjs.entry.js +6 -23
- package/dist/cjs/br-divider.cjs.entry.js +2 -2
- package/dist/cjs/br-dropdown.cjs.entry.js +677 -0
- package/dist/cjs/br-footer-category.cjs.entry.js +2 -2
- package/dist/cjs/br-footer-item.cjs.entry.js +2 -2
- package/dist/cjs/br-footer-legal.cjs.entry.js +2 -2
- package/dist/cjs/br-footer-logo.cjs.entry.js +2 -2
- package/dist/cjs/br-footer-social.cjs.entry.js +3 -3
- package/dist/cjs/br-footer.cjs.entry.js +2 -2
- package/dist/cjs/br-header-function.cjs.entry.js +2 -2
- package/dist/cjs/br-header-link.cjs.entry.js +2 -2
- package/dist/cjs/br-header-list.cjs.entry.js +4 -4
- package/dist/cjs/br-header-logo.cjs.entry.js +2 -2
- package/dist/cjs/br-header.cjs.entry.js +6 -6
- package/dist/cjs/br-icon.cjs.entry.js +172 -158
- package/dist/cjs/br-input_2.cjs.entry.js +1427 -0
- package/dist/cjs/br-item.cjs.entry.js +2 -2
- package/dist/cjs/br-link.cjs.entry.js +2 -2
- package/dist/cjs/br-magic-button.cjs.entry.js +11 -12
- package/dist/cjs/br-menu-group.cjs.entry.js +2 -2
- package/dist/cjs/br-menu-header.cjs.entry.js +3 -3
- package/dist/cjs/br-menu-info.cjs.entry.js +2 -2
- package/dist/cjs/br-menu-item.cjs.entry.js +3 -3
- package/dist/cjs/br-menu-link.cjs.entry.js +3 -3
- package/dist/cjs/br-menu-list.cjs.entry.js +2 -2
- package/dist/cjs/br-menu-logo.cjs.entry.js +2 -2
- package/dist/cjs/br-menu-social.cjs.entry.js +2 -2
- package/dist/cjs/br-menu.cjs.entry.js +5 -5
- package/dist/cjs/br-modal.cjs.entry.js +2 -2
- package/dist/cjs/br-notification-body.cjs.entry.js +2 -2
- package/dist/cjs/br-notification-header.cjs.entry.js +2 -2
- package/dist/cjs/br-notification-item.cjs.entry.js +2 -2
- package/dist/cjs/br-notification.cjs.entry.js +2 -2
- package/dist/cjs/{br-dropdown_2.cjs.entry.js → br-pagination_2.cjs.entry.js} +812 -557
- package/dist/cjs/br-radio-group.cjs.entry.js +2 -2
- package/dist/cjs/br-radio.cjs.entry.js +2 -2
- package/dist/cjs/br-scrim.cjs.entry.js +2 -2
- package/dist/cjs/br-select-input_3.cjs.entry.js +16 -93
- package/dist/cjs/br-sign-in.cjs.entry.js +3 -3
- package/dist/cjs/br-skip-link-item.cjs.entry.js +1 -1
- package/dist/cjs/br-skip-link.cjs.entry.js +2 -2
- package/dist/cjs/br-skiplink-item.cjs.entry.js +2 -2
- package/dist/cjs/br-slider.cjs.entry.js +3 -3
- package/dist/cjs/br-step_2.cjs.entry.js +3 -3
- package/dist/cjs/br-switch.cjs.entry.js +2 -2
- package/dist/cjs/br-tab-item.cjs.entry.js +3 -3
- package/dist/cjs/br-tab.cjs.entry.js +7 -7
- package/dist/cjs/br-table-action_6.cjs.entry.js +1500 -0
- package/dist/cjs/br-table-body.cjs.entry.js +4 -16
- package/dist/cjs/br-table-header.cjs.entry.js +4 -16
- package/dist/cjs/br-table.cjs.entry.js +2616 -433
- package/dist/cjs/br-tag.cjs.entry.js +4 -4
- package/dist/cjs/br-textarea.cjs.entry.js +3 -3
- package/dist/cjs/br-tooltip.cjs.entry.js +5 -29
- package/dist/cjs/br-upload.cjs.entry.js +4 -4
- package/dist/cjs/br-wizard-panel.cjs.entry.js +3 -3
- package/dist/cjs/br-wizard.cjs.entry.js +3 -3
- package/dist/cjs/helpers-DkkDubv1.js +28 -0
- package/dist/cjs/{icon.utils-DF6kMskA.js → icon.utils-CMs0ukvR.js} +1 -1
- package/dist/cjs/{index-Bc30P_6z.js → index-BP8UIQro.js} +34 -34
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/table.utils-De-9_NgJ.js +749 -0
- package/dist/cjs/webcomponents.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +3 -0
- package/dist/collection/components/avatar/avatar.css +1 -1
- package/dist/collection/components/breadcrumb/breadcrumb.css +1 -1
- package/dist/collection/components/breadcrumb/breadcrumb.js +9 -9
- package/dist/collection/components/button/button.css +1 -1
- package/dist/collection/components/button/button.js +2 -2
- package/dist/collection/components/card/card.css +1 -1
- package/dist/collection/components/carousel/carousel-page/carousel-page.css +1 -1
- package/dist/collection/components/carousel/carousel.css +1 -1
- package/dist/collection/components/carousel/carousel.js +3 -3
- package/dist/collection/components/checkbox/checkbox.css +1 -1
- package/dist/collection/components/checkbox-group/checkbox-group.css +1 -1
- package/dist/collection/components/collapse/collapse.css +1 -1
- package/dist/collection/components/collapse/collapse.js +9 -9
- package/dist/collection/components/cookiebar/cookiebar-cookie/cookiebar-cookie.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar-group/cookiebar-group.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar-group/cookiebar-group.js +2 -2
- package/dist/collection/components/cookiebar/cookiebar-header/cookiebar-header.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar-link/cookiebar-link.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar-link/cookiebar-link.js +1 -1
- package/dist/collection/components/cookiebar/cookiebar-note/cookiebar-note.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar-note-group/cookiebar-note-group.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar-note-group/cookiebar-note-group.js +1 -1
- package/dist/collection/components/cookiebar/cookiebar.css +1 -1
- package/dist/collection/components/cookiebar/cookiebar.js +3 -3
- package/dist/collection/components/datetime-picker/date-picker/date-picker.css +1 -1
- package/dist/collection/components/datetime-picker/date-picker/date-picker.js +4 -4
- package/dist/collection/components/datetime-picker/datetime-input/datetime-input.css +1 -1
- package/dist/collection/components/datetime-picker/datetime-input/datetime-input.js +3 -3
- package/dist/collection/components/datetime-picker/datetime-picker.css +1 -1
- package/dist/collection/components/datetime-picker/datetime-picker.utils.js +6 -6
- package/dist/collection/components/datetime-picker/time-picker/time-picker.css +1 -1
- package/dist/collection/components/datetime-picker/time-picker/time-picker.js +3 -3
- package/dist/collection/components/divider/divider.css +1 -1
- package/dist/collection/components/dropdown/dropdown.css +1 -1
- package/dist/collection/components/dropdown/dropdown.js +6 -8
- package/dist/collection/components/footer/footer-category/footer-category.css +1 -1
- package/dist/collection/components/footer/footer-item/footer-item.css +1 -1
- package/dist/collection/components/footer/footer-legal/footer-legal.css +1 -1
- package/dist/collection/components/footer/footer-logo/footer-logo.css +1 -1
- package/dist/collection/components/footer/footer-social/footer-social.css +1 -1
- package/dist/collection/components/footer/footer-social/footer-social.js +2 -2
- package/dist/collection/components/footer/footer.css +1 -1
- package/dist/collection/components/header/header-function/header-function.css +1 -1
- package/dist/collection/components/header/header-link/header-link.css +1 -1
- package/dist/collection/components/header/header-list/header-list.css +1 -1
- package/dist/collection/components/header/header-list/header-list.js +2 -2
- package/dist/collection/components/header/header-logo/header-logo.css +1 -1
- package/dist/collection/components/header/header.css +1 -1
- package/dist/collection/components/header/header.js +4 -4
- package/dist/collection/components/icon/default-icons-cache.js +159 -146
- package/dist/collection/components/icon/icon.css +1 -1
- package/dist/collection/components/icon/icon.js +17 -13
- package/dist/collection/components/icon/icon.utils.js +1 -1
- package/dist/collection/components/input/input.css +1 -1
- package/dist/collection/components/input/input.js +120 -2
- package/dist/collection/components/item/item.css +1 -1
- package/dist/collection/components/link/link.css +1 -1
- package/dist/collection/components/list/list.css +1 -1
- package/dist/collection/components/loading/loading.css +1 -1
- package/dist/collection/components/magic-button/magic-button.css +1 -1
- package/dist/collection/components/magic-button/magic-button.js +11 -12
- package/dist/collection/components/menu/menu-group/menu-group.css +1 -1
- package/dist/collection/components/menu/menu-header/menu-header.css +1 -1
- package/dist/collection/components/menu/menu-header/menu-header.js +1 -1
- package/dist/collection/components/menu/menu-info/menu-info.css +1 -1
- package/dist/collection/components/menu/menu-item/menu-item.css +1 -1
- package/dist/collection/components/menu/menu-item/menu-item.js +1 -1
- package/dist/collection/components/menu/menu-link/menu-link.css +1 -1
- package/dist/collection/components/menu/menu-link/menu-link.js +1 -1
- package/dist/collection/components/menu/menu-list/menu-list.css +1 -1
- package/dist/collection/components/menu/menu-logo/menu-logo.css +1 -1
- package/dist/collection/components/menu/menu-social/menu-social.css +1 -1
- package/dist/collection/components/menu/menu-social/menu-social.js +1 -1
- package/dist/collection/components/menu/menu.css +1 -1
- package/dist/collection/components/menu/menu.js +3 -3
- package/dist/collection/components/message/message.css +1 -1
- package/dist/collection/components/modal/modal.css +1 -1
- package/dist/collection/components/notification/notification-body/notification-body.css +1 -1
- package/dist/collection/components/notification/notification-header/notification-header.css +1 -1
- package/dist/collection/components/notification/notification-item/notification-item.css +1 -1
- package/dist/collection/components/notification/notification.css +1 -1
- package/dist/collection/components/pagination/pagination.css +1 -1
- package/dist/collection/components/pagination/pagination.js +4 -4
- package/dist/collection/components/radio/radio.css +1 -1
- package/dist/collection/components/radio-group/radio-group.css +1 -1
- package/dist/collection/components/scrim/scrim.css +1 -1
- package/dist/collection/components/select/select-input/select-input.css +1 -1
- package/dist/collection/components/select/select-input/select-input.js +6 -84
- package/dist/collection/components/select/select-list/select-list.css +1 -1
- package/dist/collection/components/select/select-option/select-option.css +1 -1
- package/dist/collection/components/select/select-option/select-option.js +8 -7
- package/dist/collection/components/select/select.css +1 -1
- package/dist/collection/components/select/select.js +22 -6
- package/dist/collection/components/sign-in/sign-in.css +1 -1
- package/dist/collection/components/sign-in/sign-in.js +1 -1
- package/dist/collection/components/skip-link/skip-link-item/skip-link-item.css +1 -1
- package/dist/collection/components/skip-link/skip-link.css +1 -1
- package/dist/collection/components/slider/slider.css +1 -1
- package/dist/collection/components/slider/slider.js +4 -4
- package/dist/collection/components/step/step-item/step-item.css +1 -1
- package/dist/collection/components/step/step.css +1 -1
- package/dist/collection/components/switch/switch.css +1 -1
- package/dist/collection/components/tab/tab-item/tab-item.css +1 -1
- package/dist/collection/components/tab/tab-item/tab-item.js +2 -2
- package/dist/collection/components/tab/tab.css +1 -1
- package/dist/collection/components/tab/tab.js +4 -4
- package/dist/collection/components/table/table-action/table-action.css +1 -0
- package/dist/collection/components/table/table-action/table-action.js +349 -0
- package/dist/collection/components/table/table-bar/table-bar.css +1 -0
- package/dist/collection/components/table/table-bar/table-bar.js +652 -0
- package/dist/collection/components/table/table-body/table-body.css +1 -1
- package/dist/collection/components/table/table-body/table-body.js +12 -17
- package/dist/collection/components/table/table-cell/table-cell.css +1 -1
- package/dist/collection/components/table/table-cell/table-cell.js +556 -83
- package/dist/collection/components/table/table-footer/table-footer.css +1 -0
- package/dist/collection/components/table/table-footer/table-footer.js +233 -0
- package/dist/collection/components/table/table-header/table-header.css +1 -1
- package/dist/collection/components/table/table-header/table-header.js +11 -17
- package/dist/collection/components/table/table-header-cell/table-header-cell.css +1 -1
- package/dist/collection/components/table/table-header-cell/table-header-cell.js +287 -86
- package/dist/collection/components/table/table-row/table-row.css +1 -1
- package/dist/collection/components/table/table-row/table-row.js +312 -57
- package/dist/collection/components/table/table.actions-tooltip.js +33 -0
- package/dist/collection/components/table/{table-constants.js → table.constants.js} +54 -77
- package/dist/collection/components/table/table.css +1 -1
- package/dist/collection/components/table/table.data.js +461 -0
- package/dist/collection/components/table/table.expansion.elements.js +70 -0
- package/dist/collection/components/table/table.expansion.js +179 -0
- package/dist/collection/components/table/table.grouping.js +97 -0
- package/dist/collection/components/table/table.header-height.js +47 -0
- package/dist/collection/components/table/table.js +2499 -618
- package/dist/collection/components/table/table.keyboard.js +340 -0
- package/dist/collection/components/table/table.scroll-shadows.js +36 -0
- package/dist/collection/components/table/table.selection.elements.js +63 -0
- package/dist/collection/components/table/table.selection.js +239 -0
- package/dist/collection/components/table/table.tokens.js +28 -0
- package/dist/collection/components/table/table.types.js +1 -0
- package/dist/collection/components/table/table.utils.js +75 -0
- package/dist/collection/components/table/table.virtual-list.js +342 -0
- package/dist/collection/components/tag/tag.css +1 -1
- package/dist/collection/components/tag/tag.js +2 -2
- package/dist/collection/components/textarea/textarea.css +1 -1
- package/dist/collection/components/textarea/textarea.js +1 -1
- package/dist/collection/components/tooltip/tooltip.css +1 -1
- package/dist/collection/components/tooltip/tooltip.js +3 -27
- package/dist/collection/components/upload/upload.css +1 -1
- package/dist/collection/components/upload/upload.js +2 -2
- package/dist/collection/components/wizard/wizard-panel/wizard-panel.css +1 -1
- package/dist/collection/components/wizard/wizard-panel/wizard-panel.js +1 -1
- package/dist/collection/components/wizard/wizard.css +1 -1
- package/dist/collection/components/wizard/wizard.js +1 -1
- package/dist/collection/pages/scripts/code-editor.js +28 -3
- package/dist/collection/pages/scripts/pageLoader.js +286 -20
- package/dist/collection/pages/scripts/pageloader-preview.js +3 -1
- package/dist/components/br-avatar.js +1 -1
- package/dist/components/br-breadcrumb-item.js +1 -1
- package/dist/components/br-breadcrumb.js +1 -1
- package/dist/components/br-button.js +1 -1
- package/dist/components/br-card.js +1 -1
- package/dist/components/br-carousel-page.js +1 -1
- package/dist/components/br-carousel.js +1 -1
- package/dist/components/br-checkbox-group.js +1 -1
- package/dist/components/br-checkbox.js +1 -1
- package/dist/components/br-checkgroup.js +1 -1
- package/dist/components/br-collapse.js +1 -1
- package/dist/components/br-cookiebar-cookie.js +1 -1
- package/dist/components/br-cookiebar-group.js +1 -1
- package/dist/components/br-cookiebar-header.js +1 -1
- package/dist/components/br-cookiebar-link.js +1 -1
- package/dist/components/br-cookiebar-note-group.js +1 -1
- package/dist/components/br-cookiebar-note.js +1 -1
- package/dist/components/br-cookiebar.js +1 -1
- package/dist/components/br-crumb.js +1 -1
- package/dist/components/br-date-picker.js +1 -1
- package/dist/components/br-datetime-input.js +1 -1
- package/dist/components/br-datetime-picker.js +1 -1
- package/dist/components/br-divider.js +1 -1
- package/dist/components/br-dropdown.js +1 -1
- package/dist/components/br-footer-category.js +1 -1
- package/dist/components/br-footer-item.js +1 -1
- package/dist/components/br-footer-legal.js +1 -1
- package/dist/components/br-footer-logo.js +1 -1
- package/dist/components/br-footer-social.js +1 -1
- package/dist/components/br-footer.js +1 -1
- package/dist/components/br-header-function.js +1 -1
- package/dist/components/br-header-link.js +1 -1
- package/dist/components/br-header-list.js +1 -1
- package/dist/components/br-header-logo.js +1 -1
- package/dist/components/br-header.js +1 -1
- package/dist/components/br-icon.js +1 -1
- package/dist/components/br-input.js +1 -1
- package/dist/components/br-item.js +1 -1
- package/dist/components/br-link.js +1 -1
- package/dist/components/br-list.js +1 -1
- package/dist/components/br-loading.js +1 -1
- package/dist/components/br-magic-button.js +1 -1
- package/dist/components/br-menu-group.js +1 -1
- package/dist/components/br-menu-header.js +1 -1
- package/dist/components/br-menu-info.js +1 -1
- package/dist/components/br-menu-item.js +1 -1
- package/dist/components/br-menu-link.js +1 -1
- package/dist/components/br-menu-list.js +1 -1
- package/dist/components/br-menu-logo.js +1 -1
- package/dist/components/br-menu-social.js +1 -1
- package/dist/components/br-menu.js +1 -1
- package/dist/components/br-message.js +1 -1
- package/dist/components/br-modal.js +1 -1
- package/dist/components/br-notification-body.js +1 -1
- package/dist/components/br-notification-header.js +1 -1
- package/dist/components/br-notification-item.js +1 -1
- package/dist/components/br-notification.js +1 -1
- package/dist/components/br-pagination.js +1 -1
- package/dist/components/br-radio-group.js +1 -1
- package/dist/components/br-radio.js +1 -1
- package/dist/components/br-scrim.js +1 -1
- package/dist/components/br-select-input.js +1 -1
- package/dist/components/br-select-list.js +1 -1
- package/dist/components/br-select-option.js +1 -1
- package/dist/components/br-select.js +1 -1
- package/dist/components/br-sign-in.js +1 -1
- package/dist/components/br-skip-link-item.js +1 -1
- package/dist/components/br-skip-link.js +1 -1
- package/dist/components/br-skiplink-item.js +1 -1
- package/dist/components/br-slider.js +1 -1
- package/dist/components/br-step-item.js +1 -1
- package/dist/components/br-step.js +1 -1
- package/dist/components/br-switch.js +1 -1
- package/dist/components/br-tab-item.js +1 -1
- package/dist/components/br-tab.js +1 -1
- package/dist/components/br-table-action.d.ts +11 -0
- package/dist/components/br-table-action.js +5 -0
- package/dist/components/br-table-bar.d.ts +11 -0
- package/dist/components/br-table-bar.js +5 -0
- package/dist/components/br-table-body.js +1 -1
- package/dist/components/br-table-cell.js +1 -1
- package/dist/components/br-table-footer.d.ts +11 -0
- package/dist/components/br-table-footer.js +5 -0
- package/dist/components/br-table-header-cell.js +1 -1
- package/dist/components/br-table-header.js +1 -1
- package/dist/components/br-table-row.js +1 -1
- package/dist/components/br-table.js +1 -1
- package/dist/components/br-tag.js +1 -1
- package/dist/components/br-textarea.js +1 -1
- package/dist/components/br-time-picker.js +1 -1
- package/dist/components/br-tooltip.js +1 -1
- package/dist/components/br-upload.js +1 -1
- package/dist/components/br-wizard-panel.js +1 -1
- package/dist/components/br-wizard.js +1 -1
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +1 -1
- package/dist/components/p-082jxuTj.js +5 -0
- package/dist/components/p-381n6AwK.js +5 -0
- package/dist/components/{p-CyXVsiz9.js → p-B5_zbRAr.js} +1 -1
- package/dist/components/p-BE1gDPwC.js +5 -0
- package/dist/components/p-BV-c2pxt.js +5 -0
- package/dist/components/p-BfFbYAuJ.js +5 -0
- package/dist/components/{p-DcMjwTqu.js → p-Bi2E_w9Q.js} +1 -1
- package/dist/components/p-Bk8YcMql.js +5 -0
- package/dist/components/p-C3ISxUGw.js +5 -0
- package/dist/components/p-C3J0TVQO.js +5 -0
- package/dist/components/p-C6m13lCc.js +5 -0
- package/dist/components/{p-DBmwzG9E.js → p-CCWJ-H33.js} +1 -1
- package/dist/components/p-CJuHirYK.js +5 -0
- package/dist/components/{p-SWQlgYWR.js → p-CKS7ggLM.js} +1 -1
- package/dist/components/p-COSFBwu9.js +5 -0
- package/dist/components/p-CWPrXYam.js +5 -0
- package/dist/components/p-Ca89D_0s.js +5 -0
- package/dist/components/p-CbN58CFi.js +5 -0
- package/dist/components/p-CjjxTkKb.js +5 -0
- package/dist/components/p-Ck9t4WSb.js +5 -0
- package/dist/components/p-CvfVwD6_.js +5 -0
- package/dist/components/p-D-1sfjhG.js +5 -0
- package/dist/components/p-D-p4vLlP.js +5 -0
- package/dist/components/p-D6DArHGH.js +5 -0
- package/dist/components/p-DD3BItoS.js +5 -0
- package/dist/components/{p-448Z5r2f.js → p-DEIKwFIf.js} +1 -1
- package/dist/components/p-DHHAIESt.js +5 -0
- package/dist/components/{p-Jk_KQE5V.js → p-DMj5iO7_.js} +1 -1
- package/dist/components/p-DUI-S07G.js +5 -0
- package/dist/components/p-D_K9JH6J.js +5 -0
- package/dist/components/p-DiQp2Lap.js +5 -0
- package/dist/components/{p-DJKZ8ktB.js → p-Dvbqhybt.js} +1 -1
- package/dist/components/p-Dy7MSvt-.js +5 -0
- package/dist/components/p-DywTXNHQ.js +5 -0
- package/dist/components/p-Ft_P7Roz.js +5 -0
- package/dist/components/p-KuiFoKDl.js +5 -0
- package/dist/components/p-MiiczSWA.js +5 -0
- package/dist/components/p-Um3K2SHu.js +5 -0
- package/dist/components/p-YxddSP6q.js +5 -0
- package/dist/components/p-Zk91ebVT.js +5 -0
- package/dist/components/p-jv2oG0vH.js +5 -0
- package/dist/components/p-nrG_Gd0c.js +5 -0
- package/dist/components/p-syLEZrcg.js +5 -0
- package/dist/components/{p-jvKQA6x7.js → p-ydfWTgrA.js} +1 -1
- package/dist/esm/br-avatar.entry.js +3 -3
- package/dist/esm/br-breadcrumb-item.entry.js +1 -1
- package/dist/esm/br-breadcrumb.entry.js +12 -12
- package/dist/esm/br-button_2.entry.js +6 -6
- package/dist/esm/br-card.entry.js +2 -2
- package/dist/esm/br-carousel-page.entry.js +2 -2
- package/dist/esm/br-carousel.entry.js +6 -6
- package/dist/esm/br-checkbox-group.entry.js +3 -3
- package/dist/esm/br-checkbox.entry.js +3 -3
- package/dist/esm/br-checkgroup.entry.js +1 -1
- package/dist/esm/br-collapse_2.entry.js +9 -9
- package/dist/esm/br-cookiebar-cookie.entry.js +2 -2
- package/dist/esm/br-cookiebar-group.entry.js +4 -4
- package/dist/esm/br-cookiebar-header.entry.js +2 -2
- package/dist/esm/br-cookiebar-link.entry.js +4 -4
- package/dist/esm/br-cookiebar-note-group.entry.js +3 -3
- package/dist/esm/br-cookiebar-note.entry.js +2 -2
- package/dist/esm/br-cookiebar.entry.js +6 -6
- package/dist/esm/br-crumb.entry.js +1 -1
- package/dist/esm/br-date-picker_3.entry.js +14 -14
- package/dist/esm/br-datetime-picker.entry.js +5 -22
- package/dist/esm/br-divider.entry.js +3 -3
- package/dist/esm/br-dropdown.entry.js +675 -0
- package/dist/esm/br-footer-category.entry.js +2 -2
- package/dist/esm/br-footer-item.entry.js +3 -3
- package/dist/esm/br-footer-legal.entry.js +2 -2
- package/dist/esm/br-footer-logo.entry.js +3 -3
- package/dist/esm/br-footer-social.entry.js +4 -4
- package/dist/esm/br-footer.entry.js +3 -3
- package/dist/esm/br-header-function.entry.js +3 -3
- package/dist/esm/br-header-link.entry.js +3 -3
- package/dist/esm/br-header-list.entry.js +4 -4
- package/dist/esm/br-header-logo.entry.js +3 -3
- package/dist/esm/br-header.entry.js +7 -7
- package/dist/esm/br-icon.entry.js +173 -159
- package/dist/esm/br-input_2.entry.js +1424 -0
- package/dist/esm/br-item.entry.js +3 -3
- package/dist/esm/br-link.entry.js +3 -3
- package/dist/esm/br-magic-button.entry.js +12 -13
- package/dist/esm/br-menu-group.entry.js +2 -2
- package/dist/esm/br-menu-header.entry.js +3 -3
- package/dist/esm/br-menu-info.entry.js +2 -2
- package/dist/esm/br-menu-item.entry.js +4 -4
- package/dist/esm/br-menu-link.entry.js +4 -4
- package/dist/esm/br-menu-list.entry.js +2 -2
- package/dist/esm/br-menu-logo.entry.js +2 -2
- package/dist/esm/br-menu-social.entry.js +3 -3
- package/dist/esm/br-menu.entry.js +6 -6
- package/dist/esm/br-modal.entry.js +3 -3
- package/dist/esm/br-notification-body.entry.js +2 -2
- package/dist/esm/br-notification-header.entry.js +2 -2
- package/dist/esm/br-notification-item.entry.js +3 -3
- package/dist/esm/br-notification.entry.js +3 -3
- package/dist/esm/{br-dropdown_2.entry.js → br-pagination_2.entry.js} +813 -558
- package/dist/esm/br-radio-group.entry.js +3 -3
- package/dist/esm/br-radio.entry.js +3 -3
- package/dist/esm/br-scrim.entry.js +3 -3
- package/dist/esm/br-select-input_3.entry.js +17 -94
- package/dist/esm/br-sign-in.entry.js +4 -4
- package/dist/esm/br-skip-link-item.entry.js +1 -1
- package/dist/esm/br-skip-link.entry.js +3 -3
- package/dist/esm/br-skiplink-item.entry.js +3 -3
- package/dist/esm/br-slider.entry.js +4 -4
- package/dist/esm/br-step_2.entry.js +4 -4
- package/dist/esm/br-switch.entry.js +3 -3
- package/dist/esm/br-tab-item.entry.js +4 -4
- package/dist/esm/br-tab.entry.js +8 -8
- package/dist/esm/br-table-action_6.entry.js +1493 -0
- package/dist/esm/br-table-body.entry.js +4 -16
- package/dist/esm/br-table-header.entry.js +4 -16
- package/dist/esm/br-table.entry.js +2591 -408
- package/dist/esm/br-tag.entry.js +5 -5
- package/dist/esm/br-textarea.entry.js +4 -4
- package/dist/esm/br-tooltip.entry.js +6 -30
- package/dist/esm/br-upload.entry.js +5 -5
- package/dist/esm/br-wizard-panel.entry.js +3 -3
- package/dist/esm/br-wizard.entry.js +4 -4
- package/dist/esm/helpers-BNW9pAhl.js +26 -0
- package/dist/esm/{icon.utils-zlORkiHQ.js → icon.utils-CXDYKUBz.js} +1 -1
- package/dist/esm/{index-ConyRdJe.js → index-CwL52661.js} +34 -35
- package/dist/esm/loader.js +3 -3
- package/dist/esm/{props-D07GjR4_.js → props-BbxNgEcJ.js} +1 -1
- package/dist/esm/table.utils-CtVdlcgI.js +706 -0
- package/dist/esm/webcomponents.js +3 -3
- package/dist/hydrate/index.js +5269 -1302
- package/dist/hydrate/index.mjs +5269 -1302
- package/dist/types/components/collapse/collapse.d.ts +2 -2
- package/dist/types/components/footer/footer-social/footer-social.d.ts +2 -3
- package/dist/types/components/icon/icon.d.ts +6 -6
- package/dist/types/components/icon/icon.utils.d.ts +1 -1
- package/dist/types/components/input/input.d.ts +7 -1
- package/dist/types/components/input/input.types.d.ts +18 -0
- package/dist/types/components/magic-button/magic-button.d.ts +7 -8
- package/dist/types/components/menu/menu-social/menu-social.d.ts +2 -3
- package/dist/types/components/select/select-input/select-input.d.ts +1 -4
- package/dist/types/components/select/select-option/select-option.d.ts +3 -1
- package/dist/types/components/slider/slider.d.ts +4 -4
- package/dist/types/components/tab/tab-item/tab-item.d.ts +2 -2
- package/dist/types/components/tab/tab.d.ts +1 -1
- package/dist/types/components/table/table-action/table-action.d.ts +107 -0
- package/dist/types/components/table/table-bar/table-bar.d.ts +193 -0
- package/dist/types/components/table/table-body/table-body.d.ts +11 -16
- package/dist/types/components/table/table-cell/table-cell.d.ts +178 -38
- package/dist/types/components/table/table-footer/table-footer.d.ts +40 -0
- package/dist/types/components/table/table-footer/table-footer.types.d.ts +12 -0
- package/dist/types/components/table/table-header/table-header.d.ts +10 -16
- package/dist/types/components/table/table-header-cell/table-header-cell.d.ts +102 -53
- package/dist/types/components/table/table-row/table-row.d.ts +88 -29
- package/dist/types/components/table/table.actions-tooltip.d.ts +11 -0
- package/dist/types/components/table/{table-constants.d.ts → table.constants.d.ts} +50 -77
- package/dist/types/components/table/table.d.ts +601 -222
- package/dist/types/components/table/table.data.d.ts +78 -0
- package/dist/types/components/table/table.expansion.d.ts +65 -0
- package/dist/types/components/table/table.expansion.elements.d.ts +30 -0
- package/dist/types/components/table/table.grouping.d.ts +25 -0
- package/dist/types/components/table/table.header-height.d.ts +17 -0
- package/dist/types/components/table/table.keyboard.d.ts +53 -0
- package/dist/types/components/table/table.scroll-shadows.d.ts +11 -0
- package/dist/types/components/table/table.selection.d.ts +84 -0
- package/dist/types/components/table/table.selection.elements.d.ts +42 -0
- package/dist/types/components/table/table.tokens.d.ts +24 -0
- package/dist/types/components/table/table.types.d.ts +199 -0
- package/dist/types/components/table/table.utils.d.ts +52 -0
- package/dist/types/components/table/table.virtual-list.d.ts +96 -0
- package/dist/types/components.d.ts +1401 -279
- package/dist/webcomponents/{p-85c8d060.entry.js → p-07e80bf8.entry.js} +1 -1
- package/dist/webcomponents/p-10d81622.entry.js +5 -0
- package/dist/webcomponents/{p-a9f16a65.entry.js → p-12d5f533.entry.js} +1 -1
- package/dist/webcomponents/p-15699e8a.entry.js +5 -0
- package/dist/webcomponents/{p-bbcde1ea.entry.js → p-15e2f5cc.entry.js} +1 -1
- package/dist/webcomponents/{p-5528b466.entry.js → p-16d27d5c.entry.js} +1 -1
- package/dist/webcomponents/p-18d3fab8.entry.js +5 -0
- package/dist/webcomponents/p-23c916d9.entry.js +5 -0
- package/dist/webcomponents/p-2aee69fd.entry.js +5 -0
- package/dist/webcomponents/p-2d3db296.entry.js +5 -0
- package/dist/webcomponents/p-2ed6afdd.entry.js +5 -0
- package/dist/webcomponents/{p-bbf47e78.entry.js → p-30c865e6.entry.js} +1 -1
- package/dist/webcomponents/p-32afb78c.entry.js +5 -0
- package/dist/webcomponents/p-33d24cbd.entry.js +5 -0
- package/dist/webcomponents/p-35d63edd.entry.js +5 -0
- package/dist/webcomponents/p-3b1ff55e.entry.js +5 -0
- package/dist/webcomponents/p-3c7246cf.entry.js +5 -0
- package/dist/webcomponents/{p-11d4edc5.entry.js → p-407e7b69.entry.js} +1 -1
- package/dist/webcomponents/{p-53550e8c.entry.js → p-41b12e3c.entry.js} +1 -1
- package/dist/webcomponents/p-47adc17f.entry.js +5 -0
- package/dist/webcomponents/{p-21e10074.entry.js → p-48fc8e56.entry.js} +1 -1
- package/dist/webcomponents/p-4a44c8b8.entry.js +5 -0
- package/dist/webcomponents/{p-6d58ab4f.entry.js → p-4b0f3701.entry.js} +1 -1
- package/dist/webcomponents/{p-84dfbfdd.entry.js → p-4b66200c.entry.js} +1 -1
- package/dist/webcomponents/{p-324afbce.entry.js → p-4c0a1c05.entry.js} +1 -1
- package/dist/webcomponents/p-4c72d706.entry.js +5 -0
- package/dist/webcomponents/p-505173e0.entry.js +5 -0
- package/dist/webcomponents/p-50caea68.entry.js +5 -0
- package/dist/webcomponents/p-5419fd2c.entry.js +5 -0
- package/dist/webcomponents/{p-ed3fa8ec.entry.js → p-5693e0e7.entry.js} +1 -1
- package/dist/webcomponents/p-58247764.entry.js +5 -0
- package/dist/webcomponents/{p-3926cc91.entry.js → p-5d0f4851.entry.js} +1 -1
- package/dist/webcomponents/{p-39a7826d.entry.js → p-60c949c8.entry.js} +1 -1
- package/dist/webcomponents/p-61b84035.entry.js +5 -0
- package/dist/webcomponents/{p-e121429a.entry.js → p-62a74e0a.entry.js} +1 -1
- package/dist/webcomponents/p-6450913e.entry.js +5 -0
- package/dist/webcomponents/p-66c8b8d9.entry.js +5 -0
- package/dist/webcomponents/{p-c6f2f17b.entry.js → p-67281ef1.entry.js} +1 -1
- package/dist/webcomponents/{p-087ed5e7.entry.js → p-6e128c7a.entry.js} +1 -1
- package/dist/webcomponents/p-725e92ab.entry.js +5 -0
- package/dist/webcomponents/{p-19b4b1b7.entry.js → p-74726f20.entry.js} +1 -1
- package/dist/webcomponents/{p-975ea5c7.entry.js → p-75bd655b.entry.js} +1 -1
- package/dist/webcomponents/p-7bf78e48.entry.js +5 -0
- package/dist/webcomponents/p-7cc28ecf.entry.js +5 -0
- package/dist/webcomponents/{p-913d6f28.entry.js → p-7ec01a99.entry.js} +1 -1
- package/dist/webcomponents/{p-d205f3fd.entry.js → p-7f17dbca.entry.js} +1 -1
- package/dist/webcomponents/{p-152482f9.entry.js → p-8120f3ce.entry.js} +1 -1
- package/dist/webcomponents/p-8ded7870.entry.js +5 -0
- package/dist/webcomponents/p-9ab989d1.entry.js +5 -0
- package/dist/webcomponents/p-9be642ff.entry.js +5 -0
- package/dist/webcomponents/p-9d41995a.entry.js +5 -0
- package/dist/webcomponents/{p-EbtQZm5s.js → p-CjVabz-h.js} +1 -1
- package/dist/webcomponents/{p-ConyRdJe.js → p-CwL52661.js} +2 -2
- package/dist/webcomponents/p-Zk91ebVT.js +5 -0
- package/dist/webcomponents/p-_BMaB_68.js +5 -0
- package/dist/webcomponents/p-a150b61d.entry.js +5 -0
- package/dist/webcomponents/{p-55e0822d.entry.js → p-a264acf6.entry.js} +1 -1
- package/dist/webcomponents/p-a5616523.entry.js +5 -0
- package/dist/webcomponents/{p-eb5806c7.entry.js → p-ae3dfb9c.entry.js} +1 -1
- package/dist/webcomponents/p-b1aeb805.entry.js +5 -0
- package/dist/webcomponents/p-b8eea3ef.entry.js +5 -0
- package/dist/webcomponents/p-c6952f8d.entry.js +5 -0
- package/dist/webcomponents/p-c743e5c5.entry.js +5 -0
- package/dist/webcomponents/p-d0c659c3.entry.js +5 -0
- package/dist/webcomponents/p-d3dec923.entry.js +5 -0
- package/dist/webcomponents/{p-12dd22af.entry.js → p-d5405bbe.entry.js} +1 -1
- package/dist/webcomponents/{p-c29268b5.entry.js → p-d6d3a552.entry.js} +1 -1
- package/dist/webcomponents/p-dab66328.entry.js +5 -0
- package/dist/webcomponents/{p-cb1e08b1.entry.js → p-db02533d.entry.js} +1 -1
- package/dist/webcomponents/p-dda22999.entry.js +5 -0
- package/dist/webcomponents/p-e2a46f44.entry.js +5 -0
- package/dist/webcomponents/{p-e0ccf189.entry.js → p-e3680ff8.entry.js} +1 -1
- package/dist/webcomponents/p-e5b9652d.entry.js +5 -0
- package/dist/webcomponents/p-e7f02302.entry.js +5 -0
- package/dist/webcomponents/p-f0720e23.entry.js +5 -0
- package/dist/webcomponents/p-f244009d.entry.js +5 -0
- package/dist/webcomponents/p-f32c40ee.entry.js +5 -0
- package/dist/webcomponents/{p-e4b968b5.entry.js → p-f697abbd.entry.js} +1 -1
- package/dist/webcomponents/p-f7ed35ef.entry.js +5 -0
- package/dist/webcomponents/p-f8576e0a.entry.js +5 -0
- package/dist/webcomponents/p-fcc62731.entry.js +5 -0
- package/dist/webcomponents/webcomponents.esm.js +1 -1
- package/package.json +1 -1
- package/dist/cjs/br-input.cjs.entry.js +0 -763
- package/dist/cjs/br-loading.cjs.entry.js +0 -567
- package/dist/cjs/br-pagination.cjs.entry.js +0 -916
- package/dist/cjs/br-table-cell.cjs.entry.js +0 -201
- package/dist/cjs/br-table-header-cell.cjs.entry.js +0 -189
- package/dist/cjs/br-table-row.cjs.entry.js +0 -95
- package/dist/cjs/table-constants-BOPSay0B.js +0 -183
- package/dist/collection/components/table/table-tokens.js +0 -50
- package/dist/collection/components/table/table-utils.js +0 -44
- package/dist/components/p-AhfgJCUp.js +0 -5
- package/dist/components/p-AoNL6BaW.js +0 -5
- package/dist/components/p-B468MCYC.js +0 -5
- package/dist/components/p-B985Ov_x.js +0 -5
- package/dist/components/p-BOWQIHQA.js +0 -5
- package/dist/components/p-BPQrgCRr.js +0 -5
- package/dist/components/p-BwQT0fOJ.js +0 -5
- package/dist/components/p-CAgbUwsx.js +0 -5
- package/dist/components/p-CFXey8i8.js +0 -5
- package/dist/components/p-CW8xwk6J.js +0 -5
- package/dist/components/p-CXMwM9m4.js +0 -5
- package/dist/components/p-CYZVdKeO.js +0 -5
- package/dist/components/p-CeWbZN7V.js +0 -5
- package/dist/components/p-DDe0tQEO.js +0 -5
- package/dist/components/p-DRsZ9GNg.js +0 -5
- package/dist/components/p-DU54cqCf.js +0 -5
- package/dist/components/p-DVJlmlEX.js +0 -5
- package/dist/components/p-Dd1qCWAK.js +0 -5
- package/dist/components/p-DiLI514I.js +0 -5
- package/dist/components/p-DoWy_P8b.js +0 -5
- package/dist/components/p-HbhTnepI.js +0 -5
- package/dist/components/p-Or3FLzbz.js +0 -5
- package/dist/components/p-Zb9nyfTY.js +0 -5
- package/dist/components/p-pQb-3jFY.js +0 -5
- package/dist/components/p-qX6sHxOk.js +0 -5
- package/dist/esm/br-input.entry.js +0 -761
- package/dist/esm/br-loading.entry.js +0 -565
- package/dist/esm/br-pagination.entry.js +0 -914
- package/dist/esm/br-table-cell.entry.js +0 -199
- package/dist/esm/br-table-header-cell.entry.js +0 -187
- package/dist/esm/br-table-row.entry.js +0 -93
- package/dist/esm/table-constants-CXMwM9m4.js +0 -170
- package/dist/types/components/table/table-tokens.d.ts +0 -46
- package/dist/types/components/table/table-types.d.ts +0 -107
- package/dist/types/components/table/table-utils.d.ts +0 -47
- package/dist/webcomponents/p-031a2256.entry.js +0 -5
- package/dist/webcomponents/p-0602e5b1.entry.js +0 -5
- package/dist/webcomponents/p-079d5f69.entry.js +0 -5
- package/dist/webcomponents/p-0d5a9ebf.entry.js +0 -5
- package/dist/webcomponents/p-105b4d06.entry.js +0 -5
- package/dist/webcomponents/p-14aedf0d.entry.js +0 -5
- package/dist/webcomponents/p-1cd1126e.entry.js +0 -5
- package/dist/webcomponents/p-2271ea84.entry.js +0 -5
- package/dist/webcomponents/p-271b1ede.entry.js +0 -5
- package/dist/webcomponents/p-28f732fc.entry.js +0 -5
- package/dist/webcomponents/p-2971d38a.entry.js +0 -5
- package/dist/webcomponents/p-2ac48875.entry.js +0 -5
- package/dist/webcomponents/p-2b1a919c.entry.js +0 -5
- package/dist/webcomponents/p-2da57966.entry.js +0 -5
- package/dist/webcomponents/p-2e81b0b3.entry.js +0 -5
- package/dist/webcomponents/p-2eececed.entry.js +0 -5
- package/dist/webcomponents/p-2f904c4a.entry.js +0 -5
- package/dist/webcomponents/p-32414f1c.entry.js +0 -5
- package/dist/webcomponents/p-32ea6342.entry.js +0 -5
- package/dist/webcomponents/p-330ec8ab.entry.js +0 -5
- package/dist/webcomponents/p-374f83b1.entry.js +0 -5
- package/dist/webcomponents/p-3bcc2c58.entry.js +0 -5
- package/dist/webcomponents/p-3c7ce0e4.entry.js +0 -5
- package/dist/webcomponents/p-467842ca.entry.js +0 -5
- package/dist/webcomponents/p-53e71a8a.entry.js +0 -5
- package/dist/webcomponents/p-58bacbe1.entry.js +0 -5
- package/dist/webcomponents/p-5a5ed7d8.entry.js +0 -5
- package/dist/webcomponents/p-621f0fa8.entry.js +0 -5
- package/dist/webcomponents/p-6514a75d.entry.js +0 -5
- package/dist/webcomponents/p-678b43a6.entry.js +0 -5
- package/dist/webcomponents/p-6b6be415.entry.js +0 -5
- package/dist/webcomponents/p-6ff9b26e.entry.js +0 -5
- package/dist/webcomponents/p-992167bc.entry.js +0 -5
- package/dist/webcomponents/p-CXMwM9m4.js +0 -5
- package/dist/webcomponents/p-a21872bf.entry.js +0 -5
- package/dist/webcomponents/p-b8d4ace3.entry.js +0 -5
- package/dist/webcomponents/p-bf35e506.entry.js +0 -5
- package/dist/webcomponents/p-c09af3cd.entry.js +0 -5
- package/dist/webcomponents/p-c3e61c39.entry.js +0 -5
- package/dist/webcomponents/p-c6b2545a.entry.js +0 -5
- package/dist/webcomponents/p-cae39e13.entry.js +0 -5
- package/dist/webcomponents/p-cb690a87.entry.js +0 -5
- package/dist/webcomponents/p-d0be7243.entry.js +0 -5
- package/dist/webcomponents/p-d191c6e3.entry.js +0 -5
- package/dist/webcomponents/p-d3bd2c40.entry.js +0 -5
- package/dist/webcomponents/p-dbeea64e.entry.js +0 -5
- package/dist/webcomponents/p-df475129.entry.js +0 -5
- package/dist/webcomponents/p-e661c024.entry.js +0 -5
- package/dist/webcomponents/p-e6c6f305.entry.js +0 -5
- package/dist/webcomponents/p-e8291be2.entry.js +0 -5
- package/dist/webcomponents/p-f9084f16.entry.js +0 -5
- package/dist/webcomponents/p-fad3aa61.entry.js +0 -5
- /package/dist/collection/components/table/{table-types.js → table-footer/table-footer.types.js} +0 -0
- /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-
|
|
8
|
-
var
|
|
7
|
+
var index = require('./index-BP8UIQro.js');
|
|
8
|
+
var helpers = require('./helpers-DkkDubv1.js');
|
|
9
9
|
var ownership = require('./ownership-UnpufyCx.js');
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
|
|
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
|
-
*
|
|
16
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
1888
|
+
* Recalcula os alinhamentos herdados de todas as células.
|
|
21
1889
|
*/
|
|
22
|
-
|
|
1890
|
+
handleAlignmentChange() {
|
|
1891
|
+
this.updateAllCellAlignments();
|
|
1892
|
+
}
|
|
23
1893
|
/**
|
|
24
|
-
*
|
|
1894
|
+
* Recalcula o overflow herdado de todas as células.
|
|
25
1895
|
*/
|
|
26
|
-
|
|
1896
|
+
handleOverflowChange() {
|
|
1897
|
+
this.updateAllCellOverflow();
|
|
1898
|
+
}
|
|
1899
|
+
handleVirtualExpandedContentHeightChange() {
|
|
1900
|
+
this.applyExpandedContentHeight();
|
|
1901
|
+
this.syncVisibleRange(false);
|
|
1902
|
+
}
|
|
27
1903
|
/**
|
|
28
|
-
*
|
|
1904
|
+
* Sincroniza a estrutura quando a seleção é habilitada ou desabilitada.
|
|
29
1905
|
*/
|
|
30
|
-
|
|
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
|
-
*
|
|
1915
|
+
* Sincroniza a estrutura quando a expansão é habilitada ou desabilitada.
|
|
33
1916
|
*/
|
|
34
|
-
|
|
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
|
-
*
|
|
1961
|
+
* Encaminha mudanças dos checkboxes ao controller de seleção.
|
|
37
1962
|
*/
|
|
38
|
-
|
|
1963
|
+
handleSelectionCheckboxChange(event) {
|
|
1964
|
+
this.selection.handleCheckboxChange(event);
|
|
1965
|
+
}
|
|
39
1966
|
/**
|
|
40
|
-
*
|
|
1967
|
+
* Consome ações internas de expansão e normaliza as demais ações.
|
|
41
1968
|
*/
|
|
42
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
2068
|
+
* Captura a entrada declarativa inicial e a materializa a partir do modelo virtual.
|
|
49
2069
|
*/
|
|
50
|
-
|
|
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
|
-
*
|
|
2078
|
+
* Retorna as linhas atualmente selecionadas.
|
|
2079
|
+
*
|
|
2080
|
+
* @returns Elementos `br-table-row` selecionados no corpo.
|
|
53
2081
|
*/
|
|
54
|
-
|
|
2082
|
+
async getSelectedRows() {
|
|
2083
|
+
return this.selection.getSelectedRows();
|
|
2084
|
+
}
|
|
55
2085
|
/**
|
|
56
|
-
*
|
|
2086
|
+
* Seleciona todas as linhas elegíveis.
|
|
57
2087
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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
|
-
|
|
191
|
-
|
|
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
|
-
|
|
194
|
-
|
|
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
|
-
|
|
197
|
-
|
|
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
|
-
|
|
200
|
-
|
|
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
|
-
|
|
203
|
-
|
|
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
|
-
|
|
206
|
-
|
|
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
|
-
*
|
|
2315
|
+
* Verifica se os nós alterados impactam linhas da tabela.
|
|
210
2316
|
*/
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
*
|
|
2321
|
+
* Detecta a presença de ações atribuídas às barras.
|
|
216
2322
|
*/
|
|
217
|
-
|
|
218
|
-
this.
|
|
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
|
|
2329
|
+
* Atualiza o estado reativo usado pela barra contextual.
|
|
222
2330
|
*/
|
|
223
|
-
|
|
224
|
-
this.
|
|
2331
|
+
updateSelectionCount() {
|
|
2332
|
+
this.selectedRowsCount = this.selection.getSelectedRows().length;
|
|
225
2333
|
}
|
|
226
2334
|
/**
|
|
227
|
-
*
|
|
2335
|
+
* Sincroniza células, checkboxes e estado da seleção.
|
|
228
2336
|
*/
|
|
229
|
-
|
|
230
|
-
this.
|
|
2337
|
+
syncSelectionStructure() {
|
|
2338
|
+
this.selection.sync(this.hasRowSelection);
|
|
2339
|
+
this.updateSelectionCount();
|
|
231
2340
|
}
|
|
232
2341
|
/**
|
|
233
|
-
*
|
|
2342
|
+
* Sincroniza células, ações e estado da expansão.
|
|
234
2343
|
*/
|
|
235
|
-
|
|
236
|
-
this.
|
|
237
|
-
}
|
|
238
|
-
handleTooltipPropsChange() {
|
|
239
|
-
this.validateTooltipProps();
|
|
2344
|
+
syncExpansionStructure() {
|
|
2345
|
+
this.expansion.sync(this.hasRowExpansion);
|
|
240
2346
|
}
|
|
241
|
-
|
|
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
|
-
*
|
|
245
|
-
* Inicializa os tokens visuais após a montagem do componente.
|
|
2354
|
+
* Retorna somente as linhas pertencentes ao corpo da tabela.
|
|
246
2355
|
*/
|
|
247
|
-
|
|
248
|
-
this.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
|
|
261
|
-
this.
|
|
262
|
-
|
|
263
|
-
|
|
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
|
-
|
|
266
|
-
this.el.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.
|
|
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
|
-
/**
|
|
275
|
-
|
|
276
|
-
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
|
2442
|
+
* Marca limites de linha e coluna usados pelos estilos de divisores.
|
|
284
2443
|
*/
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
...
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
|
|
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',
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
|
2516
|
+
* Resolve a largura padrão declarada na tabela.
|
|
352
2517
|
*/
|
|
353
2518
|
resolveTableColumnWidth() {
|
|
354
|
-
return this.resolveWidthToken(this.columnWidth,
|
|
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
|
|
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
|
|
2526
|
+
return this.resolveWidthToken(headerWidth, fallback);
|
|
365
2527
|
}
|
|
366
2528
|
/**
|
|
367
|
-
*
|
|
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
|
|
373
|
-
|
|
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:
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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
|
|
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 =
|
|
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.
|
|
456
|
-
return this.resolveAlignmentToken(this.
|
|
457
|
-
return
|
|
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
|
-
*
|
|
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:
|
|
467
|
-
semanticMap:
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
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.
|
|
2643
|
+
return table_utils.getTableLeafHeaders(Array.from(this.el.querySelectorAll('br-table-header > br-table-row')));
|
|
498
2644
|
}
|
|
499
2645
|
/**
|
|
500
|
-
*
|
|
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.
|
|
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
|
|
2661
|
+
* Aplica contagens e índices ARIA à estrutura atual.
|
|
508
2662
|
*/
|
|
509
2663
|
applyAriaMetadata() {
|
|
510
|
-
|
|
511
|
-
const
|
|
512
|
-
this.
|
|
513
|
-
this.el.
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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 =
|
|
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
|
|
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 =
|
|
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.
|
|
2736
|
+
value = this.overflow ?? null;
|
|
604
2737
|
}
|
|
605
2738
|
if (value === null) {
|
|
606
|
-
value =
|
|
2739
|
+
value = table_utils.TABLE_OVERFLOW.WRAP;
|
|
607
2740
|
}
|
|
608
|
-
return value ===
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
2768
|
+
* Converte a densidade semântica em tokens de espaçamento.
|
|
634
2769
|
*/
|
|
635
2770
|
applyDensity() {
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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.
|
|
649
|
-
fallback:
|
|
650
|
-
semanticMap:
|
|
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
|
-
*
|
|
2797
|
+
* Renderiza barras, slots e o grid principal.
|
|
660
2798
|
*
|
|
661
|
-
* @
|
|
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
|
-
|
|
664
|
-
return {
|
|
665
|
-
|
|
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
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
|
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: '
|
|
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
|
-
"
|
|
717
|
-
"
|
|
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
|
-
"
|
|
720
|
-
"
|
|
2902
|
+
"sortStrategy": [{
|
|
2903
|
+
"handleSortStrategyChange": 0
|
|
721
2904
|
}]
|
|
722
2905
|
}; }
|
|
723
2906
|
};
|