@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
@@ -0,0 +1,80 @@
1
+ import { ARIA_ACTIVEDESCENDANT, ATTRIBUTE_DATA_ACTIVE } from "../models/dom.model.mjs";
2
+ import { getKey, isGroupKey } from "../helpers/misc.helpers.mjs";
3
+ import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
4
+ import { clamp } from "@oscarpalmer/atoms/number";
5
+ //#region src/managers/navigation.manager.ts
6
+ var NavigationManager = class {
7
+ active;
8
+ constructor(state) {
9
+ this.state = state;
10
+ }
11
+ destroy() {
12
+ this.state = void 0;
13
+ }
14
+ handle(event) {
15
+ if (!allKeys.has(event.key)) return;
16
+ event.preventDefault();
17
+ const { components, managers } = this.state;
18
+ const activeDescendant = components.body.elements.group.getAttribute(ARIA_ACTIVEDESCENDANT);
19
+ const { keys } = managers.data;
20
+ const { length } = keys;
21
+ let next;
22
+ if (isNullableOrWhitespace(activeDescendant)) next = getDefaultIndex(event.key, length);
23
+ else next = getIndex(this.state, event, activeDescendant);
24
+ if (next != null) this.setActive(keys.at(next));
25
+ }
26
+ setActive(item, scroll) {
27
+ const { components, managers, options, prefix } = this.state;
28
+ this.active = item;
29
+ const active = components.body.elements.group.querySelectorAll(attributeDataActiveTrue);
30
+ for (const item of active) item.setAttribute(ATTRIBUTE_DATA_ACTIVE, "false");
31
+ const component = isGroupKey(item) ? managers.group.getForKey(item) : managers.row.get(item, false);
32
+ if (component != null) {
33
+ component.element?.setAttribute(ATTRIBUTE_DATA_ACTIVE, "true");
34
+ if (scroll ?? true) if (component.element == null) components.body.elements.group.scrollTo({
35
+ top: managers.data.getIndex(item) * options.rowHeight,
36
+ behavior: "smooth"
37
+ });
38
+ else component.element.scrollIntoView({ block: "nearest" });
39
+ }
40
+ components.body.elements.group.setAttribute(ARIA_ACTIVEDESCENDANT, component == null ? "" : `${prefix}${component.key}`);
41
+ }
42
+ };
43
+ function getDefaultIndex(key, max) {
44
+ switch (true) {
45
+ case negativeDefaultKeys.has(key): return -1;
46
+ case key === KEY_PAGE_DOWN: return Math.min(9, max - 1);
47
+ case key === KEY_PAGE_UP: return max < 10 ? 0 : max - 10;
48
+ default: return 0;
49
+ }
50
+ }
51
+ function getIndex(state, event, active) {
52
+ const key = getKey(active.replace(state.prefix, ""));
53
+ if (key == null) return;
54
+ if (absoluteKeys.has(event.key)) return event.key === KEY_HOME ? 0 : state.managers.data.size - 1;
55
+ return clamp(state.managers.data.getIndex(key) + (offset[event.key] ?? 0), 0, state.managers.data.size - 1, true);
56
+ }
57
+ const KEY_ARROW_DOWN = "ArrowDown";
58
+ const KEY_ARROW_UP = "ArrowUp";
59
+ const KEY_END = "End";
60
+ const KEY_HOME = "Home";
61
+ const KEY_PAGE_DOWN = "PageDown";
62
+ const KEY_PAGE_UP = "PageUp";
63
+ const absoluteKeys = new Set([KEY_END, KEY_HOME]);
64
+ const arrowKeys = new Set([KEY_ARROW_DOWN, KEY_ARROW_UP]);
65
+ const attributeDataActiveTrue = `[${ATTRIBUTE_DATA_ACTIVE}="true"]`;
66
+ const negativeDefaultKeys = new Set([KEY_ARROW_UP, KEY_END]);
67
+ const offset = {
68
+ [KEY_ARROW_DOWN]: 1,
69
+ [KEY_ARROW_UP]: -1,
70
+ [KEY_PAGE_DOWN]: 10,
71
+ [KEY_PAGE_UP]: -10
72
+ };
73
+ const pageKeys = new Set([KEY_PAGE_DOWN, KEY_PAGE_UP]);
74
+ const allKeys = new Set([
75
+ ...absoluteKeys,
76
+ ...arrowKeys,
77
+ ...pageKeys
78
+ ]);
79
+ //#endregion
80
+ export { NavigationManager, attributeDataActiveTrue };
@@ -0,0 +1,19 @@
1
+ import { RenderElementPool, RenderState, RenderVisible } from "../models/render.model.mjs";
2
+ import { State } from "../models/tabela.model.mjs";
3
+ import { RemovableEventListener } from "@oscarpalmer/toretto/models";
4
+
5
+ //#region src/managers/render.manager.d.ts
6
+ declare class RenderManager {
7
+ fragment: DocumentFragment;
8
+ listener: RemovableEventListener;
9
+ pool: RenderElementPool;
10
+ state: RenderState;
11
+ visible: RenderVisible;
12
+ constructor(state: State);
13
+ destroy(): void;
14
+ removeCells(keys: string[]): void;
15
+ getFragment(): DocumentFragment;
16
+ update(down: boolean, rerender?: boolean): void;
17
+ }
18
+ //#endregion
19
+ export { RenderManager };
@@ -0,0 +1,157 @@
1
+ import { renderGroup } from "../components/group.component.mjs";
2
+ import { isGroupKey } from "../helpers/misc.helpers.mjs";
3
+ import { removeRow, renderRow } from "../components/row.component.mjs";
4
+ import { on } from "@oscarpalmer/toretto/event";
5
+ //#region src/managers/render.manager.ts
6
+ function getRange(state, down) {
7
+ const { element, managers, options } = state;
8
+ const { clientHeight, scrollTop } = element;
9
+ const { keys } = managers.data;
10
+ const firstIndex = Math.floor(scrollTop / options.rowHeight);
11
+ const lastIndex = keys.length - managers.group.collapsed.size - 1;
12
+ const last = Math.min(lastIndex, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
13
+ const visible = clientHeight / options.rowHeight;
14
+ const before = Math.ceil(visible) * (down ? 1 : 2);
15
+ const after = Math.ceil(visible) * (down ? 2 : 1);
16
+ const start = Math.max(0, firstIndex - before);
17
+ return {
18
+ end: Math.min(lastIndex, last + after),
19
+ start
20
+ };
21
+ }
22
+ function onScroll() {
23
+ const { state } = this;
24
+ if (!state.active) {
25
+ requestAnimationFrame(() => {
26
+ const top = state.element.scrollTop;
27
+ this.update(top > state.top);
28
+ state.active = false;
29
+ state.top = top;
30
+ });
31
+ state.active = true;
32
+ }
33
+ }
34
+ var RenderManager = class {
35
+ fragment;
36
+ listener;
37
+ pool = {
38
+ cells: {},
39
+ rows: []
40
+ };
41
+ state;
42
+ visible = {
43
+ indiced: /* @__PURE__ */ new Map(),
44
+ keys: /* @__PURE__ */ new Set()
45
+ };
46
+ constructor(state) {
47
+ this.listener = on(state.element, "scroll", onScroll.bind(this));
48
+ this.state = {
49
+ ...state,
50
+ active: false,
51
+ top: 0
52
+ };
53
+ }
54
+ destroy() {
55
+ const { listener, pool, visible } = this;
56
+ listener();
57
+ visible.indiced.clear();
58
+ visible.keys.clear();
59
+ const cells = Object.values(pool.cells).flat();
60
+ let { length } = cells;
61
+ for (let index = 0; index < length; index += 1) cells[index].remove();
62
+ length = pool.rows.length;
63
+ for (let index = 0; index < length; index += 1) pool.rows[index].remove();
64
+ pool.cells = {};
65
+ pool.rows = [];
66
+ this.fragment = void 0;
67
+ this.listener = void 0;
68
+ this.pool = void 0;
69
+ this.state = void 0;
70
+ this.visible = void 0;
71
+ }
72
+ removeCells(keys) {
73
+ const { pool, state, visible } = this;
74
+ const { length } = keys;
75
+ for (let index = 0; index < length; index += 1) delete pool.cells[keys[index]];
76
+ for (const [, key] of visible.indiced) {
77
+ if (isGroupKey(key)) continue;
78
+ const row = state.managers.row.get(key, false);
79
+ if (row == null || row.element == null) continue;
80
+ for (let index = 0; index < length; index += 1) {
81
+ row.cells[keys[index]].innerHTML = "";
82
+ row.cells[keys[index]].remove();
83
+ delete row.cells[keys[index]];
84
+ }
85
+ }
86
+ }
87
+ getFragment() {
88
+ this.fragment ??= document.createDocumentFragment();
89
+ this.fragment.replaceChildren();
90
+ return this.fragment;
91
+ }
92
+ update(down, rerender) {
93
+ const { state, pool, visible } = this;
94
+ const { components, managers, options } = state;
95
+ components.body.elements.faker.style.height = `${(managers.data.size - managers.group.collapsed.size) * options.rowHeight}px`;
96
+ const indices = /* @__PURE__ */ new Set();
97
+ const range = getRange(state, down);
98
+ for (let index = range.start; index <= range.end; index += 1) indices.add(index);
99
+ let remove = rerender ?? false;
100
+ for (const [index, key] of visible.indiced) {
101
+ if (isGroupKey(key)) {
102
+ if (remove || !indices.has(index)) {
103
+ visible.indiced.delete(index);
104
+ visible.keys.delete(key);
105
+ state.managers.group.getForKey(key)?.element?.remove();
106
+ }
107
+ continue;
108
+ }
109
+ const row = managers.row.get(key, false);
110
+ if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
111
+ visible.indiced.delete(index);
112
+ visible.keys.delete(key);
113
+ if (row != null) removeRow(pool, row);
114
+ }
115
+ }
116
+ const fragment = this.getFragment();
117
+ const { keys } = managers.data;
118
+ let count = 0;
119
+ let offset = 0;
120
+ for (let index = range.start; index <= range.end + offset; index += 1) {
121
+ if (visible.indiced.has(index)) continue;
122
+ const key = keys[index];
123
+ if (isGroupKey(key)) {
124
+ const group = managers.group.getForKey(key);
125
+ if (group == null) continue;
126
+ count += 1;
127
+ renderGroup(state, group);
128
+ visible.indiced.set(index, group.key);
129
+ visible.keys.add(group.key);
130
+ if (group.element != null) {
131
+ group.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
132
+ fragment.append(group.element);
133
+ }
134
+ continue;
135
+ }
136
+ const row = managers.row.get(key, true);
137
+ if (row == null) continue;
138
+ if (managers.group.collapsed.has(key)) {
139
+ offset += 1;
140
+ continue;
141
+ }
142
+ count += 1;
143
+ renderRow(state, row);
144
+ visible.indiced.set(index, key);
145
+ visible.keys.add(key);
146
+ if (row.element != null) {
147
+ row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
148
+ fragment.append(row.element);
149
+ }
150
+ }
151
+ if (count === 0) return;
152
+ if (down) components.body.elements.group.append(fragment);
153
+ else components.body.elements.group.prepend(fragment);
154
+ }
155
+ };
156
+ //#endregion
157
+ export { RenderManager };
@@ -0,0 +1,19 @@
1
+ import { RowComponent } from "../components/row.component.mjs";
2
+ import { State } from "../models/tabela.model.mjs";
3
+ import { Key } from "@oscarpalmer/atoms/models";
4
+
5
+ //#region src/managers/row.manager.d.ts
6
+ declare class RowManager {
7
+ state: State;
8
+ components: Map<Key, RowComponent>;
9
+ constructor(state: State);
10
+ clear(): void;
11
+ destroy(): void;
12
+ get(key: Key, create: boolean): RowComponent | undefined;
13
+ has(key: Key): boolean;
14
+ remove(key: Key): void;
15
+ removeRow(row: RowComponent): void;
16
+ update(key: Key): void;
17
+ }
18
+ //#endregion
19
+ export { RowManager };
@@ -0,0 +1,45 @@
1
+ import { RowComponent, removeRow, renderRow } from "../components/row.component.mjs";
2
+ //#region src/managers/row.manager.ts
3
+ var RowManager = class {
4
+ components = /* @__PURE__ */ new Map();
5
+ constructor(state) {
6
+ this.state = state;
7
+ }
8
+ clear() {
9
+ const { components } = this;
10
+ const rows = [...components.values()];
11
+ const { length } = rows;
12
+ for (let index = 0; index < length; index += 1) this.removeRow(rows[index]);
13
+ components.clear();
14
+ }
15
+ destroy() {
16
+ this.clear();
17
+ this.components = void 0;
18
+ this.state = void 0;
19
+ }
20
+ get(key, create) {
21
+ let row = this.components.get(key);
22
+ if (row == null && create) {
23
+ row = new RowComponent(key);
24
+ this.components.set(key, row);
25
+ }
26
+ return row;
27
+ }
28
+ has(key) {
29
+ return this.components.has(key);
30
+ }
31
+ remove(key) {
32
+ const row = this.components.get(key);
33
+ if (row != null) this.removeRow(row);
34
+ }
35
+ removeRow(row) {
36
+ if (row.element != null) removeRow(this.state.managers.render.pool, row);
37
+ this.components.delete(row.key);
38
+ }
39
+ update(key) {
40
+ const row = this.components.get(key);
41
+ if (row?.element != null) renderRow(this.state, row);
42
+ }
43
+ };
44
+ //#endregion
45
+ export { RowManager };
@@ -0,0 +1,23 @@
1
+ import { TabelaSelection } from "../models/selection.model.mjs";
2
+ import { State } from "../models/tabela.model.mjs";
3
+ import { Key } from "@oscarpalmer/atoms/models";
4
+
5
+ //#region src/managers/selection.manager.d.ts
6
+ declare class SelectionManager {
7
+ state: State;
8
+ handlers: TabelaSelection;
9
+ items: Set<Key>;
10
+ last: Key | undefined;
11
+ constructor(state: State);
12
+ add(keys: Key[]): void;
13
+ clear(): void;
14
+ destroy(): void;
15
+ handle(event: MouseEvent, target: HTMLElement): void;
16
+ range(from: Key | HTMLElement, to: Key | HTMLElement): void;
17
+ remove(keys: Key[]): void;
18
+ set(keys: Key[]): void;
19
+ toggle(): void;
20
+ update(removed: Key[]): void;
21
+ }
22
+ //#endregion
23
+ export { SelectionManager };
@@ -1,19 +1,21 @@
1
- import { createElement } from "../helpers/dom.helpers.js";
2
- import { GroupComponent } from "../components/group.component.js";
3
- import { getKey } from "../helpers/misc.helpers.js";
4
- import { dragStyling } from "../helpers/style.helper.js";
1
+ import { ARIA_SELECTED, ATTRIBUTE_DATA_KEY } from "../models/dom.model.mjs";
2
+ import { CSS_ROW_BODY, CSS_ROW_SELECTED, CSS_SELECTION, CSS_TABLE } from "../models/style.model.mjs";
3
+ import { createElement } from "../helpers/dom.helpers.mjs";
4
+ import { getKey, isGroupKey } from "../helpers/misc.helpers.mjs";
5
+ import { preventSelection } from "../helpers/style.helper.mjs";
5
6
  import { setAttribute } from "@oscarpalmer/toretto/attribute";
