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