@oscarpalmer/tabela 0.14.0 → 0.15.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.
Files changed (126) hide show
  1. package/dist/components/body.component.d.mts +11 -0
  2. package/dist/components/body.component.mjs +28 -0
  3. package/dist/components/column.component.d.mts +16 -0
  4. package/dist/components/column.component.mjs +46 -0
  5. package/dist/components/footer.component.d.mts +13 -0
  6. package/dist/components/{footer.component.js → footer.component.mjs} +9 -6
  7. package/dist/components/group.component.d.mts +20 -0
  8. package/dist/components/group.component.mjs +57 -0
  9. package/dist/components/header.component.d.mts +13 -0
  10. package/dist/components/header.component.mjs +25 -0
  11. package/dist/components/row.component.d.mts +15 -0
  12. package/dist/components/row.component.mjs +56 -0
  13. package/dist/helpers/dom.helpers.d.mts +12 -0
  14. package/dist/helpers/dom.helpers.mjs +43 -0
  15. package/dist/helpers/misc.helpers.d.mts +12 -0
  16. package/dist/helpers/misc.helpers.mjs +20 -0
  17. package/dist/helpers/style.helper.d.mts +6 -0
  18. package/dist/helpers/style.helper.mjs +8 -0
  19. package/dist/index.d.mts +7 -0
  20. package/dist/{index.js → index.mjs} +3 -1
  21. package/dist/managers/column.manager.d.mts +17 -0
  22. package/dist/managers/{column.manager.js → column.manager.mjs} +11 -6
  23. package/dist/managers/data.manager.d.mts +27 -0
  24. package/dist/managers/data.manager.mjs +256 -0
  25. package/dist/managers/event.manager.d.mts +18 -0
  26. package/dist/managers/event.manager.mjs +79 -0
  27. package/dist/managers/filter.manager.d.mts +18 -0
  28. package/dist/managers/filter.manager.mjs +115 -0
  29. package/dist/managers/group.manager.d.mts +27 -0
  30. package/dist/managers/group.manager.mjs +93 -0
  31. package/dist/managers/navigation.manager.d.mts +15 -0
  32. package/dist/managers/navigation.manager.mjs +80 -0
  33. package/dist/managers/render.manager.d.mts +19 -0
  34. package/dist/managers/render.manager.mjs +157 -0
  35. package/dist/managers/row.manager.d.mts +19 -0
  36. package/dist/managers/row.manager.mjs +45 -0
  37. package/dist/managers/selection.manager.d.mts +23 -0
  38. package/dist/managers/{selection.manager.js → selection.manager.mjs} +38 -31
  39. package/dist/managers/sort.manager.d.mts +23 -0
  40. package/dist/managers/sort.manager.mjs +147 -0
  41. package/dist/managers/style.manager.d.mts +9 -0
  42. package/dist/managers/style.manager.mjs +181 -0
  43. package/dist/models/body.model.d.mts +7 -0
  44. package/dist/models/body.model.mjs +1 -0
  45. package/dist/models/column.model.d.mts +13 -0
  46. package/dist/models/column.model.mjs +1 -0
  47. package/dist/models/data.model.d.mts +28 -0
  48. package/dist/models/data.model.mjs +1 -0
  49. package/dist/models/dom.model.d.mts +19 -0
  50. package/dist/models/dom.model.mjs +19 -0
  51. package/dist/models/event.model.d.mts +99 -0
  52. package/dist/models/event.model.mjs +53 -0
  53. package/dist/models/filter.model.d.mts +26 -0
  54. package/dist/models/filter.model.mjs +13 -0
  55. package/dist/models/footer.model.d.mts +8 -0
  56. package/dist/models/footer.model.mjs +1 -0
  57. package/dist/models/group.model.d.mts +19 -0
  58. package/dist/models/group.model.mjs +5 -0
  59. package/dist/models/header.model.d.mts +7 -0
  60. package/dist/models/header.model.mjs +1 -0
  61. package/dist/models/render.model.d.mts +22 -0
  62. package/dist/models/render.model.mjs +1 -0
  63. package/dist/models/selection.model.d.mts +12 -0
  64. package/dist/models/selection.model.mjs +1 -0
  65. package/dist/models/sort.model.d.mts +19 -0
  66. package/dist/models/sort.model.mjs +5 -0
  67. package/dist/models/style.model.d.mts +29 -0
  68. package/dist/models/style.model.mjs +29 -0
  69. package/dist/models/tabela.model.d.mts +46 -0
  70. package/dist/models/tabela.model.mjs +1 -0
  71. package/dist/models/tabela.options.d.mts +14 -0
  72. package/dist/models/tabela.options.mjs +1 -0
  73. package/dist/tabela.d.mts +22 -0
  74. package/dist/{tabela.full.js → tabela.full.mjs} +1501 -803
  75. package/dist/tabela.mjs +126 -0
  76. package/package.json +2 -4
  77. package/src/components/column.component.ts +4 -4
  78. package/src/components/group.component.ts +6 -2
  79. package/src/components/row.component.ts +5 -5
  80. package/src/helpers/misc.helpers.ts +13 -1
  81. package/src/managers/column.manager.ts +9 -9
  82. package/src/managers/data.manager.ts +139 -53
  83. package/src/managers/event.manager.ts +52 -6
  84. package/src/managers/filter.manager.ts +36 -20
  85. package/src/managers/group.manager.ts +43 -10
  86. package/src/managers/render.manager.ts +30 -17
  87. package/src/managers/sort.manager.ts +81 -52
  88. package/src/managers/style.manager.ts +33 -0
  89. package/src/models/column.model.ts +2 -2
  90. package/src/models/data.model.ts +6 -6
  91. package/src/models/dom.model.ts +0 -2
  92. package/src/models/event.model.ts +168 -0
  93. package/src/models/filter.model.ts +2 -2
  94. package/src/models/group.model.ts +9 -0
  95. package/src/models/render.model.ts +6 -0
  96. package/src/models/sort.model.ts +7 -5
  97. package/src/tabela.ts +6 -2
  98. package/dist/components/body.component.js +0 -23
  99. package/dist/components/column.component.js +0 -41
  100. package/dist/components/group.component.js +0 -28
  101. package/dist/components/header.component.js +0 -22
  102. package/dist/components/row.component.js +0 -48
  103. package/dist/helpers/dom.helpers.js +0 -38
  104. package/dist/helpers/misc.helpers.js +0 -7
  105. package/dist/helpers/style.helper.js +0 -6
  106. package/dist/managers/data.manager.js +0 -181
  107. package/dist/managers/event.manager.js +0 -53
  108. package/dist/managers/filter.manager.js +0 -98
  109. package/dist/managers/group.manager.js +0 -46
  110. package/dist/managers/navigation.manager.js +0 -73
  111. package/dist/managers/render.manager.js +0 -135
  112. package/dist/managers/row.manager.js +0 -38
  113. package/dist/managers/sort.manager.js +0 -122
  114. package/dist/models/body.model.js +0 -0
  115. package/dist/models/column.model.js +0 -0
  116. package/dist/models/data.model.js +0 -0
  117. package/dist/models/filter.model.js +0 -0
  118. package/dist/models/footer.model.js +0 -0
  119. package/dist/models/group.model.js +0 -0
  120. package/dist/models/header.model.js +0 -0
  121. package/dist/models/render.model.js +0 -0
  122. package/dist/models/selection.model.js +0 -0
  123. package/dist/models/sort.model.js +0 -0
  124. package/dist/models/tabela.model.js +0 -0
  125. package/dist/models/tabela.options.js +0 -0
  126. package/dist/tabela.js +0 -105
