@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
@@ -5,24 +5,32 @@ import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
5
5
  import type {Key, Simplify} from '@oscarpalmer/atoms/models';
6
6
  import {getString} from '@oscarpalmer/atoms/string';
7
7
  import {removeGroup, type GroupComponent} from '../components/group.component';
8
- import type {TabelaGroup} from '../models/group.model';
8
+ import {
9
+ EVENT_GROUP_ADD,
10
+ EVENT_GROUP_CLEAR,
11
+ EVENT_GROUP_REMOVE,
12
+ EVENT_GROUP_TOGGLE,
13
+ } from '../models/event.model';
14
+ import type {TabelaGroupHandlers, TabelaGroupToggle} from '../models/group.model';
9
15
  import type {State} from '../models/tabela.model';
16
+ import {compare} from '@oscarpalmer/atoms/value/compare';
17
+ import {getGroup} from '../helpers/misc.helpers';
10
18
 
11
19
  export class GroupManager {
12
20
  collapsed = new Set<Key>();
13
21
 
14
22
  enabled = false;
15
23
 
16
- field!: string;
24
+ key!: string;
17
25
 
18
- handlers: TabelaGroup = {
26
+ handlers: TabelaGroupHandlers = {
19
27
  set: (group?: string) => {
20
- if (group === this.field) {
28
+ if (group === this.key) {
21
29
  return;
22
30
  }
23
31
 
24
32
  this.enabled = !isNullableOrWhitespace(group);
25
- this.field = group ?? '';
33
+ this.key = group ?? '';
26
34
 
27
35
  this.state.managers.data.set(this.state.managers.data.get());
28
36
  },
@@ -40,20 +48,34 @@ export class GroupManager {
40
48
  }
41
49
 
42
50
  this.enabled = true;
43
- this.field = state.options.grouping;
51
+ this.key = state.options.grouping;
44
52
  }
45
53
 
46
- add(group: GroupComponent): void {
54
+ add(group: GroupComponent, emit: boolean): void {
47
55
  this.set([...this.items, group]);
56
+
57
+ if (emit) {
58
+ this.state.managers.event.emit(EVENT_GROUP_ADD, [getGroup(group)]);
59
+ }
48
60
  }
49
61
 
50
62
  clear(): void {
63
+ if (this.items.length === 0) {
64
+ return;
65
+ }
66
+
51
67
  const groups = this.items.splice(0);
52
68
  const {length} = groups;
53
69
 
54
70
  for (let index = 0; index < length; index += 1) {
55
- this.remove(groups[index]);
71
+ this.remove(groups[index], false);
56
72
  }
73
+
74
+ this.collapsed.clear();
75
+
76
+ this.set([]);
77
+
78
+ this.state.managers.event.emit(EVENT_GROUP_CLEAR);
57
79
  }
58
80
 
59
81
  destroy(): void {
@@ -111,6 +133,11 @@ export class GroupManager {
111
133
  }
112
134
  }
113
135
 
136
+ state.managers.event.emit(EVENT_GROUP_TOGGLE, {
137
+ collapsed: group.expanded ? [] : [getGroup(group)],
138
+ expanded: group.expanded ? [getGroup(group)] : [],
139
+ });
140
+
114
141
  if (Object.keys(state.managers.filter.items).length > 0) {
115
142
  state.managers.filter.filter();
116
143
  } else if (state.managers.sort.items.length > 0) {
@@ -120,14 +147,20 @@ export class GroupManager {
120
147
  }
121
148
  }
122
149
 
123
- remove(group: GroupComponent): void {
150
+ remove(group: GroupComponent, update: boolean): void {
124
151
  removeGroup(group);
125
152
 
153
+ if (!update) {
154
+ return;
155
+ }
156
+
126
157
  this.set(this.items.filter(item => item !== group));
158
+
159
+ this.state.managers.event.emit(EVENT_GROUP_REMOVE, [getGroup(group)]);
127
160
  }
128
161
 
129
162
  set(items: GroupComponent[]) {
130
- this.items = sort(items, item => item.label);
163
+ this.items = sort(items, (first, second) => compare(first.label, second.label));
131
164
 
132
165
  this.mapped = toMap(items, group => group.key);
133
166
 
@@ -1,10 +1,14 @@
1
- import type {Key} from '@oscarpalmer/atoms/models';
2
1
  import {on} from '@oscarpalmer/toretto/event';
3
2
  import type {RemovableEventListener} from '@oscarpalmer/toretto/models';
4
3
  import {renderGroup} from '../components/group.component';
5
4
  import {removeRow, renderRow} from '../components/row.component';
6
5
  import {isGroupKey} from '../helpers/misc.helpers';
7
- import type {RenderElementPool, RenderRange, RenderState} from '../models/render.model';
6
+ import type {
7
+ RenderElementPool,
8
+ RenderRange,
9
+ RenderState,
10
+ RenderVisible,
11
+ } from '../models/render.model';
8
12
  import type {State} from '../models/tabela.model';
9
13
 
10
14
  function getRange(state: State, down: boolean): RenderRange {
@@ -58,7 +62,10 @@ export class RenderManager {
58
62
 
59
63
  state: RenderState;
60
64
 
61
- visible = new Map<number, Key>();
65
+ visible: RenderVisible = {
66
+ indiced: new Map(),
67
+ keys: new Set(),
68
+ };
62
69
 
63
70
  constructor(state: State) {
64
71
  this.listener = on(state.element, 'scroll', onScroll.bind(this));
@@ -74,7 +81,9 @@ export class RenderManager {
74
81
  const {listener, pool, visible} = this;
75
82
 
76
83
  listener();
77
- visible.clear();
84
+
85
+ visible.indiced.clear();
86
+ visible.keys.clear();
78
87
 
79
88
  const cells = Object.values(pool.cells).flat();
80
89
 
@@ -100,15 +109,15 @@ export class RenderManager {
100
109
  this.visible = undefined as never;
101
110
  }
102
111
 
103
- removeCells(fields: string[]): void {
112
+ removeCells(keys: string[]): void {
104
113
  const {pool, state, visible} = this;
105
- const {length} = fields;
114
+ const {length} = keys;
106
115
 
107
116
  for (let index = 0; index < length; index += 1) {
108
- delete pool.cells[fields[index]];
117
+ delete pool.cells[keys[index]];
109
118
  }
110
119
 
111
- for (const [, key] of visible) {
120
+ for (const [, key] of visible.indiced) {
112
121
  if (isGroupKey(key)) {
113
122
  continue;
114
123
  }
@@ -120,11 +129,11 @@ export class RenderManager {
120
129
  }
121
130
 
122
131
  for (let index = 0; index < length; index += 1) {
123
- row.cells[fields[index]].innerHTML = '';
132
+ row.cells[keys[index]].innerHTML = '';
124
133
 
125
- row.cells[fields[index]].remove();
134
+ row.cells[keys[index]].remove();
126
135
 
127
- delete row.cells[fields[index]];
136
+ delete row.cells[keys[index]];
128
137
  }
129
138
  }
130
139
  }
@@ -153,10 +162,11 @@ export class RenderManager {
153
162
 
154
163
  let remove = rerender ?? false;
155
164
 
156
- for (const [index, key] of visible) {
165
+ for (const [index, key] of visible.indiced) {
157
166
  if (isGroupKey(key)) {
158
167
  if (remove || !indices.has(index)) {
159
- visible.delete(index);
168
+ visible.indiced.delete(index);
169
+ visible.keys.delete(key);
160
170
 
161
171
  state.managers.group.getForKey(key as string)?.element?.remove();
162
172
  }
@@ -167,7 +177,8 @@ export class RenderManager {
167
177
  const row = managers.row.get(key, false);
168
178
 
169
179
  if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
170
- visible.delete(index);
180
+ visible.indiced.delete(index);
181
+ visible.keys.delete(key);
171
182
 
172
183
  if (row != null) {
173
184
  removeRow(pool, row);
@@ -183,7 +194,7 @@ export class RenderManager {
183
194
  let offset = 0;
184
195
 
185
196
  for (let index = range.start; index <= range.end + offset; index += 1) {
186
- if (visible.has(index)) {
197
+ if (visible.indiced.has(index)) {
187
198
  continue;
188
199
  }
189
200
 
@@ -200,7 +211,8 @@ export class RenderManager {
200
211
 
201
212
  renderGroup(state, group);
202
213
 
203
- visible.set(index, group.key);
214
+ visible.indiced.set(index, group.key);
215
+ visible.keys.add(group.key);
204
216
 
205
217
  if (group.element != null) {
206
218
  group.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
@@ -227,7 +239,8 @@ export class RenderManager {
227
239
 
228
240
  renderRow(state, row);
229
241
 
230
- visible.set(index, key);
242
+ visible.indiced.set(index, key);
243
+ visible.keys.add(key);
231
244
 
232
245
  if (row.element != null) {
233
246
  row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
@@ -3,11 +3,21 @@ import type {Key, PlainObject} from '@oscarpalmer/atoms/models';
3
3
  import {compare} from '@oscarpalmer/atoms/value/compare';
4
4
  import {getValue} from '@oscarpalmer/atoms/value/handle';
5
5
  import {setAttribute, setAttributes} from '@oscarpalmer/toretto/attribute';
6
+ import {isGroupKey} from '../helpers/misc.helpers';
7
+ import type {DataValue} from '../models/data.model';
6
8
  import {
7
9
  ARIA_SORT,
8
10
  ATTRIBUTE_DATA_SORT_DIRECTION,
9
11
  ATTRIBUTE_DATA_SORT_POSITION,
10
12
  } from '../models/dom.model';
13
+ import {
14
+ EVENT_DATA_SORTED,
15
+ EVENT_SORT_ADD,
16
+ EVENT_SORT_CLEAR,
17
+ EVENT_SORT_FLIP,
18
+ EVENT_SORT_REMOVE,
19
+ EVENT_SORT_SET,
20
+ } from '../models/event.model';
11
21
  import {
12
22
  SORT_ASCENDING,
13
23
  SORT_DESCENDING,
@@ -16,8 +26,6 @@ import {
16
26
  type TabelaSortItem,
17
27
  } from '../models/sort.model';
18
28
  import type {State} from '../models/tabela.model';
19
- import type {DataValue} from '../models/data.model';
20
- import {isGroupKey} from '../helpers/misc.helpers';
21
29
 
22
30
  export class SortManager {
23
31
  handlers: TabelaSort = {
@@ -25,42 +33,48 @@ export class SortManager {
25
33
  flip: field => this.flip(field),
26
34
  clear: () => this.clear(),
27
35
  remove: field => this.remove(field),
28
- set: items => this.set(items),
36
+ set: items => this.set(items, true),
29
37
  };
30
38
 
31
- items: PlainObject[] = [];
39
+ items: TabelaSortItem[] = [];
32
40
 
33
41
  constructor(public state: State) {}
34
42
 
35
- add(field: string, direction?: TabelaSortDirection): void {
36
- const index = this.items.findIndex(item => item.key === field);
43
+ add(key: string, direction?: TabelaSortDirection): void {
44
+ const index = this.items.findIndex(item => item.key === key);
37
45
 
38
46
  if (index > -1) {
39
47
  return;
40
48
  }
41
49
 
42
50
  this.items.push({
43
- key: field,
51
+ key,
44
52
  direction: direction ?? SORT_ASCENDING,
45
53
  });
46
54
 
55
+ this.state.managers.event.emit(EVENT_SORT_ADD, [{key, direction: direction ?? SORT_ASCENDING}]);
56
+
47
57
  this.sort();
48
58
  }
49
59
 
50
- addOrSet(event: MouseEvent, field: string): void {
60
+ addOrSet(event: MouseEvent, key: string): void {
51
61
  if (event.ctrlKey || event.metaKey) {
52
- this.add(field);
62
+ this.add(key);
53
63
  } else {
54
- this.set([{field, direction: SORT_ASCENDING}]);
64
+ this.set([{key, direction: SORT_ASCENDING}], false);
55
65
  }
56
66
  }
57
67
 
58
68
  clear(): void {
59
- if (this.items.length > 0) {
60
- this.items.length = 0;
61
-
62
- this.sort();
69
+ if (this.items.length === 0) {
70
+ return;
63
71
  }
72
+
73
+ this.items.length = 0;
74
+
75
+ this.state.managers.event.emit(EVENT_SORT_CLEAR);
76
+
77
+ this.sort();
64
78
  }
65
79
 
66
80
  destroy(): void {
@@ -69,8 +83,8 @@ export class SortManager {
69
83
  this.state = undefined as never;
70
84
  }
71
85
 
72
- flip(field: string): void {
73
- const item = this.items.find(item => item.key === field);
86
+ flip(key: string): void {
87
+ const item = this.items.find(item => item.key === key);
74
88
 
75
89
  if (item == null) {
76
90
  return;
@@ -78,34 +92,48 @@ export class SortManager {
78
92
 
79
93
  item.direction = item.direction === SORT_ASCENDING ? SORT_DESCENDING : SORT_ASCENDING;
80
94
 
95
+ this.state.managers.event.emit(EVENT_SORT_FLIP, [{key, direction: item.direction}]);
96
+
81
97
  this.sort();
82
98
  }
83
99
 
84
- remove(field: string): void {
85
- const index = this.items.findIndex(item => item.key === field);
86
-
87
- if (index > -1) {
88
- this.items.splice(index, 1);
100
+ remove(key: string): void {
101
+ const index = this.items.findIndex(item => item.key === key);
89
102
 
90
- this.sort();
103
+ if (index === -1) {
104
+ return;
91
105
  }
92
- }
93
106
 
94
- removeOrClear(event: MouseEvent, field: string): void {
95
- if (event.ctrlKey || event.metaKey) {
96
- this.remove(field);
97
- } else {
98
- this.clear();
107
+ const spliced = this.items.splice(index, 1);
108
+
109
+ this.state.managers.event.emit(EVENT_SORT_REMOVE, spliced);
110
+
111
+ if (this.items.length === 0) {
112
+ this.state.managers.event.emit(EVENT_SORT_CLEAR);
99
113
  }
114
+
115
+ this.sort();
100
116
  }
101
117
 
102
- set(items: TabelaSortItem[]): void {
103
- this.items.splice(
118
+ set(items: TabelaSortItem[], set: boolean): void {
119
+ const removed = this.items.splice(
104
120
  0,
105
121
  this.items.length,
106
- ...items.map(item => ({key: item.field, direction: item.direction})),
122
+ ...items.map(item => ({key: item.key, direction: item.direction})),
107
123
  );
108
124
 
125
+ if (set) {
126
+ this.state.managers.event.emit(EVENT_SORT_SET, {
127
+ removed,
128
+ added: items.map(item => ({key: item.key, direction: item.direction})),
129
+ });
130
+ } else {
131
+ this.state.managers.event.emit(
132
+ EVENT_SORT_ADD,
133
+ items.map(item => ({key: item.key, direction: item.direction})),
134
+ );
135
+ }
136
+
109
137
  this.sort();
110
138
  }
111
139
 
@@ -117,7 +145,7 @@ export class SortManager {
117
145
  for (let index = 0; index < length; index += 1) {
118
146
  const column = state.managers.column.items[index];
119
147
 
120
- const sorterIndex = items.findIndex(item => item.key === column.options.field);
148
+ const sorterIndex = items.findIndex(item => item.key === column.options.key);
121
149
  const sorterItem = items[sorterIndex];
122
150
 
123
151
  setAttributes(column.elements.wrapper, {
@@ -136,31 +164,32 @@ export class SortManager {
136
164
  state.managers.data.state.keys.active =
137
165
  items.length === 0 ? undefined : getSortedItems(state, items);
138
166
 
167
+ state.managers.event.emit(EVENT_DATA_SORTED, state.managers.data.get(true));
168
+
139
169
  state.managers.render.update(true, true);
140
170
  }
141
171
 
142
- toggle(event: MouseEvent, field: string, direction?: string | null): void {
172
+ toggle(event: MouseEvent, key: string, direction?: string | null): void {
143
173
  switch (direction) {
144
174
  case SORT_ASCENDING:
145
- this.flip(field);
175
+ this.flip(key);
146
176
  return;
147
177
 
148
178
  case SORT_DESCENDING:
149
- this.removeOrClear(event, field);
179
+ this.remove(key);
150
180
  return;
151
181
 
152
182
  default:
153
- this.addOrSet(event, field);
183
+ this.addOrSet(event, key);
154
184
  return;
155
185
  }
156
186
  }
157
187
  }
158
188
 
159
- function getSortedItems(state: State, sorters: PlainObject[]): Key[] {
160
- const data =
161
- (state.managers.data.state.keys.active?.map(key =>
162
- isGroupKey(key) ? key : state.managers.data.state.values.mapped.get(key)!,
163
- ) as DataValue[]) ?? state.managers.data.state.values.array;
189
+ function getSortedItems(state: State, sorters: TabelaSortItem[]): Key[] {
190
+ const data = (state.managers.data.state.keys.active?.map(key =>
191
+ isGroupKey(key) ? key : state.managers.data.state.values.mapped.get(key)!,
192
+ ) ?? state.managers.data.state.values.array) as DataValue[];
164
193
 
165
194
  if (!state.managers.group.enabled) {
166
195
  return sort(data as PlainObject[], sorters as never).map(
@@ -169,28 +198,28 @@ function getSortedItems(state: State, sorters: PlainObject[]): Key[] {
169
198
  }
170
199
 
171
200
  return sortWithGroups(state, data, sorters).map(item =>
172
- typeof item === 'string' ? item : (getValue(item, state.key) as Key),
173
- );
201
+ isGroupKey(item) ? item : (getValue(item as PlainObject, state.key) as Key),
202
+ ) as Key[];
174
203
  }
175
204
 
176
205
  export function sortWithGroups(
177
206
  state: State,
178
207
  data: DataValue[],
179
- sorters: PlainObject[],
208
+ sorters: TabelaSortItem[],
180
209
  ): DataValue[] {
181
210
  const {length} = sorters;
182
211
 
183
212
  return data.sort((first, second) => {
184
- const firstIsGroup = typeof first === 'string';
185
- const secondIsGroup = typeof second === 'string';
213
+ const firstIsGroup = isGroupKey(first);
214
+ const secondIsGroup = isGroupKey(second);
186
215
 
187
216
  const firstValue = firstIsGroup
188
- ? state.managers.group.getForKey(first)?.value.stringified
189
- : getValue(first, state.managers.group.field);
217
+ ? state.managers.group.getForKey(first as string)!.value.stringified
218
+ : getValue(first as PlainObject, state.managers.group.key);
190
219
 
191
220
  const secondValue = secondIsGroup
192
- ? state.managers.group.getForKey(second)?.value.stringified
193
- : getValue(second, state.managers.group.field);
221
+ ? state.managers.group.getForKey(second as string)!.value.stringified
222
+ : getValue(second as PlainObject, state.managers.group.key);
194
223
 
195
224
  const firstOrder = state.managers.group.order[firstValue as never];
196
225
  const secondOrder = state.managers.group.order[secondValue as never];
@@ -209,8 +238,8 @@ export function sortWithGroups(
209
238
  const sorter = sorters[index];
210
239
 
211
240
  const comparison = compare(
212
- getValue(first, (sorter as any).key),
213
- getValue(second, (sorter as any).key),
241
+ getValue(first as PlainObject, sorter.key),
242
+ getValue(second as PlainObject, sorter.key),
214
243
  );
215
244
 
216
245
  if (comparison !== 0) {
@@ -4,6 +4,8 @@ import {
4
4
  CSS_CELL_FOOTER,
5
5
  CSS_CELL_GROUP,
6
6
  CSS_HEADING,
7
+ CSS_HEADING_CONTENT,
8
+ CSS_HEADING_SORTER,
7
9
  CSS_ROW,
8
10
  CSS_ROW_SELECTED,
9
11
  CSS_ROWGROUP_BODY,
@@ -135,6 +137,37 @@ const styling = //css
135
137
  white-space: nowrap;
136
138
  }
137
139
 
140
+ :where(.${CSS_HEADING}) {
141
+ display: flex;
142
+ flex-flow: row nowrap;
143
+ align-items: center;
144
+ justify-content: space-between;
145
+ gap: 0.5em;
146
+ cursor: pointer;
147
+ }
148
+
149
+ :where(.${CSS_HEADING_CONTENT}) {
150
+ overflow: hidden;
151
+ white-space: nowrap;
152
+ text-overflow: ellipsis;
153
+ }
154
+
155
+ :where(.${CSS_HEADING}[data-sort-direction] .${CSS_HEADING_SORTER})::after {
156
+ width: 1em;
157
+ height: 1em;
158
+ display: inline-flex;
159
+ font-size: .75em;
160
+ font-weight: bold;
161
+ }
162
+
163
+ :where(.${CSS_HEADING}[data-sort-direction="ascending"] .${CSS_HEADING_SORTER})::after {
164
+ content: '\\21C8';
165
+ }
166
+
167
+ :where(.${CSS_HEADING}[data-sort-direction="descending"] .${CSS_HEADING_SORTER})::after {
168
+ content: '\\21CA';
169
+ }
170
+
138
171
  :where(.${CSS_CELL_FOOTER}) {
139
172
  border-top-width: 1px;
140
173
  border-bottom-width: 0;
@@ -1,11 +1,11 @@
1
1
  export type Column = {
2
- field: string;
2
+ key: string;
3
3
  label: string;
4
4
  width: number;
5
5
  };
6
6
 
7
7
  export type TabelaColumn = {
8
- field: string;
8
+ key: string;
9
9
  label: string;
10
10
  width?: number;
11
11
  };
@@ -19,11 +19,11 @@ type DataValues = {
19
19
  };
20
20
 
21
21
  export type TabelaData = {
22
- add(data: PlainObject[]): void;
23
- clear(): void;
22
+ add(data: PlainObject[]): Promise<void>;
23
+ clear(): Promise<void>;
24
24
  get(active?: boolean): PlainObject[];
25
- remove(keys: Key[]): void;
26
- remove(data: PlainObject[]): void;
27
- synchronize(data: PlainObject[], remove?: boolean): void;
28
- update(data: PlainObject[]): void;
25
+ remove(keys: Key[]): Promise<void>;
26
+ remove(data: PlainObject[]): Promise<void>;
27
+ synchronize(data: PlainObject[], remove?: boolean): Promise<void>;
28
+ update(data: PlainObject[]): Promise<void>;
29
29
  };
@@ -10,8 +10,6 @@ export const ATTRIBUTE_DATA_ACTIVE = 'data-active';
10
10
 
11
11
  export const ATTRIBUTE_DATA_EVENT = 'data-event';
12
12
 
13
- export const ATTRIBUTE_DATA_FIELD = 'data-field';
14
-
15
13
  export const ATTRIBUTE_DATA_KEY = 'data-key';
16
14
 
17
15
  export const ATTRIBUTE_DATA_SORT_DIRECTION = 'data-sort-direction';