@oscarpalmer/tabela 0.8.0 → 0.10.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 +2 -15
- package/dist/components/footer.component.js +3 -3
- package/dist/components/header.component.js +2 -2
- package/dist/components/row.component.js +13 -4
- 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 +7 -2
- package/dist/managers/data.manager.js +6 -4
- package/dist/managers/event.manager.js +6 -2
- package/dist/managers/filter.manager.js +92 -0
- package/dist/managers/{virtualization.manager.js → render.manager.js} +28 -22
- package/dist/managers/row.manager.js +9 -2
- package/dist/managers/selection.manager.js +191 -0
- package/dist/managers/sort.manager.js +17 -6
- package/dist/models/render.model.js +0 -0
- package/dist/tabela.full.js +1253 -105
- package/dist/tabela.js +19 -6
- package/package.json +1 -1
- package/src/components/body.component.ts +4 -21
- package/src/components/footer.component.ts +3 -3
- package/src/components/header.component.ts +2 -2
- package/src/components/row.component.ts +22 -7
- 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 +9 -1
- package/src/managers/data.manager.ts +9 -5
- package/src/managers/event.manager.ts +10 -3
- package/src/managers/filter.manager.ts +154 -0
- package/src/managers/{virtualization.manager.ts → render.manager.ts} +36 -31
- package/src/managers/row.manager.ts +16 -2
- package/src/managers/selection.manager.ts +338 -0
- package/src/managers/sort.manager.ts +35 -16
- package/src/models/filter.model.ts +17 -0
- package/src/models/{virtualization.model.ts → render.model.ts} +3 -3
- package/src/models/sort.model.ts +1 -1
- package/src/models/tabela.model.ts +22 -2
- package/src/tabela.ts +28 -6
- package/types/components/row.component.d.ts +2 -2
- 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/data.manager.d.ts +1 -1
- package/types/managers/event.manager.d.ts +1 -1
- package/types/managers/filter.manager.d.ts +19 -0
- package/types/managers/{virtualization.manager.d.ts → render.manager.d.ts} +6 -6
- package/types/managers/selection.manager.d.ts +19 -0
- package/types/managers/sort.manager.d.ts +5 -2
- package/types/models/filter.model.d.ts +6 -0
- package/types/models/{virtualization.model.d.ts → render.model.d.ts} +3 -3
- package/types/models/sort.model.d.ts +1 -1
- package/types/models/tabela.model.d.ts +20 -2
- package/types/tabela.d.ts +3 -1
- /package/dist/models/{virtualization.model.js → filter.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,8 @@ 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
|
-
setStyles(group, {
|
|
24
|
-
height: "100%",
|
|
25
|
-
overflow: "auto",
|
|
26
|
-
position: "relative"
|
|
27
|
-
});
|
|
28
15
|
group.append(this.elements.faker);
|
|
29
16
|
}
|
|
30
17
|
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 = "";
|
|
@@ -9,18 +10,26 @@ function removeRow(pool, row) {
|
|
|
9
10
|
row.cells = {};
|
|
10
11
|
}
|
|
11
12
|
function renderRow(managers, row) {
|
|
12
|
-
const element = row.element ?? managers.
|
|
13
|
+
const element = row.element ?? managers.render.pool.rows.shift() ?? createRow();
|
|
13
14
|
row.element = element;
|
|
14
|
-
element.dataset.key = String(row.key);
|
|
15
15
|
element.innerHTML = "";
|
|
16
|
+
const selected = managers.selection.items.has(row.key);
|
|
17
|
+
setAttributes(element, {
|
|
18
|
+
"aria-selected": String(selected),
|
|
19
|
+
"data-event": "row",
|
|
20
|
+
"data-key": String(row.key)
|
|
21
|
+
});
|
|
22
|
+
element.classList.add("tabela__row--body");
|
|
23
|
+
if (selected) element.classList.add("tabela__row--selected");
|
|
24
|
+
else element.classList.remove("tabela__row--selected");
|
|
16
25
|
const columns = managers.column.items;
|
|
17
26
|
const { length } = columns;
|
|
18
27
|
const data = managers.data.values.objects.mapped.get(row.key);
|
|
19
28
|
if (data == null) return;
|
|
20
29
|
for (let index = 0; index < length; index += 1) {
|
|
21
30
|
const { options } = columns[index];
|
|
22
|
-
managers.
|
|
23
|
-
const cell = managers.
|
|
31
|
+
managers.render.pool.cells[options.field] ??= [];
|
|
32
|
+
const cell = managers.render.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
|
|
24
33
|
cell.textContent = String(data[options.field]);
|
|
25
34
|
row.cells[options.field] = cell;
|
|
26
35
|
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 };
|
|
@@ -7,6 +7,8 @@ var ColumnManager = class {
|
|
|
7
7
|
this.set(columns);
|
|
8
8
|
}
|
|
9
9
|
destroy() {
|
|
10
|
+
const { length } = this.items;
|
|
11
|
+
for (let index = 0; index < length; index += 1) this.items[index].destroy();
|
|
10
12
|
this.items.length = 0;
|
|
11
13
|
}
|
|
12
14
|
remove(value) {
|
|
@@ -16,11 +18,14 @@ var ColumnManager = class {
|
|
|
16
18
|
if (length === 0) return;
|
|
17
19
|
for (let fieldIndex = 0; fieldIndex < length; fieldIndex += 1) {
|
|
18
20
|
const itemIndex = items.findIndex((component) => component.options.field === fields[fieldIndex]);
|
|
19
|
-
if (itemIndex > -1)
|
|
21
|
+
if (itemIndex > -1) {
|
|
22
|
+
items[itemIndex].destroy();
|
|
23
|
+
items.splice(itemIndex, 1);
|
|
24
|
+
}
|
|
20
25
|
}
|
|
21
26
|
components.header.update(items);
|
|
22
27
|
components.footer.update(items);
|
|
23
|
-
managers.
|
|
28
|
+
managers.render.removeCells(fields);
|
|
24
29
|
}
|
|
25
30
|
set(columns) {
|
|
26
31
|
const { components, items } = this;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sort } from "@oscarpalmer/atoms/array";
|
|
1
|
+
import { push, sort } from "@oscarpalmer/atoms/array";
|
|
2
2
|
import { toMap } from "@oscarpalmer/atoms/array/to-map";
|
|
3
3
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
4
|
var DataManager = class {
|
|
@@ -27,7 +27,7 @@ var DataManager = class {
|
|
|
27
27
|
}
|
|
28
28
|
async add(data, render) {
|
|
29
29
|
const { field, values } = this;
|
|
30
|
-
values.objects.array
|
|
30
|
+
push(values.objects.array, data);
|
|
31
31
|
values.objects.mapped = toMap(values.objects.array, field);
|
|
32
32
|
if (render) this.render();
|
|
33
33
|
}
|
|
@@ -40,6 +40,7 @@ var DataManager = class {
|
|
|
40
40
|
values.keys.active = void 0;
|
|
41
41
|
values.keys.original.length = 0;
|
|
42
42
|
values.objects.array.length = 0;
|
|
43
|
+
this.handlers = void 0;
|
|
43
44
|
}
|
|
44
45
|
get(active) {
|
|
45
46
|
const { values } = this;
|
|
@@ -63,8 +64,9 @@ var DataManager = class {
|
|
|
63
64
|
render() {
|
|
64
65
|
const { field, managers, values } = this;
|
|
65
66
|
values.keys.original = sort(values.objects.array.map((item) => item[field]));
|
|
66
|
-
if (managers.
|
|
67
|
-
else managers.
|
|
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);
|
|
68
70
|
}
|
|
69
71
|
set(data) {
|
|
70
72
|
const { field, values } = this;
|
|
@@ -2,9 +2,9 @@ import { on } from "@oscarpalmer/toretto/event";
|
|
|
2
2
|
import { findAncestor } from "@oscarpalmer/toretto";
|
|
3
3
|
var EventManager = class {
|
|
4
4
|
listener;
|
|
5
|
-
constructor(
|
|
5
|
+
constructor(element, managers) {
|
|
6
6
|
this.managers = managers;
|
|
7
|
-
on(element, "click", (event) => {
|
|
7
|
+
this.listener = on(element, "click", (event) => {
|
|
8
8
|
this.onClick(event);
|
|
9
9
|
}, { passive: false });
|
|
10
10
|
}
|
|
@@ -18,6 +18,10 @@ var EventManager = class {
|
|
|
18
18
|
case "heading":
|
|
19
19
|
this.onSort(event, target);
|
|
20
20
|
break;
|
|
21
|
+
case "row":
|
|
22
|
+
this.managers.selection.handle(event, target);
|
|
23
|
+
break;
|
|
24
|
+
default: break;
|
|
21
25
|
}
|
|
22
26
|
}
|
|
23
27
|
onSort(event, target) {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { getNumber } from "@oscarpalmer/atoms/number";
|
|
2
|
+
import { getString } from "@oscarpalmer/atoms/string";
|
|
3
|
+
import { endsWith, includes, startsWith } from "@oscarpalmer/atoms/string/match";
|
|
4
|
+
import { equal } from "@oscarpalmer/atoms/value/equal";
|
|
5
|
+
var FilterManager = class {
|
|
6
|
+
handlers = Object.freeze({
|
|
7
|
+
add: (item) => this.add(item),
|
|
8
|
+
clear: () => this.clear(),
|
|
9
|
+
remove: (value) => this.remove(value),
|
|
10
|
+
set: (items) => this.set(items)
|
|
11
|
+
});
|
|
12
|
+
items = {};
|
|
13
|
+
constructor(managers) {
|
|
14
|
+
this.managers = managers;
|
|
15
|
+
}
|
|
16
|
+
add(item) {
|
|
17
|
+
if (this.items[item.field] == null) this.items[item.field] = [];
|
|
18
|
+
else if (this.items[item.field].findIndex((existing) => equal(existing, item)) !== -1) return;
|
|
19
|
+
this.items[item.field].push(item);
|
|
20
|
+
this.filter();
|
|
21
|
+
}
|
|
22
|
+
clear() {
|
|
23
|
+
if (Object.keys(this.items).length > 0) {
|
|
24
|
+
this.items = {};
|
|
25
|
+
this.filter();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
destroy() {
|
|
29
|
+
this.handlers = void 0;
|
|
30
|
+
this.items = {};
|
|
31
|
+
}
|
|
32
|
+
filter() {
|
|
33
|
+
const { managers } = this;
|
|
34
|
+
const filtered = [];
|
|
35
|
+
const filters = Object.entries(this.items);
|
|
36
|
+
const keysLength = managers.data.values.keys.original.length;
|
|
37
|
+
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);
|
|
40
|
+
if (row == null) continue;
|
|
41
|
+
filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
|
|
42
|
+
const [field, items] = filters[filterIndex];
|
|
43
|
+
const value = row[field];
|
|
44
|
+
for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
|
|
45
|
+
const filter = items[itemIndex];
|
|
46
|
+
if (comparators[filter.comparison](value, filter.value)) continue filterLoop;
|
|
47
|
+
}
|
|
48
|
+
continue rowLoop;
|
|
49
|
+
}
|
|
50
|
+
filtered.push(key);
|
|
51
|
+
}
|
|
52
|
+
managers.data.values.keys.active = filtered;
|
|
53
|
+
if (managers.sort.items.length > 0) managers.sort.sort();
|
|
54
|
+
else managers.render.update(true, true);
|
|
55
|
+
}
|
|
56
|
+
remove(value) {
|
|
57
|
+
if (typeof value === "string") {
|
|
58
|
+
if (this.items[value] == null) return;
|
|
59
|
+
this.items = {};
|
|
60
|
+
} else {
|
|
61
|
+
const { field } = value;
|
|
62
|
+
if (this.items[field] == null) return;
|
|
63
|
+
if (this.items[field].findIndex((item) => equal(item, value)) === -1) return;
|
|
64
|
+
}
|
|
65
|
+
this.filter();
|
|
66
|
+
}
|
|
67
|
+
set(items) {
|
|
68
|
+
const keyed = {};
|
|
69
|
+
const { length } = items;
|
|
70
|
+
for (let index = 0; index < length; index += 1) {
|
|
71
|
+
const item = items[index];
|
|
72
|
+
keyed[item.field] ??= [];
|
|
73
|
+
keyed[item.field].push(item);
|
|
74
|
+
}
|
|
75
|
+
this.items = keyed;
|
|
76
|
+
this.filter();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
var comparators = {
|
|
80
|
+
contains: (row, filter) => includes(getString(row), getString(filter), true),
|
|
81
|
+
"ends-with": (row, filter) => endsWith(getString(row), getString(filter), true),
|
|
82
|
+
equals: (row, filter) => equalizer(row, filter),
|
|
83
|
+
"greater-than": (row, filter) => getNumber(row) > getNumber(filter),
|
|
84
|
+
"greater-than-or-equal": (row, filter) => getNumber(row) >= getNumber(filter),
|
|
85
|
+
"less-than": (row, filter) => getNumber(row) < getNumber(filter),
|
|
86
|
+
"less-than-or-equal": (row, filter) => getNumber(row) <= getNumber(filter),
|
|
87
|
+
"not-contains": (row, filter) => !includes(getString(row), getString(filter), true),
|
|
88
|
+
"not-equals": (row, filter) => !equalizer(row, filter),
|
|
89
|
+
"starts-with": (row, filter) => startsWith(getString(row), getString(filter), true)
|
|
90
|
+
};
|
|
91
|
+
var equalizer = equal.initialize({ ignoreCase: true });
|
|
92
|
+
export { FilterManager };
|
|
@@ -4,12 +4,12 @@ function getRange(down) {
|
|
|
4
4
|
const { components, managers } = this;
|
|
5
5
|
const { clientHeight, scrollTop } = components.body.elements.group;
|
|
6
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);
|
|
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
8
|
const before = Math.ceil(clientHeight / managers.row.height) * (down ? 1 : 2);
|
|
9
9
|
const after = Math.ceil(clientHeight / managers.row.height) * (down ? 2 : 1);
|
|
10
10
|
const start = Math.max(0, first - before);
|
|
11
11
|
return {
|
|
12
|
-
end: Math.min(managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length - 1, last + after),
|
|
12
|
+
end: Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, last + after),
|
|
13
13
|
start
|
|
14
14
|
};
|
|
15
15
|
}
|
|
@@ -24,7 +24,7 @@ function onScroll() {
|
|
|
24
24
|
this.state.active = true;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
var
|
|
27
|
+
var RenderManager = class {
|
|
28
28
|
fragment;
|
|
29
29
|
listener;
|
|
30
30
|
pool = {
|
|
@@ -42,21 +42,26 @@ var VirtualizationManager = class {
|
|
|
42
42
|
this.listener = on(components.body.elements.group, "scroll", onScroll.bind(this));
|
|
43
43
|
}
|
|
44
44
|
destroy() {
|
|
45
|
-
this
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
45
|
+
const { listener, pool, visible } = this;
|
|
46
|
+
listener();
|
|
47
|
+
visible.clear();
|
|
48
|
+
pool.cells = {};
|
|
49
|
+
pool.rows = [];
|
|
50
|
+
this.listener = void 0;
|
|
51
|
+
this.visible = void 0;
|
|
52
52
|
}
|
|
53
53
|
removeCells(fields) {
|
|
54
|
+
const { managers, pool, visible } = this;
|
|
54
55
|
const { length } = fields;
|
|
55
|
-
for (let index = 0; index < length; index += 1) delete
|
|
56
|
-
for (const [,
|
|
57
|
-
row
|
|
58
|
-
row.
|
|
59
|
-
|
|
56
|
+
for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
|
|
57
|
+
for (const [, key] of visible) {
|
|
58
|
+
const row = managers.row.get(key);
|
|
59
|
+
if (row == null || row.element == null) continue;
|
|
60
|
+
for (let index = 0; index < length; index += 1) {
|
|
61
|
+
row.cells[fields[index]].innerHTML = "";
|
|
62
|
+
row.cells[fields[index]].remove();
|
|
63
|
+
delete row.cells[fields[index]];
|
|
64
|
+
}
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
getFragment() {
|
|
@@ -71,11 +76,11 @@ var VirtualizationManager = class {
|
|
|
71
76
|
const range = getRange.call(this, down);
|
|
72
77
|
for (let index = range.start; index <= range.end; index += 1) indices.add(index);
|
|
73
78
|
let remove = rerender ?? false;
|
|
74
|
-
for (const [index,
|
|
75
|
-
|
|
76
|
-
if (remove) {
|
|
79
|
+
for (const [index, key] of visible) {
|
|
80
|
+
const row = managers.row.get(key);
|
|
81
|
+
if (remove || row == null || !indices.has(index)) {
|
|
77
82
|
visible.delete(index);
|
|
78
|
-
removeRow(pool, row);
|
|
83
|
+
if (row != null) removeRow(pool, row);
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
const fragment = this.getFragment();
|
|
@@ -83,11 +88,12 @@ var VirtualizationManager = class {
|
|
|
83
88
|
let count = 0;
|
|
84
89
|
for (let index = range.start; index <= range.end; index += 1) {
|
|
85
90
|
if (visible.has(index)) continue;
|
|
86
|
-
const
|
|
91
|
+
const key = keys[index];
|
|
92
|
+
const row = managers.row.get(key);
|
|
87
93
|
if (row == null) continue;
|
|
88
94
|
count += 1;
|
|
89
95
|
renderRow(managers, row);
|
|
90
|
-
visible.set(index,
|
|
96
|
+
visible.set(index, key);
|
|
91
97
|
if (row.element != null) {
|
|
92
98
|
row.element.style.transform = `translateY(${index * managers.row.height}px)`;
|
|
93
99
|
fragment.append(row.element);
|
|
@@ -96,4 +102,4 @@ var VirtualizationManager = class {
|
|
|
96
102
|
if (count > 0) components.body.elements.group[down ? "append" : "prepend"](fragment);
|
|
97
103
|
}
|
|
98
104
|
};
|
|
99
|
-
export {
|
|
105
|
+
export { RenderManager };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RowComponent, renderRow } from "../components/row.component.js";
|
|
1
|
+
import { RowComponent, removeRow, renderRow } from "../components/row.component.js";
|
|
2
2
|
var RowManager = class {
|
|
3
3
|
components = /* @__PURE__ */ new Map();
|
|
4
4
|
height;
|
|
@@ -7,6 +7,9 @@ var RowManager = class {
|
|
|
7
7
|
this.height = rowHeight;
|
|
8
8
|
}
|
|
9
9
|
destroy() {
|
|
10
|
+
const components = [...this.components.values()];
|
|
11
|
+
const { length } = components;
|
|
12
|
+
for (let index = 0; index < length; index += 1) removeRow(this.managers.render.pool, components[index]);
|
|
10
13
|
this.components.clear();
|
|
11
14
|
}
|
|
12
15
|
get(key) {
|
|
@@ -21,7 +24,11 @@ var RowManager = class {
|
|
|
21
24
|
return this.components.has(key);
|
|
22
25
|
}
|
|
23
26
|
remove(key) {
|
|
24
|
-
this.components.
|
|
27
|
+
const row = this.components.get(key);
|
|
28
|
+
if (row != null) {
|
|
29
|
+
removeRow(this.managers.render.pool, row);
|
|
30
|
+
this.components.delete(key);
|
|
31
|
+
}
|
|
25
32
|
}
|
|
26
33
|
update(key) {
|
|
27
34
|
const row = this.components.get(key);
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { createElement } from "../helpers/dom.helpers.js";
|
|
2
|
+
import { getKey } from "../helpers/misc.helpers.js";
|
|
3
|
+
import { dragStyling } from "../helpers/style.helper.js";
|
|
4
|
+
import { setAttribute } from "@oscarpalmer/toretto/attribute";
|
|
5
|
+
import { isKey } from "@oscarpalmer/atoms/is";
|
|
6
|
+
import { getPosition, on } from "@oscarpalmer/toretto/event";
|
|
7
|
+
import { findAncestor } from "@oscarpalmer/toretto";
|
|
8
|
+
var SelectionManager = class {
|
|
9
|
+
handlers = Object.freeze({
|
|
10
|
+
clear: () => this.clear(),
|
|
11
|
+
deselect: (keys) => this.deselect(keys),
|
|
12
|
+
select: (keys) => this.select(keys),
|
|
13
|
+
toggle: () => this.toggle()
|
|
14
|
+
});
|
|
15
|
+
items = /* @__PURE__ */ new Set();
|
|
16
|
+
last;
|
|
17
|
+
constructor(element, managers) {
|
|
18
|
+
this.element = element;
|
|
19
|
+
this.managers = managers;
|
|
20
|
+
mapped.set(element, this);
|
|
21
|
+
}
|
|
22
|
+
clear() {
|
|
23
|
+
if (this.items.size === 0) return;
|
|
24
|
+
const removed = [...this.items];
|
|
25
|
+
this.items.clear();
|
|
26
|
+
this.update(removed);
|
|
27
|
+
}
|
|
28
|
+
deselect(keys) {
|
|
29
|
+
const { length } = keys;
|
|
30
|
+
const removed = [];
|
|
31
|
+
for (let index = 0; index < length; index += 1) {
|
|
32
|
+
const key = keys[index];
|
|
33
|
+
if (this.items.delete(key)) removed.push(key);
|
|
34
|
+
}
|
|
35
|
+
if (removed.length > 0) this.update(removed);
|
|
36
|
+
}
|
|
37
|
+
destroy() {
|
|
38
|
+
mapped.delete(this.element);
|
|
39
|
+
this.handlers = void 0;
|
|
40
|
+
this.element = void 0;
|
|
41
|
+
this.items = void 0;
|
|
42
|
+
}
|
|
43
|
+
handle(event, target) {
|
|
44
|
+
const key = getKey(target.getAttribute("data-key"));
|
|
45
|
+
if (key == null) return;
|
|
46
|
+
const { items } = this;
|
|
47
|
+
if (event.shiftKey) {
|
|
48
|
+
if (this.last == null) {
|
|
49
|
+
this.last = key;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.range(this.last, key);
|
|
53
|
+
this.last = key;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.last = key;
|
|
57
|
+
if (event.ctrlKey || event.metaKey) {
|
|
58
|
+
if (items.has(key)) this.deselect([key]);
|
|
59
|
+
else this.select([key]);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (items.has(key)) if (items.size === 1) this.clear();
|
|
63
|
+
else this.set([key]);
|
|
64
|
+
else this.set([key]);
|
|
65
|
+
}
|
|
66
|
+
range(from, to) {
|
|
67
|
+
const keyed = isKey(from) && isKey(to);
|
|
68
|
+
const fromKey = keyed ? from : getKey(from.getAttribute("data-key"));
|
|
69
|
+
const toKey = keyed ? to : getKey(to.getAttribute("data-key"));
|
|
70
|
+
if (fromKey === toKey) return;
|
|
71
|
+
const keys = this.managers.data.values.keys.active ?? this.managers.data.values.keys.original;
|
|
72
|
+
const fromIndex = keys.indexOf(fromKey);
|
|
73
|
+
const toIndex = keys.indexOf(toKey);
|
|
74
|
+
if (fromIndex === -1 || toIndex === -1) return;
|
|
75
|
+
const [start, end] = fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
|
|
76
|
+
const selected = [];
|
|
77
|
+
for (let index = start; index <= end; index += 1) selected.push(keys[index]);
|
|
78
|
+
if (keyed) this.select(selected);
|
|
79
|
+
else this.set(selected);
|
|
80
|
+
}
|
|
81
|
+
select(keys) {
|
|
82
|
+
const { length } = keys;
|
|
83
|
+
let update = false;
|
|
84
|
+
for (let index = 0; index < length; index += 1) {
|
|
85
|
+
const key = keys[index];
|
|
86
|
+
if (!this.items.has(key)) {
|
|
87
|
+
this.items.add(key);
|
|
88
|
+
update = true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (update) this.update([]);
|
|
92
|
+
}
|
|
93
|
+
set(keys) {
|
|
94
|
+
const { items } = this;
|
|
95
|
+
const removed = [...items].filter((key) => !keys.includes(key));
|
|
96
|
+
const added = keys.filter((key) => !items.has(key));
|
|
97
|
+
if (removed.length === 0 && added.length === 0) return;
|
|
98
|
+
this.items = new Set(keys);
|
|
99
|
+
this.update(removed);
|
|
100
|
+
}
|
|
101
|
+
toggle() {
|
|
102
|
+
const { items, managers } = this;
|
|
103
|
+
const all = managers.data.values.keys.active ?? managers.data.values.keys.original;
|
|
104
|
+
if (items.size === all.length) this.clear();
|
|
105
|
+
else this.select(all);
|
|
106
|
+
}
|
|
107
|
+
update(removed) {
|
|
108
|
+
const items = [...removed.map((key) => ({
|
|
109
|
+
key,
|
|
110
|
+
removed: true
|
|
111
|
+
})), ...[...this.items].map((key) => ({
|
|
112
|
+
key,
|
|
113
|
+
removed: false
|
|
114
|
+
}))];
|
|
115
|
+
const { length } = items;
|
|
116
|
+
for (let index = 0; index < length; index += 1) {
|
|
117
|
+
const { key, removed } = items[index];
|
|
118
|
+
const row = this.managers.row.get(key);
|
|
119
|
+
if (row == null || row.element == null) continue;
|
|
120
|
+
setAttribute(row.element, "aria-selected", String(!removed));
|
|
121
|
+
if (removed) row.element.classList.remove("tabela__row--selected");
|
|
122
|
+
else row.element.classList.add("tabela__row--selected");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
function getPlaceholder() {
|
|
127
|
+
placeholder ??= createElement("div", { className: "tabela__selection--placeholder" }, {}, {});
|
|
128
|
+
return placeholder;
|
|
129
|
+
}
|
|
130
|
+
function onMouseDown(event) {
|
|
131
|
+
if (shifted) {
|
|
132
|
+
const row = findAncestor(event.target, ".tabela__row--body");
|
|
133
|
+
if (!(row instanceof HTMLElement)) return;
|
|
134
|
+
startElement = row;
|
|
135
|
+
startPosition = getPosition(event);
|
|
136
|
+
dragStyling.set();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function onMouseMove(event) {
|
|
140
|
+
if (startElement == null) return;
|
|
141
|
+
const currentPosition = getPosition(event);
|
|
142
|
+
if (currentPosition == null || startPosition == null) return;
|
|
143
|
+
const element = getPlaceholder();
|
|
144
|
+
if (element.parentElement == null) document.body.append(element);
|
|
145
|
+
const { x: cX, y: cY } = currentPosition;
|
|
146
|
+
const { x: sX, y: sY } = startPosition;
|
|
147
|
+
const top = Math.min(cY, sY);
|
|
148
|
+
const left = Math.min(cX, sX);
|
|
149
|
+
const width = Math.abs(cX - sX);
|
|
150
|
+
const height = Math.abs(cY - sY);
|
|
151
|
+
element.style.inset = `${top}px ${window.innerWidth - left - width}px ${window.innerHeight - top - height}px ${left}px`;
|
|
152
|
+
}
|
|
153
|
+
function onMouseUp(event) {
|
|
154
|
+
if (startElement == null) return;
|
|
155
|
+
if (!event.shiftKey) {
|
|
156
|
+
shifted = false;
|
|
157
|
+
dragStyling.remove();
|
|
158
|
+
}
|
|
159
|
+
getPlaceholder().remove();
|
|
160
|
+
const row = findAncestor(event.target, ".tabela__row--body");
|
|
161
|
+
if (row instanceof HTMLElement) {
|
|
162
|
+
endElement = row;
|
|
163
|
+
const endTable = findAncestor(endElement, ".tabela");
|
|
164
|
+
const startTable = findAncestor(startElement, ".tabela");
|
|
165
|
+
if (startTable != null && startTable === endTable) mapped.get(startTable)?.range(startElement, endElement);
|
|
166
|
+
}
|
|
167
|
+
endElement = void 0;
|
|
168
|
+
startElement = void 0;
|
|
169
|
+
startPosition = void 0;
|
|
170
|
+
}
|
|
171
|
+
function onShift(event, value) {
|
|
172
|
+
if (event.key === "Shift") shifted = value;
|
|
173
|
+
}
|
|
174
|
+
function onShiftDown(event) {
|
|
175
|
+
onShift(event, true);
|
|
176
|
+
}
|
|
177
|
+
function onShiftUp(event) {
|
|
178
|
+
onShift(event, false);
|
|
179
|
+
}
|
|
180
|
+
var mapped = /* @__PURE__ */ new WeakMap();
|
|
181
|
+
var shifted = false;
|
|
182
|
+
var endElement;
|
|
183
|
+
var placeholder;
|
|
184
|
+
var startPosition;
|
|
185
|
+
var startElement;
|
|
186
|
+
on(document, "keydown", onShiftDown);
|
|
187
|
+
on(document, "keyup", onShiftUp);
|
|
188
|
+
on(document, "mousedown", onMouseDown);
|
|
189
|
+
on(document, "mousemove", onMouseMove);
|
|
190
|
+
on(document, "mouseup", onMouseUp);
|
|
191
|
+
export { SelectionManager };
|