@oscarpalmer/tabela 0.10.0 → 0.12.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/column.component.js +4 -4
- package/dist/components/group.component.js +28 -0
- package/dist/components/row.component.js +11 -8
- package/dist/helpers/dom.helpers.js +1 -1
- package/dist/managers/column.manager.js +9 -8
- package/dist/managers/data.manager.js +95 -30
- package/dist/managers/event.manager.js +42 -23
- package/dist/managers/filter.manager.js +16 -10
- package/dist/managers/group.manager.js +46 -0
- package/dist/managers/navigation.manager.js +73 -0
- package/dist/managers/render.manager.js +61 -31
- package/dist/managers/row.manager.js +7 -7
- package/dist/managers/selection.manager.js +49 -46
- package/dist/managers/sort.manager.js +37 -9
- package/dist/models/group.model.js +0 -0
- package/dist/models/selection.model.js +0 -0
- package/dist/tabela.full.js +682 -591
- package/dist/tabela.js +31 -10
- package/package.json +1 -1
- package/src/components/body.component.ts +2 -0
- package/src/components/column.component.ts +6 -6
- package/src/components/group.component.ts +43 -0
- package/src/components/row.component.ts +14 -9
- package/src/helpers/dom.helpers.ts +3 -1
- package/src/managers/column.manager.ts +13 -15
- package/src/managers/data.manager.ts +176 -38
- package/src/managers/event.manager.ts +68 -41
- package/src/managers/filter.manager.ts +29 -20
- package/src/managers/group.manager.ts +79 -0
- package/src/managers/navigation.manager.ts +146 -0
- package/src/managers/render.manager.ts +84 -40
- package/src/managers/row.manager.ts +9 -14
- package/src/managers/selection.manager.ts +68 -67
- package/src/managers/sort.manager.ts +85 -22
- package/src/models/column.model.ts +2 -2
- package/src/models/data.model.ts +14 -3
- package/src/models/filter.model.ts +11 -3
- package/src/models/group.model.ts +4 -0
- package/src/models/render.model.ts +3 -1
- package/src/models/selection.model.ts +9 -0
- package/src/models/sort.model.ts +11 -3
- package/src/models/tabela.model.ts +14 -36
- package/src/models/tabela.options.ts +3 -2
- package/src/tabela.ts +43 -19
- package/types/components/column.component.d.ts +3 -3
- package/types/components/group.component.d.ts +14 -0
- package/types/components/row.component.d.ts +2 -2
- package/types/helpers/style.helper.d.ts +1 -1
- package/types/managers/column.manager.d.ts +6 -7
- package/types/managers/data.manager.d.ts +7 -6
- package/types/managers/event.manager.d.ts +3 -6
- package/types/managers/filter.manager.d.ts +11 -11
- package/types/managers/group.manager.d.ts +17 -0
- package/types/managers/navigation.manager.d.ts +10 -0
- package/types/managers/render.manager.d.ts +6 -7
- package/types/managers/row.manager.d.ts +4 -5
- package/types/managers/selection.manager.d.ts +12 -7
- package/types/managers/sort.manager.d.ts +11 -9
- package/types/models/column.model.d.ts +2 -2
- package/types/models/data.model.d.ts +13 -3
- package/types/models/filter.model.d.ts +10 -3
- package/types/models/group.model.d.ts +4 -0
- package/types/models/render.model.d.ts +2 -1
- package/types/models/selection.model.d.ts +8 -0
- package/types/models/sort.model.d.ts +10 -3
- package/types/models/tabela.model.d.ts +14 -33
- package/types/models/tabela.options.d.ts +3 -2
- package/types/tabela.d.ts +4 -1
|
@@ -2,13 +2,13 @@ import { createElement } from "../helpers/dom.helpers.js";
|
|
|
2
2
|
var ColumnComponent = class {
|
|
3
3
|
elements;
|
|
4
4
|
options;
|
|
5
|
-
constructor(
|
|
6
|
-
const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (
|
|
5
|
+
constructor(column) {
|
|
6
|
+
const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (column.width ?? column.title.length * 1.5);
|
|
7
7
|
this.options = {
|
|
8
|
-
...
|
|
8
|
+
...column,
|
|
9
9
|
width
|
|
10
10
|
};
|
|
11
|
-
this.elements = createHeading(options.field, options.title, width);
|
|
11
|
+
this.elements = createHeading(this.options.field, this.options.title, width);
|
|
12
12
|
}
|
|
13
13
|
destroy() {
|
|
14
14
|
this.elements.content.remove();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createElement } from "../helpers/dom.helpers.js";
|
|
2
|
+
var GroupComponent = class {
|
|
3
|
+
element;
|
|
4
|
+
expanded = true;
|
|
5
|
+
filtered = 0;
|
|
6
|
+
selected = 0;
|
|
7
|
+
total = 0;
|
|
8
|
+
constructor(key, label, value) {
|
|
9
|
+
this.key = key;
|
|
10
|
+
this.label = label;
|
|
11
|
+
this.value = value;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
function renderGroup(state, component) {
|
|
15
|
+
component.element ??= createElement("div", {
|
|
16
|
+
className: "tabela__row tabela__row--group",
|
|
17
|
+
innerHTML: `<div class="tabela__cell tabela__cell--group" role="cell">
|
|
18
|
+
<button class="tabela__button tabela__button--group" data-event="group" data-key="${component.key}" type="button">
|
|
19
|
+
<span aria-hidden="true"></span>
|
|
20
|
+
<span>Open/close</span>
|
|
21
|
+
</button>
|
|
22
|
+
<p>${component.label}</p>
|
|
23
|
+
</div>`,
|
|
24
|
+
role: "row"
|
|
25
|
+
}, {}, { height: `${state.options.rowHeight}px` });
|
|
26
|
+
}
|
|
27
|
+
function updateGroup(state, component) {}
|
|
28
|
+
export { GroupComponent, renderGroup, updateGroup };
|
|
@@ -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);
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GroupComponent } from "../components/group.component.js";
|
|
2
|
+
import { sortWithGroups } from "./sort.manager.js";
|
|
3
|
+
import { select, sort } from "@oscarpalmer/atoms/array";
|
|
2
4
|
import { toMap } from "@oscarpalmer/atoms/array/to-map";
|
|
5
|
+
import { toRecord } from "@oscarpalmer/atoms/array/to-record";
|
|
3
6
|
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
7
|
var DataManager = class {
|
|
5
8
|
handlers = Object.freeze({
|
|
@@ -17,19 +20,41 @@ var DataManager = class {
|
|
|
17
20
|
array: []
|
|
18
21
|
}
|
|
19
22
|
};
|
|
23
|
+
get keys() {
|
|
24
|
+
return this.values.keys.active ?? this.values.keys.original;
|
|
25
|
+
}
|
|
20
26
|
get size() {
|
|
21
|
-
return this.
|
|
27
|
+
return this.keys.length;
|
|
22
28
|
}
|
|
23
|
-
constructor(
|
|
24
|
-
this.
|
|
25
|
-
this.components = components;
|
|
26
|
-
this.field = field;
|
|
29
|
+
constructor(state) {
|
|
30
|
+
this.state = state;
|
|
27
31
|
}
|
|
28
32
|
async add(data, render) {
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
const { state, values } = this;
|
|
34
|
+
const { length } = data;
|
|
35
|
+
const updates = [];
|
|
36
|
+
for (let index = 0; index < length; index += 1) {
|
|
37
|
+
const item = data[index];
|
|
38
|
+
const key = item[state.key];
|
|
39
|
+
if (values.objects.mapped.has(key)) {
|
|
40
|
+
updates.push(item);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
values.objects.array.push(item);
|
|
44
|
+
values.objects.mapped.set(key, item);
|
|
45
|
+
if (!state.managers.group.enabled) continue;
|
|
46
|
+
const groupKey = item[state.managers.group.field];
|
|
47
|
+
let group = state.managers.group.get(groupKey);
|
|
48
|
+
if (group == null) {
|
|
49
|
+
group = new GroupComponent(String(groupKey), String(groupKey), groupKey);
|
|
50
|
+
values.objects.array.push(group);
|
|
51
|
+
state.managers.group.add(group);
|
|
52
|
+
}
|
|
53
|
+
if (!group.expanded) state.managers.group.collapsed.add(key);
|
|
54
|
+
group.total += 1;
|
|
55
|
+
}
|
|
56
|
+
if (updates.length > 0) this.update(updates);
|
|
57
|
+
else if (render) this.render();
|
|
33
58
|
}
|
|
34
59
|
clear() {
|
|
35
60
|
if (this.values.objects.array.length > 0) this.set([]);
|
|
@@ -41,55 +66,95 @@ var DataManager = class {
|
|
|
41
66
|
values.keys.original.length = 0;
|
|
42
67
|
values.objects.array.length = 0;
|
|
43
68
|
this.handlers = void 0;
|
|
69
|
+
this.state = void 0;
|
|
70
|
+
this.values = void 0;
|
|
44
71
|
}
|
|
45
72
|
get(active) {
|
|
46
73
|
const { values } = this;
|
|
47
|
-
return active ?? false ? values.keys.active
|
|
74
|
+
return active ?? false ? select(values.keys.active ?? [], (key) => !(key instanceof GroupComponent), (key) => values.objects.mapped.get(key)) : values.objects.array.filter((item) => !(item instanceof GroupComponent));
|
|
75
|
+
}
|
|
76
|
+
getIndex(key) {
|
|
77
|
+
return this.keys.indexOf(key);
|
|
48
78
|
}
|
|
49
79
|
async remove(items, render) {
|
|
50
|
-
const {
|
|
51
|
-
const keys = items.map((value) => isPlainObject(value) ? value[
|
|
80
|
+
const { state, values } = this;
|
|
81
|
+
const keys = items.map((value) => isPlainObject(value) ? value[state.key] : value).filter((key) => values.objects.mapped.has(key));
|
|
52
82
|
const { length } = keys;
|
|
53
83
|
if (length === 0) return;
|
|
54
84
|
for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
|
|
55
85
|
const key = keys[keyIndex];
|
|
56
86
|
values.objects.mapped.delete(key);
|
|
57
|
-
const arrayIndex = values.objects.array.findIndex((
|
|
58
|
-
|
|
87
|
+
const arrayIndex = values.objects.array.findIndex((item) => !(item instanceof GroupComponent) && item[state.key] === key);
|
|
88
|
+
let item;
|
|
89
|
+
if (arrayIndex > -1) [item] = values.objects.array.splice(arrayIndex, 1);
|
|
59
90
|
values.keys.original.splice(values.keys.original.indexOf(key), 1);
|
|
60
|
-
managers.row.remove(key);
|
|
91
|
+
state.managers.row.remove(key);
|
|
92
|
+
if (!state.managers.group.enabled || item == null) continue;
|
|
93
|
+
state.managers.group.collapsed.delete(key);
|
|
94
|
+
const groupKey = item[state.managers.group.field];
|
|
95
|
+
const group = state.managers.group.get(groupKey);
|
|
96
|
+
if (group == null) continue;
|
|
97
|
+
group.total -= 1;
|
|
98
|
+
if (group.total > 0) continue;
|
|
99
|
+
const groupIndex = values.objects.array.findIndex((item) => item instanceof GroupComponent && item.value === groupKey);
|
|
100
|
+
if (groupIndex > -1) values.objects.array.splice(groupIndex, 1);
|
|
101
|
+
state.managers.group.remove(group);
|
|
61
102
|
}
|
|
62
103
|
if (render) this.render();
|
|
63
104
|
}
|
|
64
105
|
render() {
|
|
65
|
-
const {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
106
|
+
const { state, values } = this;
|
|
107
|
+
if (state.managers.group.enabled) sortWithGroups(state, values.objects.array, [{
|
|
108
|
+
direction: "ascending",
|
|
109
|
+
key: state.key
|
|
110
|
+
}]);
|
|
111
|
+
else sort(values.objects.array, [{
|
|
112
|
+
direction: "ascending",
|
|
113
|
+
key: state.key
|
|
114
|
+
}]);
|
|
115
|
+
values.keys.original = values.objects.array.map((item) => item instanceof GroupComponent ? item : item[state.key]);
|
|
116
|
+
values.objects.mapped = toMap(values.objects.array.filter((item) => !(item instanceof GroupComponent)), (item) => item[state.key]);
|
|
117
|
+
if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
|
|
118
|
+
else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
|
|
119
|
+
else state.managers.render.update(true, true);
|
|
70
120
|
}
|
|
71
121
|
set(data) {
|
|
72
|
-
const {
|
|
73
|
-
|
|
74
|
-
|
|
122
|
+
const { state, values } = this;
|
|
123
|
+
const array = data.slice();
|
|
124
|
+
if (state.managers.group.enabled) {
|
|
125
|
+
const grouped = toRecord.arrays(data, state.managers.group.field);
|
|
126
|
+
const entries = Object.entries(grouped);
|
|
127
|
+
const { length } = entries;
|
|
128
|
+
const groups = [];
|
|
129
|
+
for (let index = 0; index < length; index += 1) {
|
|
130
|
+
const [value, items] = entries[index];
|
|
131
|
+
const key = String(value);
|
|
132
|
+
const group = new GroupComponent(key, key, value);
|
|
133
|
+
group.total = items.length;
|
|
134
|
+
groups.push(group);
|
|
135
|
+
array.push(group);
|
|
136
|
+
}
|
|
137
|
+
state.managers.group.set(groups);
|
|
138
|
+
}
|
|
139
|
+
values.objects.array = array;
|
|
75
140
|
this.render();
|
|
76
141
|
}
|
|
77
142
|
async synchronize(data, remove) {
|
|
78
|
-
const {
|
|
143
|
+
const { state, values } = this;
|
|
79
144
|
const add = [];
|
|
80
145
|
const updated = [];
|
|
81
146
|
const keys = /* @__PURE__ */ new Set([]);
|
|
82
147
|
const { length } = data;
|
|
83
148
|
for (let index = 0; index < length; index += 1) {
|
|
84
149
|
const object = data[index];
|
|
85
|
-
const key = object[
|
|
150
|
+
const key = object[state.key];
|
|
86
151
|
if (values.objects.mapped.has(key)) updated.push(object);
|
|
87
152
|
else add.push(object);
|
|
88
153
|
keys.add(key);
|
|
89
154
|
}
|
|
90
155
|
if (keys.size === 0) return;
|
|
91
156
|
if (remove ?? false) {
|
|
92
|
-
const toRemove = values.keys.original.filter((key) => !keys.has(key));
|
|
157
|
+
const toRemove = values.keys.original.filter((key) => !(key instanceof GroupComponent) && !keys.has(key));
|
|
93
158
|
if (toRemove.length > 0) await this.remove(toRemove, false);
|
|
94
159
|
}
|
|
95
160
|
await this.update(updated);
|
|
@@ -97,18 +162,18 @@ var DataManager = class {
|
|
|
97
162
|
if (add.length > 0 || (remove ?? false)) this.render();
|
|
98
163
|
}
|
|
99
164
|
async update(data) {
|
|
100
|
-
const {
|
|
165
|
+
const { state, values } = this;
|
|
101
166
|
const { length } = data;
|
|
102
167
|
for (let index = 0; index < length; index += 1) {
|
|
103
168
|
const object = data[index];
|
|
104
|
-
const key = object[
|
|
169
|
+
const key = object[state.key];
|
|
105
170
|
const value = values.objects.mapped.get(key);
|
|
106
171
|
if (value != null) {
|
|
107
172
|
values.objects.mapped.set(key, {
|
|
108
173
|
...value,
|
|
109
174
|
...object
|
|
110
175
|
});
|
|
111
|
-
managers.row.update(key);
|
|
176
|
+
state.managers.row.update(key);
|
|
112
177
|
}
|
|
113
178
|
}
|
|
114
179
|
}
|
|
@@ -1,34 +1,53 @@
|
|
|
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 "group":
|
|
26
|
+
manager.state.managers.group.handle(target);
|
|
27
|
+
break;
|
|
28
|
+
case "heading":
|
|
29
|
+
manager.onSort(event, target);
|
|
30
|
+
break;
|
|
31
|
+
case "row":
|
|
32
|
+
manager.state.managers.selection.handle(event, target);
|
|
33
|
+
break;
|
|
34
|
+
default: break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function onKeydown(event) {
|
|
38
|
+
const target = findAncestor(event, "[data-event]");
|
|
39
|
+
const table = findAncestor(event, ".tabela");
|
|
40
|
+
if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
|
|
41
|
+
const manager = mapped.get(table);
|
|
42
|
+
if (manager == null) return;
|
|
43
|
+
switch (target?.getAttribute("data-event")) {
|
|
44
|
+
case "body":
|
|
45
|
+
manager.state.managers.navigation.handle(event);
|
|
46
|
+
break;
|
|
47
|
+
default: break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
var mapped = /* @__PURE__ */ new WeakMap();
|
|
51
|
+
on(document, "click", onClick);
|
|
52
|
+
on(document, "keydown", onKeydown, { passive: false });
|
|
34
53
|
export { EventManager };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GroupComponent } from "../components/group.component.js";
|
|
1
2
|
import { getNumber } from "@oscarpalmer/atoms/number";
|
|
2
3
|
import { getString } from "@oscarpalmer/atoms/string";
|
|
3
4
|
import { endsWith, includes, startsWith } from "@oscarpalmer/atoms/string/match";
|
|
@@ -10,8 +11,8 @@ var FilterManager = class {
|
|
|
10
11
|
set: (items) => this.set(items)
|
|
11
12
|
});
|
|
12
13
|
items = {};
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
14
|
+
constructor(state) {
|
|
15
|
+
this.state = state;
|
|
15
16
|
}
|
|
16
17
|
add(item) {
|
|
17
18
|
if (this.items[item.field] == null) this.items[item.field] = [];
|
|
@@ -27,16 +28,21 @@ var FilterManager = class {
|
|
|
27
28
|
}
|
|
28
29
|
destroy() {
|
|
29
30
|
this.handlers = void 0;
|
|
30
|
-
this.items =
|
|
31
|
+
this.items = void 0;
|
|
32
|
+
this.state = void 0;
|
|
31
33
|
}
|
|
32
34
|
filter() {
|
|
33
|
-
const {
|
|
35
|
+
const { state } = this;
|
|
34
36
|
const filtered = [];
|
|
35
37
|
const filters = Object.entries(this.items);
|
|
36
|
-
const keysLength = managers.data.values.keys.original.length;
|
|
38
|
+
const keysLength = state.managers.data.values.keys.original.length;
|
|
37
39
|
rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
38
|
-
const key = managers.data.values.keys.original[keyIndex];
|
|
39
|
-
|
|
40
|
+
const key = state.managers.data.values.keys.original[keyIndex];
|
|
41
|
+
if (key instanceof GroupComponent) {
|
|
42
|
+
filtered.push(key);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const row = state.managers.data.values.objects.mapped.get(key);
|
|
40
46
|
if (row == null) continue;
|
|
41
47
|
filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
|
|
42
48
|
const [field, items] = filters[filterIndex];
|
|
@@ -49,9 +55,9 @@ var FilterManager = class {
|
|
|
49
55
|
}
|
|
50
56
|
filtered.push(key);
|
|
51
57
|
}
|
|
52
|
-
managers.data.values.keys.active = filtered;
|
|
53
|
-
if (managers.sort.items.length > 0) managers.sort.sort();
|
|
54
|
-
else managers.render.update(true, true);
|
|
58
|
+
state.managers.data.values.keys.active = filtered;
|
|
59
|
+
if (state.managers.sort.items.length > 0) state.managers.sort.sort();
|
|
60
|
+
else state.managers.render.update(true, true);
|
|
55
61
|
}
|
|
56
62
|
remove(value) {
|
|
57
63
|
if (typeof value === "string") {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { sort } from "@oscarpalmer/atoms/array";
|
|
2
|
+
import { toRecord } from "@oscarpalmer/atoms/array/to-record";
|
|
3
|
+
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
4
|
+
var GroupManager = class {
|
|
5
|
+
collapsed = /* @__PURE__ */ new Set();
|
|
6
|
+
enabled = false;
|
|
7
|
+
field;
|
|
8
|
+
items = [];
|
|
9
|
+
order = {};
|
|
10
|
+
constructor(state) {
|
|
11
|
+
this.state = state;
|
|
12
|
+
if (isNullableOrWhitespace(state.options.grouping)) return;
|
|
13
|
+
this.enabled = true;
|
|
14
|
+
this.field = state.options.grouping;
|
|
15
|
+
}
|
|
16
|
+
add(group) {
|
|
17
|
+
this.set([...this.items, group]);
|
|
18
|
+
}
|
|
19
|
+
get(value) {
|
|
20
|
+
return this.items.find((item) => item.value === value);
|
|
21
|
+
}
|
|
22
|
+
handle(button) {
|
|
23
|
+
const key = button.dataset.key;
|
|
24
|
+
const group = this.get(key);
|
|
25
|
+
if (group == null) return;
|
|
26
|
+
const { collapsed, items, state } = this;
|
|
27
|
+
group.expanded = !group.expanded;
|
|
28
|
+
const index = items.indexOf(group);
|
|
29
|
+
let first = state.managers.data.values.keys.original.indexOf(items[index]) + 1;
|
|
30
|
+
const last = items[index + 1] == null ? state.managers.data.keys.length - 1 : state.managers.data.values.keys.original.indexOf(items[index + 1]) - 1;
|
|
31
|
+
for (; first <= last; first += 1) {
|
|
32
|
+
const key = state.managers.data.values.keys.original[first];
|
|
33
|
+
if (group.expanded) collapsed.delete(key);
|
|
34
|
+
else collapsed.add(key);
|
|
35
|
+
}
|
|
36
|
+
state.managers.render.update(true, true);
|
|
37
|
+
}
|
|
38
|
+
remove(group) {
|
|
39
|
+
this.set(this.items.filter((item) => item !== group));
|
|
40
|
+
}
|
|
41
|
+
set(items) {
|
|
42
|
+
this.items = sort(items, (item) => item.label);
|
|
43
|
+
this.order = toRecord(items, "value", (_, index) => index);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export { GroupManager };
|
|
@@ -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;
|
|
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 };
|