@oscarpalmer/tabela 0.6.0 → 0.7.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.js +1 -2
- package/dist/components/column.component.js +2 -3
- package/dist/components/footer.component.js +1 -2
- package/dist/components/header.component.js +1 -2
- package/dist/components/row.component.js +7 -7
- package/dist/managers/column.manager.js +16 -15
- package/dist/managers/data.manager.js +96 -15
- package/dist/managers/row.manager.js +13 -3
- package/dist/managers/virtualization.manager.js +38 -31
- package/dist/models/tabela.model.js +0 -0
- package/dist/tabela.full.js +220 -101
- package/dist/tabela.js +36 -22
- package/package.json +3 -3
- package/src/components/body.component.ts +1 -2
- package/src/components/column.component.ts +2 -6
- package/src/components/footer.component.ts +1 -2
- package/src/components/header.component.ts +1 -2
- package/src/components/row.component.ts +10 -8
- package/src/managers/column.manager.ts +17 -20
- package/src/managers/data.manager.ts +161 -20
- package/src/managers/row.manager.ts +19 -3
- package/src/managers/virtualization.manager.ts +55 -34
- package/src/models/tabela.model.ts +31 -0
- package/src/tabela.ts +47 -40
- package/types/components/body.component.d.ts +1 -3
- package/types/components/column.component.d.ts +1 -3
- package/types/components/footer.component.d.ts +1 -3
- package/types/components/header.component.d.ts +1 -3
- package/types/components/row.component.d.ts +3 -3
- package/types/managers/column.manager.d.ts +5 -4
- package/types/managers/data.manager.d.ts +15 -6
- package/types/managers/row.manager.d.ts +6 -3
- package/types/managers/virtualization.manager.d.ts +5 -3
- package/types/models/tabela.model.d.ts +28 -0
- package/types/tabela.d.ts +4 -23
|
@@ -15,8 +15,7 @@ var BodyComponent = class {
|
|
|
15
15
|
faker: createFaker(),
|
|
16
16
|
group: void 0
|
|
17
17
|
};
|
|
18
|
-
constructor(
|
|
19
|
-
this.tabela = tabela;
|
|
18
|
+
constructor() {
|
|
20
19
|
const group = createRowGroup(false);
|
|
21
20
|
this.elements.group = group;
|
|
22
21
|
group.className += " tabela__rowgroup-body";
|
|
@@ -9,9 +9,8 @@ function createHeading(title, width) {
|
|
|
9
9
|
var ColumnComponent = class {
|
|
10
10
|
element;
|
|
11
11
|
options;
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
14
|
-
const width = Number.parseInt(getComputedStyle(tabela.element).fontSize, 10) * (options.width ?? options.title.length * 1.5);
|
|
12
|
+
constructor(options) {
|
|
13
|
+
const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (options.width ?? options.title.length * 1.5);
|
|
15
14
|
this.options = {
|
|
16
15
|
...options,
|
|
17
16
|
width
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCell, createRow } from "../helpers/dom.helpers.js";
|
|
2
|
-
function removeRow(
|
|
2
|
+
function removeRow(pool, row) {
|
|
3
3
|
if (row.element != null) {
|
|
4
4
|
row.element.innerHTML = "";
|
|
5
5
|
pool.rows.push(row.element);
|
|
@@ -8,19 +8,19 @@ function removeRow(row, pool) {
|
|
|
8
8
|
}
|
|
9
9
|
row.cells = {};
|
|
10
10
|
}
|
|
11
|
-
function renderRow(
|
|
12
|
-
const element = row.element ?? pool.rows.shift() ?? createRow();
|
|
11
|
+
function renderRow(managers, row) {
|
|
12
|
+
const element = row.element ?? managers.virtualization.pool.rows.shift() ?? createRow();
|
|
13
13
|
row.element = element;
|
|
14
14
|
element.dataset.key = String(row.key);
|
|
15
15
|
element.innerHTML = "";
|
|
16
|
-
const columns =
|
|
16
|
+
const columns = managers.column.items;
|
|
17
17
|
const { length } = columns;
|
|
18
|
-
const data =
|
|
18
|
+
const data = managers.data.values.objects.mapped.get(row.key);
|
|
19
19
|
if (data == null) return;
|
|
20
20
|
for (let index = 0; index < length; index += 1) {
|
|
21
21
|
const { options } = columns[index];
|
|
22
|
-
pool.cells[options.field] ??= [];
|
|
23
|
-
const cell = pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
|
|
22
|
+
managers.virtualization.pool.cells[options.field] ??= [];
|
|
23
|
+
const cell = managers.virtualization.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
|
|
24
24
|
cell.textContent = String(data[options.field]);
|
|
25
25
|
row.cells[options.field] = cell;
|
|
26
26
|
element.append(cell);
|
|
@@ -1,32 +1,33 @@
|
|
|
1
1
|
import { ColumnComponent } from "../components/column.component.js";
|
|
2
2
|
var ColumnManager = class {
|
|
3
|
-
|
|
4
|
-
constructor(
|
|
5
|
-
this.
|
|
3
|
+
items = [];
|
|
4
|
+
constructor(managers, components, columns) {
|
|
5
|
+
this.managers = managers;
|
|
6
|
+
this.components = components;
|
|
6
7
|
this.set(columns);
|
|
7
8
|
}
|
|
8
9
|
destroy() {
|
|
9
|
-
this.
|
|
10
|
+
this.items.length = 0;
|
|
10
11
|
}
|
|
11
12
|
remove(value) {
|
|
12
|
-
const { components,
|
|
13
|
+
const { components, items, managers } = this;
|
|
13
14
|
const fields = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string");
|
|
14
15
|
const { length } = fields;
|
|
15
16
|
if (length === 0) return;
|
|
16
17
|
for (let fieldIndex = 0; fieldIndex < length; fieldIndex += 1) {
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
18
|
+
const itemIndex = items.findIndex((component) => component.options.field === fields[fieldIndex]);
|
|
19
|
+
if (itemIndex > -1) items.splice(itemIndex, 1);
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
components.header.update(items);
|
|
22
|
+
components.footer.update(items);
|
|
23
|
+
managers.virtualization.removeCells(fields);
|
|
23
24
|
}
|
|
24
25
|
set(columns) {
|
|
25
|
-
const { components,
|
|
26
|
-
const { footer, header } =
|
|
27
|
-
|
|
28
|
-
header.update(
|
|
29
|
-
footer.update(
|
|
26
|
+
const { components, items } = this;
|
|
27
|
+
const { footer, header } = components;
|
|
28
|
+
items.splice(0, items.length, ...columns.map((column) => new ColumnComponent(column)));
|
|
29
|
+
header.update(items);
|
|
30
|
+
footer.update(items);
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
export { ColumnManager };
|
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
import { toMap } from "@oscarpalmer/atoms/array/to-map";
|
|
2
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
2
3
|
var DataManager = class {
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
handlers = Object.freeze({
|
|
5
|
+
add: (data) => void this.add(data, true),
|
|
6
|
+
clear: () => void this.clear(),
|
|
7
|
+
get: (active) => this.get(active),
|
|
8
|
+
remove: (items) => void this.remove(items, true),
|
|
9
|
+
synchronize: (data, remove) => void this.synchronize(data, remove),
|
|
10
|
+
update: (data) => void this.update(data)
|
|
11
|
+
});
|
|
12
|
+
values = {
|
|
13
|
+
keys: { original: [] },
|
|
14
|
+
objects: {
|
|
15
|
+
mapped: /* @__PURE__ */ new Map(),
|
|
16
|
+
array: []
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
get size() {
|
|
5
20
|
return this.values.keys.active?.length ?? this.values.keys.original.length;
|
|
6
21
|
}
|
|
7
|
-
constructor(
|
|
8
|
-
this.
|
|
9
|
-
|
|
10
|
-
this.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
constructor(managers, components, field) {
|
|
23
|
+
this.managers = managers;
|
|
24
|
+
this.components = components;
|
|
25
|
+
this.field = field;
|
|
26
|
+
}
|
|
27
|
+
async add(data, render) {
|
|
28
|
+
const { field, values } = this;
|
|
29
|
+
values.objects.array.push(...data);
|
|
30
|
+
values.objects.mapped = toMap(values.objects.array, field);
|
|
31
|
+
values.keys.original = [...values.objects.mapped.keys()];
|
|
32
|
+
if (render) this.managers.virtualization.update(true);
|
|
33
|
+
}
|
|
34
|
+
clear() {
|
|
35
|
+
if (this.values.objects.array.length > 0) this.set([]);
|
|
17
36
|
}
|
|
18
37
|
destroy() {
|
|
19
38
|
const { values } = this;
|
|
@@ -22,9 +41,71 @@ var DataManager = class {
|
|
|
22
41
|
values.keys.original.length = 0;
|
|
23
42
|
values.objects.array.length = 0;
|
|
24
43
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
get(active) {
|
|
45
|
+
const { values } = this;
|
|
46
|
+
return active ?? false ? values.keys.active?.map((key) => values.objects.mapped.get(key)) ?? [] : values.objects.array;
|
|
47
|
+
}
|
|
48
|
+
async remove(items, render) {
|
|
49
|
+
const { field, managers, values } = this;
|
|
50
|
+
const keys = items.map((value) => isPlainObject(value) ? value[field] : value).filter((key) => values.objects.mapped.has(key));
|
|
51
|
+
const { length } = keys;
|
|
52
|
+
if (length === 0) return;
|
|
53
|
+
for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
|
|
54
|
+
const key = keys[keyIndex];
|
|
55
|
+
values.objects.mapped.delete(key);
|
|
56
|
+
const arrayIndex = values.objects.array.findIndex((object) => object[field] === key);
|
|
57
|
+
if (arrayIndex > -1) values.objects.array.splice(arrayIndex, 1);
|
|
58
|
+
values.keys.original.splice(values.keys.original.indexOf(key), 1);
|
|
59
|
+
managers.row.remove(key);
|
|
60
|
+
}
|
|
61
|
+
if (render) this.managers.virtualization.update(true);
|
|
62
|
+
}
|
|
63
|
+
set(data) {
|
|
64
|
+
const { field, values } = this;
|
|
65
|
+
const mapped = toMap(data, field);
|
|
66
|
+
values.keys.active = void 0;
|
|
67
|
+
values.keys.original = [...mapped.keys()];
|
|
68
|
+
values.objects.mapped = mapped;
|
|
69
|
+
values.objects.array = data;
|
|
70
|
+
this.managers.virtualization.update(true);
|
|
71
|
+
}
|
|
72
|
+
async synchronize(data, remove) {
|
|
73
|
+
const { field, values } = this;
|
|
74
|
+
const add = [];
|
|
75
|
+
const updated = [];
|
|
76
|
+
const keys = /* @__PURE__ */ new Set([]);
|
|
77
|
+
const { length } = data;
|
|
78
|
+
for (let index = 0; index < length; index += 1) {
|
|
79
|
+
const object = data[index];
|
|
80
|
+
const key = object[field];
|
|
81
|
+
if (values.objects.mapped.has(key)) updated.push(object);
|
|
82
|
+
else add.push(object);
|
|
83
|
+
keys.add(key);
|
|
84
|
+
}
|
|
85
|
+
if (keys.size === 0) return;
|
|
86
|
+
if (remove ?? false) {
|
|
87
|
+
const toRemove = values.keys.original.filter((key) => !keys.has(key));
|
|
88
|
+
if (toRemove.length > 0) await this.remove(toRemove, false);
|
|
89
|
+
}
|
|
90
|
+
await this.update(updated);
|
|
91
|
+
if (add.length > 0) await this.add(add, false);
|
|
92
|
+
if (add.length > 0 || (remove ?? false)) this.managers.virtualization.update(true);
|
|
93
|
+
}
|
|
94
|
+
async update(data) {
|
|
95
|
+
const { field, managers, values } = this;
|
|
96
|
+
const { length } = data;
|
|
97
|
+
for (let index = 0; index < length; index += 1) {
|
|
98
|
+
const object = data[index];
|
|
99
|
+
const key = object[field];
|
|
100
|
+
const value = values.objects.mapped.get(key);
|
|
101
|
+
if (value != null) {
|
|
102
|
+
values.objects.mapped.set(key, {
|
|
103
|
+
...value,
|
|
104
|
+
...object
|
|
105
|
+
});
|
|
106
|
+
managers.row.update(key);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
28
109
|
}
|
|
29
110
|
};
|
|
30
111
|
export { DataManager };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RowComponent } from "../components/row.component.js";
|
|
1
|
+
import { RowComponent, renderRow } from "../components/row.component.js";
|
|
2
2
|
var RowManager = class {
|
|
3
3
|
components = /* @__PURE__ */ new Map();
|
|
4
4
|
height;
|
|
5
|
-
constructor(
|
|
6
|
-
this.
|
|
5
|
+
constructor(managers, rowHeight) {
|
|
6
|
+
this.managers = managers;
|
|
7
7
|
this.height = rowHeight;
|
|
8
8
|
}
|
|
9
9
|
destroy() {
|
|
@@ -17,5 +17,15 @@ var RowManager = class {
|
|
|
17
17
|
}
|
|
18
18
|
return row;
|
|
19
19
|
}
|
|
20
|
+
has(key) {
|
|
21
|
+
return this.components.has(key);
|
|
22
|
+
}
|
|
23
|
+
remove(key) {
|
|
24
|
+
this.components.delete(key);
|
|
25
|
+
}
|
|
26
|
+
update(key) {
|
|
27
|
+
const row = this.components.get(key);
|
|
28
|
+
if (row != null) renderRow(this.managers, row);
|
|
29
|
+
}
|
|
20
30
|
};
|
|
21
31
|
export { RowManager };
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import { removeRow, renderRow } from "../components/row.component.js";
|
|
2
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
3
|
-
function getRange(
|
|
4
|
-
const { components, managers } =
|
|
5
|
-
const {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const before = Math.ceil(clientHeight / rows.height) * (down ? 1 : 2);
|
|
11
|
-
const after = Math.ceil(clientHeight / rows.height) * (down ? 2 : 1);
|
|
3
|
+
function getRange(down) {
|
|
4
|
+
const { components, managers } = this;
|
|
5
|
+
const { clientHeight, scrollTop } = components.body.elements.group;
|
|
6
|
+
const first = Math.floor(scrollTop / managers.row.height);
|
|
7
|
+
const last = Math.min(managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length - 1, Math.ceil((scrollTop + clientHeight) / managers.row.height) - 1);
|
|
8
|
+
const before = Math.ceil(clientHeight / managers.row.height) * (down ? 1 : 2);
|
|
9
|
+
const after = Math.ceil(clientHeight / managers.row.height) * (down ? 2 : 1);
|
|
12
10
|
const start = Math.max(0, first - before);
|
|
13
11
|
return {
|
|
14
|
-
end: Math.min(data.length - 1, last + after),
|
|
12
|
+
end: Math.min(managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length - 1, last + after),
|
|
15
13
|
start
|
|
16
14
|
};
|
|
17
15
|
}
|
|
18
16
|
function onScroll() {
|
|
19
17
|
if (!this.state.active) {
|
|
20
18
|
requestAnimationFrame(() => {
|
|
21
|
-
const top = this.
|
|
19
|
+
const top = this.components.body.elements.group.scrollTop;
|
|
22
20
|
this.update(top > this.state.top);
|
|
23
21
|
this.state.active = false;
|
|
24
22
|
this.state.top = top;
|
|
@@ -38,14 +36,15 @@ var VirtualizationManager = class {
|
|
|
38
36
|
top: 0
|
|
39
37
|
};
|
|
40
38
|
visible = /* @__PURE__ */ new Map();
|
|
41
|
-
constructor(
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
39
|
+
constructor(managers, components) {
|
|
40
|
+
this.managers = managers;
|
|
41
|
+
this.components = components;
|
|
42
|
+
this.listener = on(components.body.elements.group, "scroll", onScroll.bind(this));
|
|
44
43
|
}
|
|
45
44
|
destroy() {
|
|
46
45
|
this.listener();
|
|
47
46
|
for (const [index, row] of this.visible) {
|
|
48
|
-
removeRow(
|
|
47
|
+
removeRow(this.pool, row);
|
|
49
48
|
this.visible.delete(index);
|
|
50
49
|
}
|
|
51
50
|
this.pool.cells = {};
|
|
@@ -60,33 +59,41 @@ var VirtualizationManager = class {
|
|
|
60
59
|
delete row.cells[fields[index]];
|
|
61
60
|
}
|
|
62
61
|
}
|
|
62
|
+
getFragment() {
|
|
63
|
+
this.fragment ??= document.createDocumentFragment();
|
|
64
|
+
this.fragment.replaceChildren();
|
|
65
|
+
return this.fragment;
|
|
66
|
+
}
|
|
63
67
|
update(down) {
|
|
64
|
-
const {
|
|
65
|
-
|
|
68
|
+
const { components, managers, pool, visible } = this;
|
|
69
|
+
components.body.elements.faker.style.height = `${managers.data.size * managers.row.height}px`;
|
|
66
70
|
const indices = /* @__PURE__ */ new Set();
|
|
67
|
-
const range = getRange(
|
|
71
|
+
const range = getRange.call(this, down);
|
|
68
72
|
for (let index = range.start; index <= range.end; index += 1) indices.add(index);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
let remove = false;
|
|
74
|
+
for (const [index, row] of visible) {
|
|
75
|
+
if (!managers.row.has(row.key) || !indices.has(index)) remove = true;
|
|
76
|
+
if (remove) {
|
|
77
|
+
visible.delete(index);
|
|
78
|
+
removeRow(pool, row);
|
|
79
|
+
}
|
|
72
80
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const keys = tabela.managers.data.values.keys.active ?? tabela.managers.data.values.keys.original;
|
|
81
|
+
const fragment = this.getFragment();
|
|
82
|
+
const keys = managers.data.values.keys.active ?? managers.data.values.keys.original;
|
|
76
83
|
let count = 0;
|
|
77
84
|
for (let index = range.start; index <= range.end; index += 1) {
|
|
78
|
-
if (
|
|
79
|
-
const row =
|
|
85
|
+
if (visible.has(index)) continue;
|
|
86
|
+
const row = managers.row.get(keys[index]);
|
|
80
87
|
if (row == null) continue;
|
|
81
88
|
count += 1;
|
|
82
|
-
renderRow(
|
|
83
|
-
|
|
89
|
+
renderRow(managers, row);
|
|
90
|
+
visible.set(index, row);
|
|
84
91
|
if (row.element != null) {
|
|
85
|
-
row.element.style.transform = `translateY(${index *
|
|
86
|
-
|
|
92
|
+
row.element.style.transform = `translateY(${index * managers.row.height}px)`;
|
|
93
|
+
fragment.append(row.element);
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
|
-
if (count > 0)
|
|
96
|
+
if (count > 0) components.body.elements.group[down ? "append" : "prepend"](fragment);
|
|
90
97
|
}
|
|
91
98
|
};
|
|
92
99
|
export { VirtualizationManager };
|
|
File without changes
|