@oscarpalmer/tabela 0.11.0 → 0.13.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/body.component-_VDOpJhV.d.mts +10 -0
- package/dist/body.model-2iwsovAV.d.mts +7 -0
- package/dist/column.component-Bx46r3JI.d.mts +16 -0
- package/dist/column.model-D-aw4EU4.d.mts +16 -0
- package/dist/components/body.component.d.mts +2 -0
- package/dist/components/{body.component.js → body.component.mjs} +6 -3
- package/dist/components/column.component.d.mts +2 -0
- package/dist/components/{column.component.js → column.component.mjs} +12 -9
- package/dist/components/footer.component.d.mts +2 -0
- package/dist/components/{footer.component.js → footer.component.mjs} +7 -4
- package/dist/components/group.component.d.mts +2 -0
- package/dist/components/group.component.mjs +51 -0
- package/dist/components/header.component.d.mts +2 -0
- package/dist/components/{header.component.js → header.component.mjs} +6 -3
- package/dist/components/row.component.d.mts +2 -0
- package/dist/components/{row.component.js → row.component.mjs} +11 -7
- package/dist/filter.model-7ukJrtil.d.mts +16 -0
- package/dist/footer.component-Curiab8j.d.mts +12 -0
- package/dist/footer.model-DhqoS6ds.d.mts +8 -0
- package/dist/group.component-Cq1YYbfJ.d.mts +285 -0
- package/dist/group.model-BsKFwHbt.d.mts +10 -0
- package/dist/header.component-BjjlpZIg.d.mts +12 -0
- package/dist/header.model-DN_KzUCV.d.mts +7 -0
- package/dist/helpers/dom.helpers.d.mts +12 -0
- package/dist/helpers/{dom.helpers.js → dom.helpers.mjs} +14 -10
- package/dist/helpers/misc.helpers.d.mts +6 -0
- package/dist/helpers/{misc.helpers.js → misc.helpers.mjs} +3 -1
- package/dist/helpers/style.helper.d.mts +6 -0
- package/dist/helpers/style.helper.mjs +8 -0
- package/dist/index.d.mts +7 -0
- package/dist/{index.js → index.mjs} +3 -1
- package/dist/managers/column.manager.d.mts +2 -0
- package/dist/managers/{column.manager.js → column.manager.mjs} +6 -1
- package/dist/managers/data.manager.d.mts +2 -0
- package/dist/managers/data.manager.mjs +222 -0
- package/dist/managers/event.manager.d.mts +2 -0
- package/dist/managers/{event.manager.js → event.manager.mjs} +12 -8
- package/dist/managers/filter.manager.d.mts +2 -0
- package/dist/managers/{filter.manager.js → filter.manager.mjs} +25 -11
- package/dist/managers/group.manager.d.mts +2 -0
- package/dist/managers/group.manager.mjs +73 -0
- package/dist/managers/navigation.manager.d.mts +2 -0
- package/dist/managers/{navigation.manager.js → navigation.manager.mjs} +27 -24
- package/dist/managers/render.manager.d.mts +2 -0
- package/dist/managers/render.manager.mjs +144 -0
- package/dist/managers/row.manager.d.mts +2 -0
- package/dist/managers/{row.manager.js → row.manager.mjs} +18 -11
- package/dist/managers/selection.manager.d.mts +2 -0
- package/dist/managers/{selection.manager.js → selection.manager.mjs} +57 -48
- package/dist/managers/sort.manager.d.mts +2 -0
- package/dist/managers/{sort.manager.js → sort.manager.mjs} +32 -2
- package/dist/managers/style.manager.d.mts +2 -0
- package/dist/managers/style.manager.mjs +149 -0
- package/dist/models/body.model.d.mts +2 -0
- package/dist/models/body.model.mjs +1 -0
- package/dist/models/column.model.d.mts +2 -0
- package/dist/models/column.model.mjs +1 -0
- package/dist/models/data.model.d.mts +2 -0
- package/dist/models/data.model.mjs +1 -0
- package/dist/models/filter.model.d.mts +2 -0
- package/dist/models/filter.model.mjs +1 -0
- package/dist/models/footer.model.d.mts +2 -0
- package/dist/models/footer.model.mjs +1 -0
- package/dist/models/group.model.d.mts +2 -0
- package/dist/models/group.model.mjs +1 -0
- package/dist/models/header.model.d.mts +2 -0
- package/dist/models/header.model.mjs +1 -0
- package/dist/models/render.model.d.mts +2 -0
- package/dist/models/render.model.mjs +1 -0
- package/dist/models/selection.model.d.mts +2 -0
- package/dist/models/selection.model.mjs +1 -0
- package/dist/models/sort.model.d.mts +2 -0
- package/dist/models/sort.model.mjs +1 -0
- package/dist/models/style.model.d.mts +23 -0
- package/dist/models/style.model.mjs +23 -0
- package/dist/models/tabela.model.d.mts +2 -0
- package/dist/models/tabela.model.mjs +1 -0
- package/dist/models/tabela.options.d.mts +2 -0
- package/dist/models/tabela.options.mjs +1 -0
- package/dist/selection.model-rwQe9fco.d.mts +12 -0
- package/dist/sort.model-CauImaLu.d.mts +15 -0
- package/dist/tabela.d.mts +21 -0
- package/dist/{tabela.full.js → tabela.full.mjs} +1407 -1124
- package/dist/tabela.mjs +126 -0
- package/dist/tabela.options-RkZvfptB.d.mts +14 -0
- package/package.json +45 -37
- package/src/components/body.component.ts +4 -3
- package/src/components/column.component.ts +19 -24
- package/src/components/footer.component.ts +8 -3
- package/src/components/group.component.ts +85 -0
- package/src/components/header.component.ts +3 -2
- package/src/components/row.component.ts +10 -8
- package/src/helpers/dom.helpers.ts +24 -20
- package/src/helpers/style.helper.ts +1 -1
- package/src/managers/column.manager.ts +8 -4
- package/src/managers/data.manager.ts +265 -61
- package/src/managers/event.manager.ts +14 -11
- package/src/managers/filter.manager.ts +38 -19
- package/src/managers/group.manager.ts +131 -0
- package/src/managers/navigation.manager.ts +25 -23
- package/src/managers/render.manager.ts +84 -32
- package/src/managers/row.manager.ts +23 -11
- package/src/managers/selection.manager.ts +68 -54
- package/src/managers/sort.manager.ts +81 -16
- package/src/managers/style.manager.ts +156 -0
- package/src/models/column.model.ts +2 -2
- package/src/models/data.model.ts +23 -9
- package/src/models/filter.model.ts +11 -3
- package/src/models/group.model.ts +8 -0
- package/src/models/render.model.ts +2 -2
- package/src/models/selection.model.ts +9 -0
- package/src/models/sort.model.ts +11 -3
- package/src/models/style.model.ts +39 -0
- package/src/models/tabela.model.ts +14 -46
- package/src/models/tabela.options.ts +3 -2
- package/src/tabela.ts +72 -41
- package/dist/helpers/style.helper.js +0 -6
- package/dist/managers/data.manager.js +0 -120
- package/dist/managers/render.manager.js +0 -110
- package/dist/models/body.model.js +0 -0
- package/dist/models/column.model.js +0 -0
- package/dist/models/data.model.js +0 -0
- package/dist/models/filter.model.js +0 -0
- package/dist/models/footer.model.js +0 -0
- package/dist/models/header.model.js +0 -0
- package/dist/models/render.model.js +0 -0
- package/dist/models/sort.model.js +0 -0
- package/dist/models/tabela.model.js +0 -0
- package/dist/models/tabela.options.js +0 -0
- package/dist/tabela.js +0 -102
- package/types/components/body.component.d.ts +0 -6
- package/types/components/column.component.d.ts +0 -13
- package/types/components/footer.component.d.ts +0 -8
- package/types/components/header.component.d.ts +0 -8
- package/types/components/row.component.d.ts +0 -11
- package/types/helpers/dom.helpers.d.ts +0 -10
- package/types/helpers/misc.helpers.d.ts +0 -2
- package/types/helpers/style.helper.d.ts +0 -1
- package/types/index.d.ts +0 -4
- package/types/managers/column.manager.d.ts +0 -12
- package/types/managers/data.manager.d.ts +0 -27
- package/types/managers/event.manager.d.ts +0 -7
- package/types/managers/filter.manager.d.ts +0 -19
- package/types/managers/navigation.manager.d.ts +0 -10
- package/types/managers/render.manager.d.ts +0 -16
- package/types/managers/row.manager.d.ts +0 -13
- package/types/managers/selection.manager.d.ts +0 -18
- package/types/managers/sort.manager.d.ts +0 -26
- package/types/models/body.model.d.ts +0 -4
- package/types/models/column.model.d.ts +0 -13
- package/types/models/data.model.d.ts +0 -14
- package/types/models/filter.model.d.ts +0 -6
- package/types/models/footer.model.d.ts +0 -5
- package/types/models/header.model.d.ts +0 -4
- package/types/models/render.model.d.ts +0 -13
- package/types/models/sort.model.d.ts +0 -5
- package/types/models/tabela.model.d.ts +0 -69
- package/types/models/tabela.options.d.ts +0 -9
- package/types/tabela.d.ts +0 -12
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {chunk, select, sort} from '@oscarpalmer/atoms/array';
|
|
2
2
|
import {toMap} from '@oscarpalmer/atoms/array/to-map';
|
|
3
|
+
import {toRecord} from '@oscarpalmer/atoms/array/to-record';
|
|
3
4
|
import {isPlainObject} from '@oscarpalmer/atoms/is';
|
|
4
5
|
import type {Key, PlainObject} from '@oscarpalmer/atoms/models';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
6
|
+
import {delay} from '@oscarpalmer/atoms/promise/delay';
|
|
7
|
+
import {getValue} from '@oscarpalmer/atoms/value/handle';
|
|
8
|
+
import {GroupComponent, updateGroup} from '../components/group.component';
|
|
9
|
+
import type {DataItem, DataState, TabelaData} from '../models/data.model';
|
|
10
|
+
import type {State} from '../models/tabela.model';
|
|
11
|
+
import {sortWithGroups} from './sort.manager';
|
|
12
|
+
import type {ColumnComponent} from '../components/column.component';
|
|
7
13
|
|
|
8
14
|
export class DataManager {
|
|
9
15
|
handlers = Object.freeze({
|
|
@@ -15,127 +21,322 @@ export class DataManager {
|
|
|
15
21
|
update: data => void this.update(data),
|
|
16
22
|
} satisfies TabelaData);
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
mapped: new Map(),
|
|
24
|
-
array: [],
|
|
25
|
-
},
|
|
26
|
-
};
|
|
24
|
+
state: DataState;
|
|
25
|
+
|
|
26
|
+
get items(): DataItem[] {
|
|
27
|
+
return this.state.items.active ?? this.state.items.original;
|
|
28
|
+
}
|
|
27
29
|
|
|
28
30
|
get size(): number {
|
|
29
|
-
return this.
|
|
31
|
+
return this.items.length;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
constructor(
|
|
34
|
+
constructor(state: State) {
|
|
35
|
+
this.state = {
|
|
36
|
+
...state,
|
|
37
|
+
items: {
|
|
38
|
+
original: [],
|
|
39
|
+
},
|
|
40
|
+
values: {
|
|
41
|
+
array: [],
|
|
42
|
+
mapped: new Map(),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
33
46
|
|
|
34
47
|
async add(data: PlainObject[], render: boolean): Promise<void> {
|
|
35
|
-
const {state
|
|
48
|
+
const {state} = this;
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
const groups: GroupComponent[] = [];
|
|
51
|
+
const updates: PlainObject[] = [];
|
|
38
52
|
|
|
39
|
-
|
|
53
|
+
let groupColumn: ColumnComponent | undefined;
|
|
54
|
+
let {length} = data;
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
for (let index = 0; index < length; index += 1) {
|
|
57
|
+
const item = data[index];
|
|
58
|
+
const key = getValue(item, state.key) as Key;
|
|
59
|
+
|
|
60
|
+
if (state.values.mapped.has(key)) {
|
|
61
|
+
updates.push(item);
|
|
62
|
+
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
state.values.array.push(item);
|
|
67
|
+
state.values.mapped.set(key, item);
|
|
68
|
+
|
|
69
|
+
if (!state.managers.group.enabled) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const groupValue = getValue(item, state.managers.group.field) as unknown;
|
|
74
|
+
|
|
75
|
+
let group = state.managers.group.get(groupValue);
|
|
76
|
+
|
|
77
|
+
if (group == null) {
|
|
78
|
+
groupColumn ??= state.managers.column.get(state.managers.group.field);
|
|
79
|
+
|
|
80
|
+
group = new GroupComponent(
|
|
81
|
+
`${groupColumn?.options.title ?? state.managers.group.field}: ${groupValue}`,
|
|
82
|
+
groupValue,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
state.values.array.push(group);
|
|
86
|
+
state.managers.group.add(group);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!group.expanded) {
|
|
90
|
+
state.managers.group.collapsed.add(key);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
group.total += 1;
|
|
94
|
+
|
|
95
|
+
groups.push(group);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
length = groups.length;
|
|
99
|
+
|
|
100
|
+
for (let index = 0; index < length; index += 1) {
|
|
101
|
+
updateGroup(state, groups[index]);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (updates.length > 0) {
|
|
105
|
+
void this.update(updates);
|
|
106
|
+
} else if (render) {
|
|
42
107
|
this.render();
|
|
43
108
|
}
|
|
44
109
|
}
|
|
45
110
|
|
|
46
111
|
clear(): void {
|
|
47
|
-
if (this.values.
|
|
48
|
-
this.
|
|
112
|
+
if (this.state.values.array.length > 0) {
|
|
113
|
+
void this.removeItems([], true, true);
|
|
49
114
|
}
|
|
50
115
|
}
|
|
51
116
|
|
|
52
117
|
destroy(): void {
|
|
53
|
-
const {
|
|
118
|
+
const {state} = this;
|
|
54
119
|
|
|
55
|
-
values.
|
|
120
|
+
state.values.mapped.clear();
|
|
56
121
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
values.
|
|
122
|
+
state.items.active = undefined;
|
|
123
|
+
state.items.original.length = 0;
|
|
124
|
+
state.values.array.length = 0;
|
|
60
125
|
|
|
61
126
|
this.handlers = undefined as never;
|
|
62
127
|
this.state = undefined as never;
|
|
63
|
-
this.values = undefined as never;
|
|
64
128
|
}
|
|
65
129
|
|
|
66
130
|
get(active?: boolean): PlainObject[] {
|
|
67
|
-
const {
|
|
131
|
+
const {state} = this;
|
|
68
132
|
|
|
69
133
|
return (active ?? false)
|
|
70
|
-
? (
|
|
71
|
-
|
|
134
|
+
? select(
|
|
135
|
+
state.items.active ?? [],
|
|
136
|
+
key => !(key instanceof GroupComponent),
|
|
137
|
+
key => state.values.mapped.get(key as Key)!,
|
|
138
|
+
)
|
|
139
|
+
: (state.values.array.filter(item => !(item instanceof GroupComponent)) as PlainObject[]);
|
|
72
140
|
}
|
|
73
141
|
|
|
74
|
-
getIndex(
|
|
75
|
-
|
|
142
|
+
getIndex(item: DataItem): number {
|
|
143
|
+
if (item instanceof GroupComponent) {
|
|
144
|
+
return this.items.indexOf(item);
|
|
145
|
+
}
|
|
76
146
|
|
|
77
|
-
return
|
|
147
|
+
return this.items.findIndex(value =>
|
|
148
|
+
value instanceof GroupComponent ? value.key === item : value === item,
|
|
149
|
+
);
|
|
78
150
|
}
|
|
79
151
|
|
|
80
152
|
async remove(items: Array<Key | PlainObject>, render: boolean): Promise<void> {
|
|
81
|
-
const {state
|
|
153
|
+
const {state} = this;
|
|
82
154
|
|
|
83
|
-
const keys = items
|
|
84
|
-
|
|
85
|
-
|
|
155
|
+
const keys = items.map(
|
|
156
|
+
value => (isPlainObject(value) ? getValue(value, state.key) : value) as Key,
|
|
157
|
+
);
|
|
86
158
|
|
|
87
159
|
const {length} = keys;
|
|
88
160
|
|
|
89
|
-
if (length
|
|
90
|
-
return;
|
|
161
|
+
if (length > 0) {
|
|
162
|
+
return this.removeItems(keys, false, render === true);
|
|
91
163
|
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async removeItems(items: DataItem[], clear: boolean, render: boolean): Promise<void> {
|
|
167
|
+
const {state} = this;
|
|
92
168
|
|
|
93
|
-
|
|
94
|
-
|
|
169
|
+
if (clear) {
|
|
170
|
+
state.items.active = undefined;
|
|
171
|
+
state.items.original = [];
|
|
172
|
+
state.values.array = [];
|
|
95
173
|
|
|
96
|
-
values.
|
|
174
|
+
state.values.mapped.clear();
|
|
97
175
|
|
|
98
|
-
|
|
176
|
+
state.managers.row.clear();
|
|
99
177
|
|
|
100
|
-
if (
|
|
101
|
-
|
|
178
|
+
if (state.managers.group.enabled) {
|
|
179
|
+
state.managers.group.clear();
|
|
102
180
|
}
|
|
103
181
|
|
|
104
|
-
|
|
182
|
+
return this.render();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const groups: GroupComponent[] = [];
|
|
186
|
+
|
|
187
|
+
const chunked = chunk(items);
|
|
188
|
+
const chunkedLength = chunked.length;
|
|
189
|
+
|
|
190
|
+
for (let chunkedIndex = 0; chunkedIndex < chunkedLength; chunkedIndex += 1) {
|
|
191
|
+
const chunk = chunked[chunkedIndex];
|
|
192
|
+
const chunkLength = chunk.length;
|
|
193
|
+
|
|
194
|
+
for (let itemIndex = 0; itemIndex < chunkLength; itemIndex += 1) {
|
|
195
|
+
const item = chunk[itemIndex];
|
|
196
|
+
const dataIndex = state.items.original.indexOf(item);
|
|
197
|
+
|
|
198
|
+
let dataValue: PlainObject | undefined;
|
|
199
|
+
|
|
200
|
+
[dataValue] = state.values.array.splice(dataIndex, 1) as PlainObject[];
|
|
105
201
|
|
|
106
|
-
|
|
202
|
+
state.items.original.splice(dataIndex, 1);
|
|
203
|
+
state.managers.row.remove(item as never);
|
|
204
|
+
state.values.mapped.delete(item as Key);
|
|
205
|
+
|
|
206
|
+
if (!state.managers.group.enabled || item instanceof GroupComponent) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
state.managers.group.collapsed.delete(item as never);
|
|
211
|
+
|
|
212
|
+
const groupKey = getValue(dataValue, state.managers.group.field) as unknown;
|
|
213
|
+
|
|
214
|
+
const group = state.managers.group.get(groupKey);
|
|
215
|
+
|
|
216
|
+
if (group == null) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
group.total -= 1;
|
|
221
|
+
|
|
222
|
+
if (group.total > 0) {
|
|
223
|
+
groups.push(group);
|
|
224
|
+
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let groupIndex = groups.indexOf(group);
|
|
229
|
+
|
|
230
|
+
if (groupIndex > -1) {
|
|
231
|
+
groups.splice(groupIndex, 1);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
groupIndex = state.values.array.indexOf(group);
|
|
235
|
+
|
|
236
|
+
if (groupIndex > -1) {
|
|
237
|
+
state.items.original.splice(groupIndex, 1);
|
|
238
|
+
state.values.array.splice(groupIndex, 1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
state.managers.group.remove(group);
|
|
242
|
+
|
|
243
|
+
if (items.length >= 10_000) {
|
|
244
|
+
await delay(25);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const {length} = groups;
|
|
250
|
+
|
|
251
|
+
for (let index = 0; index < length; index += 1) {
|
|
252
|
+
updateGroup(state, groups[index]);
|
|
107
253
|
}
|
|
108
254
|
|
|
109
255
|
if (render) {
|
|
110
|
-
this.render();
|
|
256
|
+
return this.render();
|
|
111
257
|
}
|
|
112
258
|
}
|
|
113
259
|
|
|
114
260
|
render(): void {
|
|
115
|
-
const {state
|
|
261
|
+
const {state} = this;
|
|
262
|
+
|
|
263
|
+
if (state.managers.group.enabled) {
|
|
264
|
+
sortWithGroups(state, state.values.array, [
|
|
265
|
+
{
|
|
266
|
+
direction: 'ascending',
|
|
267
|
+
key: state.key,
|
|
268
|
+
},
|
|
269
|
+
]);
|
|
270
|
+
} else {
|
|
271
|
+
sort(state.values.array as PlainObject[], [
|
|
272
|
+
{
|
|
273
|
+
direction: 'ascending',
|
|
274
|
+
key: state.key,
|
|
275
|
+
},
|
|
276
|
+
]);
|
|
277
|
+
}
|
|
116
278
|
|
|
117
|
-
|
|
279
|
+
state.items.original = state.values.array.map(item =>
|
|
280
|
+
item instanceof GroupComponent ? item : (getValue(item, state.key) as Key),
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
state.values.mapped = toMap(
|
|
284
|
+
state.values.array.filter(item => !(item instanceof GroupComponent)) as PlainObject[],
|
|
285
|
+
item => getValue(item, state.key) as Key,
|
|
286
|
+
);
|
|
118
287
|
|
|
119
288
|
if (Object.keys(state.managers.filter.items).length > 0) {
|
|
120
289
|
state.managers.filter.filter();
|
|
121
290
|
} else if (state.managers.sort.items.length > 0) {
|
|
122
291
|
state.managers.sort.sort();
|
|
123
292
|
} else {
|
|
124
|
-
state.managers.render.update(true);
|
|
293
|
+
state.managers.render.update(true, true);
|
|
125
294
|
}
|
|
126
295
|
}
|
|
127
296
|
|
|
128
297
|
set(data: PlainObject[]): void {
|
|
129
|
-
const {state
|
|
298
|
+
const {state} = this;
|
|
299
|
+
|
|
300
|
+
const array: Array<GroupComponent | PlainObject> = data.slice();
|
|
301
|
+
|
|
302
|
+
if (state.managers.group.enabled) {
|
|
303
|
+
const column = state.managers.column.get(state.managers.group.field);
|
|
304
|
+
|
|
305
|
+
const grouped = toRecord.arrays(data, state.managers.group.field) as Record<
|
|
306
|
+
string,
|
|
307
|
+
PlainObject[]
|
|
308
|
+
>;
|
|
309
|
+
|
|
310
|
+
const entries = Object.entries(grouped);
|
|
311
|
+
const {length} = entries;
|
|
312
|
+
|
|
313
|
+
const groups: GroupComponent[] = [];
|
|
130
314
|
|
|
131
|
-
|
|
132
|
-
|
|
315
|
+
for (let index = 0; index < length; index += 1) {
|
|
316
|
+
const [value, items] = entries[index];
|
|
317
|
+
|
|
318
|
+
const group = new GroupComponent(
|
|
319
|
+
`${column?.options.title ?? state.managers.group.field}: ${value}`,
|
|
320
|
+
value,
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
group.total = items.length;
|
|
324
|
+
|
|
325
|
+
groups.push(group);
|
|
326
|
+
|
|
327
|
+
array.push(group);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
state.managers.group.set(groups);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
state.values.array = array;
|
|
133
334
|
|
|
134
335
|
this.render();
|
|
135
336
|
}
|
|
136
337
|
|
|
137
338
|
async synchronize(data: PlainObject[], remove?: boolean): Promise<void> {
|
|
138
|
-
const {state
|
|
339
|
+
const {state} = this;
|
|
139
340
|
|
|
140
341
|
const add: PlainObject[] = [];
|
|
141
342
|
const updated: PlainObject[] = [];
|
|
@@ -146,9 +347,9 @@ export class DataManager {
|
|
|
146
347
|
|
|
147
348
|
for (let index = 0; index < length; index += 1) {
|
|
148
349
|
const object = data[index];
|
|
149
|
-
const key = object
|
|
350
|
+
const key = getValue(object, state.key) as Key;
|
|
150
351
|
|
|
151
|
-
if (values.
|
|
352
|
+
if (state.values.mapped.has(key)) {
|
|
152
353
|
updated.push(object);
|
|
153
354
|
} else {
|
|
154
355
|
add.push(object);
|
|
@@ -162,7 +363,9 @@ export class DataManager {
|
|
|
162
363
|
}
|
|
163
364
|
|
|
164
365
|
if (remove ?? false) {
|
|
165
|
-
const toRemove =
|
|
366
|
+
const toRemove = state.items.original.filter(
|
|
367
|
+
key => !(key instanceof GroupComponent) && !keys.has(key),
|
|
368
|
+
) as Key[];
|
|
166
369
|
|
|
167
370
|
if (toRemove.length > 0) {
|
|
168
371
|
await this.remove(toRemove, false);
|
|
@@ -181,17 +384,18 @@ export class DataManager {
|
|
|
181
384
|
}
|
|
182
385
|
|
|
183
386
|
async update(data: PlainObject[]): Promise<void> {
|
|
184
|
-
const {state
|
|
387
|
+
const {state} = this;
|
|
185
388
|
|
|
186
389
|
const {length} = data;
|
|
187
390
|
|
|
188
391
|
for (let index = 0; index < length; index += 1) {
|
|
189
392
|
const object = data[index];
|
|
190
|
-
|
|
191
|
-
const
|
|
393
|
+
|
|
394
|
+
const key = getValue(object, state.key) as Key;
|
|
395
|
+
const value = state.values.mapped.get(key);
|
|
192
396
|
|
|
193
397
|
if (value != null) {
|
|
194
|
-
values.
|
|
398
|
+
state.values.mapped.set(key, {...value, ...object} as PlainObject);
|
|
195
399
|
|
|
196
400
|
state.managers.row.update(key);
|
|
197
401
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {on} from '@oscarpalmer/toretto/event';
|
|
2
2
|
import {findAncestor} from '@oscarpalmer/toretto/find';
|
|
3
|
-
import type {
|
|
3
|
+
import type {State} from '../models/tabela.model';
|
|
4
4
|
|
|
5
5
|
export class EventManager {
|
|
6
|
-
constructor(public state:
|
|
6
|
+
constructor(public state: State) {
|
|
7
7
|
mapped.set(state.element, this);
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -25,7 +25,7 @@ export class EventManager {
|
|
|
25
25
|
|
|
26
26
|
function onClick(event: MouseEvent): void {
|
|
27
27
|
const target = findAncestor(event, '[data-event]');
|
|
28
|
-
const table = findAncestor(event, '.
|
|
28
|
+
const table = findAncestor(event, '.tabela__table');
|
|
29
29
|
|
|
30
30
|
if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) {
|
|
31
31
|
return;
|
|
@@ -40,6 +40,10 @@ function onClick(event: MouseEvent): void {
|
|
|
40
40
|
const type = target?.getAttribute('data-event');
|
|
41
41
|
|
|
42
42
|
switch (type) {
|
|
43
|
+
case 'group':
|
|
44
|
+
manager.state.managers.group.handle(target);
|
|
45
|
+
break;
|
|
46
|
+
|
|
43
47
|
case 'heading':
|
|
44
48
|
manager.onSort(event, target);
|
|
45
49
|
break;
|
|
@@ -55,7 +59,7 @@ function onClick(event: MouseEvent): void {
|
|
|
55
59
|
|
|
56
60
|
function onKeydown(event: KeyboardEvent): void {
|
|
57
61
|
const target = findAncestor(event, '[data-event]');
|
|
58
|
-
const table = findAncestor(event, '.
|
|
62
|
+
const table = findAncestor(event, '.tabela__table');
|
|
59
63
|
|
|
60
64
|
if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) {
|
|
61
65
|
return;
|
|
@@ -67,16 +71,15 @@ function onKeydown(event: KeyboardEvent): void {
|
|
|
67
71
|
return;
|
|
68
72
|
}
|
|
69
73
|
|
|
70
|
-
|
|
74
|
+
if (event.key === ' ') {
|
|
75
|
+
event.preventDefault();
|
|
71
76
|
|
|
72
|
-
|
|
73
|
-
case 'body':
|
|
74
|
-
manager.state.managers.navigation.handle(event);
|
|
75
|
-
break;
|
|
77
|
+
// TODO: it's on the way
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
break;
|
|
79
|
+
return;
|
|
79
80
|
}
|
|
81
|
+
|
|
82
|
+
manager.state.managers.navigation.handle(event);
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
const mapped = new WeakMap<HTMLElement, EventManager>();
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type {Key} from '@oscarpalmer/atoms/models';
|
|
2
1
|
import {getNumber} from '@oscarpalmer/atoms/number';
|
|
3
2
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
4
3
|
import {endsWith, includes, startsWith} from '@oscarpalmer/atoms/string/match';
|
|
5
4
|
import {equal} from '@oscarpalmer/atoms/value/equal';
|
|
6
|
-
import
|
|
7
|
-
import type {
|
|
5
|
+
import {GroupComponent} from '../components/group.component';
|
|
6
|
+
import type {DataItem} from '../models/data.model';
|
|
7
|
+
import type {TabelaFilter, TabelaFilterComparison, TabelaFilterItem} from '../models/filter.model';
|
|
8
|
+
import type {State} from '../models/tabela.model';
|
|
8
9
|
|
|
9
10
|
export class FilterManager {
|
|
10
11
|
handlers = Object.freeze({
|
|
@@ -14,17 +15,17 @@ export class FilterManager {
|
|
|
14
15
|
set: items => this.set(items),
|
|
15
16
|
} satisfies TabelaFilter);
|
|
16
17
|
|
|
17
|
-
items: Record<string,
|
|
18
|
+
items: Record<string, TabelaFilterItem[]> = {};
|
|
18
19
|
|
|
19
|
-
constructor(public state:
|
|
20
|
+
constructor(public state: State) {}
|
|
20
21
|
|
|
21
|
-
add(item:
|
|
22
|
+
add(item: TabelaFilterItem): void {
|
|
22
23
|
if (this.items[item.field] == null) {
|
|
23
24
|
this.items[item.field] = [];
|
|
24
25
|
} else {
|
|
25
26
|
const index = this.items[item.field].findIndex(existing => equal(existing, item));
|
|
26
27
|
|
|
27
|
-
if (index
|
|
28
|
+
if (index > -1) {
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
31
|
}
|
|
@@ -51,14 +52,21 @@ export class FilterManager {
|
|
|
51
52
|
filter(): void {
|
|
52
53
|
const {state} = this;
|
|
53
54
|
|
|
54
|
-
const filtered:
|
|
55
|
+
const filtered: DataItem[] = [];
|
|
55
56
|
const filters = Object.entries(this.items);
|
|
56
57
|
|
|
57
|
-
const
|
|
58
|
+
const itemsLength = state.managers.data.state.items.original.length;
|
|
58
59
|
|
|
59
|
-
rowLoop: for (let
|
|
60
|
-
const
|
|
61
|
-
|
|
60
|
+
rowLoop: for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
|
|
61
|
+
const item = state.managers.data.state.items.original[itemIndex];
|
|
62
|
+
|
|
63
|
+
if (item instanceof GroupComponent) {
|
|
64
|
+
filtered.push(item);
|
|
65
|
+
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const row = state.managers.data.state.values.mapped.get(item);
|
|
62
70
|
|
|
63
71
|
if (row == null) {
|
|
64
72
|
continue;
|
|
@@ -80,10 +88,10 @@ export class FilterManager {
|
|
|
80
88
|
continue rowLoop;
|
|
81
89
|
}
|
|
82
90
|
|
|
83
|
-
filtered.push(
|
|
91
|
+
filtered.push(item);
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
state.managers.data.
|
|
94
|
+
state.managers.data.state.items.active = filtered;
|
|
87
95
|
|
|
88
96
|
if (state.managers.sort.items.length > 0) {
|
|
89
97
|
state.managers.sort.sort();
|
|
@@ -92,13 +100,24 @@ export class FilterManager {
|
|
|
92
100
|
}
|
|
93
101
|
}
|
|
94
102
|
|
|
95
|
-
remove(value: string |
|
|
103
|
+
remove(value: string | TabelaFilterItem): void {
|
|
96
104
|
if (typeof value === 'string') {
|
|
97
105
|
if (this.items[value] == null) {
|
|
98
106
|
return;
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
const keyed: Record<string,
|
|
109
|
+
const keyed: Record<string, TabelaFilterItem[]> = {};
|
|
110
|
+
|
|
111
|
+
const filters = Object.keys(this.items);
|
|
112
|
+
const {length} = filters;
|
|
113
|
+
|
|
114
|
+
for (let index = 0; index < length; index += 1) {
|
|
115
|
+
const field = filters[index];
|
|
116
|
+
|
|
117
|
+
if (field !== value) {
|
|
118
|
+
keyed[field] = this.items[field];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
102
121
|
|
|
103
122
|
this.items = keyed;
|
|
104
123
|
} else {
|
|
@@ -118,8 +137,8 @@ export class FilterManager {
|
|
|
118
137
|
this.filter();
|
|
119
138
|
}
|
|
120
139
|
|
|
121
|
-
set(items:
|
|
122
|
-
const keyed: Record<string,
|
|
140
|
+
set(items: TabelaFilterItem[]): void {
|
|
141
|
+
const keyed: Record<string, TabelaFilterItem[]> = {};
|
|
123
142
|
|
|
124
143
|
const {length} = items;
|
|
125
144
|
|
|
@@ -137,7 +156,7 @@ export class FilterManager {
|
|
|
137
156
|
}
|
|
138
157
|
}
|
|
139
158
|
|
|
140
|
-
const comparators: Record<
|
|
159
|
+
const comparators: Record<TabelaFilterComparison, (row: unknown, filter: unknown) => boolean> = {
|
|
141
160
|
contains: (row, filter) => includes(getString(row), getString(filter), true),
|
|
142
161
|
'ends-with': (row, filter) => endsWith(getString(row), getString(filter), true),
|
|
143
162
|
equals: (row, filter) => equalizer(row, filter),
|