@oscarpalmer/tabela 0.2.0 → 0.3.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/components/body.component.cjs +28 -5
- package/dist/components/body.component.js +28 -5
- package/dist/components/column.component.cjs +1 -1
- package/dist/components/column.component.js +1 -1
- package/dist/components/row.component.cjs +6 -0
- package/dist/components/row.component.js +6 -0
- package/dist/managers/virtualization.manager.cjs +75 -0
- package/dist/managers/virtualization.manager.js +75 -0
- package/package.json +1 -1
- package/src/components/body.component.ts +38 -6
- package/src/components/column.component.ts +1 -1
- package/src/components/row.component.ts +23 -16
- package/src/managers/virtualization.manager.ts +98 -0
- package/types/components/body.component.d.cts +14 -1
- package/types/components/body.component.d.ts +5 -1
- package/types/components/cell.component.d.cts +14 -1
- package/types/components/column.component.d.cts +14 -1
- package/types/components/footer.component.d.cts +14 -1
- package/types/components/header.component.d.cts +14 -1
- package/types/components/row.component.d.cts +14 -1
- package/types/components/row.component.d.ts +1 -0
- package/types/index.d.cts +14 -1
- package/types/managers/virtualization.manager.d.cts +86 -0
- package/types/managers/virtualization.manager.d.ts +10 -0
- package/types/tabela.d.cts +14 -1
|
@@ -4,23 +4,46 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
6
|
const helpers_dom_helpers = require("../helpers/dom.helpers.cjs");
|
|
7
|
+
const managers_virtualization_manager = require("../managers/virtualization.manager.cjs");
|
|
7
8
|
const components_row_component = require("./row.component.cjs");
|
|
9
|
+
function createFaker() {
|
|
10
|
+
const element = document.createElement("div");
|
|
11
|
+
element.style.height = "0";
|
|
12
|
+
element.style.inset = "0 auto auto 0";
|
|
13
|
+
element.style.opacity = "0";
|
|
14
|
+
element.style.pointerEvents = "none";
|
|
15
|
+
element.style.position = "absolute";
|
|
16
|
+
element.style.width = "1px";
|
|
17
|
+
return element;
|
|
18
|
+
}
|
|
8
19
|
class BodyComponent {
|
|
9
20
|
constructor(tabela) {
|
|
21
|
+
__publicField(this, "faker", createFaker());
|
|
10
22
|
__publicField(this, "group");
|
|
11
23
|
__publicField(this, "rows", []);
|
|
24
|
+
__publicField(this, "virtualization");
|
|
12
25
|
this.tabela = tabela;
|
|
13
26
|
this.group = helpers_dom_helpers.createRowGroup(false);
|
|
27
|
+
this.virtualization = new managers_virtualization_manager.VirtualizationManager(this);
|
|
14
28
|
this.group.className += " tabela__rowgroup-body";
|
|
15
|
-
this.
|
|
29
|
+
this.group.style.height = "100%";
|
|
30
|
+
this.group.style.overflow = "auto";
|
|
31
|
+
this.group.style.position = "relative";
|
|
32
|
+
this.group.append(this.faker);
|
|
33
|
+
void this.addData(tabela.options.data).then(() => {
|
|
34
|
+
this.virtualization.update(true);
|
|
35
|
+
});
|
|
16
36
|
}
|
|
17
|
-
addData(data) {
|
|
37
|
+
async addData(data) {
|
|
18
38
|
const { length } = data;
|
|
19
39
|
for (let index = 0; index < length; index += 1) {
|
|
20
|
-
|
|
21
|
-
this.rows.push(row);
|
|
22
|
-
this.group.append(row.element);
|
|
40
|
+
this.rows.push(new components_row_component.RowComponent(this.tabela, data[index]));
|
|
23
41
|
}
|
|
42
|
+
this.updateVirtualization();
|
|
43
|
+
}
|
|
44
|
+
updateVirtualization() {
|
|
45
|
+
this.faker.style.height = `${this.rows.length * 32}px`;
|
|
46
|
+
this.virtualization.update(true);
|
|
24
47
|
}
|
|
25
48
|
}
|
|
26
49
|
exports.BodyComponent = BodyComponent;
|
|
@@ -2,23 +2,46 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { createRowGroup } from "../helpers/dom.helpers.js";
|
|
5
|
+
import { VirtualizationManager } from "../managers/virtualization.manager.js";
|
|
5
6
|
import { RowComponent } from "./row.component.js";
|
|
7
|
+
function createFaker() {
|
|
8
|
+
const element = document.createElement("div");
|
|
9
|
+
element.style.height = "0";
|
|
10
|
+
element.style.inset = "0 auto auto 0";
|
|
11
|
+
element.style.opacity = "0";
|
|
12
|
+
element.style.pointerEvents = "none";
|
|
13
|
+
element.style.position = "absolute";
|
|
14
|
+
element.style.width = "1px";
|
|
15
|
+
return element;
|
|
16
|
+
}
|
|
6
17
|
class BodyComponent {
|
|
7
18
|
constructor(tabela) {
|
|
19
|
+
__publicField(this, "faker", createFaker());
|
|
8
20
|
__publicField(this, "group");
|
|
9
21
|
__publicField(this, "rows", []);
|
|
22
|
+
__publicField(this, "virtualization");
|
|
10
23
|
this.tabela = tabela;
|
|
11
24
|
this.group = createRowGroup(false);
|
|
25
|
+
this.virtualization = new VirtualizationManager(this);
|
|
12
26
|
this.group.className += " tabela__rowgroup-body";
|
|
13
|
-
this.
|
|
27
|
+
this.group.style.height = "100%";
|
|
28
|
+
this.group.style.overflow = "auto";
|
|
29
|
+
this.group.style.position = "relative";
|
|
30
|
+
this.group.append(this.faker);
|
|
31
|
+
void this.addData(tabela.options.data).then(() => {
|
|
32
|
+
this.virtualization.update(true);
|
|
33
|
+
});
|
|
14
34
|
}
|
|
15
|
-
addData(data) {
|
|
35
|
+
async addData(data) {
|
|
16
36
|
const { length } = data;
|
|
17
37
|
for (let index = 0; index < length; index += 1) {
|
|
18
|
-
|
|
19
|
-
this.rows.push(row);
|
|
20
|
-
this.group.append(row.element);
|
|
38
|
+
this.rows.push(new RowComponent(this.tabela, data[index]));
|
|
21
39
|
}
|
|
40
|
+
this.updateVirtualization();
|
|
41
|
+
}
|
|
42
|
+
updateVirtualization() {
|
|
43
|
+
this.faker.style.height = `${this.rows.length * 32}px`;
|
|
44
|
+
this.virtualization.update(true);
|
|
22
45
|
}
|
|
23
46
|
}
|
|
24
47
|
export {
|
|
@@ -16,7 +16,7 @@ class ColumnComponent {
|
|
|
16
16
|
__publicField(this, "element");
|
|
17
17
|
__publicField(this, "options");
|
|
18
18
|
this.tabela = tabela;
|
|
19
|
-
const width = Number.parseInt(getComputedStyle(tabela.element).fontSize, 10) * (options.width ??
|
|
19
|
+
const width = Number.parseInt(getComputedStyle(tabela.element).fontSize, 10) * (options.width ?? options.title.length * 1.5);
|
|
20
20
|
this.options = {
|
|
21
21
|
...options,
|
|
22
22
|
width
|
|
@@ -14,7 +14,7 @@ class ColumnComponent {
|
|
|
14
14
|
__publicField(this, "element");
|
|
15
15
|
__publicField(this, "options");
|
|
16
16
|
this.tabela = tabela;
|
|
17
|
-
const width = Number.parseInt(getComputedStyle(tabela.element).fontSize, 10) * (options.width ??
|
|
17
|
+
const width = Number.parseInt(getComputedStyle(tabela.element).fontSize, 10) * (options.width ?? options.title.length * 1.5);
|
|
18
18
|
this.options = {
|
|
19
19
|
...options,
|
|
20
20
|
width
|
|
@@ -13,6 +13,12 @@ class RowComponent {
|
|
|
13
13
|
this.data = data;
|
|
14
14
|
this.element = helpers_dom_helpers.createRow();
|
|
15
15
|
this.element.className += " tabela__row-body";
|
|
16
|
+
}
|
|
17
|
+
render() {
|
|
18
|
+
if (this.element.innerHTML !== "") {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const { tabela } = this;
|
|
16
22
|
const { columns } = tabela.header;
|
|
17
23
|
const { length } = columns;
|
|
18
24
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -11,6 +11,12 @@ class RowComponent {
|
|
|
11
11
|
this.data = data;
|
|
12
12
|
this.element = createRow();
|
|
13
13
|
this.element.className += " tabela__row-body";
|
|
14
|
+
}
|
|
15
|
+
render() {
|
|
16
|
+
if (this.element.innerHTML !== "") {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { tabela } = this;
|
|
14
20
|
const { columns } = tabela.header;
|
|
15
21
|
const { length } = columns;
|
|
16
22
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
+
function getRange(body, down) {
|
|
7
|
+
const { group, rows } = body;
|
|
8
|
+
const { clientHeight, scrollTop } = group;
|
|
9
|
+
const first = Math.floor(scrollTop / 32);
|
|
10
|
+
const last = Math.min(
|
|
11
|
+
rows.length - 1,
|
|
12
|
+
Math.ceil((scrollTop + clientHeight) / 32) - 1
|
|
13
|
+
);
|
|
14
|
+
const before = Math.ceil(clientHeight / 32) * (down ? 1 : 2);
|
|
15
|
+
const after = Math.ceil(clientHeight / 32) * (down ? 2 : 1);
|
|
16
|
+
const start = Math.max(0, first - before);
|
|
17
|
+
const end = Math.min(rows.length - 1, last + after);
|
|
18
|
+
return { end, start };
|
|
19
|
+
}
|
|
20
|
+
class VirtualizationManager {
|
|
21
|
+
constructor(body) {
|
|
22
|
+
__publicField(this, "active", false);
|
|
23
|
+
__publicField(this, "top", 0);
|
|
24
|
+
__publicField(this, "visible", /* @__PURE__ */ new Map());
|
|
25
|
+
this.body = body;
|
|
26
|
+
this.body.group.addEventListener(
|
|
27
|
+
"scroll",
|
|
28
|
+
() => {
|
|
29
|
+
this.onScroll();
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
passive: true
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
update(down) {
|
|
37
|
+
const { body, visible } = this;
|
|
38
|
+
const indices = /* @__PURE__ */ new Set();
|
|
39
|
+
const range = getRange(body, down);
|
|
40
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
41
|
+
indices.add(index);
|
|
42
|
+
}
|
|
43
|
+
for (const [index, row] of visible) {
|
|
44
|
+
if (!indices.has(index)) {
|
|
45
|
+
visible.delete(index);
|
|
46
|
+
row.element.remove();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const fragment = document.createDocumentFragment();
|
|
50
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
51
|
+
if (!visible.has(index)) {
|
|
52
|
+
const row = body.rows[index];
|
|
53
|
+
row.element.style.inset = "0 auto auto 0";
|
|
54
|
+
row.element.style.position = "absolute";
|
|
55
|
+
row.element.style.transform = `translateY(${index * 32}px)`;
|
|
56
|
+
row.render();
|
|
57
|
+
visible.set(index, row);
|
|
58
|
+
fragment.append(row.element);
|
|
59
|
+
}
|
|
60
|
+
body.group.append(fragment);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
onScroll() {
|
|
64
|
+
if (!this.active) {
|
|
65
|
+
requestAnimationFrame(() => {
|
|
66
|
+
const top = this.body.group.scrollTop;
|
|
67
|
+
this.update(top > this.top);
|
|
68
|
+
this.active = false;
|
|
69
|
+
this.top = top;
|
|
70
|
+
});
|
|
71
|
+
this.active = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.VirtualizationManager = VirtualizationManager;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
function getRange(body, down) {
|
|
5
|
+
const { group, rows } = body;
|
|
6
|
+
const { clientHeight, scrollTop } = group;
|
|
7
|
+
const first = Math.floor(scrollTop / 32);
|
|
8
|
+
const last = Math.min(
|
|
9
|
+
rows.length - 1,
|
|
10
|
+
Math.ceil((scrollTop + clientHeight) / 32) - 1
|
|
11
|
+
);
|
|
12
|
+
const before = Math.ceil(clientHeight / 32) * (down ? 1 : 2);
|
|
13
|
+
const after = Math.ceil(clientHeight / 32) * (down ? 2 : 1);
|
|
14
|
+
const start = Math.max(0, first - before);
|
|
15
|
+
const end = Math.min(rows.length - 1, last + after);
|
|
16
|
+
return { end, start };
|
|
17
|
+
}
|
|
18
|
+
class VirtualizationManager {
|
|
19
|
+
constructor(body) {
|
|
20
|
+
__publicField(this, "active", false);
|
|
21
|
+
__publicField(this, "top", 0);
|
|
22
|
+
__publicField(this, "visible", /* @__PURE__ */ new Map());
|
|
23
|
+
this.body = body;
|
|
24
|
+
this.body.group.addEventListener(
|
|
25
|
+
"scroll",
|
|
26
|
+
() => {
|
|
27
|
+
this.onScroll();
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
passive: true
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
update(down) {
|
|
35
|
+
const { body, visible } = this;
|
|
36
|
+
const indices = /* @__PURE__ */ new Set();
|
|
37
|
+
const range = getRange(body, down);
|
|
38
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
39
|
+
indices.add(index);
|
|
40
|
+
}
|
|
41
|
+
for (const [index, row] of visible) {
|
|
42
|
+
if (!indices.has(index)) {
|
|
43
|
+
visible.delete(index);
|
|
44
|
+
row.element.remove();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const fragment = document.createDocumentFragment();
|
|
48
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
49
|
+
if (!visible.has(index)) {
|
|
50
|
+
const row = body.rows[index];
|
|
51
|
+
row.element.style.inset = "0 auto auto 0";
|
|
52
|
+
row.element.style.position = "absolute";
|
|
53
|
+
row.element.style.transform = `translateY(${index * 32}px)`;
|
|
54
|
+
row.render();
|
|
55
|
+
visible.set(index, row);
|
|
56
|
+
fragment.append(row.element);
|
|
57
|
+
}
|
|
58
|
+
body.group.append(fragment);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
onScroll() {
|
|
62
|
+
if (!this.active) {
|
|
63
|
+
requestAnimationFrame(() => {
|
|
64
|
+
const top = this.body.group.scrollTop;
|
|
65
|
+
this.update(top > this.top);
|
|
66
|
+
this.active = false;
|
|
67
|
+
this.top = top;
|
|
68
|
+
});
|
|
69
|
+
this.active = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
VirtualizationManager
|
|
75
|
+
};
|
package/package.json
CHANGED
|
@@ -1,28 +1,60 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {createRowGroup} from '../helpers/dom.helpers';
|
|
3
|
+
import {VirtualizationManager} from '../managers/virtualization.manager';
|
|
3
4
|
import type {Tabela} from '../tabela';
|
|
4
5
|
import {RowComponent} from './row.component';
|
|
5
6
|
|
|
7
|
+
function createFaker(): HTMLDivElement {
|
|
8
|
+
const element = document.createElement('div');
|
|
9
|
+
|
|
10
|
+
element.style.height = '0';
|
|
11
|
+
element.style.inset = '0 auto auto 0';
|
|
12
|
+
element.style.opacity = '0';
|
|
13
|
+
element.style.pointerEvents = 'none';
|
|
14
|
+
element.style.position = 'absolute';
|
|
15
|
+
element.style.width = '1px';
|
|
16
|
+
|
|
17
|
+
return element;
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
export class BodyComponent {
|
|
21
|
+
readonly faker = createFaker();
|
|
7
22
|
readonly group: HTMLDivElement;
|
|
8
23
|
readonly rows: RowComponent[] = [];
|
|
24
|
+
readonly virtualization: VirtualizationManager;
|
|
9
25
|
|
|
10
26
|
constructor(readonly tabela: Tabela) {
|
|
11
27
|
this.group = createRowGroup(false);
|
|
28
|
+
this.virtualization = new VirtualizationManager(this);
|
|
12
29
|
|
|
13
30
|
this.group.className += ' tabela__rowgroup-body';
|
|
14
31
|
|
|
15
|
-
this.
|
|
32
|
+
this.group.style.height = '100%';
|
|
33
|
+
this.group.style.overflow = 'auto';
|
|
34
|
+
this.group.style.position = 'relative';
|
|
35
|
+
|
|
36
|
+
this.group.append(this.faker);
|
|
37
|
+
|
|
38
|
+
void this.addData(tabela.options.data).then(() => {
|
|
39
|
+
this.virtualization.update(true);
|
|
40
|
+
});
|
|
16
41
|
}
|
|
17
42
|
|
|
18
|
-
addData(data: PlainObject[]): void {
|
|
43
|
+
async addData(data: PlainObject[]): Promise<void> {
|
|
19
44
|
const {length} = data;
|
|
20
45
|
|
|
21
46
|
for (let index = 0; index < length; index += 1) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.rows.push(row);
|
|
25
|
-
this.group.append(row.element);
|
|
47
|
+
this.rows.push(new RowComponent(this.tabela, data[index]));
|
|
26
48
|
}
|
|
49
|
+
|
|
50
|
+
this.updateVirtualization();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private updateVirtualization(): void {
|
|
54
|
+
this.faker.style.height = `${this.rows.length * 32}px`;
|
|
55
|
+
|
|
56
|
+
this.virtualization.update(true);
|
|
27
57
|
}
|
|
28
58
|
}
|
|
59
|
+
|
|
60
|
+
|
|
@@ -4,27 +4,34 @@ import type {Tabela} from '../tabela';
|
|
|
4
4
|
import {CellComponent} from './cell.component';
|
|
5
5
|
|
|
6
6
|
export class RowComponent {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
readonly cells: CellComponent[] = [];
|
|
8
|
+
readonly element: HTMLDivElement;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
constructor(
|
|
11
|
+
readonly tabela: Tabela,
|
|
12
|
+
readonly data: PlainObject,
|
|
13
|
+
) {
|
|
14
|
+
this.element = createRow();
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
this.element.className += ' tabela__row-body';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
render(): void {
|
|
20
|
+
if (this.element.innerHTML !== '') {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
const {tabela} = this;
|
|
25
|
+
const {columns} = tabela.header;
|
|
26
|
+
const {length} = columns;
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
|
|
28
|
+
for (let index = 0; index < length; index += 1) {
|
|
29
|
+
const cell = new CellComponent(tabela, columns[index], this);
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
cell.element.className += ' tabela__cell-body';
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
33
|
+
this.cells.push(cell);
|
|
34
|
+
this.element.append(cell.element);
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
|
-
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type {BodyComponent} from '../components/body.component';
|
|
2
|
+
import type {RowComponent} from '../components/row.component';
|
|
3
|
+
|
|
4
|
+
type Range = {
|
|
5
|
+
end: number;
|
|
6
|
+
start: number;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function getRange(body: BodyComponent, down: boolean): Range {
|
|
10
|
+
const {group, rows} = body;
|
|
11
|
+
const {clientHeight, scrollTop} = group;
|
|
12
|
+
|
|
13
|
+
const first = Math.floor(scrollTop / 32);
|
|
14
|
+
|
|
15
|
+
const last = Math.min(
|
|
16
|
+
rows.length - 1,
|
|
17
|
+
Math.ceil((scrollTop + clientHeight) / 32) - 1,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const before = Math.ceil(clientHeight / 32) * (down ? 1 : 2);
|
|
21
|
+
const after = Math.ceil(clientHeight / 32) * (down ? 2 : 1);
|
|
22
|
+
|
|
23
|
+
const start = Math.max(0, first - before);
|
|
24
|
+
const end = Math.min(rows.length - 1, last + after);
|
|
25
|
+
|
|
26
|
+
return {end, start};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class VirtualizationManager {
|
|
30
|
+
private active = false;
|
|
31
|
+
private top = 0;
|
|
32
|
+
private readonly visible = new Map<number, RowComponent>();
|
|
33
|
+
|
|
34
|
+
constructor(private readonly body: BodyComponent) {
|
|
35
|
+
this.body.group.addEventListener(
|
|
36
|
+
'scroll',
|
|
37
|
+
() => {
|
|
38
|
+
this.onScroll();
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
passive: true,
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
update(down: boolean): void {
|
|
47
|
+
const {body, visible} = this;
|
|
48
|
+
|
|
49
|
+
const indices = new Set<number>();
|
|
50
|
+
const range = getRange(body, down);
|
|
51
|
+
|
|
52
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
53
|
+
indices.add(index);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const [index, row] of visible) {
|
|
57
|
+
if (!indices.has(index)) {
|
|
58
|
+
visible.delete(index);
|
|
59
|
+
row.element.remove();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const fragment = document.createDocumentFragment();
|
|
64
|
+
|
|
65
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
66
|
+
if (!visible.has(index)) {
|
|
67
|
+
const row = body.rows[index];
|
|
68
|
+
|
|
69
|
+
row.element.style.inset = '0 auto auto 0';
|
|
70
|
+
row.element.style.position = 'absolute';
|
|
71
|
+
row.element.style.transform = `translateY(${index * 32}px)`;
|
|
72
|
+
|
|
73
|
+
row.render();
|
|
74
|
+
|
|
75
|
+
visible.set(index, row);
|
|
76
|
+
|
|
77
|
+
fragment.append(row.element);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
body.group.append(fragment);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private onScroll(): void {
|
|
85
|
+
if (!this.active) {
|
|
86
|
+
requestAnimationFrame(() => {
|
|
87
|
+
const top = this.body.group.scrollTop;
|
|
88
|
+
|
|
89
|
+
this.update(top > this.top);
|
|
90
|
+
|
|
91
|
+
this.active = false;
|
|
92
|
+
this.top = top;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
this.active = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
export declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import type { PlainObject } from '@oscarpalmer/atoms/models';
|
|
2
|
+
import { VirtualizationManager } from '../managers/virtualization.manager';
|
|
2
3
|
import type { Tabela } from '../tabela';
|
|
3
4
|
import { RowComponent } from './row.component';
|
|
4
5
|
export declare class BodyComponent {
|
|
5
6
|
readonly tabela: Tabela;
|
|
7
|
+
readonly faker: HTMLDivElement;
|
|
6
8
|
readonly group: HTMLDivElement;
|
|
7
9
|
readonly rows: RowComponent[];
|
|
10
|
+
readonly virtualization: VirtualizationManager;
|
|
8
11
|
constructor(tabela: Tabela);
|
|
9
|
-
addData(data: PlainObject[]): void
|
|
12
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
13
|
+
private updateVirtualization;
|
|
10
14
|
}
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
export declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ export declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
package/types/index.d.cts
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
|
+
|
|
5
|
+
export declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
14
|
+
export type TabelaColumn = {
|
|
15
|
+
field: string;
|
|
16
|
+
title: string;
|
|
17
|
+
type: TabelaColumnType;
|
|
18
|
+
width: number;
|
|
19
|
+
};
|
|
20
|
+
export type TabelaColumnOptions = {
|
|
21
|
+
field: string;
|
|
22
|
+
title: string;
|
|
23
|
+
type: TabelaColumnType;
|
|
24
|
+
width?: number;
|
|
25
|
+
};
|
|
26
|
+
export type TabelaColumnType = "boolean" | "date" | "date-time" | "number" | "string" | "time";
|
|
27
|
+
declare class ColumnComponent {
|
|
28
|
+
readonly tabela: Tabela;
|
|
29
|
+
readonly element: HTMLDivElement;
|
|
30
|
+
readonly options: TabelaColumn;
|
|
31
|
+
constructor(tabela: Tabela, options: TabelaColumnOptions);
|
|
32
|
+
}
|
|
33
|
+
declare class CellComponent {
|
|
34
|
+
readonly tabela: Tabela;
|
|
35
|
+
readonly column: ColumnComponent;
|
|
36
|
+
readonly row: RowComponent;
|
|
37
|
+
readonly element: HTMLDivElement;
|
|
38
|
+
constructor(tabela: Tabela, column: ColumnComponent, row: RowComponent);
|
|
39
|
+
}
|
|
40
|
+
declare class RowComponent {
|
|
41
|
+
readonly tabela: Tabela;
|
|
42
|
+
readonly data: PlainObject;
|
|
43
|
+
readonly cells: CellComponent[];
|
|
44
|
+
readonly element: HTMLDivElement;
|
|
45
|
+
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
47
|
+
}
|
|
48
|
+
declare class BodyComponent {
|
|
49
|
+
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
51
|
+
readonly group: HTMLDivElement;
|
|
52
|
+
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
54
|
+
constructor(tabela: Tabela);
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
57
|
+
}
|
|
58
|
+
declare class FooterComponent {
|
|
59
|
+
readonly tabela: Tabela;
|
|
60
|
+
readonly cells: HTMLDivElement[];
|
|
61
|
+
readonly group: HTMLDivElement;
|
|
62
|
+
readonly row: HTMLDivElement;
|
|
63
|
+
constructor(tabela: Tabela);
|
|
64
|
+
}
|
|
65
|
+
declare class HeaderComponent {
|
|
66
|
+
readonly tabela: Tabela;
|
|
67
|
+
readonly columns: ColumnComponent[];
|
|
68
|
+
readonly group: HTMLDivElement;
|
|
69
|
+
readonly row: HTMLDivElement;
|
|
70
|
+
constructor(tabela: Tabela);
|
|
71
|
+
}
|
|
72
|
+
export type TabelaOptions = {
|
|
73
|
+
columns: TabelaColumnOptions[];
|
|
74
|
+
data: PlainObject[];
|
|
75
|
+
label: string;
|
|
76
|
+
};
|
|
77
|
+
declare class Tabela {
|
|
78
|
+
readonly element: HTMLElement;
|
|
79
|
+
readonly options: TabelaOptions;
|
|
80
|
+
readonly body: BodyComponent;
|
|
81
|
+
readonly footer: FooterComponent;
|
|
82
|
+
readonly header: HeaderComponent;
|
|
83
|
+
constructor(element: HTMLElement, options: TabelaOptions);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BodyComponent } from '../components/body.component';
|
|
2
|
+
export declare class VirtualizationManager {
|
|
3
|
+
private readonly body;
|
|
4
|
+
private active;
|
|
5
|
+
private top;
|
|
6
|
+
private readonly visible;
|
|
7
|
+
constructor(body: BodyComponent);
|
|
8
|
+
update(down: boolean): void;
|
|
9
|
+
private onScroll;
|
|
10
|
+
}
|
package/types/tabela.d.cts
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { PlainObject } from '@oscarpalmer/atoms/models';
|
|
4
4
|
|
|
5
|
+
declare class VirtualizationManager {
|
|
6
|
+
private readonly body;
|
|
7
|
+
private active;
|
|
8
|
+
private top;
|
|
9
|
+
private readonly visible;
|
|
10
|
+
constructor(body: BodyComponent);
|
|
11
|
+
update(down: boolean): void;
|
|
12
|
+
private onScroll;
|
|
13
|
+
}
|
|
5
14
|
export type TabelaColumn = {
|
|
6
15
|
field: string;
|
|
7
16
|
title: string;
|
|
@@ -34,13 +43,17 @@ declare class RowComponent {
|
|
|
34
43
|
readonly cells: CellComponent[];
|
|
35
44
|
readonly element: HTMLDivElement;
|
|
36
45
|
constructor(tabela: Tabela, data: PlainObject);
|
|
46
|
+
render(): void;
|
|
37
47
|
}
|
|
38
48
|
declare class BodyComponent {
|
|
39
49
|
readonly tabela: Tabela;
|
|
50
|
+
readonly faker: HTMLDivElement;
|
|
40
51
|
readonly group: HTMLDivElement;
|
|
41
52
|
readonly rows: RowComponent[];
|
|
53
|
+
readonly virtualization: VirtualizationManager;
|
|
42
54
|
constructor(tabela: Tabela);
|
|
43
|
-
addData(data: PlainObject[]): void
|
|
55
|
+
addData(data: PlainObject[]): Promise<void>;
|
|
56
|
+
private updateVirtualization;
|
|
44
57
|
}
|
|
45
58
|
declare class FooterComponent {
|
|
46
59
|
readonly tabela: Tabela;
|