@sebgroup/green-core 2.36.0 → 2.37.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/components/table/table.component.d.ts +14 -0
- package/components/table/table.component.js +90 -14
- package/components/table/table.stories.data.d.ts +9 -1
- package/components/table/table.stories.data.js +51 -3
- package/components/table/table.styles.js +181 -9
- package/components/table/table.types.d.ts +9 -1
- package/custom-elements.json +130 -109
- package/gds-element.js +1 -1
- package/generated/mcp/components.json +1 -1
- package/generated/mcp/icons.json +1 -1
- package/generated/mcp/index.json +1 -1
- package/generated/mcp/table/api.md +2 -0
- package/generated/react/index.d.ts +2 -2
- package/generated/react/index.js +2 -2
- package/generated/react/table/index.d.ts +1 -0
- package/package.json +1 -1
- package/utils/helpers/custom-element-scoping.js +1 -1
|
@@ -8,6 +8,7 @@ import * as Types from './table.types';
|
|
|
8
8
|
*
|
|
9
9
|
* @slot `header-lead` - Content displayed at the start of the table header (after search).
|
|
10
10
|
* @slot `header-trail` - Content displayed at the end of the table header (before settings).
|
|
11
|
+
* @slot `footer` - Content displayed in the table footer area (before pagination).
|
|
11
12
|
* @slot `error` - Custom error state content when data loading fails.
|
|
12
13
|
* @slot `empty` - Custom empty state content when no data is available.
|
|
13
14
|
* @slot `no-results` - Custom no results content when search returns empty.
|
|
@@ -103,6 +104,19 @@ export declare class GdsTable<T extends Types.Row = Types.Row> extends GdsElemen
|
|
|
103
104
|
* Disables data caching mechanism.
|
|
104
105
|
*/
|
|
105
106
|
nocache: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Configures a table footer row (`<tfoot>`) at the bottom of the table.
|
|
109
|
+
* The footer row provides slot insertion points for each visible column,
|
|
110
|
+
* letting consumers render any aggregation (sum, average, count, etc.).
|
|
111
|
+
*
|
|
112
|
+
* Use `tfoot.label` to optionally show a label in the first cell (omitted by default).
|
|
113
|
+
* Use `tfoot.sticky` to pin the footer to the bottom of the scroll area.
|
|
114
|
+
*
|
|
115
|
+
* Slot naming convention: `tfoot:{columnKey}`
|
|
116
|
+
*
|
|
117
|
+
* Accepts: `{ label?: string, sticky?: boolean }` or omit to disable.
|
|
118
|
+
*/
|
|
119
|
+
tfoot?: Types.Tfoot;
|
|
106
120
|
/**
|
|
107
121
|
* Key to trigger data reloading when changed. Setting this to a new value
|
|
108
122
|
* forces the table to clear the cache and request new data from the data provider.
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
__privateMethod,
|
|
6
6
|
__privateSet
|
|
7
7
|
} from "../../chunks/chunk.QU3DSPNU.js";
|
|
8
|
-
var _cache, _cacheDuration, _GdsTable_instances, Density_get, hasSelection_get, isAllSelected_get, isPartialSelection_get, getCacheKey_fn, isCacheValid_fn, loadData_fn, getRowKey_fn, renderCellWrapped_fn, renderMobileLabel_fn, renderSlotElement_fn, renderCellContent_fn, renderSortIcon_fn, hasHeaderContent_fn, renderHeaderControls_fn, renderColumnHeader_fn, renderActionsHeader_fn, renderSelectableHeader_fn, renderColumnHeaders_fn, renderTableHeader_fn, renderTableCell_fn, renderSelectableCell_fn, renderRowCells_fn, renderActionsCell_fn, renderTableRow_fn, renderCheckbox_fn, renderSkeletonCell_fn, renderSkeletonRow_fn, renderTableBody_fn, renderTable_fn, renderErrorState_fn, renderEmptyState_fn, renderFooter_fn, renderHeadline_fn, handleSearch_fn, handleSearchClear_fn, handleSort_fn, handlePageChange_fn, handlePageSizeChange_fn, handleColumnVisibility_fn, handleSelectAll_fn, handleRowSelect_fn, selectAllInternal_fn, clearSelectionInternal_fn, emitSelectionChange_fn, initializeScrollTracking_fn, updateVerticalScrollState_fn, updateHorizontalScrollState_fn;
|
|
8
|
+
var _cache, _cacheDuration, _GdsTable_instances, Density_get, hasSelection_get, isAllSelected_get, isPartialSelection_get, getCacheKey_fn, isCacheValid_fn, loadData_fn, getRowKey_fn, renderCellWrapped_fn, renderMobileLabel_fn, renderSlotElement_fn, renderCellContent_fn, renderSortIcon_fn, hasHeaderContent_fn, renderHeaderControls_fn, renderColumnHeader_fn, renderActionsHeader_fn, renderSelectableHeader_fn, renderColumnHeaders_fn, renderTableHeader_fn, renderTableCell_fn, renderSelectableCell_fn, renderRowCells_fn, renderActionsCell_fn, renderTableRow_fn, renderCheckbox_fn, renderSkeletonCell_fn, renderSkeletonRow_fn, renderTableBody_fn, renderTableFoot_fn, renderTable_fn, renderErrorState_fn, renderEmptyState_fn, renderFooter_fn, renderHeadline_fn, handleSearch_fn, handleSearchClear_fn, handleSort_fn, handlePageChange_fn, handlePageSizeChange_fn, handleColumnVisibility_fn, handleSelectAll_fn, handleRowSelect_fn, selectAllInternal_fn, clearSelectionInternal_fn, emitSelectionChange_fn, initializeScrollTracking_fn, updateVerticalScrollState_fn, updateHorizontalScrollState_fn;
|
|
9
9
|
import { localized, msg } from "@lit/localize";
|
|
10
10
|
import { property, state } from "lit/decorators.js";
|
|
11
11
|
import { classMap } from "lit/directives/class-map.js";
|
|
@@ -430,6 +430,7 @@ renderActionsHeader_fn = function() {
|
|
|
430
430
|
const label = this.actions.label || msg("Actions");
|
|
431
431
|
const classes = classMap({
|
|
432
432
|
actions: true,
|
|
433
|
+
sticky: Boolean(this.actions.sticky),
|
|
433
434
|
wrap: Boolean(this.actions.width),
|
|
434
435
|
[`align-${this.actions.align}`]: !!this.actions.align,
|
|
435
436
|
[`justify-${this.actions.justify}`]: !!this.actions.justify
|
|
@@ -521,6 +522,7 @@ renderActionsCell_fn = function(row, index) {
|
|
|
521
522
|
const rowKey = __privateMethod(this, _GdsTable_instances, getRowKey_fn).call(this, row, index);
|
|
522
523
|
const classes = classMap({
|
|
523
524
|
"actions-cell": true,
|
|
525
|
+
sticky: Boolean(this.actions.sticky),
|
|
524
526
|
wrap: Boolean(this.actions.width),
|
|
525
527
|
[`align-${this.actions.align}`]: !!this.actions.align,
|
|
526
528
|
[`justify-${this.actions.justify}`]: !!this.actions.justify
|
|
@@ -650,6 +652,67 @@ renderTableBody_fn = function() {
|
|
|
650
652
|
</tbody>
|
|
651
653
|
`;
|
|
652
654
|
};
|
|
655
|
+
renderTableFoot_fn = function() {
|
|
656
|
+
if (!this.tfoot) return null;
|
|
657
|
+
const label = this.tfoot.label;
|
|
658
|
+
const visibleColumns = this.columns.filter(
|
|
659
|
+
(column) => this._view.visibleColumns.has(column.key)
|
|
660
|
+
);
|
|
661
|
+
const classes = classMap({
|
|
662
|
+
tablefoot: true,
|
|
663
|
+
sticky: Boolean(this.tfoot.sticky)
|
|
664
|
+
});
|
|
665
|
+
return html`
|
|
666
|
+
<tfoot class=${classes}>
|
|
667
|
+
<tr>
|
|
668
|
+
${when(this.selectable, () => html`<td class="checkbox-cell"></td>`)}
|
|
669
|
+
${visibleColumns.map((column, i) => {
|
|
670
|
+
const cellClasses = classMap({
|
|
671
|
+
"tablefoot-cell": true,
|
|
672
|
+
"tablefoot-label-cell": i === 0,
|
|
673
|
+
[`align-${column.align}`]: !!column.align,
|
|
674
|
+
[`justify-${column.justify}`]: !!column.justify,
|
|
675
|
+
wrap: Boolean(column.width)
|
|
676
|
+
});
|
|
677
|
+
const style = styleMap({
|
|
678
|
+
"--cell-width": column.width
|
|
679
|
+
});
|
|
680
|
+
if (i === 0 && label) {
|
|
681
|
+
return html`
|
|
682
|
+
<th scope="row" class=${cellClasses} style=${style}>
|
|
683
|
+
<div class="cell-content">
|
|
684
|
+
<span class="tablefoot-label">${label}</span>
|
|
685
|
+
<slot name="tfoot:${column.key}"></slot>
|
|
686
|
+
</div>
|
|
687
|
+
</th>
|
|
688
|
+
`;
|
|
689
|
+
}
|
|
690
|
+
return html`
|
|
691
|
+
<td class=${cellClasses} style=${style}>
|
|
692
|
+
<div class="cell-content">
|
|
693
|
+
<slot name="tfoot:${column.key}"></slot>
|
|
694
|
+
</div>
|
|
695
|
+
</td>
|
|
696
|
+
`;
|
|
697
|
+
})}
|
|
698
|
+
${when(this.actions, () => {
|
|
699
|
+
const isObj = this.actions && typeof this.actions !== "function";
|
|
700
|
+
const stickyAction = isObj && this.actions.sticky;
|
|
701
|
+
const actionClasses = classMap({
|
|
702
|
+
"actions-cell": true,
|
|
703
|
+
"tablefoot-cell": true,
|
|
704
|
+
sticky: Boolean(stickyAction)
|
|
705
|
+
});
|
|
706
|
+
return html`<td class=${actionClasses}>
|
|
707
|
+
<div class="cell-content">
|
|
708
|
+
<slot name="tfoot:actions"></slot>
|
|
709
|
+
</div>
|
|
710
|
+
</td>`;
|
|
711
|
+
})}
|
|
712
|
+
</tr>
|
|
713
|
+
</tfoot>
|
|
714
|
+
`;
|
|
715
|
+
};
|
|
653
716
|
renderTable_fn = function() {
|
|
654
717
|
const CLASSES = classMap({
|
|
655
718
|
responsive: this.responsive,
|
|
@@ -673,6 +736,7 @@ renderTable_fn = function() {
|
|
|
673
736
|
${caption}
|
|
674
737
|
</caption>
|
|
675
738
|
${__privateMethod(this, _GdsTable_instances, renderTableHeader_fn).call(this)} ${__privateMethod(this, _GdsTable_instances, renderTableBody_fn).call(this)}
|
|
739
|
+
${__privateMethod(this, _GdsTable_instances, renderTableFoot_fn).call(this)}
|
|
676
740
|
</table>
|
|
677
741
|
</div>
|
|
678
742
|
</gds-card>
|
|
@@ -735,18 +799,20 @@ renderFooter_fn = function() {
|
|
|
735
799
|
const end = Math.min(this._view.page * this._view.rows, this._total);
|
|
736
800
|
const summaryString = `${start}\u2013${end} ${msg("of")} ${this._total}`;
|
|
737
801
|
return html`
|
|
738
|
-
<
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
802
|
+
<slot name="footer">
|
|
803
|
+
<gds-pagination
|
|
804
|
+
.page=${this._view.page}
|
|
805
|
+
.rows=${this._view.rows}
|
|
806
|
+
.options=${this.options}
|
|
807
|
+
.total=${this._total}
|
|
808
|
+
.density=${this.density}
|
|
809
|
+
.label=${summaryString}
|
|
810
|
+
@gds-page-change=${__privateMethod(this, _GdsTable_instances, handlePageChange_fn)}
|
|
811
|
+
@gds-rows-change=${__privateMethod(this, _GdsTable_instances, handlePageSizeChange_fn)}
|
|
812
|
+
width="100%"
|
|
813
|
+
>
|
|
814
|
+
</gds-pagination>
|
|
815
|
+
</slot>
|
|
750
816
|
`;
|
|
751
817
|
};
|
|
752
818
|
renderHeadline_fn = function() {
|
|
@@ -916,14 +982,21 @@ initializeScrollTracking_fn = function() {
|
|
|
916
982
|
/**
|
|
917
983
|
* Updates CSS classes based on vertical scroll position.
|
|
918
984
|
* Adds 'scrolled' class when scrolled down from top.
|
|
985
|
+
* Adds 'scrolled-bottom' class when not scrolled to the very bottom.
|
|
919
986
|
*/
|
|
920
987
|
updateVerticalScrollState_fn = function(container) {
|
|
921
|
-
const { scrollTop } = container;
|
|
988
|
+
const { scrollTop, scrollHeight, clientHeight } = container;
|
|
989
|
+
const maxScrollTop = scrollHeight - clientHeight;
|
|
922
990
|
if (scrollTop > 0) {
|
|
923
991
|
container.classList.add("scrolled");
|
|
924
992
|
} else {
|
|
925
993
|
container.classList.remove("scrolled");
|
|
926
994
|
}
|
|
995
|
+
if (scrollTop < maxScrollTop - 1) {
|
|
996
|
+
container.classList.add("scrolled-bottom");
|
|
997
|
+
} else {
|
|
998
|
+
container.classList.remove("scrolled-bottom");
|
|
999
|
+
}
|
|
927
1000
|
};
|
|
928
1001
|
/**
|
|
929
1002
|
* Updates CSS classes based on horizontal scroll position.
|
|
@@ -1013,6 +1086,9 @@ __decorateClass([
|
|
|
1013
1086
|
__decorateClass([
|
|
1014
1087
|
property({ type: Boolean, reflect: false })
|
|
1015
1088
|
], GdsTable.prototype, "nocache", 2);
|
|
1089
|
+
__decorateClass([
|
|
1090
|
+
property({ type: Object })
|
|
1091
|
+
], GdsTable.prototype, "tfoot", 2);
|
|
1016
1092
|
__decorateClass([
|
|
1017
1093
|
property()
|
|
1018
1094
|
], GdsTable.prototype, "dataLoadKey", 2);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { TemplateResult } from 'lit';
|
|
2
|
-
import type { TableActions, TableColumn, TableRequest, TableResponse } from './table.types';
|
|
2
|
+
import type { TableActions, TableColumn, TableRequest, TableResponse, TableTfoot } from './table.types';
|
|
3
3
|
export declare const Users: {
|
|
4
4
|
Columns: TableColumn[];
|
|
5
5
|
Actions: TableActions;
|
|
6
|
+
Tfoot: TableTfoot;
|
|
6
7
|
Data: (request: TableRequest) => Promise<TableResponse<any>>;
|
|
7
8
|
/**
|
|
8
9
|
* Generates slot content for the given rows (current page).
|
|
@@ -14,6 +15,13 @@ export declare const Users: {
|
|
|
14
15
|
* ```
|
|
15
16
|
*/
|
|
16
17
|
SlotContent: (rows: any[]) => TemplateResult;
|
|
18
|
+
/**
|
|
19
|
+
* Generates tfoot slot content for the footer row.
|
|
20
|
+
* Receives all rows on the page and computes aggregations.
|
|
21
|
+
*
|
|
22
|
+
* Slot naming: `tfoot:{columnKey}`
|
|
23
|
+
*/
|
|
24
|
+
TfootSlotContent: (rows: any[]) => TemplateResult;
|
|
17
25
|
};
|
|
18
26
|
export declare const Feedback: {
|
|
19
27
|
Columns: TableColumn[];
|
|
@@ -123,6 +123,10 @@ const Users = {
|
|
|
123
123
|
label: "Actions",
|
|
124
124
|
justify: "end"
|
|
125
125
|
},
|
|
126
|
+
Tfoot: {
|
|
127
|
+
label: "Totals",
|
|
128
|
+
sticky: true
|
|
129
|
+
},
|
|
126
130
|
Data: userDataProvider,
|
|
127
131
|
/**
|
|
128
132
|
* Generates slot content for the given rows (current page).
|
|
@@ -212,6 +216,47 @@ const Users = {
|
|
|
212
216
|
`
|
|
213
217
|
)}
|
|
214
218
|
`;
|
|
219
|
+
},
|
|
220
|
+
/**
|
|
221
|
+
* Generates tfoot slot content for the footer row.
|
|
222
|
+
* Receives all rows on the page and computes aggregations.
|
|
223
|
+
*
|
|
224
|
+
* Slot naming: `tfoot:{columnKey}`
|
|
225
|
+
*/
|
|
226
|
+
TfootSlotContent: (rows) => {
|
|
227
|
+
const totalAmount = rows.reduce(
|
|
228
|
+
(sum, row) => sum + (Number(row.amount) || 0),
|
|
229
|
+
0
|
|
230
|
+
);
|
|
231
|
+
const activeCount = rows.filter(
|
|
232
|
+
(row) => String(row.status) === "Active"
|
|
233
|
+
).length;
|
|
234
|
+
const activeRate = Math.round(activeCount / rows.length * 100);
|
|
235
|
+
const departments = new Set(rows.map((row) => row.department)).size;
|
|
236
|
+
return html`
|
|
237
|
+
<!-- tfoot: name row count -->
|
|
238
|
+
<span slot="tfoot:name">${rows.length} Users</span>
|
|
239
|
+
|
|
240
|
+
<!-- tfoot: status active rate -->
|
|
241
|
+
<gds-badge
|
|
242
|
+
slot="tfoot:status"
|
|
243
|
+
variant="${activeRate >= 70 ? "positive" : activeRate >= 40 ? "warning" : "negative"}"
|
|
244
|
+
size="small"
|
|
245
|
+
>
|
|
246
|
+
${activeRate}% active
|
|
247
|
+
</gds-badge>
|
|
248
|
+
|
|
249
|
+
<!-- tfoot: department count -->
|
|
250
|
+
<gds-badge slot="tfoot:department" variant="information" size="small">
|
|
251
|
+
${departments} depts
|
|
252
|
+
</gds-badge>
|
|
253
|
+
|
|
254
|
+
<!-- tfoot: amount sum -->
|
|
255
|
+
<gds-flex slot="tfoot:amount" gap="s" align-items="center">
|
|
256
|
+
<gds-formatted-number .value=${totalAmount}></gds-formatted-number>
|
|
257
|
+
<gds-badge size="small">SEK</gds-badge>
|
|
258
|
+
</gds-flex>
|
|
259
|
+
`;
|
|
215
260
|
}
|
|
216
261
|
};
|
|
217
262
|
const loadFeedback = async () => {
|
|
@@ -297,7 +342,8 @@ const Actions = {
|
|
|
297
342
|
label: "Actions",
|
|
298
343
|
align: "center",
|
|
299
344
|
justify: "start",
|
|
300
|
-
width:
|
|
345
|
+
// width: '150px',
|
|
346
|
+
sticky: true
|
|
301
347
|
},
|
|
302
348
|
MultipleActionsSlotContent: (rows) => {
|
|
303
349
|
return html`
|
|
@@ -327,7 +373,8 @@ const Actions = {
|
|
|
327
373
|
label: "Actions",
|
|
328
374
|
align: "center",
|
|
329
375
|
justify: "end",
|
|
330
|
-
width:
|
|
376
|
+
// width: '150px',
|
|
377
|
+
sticky: true
|
|
331
378
|
},
|
|
332
379
|
ActionLinkSlotContent: (rows) => {
|
|
333
380
|
return html`
|
|
@@ -348,7 +395,8 @@ const Actions = {
|
|
|
348
395
|
label: "Actions",
|
|
349
396
|
align: "center",
|
|
350
397
|
justify: "end",
|
|
351
|
-
width:
|
|
398
|
+
// width: '150px',
|
|
399
|
+
sticky: true
|
|
352
400
|
},
|
|
353
401
|
ActionContextMenuSlotContent: (rows) => {
|
|
354
402
|
return html`
|
|
@@ -24,6 +24,7 @@ const TableStyles = css`
|
|
|
24
24
|
--table-gap: var(--gds-sys-space-m);
|
|
25
25
|
--table-border-spacing: 0 var(--gds-sys-space-5xs);
|
|
26
26
|
--table-data-padding: var(--gds-sys-space-5xs) var(--gds-sys-space-4xs);
|
|
27
|
+
--table-data-padding-x: var(--gds-sys-space-4xs);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
/* Comfortable default */
|
|
@@ -37,6 +38,7 @@ const TableStyles = css`
|
|
|
37
38
|
--table-gap: var(--gds-sys-space-l);
|
|
38
39
|
--table-border-spacing: 0 var(--gds-sys-space-4xs);
|
|
39
40
|
--table-data-padding: var(--gds-sys-space-3xs) var(--gds-sys-space-2xs);
|
|
41
|
+
--table-data-padding-x: var(--gds-sys-space-2xs);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
/* Spacious density */
|
|
@@ -50,6 +52,7 @@ const TableStyles = css`
|
|
|
50
52
|
--table-gap: var(--gds-sys-space-xl);
|
|
51
53
|
--table-border-spacing: 0 var(--gds-sys-space-3xs);
|
|
52
54
|
--table-data-padding: var(--gds-sys-space-3xs) var(--gds-sys-space-xs);
|
|
55
|
+
--table-data-padding-x: var(--gds-sys-space-xs);
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
/* Secondary and Tertiary */
|
|
@@ -61,6 +64,7 @@ const TableStyles = css`
|
|
|
61
64
|
--_table-row-hover: var(--gds-sys-color-l2-neutral-01);
|
|
62
65
|
--_table-row-selected-hover: var(--gds-sys-color-l3-neutral-03);
|
|
63
66
|
--_table-row-striped: var(--gds-sys-color-l2-neutral-01);
|
|
67
|
+
--_table-card-bg: var(--gds-sys-color-l1-neutral-01);
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
/* Primary variant */
|
|
@@ -75,6 +79,7 @@ const TableStyles = css`
|
|
|
75
79
|
);
|
|
76
80
|
--_table-row-selected-hover: var(--gds-sys-color-l3-neutral-03);
|
|
77
81
|
--_table-row-striped: var(--gds-sys-color-l2-neutral-01);
|
|
82
|
+
--_table-card-bg: var(--gds-sys-color-l2-neutral-01);
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
/* Apply density variables */
|
|
@@ -360,6 +365,152 @@ const TableStyles = css`
|
|
|
360
365
|
justify-content: flex-end;
|
|
361
366
|
}
|
|
362
367
|
|
|
368
|
+
/* Sticky actions column */
|
|
369
|
+
th.actions.sticky,
|
|
370
|
+
td.actions-cell.sticky {
|
|
371
|
+
position: sticky;
|
|
372
|
+
right: calc(-1 * var(--table-data-padding-x, 0px));
|
|
373
|
+
z-index: 1;
|
|
374
|
+
width: max-content;
|
|
375
|
+
padding-right: calc(
|
|
376
|
+
var(--table-cell-padding-x) + var(--table-data-padding-x, 0px)
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
th.actions.sticky {
|
|
381
|
+
z-index: 2;
|
|
382
|
+
background: var(--_table-header-bg);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
th.actions.sticky .column-header {
|
|
386
|
+
justify-content: flex-end;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
td.actions-cell.sticky {
|
|
390
|
+
background: var(--_table-card-bg);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
td.actions-cell.sticky .cell-content {
|
|
394
|
+
justify-content: flex-end;
|
|
395
|
+
position: relative;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* Left gradient fade on sticky action cells */
|
|
399
|
+
td.actions-cell.sticky::before {
|
|
400
|
+
content: '';
|
|
401
|
+
position: absolute;
|
|
402
|
+
inset-block: 0;
|
|
403
|
+
right: 100%;
|
|
404
|
+
width: var(--gds-sys-space-4xl);
|
|
405
|
+
pointer-events: none;
|
|
406
|
+
background: linear-gradient(to right, transparent, var(--_table-card-bg));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
th.actions.sticky::before {
|
|
410
|
+
content: '';
|
|
411
|
+
position: absolute;
|
|
412
|
+
inset-block: 0;
|
|
413
|
+
right: 100%;
|
|
414
|
+
width: var(--gds-sys-space-4xl);
|
|
415
|
+
pointer-events: none;
|
|
416
|
+
background: linear-gradient(to right, transparent, var(--_table-header-bg));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/* Sticky action inherits row hover/selected/striped backgrounds */
|
|
420
|
+
tbody tr:hover td.actions-cell.sticky {
|
|
421
|
+
background: var(--_table-row-hover);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
tbody tr:hover td.actions-cell.sticky::before {
|
|
425
|
+
background: linear-gradient(to right, transparent, var(--_table-row-hover));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
tbody tr.selected td.actions-cell.sticky {
|
|
429
|
+
background: var(--gds-sys-color-l3-neutral-02);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
tbody tr.selected td.actions-cell.sticky::before {
|
|
433
|
+
background: linear-gradient(
|
|
434
|
+
to right,
|
|
435
|
+
transparent,
|
|
436
|
+
var(--gds-sys-color-l3-neutral-02)
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.striped
|
|
441
|
+
tbody
|
|
442
|
+
tr:not(.selected, :hover):nth-child(even)
|
|
443
|
+
td.actions-cell.sticky {
|
|
444
|
+
background: var(--_table-row-striped);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.striped
|
|
448
|
+
tbody
|
|
449
|
+
tr:not(.selected, :hover):nth-child(even)
|
|
450
|
+
td.actions-cell.sticky::before {
|
|
451
|
+
background: linear-gradient(
|
|
452
|
+
to right,
|
|
453
|
+
transparent,
|
|
454
|
+
var(--_table-row-striped)
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* Table Footer Row */
|
|
459
|
+
|
|
460
|
+
tfoot.tablefoot tr td,
|
|
461
|
+
tfoot.tablefoot tr th[scope='row'] {
|
|
462
|
+
padding-block: var(--table-cell-padding-y);
|
|
463
|
+
padding-inline: var(--table-cell-padding-x);
|
|
464
|
+
background: var(--_table-header-bg);
|
|
465
|
+
font-weight: normal;
|
|
466
|
+
border-top: var(--_table-border-width) solid var(--_table-border-color);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
tfoot.tablefoot tr th[scope='row'] {
|
|
470
|
+
font-weight: var(--gds-sys-text-weight-book);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
tfoot.tablefoot tr td:first-child,
|
|
474
|
+
tfoot.tablefoot tr th:first-child {
|
|
475
|
+
border-top-left-radius: var(--gds-sys-radius-s);
|
|
476
|
+
border-bottom-left-radius: var(--gds-sys-radius-s);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
tfoot.tablefoot tr td:last-child,
|
|
480
|
+
tfoot.tablefoot tr th:last-child {
|
|
481
|
+
border-top-right-radius: var(--gds-sys-radius-s);
|
|
482
|
+
border-bottom-right-radius: var(--gds-sys-radius-s);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.tablefoot-label {
|
|
486
|
+
font-weight: var(--gds-sys-text-weight-book);
|
|
487
|
+
white-space: nowrap;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
tfoot.tablefoot.sticky {
|
|
491
|
+
position: sticky;
|
|
492
|
+
bottom: 0;
|
|
493
|
+
z-index: 10;
|
|
494
|
+
will-change: transform;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/* When sticky tablefoot: move padding from .data to table, keep tfoot edge-to-edge */
|
|
498
|
+
.data:has(tfoot.tablefoot.sticky) {
|
|
499
|
+
padding: 0;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.data:has(tfoot.tablefoot.sticky) table {
|
|
503
|
+
padding-top: var(--table-data-padding-x);
|
|
504
|
+
padding-inline: var(--table-data-padding-x);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
tfoot.tablefoot.sticky tr td,
|
|
508
|
+
tfoot.tablefoot.sticky tr th[scope='row'] {
|
|
509
|
+
border-radius: 0;
|
|
510
|
+
background: var(--_table-card-bg);
|
|
511
|
+
border-top: var(--_table-border-width) solid var(--_table-border-color);
|
|
512
|
+
}
|
|
513
|
+
|
|
363
514
|
/* Align utilities */
|
|
364
515
|
td {
|
|
365
516
|
height: 100%;
|
|
@@ -674,6 +825,16 @@ const TableStyles = css`
|
|
|
674
825
|
}
|
|
675
826
|
}
|
|
676
827
|
|
|
828
|
+
/* Sticky table footer */
|
|
829
|
+
tfoot.tablefoot.sticky {
|
|
830
|
+
background-color: var(--_table-card-bg);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
tfoot.tablefoot.sticky tr td,
|
|
834
|
+
tfoot.tablefoot.sticky tr th[scope='row'] {
|
|
835
|
+
background: var(--_table-card-bg);
|
|
836
|
+
}
|
|
837
|
+
|
|
677
838
|
/* Horizontal scroll */
|
|
678
839
|
@property --_start-fade {
|
|
679
840
|
syntax: '<length>';
|
|
@@ -689,18 +850,20 @@ const TableStyles = css`
|
|
|
689
850
|
|
|
690
851
|
@keyframes scroll-fade {
|
|
691
852
|
0% {
|
|
692
|
-
--_start-fade:
|
|
853
|
+
--_start-fade: 0px;
|
|
854
|
+
--_end-fade: var(--gds-sys-space-4xl);
|
|
693
855
|
}
|
|
694
|
-
|
|
695
|
-
100% {
|
|
856
|
+
1% {
|
|
696
857
|
--_start-fade: var(--gds-sys-space-4xl);
|
|
858
|
+
--_end-fade: var(--gds-sys-space-4xl);
|
|
697
859
|
}
|
|
698
|
-
|
|
699
|
-
|
|
860
|
+
99% {
|
|
861
|
+
--_start-fade: var(--gds-sys-space-4xl);
|
|
700
862
|
--_end-fade: var(--gds-sys-space-4xl);
|
|
701
863
|
}
|
|
702
864
|
100% {
|
|
703
|
-
--
|
|
865
|
+
--_start-fade: var(--gds-sys-space-4xl);
|
|
866
|
+
--_end-fade: 0px;
|
|
704
867
|
}
|
|
705
868
|
}
|
|
706
869
|
|
|
@@ -712,9 +875,18 @@ const TableStyles = css`
|
|
|
712
875
|
#ffff var(--_start-fade) calc(100% - var(--_end-fade)),
|
|
713
876
|
#0000
|
|
714
877
|
);
|
|
715
|
-
animation: scroll-fade;
|
|
716
|
-
animation-timeline:
|
|
717
|
-
|
|
878
|
+
animation: scroll-fade both linear;
|
|
879
|
+
animation-timeline: scroll(self inline);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/* When sticky actions are present, remove the right fade.*/
|
|
883
|
+
.data:has(td.actions-cell.sticky) {
|
|
884
|
+
mask: linear-gradient(
|
|
885
|
+
to right,
|
|
886
|
+
#0000,
|
|
887
|
+
#ffff var(--_start-fade),
|
|
888
|
+
#ffff 100%
|
|
889
|
+
);
|
|
718
890
|
}
|
|
719
891
|
}
|
|
720
892
|
}
|
|
@@ -18,6 +18,11 @@ export interface Actions {
|
|
|
18
18
|
align?: 'start' | 'center' | 'stretch' | 'end';
|
|
19
19
|
justify?: 'start' | 'center' | 'space-between' | 'end';
|
|
20
20
|
width?: string;
|
|
21
|
+
sticky?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface Tfoot {
|
|
24
|
+
label?: string;
|
|
25
|
+
sticky?: boolean;
|
|
21
26
|
}
|
|
22
27
|
export interface Row {
|
|
23
28
|
[key: string]: any;
|
|
@@ -44,7 +49,7 @@ export interface Response<T> {
|
|
|
44
49
|
/**
|
|
45
50
|
* Internal density configuration for the table's built-in UI controls
|
|
46
51
|
* (search input, column settings dropdown). Does not affect user-provided
|
|
47
|
-
* slot content
|
|
52
|
+
* slot content size your own components to match the chosen density.
|
|
48
53
|
*/
|
|
49
54
|
export declare const DENSITY_CONFIG: {
|
|
50
55
|
readonly compact: {
|
|
@@ -85,6 +90,9 @@ export type TableState = State;
|
|
|
85
90
|
export type TableRequest = Request;
|
|
86
91
|
export type TableResponse<T> = Response<T>;
|
|
87
92
|
export type TableDensity = Density;
|
|
93
|
+
export type TableTfoot = Tfoot;
|
|
94
|
+
/** @deprecated Use `TableTfoot` instead */
|
|
95
|
+
export type TableTotals = Tfoot;
|
|
88
96
|
export type TableCache<T> = Cache<T>;
|
|
89
97
|
export type TableCacheEntry<T> = CacheEntry<T>;
|
|
90
98
|
export type TableSlotValue = SlotValue;
|