@eunomia/elements 1.0.0-beta.4 → 1.0.0-beta.6
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/README.md +1 -1
- package/dist/breakpoints.d.ts +37 -10
- package/dist/breakpoints.js +38 -10
- package/dist/cdn/components/chunks/{chunk-MMLIPCOY.js → chunk-22D3SRFR.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-4MXL6PZC.js → chunk-2Y2EU2CI.js} +28 -28
- package/dist/cdn/components/chunks/chunk-3MTUVMM5.js +1 -0
- package/dist/cdn/components/chunks/chunk-4PI6RDUS.js +1 -0
- package/dist/cdn/components/chunks/chunk-5GKM5DIB.js +1 -0
- package/dist/cdn/components/chunks/chunk-624VJYNA.js +1 -0
- package/dist/cdn/components/chunks/{chunk-5XJLIHAU.js → chunk-7KKWYPHY.js} +4 -2
- package/dist/cdn/components/chunks/chunk-A3X4KD2X.js +1 -0
- package/dist/cdn/components/chunks/chunk-BKZGTCMF.js +1 -0
- package/dist/cdn/components/chunks/{chunk-GW3VP2L7.js → chunk-BO3JOEWM.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-NHFWATVN.js → chunk-BQFJR2UP.js} +5 -5
- package/dist/cdn/components/chunks/chunk-EUWUDCBZ.js +1 -0
- package/dist/cdn/components/chunks/{chunk-P32B7BFD.js → chunk-FF3I7C3C.js} +15 -15
- package/dist/cdn/components/chunks/{chunk-74AOAB4X.js → chunk-FOILAXLL.js} +6 -5
- package/dist/cdn/components/chunks/{chunk-E4IS25H7.js → chunk-G5SBDQQ3.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-LGLQ36QB.js → chunk-GDBPWZN6.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-S2UCEWNG.js → chunk-JYIIWN2P.js} +13 -11
- package/dist/cdn/components/chunks/{chunk-EOWBYZV7.js → chunk-KDN4O5W2.js} +26 -13
- package/dist/cdn/components/chunks/chunk-KSZRQRN4.js +1 -0
- package/dist/cdn/components/chunks/{chunk-PED5ATYN.js → chunk-L2ADCEN7.js} +1 -1
- package/dist/cdn/components/chunks/chunk-LMVW522V.js +1 -0
- package/dist/cdn/components/chunks/{chunk-5XJGYXW7.js → chunk-MOMYII3P.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-SIHZFOTK.js → chunk-MQQ4BGVJ.js} +5 -5
- package/dist/cdn/components/chunks/{chunk-A4EQSU36.js → chunk-O7PHBLH2.js} +1 -1
- package/dist/cdn/components/chunks/chunk-PD62MBOJ.js +1 -0
- package/dist/cdn/components/chunks/{chunk-KBH5PCUO.js → chunk-PE4DAXHQ.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-GSJEJLFA.js → chunk-PMPSJG5V.js} +7 -7
- package/dist/cdn/components/chunks/{chunk-5EVP7YNE.js → chunk-PPCHQG7P.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-EJIX2D4Z.js → chunk-QZ5SHR3I.js} +15 -11
- package/dist/cdn/components/chunks/chunk-RS7TWEMQ.js +1 -0
- package/dist/cdn/components/chunks/chunk-SMTIDNGW.js +1 -0
- package/dist/cdn/components/chunks/{chunk-YGUJJ25C.js → chunk-SZYEBMG6.js} +11 -10
- package/dist/cdn/components/chunks/chunk-UDVB4LAE.js +56 -0
- package/dist/cdn/components/chunks/{chunk-UAGCQF23.js → chunk-UYZR4JXZ.js} +17 -12
- package/dist/cdn/components/chunks/chunk-VG6NAAIV.js +1 -0
- package/dist/cdn/components/chunks/chunk-VJCNHMQZ.js +10 -0
- package/dist/cdn/components/chunks/chunk-VOTRXBDS.js +38 -0
- package/dist/cdn/components/chunks/{chunk-BMQOI7HX.js → chunk-VYFR364B.js} +128 -74
- package/dist/cdn/components/chunks/{chunk-IJ5WFMK4.js → chunk-XDPRWUKN.js} +7 -6
- package/dist/cdn/components/chunks/{chunk-XH6NREVZ.js → chunk-YITWLCD3.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-BQHYZB2W.js → chunk-ZBN4HTWP.js} +1 -1
- package/dist/cdn/components/chunks/{chunk-RJCJXB7Y.js → chunk-ZKZV2YG5.js} +18 -18
- package/dist/cdn/components/eun-alert.js +24 -16
- package/dist/cdn/components/eun-animate.js +12 -6
- package/dist/cdn/components/eun-badge.js +7 -7
- package/dist/cdn/components/eun-breadcrumb.js +25 -41
- package/dist/cdn/components/eun-button.js +1 -1
- package/dist/cdn/components/eun-calendar.js +68 -66
- package/dist/cdn/components/eun-card.js +67 -13
- package/dist/cdn/components/eun-carousel.js +66 -35
- package/dist/cdn/components/eun-check-card.js +13 -6
- package/dist/cdn/components/eun-checkbox-list.js +4 -4
- package/dist/cdn/components/eun-checkbox.js +1 -1
- package/dist/cdn/components/eun-chip.js +1 -1
- package/dist/cdn/components/eun-collapse.js +87 -39
- package/dist/cdn/components/eun-color-picker.js +54 -53
- package/dist/cdn/components/eun-counter.js +14 -13
- package/dist/cdn/components/eun-date-picker.js +66 -63
- package/dist/cdn/components/eun-description-list.js +152 -0
- package/dist/cdn/components/eun-divider.js +1 -1
- package/dist/cdn/components/eun-drawer.js +26 -12
- package/dist/cdn/components/eun-dropdown-button.js +1 -1
- package/dist/cdn/components/eun-dropdown-item.js +6 -5
- package/dist/cdn/components/eun-fab.js +20 -19
- package/dist/cdn/components/eun-icon.js +1 -1
- package/dist/cdn/components/eun-image-card.js +79 -22
- package/dist/cdn/components/eun-image-carousel.js +92 -47
- package/dist/cdn/components/eun-infinite-list.js +23 -11
- package/dist/cdn/components/eun-input-file.js +14 -13
- package/dist/cdn/components/eun-input-phone.js +26 -26
- package/dist/cdn/components/eun-input.js +1 -1
- package/dist/cdn/components/eun-label.js +4 -4
- package/dist/cdn/components/eun-link.js +174 -27
- package/dist/cdn/components/eun-loader.js +1 -1
- package/dist/cdn/components/eun-modal.js +29 -22
- package/dist/cdn/components/eun-pagination.js +17 -12
- package/dist/cdn/components/eun-password-strength.js +6 -2
- package/dist/cdn/components/eun-progress-bar.js +13 -5
- package/dist/cdn/components/eun-radio-card.js +16 -9
- package/dist/cdn/components/eun-radio-list.js +4 -4
- package/dist/cdn/components/eun-radio.js +1 -1
- package/dist/cdn/components/eun-scheduler-event-editor.js +8 -8
- package/dist/cdn/components/eun-scheduler-event.js +1 -1
- package/dist/cdn/components/eun-scheduler.js +42 -42
- package/dist/cdn/components/eun-search.js +21 -20
- package/dist/cdn/components/eun-select.js +12 -11
- package/dist/cdn/components/eun-sidebar.js +34 -20
- package/dist/cdn/components/eun-skeleton.js +1 -1
- package/dist/cdn/components/eun-slider.js +15 -14
- package/dist/cdn/components/eun-sliding-card.js +8 -4
- package/dist/cdn/components/eun-step.js +17 -6
- package/dist/cdn/components/eun-stepper.js +17 -6
- package/dist/cdn/components/eun-switch.js +10 -8
- package/dist/cdn/components/eun-tab-group.js +22 -17
- package/dist/cdn/components/eun-tab-panel.js +11 -3
- package/dist/cdn/components/eun-tab.js +1 -1
- package/dist/cdn/components/eun-table-action-bar.js +1 -1
- package/dist/cdn/components/eun-table.js +572 -31
- package/dist/cdn/components/eun-tag.js +13 -7
- package/dist/cdn/components/eun-textarea.js +24 -24
- package/dist/cdn/components/eun-time-picker.js +21 -19
- package/dist/cdn/components/eun-toast.js +36 -16
- package/dist/cdn/components/eun-toggle-group.js +64 -37
- package/dist/cdn/components/eun-toggle-item.js +24 -21
- package/dist/cdn/components/eun-toggle.js +12 -10
- package/dist/cdn/components/eun-toolbar.js +62 -52
- package/dist/cdn/components/eun-tooltip.js +30 -14
- package/dist/cdn/styles/breakpoints.scss +8 -0
- package/dist/cdn/styles/eunomia-grid.scss +6 -0
- package/dist/cdn/styles/eunomia-themes.css +1 -1
- package/dist/cdn/styles/themes/eunomia-theme.css +1 -1
- package/dist/cdn/styles/themes/eunomia-theme.scss +4 -3
- package/dist/cdn/styles/themes/mixins/eunomia-a11y-color.mixin.scss +34 -1
- package/dist/cdn/styles/themes/mixins/eunomia-neutrals.mixin.scss +4 -0
- package/dist/cdn/styles/themes/mixins/eunomia-states.mixin.scss +36 -12
- package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia.theme.scss +3 -2
- package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire.theme.scss +3 -2
- package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest.theme.scss +3 -2
- package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold.theme.scss +3 -2
- package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean.theme.scss +3 -2
- package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon.theme.scss +3 -2
- package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet-dark.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet.mixin.scss +10 -10
- package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet.theme.css +1 -1
- package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet.theme.scss +3 -2
- package/dist/cdn/styles/tools/indexes/eunomia-media-queries.index.scss +1 -3
- package/dist/cdn/styles/tools/indexes/eunomia-tools.index.scss +1 -0
- package/dist/cdn/styles/tools/mixins/layout/eunomia-grid.mixin.scss +117 -53
- package/dist/cdn/styles/tools/mixins/media-queries/eunomia-media-queries.mixin.scss +69 -0
- package/dist/cdn/styles/tools/mixins/settings/eunomia-alpha.mixin.scss +28 -4
- package/dist/cdn/styles/tools/mixins/settings/eunomia-motion.mixin.scss +9 -0
- package/dist/cdn/styles/tools/variables/eunomia.breakpoints.scss +4 -0
- package/dist/components/action/button/button.d.ts +51 -19
- package/dist/components/action/button/button.js +107 -24
- package/dist/components/action/button/button.styles.js +115 -62
- package/dist/components/action/dropdown-button/dropdown-button.d.ts +10 -10
- package/dist/components/action/dropdown-button/dropdown-button.js +18 -17
- package/dist/components/action/dropdown-button/dropdown-button.styles.js +3 -2
- package/dist/components/action/dropdown-button/dropdown-item.js +5 -6
- package/dist/components/action/dropdown-button/dropdown-item.styles.js +3 -2
- package/dist/components/action/fab/fab.d.ts +7 -6
- package/dist/components/action/fab/fab.js +11 -8
- package/dist/components/action/fab/fab.styles.js +18 -17
- package/dist/components/action/link/link.d.ts +72 -9
- package/dist/components/action/link/link.js +183 -23
- package/dist/components/action/link/link.styles.js +146 -10
- package/dist/components/action/shared-styles/button-palette.styles.d.ts +3 -3
- package/dist/components/action/shared-styles/button-palette.styles.js +29 -29
- package/dist/components/action/toggle/toggle-group.d.ts +17 -5
- package/dist/components/action/toggle/toggle-group.js +46 -19
- package/dist/components/action/toggle/toggle-group.styles.d.ts +4 -1
- package/dist/components/action/toggle/toggle-group.styles.js +56 -27
- package/dist/components/action/toggle/toggle-item.d.ts +4 -4
- package/dist/components/action/toggle/toggle-item.js +2 -2
- package/dist/components/action/toggle/toggle-item.styles.js +20 -17
- package/dist/components/action/toggle/toggle.d.ts +2 -0
- package/dist/components/action/toggle/toggle.js +2 -0
- package/dist/components/action/toggle/toggle.styles.d.ts +2 -0
- package/dist/components/action/toggle/toggle.styles.js +12 -8
- package/dist/components/alert/alert/alert.d.ts +2 -0
- package/dist/components/alert/alert/alert.js +2 -0
- package/dist/components/alert/alert/alert.styles.js +23 -13
- package/dist/components/alert/drawer/drawer.d.ts +3 -1
- package/dist/components/alert/drawer/drawer.js +5 -3
- package/dist/components/alert/drawer/drawer.styles.js +25 -9
- package/dist/components/alert/modal/modal.d.ts +11 -9
- package/dist/components/alert/modal/modal.js +15 -13
- package/dist/components/alert/modal/modal.styles.js +16 -7
- package/dist/components/alert/toast/toast.d.ts +2 -0
- package/dist/components/alert/toast/toast.js +2 -0
- package/dist/components/alert/toast/toast.styles.js +37 -15
- package/dist/components/content/badge/badge.d.ts +6 -6
- package/dist/components/content/badge/badge.js +4 -4
- package/dist/components/content/badge/badge.styles.js +4 -4
- package/dist/components/content/card/card.d.ts +39 -7
- package/dist/components/content/card/card.js +71 -7
- package/dist/components/content/card/card.styles.js +58 -11
- package/dist/components/content/card/image-card.d.ts +62 -7
- package/dist/components/content/card/image-card.js +121 -11
- package/dist/components/content/card/image-card.styles.js +66 -15
- package/dist/components/content/card/sliding-card.d.ts +4 -1
- package/dist/components/content/card/sliding-card.js +3 -0
- package/dist/components/content/card/sliding-card.styles.js +5 -1
- package/dist/components/content/collapse/collapse.d.ts +39 -12
- package/dist/components/content/collapse/collapse.js +65 -25
- package/dist/components/content/collapse/collapse.styles.d.ts +10 -1
- package/dist/components/content/collapse/collapse.styles.js +69 -18
- package/dist/components/content/description-list/description-list.d.ts +87 -0
- package/dist/components/content/description-list/description-list.js +107 -0
- package/dist/components/content/description-list/description-list.styles.d.ts +1 -0
- package/dist/components/content/description-list/description-list.styles.js +185 -0
- package/dist/components/content/icon/icon.d.ts +14 -2
- package/dist/components/content/icon/icon.js +54 -22
- package/dist/components/content/icon/icon.style.d.ts +2 -0
- package/dist/components/content/icon/icon.style.js +8 -2
- package/dist/components/content/image-carousel/image-carousel.d.ts +30 -19
- package/dist/components/content/image-carousel/image-carousel.js +48 -45
- package/dist/components/content/image-carousel/image-carousel.styles.js +69 -30
- package/dist/components/content/password-strength/password-strength.styles.js +5 -1
- package/dist/components/content/progress-bar/progress-bar.styles.js +12 -4
- package/dist/components/content/shared-styles/card-link.styles.js +5 -3
- package/dist/components/content/shared-styles/tone-surface.styles.d.ts +5 -0
- package/dist/components/content/shared-styles/tone-surface.styles.js +19 -14
- package/dist/components/content/tag/tag.d.ts +4 -0
- package/dist/components/content/tag/tag.js +4 -0
- package/dist/components/content/tag/tag.styles.js +14 -4
- package/dist/components/content/tooltip/tooltip.d.ts +3 -2
- package/dist/components/content/tooltip/tooltip.js +9 -16
- package/dist/components/content/tooltip/tooltip.styles.js +25 -7
- package/dist/components/form/checkbox/check-card.d.ts +4 -1
- package/dist/components/form/checkbox/check-card.js +4 -1
- package/dist/components/form/checkbox/check-card.styles.js +13 -4
- package/dist/components/form/checkbox/checkbox-list.d.ts +4 -1
- package/dist/components/form/checkbox/checkbox-list.js +11 -7
- package/dist/components/form/checkbox/checkbox.d.ts +4 -1
- package/dist/components/form/checkbox/checkbox.js +4 -1
- package/dist/components/form/checkbox/checkbox.styles.js +2 -2
- package/dist/components/form/color-picker/color-picker.d.ts +10 -4
- package/dist/components/form/color-picker/color-picker.js +23 -25
- package/dist/components/form/color-picker/color-picker.styles.js +6 -5
- package/dist/components/form/counter/counter.d.ts +7 -4
- package/dist/components/form/counter/counter.js +8 -5
- package/dist/components/form/counter/counter.styles.js +10 -9
- package/dist/components/form/date-picker/date-picker.d.ts +40 -36
- package/dist/components/form/date-picker/date-picker.js +35 -45
- package/dist/components/form/date-picker/date-picker.styles.js +13 -10
- package/dist/components/form/input/input.d.ts +10 -4
- package/dist/components/form/input/input.js +12 -6
- package/dist/components/form/input-file/input-file.d.ts +4 -1
- package/dist/components/form/input-file/input-file.js +8 -5
- package/dist/components/form/input-file/input-file.styles.js +3 -2
- package/dist/components/form/input-phone/input-phone.d.ts +11 -5
- package/dist/components/form/input-phone/input-phone.js +16 -20
- package/dist/components/form/input-phone/input-phone.styles.js +16 -16
- package/dist/components/form/label/label.styles.js +3 -3
- package/dist/components/form/radio/radio-card.d.ts +5 -2
- package/dist/components/form/radio/radio-card.js +5 -2
- package/dist/components/form/radio/radio-card.styles.js +14 -5
- package/dist/components/form/radio/radio-list.d.ts +5 -2
- package/dist/components/form/radio/radio-list.js +14 -10
- package/dist/components/form/radio/radio.d.ts +5 -2
- package/dist/components/form/radio/radio.js +5 -2
- package/dist/components/form/radio/radio.styles.js +4 -4
- package/dist/components/form/search/search.d.ts +2 -1
- package/dist/components/form/search/search.js +6 -15
- package/dist/components/form/search/search.styles.js +8 -7
- package/dist/components/form/select/select.d.ts +12 -5
- package/dist/components/form/select/select.js +18 -21
- package/dist/components/form/select/select.styles.js +3 -2
- package/dist/components/form/shared-styles/card.styles.js +5 -4
- package/dist/components/form/shared-styles/field.styles.js +21 -11
- package/dist/components/form/shared-styles/form-labels.styles.js +1 -1
- package/dist/components/form/slider/slider.d.ts +4 -1
- package/dist/components/form/slider/slider.js +5 -2
- package/dist/components/form/slider/slider.styles.js +8 -7
- package/dist/components/form/switch/switch.d.ts +4 -1
- package/dist/components/form/switch/switch.js +4 -1
- package/dist/components/form/switch/switch.styles.js +7 -5
- package/dist/components/form/textarea/textarea.d.ts +10 -4
- package/dist/components/form/textarea/textarea.js +18 -12
- package/dist/components/form/time-picker/time-picker-columns.styles.js +4 -2
- package/dist/components/form/time-picker/time-picker-list.styles.js +2 -1
- package/dist/components/form/time-picker/time-picker.d.ts +9 -5
- package/dist/components/form/time-picker/time-picker.js +25 -29
- package/dist/components/form/time-picker/time-picker.styles.js +9 -8
- package/dist/components/layout/animate/animate.d.ts +41 -11
- package/dist/components/layout/animate/animate.js +48 -16
- package/dist/components/layout/animate/animate.styles.js +9 -16
- package/dist/components/layout/infinite-list/infinite-list.d.ts +33 -10
- package/dist/components/layout/infinite-list/infinite-list.js +115 -18
- package/dist/components/layout/infinite-list/infinite-list.styles.d.ts +3 -0
- package/dist/components/layout/infinite-list/infinite-list.styles.js +17 -5
- package/dist/components/loader/loader/loader.styles.js +3 -1
- package/dist/components/navigation/breadcrumb/breadcrumb.d.ts +31 -45
- package/dist/components/navigation/breadcrumb/breadcrumb.js +111 -77
- package/dist/components/navigation/breadcrumb/breadcrumb.styles.d.ts +3 -0
- package/dist/components/navigation/breadcrumb/breadcrumb.styles.js +22 -26
- package/dist/components/navigation/carousel/carousel.d.ts +30 -10
- package/dist/components/navigation/carousel/carousel.js +37 -18
- package/dist/components/navigation/carousel/carousel.styles.js +60 -20
- package/dist/components/navigation/pagination/pagination.styles.js +8 -3
- package/dist/components/navigation/sidebar/sidebar.d.ts +2 -0
- package/dist/components/navigation/sidebar/sidebar.js +2 -0
- package/dist/components/navigation/sidebar/sidebar.styles.js +27 -11
- package/dist/components/navigation/stepper/step.styles.js +16 -5
- package/dist/components/navigation/stepper/stepper.styles.js +16 -5
- package/dist/components/navigation/tabs/tab/tab.d.ts +11 -0
- package/dist/components/navigation/tabs/tab/tab.js +11 -0
- package/dist/components/navigation/tabs/tab/tab.styles.js +22 -16
- package/dist/components/navigation/tabs/tab-group/tab-group.js +7 -8
- package/dist/components/navigation/tabs/tab-group/tab-group.styles.js +19 -14
- package/dist/components/navigation/tabs/tab-panel/tab-panel.d.ts +4 -0
- package/dist/components/navigation/tabs/tab-panel/tab-panel.js +4 -0
- package/dist/components/navigation/tabs/tab-panel/tab-panel.styles.js +18 -1
- package/dist/components/navigation/toolbar/toolbar.d.ts +17 -49
- package/dist/components/navigation/toolbar/toolbar.js +23 -71
- package/dist/components/navigation/toolbar/toolbar.styles.js +59 -36
- package/dist/events/table-row-click.event.d.ts +5 -4
- package/dist/events/table-row-click.event.js +10 -5
- package/dist/features/scheduler/calendar/calendar.d.ts +12 -12
- package/dist/features/scheduler/calendar/calendar.js +15 -14
- package/dist/features/scheduler/calendar/calendar.styles.js +8 -6
- package/dist/features/scheduler/scheduler/scheduler.d.ts +7 -7
- package/dist/features/scheduler/scheduler/scheduler.js +21 -35
- package/dist/features/scheduler/scheduler/scheduler.styles.js +6 -4
- package/dist/features/scheduler/scheduler-event/scheduler-event.d.ts +12 -8
- package/dist/features/scheduler/scheduler-event/scheduler-event.js +9 -7
- package/dist/features/scheduler/scheduler-event/scheduler-event.styles.js +16 -10
- package/dist/features/scheduler/scheduler-event-editor/scheduler-event-editor.js +5 -5
- package/dist/features/scheduler/shared/scheduler-event-popover.js +2 -2
- package/dist/features/scheduler/shared/scheduler-hour-grid.d.ts +2 -2
- package/dist/features/scheduler/shared/scheduler-hour-grid.js +3 -3
- package/dist/features/scheduler/shared/scheduler-hour-grid.styles.js +3 -3
- package/dist/features/scheduler/shared/scheduler-month-view.d.ts +3 -3
- package/dist/features/scheduler/shared/scheduler-month-view.js +2 -2
- package/dist/features/scheduler/shared/scheduler-month-view.styles.js +2 -2
- package/dist/features/scheduler/shared/scheduler-year-view.styles.js +2 -2
- package/dist/features/table/table/table-native.styles.d.ts +28 -0
- package/dist/features/table/table/table-native.styles.js +502 -0
- package/dist/features/table/table/table.d.ts +342 -294
- package/dist/features/table/table/table.js +820 -546
- package/dist/features/table/table/table.styles.js +31 -17
- package/dist/features/table/table/table.types.d.ts +18 -23
- package/dist/features/table/table/table.utils.d.ts +6 -36
- package/dist/features/table/table/table.utils.js +16 -65
- package/dist/features/table/table-action-bar/table-action-bar.d.ts +33 -16
- package/dist/features/table/table-action-bar/table-action-bar.js +18 -25
- package/dist/features/table/table-action-bar/table-action-bar.styles.js +15 -3
- package/dist/i18n/en.d.ts +34 -0
- package/dist/i18n/en.js +34 -0
- package/dist/i18n/fr.js +38 -0
- package/dist/index.d.ts +7 -13
- package/dist/index.js +6 -10
- package/dist/jsx.d.ts +1 -1
- package/dist/mixins/button.mixin.d.ts +10 -9
- package/dist/mixins/button.mixin.js +14 -6
- package/dist/mixins/card-link.mixin.d.ts +3 -2
- package/dist/mixins/card-link.mixin.js +12 -5
- package/dist/mixins/check.mixin.js +4 -5
- package/dist/mixins/disabled.mixin.d.ts +3 -3
- package/dist/mixins/disabled.mixin.js +10 -5
- package/dist/mixins/field-appearance.mixin.d.ts +19 -0
- package/dist/mixins/{field-variant.mixin.js → field-appearance.mixin.js} +11 -11
- package/dist/mixins/form.mixin.d.ts +17 -1
- package/dist/mixins/form.mixin.js +80 -25
- package/dist/mixins/radio.mixin.js +4 -5
- package/dist/mixins/validators.mixin.d.ts +7 -1
- package/dist/mixins/validators.mixin.js +36 -17
- package/dist/ssr/animate-ssr.css +27 -72
- package/dist/ssr/button-ssr.css +319 -0
- package/dist/ssr/card-ssr.css +184 -0
- package/dist/ssr/description-list-ssr.css +150 -0
- package/dist/ssr/links-ssr.css +35 -0
- package/dist/ssr/overlay-ssr.css +0 -41
- package/dist/ssr/rich-text.css +38 -0
- package/dist/ssr/sidebar-ssr.css +0 -38
- package/dist/ssr/table-ssr.css +472 -0
- package/dist/ssr/tag-ssr.css +197 -0
- package/dist/ssr/toolbar-ssr.css +77 -39
- package/dist/types/variant.type.d.ts +26 -10
- package/dist/utils/drag-drop.utils.js +18 -2
- package/dist/utils/dropdown-menu.utils.d.ts +2 -2
- package/dist/utils/dropdown-menu.utils.js +4 -14
- package/dist/utils/light-dom-styles.utils.d.ts +14 -0
- package/dist/utils/light-dom-styles.utils.js +37 -0
- package/dist/utils/media.styles.d.ts +19 -0
- package/dist/utils/media.styles.js +23 -0
- package/dist/utils/motion.utils.d.ts +40 -0
- package/dist/utils/motion.utils.js +51 -0
- package/dist/utils/navigation.utils.d.ts +14 -0
- package/dist/utils/navigation.utils.js +33 -0
- package/dist/utils/new-tab-anchor.controller.d.ts +44 -0
- package/dist/utils/new-tab-anchor.controller.js +102 -0
- package/dist/utils/severity-icon.utils.d.ts +1 -1
- package/dist/utils/severity-icon.utils.js +1 -1
- package/dist/utils/theme-generator.utils.d.ts +9 -2
- package/dist/utils/theme-generator.utils.js +62 -21
- package/package.json +24 -29
- package/styles/breakpoints.scss +8 -0
- package/styles/eunomia-grid.scss +6 -0
- package/styles/themes/eunomia-theme.scss +4 -3
- package/styles/themes/mixins/eunomia-a11y-color.mixin.scss +34 -1
- package/styles/themes/mixins/eunomia-neutrals.mixin.scss +4 -0
- package/styles/themes/mixins/eunomia-states.mixin.scss +36 -12
- package/styles/themes/prebuilt-themes/eunomia/eunomia-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/eunomia/eunomia.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/eunomia/eunomia.theme.scss +3 -2
- package/styles/themes/prebuilt-themes/fire/eunomia-fire-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/fire/eunomia-fire.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/fire/eunomia-fire.theme.scss +3 -2
- package/styles/themes/prebuilt-themes/forest/eunomia-forest-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/forest/eunomia-forest.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/forest/eunomia-forest.theme.scss +3 -2
- package/styles/themes/prebuilt-themes/gold/eunomia-gold-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/gold/eunomia-gold.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/gold/eunomia-gold.theme.scss +3 -2
- package/styles/themes/prebuilt-themes/ocean/eunomia-ocean-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/ocean/eunomia-ocean.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/ocean/eunomia-ocean.theme.scss +3 -2
- package/styles/themes/prebuilt-themes/salmon/eunomia-salmon-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/salmon/eunomia-salmon.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/salmon/eunomia-salmon.theme.scss +3 -2
- package/styles/themes/prebuilt-themes/violet/eunomia-violet-dark.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/violet/eunomia-violet.mixin.scss +10 -10
- package/styles/themes/prebuilt-themes/violet/eunomia-violet.theme.scss +3 -2
- package/styles/tools/indexes/eunomia-media-queries.index.scss +1 -3
- package/styles/tools/indexes/eunomia-tools.index.scss +1 -0
- package/styles/tools/mixins/layout/eunomia-grid.mixin.scss +117 -53
- package/styles/tools/mixins/media-queries/eunomia-media-queries.mixin.scss +69 -0
- package/styles/tools/mixins/settings/eunomia-alpha.mixin.scss +28 -4
- package/styles/tools/mixins/settings/eunomia-motion.mixin.scss +9 -0
- package/styles/tools/variables/eunomia.breakpoints.scss +4 -0
- package/dist/cdn/components/chunks/chunk-2JLDJFYD.js +0 -48
- package/dist/cdn/components/chunks/chunk-A6KGFALA.js +0 -132
- package/dist/cdn/components/chunks/chunk-ATH2OAMU.js +0 -1
- package/dist/cdn/components/chunks/chunk-BKHD4S57.js +0 -1
- package/dist/cdn/components/chunks/chunk-CEDHJUUH.js +0 -1
- package/dist/cdn/components/chunks/chunk-D2M4BV5Y.js +0 -328
- package/dist/cdn/components/chunks/chunk-E74CM7UG.js +0 -66
- package/dist/cdn/components/chunks/chunk-EST3M4AO.js +0 -1
- package/dist/cdn/components/chunks/chunk-GU6BVMFJ.js +0 -1
- package/dist/cdn/components/chunks/chunk-KVYUNKUO.js +0 -27
- package/dist/cdn/components/chunks/chunk-OAULRKHQ.js +0 -38
- package/dist/cdn/components/chunks/chunk-PCM7D3YF.js +0 -84
- package/dist/cdn/components/chunks/chunk-T4PTHUYF.js +0 -10
- package/dist/cdn/components/chunks/chunk-T7WABJEJ.js +0 -1
- package/dist/cdn/components/chunks/chunk-VRGRCYIO.js +0 -1
- package/dist/cdn/components/chunks/chunk-X2AUBZD2.js +0 -30
- package/dist/cdn/components/chunks/chunk-XSMCT4DF.js +0 -1
- package/dist/cdn/components/eun-breadcrumb-item.js +0 -93
- package/dist/cdn/components/eun-table-cell.js +0 -1
- package/dist/cdn/components/eun-table-column.js +0 -1
- package/dist/cdn/components/eun-table-header.js +0 -1
- package/dist/cdn/components/eun-table-item.js +0 -1
- package/dist/cdn/components/eun-table-skeleton-row.js +0 -1
- package/dist/cdn/styles/tools/mixins/media-queries/eunomia-device.mixin.scss +0 -14
- package/dist/cdn/styles/tools/mixins/media-queries/eunomia-gte.mixin.scss +0 -26
- package/dist/cdn/styles/tools/mixins/media-queries/eunomia-lte.mixin.scss +0 -26
- package/dist/components/navigation/breadcrumb/breadcrumb-item.d.ts +0 -77
- package/dist/components/navigation/breadcrumb/breadcrumb-item.js +0 -130
- package/dist/components/navigation/breadcrumb/breadcrumb-item.styles.d.ts +0 -6
- package/dist/components/navigation/breadcrumb/breadcrumb-item.styles.js +0 -78
- package/dist/features/table/native-table.css +0 -276
- package/dist/features/table/shared-styles/table-row.styles.d.ts +0 -7
- package/dist/features/table/shared-styles/table-row.styles.js +0 -47
- package/dist/features/table/shared-styles/table-shared.styles.d.ts +0 -23
- package/dist/features/table/shared-styles/table-shared.styles.js +0 -33
- package/dist/features/table/table-cell/table-cell.d.ts +0 -59
- package/dist/features/table/table-cell/table-cell.js +0 -73
- package/dist/features/table/table-cell/table-cell.styles.d.ts +0 -1
- package/dist/features/table/table-cell/table-cell.styles.js +0 -46
- package/dist/features/table/table-column/table-column.d.ts +0 -73
- package/dist/features/table/table-column/table-column.js +0 -89
- package/dist/features/table/table-column/table-column.styles.d.ts +0 -1
- package/dist/features/table/table-column/table-column.styles.js +0 -51
- package/dist/features/table/table-header/table-header.d.ts +0 -102
- package/dist/features/table/table-header/table-header.js +0 -165
- package/dist/features/table/table-header/table-header.styles.d.ts +0 -1
- package/dist/features/table/table-header/table-header.styles.js +0 -147
- package/dist/features/table/table-item/table-item.d.ts +0 -179
- package/dist/features/table/table-item/table-item.js +0 -291
- package/dist/features/table/table-item/table-item.styles.d.ts +0 -1
- package/dist/features/table/table-item/table-item.styles.js +0 -404
- package/dist/features/table/table-managed/table-managed.d.ts +0 -19
- package/dist/features/table/table-managed/table-managed.js +0 -128
- package/dist/features/table/table-skeleton-row/table-skeleton-row.d.ts +0 -46
- package/dist/features/table/table-skeleton-row/table-skeleton-row.js +0 -110
- package/dist/features/table/table-skeleton-row/table-skeleton-row.styles.d.ts +0 -12
- package/dist/features/table/table-skeleton-row/table-skeleton-row.styles.js +0 -65
- package/dist/mixins/field-variant.mixin.d.ts +0 -22
- package/dist/mixins/table-row.mixin.d.ts +0 -37
- package/dist/mixins/table-row.mixin.js +0 -103
- package/styles/tools/mixins/media-queries/eunomia-device.mixin.scss +0 -14
- package/styles/tools/mixins/media-queries/eunomia-gte.mixin.scss +0 -26
- package/styles/tools/mixins/media-queries/eunomia-lte.mixin.scss +0 -26
|
@@ -4,140 +4,190 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, property, query,
|
|
8
|
-
import { html, LitElement, nothing } from "lit";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { customElement, property, query, state } from "lit/decorators.js";
|
|
8
|
+
import { html, LitElement, nothing, render, } from "lit";
|
|
9
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
10
|
+
import { repeat } from "lit/directives/repeat.js";
|
|
11
11
|
import { EunomiaTableActionBarTagName, } from "../table-action-bar/table-action-bar.js";
|
|
12
|
-
import {
|
|
13
|
-
import { buildManagedHeader, buildManagedItem, } from "../table-managed/table-managed.js";
|
|
12
|
+
import { alignToTextAlign, resolveRowKey } from "./table.utils.js";
|
|
14
13
|
import { TableSelectionChangeEvent } from "../../../events/table-selection-change.event.js";
|
|
15
14
|
import { TableActionEvent } from "../../../events/table-action.event.js";
|
|
15
|
+
import { TableRowClickEvent } from "../../../events/table-row-click.event.js";
|
|
16
16
|
import { LoadMoreEvent } from "../../../events/loadmore.event.js";
|
|
17
17
|
import { LoadMoreSentinelMixin } from "../../../mixins/load-more-sentinel.mixin.js";
|
|
18
|
+
import { LocalizableMixin } from "../../../mixins/localizable.mixin.js";
|
|
18
19
|
import { tableStyles } from "./table.styles.js";
|
|
19
|
-
import "
|
|
20
|
+
import { tableNativeStyles } from "./table-native.styles.js";
|
|
21
|
+
import { adoptLightDomStyles } from "../../../utils/light-dom-styles.utils.js";
|
|
22
|
+
import "../../../components/form/checkbox/checkbox.js";
|
|
23
|
+
import "../../../components/action/button/button.js";
|
|
24
|
+
import "../../../components/action/dropdown-button/dropdown-button.js";
|
|
25
|
+
import "../../../components/content/icon/icon.js";
|
|
20
26
|
import "../../../components/loader/loader/loader.js";
|
|
27
|
+
import "../../../components/loader/skeleton/skeleton.js";
|
|
21
28
|
/**
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
*
|
|
29
|
+
* Tag name of the table component.
|
|
30
|
+
*/
|
|
31
|
+
export const EunomiaTableTagName = "eun-table";
|
|
32
|
+
/**
|
|
33
|
+
* Marks the selection column cells `eun-table` generates.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
const SELECT_ATTR = "data-table-select";
|
|
37
|
+
/**
|
|
38
|
+
* Marks a row end action cell, authored by the consumer.
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
const ACTION_ATTR = "data-table-action";
|
|
42
|
+
/**
|
|
43
|
+
* Marks the link a body row click follows, authored by the consumer.
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
const ROW_LINK_ATTR = "data-table-row-link";
|
|
47
|
+
/**
|
|
48
|
+
* Marks the placeholder body rendered while `loading`.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
const SKELETON_ATTR = "data-table-skeleton";
|
|
52
|
+
/**
|
|
53
|
+
* Reflected on a selected body row.
|
|
28
54
|
* @internal
|
|
29
55
|
*/
|
|
30
|
-
const
|
|
56
|
+
const SELECTED_ATTR = "data-selected";
|
|
31
57
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
|
|
58
|
+
* Class of a virtualized-out page's placeholder row, sized to the page's
|
|
59
|
+
* last measured height so the scroll position doesn't jump.
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
const SPACER_CLASS = "eun-table-row-spacer";
|
|
63
|
+
/**
|
|
64
|
+
* Row height (px) assumed for a virtualized page never measured yet.
|
|
36
65
|
* @internal
|
|
37
66
|
*/
|
|
38
67
|
const DEFAULT_ROW_HEIGHT = 44;
|
|
39
68
|
/**
|
|
40
|
-
*
|
|
69
|
+
* Elements a click on which belongs to that element, not to its row.
|
|
70
|
+
* @internal
|
|
41
71
|
*/
|
|
42
|
-
|
|
72
|
+
const INTERACTIVE_SELECTOR = 'a[href], button, input, select, textarea, summary, label, [contenteditable=""], [contenteditable="true"], [role="button"], [role="link"], [role="checkbox"], [role="switch"], [role="menuitem"]';
|
|
43
73
|
/**
|
|
44
|
-
* A
|
|
45
|
-
*
|
|
46
|
-
*
|
|
74
|
+
* A data table built on a native `<table>` (`<eun-table><table>…</table></eun-table>`).
|
|
75
|
+
* The table keeps its native semantics (`table`, `row`, `columnheader`,
|
|
76
|
+
* `rowheader`, `cell`), renders before any script runs, and holds any
|
|
77
|
+
* content: tags, icons, buttons, dropdown buttons, links.
|
|
47
78
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* its own `:host`, inheriting the exact same tracks the browser computed
|
|
55
|
-
* once for the whole grid: this is what keeps `auto`/flexible columns
|
|
56
|
-
* pixel-aligned across every row with zero JS measurement. The track list
|
|
57
|
-
* itself (from `eun-table-column`'s `width`, plus a select/action track
|
|
58
|
-
* when relevant) is computed in `updateColumnsTemplate` and applied as the
|
|
59
|
-
* `--_columns` custom property `table.styles.ts`'s `:host` reads.
|
|
79
|
+
* `eun-table` styles the slotted table from the light DOM and layers the
|
|
80
|
+
* optional behaviors on top: row selection with a checkbox column it
|
|
81
|
+
* generates and a floating action bar, row end actions revealed on hover
|
|
82
|
+
* (cells marked `data-table-action`), clickable rows, sticky header,
|
|
83
|
+
* footer, and columns, loading placeholders, and scroll-driven pagination.
|
|
84
|
+
* Without any of those, it's a plain, read-only table.
|
|
60
85
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* data-driven renders.
|
|
86
|
+
* A row click follows the link marked `data-table-row-link` in that row,
|
|
87
|
+
* which stays the keyboard way to reach it. Rows are identified by their
|
|
88
|
+
* `data-row-key` attribute. A `<tfoot>` holds
|
|
89
|
+
* summary rows, kept out of the selection. A `<caption>` stays in the
|
|
90
|
+
* table for its semantics, and shows above the table's frame.
|
|
67
91
|
*
|
|
68
|
-
* @slot [default] -
|
|
69
|
-
* @
|
|
70
|
-
* @prop {boolean} [
|
|
92
|
+
* @slot [default] - A native `<table>`, with a `<thead>`, a `<tbody>`, and an optional `<caption>` and `<tfoot>`
|
|
93
|
+
* @csspart frame - The bordered scroll container around the table
|
|
94
|
+
* @prop {boolean} [selectable=false] - Enables row selection (generated checkbox column, select-all, the floating action bar)
|
|
95
|
+
* @prop {boolean} [checkboxAlwaysVisible=false] - Keeps every row's own checkbox visible at all times instead of only on hover/focus/selection
|
|
71
96
|
* @attr {boolean} [checkbox-always-visible=false] - Keeps every row's own checkbox visible at all times instead of only on hover/focus/selection
|
|
72
|
-
* @prop {boolean} [actionAlwaysVisible=false] - Keeps every row
|
|
73
|
-
* @attr {boolean} [action-always-visible=false] - Keeps every row
|
|
74
|
-
* @prop {boolean} [stickyHeader=false] - Pins the
|
|
97
|
+
* @prop {boolean} [actionAlwaysVisible=false] - Keeps every row end action (a `data-table-action` cell's content) visible at all times instead of only on hover/focus ; still hidden while rows are selected
|
|
98
|
+
* @attr {boolean} [action-always-visible=false] - Keeps every row end action visible at all times instead of only on hover/focus
|
|
99
|
+
* @prop {boolean} [stickyHeader=false] - Pins the `<thead>` to the top of the table's own scroll container
|
|
75
100
|
* @attr {boolean} [sticky-header=false] - Pins the header to the top
|
|
101
|
+
* @prop {boolean} [stickyFooter=false] - Pins the `<tfoot>` to the bottom of the table's own scroll container
|
|
102
|
+
* @attr {boolean} [sticky-footer=false] - Pins the footer to the bottom
|
|
76
103
|
* @prop {boolean} [stickyFirstColumn=false] - Pins the first data column to the start edge
|
|
77
104
|
* @attr {boolean} [sticky-first-column=false] - Pins the first data column to the start edge
|
|
78
|
-
* @prop {boolean} [stickyLastColumn=false] - Pins the last data column to the end edge
|
|
105
|
+
* @prop {boolean} [stickyLastColumn=false] - Pins the last data column, and the row end action column, to the end edge
|
|
79
106
|
* @attr {boolean} [sticky-last-column=false] - Pins the last data column to the end edge
|
|
80
|
-
* @prop {boolean} [clearOnEscape=false] - Whether `Escape` clears the selection while the action bar is shown
|
|
107
|
+
* @prop {boolean} [clearOnEscape=false] - Whether `Escape` clears the selection while the action bar is shown
|
|
81
108
|
* @attr {boolean} [clear-on-escape=false] - Whether `Escape` clears the selection while the action bar is shown
|
|
82
|
-
* @prop {Array<string>} [selectedKeys=[]] - The currently selected rows' keys ; settable from outside for a "controlled" table
|
|
109
|
+
* @prop {Array<string>} [selectedKeys=[]] - The currently selected rows' keys ; settable from outside for a "controlled" table
|
|
83
110
|
* @prop {Array<import('./table.types.js').EunomiaTableAction>} [actions=[]] - Custom actions rendered in the floating action bar's center region
|
|
84
|
-
* @prop {string} [selectedLabel='selected'] - Text shown after the count in the action bar's badge
|
|
111
|
+
* @prop {string} [selectedLabel='selected'] - Text shown after the count in the action bar's badge ; translated from `locale` while unset
|
|
85
112
|
* @attr {string} [selected-label='selected'] - Text shown after the count in the action bar's badge
|
|
86
|
-
* @prop {string} [selectAllLabel='Select all'] - Label of the action bar's select-all button while not every row is selected
|
|
113
|
+
* @prop {string} [selectAllLabel='Select all'] - Label of the action bar's select-all button while not every row is selected ; translated from `locale` while unset
|
|
87
114
|
* @attr {string} [select-all-label='Select all'] - Label of the action bar's select-all button
|
|
88
|
-
* @prop {string} [deselectAllLabel='Deselect all'] - Label of the action bar's select-all button once every row is selected
|
|
115
|
+
* @prop {string} [deselectAllLabel='Deselect all'] - Label of the action bar's select-all button once every row is selected ; translated from `locale` while unset
|
|
89
116
|
* @attr {string} [deselect-all-label='Deselect all'] - Label of the action bar's select-all button once every row is selected
|
|
90
|
-
* @prop {string} [selectAllAriaLabel='Select all rows'] - Accessible label for the header's select-all checkbox while not every row is selected
|
|
117
|
+
* @prop {string} [selectAllAriaLabel='Select all rows'] - Accessible label for the header's select-all checkbox while not every row is selected ; translated from `locale` while unset
|
|
91
118
|
* @attr {string} [select-all-aria-label='Select all rows'] - Accessible label for the header's select-all checkbox
|
|
92
|
-
* @prop {string} [deselectAllAriaLabel='Deselect all rows'] - Accessible label for the header's select-all checkbox once every row is selected
|
|
119
|
+
* @prop {string} [deselectAllAriaLabel='Deselect all rows'] - Accessible label for the header's select-all checkbox once every row is selected ; translated from `locale` while unset
|
|
93
120
|
* @attr {string} [deselect-all-aria-label='Deselect all rows'] - Accessible label for the header's select-all checkbox
|
|
94
|
-
* @prop {string} [selectRowAriaLabel='Select row'] - Accessible label prefix for each row's own checkbox
|
|
121
|
+
* @prop {string} [selectRowAriaLabel='Select row'] - Accessible label prefix for each row's own checkbox, followed by the row header's text, or its 1-based row number without one ; translated from `locale` while unset
|
|
95
122
|
* @attr {string} [select-row-aria-label='Select row'] - Accessible label prefix for each row's own checkbox
|
|
96
|
-
* @prop {string} [toolbarAriaLabel='Selection actions'] - Accessible label for the floating action bar itself
|
|
123
|
+
* @prop {string} [toolbarAriaLabel='Selection actions'] - Accessible label for the floating action bar itself ; translated from `locale` while unset
|
|
97
124
|
* @attr {string} [toolbar-aria-label='Selection actions'] - Accessible label for the floating action bar itself
|
|
98
|
-
* @prop {string} [closeActionBarAriaLabel='Clear selection'] - Accessible label for the action bar's close button
|
|
125
|
+
* @prop {string} [closeActionBarAriaLabel='Clear selection'] - Accessible label for the action bar's close button ; translated from `locale` while unset
|
|
99
126
|
* @attr {string} [close-action-bar-aria-label='Clear selection'] - Accessible label for the action bar's close button
|
|
100
|
-
* @prop {Array<import('./table.types.js').EunomiaTableColumnDef<T>>} [columns] - Programmatic alternative to
|
|
127
|
+
* @prop {Array<import('./table.types.js').EunomiaTableColumnDef<T>>} [columns] - Programmatic alternative to authoring the `<table>` : when set, `eun-table` renders the native table itself from `columns`/`data`, and owns its light DOM from then on
|
|
101
128
|
* @prop {Array<T>} [data=[]] - The rows to render, in "managed" mode (see `columns`)
|
|
102
|
-
* @prop {import('./table.types.js').EunomiaTableRowActionDef<T>} [rowAction] - A single row
|
|
103
|
-
* @prop {(row: T, index: number) => string} [rowKey] - Computes each row's stable key, in "managed" mode ; defaults to a DOM-order fallback
|
|
104
|
-
* @
|
|
105
|
-
* @fires {TableActionEvent} euntableaction - Emitted when a floating action bar action is activated
|
|
106
|
-
* @prop {boolean} [loading=false] - Shows `skeletonRows` shimmering placeholder rows in place of the real ones: the header stays visible, only `eun-table-item`s are hidden ; set back to `false` once real data has arrived
|
|
129
|
+
* @prop {import('./table.types.js').EunomiaTableRowActionDef<T>} [rowAction] - A single row end action (button or dropdown), in "managed" mode
|
|
130
|
+
* @prop {(row: T, index: number) => string} [rowKey] - Computes each row's stable key, in "managed" mode ; defaults to a DOM-order fallback
|
|
131
|
+
* @prop {boolean} [loading=false] - Shows `skeletonRows` placeholder rows in place of the body rows ; the header stays visible
|
|
107
132
|
* @prop {number} [skeletonRows=6] - Number of placeholder rows rendered while `loading`
|
|
108
133
|
* @attr {number} [skeleton-rows=6] - Number of placeholder rows rendered while `loading`
|
|
109
|
-
* @prop {boolean} [syncing=false] -
|
|
110
|
-
* @prop {boolean} [clickable=false] - Shows a pointer cursor on
|
|
111
|
-
* @
|
|
112
|
-
* @prop {boolean} [
|
|
113
|
-
* @prop {
|
|
114
|
-
* @prop {number} [pageSize=20] - Number of rows per page: both the unit `eunloadmore` requests are made in, and the chunk size `virtualize` mounts/unmounts as a whole
|
|
134
|
+
* @prop {boolean} [syncing=false] - Sweeps a shimmer across every visible body row without hiding any, for a background refresh. Sets `aria-busy` on the table while set
|
|
135
|
+
* @prop {boolean} [clickable=false] - Shows a pointer cursor on body rows ; a row click fires `euntablerowclick` and follows the row's `data-table-row-link` link regardless, which stays the keyboard way to do the same
|
|
136
|
+
* @prop {boolean} [infinite=false] - Enables scroll-triggered pagination : dispatches `eunloadmore` once the user scrolls near the end of the table's own scroll container and `hasMore` is `true`
|
|
137
|
+
* @prop {boolean} [virtualize=false] - Detaches body row pages far from the current scroll position once the row count exceeds `virtualizeThreshold`, each replaced by a spacer row of the same height
|
|
138
|
+
* @prop {number} [pageSize=20] - Number of rows per page, for both `eunloadmore` and `virtualize`
|
|
115
139
|
* @attr {number} [page-size=20] - Number of rows per page
|
|
116
|
-
* @prop {number} [virtualizeThreshold=100] -
|
|
117
|
-
* @attr {number} [virtualize-threshold=100] -
|
|
118
|
-
* @prop {number} [bufferPages=1] - Number of extra pages kept mounted before and after the page
|
|
119
|
-
* @attr {number} [buffer-pages=1] - Number of extra pages kept mounted before and after the page
|
|
120
|
-
* @prop {boolean} [hasMore=false] - Whether more rows can still be obtained
|
|
140
|
+
* @prop {number} [virtualizeThreshold=100] - Row count above which `virtualize` starts detaching pages
|
|
141
|
+
* @attr {number} [virtualize-threshold=100] - Row count above which `virtualize` starts detaching pages
|
|
142
|
+
* @prop {number} [bufferPages=1] - Number of extra pages kept mounted before and after the page in view
|
|
143
|
+
* @attr {number} [buffer-pages=1] - Number of extra pages kept mounted before and after the page in view
|
|
144
|
+
* @prop {boolean} [hasMore=false] - Whether more rows can still be obtained
|
|
121
145
|
* @attr {boolean} [has-more=false] - Whether more rows can still be obtained
|
|
122
|
-
* @prop {boolean} [loadingMore=false] - Whether a `eunloadmore` request is
|
|
123
|
-
* @attr {boolean} [loading-more=false] - Whether a `eunloadmore` request is
|
|
124
|
-
* @prop {string} [rootMargin='400px'] - How far before the
|
|
125
|
-
* @attr {string} [root-margin='400px'] - How far before the
|
|
126
|
-
* @prop {string} [loadingMoreLabel='Loading more rows…'] - Accessible label passed to the trailing `eun-loader`
|
|
146
|
+
* @prop {boolean} [loadingMore=false] - Whether a `eunloadmore` request is in flight ; set to `true` right before the event fires, reset by the consumer once rows are appended
|
|
147
|
+
* @attr {boolean} [loading-more=false] - Whether a `eunloadmore` request is in flight
|
|
148
|
+
* @prop {string} [rootMargin='400px'] - How far before the end of the table `eunloadmore` triggers, as a CSS-like margin
|
|
149
|
+
* @attr {string} [root-margin='400px'] - How far before the end of the table `eunloadmore` triggers
|
|
150
|
+
* @prop {string} [loadingMoreLabel='Loading more rows…'] - Accessible label passed to the trailing `eun-loader` ; translated from `locale` while unset
|
|
127
151
|
* @attr {string} [loading-more-label='Loading more rows…'] - Accessible label passed to the trailing `eun-loader`
|
|
128
|
-
* @fires {
|
|
129
|
-
* @
|
|
130
|
-
* @
|
|
131
|
-
* @
|
|
132
|
-
* @cssprop [--table-
|
|
133
|
-
* @cssprop [--table-
|
|
134
|
-
* @cssprop [--table-
|
|
135
|
-
* @cssprop [--table-
|
|
136
|
-
* @cssprop [--table-
|
|
152
|
+
* @fires {TableSelectionChangeEvent} euntableselectionchange - Emitted whenever the selection changes, from any source
|
|
153
|
+
* @fires {TableActionEvent} euntableaction - Emitted when a floating action bar action is activated
|
|
154
|
+
* @fires {TableRowClickEvent} euntablerowclick - Emitted on a body row click outside its checkbox, its action cell, and any interactive content, while no row is selected ; cancelable, `preventDefault()` keeps the row's `data-table-row-link` link from being followed
|
|
155
|
+
* @fires {LoadMoreEvent} eunloadmore - Dispatched when `infinite` is set, more rows are needed, and `hasMore` is `true`
|
|
156
|
+
* @cssprop [--table-border-color] - Sets the border color of the frame and the rows
|
|
157
|
+
* @cssprop [--table-background] - Sets the background color of the frame
|
|
158
|
+
* @cssprop [--table-max-height] - Sets a max height, scrolling past it ; `none` by default
|
|
159
|
+
* @cssprop [--table-caption-color] - Sets the text color of the `<caption>`
|
|
160
|
+
* @cssprop [--table-caption-font-size] - Sets the font size of the `<caption>`
|
|
161
|
+
* @cssprop [--table-caption-font-weight] - Sets the font weight of the `<caption>`
|
|
162
|
+
* @cssprop [--table-header-background] - Sets the background color of the header cells
|
|
163
|
+
* @cssprop [--table-footer-background] - Sets the background color of the footer cells
|
|
164
|
+
* @cssprop [--table-row-background] - Sets the background color of the body cells
|
|
165
|
+
* @cssprop [--table-row-hover-background] - Sets the tint of a hovered or focused body row
|
|
166
|
+
* @cssprop [--table-row-selected-background] - Sets the tint of a selected body row
|
|
167
|
+
* @cssprop [--table-row-dragging-background] - Sets the tint of a row being reordered with `createDragReorder`
|
|
168
|
+
* @cssprop [--table-row-transition-duration] - Sets the duration of the hover and selection tint transitions
|
|
169
|
+
* @cssprop [--table-column-color] - Sets the text color of the header cells
|
|
170
|
+
* @cssprop [--table-column-font-weight] - Sets the font weight of the header cells
|
|
171
|
+
* @cssprop [--table-cell-color] - Sets the text color of the cells
|
|
172
|
+
* @cssprop [--table-column-border-color] - Sets the color of a vertical divider between columns ; transparent by default
|
|
173
|
+
* @cssprop [--table-sticky-column-background] - Sets the background color of a sticky column's cells, and of the selection column
|
|
174
|
+
* @cssprop [--table-sticky-row-background] - Sets the background color of the footer cells while `stickyFooter`
|
|
175
|
+
* @cssprop [--table-sticky-border-color] - Sets the color of the edges of a sticky header, footer, or column
|
|
176
|
+
* @cssprop [--table-checkbox-background] - Sets the background color of an unchecked selection checkbox
|
|
177
|
+
* @cssprop [--table-checkbox-border-color] - Sets the border color of an unchecked selection checkbox
|
|
178
|
+
* @cssprop [--table-checkbox-hover] - Sets the background color of an unchecked selection checkbox while hovered
|
|
179
|
+
* @cssprop [--table-action-color] - Sets the text and icon color of a row end action
|
|
180
|
+
* @cssprop [--eun-table-select-col-width] - Sets the width of the selection column ; 40px by default
|
|
181
|
+
* @cssprop [--eun-table-action-col-width] - Sets the width of the row end action column, which stays fixed so a sticky last column lines up with it ; 56px by default, enough for an icon-only button
|
|
182
|
+
* @cssprop [--table-skeleton-stagger] - Delay between each placeholder row's entrance animation, as a CSS time (e.g. `60ms`)
|
|
183
|
+
* @cssprop [--table-skeleton-duration] - Duration of each placeholder row's entrance animation, as a CSS time (e.g. `320ms`)
|
|
184
|
+
* @cssprop [--table-loader-color] - Sets the color of the trailing `eun-loader` shown while `loadingMore`
|
|
185
|
+
* @cssprop [--table-sync-overlay-color] - Sets the highlight color of the `syncing` shimmer sweep
|
|
186
|
+
* @cssprop [--table-sync-duration] - Sets the duration of the `syncing` shimmer sweep, as a CSS time (default `1.6s`)
|
|
137
187
|
* @element eun-table
|
|
138
188
|
* @template T Shape of a data row, in "managed" `columns`/`data` mode.
|
|
139
189
|
*/
|
|
140
|
-
let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement) {
|
|
190
|
+
let EunomiaTable = class EunomiaTable extends LocalizableMixin(LoadMoreSentinelMixin(LitElement)) {
|
|
141
191
|
constructor() {
|
|
142
192
|
super(...arguments);
|
|
143
193
|
/** @default false */
|
|
@@ -149,6 +199,8 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
149
199
|
/** @default false */
|
|
150
200
|
this.stickyHeader = false;
|
|
151
201
|
/** @default false */
|
|
202
|
+
this.stickyFooter = false;
|
|
203
|
+
/** @default false */
|
|
152
204
|
this.stickyFirstColumn = false;
|
|
153
205
|
/** @default false */
|
|
154
206
|
this.stickyLastColumn = false;
|
|
@@ -178,72 +230,50 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
178
230
|
this.loadingMore = false;
|
|
179
231
|
/** @default 400px */
|
|
180
232
|
this.rootMargin = "400px";
|
|
181
|
-
/** @default Loading more rows… */
|
|
182
|
-
this.loadingMoreLabel = "Loading more rows…";
|
|
183
233
|
/** @default [] */
|
|
184
234
|
this.actions = [];
|
|
185
|
-
/** @default selected */
|
|
186
|
-
this.selectedLabel = "selected";
|
|
187
|
-
/** @default Select all */
|
|
188
|
-
this.selectAllLabel = "Select all";
|
|
189
|
-
/** @default Deselect all */
|
|
190
|
-
this.deselectAllLabel = "Deselect all";
|
|
191
|
-
/** @default Select all rows */
|
|
192
|
-
this.selectAllAriaLabel = "Select all rows";
|
|
193
|
-
/** @default Deselect all rows */
|
|
194
|
-
this.deselectAllAriaLabel = "Deselect all rows";
|
|
195
|
-
/** @default Select row */
|
|
196
|
-
this.selectRowAriaLabel = "Select row";
|
|
197
|
-
/** @default Selection actions */
|
|
198
|
-
this.toolbarAriaLabel = "Selection actions";
|
|
199
|
-
/** @default Clear selection */
|
|
200
|
-
this.closeActionBarAriaLabel = "Clear selection";
|
|
201
235
|
/**
|
|
202
236
|
* The rows to render, in "managed" mode (see `columns`).
|
|
203
237
|
* @default []
|
|
204
238
|
*/
|
|
205
239
|
this.data = [];
|
|
206
240
|
/**
|
|
207
|
-
* The current selection,
|
|
208
|
-
*
|
|
209
|
-
* external reads/writes go through the `selectedKeys` accessor, which
|
|
210
|
-
* handles change detection and event dispatch explicitly.
|
|
241
|
+
* The current selection, the source of truth `selectedKeys` reads and
|
|
242
|
+
* writes through.
|
|
211
243
|
* @internal
|
|
212
244
|
*/
|
|
213
245
|
this.internalSelection = new Set();
|
|
214
246
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
247
|
+
* The resolved key of every body row known at the last sync.
|
|
248
|
+
* @internal
|
|
249
|
+
*/
|
|
250
|
+
this.rowKeys = new Map();
|
|
251
|
+
/**
|
|
252
|
+
* Whether `aria-rowcount`/`aria-rowindex` were set for `virtualize`, so
|
|
253
|
+
* they're only ever removed by this component.
|
|
217
254
|
* @internal
|
|
218
255
|
*/
|
|
219
|
-
this.
|
|
256
|
+
this.ariaRowsApplied = false;
|
|
220
257
|
/**
|
|
221
|
-
* Every
|
|
222
|
-
*
|
|
223
|
-
* order — only kept up to date while `virtualize` is set ; `itemEls`
|
|
224
|
-
* alone (mounted-only) is used otherwise. Reconstructed on every
|
|
225
|
-
* legitimate `slotchange` (see {@link syncLogicalItems}) by threading each
|
|
226
|
-
* spacer's cached nodes back into their position, the same reconciliation
|
|
227
|
-
* `eun-infinite-list`'s own `syncItemsFromLightDom` performs.
|
|
258
|
+
* Every body row, mounted or virtualized-out, in document order ; only
|
|
259
|
+
* kept up to date while `virtualize` is set.
|
|
228
260
|
* @internal
|
|
229
261
|
*/
|
|
230
|
-
this.
|
|
262
|
+
this.logicalRows = [];
|
|
231
263
|
/**
|
|
232
|
-
* Page indices currently mounted
|
|
233
|
-
* host, not replaced by a spacer).
|
|
264
|
+
* Page indices currently mounted.
|
|
234
265
|
* @internal
|
|
235
266
|
*/
|
|
236
267
|
this.mountedPages = new Set();
|
|
237
268
|
/**
|
|
238
|
-
* Cached
|
|
239
|
-
*
|
|
240
|
-
* state/listeners inside them are ever lost.
|
|
269
|
+
* Cached rows of each virtualized-out page, reattached as-is once the
|
|
270
|
+
* page remounts.
|
|
241
271
|
* @internal
|
|
242
272
|
*/
|
|
243
273
|
this.detachedByPage = new Map();
|
|
244
274
|
/**
|
|
245
275
|
* Measured height (px) of each page, filled in the first time it's
|
|
246
|
-
* unmounted
|
|
276
|
+
* unmounted.
|
|
247
277
|
* @internal
|
|
248
278
|
*/
|
|
249
279
|
this.pageHeights = [];
|
|
@@ -253,73 +283,81 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
253
283
|
*/
|
|
254
284
|
this.avgRowHeight = DEFAULT_ROW_HEIGHT;
|
|
255
285
|
/**
|
|
256
|
-
*
|
|
257
|
-
* children for `virtualize` (mount/unmount), so the resulting
|
|
258
|
-
* `slotchange` isn't misread as a consumer-driven content change.
|
|
259
|
-
* @internal
|
|
260
|
-
*/
|
|
261
|
-
this.mutatingSlot = false;
|
|
262
|
-
/**
|
|
263
|
-
* Count of `eunloadmore` events dispatched so far ; becomes the event's
|
|
264
|
-
* own `page` field.
|
|
286
|
+
* Count of `eunloadmore` events dispatched so far.
|
|
265
287
|
* @internal
|
|
266
288
|
*/
|
|
267
289
|
this.requestedPages = 0;
|
|
268
290
|
/**
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*/
|
|
273
|
-
this.lastFocusedRowIndex = -1;
|
|
274
|
-
/**
|
|
275
|
-
* Tracks {@link lastFocusedRow}/{@link lastFocusedRowIndex} from any
|
|
276
|
-
* `focusin` landing on a row's own leading stop or its content —
|
|
277
|
-
* `event.target` is that row itself either way, whether directly focused
|
|
278
|
-
* or retargeted through its own shadow root ; slotted content (an
|
|
279
|
-
* `action` button, ...) instead needs `closest`, since it's a light-DOM
|
|
280
|
-
* descendant rather than something the shadow boundary retargets.
|
|
291
|
+
* Re-syncs on structural light DOM changes only: added or removed rows,
|
|
292
|
+
* cells, or sections, and a changed `data-row-key`. A change deeper
|
|
293
|
+
* inside a cell's own content is ignored.
|
|
281
294
|
* @private
|
|
282
295
|
*/
|
|
283
|
-
this.
|
|
284
|
-
const
|
|
285
|
-
|
|
296
|
+
this.handleMutations = (records) => {
|
|
297
|
+
const structural = records.some((record) => {
|
|
298
|
+
if (record.type === "attributes") {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
const target = record.target;
|
|
302
|
+
return (target === this ||
|
|
303
|
+
/^(TABLE|THEAD|TBODY|TFOOT|TR)$/.test(target.nodeName ?? ""));
|
|
304
|
+
});
|
|
305
|
+
if (!structural) {
|
|
286
306
|
return;
|
|
287
307
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
308
|
+
this.sync();
|
|
309
|
+
this.announceLoadedRows();
|
|
310
|
+
if (this.virtualize) {
|
|
311
|
+
this.scheduleAnimationFrame(() => this.syncPages());
|
|
312
|
+
}
|
|
313
|
+
if (this.infinite) {
|
|
314
|
+
this.reobserveSentinel(this.sentinelEl);
|
|
291
315
|
}
|
|
292
|
-
this.lastFocusedRow = row;
|
|
293
|
-
this.lastFocusedRowIndex = index;
|
|
294
316
|
};
|
|
295
317
|
/** @private */
|
|
296
|
-
this.
|
|
297
|
-
|
|
318
|
+
this.handleClick = (event) => {
|
|
319
|
+
const target = event.target;
|
|
320
|
+
const selectCell = target.closest?.(`[${SELECT_ATTR}]`);
|
|
321
|
+
if (selectCell) {
|
|
322
|
+
const checkbox = target.closest("eun-checkbox");
|
|
323
|
+
if (checkbox?.indeterminate) {
|
|
324
|
+
this.toggleSelectAll();
|
|
325
|
+
}
|
|
298
326
|
return;
|
|
299
327
|
}
|
|
300
|
-
|
|
301
|
-
|
|
328
|
+
const row = this.bodyRowOf(target);
|
|
329
|
+
if (!row ||
|
|
330
|
+
target.closest(`[${ACTION_ATTR}]`) ||
|
|
331
|
+
this.isInteractiveClick(event, row)) {
|
|
332
|
+
return;
|
|
302
333
|
}
|
|
303
|
-
this.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
334
|
+
this.activateRow(row, event);
|
|
335
|
+
};
|
|
336
|
+
/** @private */
|
|
337
|
+
this.handleCheckboxChange = (event) => {
|
|
338
|
+
const target = event.target;
|
|
339
|
+
const cell = target.closest?.(`[${SELECT_ATTR}]`);
|
|
340
|
+
if (!cell || target.nodeName !== "EUN-CHECKBOX") {
|
|
341
|
+
return;
|
|
307
342
|
}
|
|
308
|
-
|
|
309
|
-
|
|
343
|
+
const row = cell.parentElement;
|
|
344
|
+
if (row.parentElement?.nodeName === "THEAD") {
|
|
345
|
+
this.toggleSelectAll();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const key = this.rowKeys.get(row);
|
|
349
|
+
if (key !== undefined) {
|
|
350
|
+
this.toggleRow(key);
|
|
310
351
|
}
|
|
311
352
|
};
|
|
312
353
|
/**
|
|
313
|
-
* Re-dispatches `euntableaction` from `eun-table` itself
|
|
314
|
-
*
|
|
315
|
-
* `document.body`), so its own `bubbles: true, composed: false` event
|
|
316
|
-
* never reaches here on its own — the same reasoning `eun-scheduler`'s
|
|
317
|
-
* `handleEditorCreate` documents for its own embedded (non-portaled but
|
|
318
|
-
* still non-composed) editor.
|
|
354
|
+
* Re-dispatches `euntableaction` from `eun-table` itself, since the
|
|
355
|
+
* action bar is a sibling of this element, not a descendant.
|
|
319
356
|
* @private
|
|
320
357
|
*/
|
|
321
358
|
this.handlePortaledAction = (event) => {
|
|
322
359
|
const actionEvent = event;
|
|
360
|
+
event.stopPropagation();
|
|
323
361
|
this.dispatchEvent(new TableActionEvent(actionEvent.key, actionEvent.optionKey));
|
|
324
362
|
};
|
|
325
363
|
/** @private */
|
|
@@ -335,25 +373,37 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
335
373
|
}
|
|
336
374
|
connectedCallback() {
|
|
337
375
|
super.connectedCallback?.();
|
|
338
|
-
|
|
339
|
-
|
|
376
|
+
adoptLightDomStyles(this, tableNativeStyles);
|
|
377
|
+
this.addEventListener("click", this.handleClick);
|
|
378
|
+
this.addEventListener("eunchange", this.handleCheckboxChange);
|
|
379
|
+
this.mutationObserver = new MutationObserver(this.handleMutations);
|
|
380
|
+
this.mutationObserver.observe(this, {
|
|
381
|
+
childList: true,
|
|
382
|
+
subtree: true,
|
|
383
|
+
attributes: true,
|
|
384
|
+
attributeFilter: ["data-row-key"],
|
|
385
|
+
});
|
|
386
|
+
if (this.hasUpdated) {
|
|
387
|
+
this.sync();
|
|
340
388
|
}
|
|
341
|
-
this.addEventListener("focusin", this.handleFocusIn);
|
|
342
389
|
}
|
|
343
390
|
disconnectedCallback() {
|
|
344
|
-
this.removeEventListener("
|
|
345
|
-
this.
|
|
391
|
+
this.removeEventListener("click", this.handleClick);
|
|
392
|
+
this.removeEventListener("eunchange", this.handleCheckboxChange);
|
|
393
|
+
this.mutationObserver?.disconnect();
|
|
394
|
+
this.mutationObserver = undefined;
|
|
346
395
|
this.teardownActionBar();
|
|
347
396
|
this.teardownLoadMoreSentinel();
|
|
348
397
|
this.resizeObserver?.disconnect();
|
|
398
|
+
this.resizeObserver = undefined;
|
|
399
|
+
this.captionObserver?.disconnect();
|
|
400
|
+
this.captionObserver = undefined;
|
|
401
|
+
this.observedCaption = undefined;
|
|
349
402
|
super.disconnectedCallback?.();
|
|
350
403
|
}
|
|
351
404
|
firstUpdated(changed) {
|
|
352
405
|
super.firstUpdated(changed);
|
|
353
|
-
|
|
354
|
-
this.syncLogicalItems();
|
|
355
|
-
}
|
|
356
|
-
this.syncChildren();
|
|
406
|
+
this.sync();
|
|
357
407
|
this.ensureVirtualizeObservers();
|
|
358
408
|
if (this.infinite) {
|
|
359
409
|
this.setupTableLoadObserver();
|
|
@@ -361,33 +411,23 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
361
411
|
}
|
|
362
412
|
updated(changed) {
|
|
363
413
|
super.updated(changed);
|
|
364
|
-
if (changed.has("selectable")) {
|
|
365
|
-
if (this.selectable) {
|
|
366
|
-
this.setAttribute("aria-multiselectable", "true");
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
this.removeAttribute("aria-multiselectable");
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
if (changed.has("syncing")) {
|
|
373
|
-
if (this.syncing) {
|
|
374
|
-
this.setAttribute("aria-busy", "true");
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
this.removeAttribute("aria-busy");
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
414
|
const managedTriggers = ["columns", "data", "rowAction", "rowKey"];
|
|
381
|
-
if (managedTriggers.some((prop) => changed.has(prop))) {
|
|
382
|
-
this.
|
|
415
|
+
if (this.columns && managedTriggers.some((prop) => changed.has(prop))) {
|
|
416
|
+
this.renderManagedTable();
|
|
383
417
|
}
|
|
384
418
|
const syncTriggers = [
|
|
419
|
+
"columns",
|
|
420
|
+
"data",
|
|
421
|
+
"rowAction",
|
|
422
|
+
"rowKey",
|
|
385
423
|
"selectable",
|
|
386
|
-
"checkboxAlwaysVisible",
|
|
387
|
-
"actionAlwaysVisible",
|
|
388
424
|
"stickyHeader",
|
|
389
|
-
"
|
|
390
|
-
"
|
|
425
|
+
"loading",
|
|
426
|
+
"virtualize",
|
|
427
|
+
"infinite",
|
|
428
|
+
"hasMore",
|
|
429
|
+
"skeletonRows",
|
|
430
|
+
"syncing",
|
|
391
431
|
"internalSelection",
|
|
392
432
|
"actions",
|
|
393
433
|
"selectedLabel",
|
|
@@ -398,12 +438,10 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
398
438
|
"selectRowAriaLabel",
|
|
399
439
|
"toolbarAriaLabel",
|
|
400
440
|
"closeActionBarAriaLabel",
|
|
401
|
-
"
|
|
402
|
-
"clickable",
|
|
403
|
-
"syncing",
|
|
441
|
+
"locale",
|
|
404
442
|
];
|
|
405
443
|
if (syncTriggers.some((prop) => changed.has(prop))) {
|
|
406
|
-
this.
|
|
444
|
+
this.sync();
|
|
407
445
|
}
|
|
408
446
|
if (changed.has("virtualize")) {
|
|
409
447
|
this.ensureVirtualizeObservers();
|
|
@@ -414,7 +452,9 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
414
452
|
changed.has("bufferPages"))) {
|
|
415
453
|
this.scheduleAnimationFrame(() => this.syncPages());
|
|
416
454
|
}
|
|
417
|
-
if (changed.has("infinite") ||
|
|
455
|
+
if (changed.has("infinite") ||
|
|
456
|
+
changed.has("rootMargin") ||
|
|
457
|
+
changed.has("loading")) {
|
|
418
458
|
if (this.infinite) {
|
|
419
459
|
this.setupTableLoadObserver();
|
|
420
460
|
}
|
|
@@ -435,255 +475,421 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
435
475
|
this.setSelection(new Set(keys));
|
|
436
476
|
}
|
|
437
477
|
/**
|
|
438
|
-
*
|
|
439
|
-
* `rowAction`/`rowKey` — see the class doc's "Programmatic `columns`/
|
|
440
|
-
* `data`" section. A no-op unless `columns` is set (light-DOM-authored
|
|
441
|
-
* tables never call this). Previously-selected keys that still exist
|
|
442
|
-
* among the regenerated rows stay selected ; ones that don't (a row was
|
|
443
|
-
* removed from `data`) drop out of the selection.
|
|
478
|
+
* The slotted native table.
|
|
444
479
|
* @private
|
|
445
480
|
*/
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
this.
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
481
|
+
get tableEl() {
|
|
482
|
+
return this.querySelector(":scope > table");
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Whether any body row is currently selected.
|
|
486
|
+
* @private
|
|
487
|
+
*/
|
|
488
|
+
get selectionActive() {
|
|
489
|
+
return this.selectable && this.internalSelection.size > 0;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Every visible or accessible text the table renders: its own property
|
|
493
|
+
* when set, else the `locale` dictionary's.
|
|
494
|
+
* @private
|
|
495
|
+
*/
|
|
496
|
+
get labels() {
|
|
497
|
+
const strings = this.dictionary.table;
|
|
498
|
+
return {
|
|
499
|
+
...strings,
|
|
500
|
+
loadingMore: this.loadingMoreLabel ?? strings.loadingMore,
|
|
501
|
+
selected: this.selectedLabel ?? strings.selected,
|
|
502
|
+
selectAll: this.selectAllLabel ?? strings.selectAll,
|
|
503
|
+
deselectAll: this.deselectAllLabel ?? strings.deselectAll,
|
|
504
|
+
selectAllRows: this.selectAllAriaLabel ?? strings.selectAllRows,
|
|
505
|
+
deselectAllRows: this.deselectAllAriaLabel ?? strings.deselectAllRows,
|
|
506
|
+
selectRow: this.selectRowAriaLabel ?? strings.selectRow,
|
|
507
|
+
selectionActions: this.toolbarAriaLabel ?? strings.selectionActions,
|
|
508
|
+
clearSelection: this.closeActionBarAriaLabel ?? strings.clearSelection,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Every body row this table currently knows about: the full logical set
|
|
513
|
+
* (including virtualized-out pages) while `virtualize` is set, the
|
|
514
|
+
* mounted rows otherwise.
|
|
515
|
+
* @private
|
|
516
|
+
*/
|
|
517
|
+
currentRows() {
|
|
470
518
|
if (this.virtualize) {
|
|
471
|
-
|
|
519
|
+
return this.logicalRows;
|
|
472
520
|
}
|
|
473
|
-
|
|
474
|
-
|
|
521
|
+
const table = this.tableEl;
|
|
522
|
+
if (!table) {
|
|
523
|
+
return [];
|
|
475
524
|
}
|
|
525
|
+
return Array.from(table.tBodies)
|
|
526
|
+
.filter((body) => !body.hasAttribute(SKELETON_ATTR))
|
|
527
|
+
.flatMap((body) => Array.from(body.rows))
|
|
528
|
+
.filter((row) => !row.classList.contains(SPACER_CLASS));
|
|
476
529
|
}
|
|
477
530
|
/**
|
|
478
|
-
*
|
|
479
|
-
* logical set (including virtualized-out pages) while `virtualize` is
|
|
480
|
-
* set, the mounted-only `itemEls` otherwise.
|
|
531
|
+
* The body section `virtualize` operates on.
|
|
481
532
|
* @private
|
|
482
533
|
*/
|
|
483
|
-
|
|
484
|
-
|
|
534
|
+
get bodyEl() {
|
|
535
|
+
const table = this.tableEl;
|
|
536
|
+
return table
|
|
537
|
+
? Array.from(table.tBodies).find((body) => !body.hasAttribute(SKELETON_ATTR))
|
|
538
|
+
: undefined;
|
|
485
539
|
}
|
|
486
540
|
/**
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* fall back to the document body. Left alone if focus already landed
|
|
492
|
-
* somewhere else on its own (the consumer moved it deliberately before
|
|
493
|
-
* the removal), detected by the document's active element no longer
|
|
494
|
-
* being the body.
|
|
541
|
+
* Pushes the selection and configuration state down onto the slotted
|
|
542
|
+
* table: generated selection cells, row state, action cells, the
|
|
543
|
+
* loading placeholder body, and the action bar. Its own mutations are
|
|
544
|
+
* dropped from the observer queue so they never trigger another sync.
|
|
495
545
|
* @private
|
|
496
546
|
*/
|
|
497
|
-
|
|
498
|
-
if (
|
|
547
|
+
sync() {
|
|
548
|
+
if (this.virtualize) {
|
|
549
|
+
this.syncLogicalRows();
|
|
550
|
+
}
|
|
551
|
+
const table = this.tableEl;
|
|
552
|
+
if (table) {
|
|
553
|
+
this.syncHeader(table);
|
|
554
|
+
this.syncFooter(table);
|
|
555
|
+
this.syncRows(this.currentRows());
|
|
556
|
+
this.syncSkeleton(table);
|
|
557
|
+
this.syncAriaRows(table);
|
|
558
|
+
if (this.syncing || this.loading) {
|
|
559
|
+
table.setAttribute("aria-busy", "true");
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
table.removeAttribute("aria-busy");
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
this.watchCaption(table?.caption ?? undefined);
|
|
566
|
+
this.toggleAttribute("selection-active", this.selectionActive);
|
|
567
|
+
this.syncActionBar();
|
|
568
|
+
this.mutationObserver?.takeRecords();
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Reserves the height of the table's `<caption>` above the frame, where
|
|
572
|
+
* the light DOM sheet positions it, and keeps it up to date as the
|
|
573
|
+
* caption resizes.
|
|
574
|
+
* @private
|
|
575
|
+
*/
|
|
576
|
+
watchCaption(caption) {
|
|
577
|
+
if (caption === this.observedCaption) {
|
|
499
578
|
return;
|
|
500
579
|
}
|
|
501
|
-
|
|
502
|
-
this.
|
|
503
|
-
|
|
504
|
-
|
|
580
|
+
this.captionObserver?.disconnect();
|
|
581
|
+
this.observedCaption = caption;
|
|
582
|
+
if (!caption) {
|
|
583
|
+
this.style.removeProperty("--_table-caption-height");
|
|
505
584
|
return;
|
|
506
585
|
}
|
|
507
|
-
|
|
586
|
+
const reserve = () => {
|
|
587
|
+
this.style.setProperty("--_table-caption-height", `${caption.getBoundingClientRect().height}px`);
|
|
588
|
+
};
|
|
589
|
+
this.captionObserver ??= new ResizeObserver(() => this.observedCaption ? reserve() : undefined);
|
|
590
|
+
this.captionObserver.observe(caption);
|
|
591
|
+
reserve();
|
|
508
592
|
}
|
|
509
593
|
/**
|
|
510
|
-
*
|
|
511
|
-
*
|
|
512
|
-
* header's own `MutationObserver`, {@link regenerateManagedChildren}) and
|
|
513
|
-
* whenever a reactive property that affects children changes (see
|
|
514
|
-
* {@link updated}).
|
|
594
|
+
* Adds the selection column's leading cell to `row` if missing, and
|
|
595
|
+
* returns it.
|
|
515
596
|
* @private
|
|
516
597
|
*/
|
|
517
|
-
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
598
|
+
ensureSelectCell(row, tagName) {
|
|
599
|
+
const first = row.cells[0];
|
|
600
|
+
if (first?.hasAttribute(SELECT_ATTR)) {
|
|
601
|
+
return first;
|
|
602
|
+
}
|
|
603
|
+
const cell = document.createElement(tagName);
|
|
604
|
+
cell.setAttribute(SELECT_ATTR, "");
|
|
605
|
+
row.prepend(cell);
|
|
606
|
+
return cell;
|
|
607
|
+
}
|
|
608
|
+
/** @private */
|
|
609
|
+
removeSelectCell(row) {
|
|
610
|
+
const first = row.cells[0];
|
|
611
|
+
if (first?.hasAttribute(SELECT_ATTR)) {
|
|
612
|
+
first.remove();
|
|
613
|
+
}
|
|
525
614
|
}
|
|
526
615
|
/**
|
|
527
|
-
*
|
|
528
|
-
* a different element than last time.
|
|
616
|
+
* Returns the checkbox inside a selection cell, creating it if missing.
|
|
529
617
|
* @private
|
|
530
618
|
*/
|
|
531
|
-
|
|
532
|
-
|
|
619
|
+
ensureCheckbox(cell) {
|
|
620
|
+
let checkbox = cell.querySelector("eun-checkbox");
|
|
621
|
+
if (!checkbox) {
|
|
622
|
+
checkbox = document.createElement("eun-checkbox");
|
|
623
|
+
checkbox.setAttribute("tabindex", "0");
|
|
624
|
+
cell.replaceChildren(checkbox);
|
|
625
|
+
}
|
|
626
|
+
return checkbox;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Adds or removes the header's selection cell, holding the select-all
|
|
630
|
+
* checkbox.
|
|
631
|
+
* @private
|
|
632
|
+
*/
|
|
633
|
+
syncHeader(table) {
|
|
634
|
+
const headerRows = table.tHead ? Array.from(table.tHead.rows) : [];
|
|
635
|
+
const [firstRow, ...otherRows] = headerRows;
|
|
636
|
+
otherRows.forEach((row) => this.removeSelectCell(row));
|
|
637
|
+
if (!firstRow) {
|
|
533
638
|
return;
|
|
534
639
|
}
|
|
535
|
-
this.
|
|
536
|
-
|
|
537
|
-
if (!header) {
|
|
640
|
+
if (!this.selectable) {
|
|
641
|
+
this.removeSelectCell(firstRow);
|
|
538
642
|
return;
|
|
539
643
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
644
|
+
const cell = this.ensureSelectCell(firstRow, "th");
|
|
645
|
+
cell.setAttribute("scope", "col");
|
|
646
|
+
cell.rowSpan = headerRows.length;
|
|
647
|
+
const labels = this.labels;
|
|
648
|
+
const total = this.currentRows().length;
|
|
649
|
+
const selectedCount = this.internalSelection.size;
|
|
650
|
+
const allSelected = total > 0 && selectedCount === total;
|
|
651
|
+
const checkbox = this.ensureCheckbox(cell);
|
|
652
|
+
checkbox.checked = allSelected;
|
|
653
|
+
checkbox.indeterminate = selectedCount > 0 && !allSelected;
|
|
654
|
+
checkbox.disabled = total === 0;
|
|
655
|
+
checkbox.setAttribute("aria-label", allSelected ? labels.deselectAllRows : labels.selectAllRows);
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Keeps footer rows aligned with an empty selection cell.
|
|
659
|
+
* @private
|
|
660
|
+
*/
|
|
661
|
+
syncFooter(table) {
|
|
662
|
+
const rows = table.tFoot ? Array.from(table.tFoot.rows) : [];
|
|
663
|
+
rows.forEach((row) => {
|
|
664
|
+
if (this.selectable) {
|
|
665
|
+
this.ensureSelectCell(row, "td").replaceChildren();
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
this.removeSelectCell(row);
|
|
669
|
+
}
|
|
546
670
|
});
|
|
547
671
|
}
|
|
548
672
|
/**
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
* item currently has action content — see the class doc's CSS Subgrid
|
|
552
|
-
* section.
|
|
673
|
+
* Resolves each body row's key and pushes its selection and action cell
|
|
674
|
+
* state.
|
|
553
675
|
* @private
|
|
554
676
|
*/
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
selectable
|
|
563
|
-
|
|
677
|
+
syncRows(rows) {
|
|
678
|
+
const rowKeys = new Map();
|
|
679
|
+
const selectionActive = this.selectionActive;
|
|
680
|
+
const labels = this.labels;
|
|
681
|
+
rows.forEach((row, index) => {
|
|
682
|
+
const key = resolveRowKey(row.dataset.rowKey, index);
|
|
683
|
+
rowKeys.set(row, key);
|
|
684
|
+
const selected = this.selectable && this.internalSelection.has(key);
|
|
685
|
+
row.toggleAttribute(SELECTED_ATTR, selected);
|
|
686
|
+
if (this.selectable) {
|
|
687
|
+
const checkbox = this.ensureCheckbox(this.ensureSelectCell(row, "td"));
|
|
688
|
+
checkbox.checked = selected;
|
|
689
|
+
checkbox.setAttribute("aria-label", `${labels.selectRow} ${this.rowName(row) ?? index + 1}`);
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
this.removeSelectCell(row);
|
|
693
|
+
}
|
|
694
|
+
for (const cell of Array.from(row.cells)) {
|
|
695
|
+
if (cell.hasAttribute(ACTION_ATTR)) {
|
|
696
|
+
cell.inert = selectionActive;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
564
699
|
});
|
|
565
|
-
this.
|
|
700
|
+
this.rowKeys = rowKeys;
|
|
566
701
|
}
|
|
567
|
-
/**
|
|
568
|
-
|
|
569
|
-
|
|
702
|
+
/**
|
|
703
|
+
* The name of a body row: the text of its row header (`<th scope="row">`,
|
|
704
|
+
* or else its first `<th>`), used to label its checkbox.
|
|
705
|
+
* @private
|
|
706
|
+
*/
|
|
707
|
+
rowName(row) {
|
|
708
|
+
const header = row.querySelector(':scope > th[scope="row"]') ??
|
|
709
|
+
row.querySelector(`:scope > th:not([${SELECT_ATTR}])`);
|
|
710
|
+
const name = header?.textContent?.replace(/\s+/g, " ").trim();
|
|
711
|
+
return name || undefined;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Gives every row its position and the table its total row count while
|
|
715
|
+
* `virtualize` is set, so assistive technology announces the real size
|
|
716
|
+
* of the table even though only part of its rows are in the DOM. The
|
|
717
|
+
* count is `-1` (unknown) while `infinite` can still load more.
|
|
718
|
+
* @private
|
|
719
|
+
*/
|
|
720
|
+
syncAriaRows(table) {
|
|
721
|
+
if (!this.virtualize) {
|
|
722
|
+
if (this.ariaRowsApplied) {
|
|
723
|
+
table.removeAttribute("aria-rowcount");
|
|
724
|
+
table
|
|
725
|
+
.querySelectorAll("tr[aria-rowindex]")
|
|
726
|
+
.forEach((row) => row.removeAttribute("aria-rowindex"));
|
|
727
|
+
this.ariaRowsApplied = false;
|
|
728
|
+
}
|
|
570
729
|
return;
|
|
571
730
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
header.deselectAllAriaLabel = this.deselectAllAriaLabel;
|
|
581
|
-
header.onSelectAllToggle = () => this.toggleSelectAll();
|
|
582
|
-
header.requestAdjacentRow = (direction) => this.moveFocus(this.rowIndexOf(header), direction);
|
|
583
|
-
header.requestGridEdge = (edge) => this.moveToGridEdge(edge);
|
|
731
|
+
const rows = [
|
|
732
|
+
...(table.tHead ? Array.from(table.tHead.rows) : []),
|
|
733
|
+
...this.logicalRows,
|
|
734
|
+
...(table.tFoot ? Array.from(table.tFoot.rows) : []),
|
|
735
|
+
];
|
|
736
|
+
table.setAttribute("aria-rowcount", this.infinite && this.hasMore ? "-1" : String(rows.length));
|
|
737
|
+
rows.forEach((row, index) => row.setAttribute("aria-rowindex", String(index + 1)));
|
|
738
|
+
this.ariaRowsApplied = true;
|
|
584
739
|
}
|
|
585
|
-
/**
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
item.selectionActive = this.selectable && this.internalSelection.size > 0;
|
|
600
|
-
item.selectCheckboxLabel = `${this.selectRowAriaLabel} ${index + 1}`;
|
|
601
|
-
item.onToggleSelected = () => this.toggleRow(key);
|
|
602
|
-
item.requestAdjacentRow = (direction) => this.moveFocus(this.rowIndexOf(item), direction);
|
|
603
|
-
item.requestGridEdge = (edge) => this.moveToGridEdge(edge);
|
|
604
|
-
});
|
|
740
|
+
/**
|
|
741
|
+
* Announces how many rows the last `eunloadmore` added, once they're in.
|
|
742
|
+
* @private
|
|
743
|
+
*/
|
|
744
|
+
announceLoadedRows() {
|
|
745
|
+
if (this.rowCountBeforeLoad === undefined || !this.announcerEl) {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
const added = this.currentRows().length - this.rowCountBeforeLoad;
|
|
749
|
+
if (added <= 0) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
this.rowCountBeforeLoad = undefined;
|
|
753
|
+
this.announcerEl.textContent = this.dictionary.table.rowsLoaded(added);
|
|
605
754
|
}
|
|
606
755
|
/**
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
* is set, since they're hidden (`display: none`) and shouldn't be
|
|
610
|
-
* reachable ; otherwise the full logical set (mounted or virtualized-out)
|
|
611
|
-
* while `virtualize` is on, so `Ctrl+End`/`ArrowDown` math stays correct
|
|
612
|
-
* regardless of what's currently mounted (see {@link ensureRowMounted}).
|
|
756
|
+
* Adds the placeholder body while `loading`, shaped after the header's
|
|
757
|
+
* own cells so its columns line up, and removes it otherwise.
|
|
613
758
|
* @private
|
|
614
759
|
*/
|
|
615
|
-
|
|
616
|
-
const
|
|
617
|
-
if (this.loading) {
|
|
618
|
-
|
|
760
|
+
syncSkeleton(table) {
|
|
761
|
+
const existing = table.querySelector(`:scope > tbody[${SKELETON_ATTR}]`);
|
|
762
|
+
if (!this.loading) {
|
|
763
|
+
existing?.remove();
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
const headerCells = table.tHead?.rows[0]
|
|
767
|
+
? Array.from(table.tHead.rows[0].cells).filter((cell) => !cell.hasAttribute(SELECT_ATTR))
|
|
768
|
+
: [];
|
|
769
|
+
const signature = [
|
|
770
|
+
this.selectable,
|
|
771
|
+
this.skeletonRows,
|
|
772
|
+
...headerCells.map((cell) => `${cell.colSpan}${cell.hasAttribute(ACTION_ATTR) ? "a" : ""}`),
|
|
773
|
+
].join(",");
|
|
774
|
+
if (existing?.dataset.tableSkeleton === signature) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
const body = document.createElement("tbody");
|
|
778
|
+
body.setAttribute(SKELETON_ATTR, signature);
|
|
779
|
+
body.setAttribute("aria-hidden", "true");
|
|
780
|
+
for (let index = 0; index < this.skeletonRows; index++) {
|
|
781
|
+
const row = body.insertRow();
|
|
782
|
+
row.style.setProperty("--_row-index", String(index));
|
|
783
|
+
if (this.selectable) {
|
|
784
|
+
const cell = row.insertCell();
|
|
785
|
+
cell.setAttribute(SELECT_ATTR, "");
|
|
786
|
+
cell.append(this.createSkeleton("18px", "18px", "4px"));
|
|
787
|
+
}
|
|
788
|
+
for (const headerCell of headerCells) {
|
|
789
|
+
const cell = row.insertCell();
|
|
790
|
+
cell.colSpan = headerCell.colSpan;
|
|
791
|
+
if (headerCell.hasAttribute(ACTION_ATTR)) {
|
|
792
|
+
cell.setAttribute(ACTION_ATTR, "");
|
|
793
|
+
cell.append(this.createSkeleton("28px", "28px", "8px"));
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
cell.append(this.createSkeleton("50%", "14px", "4px"));
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (existing) {
|
|
801
|
+
existing.replaceWith(body);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
const bodies = Array.from(table.tBodies);
|
|
805
|
+
const lastBody = bodies[bodies.length - 1];
|
|
806
|
+
if (lastBody) {
|
|
807
|
+
lastBody.after(body);
|
|
808
|
+
}
|
|
809
|
+
else if (table.tFoot) {
|
|
810
|
+
table.tFoot.before(body);
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
table.append(body);
|
|
619
814
|
}
|
|
620
|
-
const items = this.currentItems();
|
|
621
|
-
return header ? [header, ...items] : [...items];
|
|
622
815
|
}
|
|
623
816
|
/** @private */
|
|
624
|
-
|
|
625
|
-
|
|
817
|
+
createSkeleton(width, height, radius) {
|
|
818
|
+
const skeleton = document.createElement("eun-skeleton");
|
|
819
|
+
skeleton.setAttribute("variant", "rect");
|
|
820
|
+
skeleton.setAttribute("width", width);
|
|
821
|
+
skeleton.setAttribute("height", height);
|
|
822
|
+
skeleton.setAttribute("radius", radius);
|
|
823
|
+
if (width.endsWith("%")) {
|
|
824
|
+
skeleton.style.width = width;
|
|
825
|
+
}
|
|
826
|
+
return skeleton;
|
|
626
827
|
}
|
|
627
828
|
/**
|
|
628
|
-
*
|
|
629
|
-
* delegated up from a row's own `TableRowMixin`. Every row is always its
|
|
630
|
-
* own permanent `Tab` stop (see `TableRowMixin`'s own class doc), so this
|
|
631
|
-
* only ever needs to resolve *which* row and hand it a plain `.focus()`,
|
|
632
|
-
* no column bookkeeping of any kind.
|
|
829
|
+
* The body row `target` belongs to, if any.
|
|
633
830
|
* @private
|
|
634
831
|
*/
|
|
635
|
-
|
|
636
|
-
|
|
832
|
+
bodyRowOf(target) {
|
|
833
|
+
const row = target.closest?.("tr");
|
|
834
|
+
return row && this.rowKeys.has(row) ? row : undefined;
|
|
637
835
|
}
|
|
638
836
|
/**
|
|
639
|
-
*
|
|
837
|
+
* Whether the click went to interactive content of `row` (a link, a
|
|
838
|
+
* button, an input, a nested eunomia control) rather than to the row.
|
|
640
839
|
* @private
|
|
641
840
|
*/
|
|
642
|
-
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
|
|
841
|
+
isInteractiveClick(event, row) {
|
|
842
|
+
for (const node of event.composedPath()) {
|
|
843
|
+
if (node === row) {
|
|
844
|
+
return false;
|
|
845
|
+
}
|
|
846
|
+
if (node instanceof Element && node.matches(INTERACTIVE_SELECTOR)) {
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
646
849
|
}
|
|
647
|
-
|
|
850
|
+
return false;
|
|
648
851
|
}
|
|
649
852
|
/**
|
|
650
|
-
*
|
|
651
|
-
*
|
|
853
|
+
* Toggles a row while rows are selected, otherwise fires
|
|
854
|
+
* {@link TableRowClickEvent}.
|
|
652
855
|
* @private
|
|
653
856
|
*/
|
|
654
|
-
|
|
655
|
-
const
|
|
656
|
-
if (
|
|
857
|
+
activateRow(row, event) {
|
|
858
|
+
const key = this.rowKeys.get(row) ?? "";
|
|
859
|
+
if (this.selectionActive) {
|
|
860
|
+
this.toggleRow(key);
|
|
657
861
|
return;
|
|
658
862
|
}
|
|
659
|
-
const
|
|
660
|
-
this.
|
|
661
|
-
|
|
863
|
+
const rowClick = new TableRowClickEvent(key);
|
|
864
|
+
this.dispatchEvent(rowClick);
|
|
865
|
+
if (!rowClick.defaultPrevented) {
|
|
866
|
+
this.followRowLink(row, event);
|
|
867
|
+
}
|
|
662
868
|
}
|
|
663
869
|
/**
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
* `Ctrl+End`/a long `ArrowDown` run can target a row several pages away
|
|
668
|
-
* from what's currently mounted.
|
|
870
|
+
* Follows the row's `data-table-row-link` link, if any, keeping the
|
|
871
|
+
* modifier keys so a `Ctrl`/`Cmd` click still opens a new tab. The link
|
|
872
|
+
* stays the row's one keyboard-reachable way to do the same.
|
|
669
873
|
* @private
|
|
670
874
|
*/
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
675
|
-
const row = rows[rowIndex];
|
|
676
|
-
if (!row || row.isConnected) {
|
|
875
|
+
followRowLink(row, event) {
|
|
876
|
+
const marker = row.querySelector(`[${ROW_LINK_ATTR}]`);
|
|
877
|
+
if (!marker) {
|
|
677
878
|
return;
|
|
678
879
|
}
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
880
|
+
const link = (marker.matches("a[href]") ? marker : null) ??
|
|
881
|
+
marker.querySelector("a[href]") ??
|
|
882
|
+
marker.shadowRoot?.querySelector("a[href]") ??
|
|
883
|
+
marker;
|
|
884
|
+
link.dispatchEvent(new MouseEvent("click", {
|
|
885
|
+
bubbles: true,
|
|
886
|
+
cancelable: true,
|
|
887
|
+
composed: true,
|
|
888
|
+
ctrlKey: event.ctrlKey,
|
|
889
|
+
metaKey: event.metaKey,
|
|
890
|
+
shiftKey: event.shiftKey,
|
|
891
|
+
altKey: event.altKey,
|
|
892
|
+
}));
|
|
687
893
|
}
|
|
688
894
|
/** @private */
|
|
689
895
|
toggleRow(key) {
|
|
@@ -698,21 +904,13 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
698
904
|
}
|
|
699
905
|
/** @private */
|
|
700
906
|
toggleSelectAll() {
|
|
701
|
-
const
|
|
702
|
-
const allSelected =
|
|
703
|
-
|
|
704
|
-
this.setSelection(new Set());
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
this.setSelection(new Set(items.map((item, index) => resolveRowKey(item.rowKey, index))));
|
|
907
|
+
const keys = Array.from(this.rowKeys.values());
|
|
908
|
+
const allSelected = keys.length > 0 && keys.every((key) => this.internalSelection.has(key));
|
|
909
|
+
this.setSelection(allSelected ? new Set() : new Set(keys));
|
|
708
910
|
}
|
|
709
911
|
/**
|
|
710
|
-
* Applies a new selection and fires {@link TableSelectionChangeEvent}
|
|
711
|
-
* the
|
|
712
|
-
* an external `selectedKeys` assignment funnel through, so the event
|
|
713
|
-
* fires consistently either way (the same "always fires, whatever the
|
|
714
|
-
* source" convention `eun-scheduler`'s own `eunperiodchange` uses for its
|
|
715
|
-
* controlled `view`/`displayedDate`).
|
|
912
|
+
* Applies a new selection and fires {@link TableSelectionChangeEvent},
|
|
913
|
+
* whatever the source.
|
|
716
914
|
* @private
|
|
717
915
|
*/
|
|
718
916
|
setSelection(next) {
|
|
@@ -720,25 +918,27 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
720
918
|
this.dispatchEvent(new TableSelectionChangeEvent(Array.from(next)));
|
|
721
919
|
}
|
|
722
920
|
/**
|
|
723
|
-
* Creates the
|
|
921
|
+
* Creates the action bar the first time it's needed, right after the
|
|
922
|
+
* table so it comes next in the `Tab` order, and shows it as a manual
|
|
923
|
+
* popover so it renders above the page whatever the table's ancestors
|
|
924
|
+
* clip or transform.
|
|
724
925
|
* @private
|
|
725
926
|
*/
|
|
726
927
|
ensureActionBar() {
|
|
727
928
|
if (!this.actionBarEl) {
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
929
|
+
const bar = document.createElement(EunomiaTableActionBarTagName);
|
|
930
|
+
bar.setAttribute("popover", "manual");
|
|
931
|
+
bar.addEventListener(TableActionEvent.eventName, this.handlePortaledAction);
|
|
932
|
+
this.after(bar);
|
|
933
|
+
bar.showPopover?.();
|
|
934
|
+
this.actionBarEl = bar;
|
|
731
935
|
}
|
|
732
936
|
return this.actionBarEl;
|
|
733
937
|
}
|
|
734
938
|
/**
|
|
735
|
-
* Tears down the
|
|
736
|
-
*
|
|
737
|
-
*
|
|
738
|
-
* (see {@link restoreFocusIfLost}) — except the bar lives outside this
|
|
739
|
-
* component's own DOM subtree entirely, so that row-focused mechanism
|
|
740
|
-
* can't see it ; this restores focus back onto the grid itself (its
|
|
741
|
-
* header, or its first row absent one) instead.
|
|
939
|
+
* Tears down the action bar. If focus was inside it, it
|
|
940
|
+
* moves back to the table's first selection checkbox rather than
|
|
941
|
+
* falling to the document body.
|
|
742
942
|
* @private
|
|
743
943
|
*/
|
|
744
944
|
teardownActionBar() {
|
|
@@ -751,16 +951,16 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
751
951
|
this.actionBarEl.remove();
|
|
752
952
|
this.actionBarEl = undefined;
|
|
753
953
|
if (hadFocus) {
|
|
754
|
-
this.
|
|
954
|
+
this.querySelector(`[${SELECT_ATTR}] eun-checkbox:not([disabled])`)?.focus();
|
|
755
955
|
}
|
|
756
956
|
}
|
|
757
957
|
/**
|
|
758
|
-
* Mounts
|
|
759
|
-
* selection.
|
|
958
|
+
* Mounts, updates, or unmounts the floating action bar based on the
|
|
959
|
+
* current selection.
|
|
760
960
|
* @private
|
|
761
961
|
*/
|
|
762
962
|
syncActionBar() {
|
|
763
|
-
if (!this.
|
|
963
|
+
if (!this.selectionActive) {
|
|
764
964
|
this.teardownActionBar();
|
|
765
965
|
return;
|
|
766
966
|
}
|
|
@@ -770,41 +970,142 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
770
970
|
document.addEventListener("keydown", this.handleEscapeClear);
|
|
771
971
|
}
|
|
772
972
|
bar.selectedCount = this.internalSelection.size;
|
|
773
|
-
bar.totalCount = this.
|
|
973
|
+
bar.totalCount = this.rowKeys.size;
|
|
774
974
|
bar.actions = this.actions;
|
|
775
|
-
|
|
776
|
-
bar.
|
|
777
|
-
bar.
|
|
778
|
-
bar.
|
|
779
|
-
bar.
|
|
975
|
+
const labels = this.labels;
|
|
976
|
+
bar.toolbarAriaLabel = labels.selectionActions;
|
|
977
|
+
bar.selectedLabel = labels.selected;
|
|
978
|
+
bar.selectAllLabel = labels.selectAll;
|
|
979
|
+
bar.deselectAllLabel = labels.deselectAll;
|
|
980
|
+
bar.closeAriaLabel = labels.clearSelection;
|
|
780
981
|
bar.onSelectAll = () => this.toggleSelectAll();
|
|
781
982
|
bar.onClose = () => this.setSelection(new Set());
|
|
782
983
|
}
|
|
783
984
|
/**
|
|
784
|
-
*
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
|
|
789
|
-
|
|
985
|
+
* Renders the native table from `columns`/`data`/`rowAction`/`rowKey`
|
|
986
|
+
* into this element's light DOM. Previously selected keys that no
|
|
987
|
+
* longer match a row drop out of the selection.
|
|
988
|
+
* @private
|
|
989
|
+
*/
|
|
990
|
+
renderManagedTable() {
|
|
991
|
+
const columns = this.columns ?? [];
|
|
992
|
+
const keys = this.data.map((row, index) => this.rowKey ? this.rowKey(row, index) : resolveRowKey(undefined, index));
|
|
993
|
+
this.mountAllPages();
|
|
994
|
+
render(html `<table>
|
|
995
|
+
<thead>
|
|
996
|
+
<tr>
|
|
997
|
+
${columns.map((column) => html `<th
|
|
998
|
+
scope="col"
|
|
999
|
+
style=${ifDefined(this.columnStyle(column, true))}
|
|
1000
|
+
aria-sort=${ifDefined(column.sort)}
|
|
1001
|
+
>
|
|
1002
|
+
${column.label}
|
|
1003
|
+
</th>`)}
|
|
1004
|
+
${this.rowAction
|
|
1005
|
+
? html `<th scope="col" data-table-action>
|
|
1006
|
+
<span class="eun-table-visually-hidden"
|
|
1007
|
+
>${this.rowAction.label ?? this.labels.rowActions}</span
|
|
1008
|
+
>
|
|
1009
|
+
</th>`
|
|
1010
|
+
: nothing}
|
|
1011
|
+
</tr>
|
|
1012
|
+
</thead>
|
|
1013
|
+
<tbody>
|
|
1014
|
+
${repeat(this.data, (_, index) => keys[index], (row, index) => html `<tr data-row-key=${keys[index]}>
|
|
1015
|
+
${columns.map((column) => html `<td
|
|
1016
|
+
style=${ifDefined(this.columnStyle(column, false))}
|
|
1017
|
+
>
|
|
1018
|
+
${this.renderManagedCell(column, row, index)}
|
|
1019
|
+
</td>`)}
|
|
1020
|
+
${this.rowAction
|
|
1021
|
+
? html `<td data-table-action>
|
|
1022
|
+
${this.renderRowAction(this.rowAction, row, index)}
|
|
1023
|
+
</td>`
|
|
1024
|
+
: nothing}
|
|
1025
|
+
</tr>`)}
|
|
1026
|
+
</tbody>
|
|
1027
|
+
</table>`, this);
|
|
1028
|
+
const stillPresent = new Set(keys);
|
|
1029
|
+
const preserved = new Set([...this.internalSelection].filter((key) => stillPresent.has(key)));
|
|
1030
|
+
if (preserved.size !== this.internalSelection.size) {
|
|
1031
|
+
this.internalSelection = preserved;
|
|
1032
|
+
}
|
|
1033
|
+
if (this.virtualize) {
|
|
1034
|
+
this.scheduleAnimationFrame(() => this.syncPages());
|
|
1035
|
+
}
|
|
1036
|
+
if (this.infinite) {
|
|
1037
|
+
this.reobserveSentinel(this.sentinelEl);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
/** @private */
|
|
1041
|
+
columnStyle(column, header) {
|
|
1042
|
+
const declarations = [];
|
|
1043
|
+
if (header && column.width) {
|
|
1044
|
+
declarations.push(`width: ${column.width}`);
|
|
1045
|
+
}
|
|
1046
|
+
const align = alignToTextAlign(column.align);
|
|
1047
|
+
if (align) {
|
|
1048
|
+
declarations.push(`text-align: ${align}`);
|
|
1049
|
+
}
|
|
1050
|
+
return declarations.length ? declarations.join("; ") : undefined;
|
|
1051
|
+
}
|
|
1052
|
+
/** @private */
|
|
1053
|
+
renderManagedCell(column, row, index) {
|
|
1054
|
+
const value = row[column.key];
|
|
1055
|
+
if (column.render) {
|
|
1056
|
+
return column.render(value, row, index);
|
|
1057
|
+
}
|
|
1058
|
+
return value === null || value === undefined ? "" : String(value);
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Renders a row's `rowAction`: a `eun-dropdown-button` for
|
|
1062
|
+
* `type: "dropdown"`, a `eun-button` otherwise.
|
|
1063
|
+
* @private
|
|
1064
|
+
*/
|
|
1065
|
+
renderRowAction(action, row, index) {
|
|
1066
|
+
if (action.type === "dropdown") {
|
|
1067
|
+
return html `<eun-dropdown-button
|
|
1068
|
+
size="xs"
|
|
1069
|
+
appearance="ghost"
|
|
1070
|
+
icon=${ifDefined(action.icon)}
|
|
1071
|
+
label=${ifDefined(action.icon ? undefined : action.label)}
|
|
1072
|
+
aria-label=${action.label ?? this.labels.rowActions}
|
|
1073
|
+
.options=${action.options(row)}
|
|
1074
|
+
.disabledKeys=${action.disabledKeys?.(row) ?? []}
|
|
1075
|
+
?disabled=${action.disabled?.(row) ?? false}
|
|
1076
|
+
@eunselect=${(event) => action.onSelect(event.key, row, index)}
|
|
1077
|
+
></eun-dropdown-button>`;
|
|
1078
|
+
}
|
|
1079
|
+
return html `<eun-button
|
|
1080
|
+
size="xs"
|
|
1081
|
+
appearance=${action.color ? "default" : "ghost"}
|
|
1082
|
+
color=${ifDefined(action.color)}
|
|
1083
|
+
aria-label=${action.label}
|
|
1084
|
+
?disabled=${action.disabled?.(row) ?? false}
|
|
1085
|
+
@click=${() => action.onClick(row, index)}
|
|
1086
|
+
>
|
|
1087
|
+
${action.icon
|
|
1088
|
+
? html `<eun-icon name=${action.icon} size="16"></eun-icon>`
|
|
1089
|
+
: action.label}
|
|
1090
|
+
</eun-button>`;
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Rebuilds {@link logicalRows} from the body, threading each spacer's
|
|
1094
|
+
* cached rows back into their position, and recomputes
|
|
1095
|
+
* {@link mountedPages}.
|
|
790
1096
|
* @private
|
|
791
1097
|
*/
|
|
792
|
-
|
|
1098
|
+
syncLogicalRows() {
|
|
793
1099
|
const rebuilt = [];
|
|
794
|
-
for (const
|
|
795
|
-
if (
|
|
796
|
-
|
|
1100
|
+
for (const row of Array.from(this.bodyEl?.rows ?? [])) {
|
|
1101
|
+
if (row.classList.contains(SPACER_CLASS)) {
|
|
1102
|
+
rebuilt.push(...(this.detachedByPage.get(Number(row.dataset.eunPage)) ?? []));
|
|
797
1103
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
rebuilt.push(...(this.detachedByPage.get(page) ?? []));
|
|
801
|
-
continue;
|
|
802
|
-
}
|
|
803
|
-
if (child.tagName.toLowerCase() === EunomiaTableItemTagName) {
|
|
804
|
-
rebuilt.push(child);
|
|
1104
|
+
else {
|
|
1105
|
+
rebuilt.push(row);
|
|
805
1106
|
}
|
|
806
1107
|
}
|
|
807
|
-
this.
|
|
1108
|
+
this.logicalRows = rebuilt;
|
|
808
1109
|
const totalPages = Math.ceil(rebuilt.length / this.pageSize);
|
|
809
1110
|
const mountedPages = new Set();
|
|
810
1111
|
for (let page = 0; page < totalPages; page++) {
|
|
@@ -814,14 +1115,27 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
814
1115
|
}
|
|
815
1116
|
this.mountedPages = mountedPages;
|
|
816
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Remounts every virtualized-out page, before the light DOM gets
|
|
1120
|
+
* re-rendered wholesale.
|
|
1121
|
+
* @private
|
|
1122
|
+
*/
|
|
1123
|
+
mountAllPages() {
|
|
1124
|
+
for (const page of Array.from(this.detachedByPage.keys())) {
|
|
1125
|
+
this.mountPage(page);
|
|
1126
|
+
}
|
|
1127
|
+
this.detachedByPage.clear();
|
|
1128
|
+
this.pageHeights = [];
|
|
1129
|
+
this.mutationObserver?.takeRecords();
|
|
1130
|
+
}
|
|
817
1131
|
/**
|
|
818
1132
|
* Mounts the page range around the current scroll position and
|
|
819
|
-
* virtualizes everything outside it, once the
|
|
820
|
-
* `virtualizeThreshold
|
|
1133
|
+
* virtualizes everything outside it, once the row count passes
|
|
1134
|
+
* `virtualizeThreshold`.
|
|
821
1135
|
* @private
|
|
822
1136
|
*/
|
|
823
1137
|
syncPages() {
|
|
824
|
-
const totalRows = this.
|
|
1138
|
+
const totalRows = this.logicalRows.length;
|
|
825
1139
|
if (totalRows === 0) {
|
|
826
1140
|
return;
|
|
827
1141
|
}
|
|
@@ -833,7 +1147,7 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
833
1147
|
}
|
|
834
1148
|
}
|
|
835
1149
|
else {
|
|
836
|
-
if (this.clientHeight
|
|
1150
|
+
if (!this.frameEl?.clientHeight) {
|
|
837
1151
|
return;
|
|
838
1152
|
}
|
|
839
1153
|
const centerPage = this.estimateCenterPage(totalPages);
|
|
@@ -849,19 +1163,17 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
849
1163
|
}
|
|
850
1164
|
}
|
|
851
1165
|
if (changed) {
|
|
852
|
-
this.
|
|
1166
|
+
this.sync();
|
|
853
1167
|
}
|
|
854
1168
|
}
|
|
855
1169
|
/**
|
|
856
|
-
* Estimates which page the middle of the
|
|
857
|
-
*
|
|
858
|
-
* average-based estimate otherwise. `this` is the scroll container itself
|
|
859
|
-
* (`:host` sets `overflow: auto`, see table.styles.ts), so its own
|
|
860
|
-
* `scrollTop`/`clientHeight` are read directly.
|
|
1170
|
+
* Estimates which page the middle of the viewport falls into, from
|
|
1171
|
+
* measured page heights where known, an average otherwise.
|
|
861
1172
|
* @private
|
|
862
1173
|
*/
|
|
863
1174
|
estimateCenterPage(totalPages) {
|
|
864
|
-
const
|
|
1175
|
+
const frame = this.frameEl;
|
|
1176
|
+
const target = frame ? frame.scrollTop + frame.clientHeight / 2 : 0;
|
|
865
1177
|
let offset = 0;
|
|
866
1178
|
for (let page = 0; page < totalPages; page++) {
|
|
867
1179
|
const height = this.pageHeights[page] ?? this.estimatePageHeight(page);
|
|
@@ -874,55 +1186,38 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
874
1186
|
}
|
|
875
1187
|
/** @private */
|
|
876
1188
|
estimatePageHeight(page) {
|
|
877
|
-
const totalPages = Math.ceil(this.
|
|
1189
|
+
const totalPages = Math.ceil(this.logicalRows.length / this.pageSize);
|
|
878
1190
|
const rowsInPage = page === totalPages - 1
|
|
879
|
-
? this.
|
|
1191
|
+
? this.logicalRows.length - page * this.pageSize
|
|
880
1192
|
: this.pageSize;
|
|
881
1193
|
return rowsInPage * this.avgRowHeight;
|
|
882
1194
|
}
|
|
883
1195
|
/**
|
|
884
|
-
* Remounts a virtualized-out page
|
|
885
|
-
*
|
|
886
|
-
* if already mounted), so {@link syncPages} only re-syncs children once
|
|
887
|
-
* per batch rather than once per page.
|
|
1196
|
+
* Remounts a virtualized-out page in place of its spacer. Returns
|
|
1197
|
+
* whether it did anything.
|
|
888
1198
|
* @private
|
|
889
1199
|
*/
|
|
890
1200
|
mountPage(page) {
|
|
891
|
-
if (this.mountedPages.has(page)) {
|
|
892
|
-
return false;
|
|
893
|
-
}
|
|
894
1201
|
const cached = this.detachedByPage.get(page);
|
|
895
|
-
if (
|
|
1202
|
+
if (this.mountedPages.has(page) || !cached?.length) {
|
|
896
1203
|
return false;
|
|
897
1204
|
}
|
|
898
|
-
const spacer = this.querySelector(
|
|
899
|
-
this.mutatingSlot = true;
|
|
1205
|
+
const spacer = this.bodyEl?.querySelector(`:scope > .${SPACER_CLASS}[data-eun-page="${page}"]`);
|
|
900
1206
|
if (spacer) {
|
|
901
|
-
|
|
902
|
-
spacer.before(row);
|
|
903
|
-
}
|
|
1207
|
+
spacer.before(...cached);
|
|
904
1208
|
spacer.remove();
|
|
905
1209
|
}
|
|
906
1210
|
else {
|
|
907
|
-
|
|
908
|
-
this.append(row);
|
|
909
|
-
}
|
|
1211
|
+
this.bodyEl?.append(...cached);
|
|
910
1212
|
}
|
|
911
|
-
queueMicrotask(() => {
|
|
912
|
-
this.mutatingSlot = false;
|
|
913
|
-
});
|
|
914
1213
|
this.detachedByPage.delete(page);
|
|
915
1214
|
this.mountedPages.add(page);
|
|
916
1215
|
return true;
|
|
917
1216
|
}
|
|
918
1217
|
/**
|
|
919
|
-
*
|
|
920
|
-
*
|
|
921
|
-
*
|
|
922
|
-
* spacer of that height so the scrollbar/scroll position don't jump, and
|
|
923
|
-
* caches the actual nodes for an exact reattach later. Returns whether it
|
|
924
|
-
* actually did anything (a no-op if already virtualized-out, or if the
|
|
925
|
-
* page can't be measured — not currently rendered with real layout).
|
|
1218
|
+
* Replaces a mounted page's rows with a single spacer row of the same
|
|
1219
|
+
* measured height, caching the rows for an exact reattach later.
|
|
1220
|
+
* Returns whether it did anything.
|
|
926
1221
|
* @private
|
|
927
1222
|
*/
|
|
928
1223
|
unmountPage(page) {
|
|
@@ -930,8 +1225,8 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
930
1225
|
return false;
|
|
931
1226
|
}
|
|
932
1227
|
const start = page * this.pageSize;
|
|
933
|
-
const end = Math.min(start + this.pageSize, this.
|
|
934
|
-
const rows = this.
|
|
1228
|
+
const end = Math.min(start + this.pageSize, this.logicalRows.length);
|
|
1229
|
+
const rows = this.logicalRows
|
|
935
1230
|
.slice(start, end)
|
|
936
1231
|
.filter((row) => row.isConnected);
|
|
937
1232
|
if (rows.length === 0) {
|
|
@@ -945,26 +1240,21 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
945
1240
|
}
|
|
946
1241
|
this.pageHeights[page] = height;
|
|
947
1242
|
this.avgRowHeight = (this.avgRowHeight + height / rows.length) / 2;
|
|
948
|
-
const spacer = document.createElement("
|
|
949
|
-
spacer.className =
|
|
1243
|
+
const spacer = document.createElement("tr");
|
|
1244
|
+
spacer.className = SPACER_CLASS;
|
|
950
1245
|
spacer.dataset.eunPage = String(page);
|
|
951
|
-
spacer.style.gridColumn = "1 / -1";
|
|
952
|
-
spacer.style.blockSize = `${height}px`;
|
|
953
1246
|
spacer.setAttribute("aria-hidden", "true");
|
|
954
|
-
|
|
1247
|
+
const cell = spacer.insertCell();
|
|
1248
|
+
cell.colSpan = 1000;
|
|
1249
|
+
cell.style.blockSize = `${height}px`;
|
|
955
1250
|
first.before(spacer);
|
|
956
|
-
|
|
957
|
-
row.remove();
|
|
958
|
-
}
|
|
959
|
-
queueMicrotask(() => {
|
|
960
|
-
this.mutatingSlot = false;
|
|
961
|
-
});
|
|
1251
|
+
rows.forEach((row) => row.remove());
|
|
962
1252
|
this.detachedByPage.set(page, rows);
|
|
963
1253
|
this.mountedPages.delete(page);
|
|
964
1254
|
return true;
|
|
965
1255
|
}
|
|
966
1256
|
/**
|
|
967
|
-
* (Re)creates
|
|
1257
|
+
* (Re)creates the resize observer and scroll listener once `virtualize`
|
|
968
1258
|
* is set, and tears them down once it's cleared.
|
|
969
1259
|
* @private
|
|
970
1260
|
*/
|
|
@@ -972,31 +1262,31 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
972
1262
|
if (!this.virtualize) {
|
|
973
1263
|
this.resizeObserver?.disconnect();
|
|
974
1264
|
this.resizeObserver = undefined;
|
|
975
|
-
this.removeEventListener("scroll", this.handleTableScroll);
|
|
1265
|
+
this.frameEl?.removeEventListener("scroll", this.handleTableScroll);
|
|
976
1266
|
if (this.syncHandle) {
|
|
977
1267
|
cancelAnimationFrame(this.syncHandle);
|
|
978
1268
|
this.syncHandle = undefined;
|
|
979
1269
|
}
|
|
980
1270
|
return;
|
|
981
1271
|
}
|
|
982
|
-
if (!this.resizeObserver) {
|
|
1272
|
+
if (!this.resizeObserver && this.frameEl) {
|
|
983
1273
|
this.resizeObserver = new ResizeObserver(() => this.scheduleAnimationFrame(() => this.syncPages()));
|
|
984
|
-
this.resizeObserver.observe(this);
|
|
985
|
-
this.addEventListener("scroll", this.handleTableScroll, {
|
|
1274
|
+
this.resizeObserver.observe(this.frameEl);
|
|
1275
|
+
this.frameEl.addEventListener("scroll", this.handleTableScroll, {
|
|
986
1276
|
passive: true,
|
|
987
1277
|
});
|
|
988
1278
|
}
|
|
1279
|
+
this.sync();
|
|
989
1280
|
this.scheduleAnimationFrame(() => this.syncPages());
|
|
990
1281
|
}
|
|
991
1282
|
/**
|
|
992
1283
|
* Sets up (or re-creates, after `rootMargin` changes) the observer
|
|
993
|
-
* driving {@link maybeLoadMore}
|
|
994
|
-
*
|
|
995
|
-
* container) is used as the observer's `root`.
|
|
1284
|
+
* driving {@link maybeLoadMore}, with the frame, the scroll container,
|
|
1285
|
+
* as its root.
|
|
996
1286
|
* @private
|
|
997
1287
|
*/
|
|
998
1288
|
setupTableLoadObserver() {
|
|
999
|
-
this.setupLoadObserver(this.sentinelEl, this, this.rootMargin, () => this.maybeLoadMore());
|
|
1289
|
+
this.setupLoadObserver(this.sentinelEl, this.frameEl ?? this, this.rootMargin, () => this.maybeLoadMore());
|
|
1000
1290
|
}
|
|
1001
1291
|
/** @private */
|
|
1002
1292
|
maybeLoadMore() {
|
|
@@ -1004,45 +1294,29 @@ let EunomiaTable = class EunomiaTable extends LoadMoreSentinelMixin(LitElement)
|
|
|
1004
1294
|
return;
|
|
1005
1295
|
}
|
|
1006
1296
|
this.loadingMore = true;
|
|
1297
|
+
this.rowCountBeforeLoad = this.currentRows().length;
|
|
1007
1298
|
this.requestedPages += 1;
|
|
1008
1299
|
this.dispatchEvent(new LoadMoreEvent(this.requestedPages, this.pageSize));
|
|
1009
1300
|
}
|
|
1010
|
-
/**
|
|
1011
|
-
* Renders `skeletonRows` placeholder rows, each shaped like a real
|
|
1012
|
-
* `eun-table-item` (same select/data/action cell count, via CSS Subgrid)
|
|
1013
|
-
* so they align under the real header's columns. `--_row-index` drives
|
|
1014
|
-
* each row's own staggered entrance animation delay (see
|
|
1015
|
-
* table-skeleton-row.styles.ts).
|
|
1016
|
-
* @private
|
|
1017
|
-
*/
|
|
1018
|
-
renderSkeletonRows() {
|
|
1019
|
-
const header = this.querySelector(":scope > eun-table-header");
|
|
1020
|
-
const columnCount = this.columns?.length ??
|
|
1021
|
-
header?.querySelectorAll(":scope > eun-table-column").length ??
|
|
1022
|
-
0;
|
|
1023
|
-
return html `
|
|
1024
|
-
${Array.from({ length: this.skeletonRows }, (_, index) => html `
|
|
1025
|
-
<eun-table-skeleton-row
|
|
1026
|
-
?selectable=${this.selectable}
|
|
1027
|
-
?has-action=${this.hasAction}
|
|
1028
|
-
column-count=${columnCount}
|
|
1029
|
-
style="--_row-index: ${index}"
|
|
1030
|
-
></eun-table-skeleton-row>
|
|
1031
|
-
`)}
|
|
1032
|
-
`;
|
|
1033
|
-
}
|
|
1034
1301
|
render() {
|
|
1035
1302
|
return html `
|
|
1036
|
-
<
|
|
1037
|
-
|
|
1303
|
+
<div id="frame" part="frame">
|
|
1304
|
+
<slot></slot>
|
|
1305
|
+
${!this.loading && this.infinite
|
|
1038
1306
|
? html `
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1307
|
+
<div id="table-sentinel" aria-hidden="true"></div>
|
|
1308
|
+
<div id="table-loading-row" ?hidden=${!this.loadingMore}>
|
|
1309
|
+
<eun-loader label=${this.labels.loadingMore}></eun-loader>
|
|
1310
|
+
</div>
|
|
1311
|
+
`
|
|
1044
1312
|
: nothing}
|
|
1045
|
-
|
|
1313
|
+
</div>
|
|
1314
|
+
<div
|
|
1315
|
+
id="announcer"
|
|
1316
|
+
role="status"
|
|
1317
|
+
aria-live="polite"
|
|
1318
|
+
class="visually-hidden"
|
|
1319
|
+
></div>
|
|
1046
1320
|
`;
|
|
1047
1321
|
}
|
|
1048
1322
|
};
|
|
@@ -1074,6 +1348,9 @@ __decorate([
|
|
|
1074
1348
|
__decorate([
|
|
1075
1349
|
property({ type: Boolean, reflect: true, attribute: "sticky-header" })
|
|
1076
1350
|
], EunomiaTable.prototype, "stickyHeader", void 0);
|
|
1351
|
+
__decorate([
|
|
1352
|
+
property({ type: Boolean, reflect: true, attribute: "sticky-footer" })
|
|
1353
|
+
], EunomiaTable.prototype, "stickyFooter", void 0);
|
|
1077
1354
|
__decorate([
|
|
1078
1355
|
property({ type: Boolean, reflect: true, attribute: "sticky-first-column" })
|
|
1079
1356
|
], EunomiaTable.prototype, "stickyFirstColumn", void 0);
|
|
@@ -1164,18 +1441,15 @@ __decorate([
|
|
|
1164
1441
|
__decorate([
|
|
1165
1442
|
state()
|
|
1166
1443
|
], EunomiaTable.prototype, "internalSelection", void 0);
|
|
1167
|
-
__decorate([
|
|
1168
|
-
state()
|
|
1169
|
-
], EunomiaTable.prototype, "hasAction", void 0);
|
|
1170
|
-
__decorate([
|
|
1171
|
-
queryAssignedElements({ selector: "eun-table-header" })
|
|
1172
|
-
], EunomiaTable.prototype, "headerEls", void 0);
|
|
1173
|
-
__decorate([
|
|
1174
|
-
queryAssignedElements({ selector: "eun-table-item" })
|
|
1175
|
-
], EunomiaTable.prototype, "itemEls", void 0);
|
|
1176
1444
|
__decorate([
|
|
1177
1445
|
query("#table-sentinel")
|
|
1178
1446
|
], EunomiaTable.prototype, "sentinelEl", void 0);
|
|
1447
|
+
__decorate([
|
|
1448
|
+
query("#frame")
|
|
1449
|
+
], EunomiaTable.prototype, "frameEl", void 0);
|
|
1450
|
+
__decorate([
|
|
1451
|
+
query("#announcer")
|
|
1452
|
+
], EunomiaTable.prototype, "announcerEl", void 0);
|
|
1179
1453
|
EunomiaTable = __decorate([
|
|
1180
1454
|
customElement(EunomiaTableTagName)
|
|
1181
1455
|
], EunomiaTable);
|