@oscarpalmer/tabela 0.12.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.
Files changed (160) hide show
  1. package/dist/body.component-_VDOpJhV.d.mts +10 -0
  2. package/dist/body.model-2iwsovAV.d.mts +7 -0
  3. package/dist/column.component-Bx46r3JI.d.mts +16 -0
  4. package/dist/column.model-D-aw4EU4.d.mts +16 -0
  5. package/dist/components/body.component.d.mts +2 -0
  6. package/dist/components/{body.component.js → body.component.mjs} +6 -3
  7. package/dist/components/column.component.d.mts +2 -0
  8. package/dist/components/{column.component.js → column.component.mjs} +8 -5
  9. package/dist/components/footer.component.d.mts +2 -0
  10. package/dist/components/{footer.component.js → footer.component.mjs} +7 -4
  11. package/dist/components/group.component.d.mts +2 -0
  12. package/dist/components/group.component.mjs +51 -0
  13. package/dist/components/header.component.d.mts +2 -0
  14. package/dist/components/{header.component.js → header.component.mjs} +6 -3
  15. package/dist/components/row.component.d.mts +2 -0
  16. package/dist/components/{row.component.js → row.component.mjs} +11 -7
  17. package/dist/filter.model-7ukJrtil.d.mts +16 -0
  18. package/dist/footer.component-Curiab8j.d.mts +12 -0
  19. package/dist/footer.model-DhqoS6ds.d.mts +8 -0
  20. package/dist/group.component-Cq1YYbfJ.d.mts +285 -0
  21. package/dist/group.model-BsKFwHbt.d.mts +10 -0
  22. package/dist/header.component-BjjlpZIg.d.mts +12 -0
  23. package/dist/header.model-DN_KzUCV.d.mts +7 -0
  24. package/dist/helpers/dom.helpers.d.mts +12 -0
  25. package/dist/helpers/{dom.helpers.js → dom.helpers.mjs} +13 -9
  26. package/dist/helpers/misc.helpers.d.mts +6 -0
  27. package/dist/helpers/{misc.helpers.js → misc.helpers.mjs} +3 -1
  28. package/dist/helpers/style.helper.d.mts +6 -0
  29. package/dist/helpers/style.helper.mjs +8 -0
  30. package/dist/index.d.mts +7 -0
  31. package/dist/{index.js → index.mjs} +3 -1
  32. package/dist/managers/column.manager.d.mts +2 -0
  33. package/dist/managers/{column.manager.js → column.manager.mjs} +6 -1
  34. package/dist/managers/data.manager.d.mts +2 -0
  35. package/dist/managers/data.manager.mjs +222 -0
  36. package/dist/managers/event.manager.d.mts +2 -0
  37. package/dist/managers/{event.manager.js → event.manager.mjs} +9 -8
  38. package/dist/managers/filter.manager.d.mts +2 -0
  39. package/dist/managers/{filter.manager.js → filter.manager.mjs} +23 -14
  40. package/dist/managers/group.manager.d.mts +2 -0
  41. package/dist/managers/group.manager.mjs +73 -0
  42. package/dist/managers/navigation.manager.d.mts +2 -0
  43. package/dist/managers/{navigation.manager.js → navigation.manager.mjs} +27 -24
  44. package/dist/managers/render.manager.d.mts +2 -0
  45. package/dist/managers/{render.manager.js → render.manager.mjs} +35 -26
  46. package/dist/managers/row.manager.d.mts +2 -0
  47. package/dist/managers/{row.manager.js → row.manager.mjs} +18 -11
  48. package/dist/managers/selection.manager.d.mts +2 -0
  49. package/dist/managers/{selection.manager.js → selection.manager.mjs} +32 -28
  50. package/dist/managers/sort.manager.d.mts +2 -0
  51. package/dist/managers/{sort.manager.js → sort.manager.mjs} +12 -9
  52. package/dist/managers/style.manager.d.mts +2 -0
  53. package/dist/managers/style.manager.mjs +149 -0
  54. package/dist/models/body.model.d.mts +2 -0
  55. package/dist/models/body.model.mjs +1 -0
  56. package/dist/models/column.model.d.mts +2 -0
  57. package/dist/models/column.model.mjs +1 -0
  58. package/dist/models/data.model.d.mts +2 -0
  59. package/dist/models/data.model.mjs +1 -0
  60. package/dist/models/filter.model.d.mts +2 -0
  61. package/dist/models/filter.model.mjs +1 -0
  62. package/dist/models/footer.model.d.mts +2 -0
  63. package/dist/models/footer.model.mjs +1 -0
  64. package/dist/models/group.model.d.mts +2 -0
  65. package/dist/models/group.model.mjs +1 -0
  66. package/dist/models/header.model.d.mts +2 -0
  67. package/dist/models/header.model.mjs +1 -0
  68. package/dist/models/render.model.d.mts +2 -0
  69. package/dist/models/render.model.mjs +1 -0
  70. package/dist/models/selection.model.d.mts +2 -0
  71. package/dist/models/selection.model.mjs +1 -0
  72. package/dist/models/sort.model.d.mts +2 -0
  73. package/dist/models/sort.model.mjs +1 -0
  74. package/dist/models/style.model.d.mts +23 -0
  75. package/dist/models/style.model.mjs +23 -0
  76. package/dist/models/tabela.model.d.mts +2 -0
  77. package/dist/models/tabela.model.mjs +1 -0
  78. package/dist/models/tabela.options.d.mts +2 -0
  79. package/dist/models/tabela.options.mjs +1 -0
  80. package/dist/selection.model-rwQe9fco.d.mts +12 -0
  81. package/dist/sort.model-CauImaLu.d.mts +15 -0
  82. package/dist/tabela.d.mts +21 -0
  83. package/dist/{tabela.full.js → tabela.full.mjs} +1073 -756
  84. package/dist/tabela.mjs +126 -0
  85. package/dist/tabela.options-RkZvfptB.d.mts +14 -0
  86. package/package.json +45 -37
  87. package/src/components/body.component.ts +4 -3
  88. package/src/components/column.component.ts +13 -18
  89. package/src/components/footer.component.ts +8 -3
  90. package/src/components/group.component.ts +48 -6
  91. package/src/components/header.component.ts +3 -2
  92. package/src/components/row.component.ts +8 -6
  93. package/src/helpers/dom.helpers.ts +21 -19
  94. package/src/helpers/style.helper.ts +1 -1
  95. package/src/managers/column.manager.ts +4 -0
  96. package/src/managers/data.manager.ts +170 -100
  97. package/src/managers/event.manager.ts +9 -10
  98. package/src/managers/filter.manager.ts +23 -12
  99. package/src/managers/group.manager.ts +63 -11
  100. package/src/managers/navigation.manager.ts +23 -22
  101. package/src/managers/render.manager.ts +43 -29
  102. package/src/managers/row.manager.ts +21 -9
  103. package/src/managers/selection.manager.ts +28 -21
  104. package/src/managers/sort.manager.ts +22 -20
  105. package/src/managers/style.manager.ts +156 -0
  106. package/src/models/data.model.ts +11 -8
  107. package/src/models/group.model.ts +6 -2
  108. package/src/models/style.model.ts +39 -0
  109. package/src/models/tabela.model.ts +10 -8
  110. package/src/tabela.ts +65 -33
  111. package/dist/components/group.component.js +0 -28
  112. package/dist/helpers/style.helper.js +0 -6
  113. package/dist/managers/data.manager.js +0 -181
  114. package/dist/managers/group.manager.js +0 -46
  115. package/dist/models/body.model.js +0 -0
  116. package/dist/models/column.model.js +0 -0
  117. package/dist/models/data.model.js +0 -0
  118. package/dist/models/filter.model.js +0 -0
  119. package/dist/models/footer.model.js +0 -0
  120. package/dist/models/group.model.js +0 -0
  121. package/dist/models/header.model.js +0 -0
  122. package/dist/models/render.model.js +0 -0
  123. package/dist/models/selection.model.js +0 -0
  124. package/dist/models/sort.model.js +0 -0
  125. package/dist/models/tabela.model.js +0 -0
  126. package/dist/models/tabela.options.js +0 -0
  127. package/dist/tabela.js +0 -105
  128. package/types/components/body.component.d.ts +0 -6
  129. package/types/components/column.component.d.ts +0 -13
  130. package/types/components/footer.component.d.ts +0 -8
  131. package/types/components/group.component.d.ts +0 -14
  132. package/types/components/header.component.d.ts +0 -8
  133. package/types/components/row.component.d.ts +0 -11
  134. package/types/helpers/dom.helpers.d.ts +0 -10
  135. package/types/helpers/misc.helpers.d.ts +0 -2
  136. package/types/helpers/style.helper.d.ts +0 -1
  137. package/types/index.d.ts +0 -4
  138. package/types/managers/column.manager.d.ts +0 -12
  139. package/types/managers/data.manager.d.ts +0 -29
  140. package/types/managers/event.manager.d.ts +0 -7
  141. package/types/managers/filter.manager.d.ts +0 -19
  142. package/types/managers/group.manager.d.ts +0 -17
  143. package/types/managers/navigation.manager.d.ts +0 -10
  144. package/types/managers/render.manager.d.ts +0 -17
  145. package/types/managers/row.manager.d.ts +0 -13
  146. package/types/managers/selection.manager.d.ts +0 -24
  147. package/types/managers/sort.manager.d.ts +0 -28
  148. package/types/models/body.model.d.ts +0 -4
  149. package/types/models/column.model.d.ts +0 -13
  150. package/types/models/data.model.d.ts +0 -24
  151. package/types/models/filter.model.d.ts +0 -13
  152. package/types/models/footer.model.d.ts +0 -5
  153. package/types/models/group.model.d.ts +0 -4
  154. package/types/models/header.model.d.ts +0 -4
  155. package/types/models/render.model.d.ts +0 -13
  156. package/types/models/selection.model.d.ts +0 -8
  157. package/types/models/sort.model.d.ts +0 -12
  158. package/types/models/tabela.model.d.ts +0 -39
  159. package/types/models/tabela.options.d.ts +0 -10
  160. package/types/tabela.d.ts +0 -15