6
7
  import { isKey } from "@oscarpalmer/atoms/is";
7
8
  import { getPosition, on } from "@oscarpalmer/toretto/event";
8
9
  import { findAncestor } from "@oscarpalmer/toretto/find";
10
+ //#region src/managers/selection.manager.ts
9
11
  var SelectionManager = class {
10
- handlers = Object.freeze({
12
+ handlers = {
11
13
  add: (keys) => this.add(keys),
12
14
  clear: () => this.clear(),
13
15
  remove: (keys) => this.remove(keys),
14
16
  set: (keys) => this.set(keys),
15
17
  toggle: () => this.toggle()
16
- });
18
+ };
17
19
  items = /* @__PURE__ */ new Set();
18
20
  last;
19
21
  constructor(state) {
@@ -46,7 +48,7 @@ var SelectionManager = class {
46
48
  this.state = void 0;
47
49
  }
48
50
  handle(event, target) {
49
- const key = getKey(target.getAttribute("data-key"));
51
+ const key = getKey(target.getAttribute(ATTRIBUTE_DATA_KEY));
50
52
  if (key == null) return;
51
53
  const { items } = this;
52
54
  if (event.shiftKey) {
@@ -66,8 +68,8 @@ var SelectionManager = class {
66
68
  range(from, to) {
67
69
  const { state } = this;
68
70
  const keyed = isKey(from) && isKey(to);
69
- const fromKey = keyed ? from : getKey(from.getAttribute("data-key"));
70
- const toKey = keyed ? to : getKey(to.getAttribute("data-key"));
71
+ const fromKey = keyed ? from : getKey(from.getAttribute(ATTRIBUTE_DATA_KEY));
72
+ const toKey = keyed ? to : getKey(to.getAttribute(ATTRIBUTE_DATA_KEY));
71
73
  if (fromKey === toKey) return;
72
74
  const { keys } = state.managers.data;
73
75
  const fromIndex = state.managers.data.getIndex(fromKey);
@@ -77,7 +79,7 @@ var SelectionManager = class {
77
79
  const selected = [];
78
80
  for (let index = start; index <= end; index += 1) {
79
81
  const key = keys[index];
80
- if (!(key instanceof GroupComponent)) selected.push(key);
82
+ if (!isGroupKey(key)) selected.push(key);
81
83
  }
82
84
  if (keyed) this.add(selected);
83
85
  else this.set(selected);
@@ -105,9 +107,10 @@ var SelectionManager = class {
105
107
  const { items, state } = this;
106
108
  const { keys } = state.managers.data;
107
109
  if (items.size === keys.length - state.managers.group.items.length) this.clear();
108
- else this.set(keys.filter((key) => !(key instanceof GroupComponent)));
110
+ else this.set(keys.filter((key) => !isGroupKey(key)));
109
111
  }
110
112
  update(removed) {
113
+ const { state } = this;
111
114
  const items = [...removed.map((key) => ({
112
115
  key,
113
116
  removed: true
@@ -115,28 +118,28 @@ var SelectionManager = class {
115
118
  key,
116
119
  removed: false
117
120
  }))];
118
- const { length } = items;
121
+ let { length } = items;
119
122
  for (let index = 0; index < length; index += 1) {
120
123
  const { key, removed } = items[index];
121
- const row = this.state.managers.row.get(key);
122
- if (row == null || row.element == null) continue;
123
- setAttribute(row.element, "aria-selected", String(!removed));
124
- if (removed) row.element.classList.remove("tabela__row--selected");
125
- else row.element.classList.add("tabela__row--selected");
124
+ const element = state.managers.row.get(key, false)?.element;
125
+ if (element == null) continue;
126
+ setAttribute(element, ARIA_SELECTED, String(!removed));
127
+ if (removed) element.classList.remove(CSS_ROW_SELECTED);
128
+ else element.classList.add(CSS_ROW_SELECTED);
126
129
  }
127
130
  }
128
131
  };
129
132
  function getPlaceholder() {
130
- placeholder ??= createElement("div", { className: "tabela__selection--placeholder" }, {}, {});
133
+ placeholder ??= createElement("div", { className: CSS_SELECTION });
131
134
  return placeholder;
132
135
  }
133
136
  function onMouseDown(event) {
134
137
  if (shifted) {
135
- const row = findAncestor(event.target, ".tabela__row--body");
138
+ const row = findAncestor(event.target, `.${CSS_ROW_BODY}`);
136
139
  if (!(row instanceof HTMLElement)) return;
137
140
  startElement = row;
138
141
  startPosition = getPosition(event);
139
- dragStyling.set();
142
+ preventSelection.set();
140
143
  }
141
144
  }
142
145
  function onMouseMove(event) {
@@ -157,14 +160,14 @@ function onMouseUp(event) {
157
160
  if (startElement == null) return;
158
161
  if (!event.shiftKey) {
159
162
  shifted = false;
160
- dragStyling.remove();
163
+ preventSelection.remove();
161
164
  }
162
165
  getPlaceholder().remove();
163
- const row = findAncestor(event.target, ".tabela__row--body");
166
+ const row = findAncestor(event.target, bodyRowSelector);
164
167
  if (row instanceof HTMLElement) {
165
168
  endElement = row;
166
- const endTable = findAncestor(endElement, ".tabela");
167
- const startTable = findAncestor(startElement, ".tabela");
169
+ const endTable = findAncestor(endElement, tableSelector);
170
+ const startTable = findAncestor(startElement, tableSelector);
168
171
  if (startTable != null && startTable === endTable) mapped.get(startTable)?.range(startElement, endElement);
169
172
  }
170
173
  endElement = void 0;
@@ -172,7 +175,7 @@ function onMouseUp(event) {
172
175
  startPosition = void 0;
173
176
  }
174
177
  function onShift(event, value) {
175
- if (event.key === "Shift") shifted = value;
178
+ if (event.key === KEY_SHIFT) shifted = value;
176
179
  }
177
180
  function onShiftDown(event) {
178
181
  onShift(event, true);
@@ -180,15 +183,19 @@ function onShiftDown(event) {
180
183
  function onShiftUp(event) {
181
184
  onShift(event, false);
182
185
  }
183
- var mapped = /* @__PURE__ */ new WeakMap();
184
- var shifted = false;
185
- var endElement;
186
- var placeholder;
187
- var startPosition;
188
- var startElement;
186
+ const KEY_SHIFT = "Shift";
187
+ const mapped = /* @__PURE__ */ new WeakMap();
188
+ const bodyRowSelector = `.${CSS_ROW_BODY}`;
189
+ const tableSelector = `.${CSS_TABLE}`;
190
+ let shifted = false;
191
+ let endElement;
192
+ let placeholder;
193
+ let startPosition;
194
+ let startElement;
189
195
  on(document, "keydown", onShiftDown);
190
196
  on(document, "keyup", onShiftUp);
191
197
  on(document, "mousedown", onMouseDown);
192
198
  on(document, "mousemove", onMouseMove);
193
199
  on(document, "mouseup", onMouseUp);
200
+ //#endregion
194
201
  export { SelectionManager };
@@ -0,0 +1,23 @@
1
+ import { DataValue } from "../models/data.model.mjs";
2
+ import { TabelaSort, TabelaSortDirection, TabelaSortItem } from "../models/sort.model.mjs";
3
+ import { State } from "../models/tabela.model.mjs";
4
+
5
+ //#region src/managers/sort.manager.d.ts
6
+ declare class SortManager {
7
+ state: State;
8
+ handlers: TabelaSort;
9
+ items: TabelaSortItem[];
10
+ constructor(state: State);
11
+ add(key: string, direction?: TabelaSortDirection): void;
12
+ addOrSet(event: MouseEvent, key: string): void;
13
+ clear(): void;
14
+ destroy(): void;
15
+ flip(key: string): void;
16
+ remove(key: string): void;
17
+ set(items: TabelaSortItem[], set: boolean): void;
18
+ sort(): void;
19
+ toggle(event: MouseEvent, key: string, direction?: string | null): void;
20
+ }
21
+ declare function sortWithGroups(state: State, data: DataValue[], sorters: TabelaSortItem[]): DataValue[];
22
+ //#endregion
23
+ export { SortManager, sortWithGroups };
@@ -0,0 +1,147 @@
1
+ import { ARIA_SORT, ATTRIBUTE_DATA_SORT_DIRECTION, ATTRIBUTE_DATA_SORT_POSITION } from "../models/dom.model.mjs";
2
+ import { EVENT_DATA_SORTED, EVENT_SORT_ADD, EVENT_SORT_CLEAR, EVENT_SORT_FLIP, EVENT_SORT_REMOVE, EVENT_SORT_SET } from "../models/event.model.mjs";
3
+ import { isGroupKey } from "../helpers/misc.helpers.mjs";
4
+ import { SORT_ASCENDING, SORT_DESCENDING } from "../models/sort.model.mjs";
5
+ import { setAttribute, setAttributes } from "@oscarpalmer/toretto/attribute";
6
+ import { sort } from "@oscarpalmer/atoms/array";
7
+ import { getValue } from "@oscarpalmer/atoms/value/handle";
8
+ import { compare } from "@oscarpalmer/atoms/value/compare";
9
+ //#region src/managers/sort.manager.ts
10
+ var SortManager = class {
11
+ handlers = {
12
+ add: (field, direction) => this.add(field, direction),
13
+ flip: (field) => this.flip(field),
14
+ clear: () => this.clear(),
15
+ remove: (field) => this.remove(field),
16
+ set: (items) => this.set(items, true)
17
+ };
18
+ items = [];
19
+ constructor(state) {
20
+ this.state = state;
21
+ }
22
+ add(key, direction) {
23
+ if (this.items.findIndex((item) => item.key === key) > -1) return;
24
+ this.items.push({
25
+ key,
26
+ direction: direction ?? "ascending"
27
+ });
28
+ this.state.managers.event.emit(EVENT_SORT_ADD, [{
29
+ key,
30
+ direction: direction ?? "ascending"
31
+ }]);
32
+ this.sort();
33
+ }
34
+ addOrSet(event, key) {
35
+ if (event.ctrlKey || event.metaKey) this.add(key);
36
+ else this.set([{
37
+ key,
38
+ direction: SORT_ASCENDING
39
+ }], false);
40
+ }
41
+ clear() {
42
+ if (this.items.length === 0) return;
43
+ this.items.length = 0;
44
+ this.state.managers.event.emit(EVENT_SORT_CLEAR);
45
+ this.sort();
46
+ }
47
+ destroy() {
48
+ this.handlers = void 0;
49
+ this.items = void 0;
50
+ this.state = void 0;
51
+ }
52
+ flip(key) {
53
+ const item = this.items.find((item) => item.key === key);
54
+ if (item == null) return;
55
+ item.direction = item.direction === "ascending" ? SORT_DESCENDING : SORT_ASCENDING;
56
+ this.state.managers.event.emit(EVENT_SORT_FLIP, [{
57
+ key,
58
+ direction: item.direction
59
+ }]);
60
+ this.sort();
61
+ }
62
+ remove(key) {
63
+ const index = this.items.findIndex((item) => item.key === key);
64
+ if (index === -1) return;
65
+ const spliced = this.items.splice(index, 1);
66
+ this.state.managers.event.emit(EVENT_SORT_REMOVE, spliced);
67
+ if (this.items.length === 0) this.state.managers.event.emit(EVENT_SORT_CLEAR);
68
+ this.sort();
69
+ }
70
+ set(items, set) {
71
+ const removed = this.items.splice(0, this.items.length, ...items.map((item) => ({
72
+ key: item.key,
73
+ direction: item.direction
74
+ })));
75
+ if (set) this.state.managers.event.emit(EVENT_SORT_SET, {
76
+ removed,
77
+ added: items.map((item) => ({
78
+ key: item.key,
79
+ direction: item.direction
80
+ }))
81
+ });
82
+ else this.state.managers.event.emit(EVENT_SORT_ADD, items.map((item) => ({
83
+ key: item.key,
84
+ direction: item.direction
85
+ })));
86
+ this.sort();
87
+ }
88
+ sort() {
89
+ const { items, state } = this;
90
+ const { length } = state.managers.column.items;
91
+ for (let index = 0; index < length; index += 1) {
92
+ const column = state.managers.column.items[index];
93
+ const sorterIndex = items.findIndex((item) => item.key === column.options.key);
94
+ const sorterItem = items[sorterIndex];
95
+ setAttributes(column.elements.wrapper, {
96
+ [ARIA_SORT]: sorterItem == null ? SORT_NONE : items.length > 1 ? SORT_OTHER : sorterItem.direction,
97
+ [ATTRIBUTE_DATA_SORT_DIRECTION]: sorterItem == null ? void 0 : sorterItem.direction
98
+ });
99
+ setAttribute(column.elements.sorter, ATTRIBUTE_DATA_SORT_POSITION, sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
100
+ }
101
+ state.managers.data.state.keys.active = items.length === 0 ? void 0 : getSortedItems(state, items);
102
+ state.managers.event.emit(EVENT_DATA_SORTED, state.managers.data.get(true));
103
+ state.managers.render.update(true, true);
104
+ }
105
+ toggle(event, key, direction) {
106
+ switch (direction) {
107
+ case SORT_ASCENDING:
108
+ this.flip(key);
109
+ return;
110
+ case SORT_DESCENDING:
111
+ this.remove(key);
112
+ return;
113
+ default:
114
+ this.addOrSet(event, key);
115
+ return;
116
+ }
117
+ }
118
+ };
119
+ function getSortedItems(state, sorters) {
120
+ const data = state.managers.data.state.keys.active?.map((key) => isGroupKey(key) ? key : state.managers.data.state.values.mapped.get(key)) ?? state.managers.data.state.values.array;
121
+ if (!state.managers.group.enabled) return sort(data, sorters).map((item) => getValue(item, state.key));
122
+ return sortWithGroups(state, data, sorters).map((item) => isGroupKey(item) ? item : getValue(item, state.key));
123
+ }
124
+ function sortWithGroups(state, data, sorters) {
125
+ const { length } = sorters;
126
+ return data.sort((first, second) => {
127
+ const firstIsGroup = isGroupKey(first);
128
+ const secondIsGroup = isGroupKey(second);
129
+ const firstValue = firstIsGroup ? state.managers.group.getForKey(first).value.stringified : getValue(first, state.managers.group.key);
130
+ const secondValue = secondIsGroup ? state.managers.group.getForKey(second).value.stringified : getValue(second, state.managers.group.key);
131
+ const firstOrder = state.managers.group.order[firstValue];
132
+ const secondOrder = state.managers.group.order[secondValue];
133
+ const groupComparison = compare(firstOrder, secondOrder);
134
+ if (groupComparison !== 0) return groupComparison;
135
+ if (firstIsGroup || secondIsGroup) return firstIsGroup && secondIsGroup ? 0 : firstIsGroup ? -1 : 1;
136
+ for (let index = 0; index < length; index += 1) {
137
+ const sorter = sorters[index];
138
+ const comparison = compare(getValue(first, sorter.key), getValue(second, sorter.key));
139
+ if (comparison !== 0) return comparison * (sorter.direction === "ascending" ? 1 : -1);
140
+ }
141
+ return 0;
142
+ });
143
+ }
144
+ const SORT_NONE = "none";
145
+ const SORT_OTHER = "other";
146
+ //#endregion
147
+ export { SortManager, sortWithGroups };
@@ -0,0 +1,9 @@
1
+ import { State } from "../models/tabela.model.mjs";
2
+
3
+ //#region src/managers/style.manager.d.ts
4
+ declare class StyleManager {
5
+ readonly state: State;
6
+ constructor(state: State);
7
+ }
8
+ //#endregion
9
+ export { StyleManager };