@redvars/peacock 3.2.10 → 3.3.1
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/dist/{PeacockComponent-CxJc63xj.js → IndividualComponent-tDnXrOLV.js} +3 -3
- package/dist/IndividualComponent-tDnXrOLV.js.map +1 -0
- package/dist/assets/components.css +1 -1
- package/dist/assets/components.css.map +1 -1
- package/dist/assets/styles.css +1 -1
- package/dist/assets/styles.css.map +1 -1
- package/dist/button-group-DA7xoziD.js +292 -0
- package/dist/button-group-DA7xoziD.js.map +1 -0
- package/dist/button-group.js +6 -107
- package/dist/button-group.js.map +1 -1
- package/dist/{button-DaL4va7Q.js → button-trIfcqC7.js} +21 -35
- package/dist/button-trIfcqC7.js.map +1 -0
- package/dist/button.js +5 -5
- package/dist/chart-donut.js +307 -0
- package/dist/chart-donut.js.map +1 -0
- package/dist/chart-doughnut.js +307 -0
- package/dist/chart-doughnut.js.map +1 -0
- package/dist/chart-pie.js +259 -0
- package/dist/chart-pie.js.map +1 -0
- package/dist/{class-map-BvQRv7eW.js → class-map-hJdvjl-W.js} +9 -3
- package/dist/class-map-hJdvjl-W.js.map +1 -0
- package/dist/clock.js +5 -6
- package/dist/clock.js.map +1 -1
- package/dist/code-editor.js +38 -25
- package/dist/code-editor.js.map +1 -1
- package/dist/code-highlighter.js +10 -14
- package/dist/code-highlighter.js.map +1 -1
- package/dist/custom-elements-jsdocs.json +8144 -3654
- package/dist/custom-elements.json +7925 -3901
- package/dist/{dispatch-event-utils-vbdiOSeC.js → dispatch-event-utils-B4odODQf.js} +2 -15
- package/dist/dispatch-event-utils-B4odODQf.js.map +1 -0
- package/dist/index.js +13 -10
- package/dist/index.js.map +1 -1
- package/dist/number-counter.js +12 -10
- package/dist/number-counter.js.map +1 -1
- package/dist/{observe-theme-change-NneLARW8.js → observe-theme-change-BISF-Gl5.js} +2 -2
- package/dist/{observe-theme-change-NneLARW8.js.map → observe-theme-change-BISF-Gl5.js.map} +1 -1
- package/dist/peacock-loader.js +94 -502
- package/dist/peacock-loader.js.map +1 -1
- package/dist/query-QBcUV-L_.js +15 -0
- package/dist/query-QBcUV-L_.js.map +1 -0
- package/dist/src/IndividualComponent.d.ts +1 -0
- package/dist/src/accordion/{accordion-item/accordion-item.d.ts → accordion-item.d.ts} +5 -4
- package/dist/src/accordion/{accordion/accordion.d.ts → accordion.d.ts} +6 -6
- package/dist/src/accordion/{accordion-item/index.d.ts → index.d.ts} +1 -0
- package/dist/src/avatar/avatar.d.ts +2 -2
- package/dist/src/badge/badge.d.ts +2 -2
- package/dist/src/breadcrumb/breadcrumb/breadcrumb.d.ts +9 -8
- package/dist/src/breadcrumb/breadcrumb-item/breadcrumb-item.d.ts +4 -3
- package/dist/src/button/button/button.d.ts +2 -2
- package/dist/src/button/button-group/button-group.d.ts +9 -5
- package/dist/src/button/icon-button/icon-button.d.ts +2 -2
- package/dist/src/chart-donut/chart-donut.d.ts +53 -0
- package/dist/src/chart-donut/index.d.ts +1 -0
- package/dist/src/chart-doughnut/chart-doughnut.d.ts +53 -0
- package/dist/src/chart-doughnut/index.d.ts +1 -0
- package/dist/src/chart-pie/chart-pie.d.ts +50 -0
- package/dist/src/chart-pie/index.d.ts +1 -0
- package/dist/src/checkbox/checkbox.d.ts +3 -6
- package/dist/src/chip/chip/chip.d.ts +4 -4
- package/dist/src/chip/tag/tag.d.ts +3 -3
- package/dist/src/clock/clock.d.ts +3 -4
- package/dist/src/code-editor/code-editor.d.ts +13 -10
- package/dist/src/code-highlighter/code-highlighter.d.ts +4 -7
- package/dist/src/container/container.d.ts +6 -11
- package/dist/src/date-picker/date-picker.d.ts +3 -3
- package/dist/src/divider/divider.d.ts +2 -2
- package/dist/src/elevation/elevation.d.ts +2 -2
- package/dist/src/empty-state/empty-state.d.ts +9 -2
- package/dist/src/field/field.d.ts +17 -0
- package/dist/src/focus-ring/focus-ring.d.ts +1 -1
- package/dist/src/icon/icon.d.ts +2 -2
- package/dist/src/image/image.d.ts +4 -12
- package/dist/src/index.d.ts +9 -1
- package/dist/src/input/input.d.ts +2 -2
- package/dist/src/link/link.d.ts +4 -5
- package/dist/src/menu/index.d.ts +3 -0
- package/dist/src/menu/menu/MenuSurfaceController.d.ts +18 -0
- package/dist/src/menu/menu/menu.d.ts +66 -8
- package/dist/src/menu/menu-item/menu-item.d.ts +24 -5
- package/dist/src/menu/sub-menu/sub-menu.d.ts +36 -0
- package/dist/src/number-counter/number-counter.d.ts +9 -7
- package/dist/src/number-field/number-field.d.ts +1 -1
- package/dist/src/pagination/index.d.ts +1 -0
- package/dist/src/pagination/pagination.d.ts +38 -0
- package/dist/src/popover/PopoverController.d.ts +4 -1
- package/dist/src/popover/index.d.ts +1 -1
- package/dist/src/progress/circular-progress/circular-progress.d.ts +3 -3
- package/dist/src/progress/linear-progress/linear-progress.d.ts +3 -3
- package/dist/src/ripple/ripple.d.ts +60 -4
- package/dist/src/skeleton/skeleton.d.ts +6 -5
- package/dist/src/slider/index.d.ts +1 -0
- package/dist/src/slider/slider.d.ts +52 -0
- package/dist/src/spinner/spinner.d.ts +2 -2
- package/dist/src/switch/switch.d.ts +2 -2
- package/dist/src/table/index.d.ts +1 -0
- package/dist/src/table/table.d.ts +110 -0
- package/dist/src/tabs/index.d.ts +4 -0
- package/dist/src/tabs/tab-group.d.ts +45 -0
- package/dist/src/tabs/tab-panel.d.ts +22 -0
- package/dist/src/tabs/tab.d.ts +59 -0
- package/dist/src/tabs/tabs.d.ts +29 -0
- package/dist/src/textarea/textarea.d.ts +3 -3
- package/dist/src/time-picker/time-picker.d.ts +3 -3
- package/dist/src/{popover/tooltip → tooltip}/tooltip.d.ts +4 -3
- package/dist/src/tree-view/index.d.ts +2 -0
- package/dist/src/tree-view/tree-node.d.ts +69 -0
- package/dist/src/tree-view/tree-view.d.ts +40 -0
- package/dist/src/tree-view/wc-tree-view.d.ts +6 -0
- package/dist/{style-map-B8xgVEc9.js → style-map-CfNHEkQp.js} +2 -2
- package/dist/{style-map-B8xgVEc9.js.map → style-map-CfNHEkQp.js.map} +1 -1
- package/dist/test/icon.test.d.ts +1 -1
- package/dist/test/menu.test.d.ts +1 -0
- package/dist/test/sub-menu.test.d.ts +1 -0
- package/dist/test/tree-view.test.d.ts +1 -0
- package/dist/transform-DRuHEvar.js +3312 -0
- package/dist/transform-DRuHEvar.js.map +1 -0
- package/dist/{image-v3BujlY5.js → tree-view-CLolVlU0.js} +4088 -672
- package/dist/tree-view-CLolVlU0.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/{unsafe-html-B-dV3Jps.js → unsafe-html-CV6Je6HL.js} +2 -2
- package/dist/{unsafe-html-B-dV3Jps.js.map → unsafe-html-CV6Je6HL.js.map} +1 -1
- package/package.json +3 -1
- package/readme.md +40 -40
- package/src/{PeacockComponent.ts → IndividualComponent.ts} +1 -1
- package/src/accordion/{accordion-item/accordion-item.scss → accordion-item.scss} +1 -1
- package/src/accordion/{accordion-item/accordion-item.ts → accordion-item.ts} +7 -6
- package/src/accordion/{accordion/accordion.scss → accordion.scss} +2 -1
- package/src/accordion/{accordion/accordion.ts → accordion.ts} +6 -6
- package/src/accordion/{accordion-item/index.ts → index.ts} +2 -0
- package/src/avatar/avatar.ts +2 -2
- package/src/badge/badge.ts +2 -2
- package/src/breadcrumb/breadcrumb/breadcrumb.ts +10 -8
- package/src/breadcrumb/breadcrumb-item/breadcrumb-item.ts +4 -3
- package/src/button/BaseButton.ts +1 -1
- package/src/button/button/button.scss +9 -23
- package/src/button/button/button.ts +8 -8
- package/src/button/button-group/button-group.ts +13 -7
- package/src/button/icon-button/icon-button.ts +8 -8
- package/src/chart-donut/chart-donut.scss +37 -0
- package/src/chart-donut/chart-donut.ts +287 -0
- package/src/chart-donut/demo/index.html +51 -0
- package/src/chart-donut/index.ts +1 -0
- package/src/chart-doughnut/chart-donut.scss +37 -0
- package/src/chart-doughnut/chart-doughnut.ts +287 -0
- package/src/chart-doughnut/demo/index.html +51 -0
- package/src/chart-doughnut/index.ts +1 -0
- package/src/chart-pie/chart-pie.scss +27 -0
- package/src/chart-pie/chart-pie.ts +256 -0
- package/src/chart-pie/demo/index.html +51 -0
- package/src/chart-pie/index.ts +1 -0
- package/src/checkbox/checkbox.ts +3 -6
- package/src/chip/chip/chip.ts +6 -6
- package/src/chip/tag/tag.ts +6 -6
- package/src/clock/clock.ts +5 -6
- package/src/code-editor/code-editor.scss +3 -5
- package/src/code-editor/code-editor.ts +32 -16
- package/src/code-highlighter/code-highlighter.ts +8 -11
- package/src/container/container.ts +6 -11
- package/src/date-picker/date-picker.ts +7 -7
- package/src/divider/divider.scss +2 -2
- package/src/divider/divider.ts +2 -2
- package/src/elevation/elevation.ts +2 -2
- package/src/empty-state/empty-state.scss +1 -1
- package/src/empty-state/empty-state.ts +10 -3
- package/src/field/field.scss +4 -4
- package/src/field/field.ts +19 -2
- package/src/focus-ring/focus-ring.scss +2 -1
- package/src/focus-ring/focus-ring.ts +1 -1
- package/src/icon/icon.ts +2 -2
- package/src/icon/p-icon.ts +1 -1
- package/src/image/image.ts +4 -12
- package/src/index.ts +11 -3
- package/src/input/input.ts +6 -6
- package/src/link/link.ts +4 -5
- package/src/menu/index.ts +3 -0
- package/src/menu/menu/MenuSurfaceController.ts +61 -0
- package/src/menu/{menu-list/menu-list.scss → menu/menu.scss} +19 -4
- package/src/menu/menu/menu.ts +401 -77
- package/src/menu/menu-item/menu-item-colors.scss +2 -2
- package/src/menu/menu-item/menu-item.ts +128 -37
- package/src/menu/sub-menu/sub-menu.scss +7 -0
- package/src/menu/sub-menu/sub-menu.ts +243 -0
- package/src/number-counter/demo/index.html +1 -1
- package/src/number-counter/number-counter.ts +11 -9
- package/src/number-field/number-field.ts +7 -7
- package/src/pagination/index.ts +1 -0
- package/src/pagination/pagination.scss +59 -0
- package/src/pagination/pagination.ts +135 -0
- package/src/peacock-loader.ts +92 -51
- package/src/popover/PopoverController.ts +13 -7
- package/src/popover/index.ts +1 -1
- package/src/progress/circular-progress/circular-progress.scss +1 -1
- package/src/progress/circular-progress/circular-progress.ts +3 -3
- package/src/progress/linear-progress/linear-progress.ts +3 -3
- package/src/ripple/ripple.ts +478 -94
- package/src/skeleton/skeleton.ts +6 -5
- package/src/slider/index.ts +1 -0
- package/src/slider/slider.scss +130 -0
- package/src/slider/slider.ts +178 -0
- package/src/spinner/spinner.ts +2 -2
- package/src/switch/switch.ts +4 -4
- package/src/table/index.ts +1 -0
- package/src/table/table.scss +174 -0
- package/src/table/table.ts +475 -0
- package/src/tabs/index.ts +4 -0
- package/src/tabs/tab-group.scss +10 -0
- package/src/tabs/tab-group.ts +143 -0
- package/src/tabs/tab-panel.scss +12 -0
- package/src/tabs/tab-panel.ts +29 -0
- package/src/tabs/tab.scss +157 -0
- package/src/tabs/tab.ts +243 -0
- package/src/tabs/tabs.scss +19 -0
- package/src/tabs/tabs.ts +66 -0
- package/src/text/text.css-component.scss +6 -3
- package/src/textarea/textarea.ts +5 -5
- package/src/time-picker/time-picker.ts +7 -7
- package/src/{popover/tooltip → tooltip}/tooltip.scss +17 -14
- package/src/{popover/tooltip → tooltip}/tooltip.ts +12 -10
- package/src/tree-view/demo/index.html +57 -0
- package/src/tree-view/index.ts +2 -0
- package/src/tree-view/tree-node.scss +101 -0
- package/src/tree-view/tree-node.ts +268 -0
- package/src/tree-view/tree-view.scss +12 -0
- package/src/tree-view/tree-view.ts +182 -0
- package/src/tree-view/wc-tree-view.ts +9 -0
- package/dist/PeacockComponent-CxJc63xj.js.map +0 -1
- package/dist/button-DaL4va7Q.js.map +0 -1
- package/dist/class-map-BvQRv7eW.js.map +0 -1
- package/dist/dispatch-event-utils-vbdiOSeC.js.map +0 -1
- package/dist/image-v3BujlY5.js.map +0 -1
- package/dist/src/PeacockComponent.d.ts +0 -1
- package/dist/src/accordion/accordion/index.d.ts +0 -1
- package/dist/src/avatar/p-avatar.d.ts +0 -3
- package/dist/src/badge/p-badge.d.ts +0 -3
- package/dist/src/menu/menu-list/menu-list.d.ts +0 -7
- package/dist/state-B09bP3XH.js +0 -10
- package/dist/state-B09bP3XH.js.map +0 -1
- package/src/accordion/accordion/index.ts +0 -1
- package/src/avatar/p-avatar.ts +0 -5
- package/src/badge/p-badge.ts +0 -5
- package/src/menu/menu-list/menu-list.ts +0 -33
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import { html, LitElement, nothing } from 'lit';
|
|
2
|
+
import { property, state } from 'lit/decorators.js';
|
|
3
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
5
|
+
import { throttle } from '../utils.js';
|
|
6
|
+
import styles from './table.scss';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_CELL_WIDTH = 16; // in rem
|
|
9
|
+
|
|
10
|
+
export interface TableColumn {
|
|
11
|
+
name: string;
|
|
12
|
+
label: string;
|
|
13
|
+
width?: number;
|
|
14
|
+
fixed?: boolean;
|
|
15
|
+
template?: (row: any, column: TableColumn) => string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @label Table
|
|
20
|
+
* @tag wc-table
|
|
21
|
+
* @rawTag table
|
|
22
|
+
* @summary A configurable component for displaying tabular data.
|
|
23
|
+
* @overview
|
|
24
|
+
* <p>The table component displays rows of data with support for sorting, pagination, row selection, and fixed columns.</p>
|
|
25
|
+
*
|
|
26
|
+
* @fires {CustomEvent} cell-click - Dispatched when a table cell is clicked.
|
|
27
|
+
* @fires {CustomEvent} selection-change - Dispatched when the row selection changes.
|
|
28
|
+
* @fires {CustomEvent} sort - Dispatched when the table is sorted.
|
|
29
|
+
* @fires {CustomEvent} page - Dispatched when the page or page size changes.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```html
|
|
33
|
+
* <wc-table columns="[{'name': 'name','label': 'Name','width': 16},{'name': 'age','label': 'Age','width': 7}]" data="[{'name': 'John','age': 30},{'name': 'Jane','age': 25}]"></wc-table>
|
|
34
|
+
* ```
|
|
35
|
+
* @tags display, data
|
|
36
|
+
*/
|
|
37
|
+
export class Table extends LitElement {
|
|
38
|
+
static styles = [styles];
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Grid columns configuration.
|
|
42
|
+
* Each column can have: name, label, width (px), fixed (boolean), template (function).
|
|
43
|
+
*/
|
|
44
|
+
@property({ type: Array })
|
|
45
|
+
columns: TableColumn[] = [];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Grid data to display on table.
|
|
49
|
+
*/
|
|
50
|
+
@property({ type: Array })
|
|
51
|
+
data: any[] = [];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Row selection type. Set to `"checkbox"` to enable checkbox selection.
|
|
55
|
+
*/
|
|
56
|
+
@property({ type: String, attribute: 'selection-type' })
|
|
57
|
+
selectionType: 'checkbox' | undefined;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Array of selected row key values.
|
|
61
|
+
*/
|
|
62
|
+
@property({ type: Array, attribute: 'selected-row-keys' })
|
|
63
|
+
selectedRowKeys: string[] = [];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The field name used as the unique key for each row. Defaults to `"id"`.
|
|
67
|
+
*/
|
|
68
|
+
@property({ type: String, attribute: 'key-field' })
|
|
69
|
+
keyField: string = 'id';
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* If true, sorting and pagination are managed externally (controlled mode).
|
|
73
|
+
*/
|
|
74
|
+
@property({ type: Boolean })
|
|
75
|
+
managed: boolean = false;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* If true, columns are sortable. Defaults to `true`.
|
|
79
|
+
*/
|
|
80
|
+
@property({ type: Boolean })
|
|
81
|
+
sortable: boolean = true;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The field name currently used for sorting.
|
|
85
|
+
*/
|
|
86
|
+
@property({ type: String, attribute: 'sort-by' })
|
|
87
|
+
sortBy: string = '';
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The current sort order. Possible values are `"asc"` and `"desc"`. Defaults to `"asc"`.
|
|
91
|
+
*/
|
|
92
|
+
@property({ type: String, attribute: 'sort-order' })
|
|
93
|
+
sortOrder: 'asc' | 'desc' = 'asc';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* If true, pagination is enabled. Defaults to `true`.
|
|
97
|
+
*/
|
|
98
|
+
@property({ type: Boolean })
|
|
99
|
+
paginate: boolean = false;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The current page number (1-based). Defaults to `1`.
|
|
103
|
+
*/
|
|
104
|
+
@property({ type: Number })
|
|
105
|
+
page: number = 1;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The number of rows per page. Defaults to `10`.
|
|
109
|
+
*/
|
|
110
|
+
@property({ type: Number, attribute: 'page-size' })
|
|
111
|
+
pageSize: number = 10;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Total number of items (used in managed/controlled mode).
|
|
115
|
+
*/
|
|
116
|
+
@property({ type: Number, attribute: 'total-items' })
|
|
117
|
+
totalItems: number | undefined;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Headline text shown when the table has no data.
|
|
121
|
+
*/
|
|
122
|
+
@property({ type: String, attribute: 'empty-state-headline' })
|
|
123
|
+
emptyStateHeadline: string = 'No items';
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Description text shown when the table has no data.
|
|
127
|
+
*/
|
|
128
|
+
@property({ type: String, attribute: 'empty-state-description' })
|
|
129
|
+
emptyStateDescription: string = 'There are no items to display';
|
|
130
|
+
|
|
131
|
+
@state()
|
|
132
|
+
private hoveredCell: { row?: any; column?: any } = {};
|
|
133
|
+
|
|
134
|
+
@state()
|
|
135
|
+
private isSelectAll: boolean = false;
|
|
136
|
+
|
|
137
|
+
@state()
|
|
138
|
+
private isSelectAllIntermediate: boolean = false;
|
|
139
|
+
|
|
140
|
+
@state()
|
|
141
|
+
private isHorizontallyScrolled: boolean = false;
|
|
142
|
+
|
|
143
|
+
private onCellMouseOverThrottled = throttle((row: any, column: any) => {
|
|
144
|
+
this.hoveredCell = { row, column };
|
|
145
|
+
}, 30);
|
|
146
|
+
|
|
147
|
+
private onSelectAllClick = () => {
|
|
148
|
+
this.isSelectAll = !this.isSelectAll;
|
|
149
|
+
let selectedRowKeys: string[] = [];
|
|
150
|
+
if (this.isSelectAll) {
|
|
151
|
+
selectedRowKeys = this.data
|
|
152
|
+
.slice((this.page - 1) * this.pageSize, this.page * this.pageSize)
|
|
153
|
+
.map(row => row[this.keyField]);
|
|
154
|
+
}
|
|
155
|
+
this.onSelectChange(selectedRowKeys);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
private onRowSelectClick = (row: any) => {
|
|
159
|
+
let selectedRowKeys = [...this.selectedRowKeys];
|
|
160
|
+
if (selectedRowKeys.includes(row[this.keyField])) {
|
|
161
|
+
this.isSelectAll = false;
|
|
162
|
+
selectedRowKeys = selectedRowKeys.filter(
|
|
163
|
+
rowId => rowId !== row[this.keyField],
|
|
164
|
+
);
|
|
165
|
+
} else {
|
|
166
|
+
selectedRowKeys.push(row[this.keyField]);
|
|
167
|
+
}
|
|
168
|
+
this.onSelectChange(selectedRowKeys);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
private onSelectChange(selectedRowKeys: string[]) {
|
|
172
|
+
this.selectedRowKeys = selectedRowKeys;
|
|
173
|
+
this.dispatchEvent(
|
|
174
|
+
new CustomEvent('selection-change', {
|
|
175
|
+
detail: {
|
|
176
|
+
value: this.selectedRowKeys,
|
|
177
|
+
isSelectAll: this.isSelectAll,
|
|
178
|
+
},
|
|
179
|
+
bubbles: true,
|
|
180
|
+
composed: true,
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private onCellClick(row: any, col: TableColumn, evt: MouseEvent) {
|
|
186
|
+
this.dispatchEvent(
|
|
187
|
+
new CustomEvent('cell-click', {
|
|
188
|
+
detail: {
|
|
189
|
+
record: row,
|
|
190
|
+
column: col,
|
|
191
|
+
altKey: evt.altKey,
|
|
192
|
+
ctrlKey: evt.ctrlKey,
|
|
193
|
+
metaKey: evt.metaKey,
|
|
194
|
+
shiftKey: evt.shiftKey,
|
|
195
|
+
},
|
|
196
|
+
bubbles: true,
|
|
197
|
+
composed: true,
|
|
198
|
+
}),
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private onScrollContainer = (event: Event) => {
|
|
203
|
+
const target = event.target as HTMLElement;
|
|
204
|
+
this.isHorizontallyScrolled = !!target.scrollLeft;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
private get totalColumnsWidth(): number {
|
|
208
|
+
let total = 0;
|
|
209
|
+
if (this.selectionType === 'checkbox') {
|
|
210
|
+
total += 3; // approximate checkbox column width in rem
|
|
211
|
+
}
|
|
212
|
+
this.columns.forEach(col => {
|
|
213
|
+
total += col.width ?? DEFAULT_CELL_WIDTH;
|
|
214
|
+
});
|
|
215
|
+
return total;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private getTotalItems(): number {
|
|
219
|
+
if (this.paginate && !this.managed) return this.data.length;
|
|
220
|
+
return this.totalItems ?? 0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private getSortIcon(col: TableColumn): string {
|
|
224
|
+
if (this.sortBy === col.name) {
|
|
225
|
+
return this.sortOrder === 'asc' ? 'keyboard_arrow_up' : 'keyboard_arrow_down';
|
|
226
|
+
}
|
|
227
|
+
return '';
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private onSortClick(col: TableColumn) {
|
|
231
|
+
if (this.sortBy === col.name) {
|
|
232
|
+
if (this.sortOrder === 'asc') {
|
|
233
|
+
this.sortOrder = 'desc';
|
|
234
|
+
} else {
|
|
235
|
+
this.sortBy = '';
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
this.sortBy = col.name;
|
|
239
|
+
this.sortOrder = 'asc';
|
|
240
|
+
}
|
|
241
|
+
this.dispatchEvent(
|
|
242
|
+
new CustomEvent('sort', {
|
|
243
|
+
detail: { sortBy: this.sortBy, sortOrder: this.sortOrder },
|
|
244
|
+
bubbles: true,
|
|
245
|
+
composed: true,
|
|
246
|
+
}),
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private renderHeader() {
|
|
251
|
+
const fixedCols: any[] = [];
|
|
252
|
+
const scrollCols: any[] = [];
|
|
253
|
+
|
|
254
|
+
if (this.selectionType === 'checkbox') {
|
|
255
|
+
fixedCols.push(html`
|
|
256
|
+
<div class="col col-checkbox center">
|
|
257
|
+
<div class="col-content">
|
|
258
|
+
<wc-checkbox
|
|
259
|
+
class="checkbox"
|
|
260
|
+
.value=${this.isSelectAll}
|
|
261
|
+
.indeterminate=${this.isSelectAllIntermediate}
|
|
262
|
+
@change=${this.onSelectAllClick}
|
|
263
|
+
></wc-checkbox>
|
|
264
|
+
</div>
|
|
265
|
+
</div>
|
|
266
|
+
`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
this.columns.forEach(col => {
|
|
270
|
+
const colWidth = col.width
|
|
271
|
+
? parseInt(String(col.width), 10)
|
|
272
|
+
: DEFAULT_CELL_WIDTH;
|
|
273
|
+
const colEl = html`
|
|
274
|
+
<div
|
|
275
|
+
class=${classMap({ col: true, sort: this.sortBy === col.name })}
|
|
276
|
+
style="width: ${colWidth}rem"
|
|
277
|
+
>
|
|
278
|
+
<div class="col-content">
|
|
279
|
+
<div class="col-text">${col.label}</div>
|
|
280
|
+
<div class="col-actions">
|
|
281
|
+
${this.sortable
|
|
282
|
+
? html`
|
|
283
|
+
<wc-button
|
|
284
|
+
class="col-action"
|
|
285
|
+
color="secondary"
|
|
286
|
+
variant="text"
|
|
287
|
+
@click=${() => this.onSortClick(col)}
|
|
288
|
+
>
|
|
289
|
+
<wc-icon
|
|
290
|
+
slot="icon"
|
|
291
|
+
name=${this.getSortIcon(col)}
|
|
292
|
+
></wc-icon>
|
|
293
|
+
</wc-button>
|
|
294
|
+
`
|
|
295
|
+
: nothing}
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
`;
|
|
300
|
+
if (col.fixed) {
|
|
301
|
+
fixedCols.push(colEl);
|
|
302
|
+
} else {
|
|
303
|
+
scrollCols.push(colEl);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
return html`
|
|
308
|
+
<div class="header">
|
|
309
|
+
<div class="row" style="min-width: ${this.totalColumnsWidth}rem">
|
|
310
|
+
<div class="fixed-columns columns-container">${fixedCols}</div>
|
|
311
|
+
<div class="scrollable-columns columns-container">${scrollCols}</div>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
`;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private renderBody() {
|
|
318
|
+
let data = [...this.data];
|
|
319
|
+
|
|
320
|
+
if (!this.managed) {
|
|
321
|
+
if (this.sortable && this.sortBy) {
|
|
322
|
+
data = data.sort((a, b) => {
|
|
323
|
+
if (a[this.sortBy] < b[this.sortBy])
|
|
324
|
+
return this.sortOrder === 'asc' ? -1 : 1;
|
|
325
|
+
if (a[this.sortBy] > b[this.sortBy])
|
|
326
|
+
return this.sortOrder === 'asc' ? 1 : -1;
|
|
327
|
+
return 0;
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
if (this.paginate) {
|
|
331
|
+
data = data.slice(
|
|
332
|
+
(this.page - 1) * this.pageSize,
|
|
333
|
+
this.page * this.pageSize,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const rows = data.map(row => {
|
|
339
|
+
const fixedCols: any[] = [];
|
|
340
|
+
const scrollCols: any[] = [];
|
|
341
|
+
|
|
342
|
+
if (this.selectionType === 'checkbox') {
|
|
343
|
+
fixedCols.push(html`
|
|
344
|
+
<div class="col center col-checkbox">
|
|
345
|
+
<div class="col-content">
|
|
346
|
+
<wc-checkbox
|
|
347
|
+
class="checkbox"
|
|
348
|
+
.value=${this.selectedRowKeys.includes(row[this.keyField])}
|
|
349
|
+
@change=${() => this.onRowSelectClick(row)}
|
|
350
|
+
></wc-checkbox>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
this.columns.forEach(column => {
|
|
357
|
+
const colWidth = column.width
|
|
358
|
+
? parseInt(String(column.width), 10)
|
|
359
|
+
: DEFAULT_CELL_WIDTH;
|
|
360
|
+
const colEl = html`
|
|
361
|
+
<div
|
|
362
|
+
tabindex="0"
|
|
363
|
+
class=${classMap({
|
|
364
|
+
col: true,
|
|
365
|
+
'col-hover':
|
|
366
|
+
this.hoveredCell.row === row &&
|
|
367
|
+
this.hoveredCell.column === column,
|
|
368
|
+
})}
|
|
369
|
+
style="width: ${colWidth}rem"
|
|
370
|
+
@mouseover=${() => this.onCellMouseOverThrottled(row, column)}
|
|
371
|
+
@focus=${() => this.onCellMouseOverThrottled(row, column)}
|
|
372
|
+
@keydown=${(event: KeyboardEvent) => {
|
|
373
|
+
if ((event.ctrlKey || event.metaKey) && event.key === 'c') {
|
|
374
|
+
const elem = event.target as HTMLElement;
|
|
375
|
+
window.navigator.clipboard
|
|
376
|
+
.writeText(elem.innerText)
|
|
377
|
+
.catch(() => {});
|
|
378
|
+
}
|
|
379
|
+
}}
|
|
380
|
+
@click=${(evt: MouseEvent) => {
|
|
381
|
+
const selection = window.getSelection();
|
|
382
|
+
if (selection?.type !== 'Range') {
|
|
383
|
+
this.onCellClick(row, column, evt);
|
|
384
|
+
}
|
|
385
|
+
}}
|
|
386
|
+
>
|
|
387
|
+
<div class="col-content">
|
|
388
|
+
${column.template
|
|
389
|
+
? html`<div class="col-template">
|
|
390
|
+
${unsafeHTML(column.template(row, column))}
|
|
391
|
+
</div>`
|
|
392
|
+
: html`<div class="col-text" title=${row?.[column.name] ?? ''}>
|
|
393
|
+
${row?.[column.name]}
|
|
394
|
+
</div>`}
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
`;
|
|
398
|
+
if (column.fixed) {
|
|
399
|
+
fixedCols.push(colEl);
|
|
400
|
+
} else {
|
|
401
|
+
scrollCols.push(colEl);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
return html`
|
|
406
|
+
<div
|
|
407
|
+
class=${classMap({
|
|
408
|
+
row: true,
|
|
409
|
+
'row-hover': this.hoveredCell.row === row,
|
|
410
|
+
})}
|
|
411
|
+
style="min-width: ${this.totalColumnsWidth}rem"
|
|
412
|
+
>
|
|
413
|
+
<div class="fixed-columns columns-container">${fixedCols}</div>
|
|
414
|
+
<div class="scrollable-columns columns-container">${scrollCols}</div>
|
|
415
|
+
</div>
|
|
416
|
+
`;
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
return html`<div class="body">${rows}</div>`;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
private renderEmptyState() {
|
|
423
|
+
return html`
|
|
424
|
+
<div class="empty-table">
|
|
425
|
+
<wc-empty-state
|
|
426
|
+
class="empty-state content-center"
|
|
427
|
+
headline=${this.emptyStateHeadline}
|
|
428
|
+
description=${this.emptyStateDescription}
|
|
429
|
+
></wc-empty-state>
|
|
430
|
+
</div>
|
|
431
|
+
`;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private renderPagination() {
|
|
435
|
+
if (!this.paginate) return nothing;
|
|
436
|
+
|
|
437
|
+
return html`
|
|
438
|
+
<wc-pagination
|
|
439
|
+
.page=${this.page}
|
|
440
|
+
.pageSize=${this.pageSize}
|
|
441
|
+
.totalItems=${this.getTotalItems()}
|
|
442
|
+
@page=${(e: CustomEvent) => {
|
|
443
|
+
this.page = e.detail.page;
|
|
444
|
+
this.pageSize = e.detail.pageSize;
|
|
445
|
+
this.dispatchEvent(
|
|
446
|
+
new CustomEvent('page', {
|
|
447
|
+
detail: { page: this.page, pageSize: this.pageSize },
|
|
448
|
+
bubbles: true,
|
|
449
|
+
composed: true,
|
|
450
|
+
}),
|
|
451
|
+
);
|
|
452
|
+
}}
|
|
453
|
+
></wc-pagination>
|
|
454
|
+
`;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
render() {
|
|
458
|
+
const tableClasses = {
|
|
459
|
+
table: true,
|
|
460
|
+
sortable: this.sortable,
|
|
461
|
+
paginate: this.paginate,
|
|
462
|
+
'horizontal-scrolled': this.isHorizontallyScrolled,
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
return html`
|
|
466
|
+
<div class=${classMap(tableClasses)}>
|
|
467
|
+
<div class="table-scroll-container" @scroll=${this.onScrollContainer}>
|
|
468
|
+
${this.renderHeader()}
|
|
469
|
+
${this.data.length ? this.renderBody() : this.renderEmptyState()}
|
|
470
|
+
</div>
|
|
471
|
+
<div class="table-footer">${this.renderPagination()}</div>
|
|
472
|
+
</div>
|
|
473
|
+
`;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import styles from './tab-group.scss';
|
|
4
|
+
import { Tabs } from './tabs.js';
|
|
5
|
+
import { TabPanel } from './tab-panel.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @label Tab Group
|
|
9
|
+
* @tag wc-tab-group
|
|
10
|
+
* @rawTag tab-group
|
|
11
|
+
*
|
|
12
|
+
* @summary The tab group component is used to display multiple panels of content in a container.
|
|
13
|
+
* @overview
|
|
14
|
+
* <p>The tab group component allows users to switch between different views or content sections.</p>
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```html
|
|
18
|
+
* <wc-tab-group>
|
|
19
|
+
*
|
|
20
|
+
* <wc-tabs>
|
|
21
|
+
* <wc-tab selected >Tab 1</wc-tab>
|
|
22
|
+
* <wc-tab>Tab 2</wc-tab>
|
|
23
|
+
* </wc-tabs>
|
|
24
|
+
*
|
|
25
|
+
* <wc-tab-panel>Panel 1</wc-tab-panel>
|
|
26
|
+
* <wc-tab-panel>Panel 2</wc-tab-panel>
|
|
27
|
+
* </wc-tab-group>
|
|
28
|
+
* ```
|
|
29
|
+
* @tags navigation
|
|
30
|
+
*/
|
|
31
|
+
export class TabGroup extends LitElement {
|
|
32
|
+
static styles = [styles];
|
|
33
|
+
|
|
34
|
+
static Tabs = Tabs;
|
|
35
|
+
|
|
36
|
+
static TabPanel = TabPanel;
|
|
37
|
+
|
|
38
|
+
@property({ reflect: true })
|
|
39
|
+
variant: 'line' | 'line-secondary' | 'contained' | 'pill' = 'line';
|
|
40
|
+
|
|
41
|
+
private uid = crypto.randomUUID();
|
|
42
|
+
|
|
43
|
+
connectedCallback() {
|
|
44
|
+
super.connectedCallback();
|
|
45
|
+
this.addEventListener('tab-click', this.onTabClick as EventListener);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
disconnectedCallback() {
|
|
49
|
+
this.removeEventListener('tab-click', this.onTabClick as EventListener);
|
|
50
|
+
super.disconnectedCallback();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
firstUpdated() {
|
|
54
|
+
this.initializeTabs();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private onTabClick = (event: Event) => {
|
|
58
|
+
const custom = event as CustomEvent;
|
|
59
|
+
event.stopPropagation();
|
|
60
|
+
const targetValue = custom.detail?.target || custom.detail?.value;
|
|
61
|
+
if (targetValue) {
|
|
62
|
+
this.selectTab(targetValue);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
selectTab(target: string) {
|
|
67
|
+
const tabs = this.getTabs();
|
|
68
|
+
tabs.forEach((tab: HTMLElement) => {
|
|
69
|
+
(tab as any).selected = false;
|
|
70
|
+
tab.classList.remove('previous-tab', 'next-tab');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
let selectedIndex = -1;
|
|
74
|
+
tabs.forEach((tab: HTMLElement, index: number) => {
|
|
75
|
+
const t = tab.getAttribute('target') || tab.getAttribute('value');
|
|
76
|
+
if (t === target) {
|
|
77
|
+
selectedIndex = index;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (selectedIndex >= 0) {
|
|
82
|
+
const selectedTab = tabs[selectedIndex];
|
|
83
|
+
(selectedTab as any).selected = true;
|
|
84
|
+
if (tabs[selectedIndex - 1]) {
|
|
85
|
+
tabs[selectedIndex - 1].classList.add('previous-tab');
|
|
86
|
+
}
|
|
87
|
+
if (tabs[selectedIndex + 1]) {
|
|
88
|
+
tabs[selectedIndex + 1].classList.add('next-tab');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const panels = this.getTabPanels();
|
|
93
|
+
panels.forEach(panel => {
|
|
94
|
+
const panelValue = panel.getAttribute('value');
|
|
95
|
+
(panel as any).active = panelValue === target;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private getTabs(): NodeListOf<HTMLElement> {
|
|
100
|
+
return this.querySelectorAll(':scope > tabs-list wc-tab');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private getTabPanels(): NodeListOf<HTMLElement> {
|
|
104
|
+
return this.querySelectorAll(':scope > wc-tab-panel');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private getTabList(): HTMLElement | null {
|
|
108
|
+
return this.querySelector(':scope > tabs-list');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private tabsHaveTarget(): boolean {
|
|
112
|
+
return !!this.querySelector(':scope > tabs-list wc-tab[target]');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private initializeTabs() {
|
|
116
|
+
const tabs = Array.from(this.getTabs());
|
|
117
|
+
if (!this.tabsHaveTarget()) {
|
|
118
|
+
|
|
119
|
+
this.getTabPanels().forEach((panel, index) => {
|
|
120
|
+
if (!panel.getAttribute('value')) {
|
|
121
|
+
panel.setAttribute('value', `tab-${this.uid}-${index}`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (tabs.length > 0) {
|
|
126
|
+
const firstTarget = tabs[0].getAttribute('target');
|
|
127
|
+
if (firstTarget) {
|
|
128
|
+
this.selectTab(firstTarget);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
const selectedTab = this.querySelector(':scope > tabs-list wc-tab[selected]') as HTMLElement;
|
|
133
|
+
if (selectedTab) {
|
|
134
|
+
const selectedTarget = selectedTab.getAttribute('target');
|
|
135
|
+
if (selectedTarget) this.selectTab(selectedTarget);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
render() {
|
|
141
|
+
return html`<slot></slot>`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import styles from './tab-panel.scss';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @label Tab Panel
|
|
7
|
+
* @tag wc-tab-panel
|
|
8
|
+
* @rawTag tab-panel
|
|
9
|
+
* @parentRawTag tab-group
|
|
10
|
+
*
|
|
11
|
+
* @summary Content panel for tabs.
|
|
12
|
+
* @overview
|
|
13
|
+
* <p>TabPanel contains the content associated with a tab.</p>
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```html
|
|
17
|
+
* <wc-tab-panel>Content for this tab</wc-tab-panel>
|
|
18
|
+
* ```
|
|
19
|
+
* @tags navigation
|
|
20
|
+
*/
|
|
21
|
+
export class TabPanel extends LitElement {
|
|
22
|
+
static styles = [styles];
|
|
23
|
+
|
|
24
|
+
@property({ reflect: true }) value?: string;
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
return html`<slot></slot>`;
|
|
28
|
+
}
|
|
29
|
+
}
|