@oscarpalmer/tabela 0.10.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 +1 -0
- package/dist/components/row.component.js +11 -8
- package/dist/managers/column.manager.js +9 -8
- package/dist/managers/data.manager.js +26 -22
- package/dist/managers/event.manager.js +39 -23
- package/dist/managers/filter.manager.js +11 -10
- package/dist/managers/navigation.manager.js +73 -0
- package/dist/managers/render.manager.js +30 -25
- package/dist/managers/row.manager.js +7 -7
- package/dist/managers/selection.manager.js +19 -21
- package/dist/managers/sort.manager.js +9 -8
- package/dist/tabela.full.js +535 -410
- package/dist/tabela.js +27 -9
- package/package.json +1 -1
- package/src/components/body.component.ts +2 -0
- package/src/components/row.component.ts +14 -9
- package/src/managers/column.manager.ts +11 -13
- package/src/managers/data.manager.ts +31 -27
- package/src/managers/event.manager.ts +65 -42
- package/src/managers/filter.manager.ts +12 -11
- package/src/managers/navigation.manager.ts +145 -0
- package/src/managers/render.manager.ts +34 -28
- package/src/managers/row.manager.ts +9 -14
- package/src/managers/selection.manager.ts +24 -30
- package/src/managers/sort.manager.ts +14 -14
- package/src/models/render.model.ts +3 -1
- package/src/models/tabela.model.ts +12 -0
- package/src/tabela.ts +34 -9
- package/types/components/row.component.d.ts +2 -2
- 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 +4 -6
- package/types/managers/row.manager.d.ts +4 -5
- package/types/managers/selection.manager.d.ts +3 -4
- package/types/managers/sort.manager.d.ts +4 -4
- package/types/models/render.model.d.ts +2 -1
- package/types/models/tabela.model.d.ts +11 -0
|
@@ -9,27 +9,30 @@ function removeRow(pool, row) {
|
|
|
9
9
|
}
|
|
10
10
|
row.cells = {};
|
|
11
11
|
}
|
|
12
|
-
function renderRow(
|
|
13
|
-
const element = row.element ?? managers.render.pool.rows.shift() ?? createRow();
|
|
12
|
+
function renderRow(state, row) {
|
|
13
|
+
const element = row.element ?? state.managers.render.pool.rows.shift() ?? createRow();
|
|
14
14
|
row.element = element;
|
|
15
15
|
element.innerHTML = "";
|
|
16
|
-
const selected = managers.selection.items.has(row.key);
|
|
16
|
+
const selected = state.managers.selection.items.has(row.key);
|
|
17
|
+
const key = String(row.key);
|
|
17
18
|
setAttributes(element, {
|
|
18
19
|
"aria-selected": String(selected),
|
|
20
|
+
"data-active": String(state.managers.navigation.active === row.key),
|
|
19
21
|
"data-event": "row",
|
|
20
|
-
"data-key":
|
|
22
|
+
"data-key": key,
|
|
23
|
+
id: `tabela_${state.id}_row_${key}`
|
|
21
24
|
});
|
|
22
25
|
element.classList.add("tabela__row--body");
|
|
23
26
|
if (selected) element.classList.add("tabela__row--selected");
|
|
24
27
|
else element.classList.remove("tabela__row--selected");
|
|
25
|
-
const columns = managers.column.items;
|
|
28
|
+
const columns = state.managers.column.items;
|
|
26
29
|
const { length } = columns;
|
|
27
|
-
const data = managers.data.values.objects.mapped.get(row.key);
|
|
30
|
+
const data = state.managers.data.values.objects.mapped.get(row.key);
|
|
28
31
|
if (data == null) return;
|
|
29
32
|
for (let index = 0; index < length; index += 1) {
|
|
30
33
|
const { options } = columns[index];
|
|
31
|
-
managers.render.pool.cells[options.field] ??= [];
|
|
32
|
-
const cell = managers.render.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
|
|
34
|
+
state.managers.render.pool.cells[options.field] ??= [];
|
|
35
|
+
const cell = state.managers.render.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
|
|
33
36
|
cell.textContent = String(data[options.field]);
|
|
34
37
|
row.cells[options.field] = cell;
|
|
35
38
|
element.append(cell);
|
|
@@ -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;
|
|
@@ -28,8 +29,8 @@ var ColumnManager = class {
|
|
|
28
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.render.update(true);
|
|
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,34 +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
|
-
case "row":
|
|
22
|
-
this.managers.selection.handle(event, target);
|
|
23
|
-
break;
|
|
24
|
-
default: break;
|
|
25
|
-
}
|
|
9
|
+
mapped.delete(this.state.element);
|
|
10
|
+
this.state = void 0;
|
|
26
11
|
}
|
|
27
12
|
onSort(event, target) {
|
|
28
|
-
const { managers } = this;
|
|
29
13
|
const direction = target.getAttribute("data-sort-direction");
|
|
30
14
|
const field = target.getAttribute("data-field");
|
|
31
|
-
if (field != null) managers.sort.toggle(event, field, direction);
|
|
15
|
+
if (field != null) this.state.managers.sort.toggle(event, field, direction);
|
|
32
16
|
}
|
|
33
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 });
|
|
34
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.render.update(true, true);
|
|
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 };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { removeRow, renderRow } from "../components/row.component.js";
|
|
2
2
|
import { on } from "@oscarpalmer/toretto/event";
|
|
3
3
|
function getRange(down) {
|
|
4
|
-
const { components, managers } = this;
|
|
4
|
+
const { components, managers, options } = this.state;
|
|
5
5
|
const { clientHeight, scrollTop } = components.body.elements.group;
|
|
6
|
-
const first = Math.floor(scrollTop /
|
|
7
|
-
const last = Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, Math.ceil((scrollTop + clientHeight) /
|
|
8
|
-
const before = Math.ceil(clientHeight /
|
|
9
|
-
const after = Math.ceil(clientHeight /
|
|
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
10
|
const start = Math.max(0, first - before);
|
|
11
11
|
return {
|
|
12
12
|
end: Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, last + after),
|
|
@@ -14,14 +14,15 @@ function getRange(down) {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
function onScroll() {
|
|
17
|
-
|
|
17
|
+
const { state } = this;
|
|
18
|
+
if (!state.active) {
|
|
18
19
|
requestAnimationFrame(() => {
|
|
19
|
-
const top =
|
|
20
|
-
this.update(top >
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const top = state.components.body.elements.group.scrollTop;
|
|
21
|
+
this.update(top > state.top);
|
|
22
|
+
state.active = false;
|
|
23
|
+
state.top = top;
|
|
23
24
|
});
|
|
24
|
-
|
|
25
|
+
state.active = true;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
var RenderManager = class {
|
|
@@ -31,15 +32,15 @@ var RenderManager = class {
|
|
|
31
32
|
cells: {},
|
|
32
33
|
rows: []
|
|
33
34
|
};
|
|
34
|
-
state
|
|
35
|
-
active: false,
|
|
36
|
-
top: 0
|
|
37
|
-
};
|
|
35
|
+
state;
|
|
38
36
|
visible = /* @__PURE__ */ new Map();
|
|
39
|
-
constructor(
|
|
40
|
-
this.
|
|
41
|
-
this.
|
|
42
|
-
|
|
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
|
+
};
|
|
43
44
|
}
|
|
44
45
|
destroy() {
|
|
45
46
|
const { listener, pool, visible } = this;
|
|
@@ -47,15 +48,18 @@ var RenderManager = class {
|
|
|
47
48
|
visible.clear();
|
|
48
49
|
pool.cells = {};
|
|
49
50
|
pool.rows = [];
|
|
51
|
+
this.fragment = void 0;
|
|
50
52
|
this.listener = void 0;
|
|
53
|
+
this.pool = void 0;
|
|
54
|
+
this.state = void 0;
|
|
51
55
|
this.visible = void 0;
|
|
52
56
|
}
|
|
53
57
|
removeCells(fields) {
|
|
54
|
-
const {
|
|
58
|
+
const { pool, state, visible } = this;
|
|
55
59
|
const { length } = fields;
|
|
56
60
|
for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
|
|
57
61
|
for (const [, key] of visible) {
|
|
58
|
-
const row = managers.row.get(key);
|
|
62
|
+
const row = state.managers.row.get(key);
|
|
59
63
|
if (row == null || row.element == null) continue;
|
|
60
64
|
for (let index = 0; index < length; index += 1) {
|
|
61
65
|
row.cells[fields[index]].innerHTML = "";
|
|
@@ -70,8 +74,9 @@ var RenderManager = class {
|
|
|
70
74
|
return this.fragment;
|
|
71
75
|
}
|
|
72
76
|
update(down, rerender) {
|
|
73
|
-
const {
|
|
74
|
-
components
|
|
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`;
|
|
75
80
|
const indices = /* @__PURE__ */ new Set();
|
|
76
81
|
const range = getRange.call(this, down);
|
|
77
82
|
for (let index = range.start; index <= range.end; index += 1) indices.add(index);
|
|
@@ -92,10 +97,10 @@ var RenderManager = class {
|
|
|
92
97
|
const row = managers.row.get(key);
|
|
93
98
|
if (row == null) continue;
|
|
94
99
|
count += 1;
|
|
95
|
-
renderRow(
|
|
100
|
+
renderRow(state, row);
|
|
96
101
|
visible.set(index, key);
|
|
97
102
|
if (row.element != null) {
|
|
98
|
-
row.element.style.transform = `translateY(${index *
|
|
103
|
+
row.element.style.transform = `translateY(${index * options.rowHeight}px)`;
|
|
99
104
|
fragment.append(row.element);
|
|
100
105
|
}
|
|
101
106
|
}
|
|
@@ -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.render.pool, components[index]);
|
|
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.render.pool, row);
|
|
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 };
|
|
@@ -14,10 +14,9 @@ var SelectionManager = class {
|
|
|
14
14
|
});
|
|
15
15
|
items = /* @__PURE__ */ new Set();
|
|
16
16
|
last;
|
|
17
|
-
constructor(
|
|
18
|
-
this.
|
|
19
|
-
|
|
20
|
-
mapped.set(element, this);
|
|
17
|
+
constructor(state) {
|
|
18
|
+
this.state = state;
|
|
19
|
+
mapped.set(state.element, this);
|
|
21
20
|
}
|
|
22
21
|
clear() {
|
|
23
22
|
if (this.items.size === 0) return;
|
|
@@ -35,48 +34,47 @@ var SelectionManager = class {
|
|
|
35
34
|
if (removed.length > 0) this.update(removed);
|
|
36
35
|
}
|
|
37
36
|
destroy() {
|
|
38
|
-
mapped.delete(this.element);
|
|
37
|
+
mapped.delete(this.state.element);
|
|
39
38
|
this.handlers = void 0;
|
|
40
|
-
this.element = void 0;
|
|
41
39
|
this.items = void 0;
|
|
40
|
+
this.last = void 0;
|
|
41
|
+
this.state = void 0;
|
|
42
42
|
}
|
|
43
43
|
handle(event, target) {
|
|
44
44
|
const key = getKey(target.getAttribute("data-key"));
|
|
45
45
|
if (key == null) return;
|
|
46
46
|
const { items } = this;
|
|
47
47
|
if (event.shiftKey) {
|
|
48
|
-
if (this.last == null)
|
|
49
|
-
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
this.range(this.last, key);
|
|
53
|
-
this.last = key;
|
|
48
|
+
if (this.last == null) this.state.managers.navigation.setActive(key, false);
|
|
49
|
+
else this.range(this.last, key);
|
|
54
50
|
return;
|
|
55
51
|
}
|
|
56
52
|
this.last = key;
|
|
53
|
+
this.state.managers.navigation.setActive(key, false);
|
|
57
54
|
if (event.ctrlKey || event.metaKey) {
|
|
58
55
|
if (items.has(key)) this.deselect([key]);
|
|
59
56
|
else this.select([key]);
|
|
60
57
|
return;
|
|
61
58
|
}
|
|
62
|
-
|
|
63
|
-
else this.set([key]);
|
|
64
|
-
else this.set([key]);
|
|
59
|
+
this.set([key]);
|
|
65
60
|
}
|
|
66
61
|
range(from, to) {
|
|
62
|
+
const { state } = this;
|
|
67
63
|
const keyed = isKey(from) && isKey(to);
|
|
68
64
|
const fromKey = keyed ? from : getKey(from.getAttribute("data-key"));
|
|
69
65
|
const toKey = keyed ? to : getKey(to.getAttribute("data-key"));
|
|
70
66
|
if (fromKey === toKey) return;
|
|
71
|
-
const keys =
|
|
72
|
-
const fromIndex =
|
|
73
|
-
const toIndex =
|
|
67
|
+
const keys = state.managers.data.values.keys.active ?? state.managers.data.values.keys.original;
|
|
68
|
+
const fromIndex = state.managers.data.getIndex(fromKey);
|
|
69
|
+
const toIndex = state.managers.data.getIndex(toKey);
|
|
74
70
|
if (fromIndex === -1 || toIndex === -1) return;
|
|
75
71
|
const [start, end] = fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
|
|
76
72
|
const selected = [];
|
|
77
73
|
for (let index = start; index <= end; index += 1) selected.push(keys[index]);
|
|
78
74
|
if (keyed) this.select(selected);
|
|
79
75
|
else this.set(selected);
|
|
76
|
+
this.last = toKey;
|
|
77
|
+
this.state.managers.navigation.setActive(toKey, false);
|
|
80
78
|
}
|
|
81
79
|
select(keys) {
|
|
82
80
|
const { length } = keys;
|
|
@@ -99,8 +97,8 @@ var SelectionManager = class {
|
|
|
99
97
|
this.update(removed);
|
|
100
98
|
}
|
|
101
99
|
toggle() {
|
|
102
|
-
const { items,
|
|
103
|
-
const all = managers.data.values.keys.active ?? managers.data.values.keys.original;
|
|
100
|
+
const { items, state } = this;
|
|
101
|
+
const all = state.managers.data.values.keys.active ?? state.managers.data.values.keys.original;
|
|
104
102
|
if (items.size === all.length) this.clear();
|
|
105
103
|
else this.select(all);
|
|
106
104
|
}
|
|
@@ -115,7 +113,7 @@ var SelectionManager = class {
|
|
|
115
113
|
const { length } = items;
|
|
116
114
|
for (let index = 0; index < length; index += 1) {
|
|
117
115
|
const { key, removed } = items[index];
|
|
118
|
-
const row = this.managers.row.get(key);
|
|
116
|
+
const row = this.state.managers.row.get(key);
|
|
119
117
|
if (row == null || row.element == null) continue;
|
|
120
118
|
setAttribute(row.element, "aria-selected", String(!removed));
|
|
121
119
|
if (removed) row.element.classList.remove("tabela__row--selected");
|