@beaconsoftware/b-report-table 1.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/dist/b-report-table-body.d.ts +16 -0
- package/dist/b-report-table-body.d.ts.map +1 -0
- package/dist/b-report-table-body.js +28 -0
- package/dist/b-report-table-body.js.map +1 -0
- package/dist/b-report-table-cell.d.ts +23 -0
- package/dist/b-report-table-cell.d.ts.map +1 -0
- package/dist/b-report-table-cell.js +103 -0
- package/dist/b-report-table-cell.js.map +1 -0
- package/dist/b-report-table-footer-cell.d.ts +25 -0
- package/dist/b-report-table-footer-cell.d.ts.map +1 -0
- package/dist/b-report-table-footer-cell.js +125 -0
- package/dist/b-report-table-footer-cell.js.map +1 -0
- package/dist/b-report-table-footer-row.d.ts +16 -0
- package/dist/b-report-table-footer-row.d.ts.map +1 -0
- package/dist/b-report-table-footer-row.js +28 -0
- package/dist/b-report-table-footer-row.js.map +1 -0
- package/dist/b-report-table-footer.d.ts +20 -0
- package/dist/b-report-table-footer.d.ts.map +1 -0
- package/dist/b-report-table-footer.js +38 -0
- package/dist/b-report-table-footer.js.map +1 -0
- package/dist/b-report-table-header-cell.d.ts +30 -0
- package/dist/b-report-table-header-cell.d.ts.map +1 -0
- package/dist/b-report-table-header-cell.js +121 -0
- package/dist/b-report-table-header-cell.js.map +1 -0
- package/dist/b-report-table-header-row.d.ts +16 -0
- package/dist/b-report-table-header-row.d.ts.map +1 -0
- package/dist/b-report-table-header-row.js +28 -0
- package/dist/b-report-table-header-row.js.map +1 -0
- package/dist/b-report-table-header.d.ts +25 -0
- package/dist/b-report-table-header.d.ts.map +1 -0
- package/dist/b-report-table-header.js +114 -0
- package/dist/b-report-table-header.js.map +1 -0
- package/dist/b-report-table-row.d.ts +16 -0
- package/dist/b-report-table-row.d.ts.map +1 -0
- package/dist/b-report-table-row.js +32 -0
- package/dist/b-report-table-row.js.map +1 -0
- package/dist/b-report-table.d.ts +32 -0
- package/dist/b-report-table.d.ts.map +1 -0
- package/dist/b-report-table.js +74 -0
- package/dist/b-report-table.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
- package/src/b-report-table-body.ts +26 -0
- package/src/b-report-table-cell.ts +109 -0
- package/src/b-report-table-footer-cell.ts +131 -0
- package/src/b-report-table-footer-row.ts +26 -0
- package/src/b-report-table-footer.ts +32 -0
- package/src/b-report-table-header-cell.ts +128 -0
- package/src/b-report-table-header-row.ts +26 -0
- package/src/b-report-table-header.ts +125 -0
- package/src/b-report-table-row.ts +30 -0
- package/src/b-report-table.ts +80 -0
- package/src/index.ts +12 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
import type { ColumnStickyConfig } from './b-report-table.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A cell within a table footer row.
|
|
7
|
+
* Inherits sticky behavior from corresponding header columns.
|
|
8
|
+
*
|
|
9
|
+
* @slot - Default slot for cell content
|
|
10
|
+
*/
|
|
11
|
+
@customElement('b-report-table-footer-cell')
|
|
12
|
+
export class BReportTableFooterCell extends LitElement {
|
|
13
|
+
static styles = css`
|
|
14
|
+
:host {
|
|
15
|
+
display: table-cell;
|
|
16
|
+
padding: 12px 16px;
|
|
17
|
+
font-weight: 600;
|
|
18
|
+
background: #f8fafc;
|
|
19
|
+
border-top: 2px solid #e2e8f0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* Vertical sticky (when parent footer has sticky attribute) */
|
|
23
|
+
:host([data-sticky-bottom]) {
|
|
24
|
+
position: sticky;
|
|
25
|
+
bottom: 0;
|
|
26
|
+
z-index: 2;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Horizontal sticky columns */
|
|
30
|
+
:host([data-sticky='left']),
|
|
31
|
+
:host([data-sticky='right']) {
|
|
32
|
+
position: sticky;
|
|
33
|
+
z-index: 2;
|
|
34
|
+
background: #f1f5f9;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Both vertical and horizontal sticky */
|
|
38
|
+
:host([data-sticky-bottom][data-sticky='left']),
|
|
39
|
+
:host([data-sticky-bottom][data-sticky='right']) {
|
|
40
|
+
z-index: 4;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:host([data-sticky='left']) {
|
|
44
|
+
left: var(--sticky-offset, 0px);
|
|
45
|
+
box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host([data-sticky='right']) {
|
|
49
|
+
right: var(--sticky-offset, 0px);
|
|
50
|
+
box-shadow: -2px 0 4px -2px rgba(0, 0, 0, 0.1);
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
connectedCallback(): void {
|
|
56
|
+
super.connectedCallback();
|
|
57
|
+
const table = this._findTable();
|
|
58
|
+
if (table) {
|
|
59
|
+
table.addEventListener('column-config-change', this._handleConfigChange);
|
|
60
|
+
// Check if configs are already available
|
|
61
|
+
this._applyInitialConfig();
|
|
62
|
+
}
|
|
63
|
+
// Check if parent footer has sticky attribute
|
|
64
|
+
this._updateVerticalSticky();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private _updateVerticalSticky(): void {
|
|
68
|
+
const footer = this.closest('b-report-table-footer');
|
|
69
|
+
if (footer?.hasAttribute('sticky')) {
|
|
70
|
+
this.setAttribute('data-sticky-bottom', '');
|
|
71
|
+
} else {
|
|
72
|
+
this.removeAttribute('data-sticky-bottom');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
disconnectedCallback(): void {
|
|
77
|
+
super.disconnectedCallback();
|
|
78
|
+
this._findTable()?.removeEventListener(
|
|
79
|
+
'column-config-change',
|
|
80
|
+
this._handleConfigChange
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private _findTable(): HTMLElement | null {
|
|
85
|
+
return this.closest('b-report-table');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private _applyInitialConfig(): void {
|
|
89
|
+
const table = this._findTable() as any;
|
|
90
|
+
if (table?.columnConfigs) {
|
|
91
|
+
this._applyConfig(table.columnConfigs);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private _handleConfigChange = (event: Event): void => {
|
|
96
|
+
const customEvent = event as CustomEvent<{ configs: ColumnStickyConfig[] }>;
|
|
97
|
+
this._applyConfig(customEvent.detail.configs);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
private _applyConfig(configs: ColumnStickyConfig[]): void {
|
|
101
|
+
const index = this._getColumnIndex();
|
|
102
|
+
const config = configs.find((c) => c.index === index);
|
|
103
|
+
|
|
104
|
+
if (config) {
|
|
105
|
+
if (config.sticky) {
|
|
106
|
+
this.setAttribute('data-sticky', config.sticky);
|
|
107
|
+
this.style.setProperty('--sticky-offset', `${config.offset}px`);
|
|
108
|
+
} else {
|
|
109
|
+
this.removeAttribute('data-sticky');
|
|
110
|
+
this.style.removeProperty('--sticky-offset');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private _getColumnIndex(): number {
|
|
116
|
+
const row = this.parentElement;
|
|
117
|
+
if (!row) return -1;
|
|
118
|
+
const cells = Array.from(row.querySelectorAll('b-report-table-footer-cell'));
|
|
119
|
+
return cells.indexOf(this);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
render() {
|
|
123
|
+
return html`<slot></slot>`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
declare global {
|
|
128
|
+
interface HTMLElementTagNameMap {
|
|
129
|
+
'b-report-table-footer-cell': BReportTableFooterCell;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A row within the table footer.
|
|
6
|
+
*
|
|
7
|
+
* @slot - Default slot for footer cells (b-report-table-footer-cell)
|
|
8
|
+
*/
|
|
9
|
+
@customElement('b-report-table-footer-row')
|
|
10
|
+
export class BReportTableFooterRow extends LitElement {
|
|
11
|
+
static styles = css`
|
|
12
|
+
:host {
|
|
13
|
+
display: table-row;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
render() {
|
|
18
|
+
return html`<slot></slot>`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare global {
|
|
23
|
+
interface HTMLElementTagNameMap {
|
|
24
|
+
'b-report-table-footer-row': BReportTableFooterRow;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Table footer component that wraps footer rows.
|
|
6
|
+
*
|
|
7
|
+
* @slot - Default slot for footer rows (b-report-table-footer-row)
|
|
8
|
+
*/
|
|
9
|
+
@customElement('b-report-table-footer')
|
|
10
|
+
export class BReportTableFooter extends LitElement {
|
|
11
|
+
static styles = css`
|
|
12
|
+
:host {
|
|
13
|
+
display: table-footer-group;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Whether the footer should be sticky (fixed at the bottom when scrolling).
|
|
19
|
+
*/
|
|
20
|
+
@property({ type: Boolean, reflect: true })
|
|
21
|
+
sticky = false;
|
|
22
|
+
|
|
23
|
+
render() {
|
|
24
|
+
return html`<slot></slot>`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare global {
|
|
29
|
+
interface HTMLElementTagNameMap {
|
|
30
|
+
'b-report-table-footer': BReportTableFooter;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
3
|
+
import type { ColumnStickyConfig } from './b-report-table.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A header cell within a table header row.
|
|
7
|
+
*
|
|
8
|
+
* @slot - Default slot for cell content
|
|
9
|
+
*/
|
|
10
|
+
@customElement('b-report-table-header-cell')
|
|
11
|
+
export class BReportTableHeaderCell extends LitElement {
|
|
12
|
+
static styles = css`
|
|
13
|
+
:host {
|
|
14
|
+
display: table-cell;
|
|
15
|
+
padding: 12px 16px;
|
|
16
|
+
text-align: left;
|
|
17
|
+
font-weight: 600;
|
|
18
|
+
background: #f8fafc;
|
|
19
|
+
border-bottom: 2px solid #e2e8f0;
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Vertical sticky (when parent header has sticky attribute) */
|
|
24
|
+
:host([data-sticky-top]) {
|
|
25
|
+
position: sticky;
|
|
26
|
+
top: 0;
|
|
27
|
+
z-index: 2;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Horizontal sticky columns */
|
|
31
|
+
:host([sticky='left']),
|
|
32
|
+
:host([sticky='right']) {
|
|
33
|
+
position: sticky;
|
|
34
|
+
z-index: 2;
|
|
35
|
+
background: #f1f5f9;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Both vertical and horizontal sticky */
|
|
39
|
+
:host([data-sticky-top][sticky='left']),
|
|
40
|
+
:host([data-sticky-top][sticky='right']) {
|
|
41
|
+
z-index: 4;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:host([sticky='left']) {
|
|
45
|
+
left: var(--sticky-offset, 0px);
|
|
46
|
+
box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
:host([sticky='right']) {
|
|
50
|
+
right: var(--sticky-offset, 0px);
|
|
51
|
+
box-shadow: -2px 0 4px -2px rgba(0, 0, 0, 0.1);
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Determines if this column should be sticky.
|
|
57
|
+
* - "left": Column sticks to the left side
|
|
58
|
+
* - "right": Column sticks to the right side
|
|
59
|
+
* - null/undefined: Column is not sticky
|
|
60
|
+
*/
|
|
61
|
+
@property({ type: String, reflect: true })
|
|
62
|
+
sticky: 'left' | 'right' | null = null;
|
|
63
|
+
|
|
64
|
+
@state()
|
|
65
|
+
private _offset = 0;
|
|
66
|
+
|
|
67
|
+
connectedCallback(): void {
|
|
68
|
+
super.connectedCallback();
|
|
69
|
+
this._findTable()?.addEventListener(
|
|
70
|
+
'column-config-change',
|
|
71
|
+
this._handleConfigChange
|
|
72
|
+
);
|
|
73
|
+
// Check if parent header has sticky attribute
|
|
74
|
+
this._updateVerticalSticky();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private _updateVerticalSticky(): void {
|
|
78
|
+
const header = this.closest('b-report-table-header');
|
|
79
|
+
if (header?.hasAttribute('sticky')) {
|
|
80
|
+
this.setAttribute('data-sticky-top', '');
|
|
81
|
+
} else {
|
|
82
|
+
this.removeAttribute('data-sticky-top');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
disconnectedCallback(): void {
|
|
87
|
+
super.disconnectedCallback();
|
|
88
|
+
this._findTable()?.removeEventListener(
|
|
89
|
+
'column-config-change',
|
|
90
|
+
this._handleConfigChange
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private _findTable(): HTMLElement | null {
|
|
95
|
+
return this.closest('b-report-table');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private _handleConfigChange = (event: Event): void => {
|
|
99
|
+
const customEvent = event as CustomEvent<{ configs: ColumnStickyConfig[] }>;
|
|
100
|
+
const configs = customEvent.detail.configs;
|
|
101
|
+
const index = this._getColumnIndex();
|
|
102
|
+
|
|
103
|
+
const config = configs.find((c) => c.index === index);
|
|
104
|
+
if (config && config.sticky) {
|
|
105
|
+
this._offset = config.offset;
|
|
106
|
+
this.style.setProperty('--sticky-offset', `${this._offset}px`);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
private _getColumnIndex(): number {
|
|
111
|
+
const row = this.parentElement;
|
|
112
|
+
if (!row) return -1;
|
|
113
|
+
const cells = Array.from(
|
|
114
|
+
row.querySelectorAll('b-report-table-header-cell')
|
|
115
|
+
);
|
|
116
|
+
return cells.indexOf(this);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
render() {
|
|
120
|
+
return html`<slot></slot>`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
declare global {
|
|
125
|
+
interface HTMLElementTagNameMap {
|
|
126
|
+
'b-report-table-header-cell': BReportTableHeaderCell;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A row within the table header.
|
|
6
|
+
*
|
|
7
|
+
* @slot - Default slot for header cells (b-report-table-header-cell)
|
|
8
|
+
*/
|
|
9
|
+
@customElement('b-report-table-header-row')
|
|
10
|
+
export class BReportTableHeaderRow extends LitElement {
|
|
11
|
+
static styles = css`
|
|
12
|
+
:host {
|
|
13
|
+
display: table-row;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
render() {
|
|
18
|
+
return html`<slot></slot>`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare global {
|
|
23
|
+
interface HTMLElementTagNameMap {
|
|
24
|
+
'b-report-table-header-row': BReportTableHeaderRow;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
3
|
+
import type { BReportTable, ColumnStickyConfig } from './b-report-table.js';
|
|
4
|
+
import type { BReportTableHeaderCell } from './b-report-table-header-cell.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Table header component that wraps header rows.
|
|
8
|
+
*
|
|
9
|
+
* @slot - Default slot for header rows (b-report-table-header-row)
|
|
10
|
+
*/
|
|
11
|
+
@customElement('b-report-table-header')
|
|
12
|
+
export class BReportTableHeader extends LitElement {
|
|
13
|
+
static styles = css`
|
|
14
|
+
:host {
|
|
15
|
+
display: table-header-group;
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether the header should be sticky (fixed at the top when scrolling).
|
|
21
|
+
*/
|
|
22
|
+
@property({ type: Boolean, reflect: true })
|
|
23
|
+
sticky = false;
|
|
24
|
+
|
|
25
|
+
private _resizeObserver?: ResizeObserver;
|
|
26
|
+
|
|
27
|
+
connectedCallback(): void {
|
|
28
|
+
super.connectedCallback();
|
|
29
|
+
this._setupResizeObserver();
|
|
30
|
+
// Delay initial calculation to ensure all children are rendered
|
|
31
|
+
requestAnimationFrame(() => {
|
|
32
|
+
this._calculateColumnConfigs();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
disconnectedCallback(): void {
|
|
37
|
+
super.disconnectedCallback();
|
|
38
|
+
this._resizeObserver?.disconnect();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private _setupResizeObserver(): void {
|
|
42
|
+
this._resizeObserver = new ResizeObserver(() => {
|
|
43
|
+
this._calculateColumnConfigs();
|
|
44
|
+
});
|
|
45
|
+
this._resizeObserver.observe(this);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private _calculateColumnConfigs(): void {
|
|
49
|
+
const table = this.closest('b-report-table') as BReportTable | null;
|
|
50
|
+
if (!table) return;
|
|
51
|
+
|
|
52
|
+
// Find the first header row to get column configurations
|
|
53
|
+
const firstRow = this.querySelector('b-report-table-header-row');
|
|
54
|
+
if (!firstRow) return;
|
|
55
|
+
|
|
56
|
+
const cells = Array.from(
|
|
57
|
+
firstRow.querySelectorAll('b-report-table-header-cell')
|
|
58
|
+
) as BReportTableHeaderCell[];
|
|
59
|
+
|
|
60
|
+
const configs: ColumnStickyConfig[] = [];
|
|
61
|
+
let leftOffset = 0;
|
|
62
|
+
let rightOffset = 0;
|
|
63
|
+
|
|
64
|
+
// First pass: collect all cells and their sticky values
|
|
65
|
+
const cellData = cells.map((cell, index) => ({
|
|
66
|
+
index,
|
|
67
|
+
sticky: cell.sticky as 'left' | 'right' | null,
|
|
68
|
+
width: cell.offsetWidth || 100,
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
// Calculate left sticky offsets
|
|
72
|
+
for (const data of cellData) {
|
|
73
|
+
if (data.sticky === 'left') {
|
|
74
|
+
configs.push({
|
|
75
|
+
index: data.index,
|
|
76
|
+
sticky: 'left',
|
|
77
|
+
width: data.width,
|
|
78
|
+
offset: leftOffset,
|
|
79
|
+
});
|
|
80
|
+
leftOffset += data.width;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Calculate right sticky offsets (from right to left)
|
|
85
|
+
for (let i = cellData.length - 1; i >= 0; i--) {
|
|
86
|
+
const data = cellData[i];
|
|
87
|
+
if (data.sticky === 'right') {
|
|
88
|
+
configs.push({
|
|
89
|
+
index: data.index,
|
|
90
|
+
sticky: 'right',
|
|
91
|
+
width: data.width,
|
|
92
|
+
offset: rightOffset,
|
|
93
|
+
});
|
|
94
|
+
rightOffset += data.width;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add non-sticky columns
|
|
99
|
+
for (const data of cellData) {
|
|
100
|
+
if (data.sticky !== 'left' && data.sticky !== 'right') {
|
|
101
|
+
configs.push({
|
|
102
|
+
index: data.index,
|
|
103
|
+
sticky: null,
|
|
104
|
+
width: data.width,
|
|
105
|
+
offset: 0,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Sort by index
|
|
111
|
+
configs.sort((a, b) => a.index - b.index);
|
|
112
|
+
|
|
113
|
+
table.updateColumnConfigs(configs);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render() {
|
|
117
|
+
return html`<slot></slot>`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
declare global {
|
|
122
|
+
interface HTMLElementTagNameMap {
|
|
123
|
+
'b-report-table-header': BReportTableHeader;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A row within the table body.
|
|
6
|
+
*
|
|
7
|
+
* @slot - Default slot for cells (b-report-table-cell)
|
|
8
|
+
*/
|
|
9
|
+
@customElement('b-report-table-row')
|
|
10
|
+
export class BReportTableRow extends LitElement {
|
|
11
|
+
static styles = css`
|
|
12
|
+
:host {
|
|
13
|
+
display: table-row;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
:host(:hover) {
|
|
17
|
+
background: #f8fafc;
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
render() {
|
|
22
|
+
return html`<slot></slot>`;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare global {
|
|
27
|
+
interface HTMLElementTagNameMap {
|
|
28
|
+
'b-report-table-row': BReportTableRow;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { customElement, state } from 'lit/decorators.js';
|
|
3
|
+
|
|
4
|
+
export interface ColumnStickyConfig {
|
|
5
|
+
index: number;
|
|
6
|
+
sticky: 'left' | 'right' | null;
|
|
7
|
+
width: number;
|
|
8
|
+
offset: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A report table component with support for sticky headers, footers, and columns.
|
|
13
|
+
*
|
|
14
|
+
* @slot header - The table header (b-report-table-header)
|
|
15
|
+
* @slot - Default slot for table body (b-report-table-body)
|
|
16
|
+
* @slot footer - The table footer (b-report-table-footer)
|
|
17
|
+
*/
|
|
18
|
+
@customElement('b-report-table')
|
|
19
|
+
export class BReportTable extends LitElement {
|
|
20
|
+
static styles = css`
|
|
21
|
+
:host {
|
|
22
|
+
display: block;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
table {
|
|
26
|
+
width: 100%;
|
|
27
|
+
border-collapse: separate;
|
|
28
|
+
border-spacing: 0;
|
|
29
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
30
|
+
font-size: 14px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
::slotted(*) {
|
|
34
|
+
display: table-row-group;
|
|
35
|
+
}
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
@state()
|
|
39
|
+
private _columnConfigs: ColumnStickyConfig[] = [];
|
|
40
|
+
|
|
41
|
+
get columnConfigs(): ColumnStickyConfig[] {
|
|
42
|
+
return this._columnConfigs;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Updates the sticky column configuration based on header cells.
|
|
47
|
+
* This is called by the header component when it's connected or updated.
|
|
48
|
+
*/
|
|
49
|
+
updateColumnConfigs(configs: ColumnStickyConfig[]): void {
|
|
50
|
+
this._columnConfigs = configs;
|
|
51
|
+
this._notifyChildren();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private _notifyChildren(): void {
|
|
55
|
+
// Dispatch event to notify all children of column config changes
|
|
56
|
+
this.dispatchEvent(
|
|
57
|
+
new CustomEvent('column-config-change', {
|
|
58
|
+
detail: { configs: this._columnConfigs },
|
|
59
|
+
bubbles: true,
|
|
60
|
+
composed: true,
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
render() {
|
|
66
|
+
return html`
|
|
67
|
+
<table role="table">
|
|
68
|
+
<slot name="header"></slot>
|
|
69
|
+
<slot></slot>
|
|
70
|
+
<slot name="footer"></slot>
|
|
71
|
+
</table>
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
declare global {
|
|
77
|
+
interface HTMLElementTagNameMap {
|
|
78
|
+
'b-report-table': BReportTable;
|
|
79
|
+
}
|
|
80
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { BReportTable } from './b-report-table.js';
|
|
2
|
+
export { BReportTableHeader } from './b-report-table-header.js';
|
|
3
|
+
export { BReportTableHeaderRow } from './b-report-table-header-row.js';
|
|
4
|
+
export { BReportTableHeaderCell } from './b-report-table-header-cell.js';
|
|
5
|
+
export { BReportTableBody } from './b-report-table-body.js';
|
|
6
|
+
export { BReportTableRow } from './b-report-table-row.js';
|
|
7
|
+
export { BReportTableCell } from './b-report-table-cell.js';
|
|
8
|
+
export { BReportTableFooter } from './b-report-table-footer.js';
|
|
9
|
+
export { BReportTableFooterRow } from './b-report-table-footer-row.js';
|
|
10
|
+
export { BReportTableFooterCell } from './b-report-table-footer-cell.js';
|
|
11
|
+
|
|
12
|
+
export type { ColumnStickyConfig } from './b-report-table.js';
|