@spectric/ui 0.0.20 → 0.0.21

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.
@@ -1,139 +1,189 @@
1
- import { html } from 'lit';
2
- import { customElement, property, } from 'lit/decorators.js';
3
- import { HTMLElementTagWithEvents, ReactElementWithPropsAndEvents } from '../types';
4
- export const TableBodyElementTag = "spectric-table-virtual-body"
5
- import "./cell"
6
- import { ColumnSettings, SpectricTableElement, TD_BorderAndPadding } from './table';
7
- import { repeat } from 'lit/directives/repeat.js';
8
- import { DisposableElement } from '../../classes/DisposibleElement';
9
- import "./virtualBody.css"
1
+ import { html } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+ import {
4
+ HTMLElementTagWithEvents,
5
+ ReactElementWithPropsAndEvents,
6
+ } from "../types";
7
+ export const TableBodyElementTag = "spectric-table-virtual-body";
8
+ import "./cell";
9
+ import {
10
+ ColumnSettings,
11
+ SpectricTableElement,
12
+ TD_BorderAndPadding,
13
+ } from "./table";
14
+ import { repeat } from "lit/directives/repeat.js";
15
+ import { DisposableElement } from "../../classes/DisposibleElement";
16
+ import "./virtualBody.css";
10
17
  interface BodyProps<T> {
11
- columns: ColumnSettings<T>[]
12
- data: T[]
13
- rowHeight: number
18
+ columns: ColumnSettings<T>[];
19
+ data: T[];
20
+ rowHeight: number;
14
21
  }
15
22
 
16
-
17
23
  /**
18
24
  * Table Body Element
19
25
  */
20
26
  @customElement(TableBodyElementTag)