@@ -7,20 +7,30 @@ import {delay} from '@oscarpalmer/atoms/promise/delay';
7
7
  import {getValue} from '@oscarpalmer/atoms/value/handle';
8
8
  import type {ColumnComponent} from '../components/column.component';
9
9
  import {GroupComponent, updateGroup} from '../components/group.component';
10
+ import {getGroup, isGroupKey} from '../helpers/misc.helpers';
10
11
  import type {DataState, DataValue, TabelaData} from '../models/data.model';
12
+ import {
13
+ EVENT_DATA_ADD,
14
+ EVENT_DATA_CLEAR,
15
+ EVENT_DATA_REMOVE,
16
+ EVENT_DATA_SYNCHRONIZE,
17
+ EVENT_DATA_UPDATE,
18
+ EVENT_GROUP_ADD,
19
+ EVENT_GROUP_REMOVE,
20
+ EVENT_GROUP_UPDATE,
21
+ } from '../models/event.model';
11
22
  import {SORT_ASCENDING} from '../models/sort.model';
12
23
  import type {State} from '../models/tabela.model';
13
24
  import {sortWithGroups} from './sort.manager';
14
- import {isGroupKey} from '../helpers/misc.helpers';
15
25
 
16
26
  export class DataManager {
17
27
  handlers: TabelaData = {
18
- add: data => void this.add(data, true),
28
+ add: data => this.add(data, true),
19
29
  clear: () => this.clear(),
20
30
  get: active => this.get(active),
21
- remove: items => void this.remove(items, true),
22
- synchronize: (data, remove) => void this.synchronize(data, remove === true),
23
- update: data => void this.update(data, true),
31
+ remove: items => this.remove(items, true),
32
+ synchronize: (data, remove) => this.synchronize(data, remove === true),
33
+ update: data => this.update(data, true),
24
34
  };
25
35
 
26
36
  state: DataState;
@@ -49,47 +59,52 @@ export class DataManager {
49
59
  async add(data: PlainObject[], render: boolean): Promise<void> {
50
60
  const {state} = this;
51
61
 
52
- const groups: GroupComponent[] = [];
53
- const updates: PlainObject[] = [];
62
+ const addedData: PlainObject[] = [];
63
+ const updatedData: PlainObject[] = [];
64
+
65
+ const addedGroups: GroupComponent[] = [];
66
+ const updatedGroups: GroupComponent[] = [];
54
67
 
55
68
  let groupColumn: ColumnComponent | undefined;
56
69
  let {length} = data;
57
70
 
58
- let added = 0;
59
-
60
71
  for (let index = 0; index < length; index += 1) {
61
72
  const item = data[index];
62
73
  const key = getValue(item, state.key) as Key;
63
74
 
64
75
  if (state.values.mapped.has(key)) {
65
- updates.push(item);
76
+ updatedData.push(item);
66
77
 
67
78
  continue;
68
79
  }
69
80
 
81
+ addedData.push(item);
82
+
70
83
  state.values.array.push(item);
71
84
  state.values.mapped.set(key, item);
72
85
 
73
- added += 1;
74
-
75
86
  if (!state.managers.group.enabled) {
76
87
  continue;
77
88
  }
78
89
 
79
- const groupValue = getValue(item, state.managers.group.field) as Key;
90
+ const groupValue = getValue(item, state.managers.group.key) as Key;
80
91
 
81
92
  let group = state.managers.group.getForValue(groupValue);
82
93
 
83
94
  if (group == null) {
84
- groupColumn ??= state.managers.column.get(state.managers.group.field);
95
+ groupColumn ??= state.managers.column.get(state.managers.group.key);
85
96
 
86
97
  group = new GroupComponent(
87
- `${groupColumn?.options.label ?? state.managers.group.field}: ${groupValue}`,
98
+ `${groupColumn?.options.label ?? state.managers.group.key}: ${groupValue}`,
88
99
  groupValue,
89
100
  );
90
101
 
91
102
  state.values.array.push(group.key);
92
- state.managers.group.add(group);
103
+ state.managers.group.add(group, false);
104
+
105
+ addedGroups.push(group);
106
+ } else if (!addedGroups.includes(group) && !updatedGroups.includes(group)) {
107
+ updatedGroups.push(group);
93
108
  }
94
109
 
95
110
  if (!group.expanded) {
@@ -97,26 +112,44 @@ export class DataManager {
97
112
  }
98
113
 
99
114
  group.total += 1;
115
+ }
100
116
 
101
- groups.push(group);
117
+ length = addedGroups.length;
118
+
119
+ if (length > 0) {
120
+ state.managers.event.emit(EVENT_GROUP_ADD, addedGroups.map(getGroup));
121
+
122
+ for (let index = 0; index < length; index += 1) {
123
+ updateGroup(state, addedGroups[index], false);
124
+ }
102
125
  }
103
126
 
104
- length = groups.length;
127
+ length = updatedGroups.length;
105
128
 
106
- for (let index = 0; index < length; index += 1) {
107
- updateGroup(state, groups[index]);
129
+ if (length > 0) {
130
+ for (let index = 0; index < length; index += 1) {
131
+ updateGroup(state, updatedGroups[index], false);
132
+ }
133
+
134
+ state.managers.event.emit(EVENT_GROUP_UPDATE, updatedGroups.map(getGroup));
108
135
  }
109
136
 
110
- await this.update(updates, added === 0);
137
+ await this.update(updatedData, addedData.length === 0);
138
+
139
+ if (addedData.length === 0) {
140
+ return;
141
+ }
111
142
 
112
- if (added > 0 && render) {
143
+ state.managers.event.emit(EVENT_DATA_ADD, addedData);
144
+
145
+ if (render) {
113
146
  this.render();
114
147
  }
115
148
  }
116
149
 
117
- clear(): void {
150
+ async clear(): Promise<void> {
118
151
  if (this.state.values.array.length > 0) {
119
- void this.removeItems([], true, true);
152
+ return this.removeItems([], true, true).then(() => undefined);
120
153
  }
121
154
  }
122
155
 
@@ -136,9 +169,9 @@ export class DataManager {
136
169
  get(active?: boolean): PlainObject[] {
137
170
  const {state} = this;
138
171
 
139
- return (active ?? false)
172
+ return (active ?? false) && state.keys.active != null
140
173
  ? select(
141
- state.keys.active ?? [],
174
+ state.keys.active,
142
175
  key => !isGroupKey(key),
143
176
  key => state.values.mapped.get(key as Key)!,
144
177
  )
@@ -149,7 +182,11 @@ export class DataManager {
149
182
  return this.keys.indexOf(item);
150
183
  }
151
184
 
152
- async remove(items: Array<Key | PlainObject>, render: boolean): Promise<void> {
185
+ async remove(items: Array<Key | PlainObject>, render: false): Promise<PlainObject[]>;
186
+
187
+ async remove(items: Array<Key | PlainObject>, render: true): Promise<void>;
188
+
189
+ async remove(items: Array<Key | PlainObject>, render: boolean): Promise<unknown> {
153
190
  const {state} = this;
154
191
 
155
192
  const keys = items
@@ -158,12 +195,18 @@ export class DataManager {
158
195
 
159
196
  const {length} = keys;
160
197
 
161
- if (length > 0) {
162
- return this.removeItems(keys, false, render === true);
163
- }
198
+ return length === 0
199
+ ? render
200
+ ? undefined
201
+ : []
202
+ : this.removeItems(keys, false, render as never);
164
203
  }
165
204
 
166
- async removeItems(keys: Key[], clear: boolean, render: boolean): Promise<void> {
205
+ async removeItems(data: Key[], clear: boolean, render: false): Promise<PlainObject[]>;
206
+
207
+ async removeItems(data: Key[], clear: boolean, render: true): Promise<void>;
208
+
209
+ async removeItems(keys: Key[], clear: boolean, render: boolean): Promise<unknown> {
167
210
  const {state} = this;
168
211
 
169
212
  if (clear) {
@@ -179,10 +222,17 @@ export class DataManager {
179
222
  state.managers.group.clear();
180
223
  }
181
224
 
182
- return this.render();
225
+ state.managers.event.emit(EVENT_DATA_CLEAR);
226
+
227
+ this.render();
228
+
229
+ return render ? undefined : [];
183
230
  }
184
231
 
185
- const groups: GroupComponent[] = [];
232
+ const removedGroups: GroupComponent[] = [];
233
+ const updatedGroups: GroupComponent[] = [];
234
+
235
+ const removedData: PlainObject[] = [];
186
236
 
187
237
  const chunked = chunk(keys);
188
238
  const chunkedLength = chunked.length;
@@ -199,6 +249,8 @@ export class DataManager {
199
249
 
200
250
  [dataValue] = state.values.array.splice(dataIndex, 1) as PlainObject[];
201
251
 
252
+ removedData.push(dataValue);
253
+
202
254
  state.keys.original.splice(dataIndex, 1);
203
255
  state.managers.row.remove(key as never);
204
256
  state.values.mapped.delete(key as Key);
@@ -209,7 +261,7 @@ export class DataManager {
209
261
 
210
262
  state.managers.group.collapsed.delete(key as never);
211
263
 
212
- const groupValue = getValue(dataValue, state.managers.group.field) as unknown;
264
+ const groupValue = getValue(dataValue, state.managers.group.key) as unknown;
213
265
 
214
266
  const group = state.managers.group.getForValue(groupValue);
215
267
 
@@ -220,15 +272,15 @@ export class DataManager {
220
272
  group.total -= 1;
221
273
 
222
274
  if (group.total > 0) {
223
- groups.push(group);
275
+ updatedGroups.push(group);
224
276
 
225
277
  continue;
226
278
  }
227
279
 
228
- let groupIndex = groups.indexOf(group);
280
+ let groupIndex = updatedGroups.indexOf(group);
229
281
 
230
282
  if (groupIndex > -1) {
231
- groups.splice(groupIndex, 1);
283
+ updatedGroups.splice(groupIndex, 1);
232
284
  }
233
285
 
234
286
  groupIndex = state.values.array.indexOf(group.key);
@@ -238,7 +290,9 @@ export class DataManager {
238
290
  state.values.array.splice(groupIndex, 1);
239
291
  }
240
292
 
241
- state.managers.group.remove(group);
293
+ removedGroups.push(group);
294
+
295
+ state.managers.group.remove(group, false);
242
296
 
243
297
  if (keys.length >= 10_000) {
244
298
  await delay(25);
@@ -246,15 +300,29 @@ export class DataManager {
246
300
  }
247
301
  }
248
302
 
249
- const {length} = groups;
303
+ let {length} = updatedGroups;
250
304
 
251
- for (let index = 0; index < length; index += 1) {
252
- updateGroup(state, groups[index]);
305
+ if (length > 0) {
306
+ for (let index = 0; index < length; index += 1) {
307
+ updateGroup(state, updatedGroups[index], false);
308
+ }
309
+
310
+ state.managers.event.emit(EVENT_GROUP_UPDATE, updatedGroups.map(getGroup));
253
311
  }
254
312
 
313
+ length = removedGroups.length;
314
+
315
+ if (length > 0) {
316
+ state.managers.event.emit(EVENT_GROUP_REMOVE, removedGroups.map(getGroup));
317
+ }
318
+
319
+ state.managers.event.emit(EVENT_DATA_REMOVE, removedData);
320
+
255
321
  if (render) {
256
- return this.render();
322
+ this.render();
257
323
  }
324
+
325
+ return render ? undefined : removedData;
258
326
  }
259
327
 
260
328
  render(): void {
@@ -276,6 +344,8 @@ export class DataManager {
276
344
  ]);
277
345
  }
278
346
 
347
+ state.keys.active = undefined;
348
+
279
349
  state.keys.original = state.values.array.map(item =>
280
350
  typeof item === 'string' ? item : (getValue(item, state.key) as Key),
281
351
  );
@@ -300,9 +370,9 @@ export class DataManager {
300
370
  const array: DataValue[] = data.slice();
301
371
 
302
372
  if (state.managers.group.enabled) {
303
- const column = state.managers.column.get(state.managers.group.field);
373
+ const column = state.managers.column.get(state.managers.group.key);
304
374
 
305
- const grouped = toRecord.arrays(data, state.managers.group.field) as Record<
375
+ const grouped = toRecord.arrays(data, state.managers.group.key) as Record<
306
376
  string,
307
377
  PlainObject[]
308
378
  >;
@@ -316,7 +386,7 @@ export class DataManager {
316
386
  const [value, items] = entries[index];
317
387
 
318
388
  const group = new GroupComponent(
319
- `${column?.options.label ?? state.managers.group.field}: ${value}`,
389
+ `${column?.options.label ?? state.managers.group.key}: ${value}`,
320
390
  value,
321
391
  );
322
392
 
@@ -362,13 +432,15 @@ export class DataManager {
362
432
  return;
363
433
  }
364
434
 
435
+ let removed: PlainObject[] = [];
436
+
365
437
  if (remove) {
366
438
  const toRemove = state.keys.original.filter(
367
439
  key => !isGroupKey(key) && !keys.has(key),
368
440
  ) as Key[];
369
441
 
370
442
  if (toRemove.length > 0) {
371
- await this.remove(toRemove, false);
443
+ removed = await this.remove(toRemove, false);
372
444
  }
373
445
  }
374
446
 
@@ -376,6 +448,12 @@ export class DataManager {
376
448
 
377
449
  await this.add(added, false);
378
450
 
451
+ state.managers.event.emit(EVENT_DATA_SYNCHRONIZE, {
452
+ added,
453
+ removed,
454
+ updated,
455
+ });
456
+
379
457
  if (added.length > 0 || remove) {
380
458
  this.render();
381
459
  }
@@ -386,22 +464,30 @@ export class DataManager {
386
464
 
387
465
  const {length} = data;
388
466
 
389
- for (let dataIndex = 0; dataIndex < length; dataIndex += 1) {
390
- const dataItem = data[dataIndex];
467
+ const updated: PlainObject[] = [];
468
+
469
+ for (let index = 0; index < length; index += 1) {
470
+ const item = data[index];
391
471
 
392
- const key = getValue(dataItem, state.key) as Key;
472
+ const key = getValue(item, state.key) as Key;
393
473
 
394
- const keyIndex = state.keys.original.indexOf(key);
474
+ const existing = state.keys.original.indexOf(key);
395
475
 
396
- if (keyIndex === -1) {
476
+ if (existing === -1) {
397
477
  continue;
398
478
  }
399
479
 
400
- Object.assign(state.values.array[keyIndex], dataItem);
480
+ Object.assign(state.values.array[existing], item);
401
481
 
402
- if (render) {
482
+ updated.push(state.values.array[existing] as PlainObject);
483
+
484
+ if (render && state.managers.render.visible.keys.has(key)) {
403
485
  state.managers.row.update(key);
404
486
  }
405
487
  }
488
+
489
+ if (updated.length > 0) {
490
+ state.managers.event.emit(EVENT_DATA_UPDATE, updated);
491
+ }
406
492
  }
407
493
  }
@@ -1,19 +1,49 @@
1
+ import type {GenericCallback} from '@oscarpalmer/atoms/models';
1
2
  import {on} from '@oscarpalmer/toretto/event';
2
3
  import {findAncestor} from '@oscarpalmer/toretto/find';
3
- import type {State} from '../models/tabela.model';
4
+ import {isEvent} from '../helpers/misc.helpers';
4
5
  import {
5
6
  ATTRIBUTE_DATA_EVENT,
6
- ATTRIBUTE_DATA_FIELD,
7
+ ATTRIBUTE_DATA_KEY,
7
8
  ATTRIBUTE_DATA_SORT_DIRECTION,
8
9
  } from '../models/dom.model';
10
+ import {
11
+ EVENT_GROUP,
12
+ EVENT_HEADING,
13
+ EVENT_ROW,
14
+ type EventMap,
15
+ type EventName,
16
+ type Events,
17
+ type TabelaEvents,
18
+ } from '../models/event.model';
9
19
  import {CSS_TABLE} from '../models/style.model';
10
- import {EVENT_GROUP, EVENT_HEADING, EVENT_ROW} from '../models/event.model';
20
+ import type {State} from '../models/tabela.model';
11
21
 
12
22
  export class EventManager {
23
+ events: Events = {};
24
+
25
+ handlers: TabelaEvents = {
26
+ subscribe: (name, callback) => this.subscribe(name, callback),
27
+ unsubscribe: (name, callback) => this.unsubscribe(name, callback),
28
+ };
29
+
13
30
  constructor(public state: State) {
14
31
  mapped.set(state.element, this);
15
32
  }
16
33
 
34
+ emit<Name extends EventName>(name: Name, ...parameters: Parameters<EventMap[Name]>): void {
35
+ if (this.events[name] == null) {
36
+ return;
37
+ }
38
+
39
+ const handlers = [...this.events[name]];
40
+ const {length} = handlers;
41
+
42
+ for (let index = 0; index < length; index += 1) {
43
+ (handlers[index] as GenericCallback)(...parameters);
44
+ }
45
+ }
46
+
17
47
  destroy(): void {
18
48
  mapped.delete(this.state.element);
19
49
 
@@ -22,10 +52,26 @@ export class EventManager {
22
52
 
23
53
  onSort(event: MouseEvent, target: HTMLElement): void {
24
54
  const direction = target.getAttribute(ATTRIBUTE_DATA_SORT_DIRECTION);
25
- const field = target.getAttribute(ATTRIBUTE_DATA_FIELD);
55
+ const key = target.getAttribute(ATTRIBUTE_DATA_KEY);
56
+
57
+ if (key != null) {
58
+ this.state.managers.sort.toggle(event, key, direction);
59
+ }
60
+ }
61
+
62
+ subscribe(name: string, callback: GenericCallback): void {
63
+ if (!isEvent(name) || typeof callback !== 'function') {
64
+ return;
65
+ }
66
+
67
+ (this.events as Record<string, Set<unknown>>)[name] ??= new Set();
68
+
69
+ (this.events[name] as Set<unknown>).add(callback);
70
+ }
26
71
 
27
- if (field != null) {
28
- this.state.managers.sort.toggle(event, field, direction);
72
+ unsubscribe(name: string, callback: GenericCallback): void {
73
+ if (isEvent(name) && typeof callback === 'function') {
74
+ this.events[name]?.delete(callback);
29
75
  }
30
76
  }
31
77
  }
@@ -33,27 +33,35 @@ export class FilterManager {
33
33
  constructor(public state: State) {}
34
34
 
35
35
  add(item: TabelaFilterItem): void {
36
- if (this.items[item.field] == null) {
37
- this.items[item.field] = [];
36
+ const {items, state} = this;
37
+
38
+ if (items[item.key] == null) {
39
+ items[item.key] = [];
38
40
  } else {
39
- const index = this.items[item.field].findIndex(existing => equal(existing, item));
41
+ const index = items[item.key].findIndex(existing => equal(existing, item));
40
42
 
41
43
  if (index > -1) {
42
44
  return;
43
45
  }
44
46
  }
45
47
 
46
- this.items[item.field].push(item);
48
+ items[item.key].push(item);
49
+
50
+ state.managers.event.emit('filter:add', [item]);
47
51
 
48
52
  this.filter();
49
53
  }
50
54
 
51
55
  clear(): void {
52
- if (Object.keys(this.items).length > 0) {
53
- this.items = {};
54
-
55
- this.filter();
56
+ if (Object.keys(this.items).length === 0) {
57
+ return;
56
58
  }
59
+
60
+ this.items = {};
61
+
62
+ this.state.managers.event.emit('filter:clear');
63
+
64
+ this.filter();
57
65
  }
58
66
 
59
67
  destroy(): void {
@@ -86,9 +94,9 @@ export class FilterManager {
86
94
  }
87
95
 
88
96
  filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
89
- const [field, items] = filters[filterIndex];
97
+ const [key, items] = filters[filterIndex];
90
98
 
91
- const value = row[field];
99
+ const value = row[key];
92
100
 
93
101
  for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
94
102
  const filter = items[itemIndex];
@@ -114,6 +122,8 @@ export class FilterManager {
114
122
  }
115
123
 
116
124
  remove(value: string | TabelaFilterItem): void {
125
+ const removed: TabelaFilterItem[] = [];
126
+
117
127
  if (typeof value === 'string') {
118
128
  if (this.items[value] == null) {
119
129
  return;
@@ -121,32 +131,38 @@ export class FilterManager {
121
131
 
122
132
  const keyed: Record<string, TabelaFilterItem[]> = {};
123
133
 
124
- const filters = Object.keys(this.items);
125
- const {length} = filters;
134
+ const keys = Object.keys(this.items);
135
+ const {length} = keys;
126
136
 
127
137
  for (let index = 0; index < length; index += 1) {
128
- const field = filters[index];
138
+ const key = keys[index];
129
139
 
130
- if (field !== value) {
131
- keyed[field] = this.items[field];
140
+ if (key === value) {
141
+ removed.push(...this.items[key]);
142
+ } else {
143
+ keyed[key] = this.items[key];
132
144
  }
133
145
  }
134
146
 
135
147
  this.items = keyed;
136
148
  } else {
137
- const {field} = value;
149
+ const {key} = value;
138
150
 
139
- if (this.items[field] == null) {
151
+ if (this.items[key] == null) {
140
152
  return;
141
153
  }
142
154
 
143
- const index = this.items[field].findIndex(item => equal(item, value));
155
+ const index = this.items[key].findIndex(item => equal(item, value));
144
156
 
145
157
  if (index === -1) {
146
158
  return;
147
159
  }
160
+
161
+ removed.push(this.items[key][index]);
148
162
  }
149
163
 
164
+ this.state.managers.event.emit('filter:remove', removed);
165
+
150
166
  this.filter();
151
167
  }
152
168
 
@@ -158,9 +174,9 @@ export class FilterManager {
158
174
  for (let index = 0; index < length; index += 1) {
159
175
  const item = items[index];
160
176
 
161
- keyed[item.field] ??= [];
177
+ keyed[item.key] ??= [];
162
178
 
163
- keyed[item.field].push(item);
179
+ keyed[item.key].push(item);
164
180
  }
165
181
 
166
182
  this.items = keyed;