@@ -2,7 +2,9 @@ import {sort} from '@oscarpalmer/atoms/array';
2
2
  import {toRecord} from '@oscarpalmer/atoms/array/to-record';
3
3
  import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
4
4
  import type {Key, Simplify} from '@oscarpalmer/atoms/models';
5
- import type {GroupComponent} from '../components/group.component';
5
+ import {getString} from '@oscarpalmer/atoms/string';
6
+ import {removeGroup, type GroupComponent} from '../components/group.component';
7
+ import type {TabelaGroup} from '../models/group.model';
6
8
  import type {State} from '../models/tabela.model';
7
9
 
8
10
  export class GroupManager {
@@ -12,11 +14,24 @@ export class GroupManager {
12
14
 
13
15
  field!: string;
14
16
 
17
+ handlers = Object.freeze({
18
+ set: (group?: string) => {
19
+ if (group === this.field) {
20
+ return;
21
+ }
22
+
23
+ this.enabled = !isNullableOrWhitespace(group);
24
+ this.field = group ?? '';
25
+
26
+ this.state.managers.data.set(this.state.managers.data.get());
27
+ },
28
+ } satisfies TabelaGroup);
29
+
15
30
  items: GroupComponent[] = [];
16
31
 
17
32
  order: Record<never, number> = {};
18
33
 
19
- constructor(readonly state: State) {
34
+ constructor(public state: State) {
20
35
  if (isNullableOrWhitespace(state.options.grouping)) {
21
36
  return;
22
37
  }
@@ -29,13 +44,38 @@ export class GroupManager {
29
44
  this.set([...this.items, group]);
30
45
  }
31
46
 
47
+ clear(): void {
48
+ const groups = this.items.splice(0);
49
+ const {length} = groups;
50
+
51
+ for (let index = 0; index < length; index += 1) {
52
+ this.remove(groups[index]);
53
+ }
54
+ }
55
+
56
+ destroy(): void {
57
+ const groups = this.items.splice(0);
58
+ const {length} = groups;
59
+
60
+ for (let index = 0; index < length; index += 1) {
61
+ removeGroup(groups[index]);
62
+ }
63
+
64
+ this.collapsed.clear();
65
+
66
+ this.handlers = undefined as never;
67
+ this.state = undefined as never;
68
+ }
69
+
32
70
  get(value: unknown) {
33
- return this.items.find(item => item.value === value);
71
+ const asString = getString(value);
72
+
73
+ return this.items.find(item => item.value.stringified === asString);
34
74
  }
35
75
 
36
76
  handle(button: HTMLElement): void {
37
- const key = button.dataset.key;
38
- const group = this.get(key);
77
+ const value = button.dataset.key?.replace(`tabela_${this.state.id}_group:`, '');
78
+ const group = this.get(value);
39
79
 
40
80
  if (group == null) {
41
81
  return;
@@ -47,15 +87,15 @@ export class GroupManager {
47
87
 
48
88
  const index = items.indexOf(group);
49
89
 
50
- let first = state.managers.data.values.keys.original.indexOf(items[index]) + 1;
90
+ let first = state.managers.data.state.items.original.indexOf(items[index]) + 1;
51
91
 
52
92
  const last =
53
93
  items[index + 1] == null
54
- ? state.managers.data.keys.length - 1
55
- : state.managers.data.values.keys.original.indexOf(items[index + 1]) - 1;
94
+ ? state.managers.data.state.items.original.length - 1
95
+ : state.managers.data.state.items.original.indexOf(items[index + 1]) - 1;
56
96
 
57
97
  for (; first <= last; first += 1) {
58
- const key = state.managers.data.values.keys.original[first] as Key;
98
+ const key = state.managers.data.state.items.original[first] as Key;
59
99
 
60
100
  if (group.expanded) {
61
101
  collapsed.delete(key);
@@ -64,16 +104,28 @@ export class GroupManager {
64
104
  }
65
105
  }
66
106
 
67
- state.managers.render.update(true, true);
107
+ if (Object.keys(state.managers.filter.items).length > 0) {
108
+ state.managers.filter.filter();
109
+ } else if (state.managers.sort.items.length > 0) {
110
+ state.managers.sort.sort();
111
+ } else {
112
+ state.managers.render.update(true, true);
113
+ }
68
114
  }
69
115
 
70
116
  remove(group: GroupComponent): void {
117
+ removeGroup(group);
118
+
71
119
  this.set(this.items.filter(item => item !== group));
72
120
  }
73
121
 
74
122
  set(items: GroupComponent[]) {
75
123
  this.items = sort(items, item => item.label);
76
124
 
77
- this.order = toRecord(items as Simplify<GroupComponent>[], 'value', (_, index) => index);
125
+ this.order = toRecord(
126
+ items as Simplify<GroupComponent>[],
127
+ group => group.value.stringified,
128
+ (_, index) => index,
129
+ );
78
130
  }
79
131
  }
@@ -1,12 +1,12 @@
1
1
  import {isNullableOrWhitespace} from '@oscarpalmer/atoms/is';
2
- import type {Key} from '@oscarpalmer/atoms/models';
3
2
  import {clamp} from '@oscarpalmer/atoms/number';
4
- import type {GroupComponent} from '../components/group.component';
5
3
  import {getKey} from '../helpers/misc.helpers';
4
+ import type {DataItem} from '../models/data.model';
6
5
  import type {State} from '../models/tabela.model';
6
+ import {GroupComponent} from '../components/group.component';
7
7
 
8
8
  export class NavigationManager {
9
- active: Key | undefined;
9
+ active: DataItem | undefined;
10
10
 
11
11
  constructor(public state: State) {}
12
12
 
@@ -25,26 +25,26 @@ export class NavigationManager {
25
25
 
26
26
  const activeDescendant = components.body.elements.group.getAttribute('aria-activedescendant');
27
27
 
28
- const {keys} = managers.data;
29
- const {length} = keys;
28
+ const {items} = managers.data;
29
+ const {length} = items;
30
30
 
31
31
  let next: number;
32
32
 
33
33
  if (isNullableOrWhitespace(activeDescendant)) {
34
34
  next = getDefaultIndex(event.key, length);
35
35
  } else {
36
- next = getIndex(event, activeDescendant, id, keys)!;
36
+ next = getIndex(this.state, event, activeDescendant, id)!;
37
37
  }
38
38
 
39
39
  if (next != null) {
40
- this.setActive(keys.at(next) as Key);
40
+ this.setActive(items.at(next));
41
41
  }
42
42
  }
43
43
 
44
- setActive(key: Key | undefined, scroll?: boolean): void {
45
- const {components, managers, options} = this.state;
44
+ setActive(item: DataItem | undefined, scroll?: boolean): void {
45
+ const {components, id, managers, options} = this.state;
46
46
 
47
- this.active = key;
47
+ this.active = item;
48
48
 
49
49
  const active = components.body.elements.group.querySelectorAll('[data-active="true"]');
50
50
 
@@ -52,19 +52,19 @@ export class NavigationManager {
52
52
  item.setAttribute('data-active', 'false');
53
53
  }
54
54
 
55
- const row = managers.row.get(key!);
55
+ const component = item instanceof GroupComponent ? item : managers.row.get(item!, false);
56
56
 
57
- if (row != null) {
58
- row.element?.setAttribute('data-active', 'true');
57
+ if (component != null) {
58
+ component.element?.setAttribute('data-active', 'true');
59
59
 
60
60
  if (scroll ?? true) {
61
- if (row.element == null) {
61
+ if (component.element == null) {
62
62
  components.body.elements.group.scrollTo({
63
- top: managers.data.getIndex(key!) * options.rowHeight,
63
+ top: managers.data.getIndex(item!) * options.rowHeight,
64
64
  behavior: 'smooth',
65
65
  });
66
66
  } else {
67
- row.element.scrollIntoView({
67
+ component.element.scrollIntoView({
68
68
  block: 'nearest',
69
69
  });
70
70
  }
@@ -73,7 +73,7 @@ export class NavigationManager {
73
73
 
74
74
  components.body.elements.group.setAttribute(
75
75
  'aria-activedescendant',
76
- row == null ? '' : `tabela_${this.state.id}_row_${key}`,
76
+ component == null ? '' : `tabela_${id}_${component.key}`,
77
77
  );
78
78
  }
79
79
  }
@@ -95,25 +95,26 @@ function getDefaultIndex(key: string, max: number): number {
95
95
  }
96
96
 
97
97
  function getIndex(
98
+ state: State,
98
99
  event: KeyboardEvent,
99
100
  active: string,
100
101
  id: number,
101
- keys: Array<GroupComponent | Key>,
102
102
  ): number | undefined {
103
- const key = getKey(active.replace(`tabela_${id}_row_`, ''));
103
+ const key = getKey(active.replace(`tabela_${id}_`, ''));
104
104
 
105
105
  if (key == null) {
106
106
  return;
107
107
  }
108
108
 
109
109
  if (absoluteKeys.has(event.key)) {
110
- return event.key === 'Home' ? 0 : keys.length - 1;
110
+ return event.key === 'Home' ? 0 : state.managers.data.size - 1;
111
111
  }
112
112
 
113
- const index = keys.indexOf(key);
113
+ const index = state.managers.data.getIndex(key);
114
+
114
115
  const offset = getOffset(event.key);
115
116
 
116
- return clamp(index + offset, 0, keys.length - 1, true);
117
+ return clamp(index + offset, 0, state.managers.data.size - 1, true);
117
118
  }
118
119
 
119
120
  function getOffset(key: string): number {
@@ -1,29 +1,29 @@
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 {GroupComponent, renderGroup} from '../components/group.component';
5
4
  import {removeRow, renderRow} from '../components/row.component';
5
+ import type {DataItem} from '../models/data.model';
6
6
  import type {RenderElementPool, RenderRange, RenderState} from '../models/render.model';
7
7
  import type {State} from '../models/tabela.model';
8
8
 
9
9
  function getRange(state: State, down: boolean): RenderRange {
10
- const {components, managers, options} = state;
11
- const {clientHeight, scrollTop} = components.body.elements.group;
10
+ const {element, managers, options} = state;
11
+ const {clientHeight, scrollTop} = element;
12
12
 
13
- const {keys} = managers.data;
13
+ const {items} = managers.data;
14
14
 
15
- const first = Math.floor(scrollTop / options.rowHeight);
15
+ const firstIndex = Math.floor(scrollTop / options.rowHeight);
16
+ const lastIndex = items.length - managers.group.collapsed.size - 1;
16
17
 
17
- const last = Math.min(
18
- keys.length - managers.group.collapsed.size - 1,
19
- Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1,
20
- );
18
+ const last = Math.min(lastIndex, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
21
19
 
22
- const before = Math.ceil(clientHeight / options.rowHeight) * (down ? 1 : 2);
23
- const after = Math.ceil(clientHeight / options.rowHeight) * (down ? 2 : 1);
20
+ const visible = clientHeight / options.rowHeight;
24
21
 
25
- const start = Math.max(0, first - before);
26
- const end = Math.min(keys.length - managers.group.collapsed.size - 1, last + after);
22
+ const before = Math.ceil(visible) * (down ? 1 : 2);
23
+ const after = Math.ceil(visible) * (down ? 2 : 1);
24
+
25
+ const start = Math.max(0, firstIndex - before);
26
+ const end = Math.min(lastIndex, last + after);
27
27
 
28
28
  return {end, start};
29
29
  }
@@ -33,7 +33,7 @@ function onScroll(this: RenderManager): void {
33
33
 
34
34
  if (!state.active) {
35
35
  requestAnimationFrame(() => {
36
- const top = state.components.body.elements.group.scrollTop;
36
+ const top = state.element.scrollTop;
37
37
 
38
38
  this.update(top > state.top);
39
39
 
@@ -57,10 +57,10 @@ export class RenderManager {
57
57
 
58
58
  state: RenderState;
59
59
 
60
- visible = new Map<number, GroupComponent | Key>();
60
+ visible = new Map<number, DataItem>();
61
61
 
62
62
  constructor(state: State) {
63
- this.listener = on(state.components.body.elements.group, 'scroll', onScroll.bind(this));
63
+ this.listener = on(state.element, 'scroll', onScroll.bind(this));
64
64
 
65
65
  this.state = {
66
66
  ...state,
@@ -75,6 +75,20 @@ export class RenderManager {
75
75
  listener();
76
76
  visible.clear();
77
77
 
78
+ const cells = Object.values(pool.cells).flat();
79
+
80
+ let {length} = cells;
81
+
82
+ for (let index = 0; index < length; index += 1) {
83
+ cells[index].remove();
84
+ }
85
+
86
+ length = pool.rows.length;
87
+
88
+ for (let index = 0; index < length; index += 1) {
89
+ pool.rows[index].remove();
90
+ }
91
+
78
92
  pool.cells = {};
79
93
  pool.rows = [];
80
94
 
@@ -98,7 +112,7 @@ export class RenderManager {
98
112
  continue;
99
113
  }
100
114
 
101
- const row = state.managers.row.get(key);
115
+ const row = state.managers.row.get(key, false);
102
116
 
103
117
  if (row == null || row.element == null) {
104
118
  continue;
@@ -149,7 +163,7 @@ export class RenderManager {
149
163
  continue;
150
164
  }
151
165
 
152
- const row = managers.row.get(key);
166
+ const row = managers.row.get(key, false);
153
167
 
154
168
  if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
155
169
  visible.delete(index);
@@ -162,7 +176,7 @@ export class RenderManager {
162
176
 
163
177
  const fragment = this.getFragment();
164
178
 
165
- const {keys} = managers.data;
179
+ const {items} = managers.data;
166
180
 
167
181
  let count = 0;
168
182
  let offset = 0;
@@ -172,31 +186,31 @@ export class RenderManager {
172
186
  continue;
173
187
  }
174
188
 
175
- const key = keys[index];
189
+ const item = items[index];
176
190
 
177
- if (key instanceof GroupComponent) {
191
+ if (item instanceof GroupComponent) {
178
192
  count += 1;
179
193
 
180
- renderGroup(state, key);
194
+ renderGroup(state, item);
181
195
 
182
- visible.set(index, key);
196
+ visible.set(index, item);
183
197
 
184
- if (key.element != null) {
185
- key.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
198
+ if (item.element != null) {
199
+ item.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
186
200
 
187
- fragment.append(key.element);
201
+ fragment.append(item.element);
188
202
  }
189
203
 
190
204
  continue;
191
205
  }
192
206
 
193
- const row = managers.row.get(key);
207
+ const row = managers.row.get(item, true);
194
208
 
195
209
  if (row == null) {
196
210
  continue;
197
211
  }
198
212
 
199
- if (managers.group.collapsed.has(key)) {
213
+ if (managers.group.collapsed.has(item)) {
200
214
  offset += 1;
201
215
 
202
216
  continue;
@@ -206,7 +220,7 @@ export class RenderManager {
206
220
 
207
221
  renderRow(state, row);
208
222
 
209
- visible.set(index, key);
223
+ visible.set(index, item);
210
224
 
211
225
  if (row.element != null) {
212
226
  row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
@@ -7,24 +7,30 @@ export class RowManager {
7
7
 
8
8
  constructor(public state: State) {}
9
9
 
10
- destroy(): void {
11
- const components = [...this.components.values()];
12
- const {length} = components;
10
+ clear(): void {
11
+ const {components} = this;
12
+
13
+ const rows = [...components.values()];
14
+ const {length} = rows;
13
15
 
14
16
  for (let index = 0; index < length; index += 1) {
15
- removeRow(this.state.managers.render.pool, components[index]);
17
+ this.removeRow(rows[index]);
16
18
  }
17
19
 
18
- this.components.clear();
20
+ components.clear();
21
+ }
22
+
23
+ destroy(): void {
24
+ this.clear();
19
25
 
20
26
  this.components = undefined as never;
21
27
  this.state = undefined as never;
22
28
  }
23
29
 
24
- get(key: Key): RowComponent | undefined {
30
+ get(key: Key, create: boolean): RowComponent | undefined {
25
31
  let row = this.components.get(key);
26
32
 
27
- if (row == null) {
33
+ if (row == null && create) {
28
34
  row = new RowComponent(key);
29
35
 
30
36
  this.components.set(key, row);
@@ -41,10 +47,16 @@ export class RowManager {
41
47
  const row = this.components.get(key);
42
48
 
43
49
  if (row != null) {
44
- removeRow(this.state.managers.render.pool, row);
50
+ this.removeRow(row);
51
+ }
52
+ }
45
53
 
46
- this.components.delete(key);
54
+ removeRow(row: RowComponent): void {
55
+ if (row.element != null) {
56
+ removeRow(this.state.managers.render.pool, row);
47
57
  }
58
+
59
+ this.components.delete(row.key);
48
60
  }
49
61
 
50
62
  update(key: Key): void {
@@ -4,12 +4,17 @@ import {setAttribute} from '@oscarpalmer/toretto/attribute';
4
4
  import {getPosition, on} from '@oscarpalmer/toretto/event';
5
5
  import {findAncestor} from '@oscarpalmer/toretto/find';
6
6
  import type {EventPosition} from '@oscarpalmer/toretto/models';
7
+ import {GroupComponent} from '../components/group.component';
7
8
  import {createElement} from '../helpers/dom.helpers';
8
9
  import {getKey} from '../helpers/misc.helpers';
9
- import {dragStyling} from '../helpers/style.helper';
10
+ import {preventSelection} from '../helpers/style.helper';
10
11
  import type {TabelaSelection} from '../models/selection.model';
12
+ import {
13
+ CSS_TABELA_ROW_BODY,
14
+ CSS_TABELA_ROW_SELECTED,
15
+ CSS_TABELA_SELECTION,
16
+ } from '../models/style.model';
11
17
  import type {State} from '../models/tabela.model';
12
- import {GroupComponent} from '../components/group.component';
13
18
 
14
19
  export class SelectionManager {
15
20
  handlers = Object.freeze({
@@ -117,7 +122,7 @@ export class SelectionManager {
117
122
  return;
118
123
  }
119
124
 
120
- const {keys} = state.managers.data;
125
+ const {items} = state.managers.data;
121
126
 
122
127
  const fromIndex = state.managers.data.getIndex(fromKey);
123
128
  const toIndex = state.managers.data.getIndex(toKey);
@@ -131,10 +136,10 @@ export class SelectionManager {
131
136
  const selected: Key[] = [];
132
137
 
133
138
  for (let index = start; index <= end; index += 1) {
134
- const key = keys[index];
139
+ const item = items[index];
135
140
 
136
- if (!(key instanceof GroupComponent)) {
137
- selected.push(key);
141
+ if (!(item instanceof GroupComponent)) {
142
+ selected.push(item as Key);
138
143
  }
139
144
  }
140
145
 
@@ -184,38 +189,40 @@ export class SelectionManager {
184
189
 
185
190
  toggle(): void {
186
191
  const {items, state} = this;
187
- const {keys} = state.managers.data;
192
+ const data = state.managers.data.items;
188
193
 
189
- if (items.size === keys.length - state.managers.group.items.length) {
194
+ if (items.size === data.length - state.managers.group.items.length) {
190
195
  this.clear();
191
196
  } else {
192
- this.set(keys.filter(key => !(key instanceof GroupComponent)) as Key[]);
197
+ this.set(data.filter(key => !(key instanceof GroupComponent)) as Key[]);
193
198
  }
194
199
  }
195
200
 
196
201
  update(removed: Key[]): void {
202
+ const {state} = this;
203
+
197
204
  const items = [
198
205
  ...removed.map(key => ({key, removed: true})),
199
206
  ...[...this.items].map(key => ({key, removed: false})),
200
207
  ];
201
208
 
202
- const {length} = items;
209
+ let {length} = items;
203
210
 
204
211
  for (let index = 0; index < length; index += 1) {
205
212
  const {key, removed} = items[index];
206
213
 
207
- const row = this.state.managers.row.get(key);
214
+ const element = state.managers.row.get(key, false)?.element;
208
215
 
209
- if (row == null || row.element == null) {
216
+ if (element == null) {
210
217
  continue;
211
218
  }
212
219
 
213
- setAttribute(row.element, 'aria-selected', String(!removed));
220
+ setAttribute(element, 'aria-selected', String(!removed));
214
221
 
215
222
  if (removed) {
216
- row.element.classList.remove('tabela__row--selected');
223
+ element.classList.remove(CSS_TABELA_ROW_SELECTED);
217
224
  } else {
218
- row.element.classList.add('tabela__row--selected');
225
+ element.classList.add(CSS_TABELA_ROW_SELECTED);
219
226
  }
220
227
  }
221
228
  }
@@ -225,7 +232,7 @@ function getPlaceholder(): HTMLElement {
225
232
  placeholder ??= createElement(
226
233
  'div',
227
234
  {
228
- className: 'tabela__selection--placeholder',
235
+ className: CSS_TABELA_SELECTION,
229
236
  },
230
237
  {},
231
238
  {},
@@ -236,7 +243,7 @@ function getPlaceholder(): HTMLElement {
236
243
 
237
244
  function onMouseDown(event: MouseEvent): void {
238
245
  if (shifted) {
239
- const row = findAncestor(event.target as HTMLElement, '.tabela__row--body');
246
+ const row = findAncestor(event.target as HTMLElement, `.${CSS_TABELA_ROW_BODY}`);
240
247
 
241
248
  if (!(row instanceof HTMLElement)) {
242
249
  return;
@@ -245,7 +252,7 @@ function onMouseDown(event: MouseEvent): void {
245
252
  startElement = row;
246
253
  startPosition = getPosition(event)!;
247
254
 
248
- dragStyling.set();
255
+ preventSelection.set();
249
256
  }
250
257
  }
251
258
 
@@ -286,7 +293,7 @@ function onMouseUp(event: MouseEvent): void {
286
293
  if (!event.shiftKey) {
287
294
  shifted = false;
288
295
 
289
- dragStyling.remove();
296
+ preventSelection.remove();
290
297
  }
291
298
 
292
299
  getPlaceholder().remove();
@@ -296,8 +303,8 @@ function onMouseUp(event: MouseEvent): void {
296
303
  if (row instanceof HTMLElement) {
297
304
  endElement = row;
298
305
 
299
- const endTable = findAncestor(endElement, '.tabela');
300
- const startTable = findAncestor(startElement, '.tabela');
306
+ const endTable = findAncestor(endElement, '.tabela__table');
307
+ const startTable = findAncestor(startElement, '.tabela__table');
301
308
 
302
309
  if (startTable != null && startTable === endTable) {
303
310
  mapped.get(startTable)?.range(startElement, endElement);