21
- export class TableVirtualBodyElement<T> extends DisposableElement implements BodyProps<T> {
22
- @property({ type: Array, attribute: false })
23
- data: T[] = [];
24
- @property({ type: Array, attribute: false })
25
- columns: ColumnSettings<T>[] = [];
26
- @property({ type: Number, attribute: false })
27
- rowHeight: number = 30;
27
+ export class TableVirtualBodyElement<T>
28
+ extends DisposableElement
29
+ implements BodyProps<T>
30
+ {
31
+ @property({ type: Array, attribute: false })
32
+ data: T[] = [];
33
+ @property({ type: Array, attribute: false })
34
+ columns: ColumnSettings<T>[] = [];
35
+ @property({ type: Number, attribute: false })
36
+ rowHeight: number = 30;
28
37
 
29
- @property({ type: Number, state: true })
30
- startIndex: number = 0
38
+ @property({ type: Number, state: true })
39
+ startIndex: number = 0;
31
40
 
32
- table!: SpectricTableElement<T>
33
- columnsMeasured: boolean = false;
34
- constructor() {
35
- super()
36
- this.addDisposableListener(() => this.table.querySelector(".table-wrapper")!, "scroll", () => {
37
- const scrollTop = this.table.querySelector(".table-wrapper")!.scrollTop;
38
- requestAnimationFrame(() => {
39
- this.startIndex = Math.floor(scrollTop / this.rowHeight);
40
- })
41
- })
42
- }
43
- protected updated(): void {
44
- if (this.columnsMeasured === false) {
45
- let tr = this.querySelector("tr");
46
- let cells = tr?.querySelectorAll("spectric-table-cell td")
47
- if (tr && cells && cells.length) {
48
- this.columns.forEach((col, index) => {
49
- if (!col.width || col.width === 0) {
50
- let rect = cells[index].getBoundingClientRect()
51
- if (rect.width > 0) {
52
- this.columnsMeasured = true
53
- col.width = rect.width - TD_BorderAndPadding
54
- }
55
- }
56
- })
57
- this.columns = [...this.columns]
41
+ @property({ type: Object, attribute: false })
42
+ table!: SpectricTableElement<T>;
43
+ columnsMeasured: boolean = false;
44
+ constructor() {
45
+ super();
46
+ this.addDisposableListener(
47
+ () => this.table.querySelector(".table-wrapper")!,
48
+ "scroll",
49
+ () => {
50
+ const scrollTop = this.table.querySelector(".table-wrapper")!.scrollTop;
51
+ requestAnimationFrame(() => {
52
+ this.startIndex = Math.floor(scrollTop / this.rowHeight);
53
+ });
54
+ }
55
+ );
56
+ }
57
+ protected updated(): void {
58
+ if (this.columnsMeasured === false) {
59
+ let tr = this.querySelector("tr");
60
+ let cells = tr?.querySelectorAll("spectric-table-cell td");
61
+ if (tr && cells && cells.length) {
62
+ this.columns.forEach((col, index) => {
63
+ if (!col.width || col.width === 0) {
64
+ let rect = cells[index].getBoundingClientRect();
65
+ if (rect.width > 0) {
66
+ this.columnsMeasured = true;
67
+ col.width = rect.width - TD_BorderAndPadding;
58
68
  }
69
+ }
70
+ });
71
+ if (this.columnsMeasured) {
72
+ this.columns = [...this.columns];
59
73
  }
74
+ }
60
75
  }
61
- protected createRenderRoot(): HTMLElement | DocumentFragment {
62
- return this
63
- }
64
- protected render(): unknown {
65
- let totalRows = this.data.length
66
- let buffer = 10 // Have a buffer of rows to prevent column jitter
67
- let headerHeight = this.table.querySelector("spectric-table-header")!.clientHeight
68
- let viewport = this.table.querySelector(".table-wrapper")!
69
- let startIndex = Math.max(this.startIndex, 0)
70
- const rowsThatFit = Math.ceil((viewport.clientHeight - headerHeight) / this.rowHeight);
71
- const endIndex = Math.min(startIndex + rowsThatFit + buffer, totalRows);
72
- const visibleRows = endIndex - startIndex
73
- let totalHeight = totalRows * this.rowHeight
74
- let beforeHeight = (startIndex * this.rowHeight) + (viewport.scrollTop - (startIndex * this.rowHeight))
75
- if (endIndex === totalRows) {
76
- beforeHeight = (startIndex * this.rowHeight)
77
- }
78
- let visibleHeight = (visibleRows * this.rowHeight)
79
- let afterHeight = totalHeight - beforeHeight - visibleHeight
80
- let spacerElementBefore = startIndex != 0 ? html`
81
- <tr style="height:${beforeHeight}px" class="virtual-scroll-spacer">
82
- <td colspan="${this.columns.length}"></td></tr>` : null
83
-
84
- let spacerElementAfter = html`
85
- <tr style="height:${afterHeight}px" class="virtual-scroll-spacer">
86
- <td colspan="${this.columns.length}"></td></tr>`
87
- return html`
88
- <div style="height:${totalHeight}px;position: absolute;overflow-x: hidden;overflow-y: hidden;z-index:-1;width:1px;"></div>
89
- <tbody>
90
- ${spacerElementBefore}
91
- </tbody>
92
- <div style="display:table-row-group;max-height:${visibleHeight}px; overflow:hidden;">
93
-
94
- ${repeat(this.data.slice(Math.max(startIndex, 0), endIndex), (row, index) => html`
95
- <tr class="${(index + startIndex) % 2 === 0 ? "odd" : ""}">
96
- ${repeat(this.columns, (col) => {
97
- return html`<spectric-table-cell .column=${col} .row=${row} .index=${index + startIndex} .columns=${this.columns}></spectric-table-cell>`
98
- })}
99
- </tr>`)
100
- }
101
- </div>
102
- <tbody>
103
- ${afterHeight > 0 ? spacerElementAfter : null}
104
- </tbody>
105
-
106
- `
107
-
76
+ }
77
+ protected createRenderRoot(): HTMLElement | DocumentFragment {
78
+ return this;
79
+ }
80
+ protected render(): unknown {
81
+ let totalRows = this.data.length;
82
+ let buffer = 10; // Have a buffer of rows to prevent column jitter
83
+ let headerHeight = this.table.querySelector(
84
+ "spectric-table-header"
85
+ )!.clientHeight;
86
+ let viewport = this.table.querySelector(".table-wrapper")!;
87
+ let startIndex = Math.max(this.startIndex, 0);
88
+ const rowsThatFit = Math.ceil(
89
+ (viewport.clientHeight - headerHeight) / this.rowHeight
90
+ );
91
+ const endIndex = Math.min(startIndex + rowsThatFit + buffer, totalRows);
92
+ const visibleRows = endIndex - startIndex;
93
+ let totalHeight = totalRows * this.rowHeight;
94
+ let beforeHeight =
95
+ startIndex * this.rowHeight +
96
+ (viewport.scrollTop - startIndex * this.rowHeight);
97
+ if (endIndex === totalRows) {
98
+ beforeHeight = startIndex * this.rowHeight;
108
99
  }
100
+ let visibleHeight = visibleRows * this.rowHeight;
101
+ let afterHeight = totalHeight - beforeHeight - visibleHeight;
102
+ let spacerElementBefore =
103
+ startIndex != 0
104
+ ? html` <tr
105
+ style="height:${beforeHeight}px"
106
+ class="virtual-scroll-spacer"
107
+ >
108
+ <td colspan="${this.columns.length}"></td>
109
+ </tr>`
110
+ : null;
109
111
 
112
+ let spacerElementAfter = html` <tr
113
+ style="height:${afterHeight}px"
114
+ class="virtual-scroll-spacer"
115
+ >
116
+ <td colspan="${this.columns.length}"></td>
117
+ </tr>`;
118
+ return html`
119
+ <div
120
+ style="height:${totalHeight}px;position: absolute;overflow-x: hidden;overflow-y: hidden;z-index:-1;width:1px;"
121
+ ></div>
122
+ <tbody>
123
+ ${spacerElementBefore}
124
+ </tbody>
125
+ <div
126
+ style="display:table-row-group;max-height:${visibleHeight}px; overflow:hidden;"
127
+ >
128
+ ${repeat(
129
+ this.data.slice(Math.max(startIndex, 0), endIndex),
130
+ (row, index) => html` <tr
131
+ class="${(index + startIndex) % 2 === 0 ? "odd" : ""}"
132
+ >
133
+ ${repeat(this.columns, (col) => {
134
+ return html`<spectric-table-cell
135
+ .column=${col}
136
+ .row=${row}
137
+ .index=${index + startIndex}
138
+ .columns=${this.columns}
139
+ .table=${this.table}
140
+ ></spectric-table-cell>`;
141
+ })}
142
+ </tr>`
143
+ )}
144
+ </div>
145
+ <tbody>
146
+ ${afterHeight > 0 ? spacerElementAfter : null}
147
+ </tbody>
148
+ `;
149
+ }
110
150
  }
111
151
 
112
152
  interface TableBodyEvents {
113
- //'sort': (event: CustomEvent<ColumnSettings<any>>) => void; //TODO sort events
153
+ //'sort': (event: CustomEvent<ColumnSettings<any>>) => void; //TODO sort events
114
154
  }
115
155
 
116
156
  declare global {
117
- interface HTMLElementTagNameMap {
118
- [TableBodyElementTag]: HTMLElementTagWithEvents<TableVirtualBodyElement<any>, TableBodyEvents>
119
-
157
+ interface HTMLElementTagNameMap {
158
+ [TableBodyElementTag]: HTMLElementTagWithEvents<
159
+ TableVirtualBodyElement<any>,
160
+ TableBodyEvents
161
+ >;
162
+ }
163
+ namespace JSX {
164
+ interface IntrinsicElements {
165
+ /**
166
+ * @see {@link DialogElement}
167
+ */
168
+ [TableBodyElementTag]: ReactElementWithPropsAndEvents<
169
+ TableVirtualBodyElement<any>,
170
+ BodyProps<any>,
171
+ TableBodyEvents
172
+ >;
120
173
  }
174
+ }
175
+ namespace React {
121
176
  namespace JSX {
122
- interface IntrinsicElements {
123
- /**
124
- * @see {@link DialogElement}
125
- */
126
- [TableBodyElementTag]: ReactElementWithPropsAndEvents<TableVirtualBodyElement<any>, BodyProps<any>, TableBodyEvents>;
127
- }
128
- }
129
- namespace React {
130
- namespace JSX {
131
- interface IntrinsicElements {
132
- /**
133
- * @see {@link DialogElement}
134
- */
135
- [TableBodyElementTag]: ReactElementWithPropsAndEvents<TableVirtualBodyElement<any>, BodyProps<any>, TableBodyEvents>
136
- }
137
- }
177
+ interface IntrinsicElements {
178
+ /**
179
+ * @see {@link DialogElement}
180
+ */
181
+ [TableBodyElementTag]: ReactElementWithPropsAndEvents<
182
+ TableVirtualBodyElement<any>,
183
+ BodyProps<any>,
184
+ TableBodyEvents
185
+ >;
186
+ }
138
187
  }
188
+ }
139
189
  }