@oscarpalmer/tabela 0.9.0 → 0.11.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 +3 -15
- package/dist/components/footer.component.js +3 -3
- package/dist/components/header.component.js +2 -2
- package/dist/components/row.component.js +19 -7
- package/dist/helpers/dom.helpers.js +5 -10
- package/dist/helpers/misc.helpers.js +7 -0
- package/dist/helpers/style.helper.js +6 -0
- package/dist/managers/column.manager.js +10 -9
- package/dist/managers/data.manager.js +26 -22
- package/dist/managers/event.manager.js +39 -19
- package/dist/managers/filter.manager.js +11 -10
- package/dist/managers/navigation.manager.js +73 -0
- package/dist/managers/render.manager.js +110 -0
- package/dist/managers/row.manager.js +7 -7
- package/dist/managers/selection.manager.js +189 -0
- package/dist/managers/sort.manager.js +9 -8
- package/dist/tabela.full.js +1096 -433
- package/dist/tabela.js +34 -11
- package/package.json +1 -1
- package/src/components/body.component.ts +5 -20
- package/src/components/footer.component.ts +3 -3
- package/src/components/header.component.ts +2 -2
- package/src/components/row.component.ts +30 -10
- package/src/helpers/dom.helpers.ts +3 -10
- package/src/helpers/misc.helpers.ts +15 -0
- package/src/helpers/style.helper.ts +6 -0
- package/src/managers/column.manager.ts +12 -14
- package/src/managers/data.manager.ts +31 -27
- package/src/managers/event.manager.ts +67 -37
- package/src/managers/filter.manager.ts +12 -11
- package/src/managers/navigation.manager.ts +145 -0
- package/src/managers/render.manager.ts +184 -0
- package/src/managers/row.manager.ts +9 -14
- package/src/managers/selection.manager.ts +332 -0
- package/src/managers/sort.manager.ts +14 -14
- package/src/models/render.model.ts +16 -0
- package/src/models/tabela.model.ts +23 -2
- package/src/tabela.ts +42 -10
- package/types/components/row.component.d.ts +4 -4
- package/types/helpers/dom.helpers.d.ts +1 -1
- package/types/helpers/misc.helpers.d.ts +2 -0
- package/types/helpers/style.helper.d.ts +1 -0
- package/types/managers/column.manager.d.ts +4 -5
- package/types/managers/data.manager.d.ts +5 -6
- package/types/managers/event.manager.d.ts +3 -6
- package/types/managers/filter.manager.d.ts +3 -3
- package/types/managers/navigation.manager.d.ts +10 -0
- package/types/managers/render.manager.d.ts +16 -0
- package/types/managers/row.manager.d.ts +4 -5
- package/types/managers/selection.manager.d.ts +18 -0
- package/types/managers/sort.manager.d.ts +4 -4
- package/types/models/render.model.d.ts +13 -0
- package/types/models/tabela.model.d.ts +21 -2
- package/types/tabela.d.ts +2 -1
- package/dist/managers/virtualization.manager.js +0 -101
- package/src/managers/virtualization.manager.ts +0 -176
- package/src/models/virtualization.model.ts +0 -14
- package/types/managers/virtualization.manager.d.ts +0 -18
- package/types/models/virtualization.model.d.ts +0 -12
- /package/dist/models/{virtualization.model.js → render.model.js} +0 -0
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { createElement, createRowGroup } from "../helpers/dom.helpers.js";
|
|
2
|
-
import { setStyles } from "@oscarpalmer/toretto/style";
|
|
3
2
|
function createFaker() {
|
|
4
|
-
return createElement("div", {}, {}, {
|
|
5
|
-
height: "0",
|
|
6
|
-
inset: "0 auto auto 0",
|
|
7
|
-
opacity: "0",
|
|
8
|
-
pointerEvents: "none",
|
|
9
|
-
position: "absolute",
|
|
10
|
-
width: "1px"
|
|
11
|
-
});
|
|
3
|
+
return createElement("div", { className: "tabela__faker" }, {}, {});
|
|
12
4
|
}
|
|
13
5
|
var BodyComponent = class {
|
|
14
6
|
elements = {
|
|
@@ -18,13 +10,9 @@ var BodyComponent = class {
|
|
|
18
10
|
constructor() {
|
|
19
11
|
const group = createRowGroup(false);
|
|
20
12
|
this.elements.group = group;
|
|
21
|
-
group.className += " tabela__rowgroup
|
|
13
|
+
group.className += " tabela__rowgroup--body";
|
|
22
14
|
group.tabIndex = 0;
|
|
23
|
-
|
|
24
|
-
height: "100%",
|
|
25
|
-
overflow: "auto",
|
|
26
|
-
position: "relative"
|
|
27
|
-
});
|
|
15
|
+
group.setAttribute("data-event", "body");
|
|
28
16
|
group.append(this.elements.faker);
|
|
29
17
|
}
|
|
30
18
|
destroy() {
|
|
@@ -8,8 +8,8 @@ var FooterComponent = class {
|
|
|
8
8
|
row,
|
|
9
9
|
cells: []
|
|
10
10
|
};
|
|
11
|
-
group.className += " tabela__rowgroup
|
|
12
|
-
row.className += " tabela__row
|
|
11
|
+
group.className += " tabela__rowgroup--footer";
|
|
12
|
+
row.className += " tabela__row--footer";
|
|
13
13
|
}
|
|
14
14
|
destroy() {
|
|
15
15
|
this.elements.cells.length = 0;
|
|
@@ -23,7 +23,7 @@ var FooterComponent = class {
|
|
|
23
23
|
elements.row.innerHTML = "";
|
|
24
24
|
for (let index = 0; index < length; index += 1) {
|
|
25
25
|
const cell = createCell(columns[index].options.width ?? 4, false);
|
|
26
|
-
cell.className += " tabela__cell
|
|
26
|
+
cell.className += " tabela__cell--footer";
|
|
27
27
|
cell.innerHTML = " ";
|
|
28
28
|
elements.cells.push(cell);
|
|
29
29
|
elements.row.append(cell);
|
|
@@ -7,8 +7,8 @@ var HeaderComponent = class {
|
|
|
7
7
|
group,
|
|
8
8
|
row
|
|
9
9
|
};
|
|
10
|
-
group.className += " tabela__rowgroup
|
|
11
|
-
row.className += " tabela__row
|
|
10
|
+
group.className += " tabela__rowgroup--header";
|
|
11
|
+
row.className += " tabela__row--header";
|
|
12
12
|
}
|
|
13
13
|
destroy() {
|
|
14
14
|
this.elements.group = void 0;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createCell, createRow } from "../helpers/dom.helpers.js";
|
|
2
|
+
import { setAttributes } from "@oscarpalmer/toretto/attribute";
|
|
2
3
|
function removeRow(pool, row) {
|
|
3
4
|
if (row.element != null) {
|
|
4
5
|
row.element.innerHTML = "";
|
|
@@ -8,19 +9,30 @@ function removeRow(pool, row) {
|
|
|
8
9
|
}
|
|
9
10
|
row.cells = {};
|
|
10
11
|
}
|
|
11
|
-
function renderRow(
|
|
12
|
-
const element = row.element ?? managers.
|
|
12
|
+
function renderRow(state, row) {
|
|
13
|
+
const element = row.element ?? state.managers.render.pool.rows.shift() ?? createRow();
|
|
13
14
|
row.element = element;
|
|
14
|
-
element.dataset.key = String(row.key);
|
|
15
15
|
element.innerHTML = "";
|
|
16
|
-
const
|
|
16
|
+
const selected = state.managers.selection.items.has(row.key);
|
|
17
|
+
const key = String(row.key);
|
|
18
|
+
setAttributes(element, {
|
|
19
|
+
"aria-selected": String(selected),
|
|
20
|
+
"data-active": String(state.managers.navigation.active === row.key),
|
|
21
|
+
"data-event": "row",
|
|
22
|
+
"data-key": key,
|
|
23
|
+
id: `tabela_${state.id}_row_${key}`
|
|
24
|
+
});
|
|
25
|
+
element.classList.add("tabela__row--body");
|
|
26
|
+
if (selected) element.classList.add("tabela__row--selected");
|
|
27
|
+
else element.classList.remove("tabela__row--selected");
|
|
28
|
+
const columns = state.managers.column.items;
|
|
17
29
|
const { length } = columns;
|
|
18
|
-
const data = managers.data.values.objects.mapped.get(row.key);
|
|
30
|
+
const data = state.managers.data.values.objects.mapped.get(row.key);
|
|
19
31
|
if (data == null) return;
|
|
20
32
|
for (let index = 0; index < length; index += 1) {
|
|
21
33
|
const { options } = columns[index];
|
|
22
|
-
managers.
|
|
23
|
-
const cell = managers.
|
|
34
|
+
state.managers.render.pool.cells[options.field] ??= [];
|
|
35
|
+
const cell = state.managers.render.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
|
|
24
36
|
cell.textContent = String(data[options.field]);
|
|
25
37
|
row.cells[options.field] = cell;
|
|
26
38
|
element.append(cell);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { setStyles } from "@oscarpalmer/toretto/style";
|
|
2
1
|
import { setAttributes } from "@oscarpalmer/toretto/attribute";
|
|
2
|
+
import { setStyles } from "@oscarpalmer/toretto/style";
|
|
3
3
|
function createCell(width, body) {
|
|
4
4
|
const cell = createElement("div", {
|
|
5
5
|
className: "tabela__cell",
|
|
6
6
|
role: "cell"
|
|
7
7
|
}, {}, { width: `${width}px` });
|
|
8
|
-
if (body ?? true) cell.classList.add("tabela__cell
|
|
8
|
+
if (body ?? true) cell.classList.add("tabela__cell--body");
|
|
9
9
|
return cell;
|
|
10
10
|
}
|
|
11
11
|
function createElement(tagName, properties, attributes, style) {
|
|
@@ -22,22 +22,17 @@ function createRowGroup(withRow) {
|
|
|
22
22
|
role: "rowgroup"
|
|
23
23
|
}, {}, {});
|
|
24
24
|
if (!(withRow ?? true)) return group;
|
|
25
|
-
const row = createRow(
|
|
25
|
+
const row = createRow();
|
|
26
26
|
group.append(row);
|
|
27
27
|
return {
|
|
28
28
|
group,
|
|
29
29
|
row
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
function createRow(
|
|
33
|
-
|
|
32
|
+
function createRow() {
|
|
33
|
+
return createElement("div", {
|
|
34
34
|
className: "tabela__row",
|
|
35
35
|
role: "row"
|
|
36
36
|
}, {}, {});
|
|
37
|
-
if (withStyle ?? true) setStyles(row, {
|
|
38
|
-
inset: "0 auto auto 0",
|
|
39
|
-
position: "absolute"
|
|
40
|
-
});
|
|
41
|
-
return row;
|
|
42
37
|
}
|
|
43
38
|
export { createCell, createElement, createRow, createRowGroup };
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { ColumnComponent } from "../components/column.component.js";
|
|
2
2
|
var ColumnManager = class {
|
|
3
3
|
items = [];
|
|
4
|
-
constructor(
|
|
5
|
-
this.
|
|
6
|
-
this.
|
|
7
|
-
this.set(columns);
|
|
4
|
+
constructor(state) {
|
|
5
|
+
this.state = state;
|
|
6
|
+
this.set(state.options.columns);
|
|
8
7
|
}
|
|
9
8
|
destroy() {
|
|
10
9
|
const { length } = this.items;
|
|
11
10
|
for (let index = 0; index < length; index += 1) this.items[index].destroy();
|
|
12
|
-
this.items
|
|
11
|
+
this.items = void 0;
|
|
12
|
+
this.state = void 0;
|
|
13
13
|
}
|
|
14
14
|
remove(value) {
|
|
15
|
-
const {
|
|
15
|
+
const { items, state } = this;
|
|
16
|
+
const { components, managers } = state;
|
|
16
17
|
const fields = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string");
|
|
17
18
|
const { length } = fields;
|
|
18
19
|
if (length === 0) return;
|
|
@@ -25,11 +26,11 @@ var ColumnManager = class {
|
|
|
25
26
|
}
|
|
26
27
|
components.header.update(items);
|
|
27
28
|
components.footer.update(items);
|
|
28
|
-
managers.
|
|
29
|
+
managers.render.removeCells(fields);
|
|
29
30
|
}
|
|
30
31
|
set(columns) {
|
|
31
|
-
const {
|
|
32
|
-
const { footer, header } = components;
|
|
32
|
+
const { items, state } = this;
|
|
33
|
+
const { footer, header } = state.components;
|
|
33
34
|
items.splice(0, items.length, ...columns.map((column) => new ColumnComponent(column)));
|
|
34
35
|
header.update(items);
|
|
35
36
|
footer.update(items);
|
|
@@ -20,15 +20,13 @@ var DataManager = class {
|
|
|
20
20
|
get size() {
|
|
21
21
|
return this.values.keys.active?.length ?? this.values.keys.original.length;
|
|
22
22
|
}
|
|
23
|
-
constructor(
|
|
24
|
-
this.
|
|
25
|
-
this.components = components;
|
|
26
|
-
this.field = field;
|
|
23
|
+
constructor(state) {
|
|
24
|
+
this.state = state;
|
|
27
25
|
}
|
|
28
26
|
async add(data, render) {
|
|
29
|
-
const {
|
|
27
|
+
const { state, values } = this;
|
|
30
28
|
push(values.objects.array, data);
|
|
31
|
-
values.objects.mapped = toMap(values.objects.array,
|
|
29
|
+
values.objects.mapped = toMap(values.objects.array, state.key);
|
|
32
30
|
if (render) this.render();
|
|
33
31
|
}
|
|
34
32
|
clear() {
|
|
@@ -41,48 +39,54 @@ var DataManager = class {
|
|
|
41
39
|
values.keys.original.length = 0;
|
|
42
40
|
values.objects.array.length = 0;
|
|
43
41
|
this.handlers = void 0;
|
|
42
|
+
this.state = void 0;
|
|
43
|
+
this.values = void 0;
|
|
44
44
|
}
|
|
45
45
|
get(active) {
|
|
46
46
|
const { values } = this;
|
|
47
47
|
return active ?? false ? values.keys.active?.map((key) => values.objects.mapped.get(key)) ?? [] : values.objects.array;
|
|
48
48
|
}
|
|
49
|
+
getIndex(key) {
|
|
50
|
+
const { values } = this;
|
|
51
|
+
return (values.keys.active ?? values.keys.original).indexOf(key);
|
|
52
|
+
}
|
|
49
53
|
async remove(items, render) {
|
|
50
|
-
const {
|
|
51
|
-
const keys = items.map((value) => isPlainObject(value) ? value[
|
|
54
|
+
const { state, values } = this;
|
|
55
|
+
const keys = items.map((value) => isPlainObject(value) ? value[state.key] : value).filter((key) => values.objects.mapped.has(key));
|
|
52
56
|
const { length } = keys;
|
|
53
57
|
if (length === 0) return;
|
|
54
58
|
for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
|
|
55
59
|
const key = keys[keyIndex];
|
|
56
60
|
values.objects.mapped.delete(key);
|
|
57
|
-
const arrayIndex = values.objects.array.findIndex((object) => object[
|
|
61
|
+
const arrayIndex = values.objects.array.findIndex((object) => object[state.key] === key);
|
|
58
62
|
if (arrayIndex > -1) values.objects.array.splice(arrayIndex, 1);
|
|
59
63
|
values.keys.original.splice(values.keys.original.indexOf(key), 1);
|
|
60
|
-
managers.row.remove(key);
|
|
64
|
+
state.managers.row.remove(key);
|
|
61
65
|
}
|
|
62
66
|
if (render) this.render();
|
|
63
67
|
}
|
|
64
68
|
render() {
|
|
65
|
-
const {
|
|
66
|
-
values.keys.original = sort(values.objects.array.map((item) => item[
|
|
67
|
-
if (Object.keys(managers.filter.items).length > 0) managers.filter.filter();
|
|
68
|
-
else if (managers.sort.items.length > 0) managers.sort.sort();
|
|
69
|
-
else managers.
|
|
69
|
+
const { state, values } = this;
|
|
70
|
+
values.keys.original = sort(values.objects.array.map((item) => item[state.key]));
|
|
71
|
+
if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
|
|
72
|
+
else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
|
|
73
|
+
else state.managers.render.update(true);
|
|
70
74
|
}
|
|
71
75
|
set(data) {
|
|
72
|
-
const {
|
|
73
|
-
values.objects.mapped = toMap(data,
|
|
76
|
+
const { state, values } = this;
|
|
77
|
+
values.objects.mapped = toMap(data, state.key);
|
|
74
78
|
values.objects.array = data;
|
|
75
79
|
this.render();
|
|
76
80
|
}
|
|
77
81
|
async synchronize(data, remove) {
|
|
78
|
-
const {
|
|
82
|
+
const { state, values } = this;
|
|
79
83
|
const add = [];
|
|
80
84
|
const updated = [];
|
|
81
85
|
const keys = /* @__PURE__ */ new Set([]);
|
|
82
86
|
const { length } = data;
|
|
83
87
|
for (let index = 0; index < length; index += 1) {
|
|
84
88
|
const object = data[index];
|
|
85
|
-
const key = object[
|
|
89
|
+
const key = object[state.key];
|
|
86
90
|
if (values.objects.mapped.has(key)) updated.push(object);
|
|
87
91
|
else add.push(object);
|
|
88
92
|
keys.add(key);
|
|
@@ -97,18 +101,18 @@ var DataManager = class {
|
|
|
97
101
|
if (add.length > 0 || (remove ?? false)) this.render();
|
|
98
102
|
}
|
|
99
103
|
async update(data) {
|
|
100
|
-
const {
|
|
104
|
+
const { state, values } = this;
|
|
101
105
|
const { length } = data;
|
|
102
106
|
for (let index = 0; index < length; index += 1) {
|
|
103
107
|
const object = data[index];
|
|
104
|
-
const key = object[
|
|
108
|
+
const key = object[state.key];
|
|
105
109
|
const value = values.objects.mapped.get(key);
|
|
106
110
|
if (value != null) {
|
|
107
111
|
values.objects.mapped.set(key, {
|
|
108
112
|
...value,
|
|
109
113
|
...object
|
|
110
114
|
});
|
|
111
|
-
managers.row.update(key);
|
|
115
|
+
state.managers.row.update(key);
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
}
|
|
@@ -1,30 +1,50 @@
|
|
|
1
1
|
import { on } from "@oscarpalmer/toretto/event";
|
|
2
|
-
import { findAncestor } from "@oscarpalmer/toretto";
|
|
2
|
+
import { findAncestor } from "@oscarpalmer/toretto/find";
|
|
3
3
|
var EventManager = class {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
this.listener = on(element, "click", (event) => {
|
|
8
|
-
this.onClick(event);
|
|
9
|
-
}, { passive: false });
|
|
4
|
+
constructor(state) {
|
|
5
|
+
this.state = state;
|
|
6
|
+
mapped.set(state.element, this);
|
|
10
7
|
}
|
|
11
8
|
destroy() {
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
onClick(event) {
|
|
15
|
-
const target = findAncestor(event, "[data-event]");
|
|
16
|
-
if (!(target instanceof HTMLElement)) return;
|
|
17
|
-
switch (target?.getAttribute("data-event")) {
|
|
18
|
-
case "heading":
|
|
19
|
-
this.onSort(event, target);
|
|
20
|
-
break;
|
|
21
|
-
}
|
|
9
|
+
mapped.delete(this.state.element);
|
|
10
|
+
this.state = void 0;
|
|
22
11
|
}
|
|
23
12
|
onSort(event, target) {
|
|
24
|
-
const { managers } = this;
|
|
25
13
|
const direction = target.getAttribute("data-sort-direction");
|
|
26
14
|
const field = target.getAttribute("data-field");
|
|
27
|
-
if (field != null) managers.sort.toggle(event, field, direction);
|
|
15
|
+
if (field != null) this.state.managers.sort.toggle(event, field, direction);
|
|
28
16
|
}
|
|
29
17
|
};
|
|
18
|
+
function onClick(event) {
|
|
19
|
+
const target = findAncestor(event, "[data-event]");
|
|
20
|
+
const table = findAncestor(event, ".tabela");
|
|
21
|
+
if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
|
|
22
|
+
const manager = mapped.get(table);
|
|
23
|
+
if (manager == null) return;
|
|
24
|
+
switch (target?.getAttribute("data-event")) {
|
|
25
|
+
case "heading":
|
|
26
|
+
manager.onSort(event, target);
|
|
27
|
+
break;
|
|
28
|
+
case "row":
|
|
29
|
+
manager.state.managers.selection.handle(event, target);
|
|
30
|
+
break;
|
|
31
|
+
default: break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function onKeydown(event) {
|
|
35
|
+
const target = findAncestor(event, "[data-event]");
|
|
36
|
+
const table = findAncestor(event, ".tabela");
|
|
37
|
+
if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
|
|
38
|
+
const manager = mapped.get(table);
|
|
39
|
+
if (manager == null) return;
|
|
40
|
+
switch (target?.getAttribute("data-event")) {
|
|
41
|
+
case "body":
|
|
42
|
+
manager.state.managers.navigation.handle(event);
|
|
43
|
+
break;
|
|
44
|
+
default: break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
var mapped = /* @__PURE__ */ new WeakMap();
|
|
48
|
+
on(document, "click", onClick);
|
|
49
|
+
on(document, "keydown", onKeydown, { passive: false });
|
|
30
50
|
export { EventManager };
|
|
@@ -10,8 +10,8 @@ var FilterManager = class {
|
|
|
10
10
|
set: (items) => this.set(items)
|
|
11
11
|
});
|
|
12
12
|
items = {};
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
13
|
+
constructor(state) {
|
|
14
|
+
this.state = state;
|
|
15
15
|
}
|
|
16
16
|
add(item) {
|
|
17
17
|
if (this.items[item.field] == null) this.items[item.field] = [];
|
|
@@ -27,16 +27,17 @@ var FilterManager = class {
|
|
|
27
27
|
}
|
|
28
28
|
destroy() {
|
|
29
29
|
this.handlers = void 0;
|
|
30
|
-
this.items =
|
|
30
|
+
this.items = void 0;
|
|
31
|
+
this.state = void 0;
|
|
31
32
|
}
|
|
32
33
|
filter() {
|
|
33
|
-
const {
|
|
34
|
+
const { state } = this;
|
|
34
35
|
const filtered = [];
|
|
35
36
|
const filters = Object.entries(this.items);
|
|
36
|
-
const keysLength = managers.data.values.keys.original.length;
|
|
37
|
+
const keysLength = state.managers.data.values.keys.original.length;
|
|
37
38
|
rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
38
|
-
const key = managers.data.values.keys.original[keyIndex];
|
|
39
|
-
const row = managers.data.values.objects.mapped.get(key);
|
|
39
|
+
const key = state.managers.data.values.keys.original[keyIndex];
|
|
40
|
+
const row = state.managers.data.values.objects.mapped.get(key);
|
|
40
41
|
if (row == null) continue;
|
|
41
42
|
filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
|
|
42
43
|
const [field, items] = filters[filterIndex];
|
|
@@ -49,9 +50,9 @@ var FilterManager = class {
|
|
|
49
50
|
}
|
|
50
51
|
filtered.push(key);
|
|
51
52
|
}
|
|
52
|
-
managers.data.values.keys.active = filtered;
|
|
53
|
-
if (managers.sort.items.length > 0) managers.sort.sort();
|
|
54
|
-
else managers.
|
|
53
|
+
state.managers.data.values.keys.active = filtered;
|
|
54
|
+
if (state.managers.sort.items.length > 0) state.managers.sort.sort();
|
|
55
|
+
else state.managers.render.update(true, true);
|
|
55
56
|
}
|
|
56
57
|
remove(value) {
|
|
57
58
|
if (typeof value === "string") {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getKey } from "../helpers/misc.helpers.js";
|
|
2
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
3
|
+
import { clamp } from "@oscarpalmer/atoms/number";
|
|
4
|
+
var NavigationManager = class {
|
|
5
|
+
active;
|
|
6
|
+
constructor(state) {
|
|
7
|
+
this.state = state;
|
|
8
|
+
}
|
|
9
|
+
destroy() {
|
|
10
|
+
this.state = void 0;
|
|
11
|
+
}
|
|
12
|
+
handle(event) {
|
|
13
|
+
if (!allKeys.has(event.key)) return;
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
const { components, id, managers } = this.state;
|
|
16
|
+
const activeDescendant = components.body.elements.group.getAttribute("aria-activedescendant");
|
|
17
|
+
const keys = managers.data.values.keys.active ?? managers.data.values.keys.original;
|
|
18
|
+
const { length } = keys;
|
|
19
|
+
let next;
|
|
20
|
+
if (isNullableOrWhitespace(activeDescendant)) next = getDefaultIndex(event.key, length);
|
|
21
|
+
else next = getIndex(event, activeDescendant, id, keys);
|
|
22
|
+
if (next != null) this.setActive(keys.at(next));
|
|
23
|
+
}
|
|
24
|
+
setActive(key, scroll) {
|
|
25
|
+
const { components, managers, options } = this.state;
|
|
26
|
+
this.active = key;
|
|
27
|
+
const active = components.body.elements.group.querySelectorAll("[data-active=\"true\"]");
|
|
28
|
+
for (const item of active) item.setAttribute("data-active", "false");
|
|
29
|
+
const row = managers.row.get(key);
|
|
30
|
+
if (row != null) {
|
|
31
|
+
row.element?.setAttribute("data-active", "true");
|
|
32
|
+
if (scroll ?? true) if (row.element == null) components.body.elements.group.scrollTo({
|
|
33
|
+
top: managers.data.getIndex(key) * options.rowHeight,
|
|
34
|
+
behavior: "smooth"
|
|
35
|
+
});
|
|
36
|
+
else row.element.scrollIntoView({ block: "nearest" });
|
|
37
|
+
}
|
|
38
|
+
components.body.elements.group.setAttribute("aria-activedescendant", row == null ? "" : `tabela_${this.state.id}_row_${key}`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function getDefaultIndex(key, max) {
|
|
42
|
+
switch (true) {
|
|
43
|
+
case negativeDefaultKeys.has(key): return -1;
|
|
44
|
+
case key === "PageDown": return Math.min(9, max - 1);
|
|
45
|
+
case key === "PageUp": return max < 10 ? 0 : max - 10;
|
|
46
|
+
default: return 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function getIndex(event, active, id, keys) {
|
|
50
|
+
const key = getKey(active.replace(`tabela_${id}_row_`, ""));
|
|
51
|
+
if (key == null) return;
|
|
52
|
+
if (absoluteKeys.has(event.key)) return event.key === "Home" ? 0 : keys.length - 1;
|
|
53
|
+
return clamp(keys.indexOf(key) + getOffset(event.key), 0, keys.length - 1, true);
|
|
54
|
+
}
|
|
55
|
+
function getOffset(key) {
|
|
56
|
+
switch (key) {
|
|
57
|
+
case "ArrowDown": return 1;
|
|
58
|
+
case "ArrowUp": return -1;
|
|
59
|
+
case "PageDown": return 10;
|
|
60
|
+
case "PageUp": return -10;
|
|
61
|
+
default: return 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
var absoluteKeys = new Set(["End", "Home"]);
|
|
65
|
+
var arrowKeys = new Set(["ArrowDown", "ArrowUp"]);
|
|
66
|
+
var negativeDefaultKeys = new Set(["ArrowUp", "End"]);
|
|
67
|
+
var pageKeys = new Set(["PageDown", "PageUp"]);
|
|
68
|
+
var allKeys = new Set([
|
|
69
|
+
...absoluteKeys,
|
|
70
|
+
...arrowKeys,
|
|
71
|
+
...pageKeys
|
|
72
|
+
]);
|
|
73
|
+
export { NavigationManager };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { removeRow, renderRow } from "../components/row.component.js";
|
|
2
|
+
import { on } from "@oscarpalmer/toretto/event";
|
|
3
|
+
function getRange(down) {
|
|
4
|
+
const { components, managers, options } = this.state;
|
|
5
|
+
const { clientHeight, scrollTop } = components.body.elements.group;
|
|
6
|
+
const first = Math.floor(scrollTop / options.rowHeight);
|
|
7
|
+
const last = Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
|
|
8
|
+
const before = Math.ceil(clientHeight / options.rowHeight) * (down ? 1 : 2);
|
|
9
|
+
const after = Math.ceil(clientHeight / options.rowHeight) * (down ? 2 : 1);
|
|
10
|
+
const start = Math.max(0, first - before);
|
|
11
|
+
return {
|
|
12
|
+
end: Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, last + after),
|
|
13
|
+
start
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function onScroll() {
|
|
17
|
+
const { state } = this;
|
|
18
|
+
if (!state.active) {
|
|
19
|
+
requestAnimationFrame(() => {
|
|
20
|
+
const top = state.components.body.elements.group.scrollTop;
|
|
21
|
+
this.update(top > state.top);
|
|
22
|
+
state.active = false;
|
|
23
|
+
state.top = top;
|
|
24
|
+
});
|
|
25
|
+
state.active = true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
var RenderManager = class {
|
|
29
|
+
fragment;
|
|
30
|
+
listener;
|
|
31
|
+
pool = {
|
|
32
|
+
cells: {},
|
|
33
|
+
rows: []
|
|
34
|
+
};
|
|
35
|
+
state;
|
|
36
|
+
visible = /* @__PURE__ */ new Map();
|
|
37
|
+
constructor(state) {
|
|
38
|
+
this.listener = on(state.components.body.elements.group, "scroll", onScroll.bind(this));
|
|
39
|
+
this.state = {
|
|
40
|
+
...state,
|
|
41
|
+
active: false,
|
|
42
|
+
top: 0
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
destroy() {
|
|
46
|
+
const { listener, pool, visible } = this;
|
|
47
|
+
listener();
|
|
48
|
+
visible.clear();
|
|
49
|
+
pool.cells = {};
|
|
50
|
+
pool.rows = [];
|
|
51
|
+
this.fragment = void 0;
|
|
52
|
+
this.listener = void 0;
|
|
53
|
+
this.pool = void 0;
|
|
54
|
+
this.state = void 0;
|
|
55
|
+
this.visible = void 0;
|
|
56
|
+
}
|
|
57
|
+
removeCells(fields) {
|
|
58
|
+
const { pool, state, visible } = this;
|
|
59
|
+
const { length } = fields;
|
|
60
|
+
for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
|
|
61
|
+
for (const [, key] of visible) {
|
|
62
|
+
const row = state.managers.row.get(key);
|
|
63
|
+
if (row == null || row.element == null) continue;
|
|
64
|
+
for (let index = 0; index < length; index += 1) {
|
|
65
|
+
row.cells[fields[index]].innerHTML = "";
|
|
66
|
+
row.cells[fields[index]].remove();
|
|
67
|
+
delete row.cells[fields[index]];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
getFragment() {
|
|
72
|
+
this.fragment ??= document.createDocumentFragment();
|
|
73
|
+
this.fragment.replaceChildren();
|
|
74
|
+
return this.fragment;
|
|
75
|
+
}
|
|
76
|
+
update(down, rerender) {
|
|
77
|
+
const { state, pool, visible } = this;
|
|
78
|
+
const { components, managers, options } = state;
|
|
79
|
+
components.body.elements.faker.style.height = `${managers.data.size * options.rowHeight}px`;
|
|
80
|
+
const indices = /* @__PURE__ */ new Set();
|
|
81
|
+
const range = getRange.call(this, down);
|
|
82
|
+
for (let index = range.start; index <= range.end; index += 1) indices.add(index);
|
|
83
|
+
let remove = rerender ?? false;
|
|
84
|
+
for (const [index, key] of visible) {
|
|
85
|
+
const row = managers.row.get(key);
|
|
86
|
+
if (remove || row == null || !indices.has(index)) {
|
|
87
|
+
visible.delete(index);
|
|
88
|
+
if (row != null) removeRow(pool, row);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const fragment = this.getFragment();
|
|
92
|
+
const keys = managers.data.values.keys.active ?? managers.data.values.keys.original;
|
|
93
|
+
let count = 0;
|
|
94
|
+
for (let index = range.start; index <= range.end; index += 1) {
|
|
95
|
+
if (visible.has(index)) continue;
|
|
96
|
+
const key = keys[index];
|
|
97
|
+
const row = managers.row.get(key);
|
|
98
|
+
if (row == null) continue;
|
|
99
|
+
count += 1;
|
|
100
|
+
renderRow(state, row);
|
|
101
|
+
visible.set(index, key);
|
|
102
|
+
if (row.element != null) {
|
|
103
|
+
row.element.style.transform = `translateY(${index * options.rowHeight}px)`;
|
|
104
|
+
fragment.append(row.element);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (count > 0) components.body.elements.group[down ? "append" : "prepend"](fragment);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
export { RenderManager };
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { RowComponent, removeRow, renderRow } from "../components/row.component.js";
|
|
2
2
|
var RowManager = class {
|
|
3
3
|
components = /* @__PURE__ */ new Map();
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
this.managers = managers;
|
|
7
|
-
this.height = rowHeight;
|
|
4
|
+
constructor(state) {
|
|
5
|
+
this.state = state;
|
|
8
6
|
}
|
|
9
7
|
destroy() {
|
|
10
8
|
const components = [...this.components.values()];
|
|
11
9
|
const { length } = components;
|
|
12
|
-
for (let index = 0; index < length; index += 1) removeRow(this.managers.
|
|
10
|
+
for (let index = 0; index < length; index += 1) removeRow(this.state.managers.render.pool, components[index]);
|
|
13
11
|
this.components.clear();
|
|
12
|
+
this.components = void 0;
|
|
13
|
+
this.state = void 0;
|
|
14
14
|
}
|
|
15
15
|
get(key) {
|
|
16
16
|
let row = this.components.get(key);
|
|
@@ -26,13 +26,13 @@ var RowManager = class {
|
|
|
26
26
|
remove(key) {
|
|
27
27
|
const row = this.components.get(key);
|
|
28
28
|
if (row != null) {
|
|
29
|
-
removeRow(this.managers.
|
|
29
|
+
removeRow(this.state.managers.render.pool, row);
|
|
30
30
|
this.components.delete(key);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
update(key) {
|
|
34
34
|
const row = this.components.get(key);
|
|
35
|
-
if (row != null) renderRow(this.
|
|
35
|
+
if (row != null) renderRow(this.state, row);
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
export { RowManager };
|