@kubex/zinc 1.1.184 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +2 -0
- package/.github/workflows/js_build_and_deploy.yaml +54 -1
- package/.github/workflows/test.yaml +27 -0
- package/dist/chunks/zn.UWJLIXDT.js +1 -0
- package/dist/custom-elements.json +10344 -2583
- package/dist/vscode.html-custom-data.json +1102 -125
- package/dist/web-types.json +2217 -224
- package/dist/zn.d.ts +2306 -417
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +2313 -1635
- package/docs/_includes/default.njk +4 -1
- package/docs/assets/scripts/docs.js +22 -6
- package/docs/assets/styles/docs.css +9 -2
- package/docs/data/report-table-day-compare.json +380 -0
- package/docs/data/report-table.json +314 -0
- package/docs/pages/components/avatar-group.md +57 -0
- package/docs/pages/components/badge.md +67 -0
- package/docs/pages/components/button.md +41 -1
- package/docs/pages/components/chat-message.md +16 -0
- package/docs/pages/components/checkbox.md +1 -1
- package/docs/pages/components/chip.md +25 -13
- package/docs/pages/components/color-picker.md +37 -0
- package/docs/pages/components/copy-button.md +2 -2
- package/docs/pages/components/data-table-filter.md +33 -50
- package/docs/pages/components/data-table-search.md +4 -4
- package/docs/pages/components/data-table.md +27 -3
- package/docs/pages/components/date-range.md +116 -0
- package/docs/pages/components/dialog.md +29 -37
- package/docs/pages/components/diff-row.md +28 -0
- package/docs/pages/components/diff.md +46 -0
- package/docs/pages/components/editor.md +55 -0
- package/docs/pages/components/filter-wrapper.md +20 -0
- package/docs/pages/components/icon.md +46 -1
- package/docs/pages/components/input.md +30 -11
- package/docs/pages/components/item.md +35 -0
- package/docs/pages/components/key-value.md +25 -0
- package/docs/pages/components/menu.md +74 -7
- package/docs/pages/components/nav-item.md +15 -0
- package/docs/pages/components/nav-list.md +132 -0
- package/docs/pages/components/navbar.md +100 -1
- package/docs/pages/components/page.md +242 -74
- package/docs/pages/components/priority-list.md +43 -5
- package/docs/pages/components/query-builder.md +23 -0
- package/docs/pages/components/radio-group.md +33 -1
- package/docs/pages/components/radio.md +1 -1
- package/docs/pages/components/report-table.md +202 -0
- package/docs/pages/components/stat.md +30 -0
- package/docs/pages/components/tile.md +11 -0
- package/docs/pages/components/tooltip.md +1 -1
- package/docs/pages/components/translation-grid.md +86 -0
- package/docs/pages/components/vertical-stepper.md +108 -64
- package/package.json +2 -1
- package/scss/_global-spacing.scss +2 -2
- package/scss/_root.scss +11 -171
- package/scss/boot.scss +14 -0
- package/scss/mixins/_helper-mixins.scss +24 -2
- package/scss/mixins/_motion-mixins.scss +126 -0
- package/scss/mixins/_spacing-mixins.scss +4 -3
- package/scss/mixins/_tab-indicator-mixins.scss +12 -0
- package/scss/mixins/_typography-mixins.scss +1 -1
- package/scss/mixins/index.scss +14 -0
- package/scss/shared/_base.scss +32 -1
- package/scss/shared/_button-mixin.scss +7 -5
- package/scss/shared/_table.scss +35 -4
- package/scss/shared/nav.scss +4 -0
- package/scss/shared/shimmer.scss +1 -1
- package/scss/table-controls.scss +206 -0
- package/scss/themes/_dark.scss +1 -3
- package/scss/themes/_index.scss +1 -1
- package/scss/themes/_light.scss +46 -6
- package/scss/themes/_modes.scss +11 -11
- package/scss/themes/_openbyte.scss +944 -0
- package/scss/themes/_typography.scss +4 -2
- package/scss/variables/index.scss +0 -9
- package/src/components/alert/alert.component.ts +14 -4
- package/src/components/alert/alert.scss +55 -69
- package/src/components/alert/alert.test.ts +8 -0
- package/src/components/animated-button/animated-button.component.ts +3 -2
- package/src/components/animated-button/animated-button.scss +6 -23
- package/src/components/animated-button/animated-button.test.ts +4 -3
- package/src/components/avatar-group/avatar-group.component.ts +84 -0
- package/src/components/avatar-group/avatar-group.scss +54 -0
- package/src/components/avatar-group/avatar-group.test.ts +59 -0
- package/src/components/avatar-group/index.ts +12 -0
- package/src/components/badge/badge.component.ts +49 -0
- package/src/components/badge/badge.scss +80 -0
- package/src/components/badge/badge.test.ts +34 -0
- package/src/components/badge/index.ts +12 -0
- package/src/components/bulk-actions/bulk-actions.component.ts +14 -2
- package/src/components/button/button.component.ts +242 -11
- package/src/components/button/button.scss +133 -25
- package/src/components/button/button.test.ts +122 -0
- package/src/components/button-menu/button-menu.component.ts +32 -11
- package/src/components/button-menu/button-menu.scss +5 -1
- package/src/components/channel-tile/channel-tile.component.ts +34 -27
- package/src/components/channel-tile/channel-tile.scss +76 -43
- package/src/components/chart/builders.test.ts +46 -0
- package/src/components/chart/builders.ts +27 -3
- package/src/components/chart/chart-live.test.ts +4 -6
- package/src/components/chart/chart.component.ts +125 -5
- package/src/components/chart/chart.scss +121 -0
- package/src/components/chart/chart.test.ts +81 -0
- package/src/components/chat-message/chat-message.component.ts +21 -1
- package/src/components/chat-message/chat-message.scss +13 -2
- package/src/components/chat-message/chat-message.test.ts +9 -0
- package/src/components/checkbox/checkbox.component.ts +61 -27
- package/src/components/checkbox/checkbox.scss +58 -25
- package/src/components/checkbox-group/checkbox-group.component.ts +7 -1
- package/src/components/chip/chip.component.ts +11 -1
- package/src/components/chip/chip.scss +91 -26
- package/src/components/chip/chip.test.ts +17 -0
- package/src/components/collapsible/collapsible.component.ts +17 -3
- package/src/components/collapsible/collapsible.scss +19 -10
- package/src/components/color-picker/color-picker.component.ts +277 -0
- package/src/components/color-picker/color-picker.scss +141 -0
- package/src/components/color-picker/color-picker.test.ts +57 -0
- package/src/components/color-picker/index.ts +12 -0
- package/src/components/cols/cols.component.ts +17 -3
- package/src/components/cols/cols.scss +24 -13
- package/src/components/cols/cols.test.ts +33 -0
- package/src/components/confirm/confirm.component.ts +20 -6
- package/src/components/confirm/confirm.test.ts +52 -0
- package/src/components/content-block/content-block.component.ts +38 -9
- package/src/components/content-block/content-block.scss +11 -5
- package/src/components/content-block/content-block.test.ts +26 -0
- package/src/components/copy-button/copy-button.component.ts +2 -2
- package/src/components/copy-button/copy-button.scss +17 -4
- package/src/components/data-select/data-select.component.ts +3 -1
- package/src/components/data-table/data-table.component.ts +364 -142
- package/src/components/data-table/data-table.scss +133 -60
- package/src/components/data-table/data-table.test.ts +356 -4
- package/src/components/data-table-filter/data-table-filter.component.ts +426 -406
- package/src/components/data-table-filter/data-table-filter.scss +176 -148
- package/src/components/data-table-filter/data-table-filter.test.ts +271 -273
- package/src/components/data-table-search/data-table-search.component.ts +4 -2
- package/src/components/data-table-search/data-table-search.scss +8 -1
- package/src/components/data-table-search/data-table-search.test.ts +29 -0
- package/src/components/date-range/date-range-math.test.ts +78 -0
- package/src/components/date-range/date-range-math.ts +105 -0
- package/src/components/date-range/date-range.component.ts +375 -0
- package/src/components/date-range/date-range.scss +272 -0
- package/src/components/date-range/date-range.test.ts +247 -0
- package/src/components/date-range/index.ts +12 -0
- package/src/components/datepicker/datepicker.component.ts +44 -7
- package/src/components/datepicker/datepicker.scss +9 -0
- package/src/components/datepicker/datepicker.test.ts +2 -2
- package/src/components/dialog/dialog.component.ts +38 -19
- package/src/components/dialog/dialog.scss +65 -36
- package/src/components/dialog/dialog.test.ts +14 -0
- package/src/components/diff/diff.component.ts +55 -0
- package/src/components/diff/diff.scss +46 -0
- package/src/components/diff/diff.test.ts +15 -0
- package/src/components/diff/index.ts +12 -0
- package/src/components/diff-row/diff-row.component.ts +75 -0
- package/src/components/diff-row/diff-row.scss +70 -0
- package/src/components/diff-row/diff-row.test.ts +37 -0
- package/src/components/diff-row/index.ts +12 -0
- package/src/components/dropdown/dropdown.component.ts +12 -10
- package/src/components/dropdown/dropdown.scss +2 -0
- package/src/components/editor/editor.component.ts +159 -11
- package/src/components/editor/editor.scss +250 -1
- package/src/components/editor/editor.test.ts +31 -3
- package/src/components/editor/modules/ai/panel/ai-panel.scss +0 -1
- package/src/components/editor/modules/attachment/attachment.ts +53 -31
- package/src/components/editor/modules/context-menu/context-menu.ts +17 -0
- package/src/components/editor/modules/dialog/dialog.component.ts +23 -1
- package/src/components/editor/modules/dialog/dialog.test.ts +28 -0
- package/src/components/editor/modules/emoji/emoji.ts +4 -5
- package/src/components/editor/modules/merge-field/merge-field.ts +83 -0
- package/src/components/editor/modules/toolbar/toolbar.component.ts +121 -68
- package/src/components/editor/modules/toolbar/toolbar.scss +38 -0
- package/src/components/editor/modules/toolbar/toolbar.ts +25 -1
- package/src/components/empty-state/empty-state.component.ts +6 -1
- package/src/components/empty-state/empty-state.scss +21 -4
- package/src/components/expanding-action/expanding-action.component.ts +22 -34
- package/src/components/expanding-action/expanding-action.scss +3 -45
- package/src/components/expanding-action/expanding-action.test.ts +2 -1
- package/src/components/file/file.component.ts +30 -2
- package/src/components/file/file.scss +6 -0
- package/src/components/filter-wrapper/filter-wrapper.component.ts +45 -10
- package/src/components/filter-wrapper/filter-wrapper.test.ts +58 -2
- package/src/components/flow-builder/flow-builder.component.ts +36 -3
- package/src/components/flow-builder/flow-builder.scss +0 -6
- package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +8 -0
- package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +10 -5
- package/src/components/flow-builder/modules/flow-node/flow-node.component.ts +17 -0
- package/src/components/flow-builder/modules/flow-node/flow-node.scss +10 -0
- package/src/components/form-actions/form-actions.component.ts +48 -2
- package/src/components/form-actions/form-actions.scss +1 -1
- package/src/components/form-group/form-group.component.ts +10 -3
- package/src/components/form-group/form-group.scss +37 -4
- package/src/components/form-group/form-group.test.ts +10 -0
- package/src/components/header/header.component.ts +11 -4
- package/src/components/header/header.scss +47 -5
- package/src/components/hover-container/hover-container.component.ts +4 -5
- package/src/components/icon/icon.component.ts +95 -9
- package/src/components/icon/icon.scss +70 -6
- package/src/components/icon/icon.test.ts +55 -0
- package/src/components/icon-picker/icon-picker.component.ts +35 -1
- package/src/components/inline-edit/inline-edit.component.ts +38 -8
- package/src/components/inline-edit/inline-edit.scss +128 -19
- package/src/components/input/input.component.ts +173 -297
- package/src/components/input/input.scss +65 -43
- package/src/components/input/input.test.ts +86 -4
- package/src/components/item/item.component.ts +12 -0
- package/src/components/item/item.scss +102 -3
- package/src/components/item/item.test.ts +23 -0
- package/src/components/key/key.component.ts +2 -2
- package/src/components/key/key.scss +11 -0
- package/src/components/key-value/index.ts +12 -0
- package/src/components/key-value/key-value.component.ts +160 -0
- package/src/components/key-value/key-value.scss +20 -0
- package/src/components/key-value/key-value.test.ts +22 -0
- package/src/components/markdown-editor/markdown-editor.component.ts +8 -1
- package/src/components/menu/menu.component.ts +21 -2
- package/src/components/menu/menu.scss +43 -23
- package/src/components/menu/menu.test.ts +33 -0
- package/src/components/menu-item/menu-item.component.ts +13 -2
- package/src/components/menu-item/menu-item.scss +56 -23
- package/src/components/menu-item/menu-item.test.ts +31 -0
- package/src/components/menu-item/submenu-controller.ts +25 -15
- package/src/components/menu-label/index.ts +12 -0
- package/src/components/menu-label/menu-label.component.ts +30 -0
- package/src/components/menu-label/menu-label.scss +18 -0
- package/src/components/nav-item/index.ts +12 -0
- package/src/components/nav-item/nav-item.component.ts +83 -0
- package/src/components/nav-item/nav-item.scss +128 -0
- package/src/components/nav-list/index.ts +12 -0
- package/src/components/nav-list/nav-list.component.ts +313 -0
- package/src/components/nav-list/nav-list.scss +87 -0
- package/src/components/nav-list/nav-list.test.ts +250 -0
- package/src/components/navbar/navbar.component.ts +235 -171
- package/src/components/navbar/navbar.scss +333 -169
- package/src/components/navbar/navbar.test.ts +63 -143
- package/src/components/page/page.component.ts +114 -29
- package/src/components/page/page.scss +223 -95
- package/src/components/page/page.test.ts +214 -3
- package/src/components/page-builder/page-builder.component.ts +51 -5
- package/src/components/page-builder/page-builder.scss +6 -1
- package/src/components/page-nav/page-nav.component.ts +25 -3
- package/src/components/page-nav/page-nav.scss +10 -2
- package/src/components/pagination/pagination.scss +1 -1
- package/src/components/panel/panel.component.ts +14 -13
- package/src/components/panel/panel.scss +14 -10
- package/src/components/panel/panel.test.ts +42 -0
- package/src/components/popup/popup.component.ts +20 -13
- package/src/components/popup/popup.test.ts +21 -1
- package/src/components/priority-list/priority-list.component.ts +157 -172
- package/src/components/priority-list/priority-list.scss +113 -17
- package/src/components/priority-list/priority-list.test.ts +301 -3
- package/src/components/progress-bar/progress-bar.component.ts +1 -1
- package/src/components/progress-bar/progress-bar.scss +16 -4
- package/src/components/progress-tile/progress-tile.scss +1 -1
- package/src/components/query-builder/query-builder.component.ts +85 -10
- package/src/components/query-builder/query-builder.scss +7 -1
- package/src/components/query-builder/query-builder.test.ts +40 -0
- package/src/components/radio/radio.component.ts +57 -18
- package/src/components/radio/radio.scss +101 -26
- package/src/components/radio-group/radio-group.component.ts +45 -7
- package/src/components/radio-group/radio-group.scss +17 -0
- package/src/components/radio-group/radio-group.test.ts +63 -2
- package/src/components/rating/rating.component.ts +23 -0
- package/src/components/rating/rating.scss +1 -1
- package/src/components/remarkd-editor/remarkd-editor.component.ts +60 -5
- package/src/components/remarkd-editor/remarkd-editor.scss +12 -4
- package/src/components/report-table/index.ts +12 -0
- package/src/components/report-table/report-format.test.ts +86 -0
- package/src/components/report-table/report-format.ts +72 -0
- package/src/components/report-table/report-math.test.ts +74 -0
- package/src/components/report-table/report-math.ts +252 -0
- package/src/components/report-table/report-table.component.ts +681 -0
- package/src/components/report-table/report-table.scss +328 -0
- package/src/components/report-table/report-table.test.ts +702 -0
- package/src/components/reveal/reveal.component.ts +15 -1
- package/src/components/reveal/reveal.scss +5 -0
- package/src/components/schedule-builder/schedule-builder.component.ts +23 -8
- package/src/components/scroll-container/scroll-container.component.ts +19 -1
- package/src/components/scroll-container/scroll-container.scss +6 -1
- package/src/components/select/select.component.ts +52 -36
- package/src/components/select/select.scss +42 -25
- package/src/components/select/select.test.ts +14 -2
- package/src/components/settings-container/settings-container.scss +18 -5
- package/src/components/sidebar/sidebar.component.ts +8 -1
- package/src/components/sidebar/sidebar.scss +6 -1
- package/src/components/skeleton/skeleton.component.ts +3 -3
- package/src/components/skeleton/skeleton.scss +6 -6
- package/src/components/skeleton/skeleton.test.ts +9 -0
- package/src/components/slash-menu/slash-menu.scss +1 -1
- package/src/components/slideout/slideout.component.ts +20 -3
- package/src/components/slideout/slideout.scss +13 -6
- package/src/components/slideout/slideout.test.ts +19 -0
- package/src/components/split-button/split-button.component.ts +1 -1
- package/src/components/split-pane/split-pane.component.ts +71 -8
- package/src/components/split-pane/split-pane.scss +145 -41
- package/src/components/split-pane/split-pane.test.ts +23 -3
- package/src/components/stat/stat.component.ts +209 -14
- package/src/components/stat/stat.scss +305 -5
- package/src/components/stat/stat.test.ts +143 -2
- package/src/components/status-indicator/status-indicator.scss +22 -21
- package/src/components/stepper/stepper.scss +3 -3
- package/src/components/tab/tab.component.ts +1 -0
- package/src/components/table/table.component.ts +12 -1
- package/src/components/table/table.scss +21 -13
- package/src/components/table/table.test.ts +17 -0
- package/src/components/tabs/tabs.component.ts +150 -37
- package/src/components/tabs/tabs.scss +48 -7
- package/src/components/tabs/tabs.test.ts +169 -0
- package/src/components/textarea/textarea.component.ts +25 -3
- package/src/components/textarea/textarea.scss +10 -0
- package/src/components/textarea/textarea.test.ts +8 -4
- package/src/components/theme-editor/theme-editor.scss +0 -6
- package/src/components/tile/tile.component.ts +32 -2
- package/src/components/tile/tile.scss +40 -7
- package/src/components/tile/tile.test.ts +10 -0
- package/src/components/toggle/toggle.component.ts +23 -7
- package/src/components/toggle/toggle.scss +36 -29
- package/src/components/toggle/toggle.test.ts +17 -0
- package/src/components/tooltip/tooltip.component.ts +3 -0
- package/src/components/tooltip/tooltip.scss +11 -6
- package/src/components/tooltip/tooltip.test.ts +12 -0
- package/src/components/translation-field/index.ts +12 -0
- package/src/components/translation-field/translation-field.component.ts +55 -0
- package/src/components/translation-field/translation-field.scss +101 -0
- package/src/components/translation-fields/index.ts +12 -0
- package/src/components/translation-fields/translation-fields.component.ts +80 -0
- package/src/components/translation-fields/translation-fields.scss +60 -0
- package/src/components/translation-grid/index.ts +12 -0
- package/src/components/translation-grid/translation-grid.component.ts +157 -0
- package/src/components/translation-grid/translation-grid.scss +138 -0
- package/src/components/translation-grid/translation-grid.test.ts +28 -0
- package/src/components/vertical-stepper/vertical-stepper.component.ts +35 -9
- package/src/components/vertical-stepper/vertical-stepper.scss +110 -39
- package/src/components/vertical-stepper/vertical-stepper.test.ts +35 -0
- package/src/components/well/well.scss +2 -2
- package/src/events/events.ts +2 -0
- package/src/events/zn-chart-click.ts +13 -0
- package/src/events/zn-report-change.ts +7 -0
- package/src/form-control.scss +36 -3
- package/src/internal/anchored-popover.ts +175 -0
- package/src/internal/animate.ts +19 -5
- package/src/internal/cosmic-border.ts +15 -0
- package/src/internal/form.ts +1 -1
- package/src/internal/hover-intent.ts +15 -0
- package/src/internal/input-modality.ts +15 -0
- package/src/internal/pointer-intent.ts +37 -0
- package/src/internal/reorder.ts +625 -0
- package/src/internal/scroll.ts +51 -3
- package/src/internal/selection-card.ts +1 -1
- package/src/internal/tab-indicator.ts +92 -0
- package/src/internal/table-sort.ts +25 -0
- package/src/internal/table-tabs.ts +108 -0
- package/src/internal/test-drag.ts +35 -0
- package/src/internal/theme-openbyte.test.ts +126 -0
- package/src/internal/theme.ts +4 -4
- package/src/internal/zinc-element.ts +2 -2
- package/src/selection-card.scss +25 -0
- package/src/types/web-test-runner-commands.d.ts +1 -0
- package/src/utilities/color.test.ts +43 -0
- package/src/utilities/color.ts +189 -0
- package/src/zinc.ts +14 -0
- package/.github/workflows/eleventy_build.yml +0 -42
- package/scss/themes/_aura.scss +0 -114
|
@@ -4,18 +4,22 @@ import {HasSlotController} from "../../internal/slot";
|
|
|
4
4
|
import {ifDefined} from "lit/directives/if-defined.js";
|
|
5
5
|
import {property, state} from 'lit/decorators.js';
|
|
6
6
|
import {ref} from "lit/directives/ref.js";
|
|
7
|
+
import {styleMap} from "lit/directives/style-map.js";
|
|
8
|
+
import {renderSortIcon, sortKeyHandler} from "../../internal/table-sort";
|
|
9
|
+
import {ReorderController} from "../../internal/reorder";
|
|
7
10
|
import {ResizeController} from '@lit-labs/observers/resize-controller.js';
|
|
11
|
+
import {type TableTab, TabRowController} from "../../internal/table-tabs";
|
|
8
12
|
import {Task} from "@lit/task";
|
|
9
13
|
import {unsafeHTML} from "lit/directives/unsafe-html.js";
|
|
10
14
|
import {type ZnFilterChangeEvent} from "../../events/zn-filter-change";
|
|
11
15
|
import {type ZnSearchChangeEvent} from "../../events/zn-search-change";
|
|
12
16
|
import ZincElement from '../../internal/zinc-element';
|
|
13
17
|
import ZnAlert from "../alert";
|
|
18
|
+
import ZnBadge from "../badge";
|
|
14
19
|
import ZnButton from "../button";
|
|
15
|
-
import ZnButtonGroup from "../button-group";
|
|
16
20
|
import ZnChip from "../chip";
|
|
17
21
|
import ZnConfirm from "../confirm";
|
|
18
|
-
import ZnDataTableFilter from "../data-table-filter";
|
|
22
|
+
import ZnDataTableFilter, {type FilterField} from "../data-table-filter";
|
|
19
23
|
import ZnDataTableSearch from "../data-table-search";
|
|
20
24
|
import ZnDropdown from "../dropdown";
|
|
21
25
|
import ZnEmptyState from "../empty-state";
|
|
@@ -26,13 +30,17 @@ import ZnPanel from "../panel";
|
|
|
26
30
|
import ZnSkeleton from "../skeleton";
|
|
27
31
|
import ZnStyle from "../style";
|
|
28
32
|
import type ZnDataSelect from "../data-select";
|
|
29
|
-
import
|
|
33
|
+
import ZnIcon from "../icon";
|
|
34
|
+
import ZnInput from "../input";
|
|
35
|
+
import ZnOptGroup from "../opt-group";
|
|
36
|
+
import ZnOption from "../option";
|
|
30
37
|
import type ZnQueryBuilder from "../query-builder";
|
|
31
|
-
import
|
|
38
|
+
import ZnSelect from "../select";
|
|
32
39
|
|
|
33
40
|
// Tables load in such a way that the global sheet has to be re-applied inside the shadow root.
|
|
34
41
|
import bootStyles from '../../../scss/boot.scss';
|
|
35
42
|
import styles from './data-table.scss';
|
|
43
|
+
import tableControlsStyles from '../../../scss/table-controls.scss';
|
|
36
44
|
|
|
37
45
|
const DEFAULT_PAGE = 1;
|
|
38
46
|
const DEFAULT_PER_PAGE = 10;
|
|
@@ -53,6 +61,8 @@ interface Cell {
|
|
|
53
61
|
hoverContent?: string;
|
|
54
62
|
hoverPlacement?: string;
|
|
55
63
|
chipColor?: string;
|
|
64
|
+
badgeType?: string;
|
|
65
|
+
badgeDot?: boolean;
|
|
56
66
|
gaid?: string;
|
|
57
67
|
sortValue?: string;
|
|
58
68
|
uri?: string;
|
|
@@ -125,6 +135,7 @@ interface HeaderConfig {
|
|
|
125
135
|
hideColumn?: boolean;
|
|
126
136
|
secondary?: boolean;
|
|
127
137
|
type?: string;
|
|
138
|
+
align?: 'left' | 'right' | 'center';
|
|
128
139
|
cellTemplate?: Cell;
|
|
129
140
|
ifEmpty?: Cell;
|
|
130
141
|
}
|
|
@@ -171,6 +182,7 @@ type AllowedInputElement =
|
|
|
171
182
|
* @since 1.0
|
|
172
183
|
*
|
|
173
184
|
* @dependency zn-alert
|
|
185
|
+
* @dependency zn-badge
|
|
174
186
|
* @dependency zn-button
|
|
175
187
|
* @dependency zn-empty-state
|
|
176
188
|
* @dependency zn-chip
|
|
@@ -179,7 +191,6 @@ type AllowedInputElement =
|
|
|
179
191
|
* @dependency zn-menu
|
|
180
192
|
* @dependency zn-menu-item
|
|
181
193
|
* @dependency zn-panel
|
|
182
|
-
* @dependency zn-button-group
|
|
183
194
|
* @dependency zn-confirm
|
|
184
195
|
* @dependency zn-skeleton
|
|
185
196
|
* @dependency zn-data-table-search
|
|
@@ -202,9 +213,10 @@ type AllowedInputElement =
|
|
|
202
213
|
* @cssproperty --example - An example CSS custom property.
|
|
203
214
|
*/
|
|
204
215
|
export default class ZnDataTable extends ZincElement {
|
|
205
|
-
static styles: CSSResultGroup = [unsafeCSS(bootStyles), unsafeCSS(styles)];
|
|
216
|
+
static styles: CSSResultGroup = [unsafeCSS(bootStyles), unsafeCSS(styles), unsafeCSS(tableControlsStyles)];
|
|
206
217
|
static dependencies = {
|
|
207
218
|
'zn-alert': ZnAlert,
|
|
219
|
+
'zn-badge': ZnBadge,
|
|
208
220
|
'zn-button': ZnButton,
|
|
209
221
|
'zn-empty-state': ZnEmptyState,
|
|
210
222
|
'zn-chip': ZnChip,
|
|
@@ -213,11 +225,16 @@ export default class ZnDataTable extends ZincElement {
|
|
|
213
225
|
'zn-menu': ZnMenu,
|
|
214
226
|
'zn-menu-item': ZnMenuItem,
|
|
215
227
|
'zn-panel': ZnPanel,
|
|
216
|
-
'zn-button-group': ZnButtonGroup,
|
|
217
228
|
'zn-confirm': ZnConfirm,
|
|
218
229
|
'zn-skeleton': ZnSkeleton,
|
|
219
230
|
'zn-style': ZnStyle,
|
|
231
|
+
'zn-icon': ZnIcon,
|
|
232
|
+
'zn-input': ZnInput,
|
|
233
|
+
'zn-opt-group': ZnOptGroup,
|
|
234
|
+
'zn-option': ZnOption,
|
|
235
|
+
'zn-select': ZnSelect,
|
|
220
236
|
'zn-data-table-search': ZnDataTableSearch,
|
|
237
|
+
'zn-data-table-filter': ZnDataTableFilter,
|
|
221
238
|
};
|
|
222
239
|
|
|
223
240
|
@property({attribute: 'data-uri'}) dataUri: string;
|
|
@@ -263,6 +280,35 @@ export default class ZnDataTable extends ZincElement {
|
|
|
263
280
|
|
|
264
281
|
@property({attribute: "empty-state-icon"}) emptyStateIcon: string = "data_alert";
|
|
265
282
|
|
|
283
|
+
/** Unit for the row total shown with the caption: "publishers" reads "16 publishers". */
|
|
284
|
+
@property({attribute: 'total-label'}) totalLabel = '';
|
|
285
|
+
|
|
286
|
+
/** Unit used when the total is exactly one: "publisher" reads "1 publisher". Falls back to `total-label`. */
|
|
287
|
+
@property({attribute: 'total-label-singular'}) totalLabelSingular = '';
|
|
288
|
+
|
|
289
|
+
/** Tabs rendered inside the table. The selected tab's value is sent as `tab-param` with every request. */
|
|
290
|
+
@property({type: Array}) tabs: TableTab[] = [];
|
|
291
|
+
|
|
292
|
+
@property({attribute: 'tab-param'}) tabParam = 'tab';
|
|
293
|
+
|
|
294
|
+
/** Draws the tabs as a segmented control: a grey track with a pill that slides to the selected tab. */
|
|
295
|
+
@property({attribute: 'pill-tabs', type: Boolean, reflect: true}) pillTabs = false;
|
|
296
|
+
|
|
297
|
+
/** The selected tab's value; the first tab when empty. */
|
|
298
|
+
// Not the `tab` attribute: on any element that marks a zn-tabs trigger, which is clickable and switches tabs
|
|
299
|
+
@property({attribute: 'active-tab', reflect: true}) tab = '';
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Fields for the funnel's filter builder. When set, the table renders its own zn-data-table-filter in the
|
|
303
|
+
* header, in place of the `filter` slot, and the applied rules show as chips under the tabs. Rules are sent
|
|
304
|
+
* as `filter`.
|
|
305
|
+
*/
|
|
306
|
+
@property({attribute: 'filter-fields', type: Array}) filterFields: FilterField[] = [];
|
|
307
|
+
|
|
308
|
+
private readonly _fieldsFilter = document.createElement('zn-data-table-filter');
|
|
309
|
+
|
|
310
|
+
private readonly _tabRow = new TabRowController(this, {onSelect: (value: string) => this.selectTab(value)});
|
|
311
|
+
|
|
266
312
|
@property() filters: [] = [];
|
|
267
313
|
|
|
268
314
|
@property() method: 'GET' | 'POST' = 'POST';
|
|
@@ -293,6 +339,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
293
339
|
private _hasLoadedData = false;
|
|
294
340
|
private _lastLoadHadRows = false;
|
|
295
341
|
private _lastTableContent: TemplateResult = html``;
|
|
342
|
+
private _headObserver: ResizeObserver | null = null;
|
|
296
343
|
|
|
297
344
|
// Sharable (URL <-> state) sync
|
|
298
345
|
private _sharableInitialised = false;
|
|
@@ -332,6 +379,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
332
379
|
ActionSlots.filter.valueOf(),
|
|
333
380
|
ActionSlots.sort.valueOf(),
|
|
334
381
|
ActionSlots.inputs.valueOf(),
|
|
382
|
+
'toolbar',
|
|
335
383
|
'empty-state',
|
|
336
384
|
'no-results'
|
|
337
385
|
);
|
|
@@ -379,6 +427,11 @@ export default class ZnDataTable extends ZincElement {
|
|
|
379
427
|
Object.assign(requestData, params);
|
|
380
428
|
}
|
|
381
429
|
|
|
430
|
+
Object.assign(requestData, this.toolbarParams());
|
|
431
|
+
if (this.tabs.length > 0) {
|
|
432
|
+
Object.assign(requestData, {[this.tabParam]: this.activeTab()});
|
|
433
|
+
}
|
|
434
|
+
|
|
382
435
|
// Add any extra request params
|
|
383
436
|
const extraParams = requestParams && typeof requestParams === 'object'
|
|
384
437
|
? requestParams as Record<string, unknown>
|
|
@@ -425,16 +478,24 @@ export default class ZnDataTable extends ZincElement {
|
|
|
425
478
|
private _hiddenCells: Map<string, Cell[]> = new Map();
|
|
426
479
|
private _secondaryHeaders: HeaderConfig[];
|
|
427
480
|
@state() private _deselectedColumns: Set<string> = new Set();
|
|
428
|
-
|
|
481
|
+
// Header keys in the order the user has dragged them into; keys not listed keep their configured order after these
|
|
482
|
+
@state() private _columnOrder: string[] = [];
|
|
483
|
+
private readonly reorderController = new ReorderController(this, {
|
|
484
|
+
axis: 'horizontal',
|
|
485
|
+
indicator: true,
|
|
486
|
+
// Plain arrows are left for scrolling the table
|
|
487
|
+
modifier: 'alt',
|
|
488
|
+
focus: key => this.columnCells(key)[0]?.focus(),
|
|
489
|
+
});
|
|
429
490
|
private _columnDefaultsApplied = false;
|
|
430
491
|
private _formatTemplates: Record<string, DisplayTemplate> = defaultTemplates;
|
|
431
492
|
|
|
432
493
|
requestParams: Record<string, any> = {};
|
|
433
494
|
|
|
434
|
-
refresh() {
|
|
495
|
+
refresh(): Promise<void> {
|
|
435
496
|
// Allow manual refresh to trigger the first data load when no-initial-load is set
|
|
436
497
|
this._initialLoad = false;
|
|
437
|
-
this._dataTask.run()
|
|
498
|
+
return this._dataTask.run();
|
|
438
499
|
}
|
|
439
500
|
|
|
440
501
|
// Headers that make up the visible columns, in header order
|
|
@@ -444,11 +505,78 @@ export default class ZnDataTable extends ZincElement {
|
|
|
444
505
|
|
|
445
506
|
// Headers the column select can toggle - everything but the permanently hidden and secondary ones
|
|
446
507
|
private selectableHeaders(): HeaderConfig[] {
|
|
447
|
-
|
|
508
|
+
const headers = (Object.values(this.headers) as HeaderConfig[]).filter((header: HeaderConfig) => {
|
|
448
509
|
if (header.hideHeader || header.hideColumn || header.secondary) return false;
|
|
449
510
|
|
|
450
511
|
return !Object.values(this.hiddenColumns).includes(header.key);
|
|
451
512
|
});
|
|
513
|
+
|
|
514
|
+
const rank = new Map(this._columnOrder.map((key, i) => [key, i]));
|
|
515
|
+
return headers.sort((a, b) => (rank.get(a.key) ?? headers.length) - (rank.get(b.key) ?? headers.length));
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/** @internal ReorderHost: the visible columns' keys in order. */
|
|
519
|
+
reorderKeys() {
|
|
520
|
+
return this.visibleHeaders().map(h => h.key);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** @internal ReorderHost: puts the visible columns in a new order, leaving deselected ones in their slots. */
|
|
524
|
+
applyReorder(keys: string[]) {
|
|
525
|
+
const visible = new Set(keys);
|
|
526
|
+
let i = 0;
|
|
527
|
+
this._columnOrder = this.selectableHeaders().map(h => visible.has(h.key) ? keys[i++] : h.key);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/** @internal ReorderHost: the heading drawn for a column. */
|
|
531
|
+
reorderRow(key: string) {
|
|
532
|
+
return this.columnCells(key)[0] ?? null;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/** @internal ReorderHost: the heading and every cell of a column. */
|
|
536
|
+
reorderSlides(key: string) {
|
|
537
|
+
return this.columnCells(key);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
private reorderable() {
|
|
541
|
+
return this.visibleHeaders().length > 1;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// One line over the whole table, as per-cell borders break where the heading meets the body
|
|
545
|
+
private renderDropLine() {
|
|
546
|
+
const dropIndex = this.reorderController.dropIndex;
|
|
547
|
+
if (dropIndex === null) return nothing;
|
|
548
|
+
|
|
549
|
+
const keys = this.reorderKeys();
|
|
550
|
+
const heading = this.reorderRow(keys[Math.min(dropIndex, keys.length - 1)]);
|
|
551
|
+
const table = heading?.closest('table');
|
|
552
|
+
const scroll = heading?.closest<HTMLElement>('.table__scroll');
|
|
553
|
+
if (!heading || !table || !scroll) return nothing;
|
|
554
|
+
|
|
555
|
+
const rect = heading.getBoundingClientRect();
|
|
556
|
+
const bounds = table.getBoundingClientRect();
|
|
557
|
+
// Held inside the table: a line poking past its edge widens the scroller, which then scrolls under the drag
|
|
558
|
+
const half = 1; // half of .table__drop-line's width
|
|
559
|
+
const edge = Math.min(Math.max(dropIndex === keys.length ? rect.right : rect.left, bounds.left + half), bounds.right - half);
|
|
560
|
+
const left = edge - scroll.getBoundingClientRect().left + scroll.scrollLeft;
|
|
561
|
+
return html`<div class="table__drop-line" style=${styleMap({left: `${left}px`})}></div>`;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/** @internal ReorderHost: a column lands anywhere over the table, not just its headings. */
|
|
565
|
+
reorderArea() {
|
|
566
|
+
return this.shadowRoot?.querySelector<HTMLElement>('.table__scroll table') ?? null;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/** @internal ReorderHost: the column's label, as a copy of the whole heading is unusable for a wide or wrapped one. */
|
|
570
|
+
reorderGhost(key: string) {
|
|
571
|
+
const header = (Object.values(this.headers) as HeaderConfig[]).find(h => h.key === key);
|
|
572
|
+
const ghost = document.createElement('div');
|
|
573
|
+
ghost.className = 'table__drag-ghost';
|
|
574
|
+
ghost.textContent = header?.label ?? key;
|
|
575
|
+
return ghost;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
private columnCells(key: string) {
|
|
579
|
+
return [...this.shadowRoot?.querySelectorAll<HTMLElement>(`[data-column="${CSS.escape(key)}"]`) ?? []];
|
|
452
580
|
}
|
|
453
581
|
|
|
454
582
|
private isColumnVisible(header: HeaderConfig): boolean {
|
|
@@ -716,7 +844,9 @@ export default class ZnDataTable extends ZincElement {
|
|
|
716
844
|
|| this.hasSlotController.test(ActionSlots.actions.valueOf())
|
|
717
845
|
|| this.hasSlotController.test(ActionSlots.create.valueOf())
|
|
718
846
|
|| this.hasSlotController.test(ActionSlots.sort.valueOf())
|
|
719
|
-
|| this.hasSlotController.test(ActionSlots.search.valueOf())
|
|
847
|
+
|| this.hasSlotController.test(ActionSlots.search.valueOf())
|
|
848
|
+
|| this.hasSlotController.test(ActionSlots.filter.valueOf())
|
|
849
|
+
|| this.filterFields.length > 0;
|
|
720
850
|
|
|
721
851
|
const hasInputs = this.hasSlotController.test(ActionSlots.inputs.valueOf());
|
|
722
852
|
const hasControls = hasActions || this.hasColumnSelect() || this.hasRefresh();
|
|
@@ -725,14 +855,6 @@ export default class ZnDataTable extends ZincElement {
|
|
|
725
855
|
// often bring their own panel for it, so let it stand on its own
|
|
726
856
|
const bareEmptyState = emptyBody && !hasControls && !this.caption;
|
|
727
857
|
|
|
728
|
-
// The filter bar is inline, so it gets its own row rather than a slot in the header
|
|
729
|
-
const filters = this.hasSlotController.test(ActionSlots.filter.valueOf())
|
|
730
|
-
? html`
|
|
731
|
-
<div class="table__filters" ?hidden="${!this._filtersOpen}">
|
|
732
|
-
<slot name="${ActionSlots.filter.valueOf()}"></slot>
|
|
733
|
-
</div>`
|
|
734
|
-
: nothing;
|
|
735
|
-
|
|
736
858
|
// Headers do not need to be re-rendered with new data
|
|
737
859
|
return html`
|
|
738
860
|
<div class="table-container" ${ref((el) => (this.tableContainer = el))}>
|
|
@@ -741,29 +863,42 @@ export default class ZnDataTable extends ZincElement {
|
|
|
741
863
|
<slot name="${ActionSlots.filter_top.valueOf()}"></slot>
|
|
742
864
|
${this.standalone && !bareEmptyState
|
|
743
865
|
? html`
|
|
744
|
-
<zn-panel caption="${ifDefined(this.caption || undefined)}"
|
|
866
|
+
<zn-panel caption="${ifDefined(this.caption || undefined)}"
|
|
867
|
+
description="${ifDefined(this.totalText())}"
|
|
868
|
+
?inline-description="${!!this.totalLabel}"
|
|
869
|
+
flush>
|
|
745
870
|
${hasControls ? html`
|
|
746
871
|
<div slot="actions" class="table__header__right">
|
|
747
872
|
${this.getActions()}
|
|
748
873
|
${this.getHeaderControls()}
|
|
749
874
|
</div>` : nothing}
|
|
750
|
-
${
|
|
875
|
+
${this.renderTabs()}
|
|
876
|
+
${this.renderFilterChips()}
|
|
877
|
+
${this.renderToolbar()}
|
|
751
878
|
${tableBody}
|
|
752
879
|
${this.getTableFooter('footer')}
|
|
753
880
|
</zn-panel>`
|
|
754
881
|
: html`
|
|
755
882
|
${hasControls || this.caption ? this.getTableHeader() : nothing}
|
|
756
|
-
${
|
|
883
|
+
${this.renderTabs()}
|
|
884
|
+
${this.renderFilterChips()}
|
|
885
|
+
${this.renderToolbar()}
|
|
757
886
|
${tableBody}
|
|
758
887
|
${this.getTableFooter()}`}
|
|
759
888
|
</div>
|
|
760
889
|
`;
|
|
761
890
|
}
|
|
762
891
|
|
|
892
|
+
protected willUpdate(changed: PropertyValues) {
|
|
893
|
+
super.willUpdate(changed);
|
|
894
|
+
this._fieldsFilter.filters = this.filterFields;
|
|
895
|
+
this._fieldsFilter.value = this.filter;
|
|
896
|
+
}
|
|
897
|
+
|
|
763
898
|
connectedCallback() {
|
|
764
899
|
super.connectedCallback();
|
|
765
900
|
this.addEventListener('zn-filter-change', this.filterChangeListener);
|
|
766
|
-
this.addEventListener('zn-
|
|
901
|
+
this._fieldsFilter.addEventListener('zn-filter-change', this.fieldsFilterChange);
|
|
767
902
|
this.addEventListener('zn-search-change', this.searchChangeListener);
|
|
768
903
|
// Capture defaults before reading the URL so URL values are treated as deltas, then seed state.
|
|
769
904
|
this._captureSharableDefaults();
|
|
@@ -816,15 +951,10 @@ export default class ZnDataTable extends ZincElement {
|
|
|
816
951
|
disconnectedCallback() {
|
|
817
952
|
super.disconnectedCallback();
|
|
818
953
|
this.removeEventListener('zn-filter-change', this.filterChangeListener);
|
|
819
|
-
this.removeEventListener('zn-
|
|
954
|
+
this._fieldsFilter.removeEventListener('zn-filter-change', this.fieldsFilterChange);
|
|
820
955
|
this.removeEventListener('zn-search-change', this.searchChangeListener);
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
// Clearing the filters leaves an empty row behind, so fold it away
|
|
824
|
-
filterClearListener = (e: Event) => {
|
|
825
|
-
if (e.target instanceof ZnDataTableFilter) {
|
|
826
|
-
this._filtersOpen = false;
|
|
827
|
-
}
|
|
956
|
+
this._headObserver?.disconnect();
|
|
957
|
+
this._headObserver = null;
|
|
828
958
|
}
|
|
829
959
|
|
|
830
960
|
filterChangeListener = (e: ZnFilterChangeEvent) => {
|
|
@@ -873,7 +1003,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
873
1003
|
emptyState() {
|
|
874
1004
|
if (this.isNarrowed || (this.noInitialLoad && !this._initialLoad)) {
|
|
875
1005
|
return html`
|
|
876
|
-
<div class="table--empty">
|
|
1006
|
+
<div class="table--empty table__enter">
|
|
877
1007
|
<slot name="no-results">
|
|
878
1008
|
<zn-empty-state caption="No Results Found" icon="search">
|
|
879
1009
|
<p>Nothing matched your search. Try adjusting your filters.</p>
|
|
@@ -883,7 +1013,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
883
1013
|
}
|
|
884
1014
|
|
|
885
1015
|
return html`
|
|
886
|
-
<div class="table--empty">
|
|
1016
|
+
<div class="table--empty table__enter">
|
|
887
1017
|
<slot name="empty-state">
|
|
888
1018
|
<zn-empty-state
|
|
889
1019
|
caption="${this.emptyStateCaption ? this.emptyStateCaption : (this.caption ? "No " + this.caption.toLowerCase() + " found" : "No data found")}"
|
|
@@ -1036,12 +1166,12 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1036
1166
|
const colCount = filteredHeaders.length + (this.rowHasActions ? 1 : 0) + (anyHidden ? 1 : 0) + (showCheckboxes ? 1 : 0);
|
|
1037
1167
|
|
|
1038
1168
|
return html`
|
|
1039
|
-
<div class="table__scroll">
|
|
1169
|
+
<div class="table__scroll table__enter">
|
|
1040
1170
|
<table class="${classMap({
|
|
1041
1171
|
'table': true,
|
|
1042
1172
|
'with-hover': !this.unsortable && this.isSelectable(),
|
|
1043
1173
|
})}">
|
|
1044
|
-
<thead>
|
|
1174
|
+
<thead ${ref(this.observeHead)}>
|
|
1045
1175
|
<tr>
|
|
1046
1176
|
${showCheckboxes ? this.renderSelectAllCheckbox() : nothing}
|
|
1047
1177
|
${anyHidden ? html`
|
|
@@ -1073,6 +1203,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1073
1203
|
`)}
|
|
1074
1204
|
</tbody>
|
|
1075
1205
|
</table>
|
|
1206
|
+
${this.renderDropLine()}
|
|
1076
1207
|
</div>
|
|
1077
1208
|
`;
|
|
1078
1209
|
}
|
|
@@ -1080,15 +1211,33 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1080
1211
|
// Pending and loaded states share this template so Lit keeps the table's DOM (and focus) across loads
|
|
1081
1212
|
private tableContent(content: TemplateResult, pending: boolean) {
|
|
1082
1213
|
return html`
|
|
1083
|
-
<div class="${classMap({'reduced-opacity': pending})}"
|
|
1214
|
+
<div class="${classMap({'table__frame': true, 'reduced-opacity': pending})}">
|
|
1215
|
+
${pending ? html`<div class="table__loader" aria-hidden="true"></div>` : nothing}
|
|
1216
|
+
${content}
|
|
1217
|
+
</div>`;
|
|
1084
1218
|
}
|
|
1085
1219
|
|
|
1220
|
+
private observeHead = (el: Element | undefined) => {
|
|
1221
|
+
this._headObserver?.disconnect();
|
|
1222
|
+
this._headObserver = null;
|
|
1223
|
+
if (!el) return;
|
|
1224
|
+
this._headObserver = new ResizeObserver(([entry]) => {
|
|
1225
|
+
const height = `${Math.round(entry.borderBoxSize[0].blockSize)}px`;
|
|
1226
|
+
if (this.style.getPropertyValue('--_head-height') !== height) {
|
|
1227
|
+
this.style.setProperty('--_head-height', height);
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
this._headObserver.observe(el);
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1086
1233
|
getTableHeader() {
|
|
1087
1234
|
return html`
|
|
1088
1235
|
<div class="table__header">
|
|
1089
1236
|
<div class="table__header__actions">
|
|
1090
1237
|
${this.caption ? html`
|
|
1091
1238
|
<h3 class="table__header__caption">${this.caption}</h3>` : nothing}
|
|
1239
|
+
${this.totalText() ? html`
|
|
1240
|
+
<span class="table__header__count">${this.totalText()}</span>` : nothing}
|
|
1092
1241
|
</div>
|
|
1093
1242
|
<div class="table__header__right">
|
|
1094
1243
|
${this.getActions()}
|
|
@@ -1098,13 +1247,73 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1098
1247
|
`;
|
|
1099
1248
|
}
|
|
1100
1249
|
|
|
1250
|
+
private totalText(): string | undefined {
|
|
1251
|
+
if (!this.totalLabel || !this._hasLoadedData) return undefined;
|
|
1252
|
+
// Narrowed by a search or filter: read as a share of the selected tab, e.g. "1 of 16"
|
|
1253
|
+
const tabCount = this.tabs.find(tab => tab.value === this.activeTab())?.count;
|
|
1254
|
+
if (this.isNarrowed && tabCount !== undefined && tabCount !== null && tabCount !== '') {
|
|
1255
|
+
return `${this._totalRows.toLocaleString()} of ${tabCount}`;
|
|
1256
|
+
}
|
|
1257
|
+
const label = this._totalRows === 1 && this.totalLabelSingular ? this.totalLabelSingular : this.totalLabel;
|
|
1258
|
+
return `${this._totalRows.toLocaleString()} ${label}`;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
private activeTab(): string {
|
|
1262
|
+
return this.tab || this.tabs[0]?.value || '';
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
private renderTabs() {
|
|
1266
|
+
return this._tabRow.render(this.tabs, this.activeTab(), this.pillTabs);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
private selectTab(value: string) {
|
|
1270
|
+
if (value === this.activeTab()) return;
|
|
1271
|
+
this.tab = value;
|
|
1272
|
+
this.page = 1;
|
|
1273
|
+
this._dataTask.run().then(r => r);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
private renderToolbar() {
|
|
1277
|
+
if (!this.hasSlotController.test('toolbar')) return nothing;
|
|
1278
|
+
|
|
1279
|
+
return html`
|
|
1280
|
+
<div class="table__toolbar" @zn-change="${this.toolbarChanged}" @change="${this.toolbarChanged}">
|
|
1281
|
+
<slot name="toolbar"></slot>
|
|
1282
|
+
</div>`;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
// zn-select and native fields can both announce one edit, so coalesce them into a single reload
|
|
1286
|
+
private _toolbarQueued = false;
|
|
1287
|
+
private toolbarChanged = () => {
|
|
1288
|
+
if (this._toolbarQueued) return;
|
|
1289
|
+
this._toolbarQueued = true;
|
|
1290
|
+
queueMicrotask(() => {
|
|
1291
|
+
this._toolbarQueued = false;
|
|
1292
|
+
this.page = 1;
|
|
1293
|
+
this._dataTask.run().then(r => r);
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
private toolbarParams(): Record<string, unknown> {
|
|
1298
|
+
const params: Record<string, unknown> = {};
|
|
1299
|
+
this.querySelectorAll('[slot="toolbar"]').forEach((slotted) => {
|
|
1300
|
+
[slotted, ...Array.from(slotted.querySelectorAll('[name]'))].forEach((field) => {
|
|
1301
|
+
const name = (field as AllowedInputElement).name || field.getAttribute('name');
|
|
1302
|
+
if (name && 'value' in field) {
|
|
1303
|
+
params[name] = (field as AllowedInputElement).value;
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
});
|
|
1307
|
+
return params;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1101
1310
|
private getHeaderControls() {
|
|
1102
1311
|
return html`
|
|
1312
|
+
<slot name="${ActionSlots.search.valueOf()}"></slot>
|
|
1313
|
+
${this.getFilter()}
|
|
1103
1314
|
${this.getColumnSelect()}
|
|
1104
|
-
${this.getFilterToggle()}
|
|
1105
1315
|
${this.getRefreshButton()}
|
|
1106
1316
|
<slot name="${ActionSlots.sort.valueOf()}"></slot>
|
|
1107
|
-
<slot name="${ActionSlots.search.valueOf()}"></slot>
|
|
1108
1317
|
<slot name="${ActionSlots.create.valueOf()}"></slot>`;
|
|
1109
1318
|
}
|
|
1110
1319
|
|
|
@@ -1113,42 +1322,34 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1113
1322
|
return this._hasLoadedData && this._lastLoadHadRows;
|
|
1114
1323
|
}
|
|
1115
1324
|
|
|
1116
|
-
private
|
|
1325
|
+
private getFilter() {
|
|
1326
|
+
if (this.filterFields.length > 0) return this._fieldsFilter;
|
|
1117
1327
|
if (!this.hasSlotController.test(ActionSlots.filter.valueOf())) return nothing;
|
|
1118
|
-
|
|
1119
|
-
const applied = this.appliedFilterCount();
|
|
1120
|
-
|
|
1121
|
-
return html`
|
|
1122
|
-
<zn-button icon-button="small"
|
|
1123
|
-
icon="funnel@lu"
|
|
1124
|
-
icon-size="18"
|
|
1125
|
-
tooltip="Filter"
|
|
1126
|
-
aria-label="Filter"
|
|
1127
|
-
muted-notifications
|
|
1128
|
-
notification="${applied || nothing}"
|
|
1129
|
-
aria-pressed="${this._filtersOpen}"
|
|
1130
|
-
class="${classMap({'table__header__toggle--active': applied > 0})}"
|
|
1131
|
-
@click="${this.toggleFilters}">
|
|
1132
|
-
</zn-button>`;
|
|
1328
|
+
return html`<slot name="${ActionSlots.filter.valueOf()}"></slot>`;
|
|
1133
1329
|
}
|
|
1134
1330
|
|
|
1135
|
-
private
|
|
1136
|
-
this.
|
|
1331
|
+
private filterSource(): ZnDataTableFilter | null {
|
|
1332
|
+
if (this.filterFields.length > 0) return this._fieldsFilter;
|
|
1333
|
+
return this.querySelector<ZnDataTableFilter>(':scope > zn-data-table-filter[slot="filter"]');
|
|
1137
1334
|
}
|
|
1138
1335
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
return Array.isArray(applied) ? applied.length : 0;
|
|
1145
|
-
} catch {
|
|
1146
|
-
return 0;
|
|
1147
|
-
}
|
|
1336
|
+
// The funnel sits in the header, so its chips get a filter of their own in a row under the tabs
|
|
1337
|
+
private renderFilterChips() {
|
|
1338
|
+
const source = this.filterSource();
|
|
1339
|
+
if (!source) return nothing;
|
|
1340
|
+
return html`<zn-data-table-filter class="table__chips" .source="${source}"></zn-data-table-filter>`;
|
|
1148
1341
|
}
|
|
1149
1342
|
|
|
1343
|
+
private fieldsFilterChange = (e: Event) => {
|
|
1344
|
+
e.stopPropagation();
|
|
1345
|
+
this.filter = this._fieldsFilter.value;
|
|
1346
|
+
this.page = 1;
|
|
1347
|
+
this._dataTask.run().then(r => r);
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1150
1350
|
private hasColumnSelect(): boolean {
|
|
1151
|
-
|
|
1351
|
+
const headers = this.selectableHeaders();
|
|
1352
|
+
return !this.hideColumnSelect && this.hasRows() && headers.length > 1 && headers.some(h => h.required !== true);
|
|
1152
1353
|
}
|
|
1153
1354
|
|
|
1154
1355
|
private hasRefresh(): boolean {
|
|
@@ -1208,18 +1409,21 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1208
1409
|
|
|
1209
1410
|
if (rowSelected === null && pagination === null && rowsPerPage === null) return null;
|
|
1210
1411
|
|
|
1412
|
+
const first = (this.page - 1) * this.itemsPerPage + 1;
|
|
1413
|
+
const last = Math.min(this.page * this.itemsPerPage, this._totalRows);
|
|
1414
|
+
|
|
1211
1415
|
return html`
|
|
1212
1416
|
<div class="${classMap({
|
|
1213
1417
|
'table__footer': true,
|
|
1214
1418
|
'table__footer--panel': !!slot,
|
|
1215
1419
|
})}" slot="${ifDefined(slot)}">
|
|
1216
1420
|
<div class="table__footer__left">
|
|
1217
|
-
${
|
|
1421
|
+
${this._totalRows > 0 ? html`
|
|
1422
|
+
<span>${first.toLocaleString()}–${last.toLocaleString()} of ${this._totalRows.toLocaleString()}</span>` : nothing}
|
|
1218
1423
|
${rowSelected}
|
|
1219
1424
|
</div>
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
</div>
|
|
1425
|
+
${pagination}
|
|
1426
|
+
${rowsPerPage}
|
|
1223
1427
|
</div>`;
|
|
1224
1428
|
}
|
|
1225
1429
|
|
|
@@ -1227,13 +1431,13 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1227
1431
|
if (this.selectedRows.length <= 0) return null;
|
|
1228
1432
|
|
|
1229
1433
|
return html`
|
|
1230
|
-
<
|
|
1434
|
+
<span>${this.numberOfRowsSelected} of ${this._rows.length} rows selected</span>`
|
|
1231
1435
|
}
|
|
1232
1436
|
|
|
1233
1437
|
getRowsPerPage() {
|
|
1234
1438
|
if (this.hidePagination) return null;
|
|
1235
1439
|
|
|
1236
|
-
const optionsRowsPerPage = [10,
|
|
1440
|
+
const optionsRowsPerPage = [10, 25, 50, 100];
|
|
1237
1441
|
|
|
1238
1442
|
// Keyed to the dataset, not the current page size - raising the size past the total
|
|
1239
1443
|
// must not hide the only control that can lower it again
|
|
@@ -1241,7 +1445,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1241
1445
|
|
|
1242
1446
|
return html`
|
|
1243
1447
|
<div class="table__footer__rows-per-page">
|
|
1244
|
-
<
|
|
1448
|
+
<span>Rows</span>
|
|
1245
1449
|
<zn-select name="rowPerPage"
|
|
1246
1450
|
size="small"
|
|
1247
1451
|
value="${this.itemsPerPage}"
|
|
@@ -1255,57 +1459,59 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1255
1459
|
</div>`;
|
|
1256
1460
|
}
|
|
1257
1461
|
|
|
1258
|
-
// A window of PAGE_WINDOW pages
|
|
1259
|
-
//
|
|
1260
|
-
private getPageRange(): number[] {
|
|
1462
|
+
// A window of PAGE_WINDOW pages around the current one, plus the first and last pages;
|
|
1463
|
+
// null marks a gap, except a gap of one page, which shows that page instead
|
|
1464
|
+
private getPageRange(): (number | null)[] {
|
|
1261
1465
|
const size = Math.min(PAGE_WINDOW, this.totalPages);
|
|
1262
1466
|
const start = Math.min(
|
|
1263
1467
|
Math.max(1, this.page - Math.floor(size / 2)),
|
|
1264
1468
|
this.totalPages - size + 1
|
|
1265
1469
|
);
|
|
1470
|
+
const pages = [...new Set([1, ...Array.from({length: size}, (_, i) => start + i), this.totalPages])];
|
|
1266
1471
|
|
|
1267
|
-
return
|
|
1472
|
+
return pages.flatMap((p, i) => {
|
|
1473
|
+
const gap = i > 0 ? p - pages[i - 1] : 1;
|
|
1474
|
+
if (gap === 2) return [p - 1, p];
|
|
1475
|
+
return gap > 2 ? [null, p] : [p];
|
|
1476
|
+
});
|
|
1268
1477
|
}
|
|
1269
1478
|
|
|
1270
1479
|
getPagination() {
|
|
1271
1480
|
if (this.hidePagination || this.totalPages <= 1) return null;
|
|
1272
1481
|
|
|
1273
1482
|
return html`
|
|
1274
|
-
<
|
|
1275
|
-
<zn-button
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
icon-button="small"
|
|
1279
|
-
label="First page">
|
|
1280
|
-
</zn-button>
|
|
1281
|
-
<zn-button @click="${this.page !== 1 ? this.goToPreviousPage : undefined}"
|
|
1282
|
-
?disabled="${this.page === 1}"
|
|
1483
|
+
<div class="table__footer__pages">
|
|
1484
|
+
<zn-button class="table__footer__page"
|
|
1485
|
+
color="transparent"
|
|
1486
|
+
size="small"
|
|
1283
1487
|
icon="chevron-left@lu"
|
|
1284
|
-
icon-
|
|
1285
|
-
|
|
1488
|
+
icon-size="16"
|
|
1489
|
+
?disabled="${this.page === 1}"
|
|
1490
|
+
aria-label="Previous page"
|
|
1491
|
+
@click="${this.goToPreviousPage}">
|
|
1286
1492
|
</zn-button>
|
|
1287
|
-
${this.getPageRange().map((p
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1493
|
+
${this.getPageRange().map((p) => p === null
|
|
1494
|
+
? html`<span class="table__footer__gap">…</span>`
|
|
1495
|
+
: html`
|
|
1496
|
+
<zn-button class="${classMap({
|
|
1497
|
+
'table__footer__page': true,
|
|
1498
|
+
'table__footer__page--active': p === this.page,
|
|
1499
|
+
})}"
|
|
1500
|
+
color="transparent"
|
|
1501
|
+
size="small"
|
|
1502
|
+
aria-current="${ifDefined(p === this.page ? 'page' : undefined)}"
|
|
1503
|
+
@click="${p !== this.page ? () => this.goToPage(p) : undefined}">${p}
|
|
1504
|
+
</zn-button>`)}
|
|
1505
|
+
<zn-button class="table__footer__page"
|
|
1506
|
+
color="transparent"
|
|
1507
|
+
size="small"
|
|
1298
1508
|
icon="chevron-right@lu"
|
|
1299
|
-
icon-
|
|
1300
|
-
label="Next page">
|
|
1301
|
-
</zn-button>
|
|
1302
|
-
<zn-button @click="${this.page !== this.totalPages ? this.goToLastPage : undefined}"
|
|
1509
|
+
icon-size="16"
|
|
1303
1510
|
?disabled="${this.page === this.totalPages}"
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
label="Last page">
|
|
1511
|
+
aria-label="Next page"
|
|
1512
|
+
@click="${this.goToNextPage}">
|
|
1307
1513
|
</zn-button>
|
|
1308
|
-
</
|
|
1514
|
+
</div>`;
|
|
1309
1515
|
}
|
|
1310
1516
|
|
|
1311
1517
|
getActions() {
|
|
@@ -1360,10 +1566,17 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1360
1566
|
</zn-menu>
|
|
1361
1567
|
</zn-dropdown>
|
|
1362
1568
|
<div class="table__actions-source">
|
|
1363
|
-
<slot name="${ActionSlots.actions.valueOf()}"></slot>
|
|
1569
|
+
<slot name="${ActionSlots.actions.valueOf()}" @slotchange="${this.hideActionSources}"></slot>
|
|
1364
1570
|
</div>`;
|
|
1365
1571
|
}
|
|
1366
1572
|
|
|
1573
|
+
// Inert per item rather than on the wrapper: an inert ancestor would also make a zn-confirm's modal dialog inert
|
|
1574
|
+
private hideActionSources = (event: Event) => {
|
|
1575
|
+
(event.target as HTMLSlotElement).assignedElements().forEach(el => {
|
|
1576
|
+
if (!(el instanceof ZnConfirm)) (el as HTMLElement).inert = true;
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1367
1580
|
private actionTrigger(item: HTMLElement): HTMLElement | null {
|
|
1368
1581
|
if (item instanceof ZnConfirm) {
|
|
1369
1582
|
return item.querySelector<HTMLElement>(':scope > [slot="trigger"]');
|
|
@@ -1390,12 +1603,24 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1390
1603
|
}
|
|
1391
1604
|
|
|
1392
1605
|
goToPage(page: number) {
|
|
1606
|
+
const focused = this.shadowRoot?.activeElement;
|
|
1393
1607
|
this.page = page;
|
|
1394
1608
|
this.selectedRows = [];
|
|
1395
1609
|
this.numberOfRowsSelected = 0;
|
|
1396
1610
|
this._dataTask.run().then(r => r);
|
|
1397
1611
|
|
|
1398
1612
|
this.resizeObserver.observe(this);
|
|
1613
|
+
|
|
1614
|
+
if (focused instanceof ZnButton && focused.classList.contains('table__footer__page')) {
|
|
1615
|
+
this.keepPagerFocus(focused);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
private async keepPagerFocus(button: ZnButton) {
|
|
1620
|
+
await this.updateComplete;
|
|
1621
|
+
if (button.disabled || !button.isConnected) {
|
|
1622
|
+
this.shadowRoot?.querySelector<ZnButton>('.table__footer__page--active')?.button?.focus();
|
|
1623
|
+
}
|
|
1399
1624
|
}
|
|
1400
1625
|
|
|
1401
1626
|
goToFirstPage() {
|
|
@@ -1559,10 +1784,14 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1559
1784
|
}
|
|
1560
1785
|
|
|
1561
1786
|
if (data.uri) {
|
|
1787
|
+
// A browser target such as _blank opens outside the console, which only leaves links with a target alone
|
|
1788
|
+
const browserTarget = data.target?.startsWith('_') ? data.target : undefined;
|
|
1562
1789
|
content = html`
|
|
1563
1790
|
<a href="${data.uri}"
|
|
1564
1791
|
title="${ifDefined(data.title)}"
|
|
1565
|
-
|
|
1792
|
+
target="${ifDefined(browserTarget || nothing)}"
|
|
1793
|
+
rel="${ifDefined(browserTarget ? 'noopener noreferrer' : nothing)}"
|
|
1794
|
+
data-target="${ifDefined(browserTarget ? nothing : (data.target || nothing))}"
|
|
1566
1795
|
gaid="${ifDefined(data.gaid || nothing)}">${content}</a>`;
|
|
1567
1796
|
}
|
|
1568
1797
|
|
|
@@ -1571,6 +1800,11 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1571
1800
|
<zn-chip type="${data.chipColor}" title="${ifDefined(data.title)}">${content}</zn-chip>`;
|
|
1572
1801
|
}
|
|
1573
1802
|
|
|
1803
|
+
if (data.badgeType) {
|
|
1804
|
+
content = html`
|
|
1805
|
+
<zn-badge type="${data.badgeType}" ?dot="${data.badgeDot}" title="${ifDefined(data.title)}">${content}</zn-badge>`;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1574
1808
|
|
|
1575
1809
|
if (data.iconSrc) {
|
|
1576
1810
|
const src = data.iconSrc;
|
|
@@ -1648,47 +1882,36 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1648
1882
|
}
|
|
1649
1883
|
}
|
|
1650
1884
|
|
|
1651
|
-
private getTableSortIcon(key: any) {
|
|
1652
|
-
if (this.sortColumn !== key) {
|
|
1653
|
-
return html`
|
|
1654
|
-
<div class="table__head__sort">
|
|
1655
|
-
<zn-icon src="chevrons_up_down@lu" size="14"></zn-icon>
|
|
1656
|
-
</div>`;
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
if (this.sortDirection === 'asc') {
|
|
1660
|
-
return html`
|
|
1661
|
-
<div class="table__head__sort table__head__sort--active">
|
|
1662
|
-
<zn-icon src="chevron_down@lu" size="16"></zn-icon>
|
|
1663
|
-
</div>`;
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
return html`
|
|
1667
|
-
<div class="table__head__sort table__head__sort--active">
|
|
1668
|
-
<zn-icon src="chevron_up@lu" size="16"></zn-icon>
|
|
1669
|
-
</div>`;
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
1885
|
private renderCellHeader(header: HeaderConfig) {
|
|
1673
1886
|
const sortable = !Object.values(this.unsortableHeaders).includes(header.key) && !Object.values(this.hiddenHeaders).includes(header.key) && !this.unsortable && header.sortable !== false;
|
|
1674
1887
|
|
|
1675
1888
|
const lastVisibleHeaderKey = this.visibleHeaders().slice(-1)[0]?.key;
|
|
1889
|
+
const reorderable = this.reorderable();
|
|
1676
1890
|
|
|
1677
1891
|
return html`
|
|
1678
1892
|
<th
|
|
1893
|
+
data-column="${header.key}"
|
|
1679
1894
|
class="${classMap({
|
|
1680
1895
|
'table__head': true,
|
|
1681
1896
|
'table__head--wide': header.key === this.wideColumn,
|
|
1682
1897
|
'table__head--last': header.key === lastVisibleHeaderKey,
|
|
1683
1898
|
'table__head--hidden': Object.values(this.hiddenHeaders).includes(header.key),
|
|
1899
|
+
'table__head--dragging': header.key === this.reorderController.draggedKey,
|
|
1900
|
+
'table__head--reorderable': reorderable,
|
|
1901
|
+
|
|
1902
|
+
[`table__head--${header.align}`]: !!header.align,
|
|
1684
1903
|
})}"
|
|
1685
|
-
tabindex="${ifDefined(sortable ? '0' : undefined)}"
|
|
1904
|
+
tabindex="${ifDefined(sortable || reorderable ? '0' : undefined)}"
|
|
1686
1905
|
aria-sort="${ifDefined(sortable ? this.sortState(header.key) : undefined)}"
|
|
1906
|
+
aria-description="${ifDefined(reorderable ? 'Alt + arrow keys to move column' : undefined)}"
|
|
1687
1907
|
@click="${sortable ? this.updateSort(header.key) : undefined}"
|
|
1688
|
-
@keydown="${
|
|
1908
|
+
@keydown="${(e: KeyboardEvent) => {
|
|
1909
|
+
if (!this.reorderController.handleKeyDown(e, header.key) && sortable) sortKeyHandler(this.updateSort(header.key))(e);
|
|
1910
|
+
}}"
|
|
1911
|
+
@pointerdown="${reorderable ? (e: PointerEvent) => this.reorderController.handlePointerDown(e, header.key) : undefined}">
|
|
1689
1912
|
<div>
|
|
1690
1913
|
${header.label}
|
|
1691
|
-
${sortable ? this.
|
|
1914
|
+
${sortable ? renderSortIcon(this.sortState(header.key)) : nothing}
|
|
1692
1915
|
</div>
|
|
1693
1916
|
</th>
|
|
1694
1917
|
`;
|
|
@@ -1699,12 +1922,6 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1699
1922
|
return this.sortDirection === 'asc' ? 'ascending' : 'descending';
|
|
1700
1923
|
}
|
|
1701
1924
|
|
|
1702
|
-
private handleSortKeyDown(e: KeyboardEvent, key: string) {
|
|
1703
|
-
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
1704
|
-
e.preventDefault();
|
|
1705
|
-
this.updateSort(key)();
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
1925
|
private renderCellBody(index: number, value: Cell, row: Row) {
|
|
1709
1926
|
const filteredHeaders = this.visibleHeaders();
|
|
1710
1927
|
const header: HeaderConfig | undefined = filteredHeaders[index];
|
|
@@ -1712,11 +1929,15 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1712
1929
|
|
|
1713
1930
|
return html`
|
|
1714
1931
|
<td
|
|
1932
|
+
data-column="${ifDefined(headerKey)}"
|
|
1715
1933
|
@click="${this.isSelectable() ? this.selectRow : undefined}"
|
|
1716
1934
|
class="${classMap({
|
|
1717
1935
|
'table__cell': true,
|
|
1936
|
+
'table__cell--dragging': !!headerKey && headerKey === this.reorderController.draggedKey,
|
|
1937
|
+
|
|
1718
1938
|
'table__cell--wide': headerKey === this.wideColumn,
|
|
1719
1939
|
'table__cell--last': index === filteredHeaders.length - 1,
|
|
1940
|
+
[`table__cell--${header?.align}`]: !!header?.align,
|
|
1720
1941
|
})}">
|
|
1721
1942
|
<div>${this.renderCell(value, row, header)}</div>
|
|
1722
1943
|
</td>`;
|
|
@@ -1801,8 +2022,9 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1801
2022
|
if (changed) this.updateKeys();
|
|
1802
2023
|
}
|
|
1803
2024
|
|
|
2025
|
+
/** Rows are selectable when an action works on the selection; creating does not. */
|
|
1804
2026
|
private isSelectable(): boolean {
|
|
1805
|
-
return [ActionSlots.delete, ActionSlots.modify, ActionSlots.actions
|
|
2027
|
+
return [ActionSlots.delete, ActionSlots.modify, ActionSlots.actions]
|
|
1806
2028
|
.some(slot => this.hasSlotController.test(slot.valueOf()));
|
|
1807
2029
|
}
|
|
1808
2030
|
|
|
@@ -1926,7 +2148,7 @@ export default class ZnDataTable extends ZincElement {
|
|
|
1926
2148
|
|
|
1927
2149
|
private loadingTable() {
|
|
1928
2150
|
return html`
|
|
1929
|
-
<div class="table__scroll">
|
|
2151
|
+
<div class="table__scroll table__enter">
|
|
1930
2152
|
<table class="table">
|
|
1931
2153
|
<thead>
|
|
1932
2154
|
<tr>
|