@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
@@ -1,53 +0,0 @@
1
- import { on } from "@oscarpalmer/toretto/event";
2
- import { findAncestor } from "@oscarpalmer/toretto/find";
3
- var EventManager = class {
4
- constructor(state) {
5
- this.state = state;
6
- mapped.set(state.element, this);
7
- }
8
- destroy() {
9
- mapped.delete(this.state.element);
10
- this.state = void 0;
11
- }
12
- onSort(event, target) {
13
- const direction = target.getAttribute("data-sort-direction");
14
- const field = target.getAttribute("data-field");
15
- if (field != null) this.state.managers.sort.toggle(event, field, direction);
16
- }
17
- };
18
- function onClick(event) {
19
- const target = findAncestor(event, "[data-event]");
20
- const table = findAncestor(event, ".tabela");
21
- if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
22
- const manager = mapped.get(table);
23
- if (manager == null) return;
24
- switch (target?.getAttribute("data-event")) {
25
- case "group":
26
- manager.state.managers.group.handle(target);
27
- break;
28
- case "heading":
29
- manager.onSort(event, target);
30
- break;
31
- case "row":
32
- manager.state.managers.selection.handle(event, target);
33
- break;
34
- default: break;
35
- }
36
- }
37
- function onKeydown(event) {
38
- const target = findAncestor(event, "[data-event]");
39
- const table = findAncestor(event, ".tabela");
40
- if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
41
- const manager = mapped.get(table);
42
- if (manager == null) return;
43
- switch (target?.getAttribute("data-event")) {
44
- case "body":
45
- manager.state.managers.navigation.handle(event);
46
- break;
47
- default: break;
48
- }
49
- }
50
- var mapped = /* @__PURE__ */ new WeakMap();
51
- on(document, "click", onClick);
52
- on(document, "keydown", onKeydown, { passive: false });
53
- export { EventManager };
@@ -1,98 +0,0 @@
1
- import { GroupComponent } from "../components/group.component.js";
2
- import { getNumber } from "@oscarpalmer/atoms/number";
3
- import { getString } from "@oscarpalmer/atoms/string";
4
- import { endsWith, includes, startsWith } from "@oscarpalmer/atoms/string/match";
5
- import { equal } from "@oscarpalmer/atoms/value/equal";
6
- var FilterManager = class {
7
- handlers = Object.freeze({
8
- add: (item) => this.add(item),
9
- clear: () => this.clear(),
10
- remove: (value) => this.remove(value),
11
- set: (items) => this.set(items)
12
- });
13
- items = {};
14
- constructor(state) {
15
- this.state = state;
16
- }
17
- add(item) {
18
- if (this.items[item.field] == null) this.items[item.field] = [];
19
- else if (this.items[item.field].findIndex((existing) => equal(existing, item)) !== -1) return;
20
- this.items[item.field].push(item);
21
- this.filter();
22
- }
23
- clear() {
24
- if (Object.keys(this.items).length > 0) {
25
- this.items = {};
26
- this.filter();
27
- }
28
- }
29
- destroy() {
30
- this.handlers = void 0;
31
- this.items = void 0;
32
- this.state = void 0;
33
- }
34
- filter() {
35
- const { state } = this;
36
- const filtered = [];
37
- const filters = Object.entries(this.items);
38
- const keysLength = state.managers.data.values.keys.original.length;
39
- rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
40
- const key = state.managers.data.values.keys.original[keyIndex];
41
- if (key instanceof GroupComponent) {
42
- filtered.push(key);
43
- continue;
44
- }
45
- const row = state.managers.data.values.objects.mapped.get(key);
46
- if (row == null) continue;
47
- filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
48
- const [field, items] = filters[filterIndex];
49
- const value = row[field];
50
- for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
51
- const filter = items[itemIndex];
52
- if (comparators[filter.comparison](value, filter.value)) continue filterLoop;
53
- }
54
- continue rowLoop;
55
- }
56
- filtered.push(key);
57
- }
58
- state.managers.data.values.keys.active = filtered;
59
- if (state.managers.sort.items.length > 0) state.managers.sort.sort();
60
- else state.managers.render.update(true, true);
61
- }
62
- remove(value) {
63
- if (typeof value === "string") {
64
- if (this.items[value] == null) return;
65
- this.items = {};
66
- } else {
67
- const { field } = value;
68
- if (this.items[field] == null) return;
69
- if (this.items[field].findIndex((item) => equal(item, value)) === -1) return;
70
- }
71
- this.filter();
72
- }
73
- set(items) {
74
- const keyed = {};
75
- const { length } = items;
76
- for (let index = 0; index < length; index += 1) {
77
- const item = items[index];
78
- keyed[item.field] ??= [];
79
- keyed[item.field].push(item);
80
- }
81
- this.items = keyed;
82
- this.filter();
83
- }
84
- };
85
- var comparators = {
86
- contains: (row, filter) => includes(getString(row), getString(filter), true),
87
- "ends-with": (row, filter) => endsWith(getString(row), getString(filter), true),
88
- equals: (row, filter) => equalizer(row, filter),
89
- "greater-than": (row, filter) => getNumber(row) > getNumber(filter),
90
- "greater-than-or-equal": (row, filter) => getNumber(row) >= getNumber(filter),
91
- "less-than": (row, filter) => getNumber(row) < getNumber(filter),
92
- "less-than-or-equal": (row, filter) => getNumber(row) <= getNumber(filter),
93
- "not-contains": (row, filter) => !includes(getString(row), getString(filter), true),
94
- "not-equals": (row, filter) => !equalizer(row, filter),
95
- "starts-with": (row, filter) => startsWith(getString(row), getString(filter), true)
96
- };
97
- var equalizer = equal.initialize({ ignoreCase: true });
98
- export { FilterManager };
@@ -1,46 +0,0 @@
1
- import { sort } from "@oscarpalmer/atoms/array";
2
- import { toRecord } from "@oscarpalmer/atoms/array/to-record";
3
- import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
4
- var GroupManager = class {
5
- collapsed = /* @__PURE__ */ new Set();
6
- enabled = false;
7
- field;
8
- items = [];
9
- order = {};
10
- constructor(state) {
11
- this.state = state;
12
- if (isNullableOrWhitespace(state.options.grouping)) return;
13
- this.enabled = true;
14
- this.field = state.options.grouping;
15
- }
16
- add(group) {
17
- this.set([...this.items, group]);
18
- }
19
- get(value) {
20
- return this.items.find((item) => item.value === value);
21
- }
22
- handle(button) {
23
- const key = button.dataset.key;
24
- const group = this.get(key);
25
- if (group == null) return;
26
- const { collapsed, items, state } = this;
27
- group.expanded = !group.expanded;
28
- const index = items.indexOf(group);
29
- let first = state.managers.data.values.keys.original.indexOf(items[index]) + 1;
30
- const last = items[index + 1] == null ? state.managers.data.keys.length - 1 : state.managers.data.values.keys.original.indexOf(items[index + 1]) - 1;
31
- for (; first <= last; first += 1) {
32
- const key = state.managers.data.values.keys.original[first];
33
- if (group.expanded) collapsed.delete(key);
34
- else collapsed.add(key);
35
- }
36
- state.managers.render.update(true, true);
37
- }
38
- remove(group) {
39
- this.set(this.items.filter((item) => item !== group));
40
- }
41
- set(items) {
42
- this.items = sort(items, (item) => item.label);
43
- this.order = toRecord(items, "value", (_, index) => index);
44
- }
45
- };
46
- export { GroupManager };
@@ -1,73 +0,0 @@
1
- import { getKey } from "../helpers/misc.helpers.js";
2
- import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
3
- import { clamp } from "@oscarpalmer/atoms/number";
4
- var NavigationManager = class {
5
- active;
6
- constructor(state) {
7
- this.state = state;
8
- }
9
- destroy() {
10
- this.state = void 0;
11
- }
12
- handle(event) {
13
- if (!allKeys.has(event.key)) return;
14
- event.preventDefault();
15
- const { components, id, managers } = this.state;
16
- const activeDescendant = components.body.elements.group.getAttribute("aria-activedescendant");
17
- const { keys } = managers.data;
18
- const { length } = keys;
19
- let next;
20
- if (isNullableOrWhitespace(activeDescendant)) next = getDefaultIndex(event.key, length);
21
- else next = getIndex(event, activeDescendant, id, keys);
22
- if (next != null) this.setActive(keys.at(next));
23
- }
24
- setActive(key, scroll) {
25
- const { components, managers, options } = this.state;
26
- this.active = key;
27
- const active = components.body.elements.group.querySelectorAll("[data-active=\"true\"]");
28
- for (const item of active) item.setAttribute("data-active", "false");
29
- const row = managers.row.get(key);
30
- if (row != null) {
31
- row.element?.setAttribute("data-active", "true");
32
- if (scroll ?? true) if (row.element == null) components.body.elements.group.scrollTo({
33
- top: managers.data.getIndex(key) * options.rowHeight,
34
- behavior: "smooth"
35
- });
36
- else row.element.scrollIntoView({ block: "nearest" });
37
- }
38
- components.body.elements.group.setAttribute("aria-activedescendant", row == null ? "" : `tabela_${this.state.id}_row_${key}`);
39
- }
40
- };
41
- function getDefaultIndex(key, max) {
42
- switch (true) {
43
- case negativeDefaultKeys.has(key): return -1;
44
- case key === "PageDown": return Math.min(9, max - 1);
45
- case key === "PageUp": return max < 10 ? 0 : max - 10;
46
- default: return 0;
47
- }
48
- }
49
- function getIndex(event, active, id, keys) {
50
- const key = getKey(active.replace(`tabela_${id}_row_`, ""));
51
- if (key == null) return;
52
- if (absoluteKeys.has(event.key)) return event.key === "Home" ? 0 : keys.length - 1;
53
- return clamp(keys.indexOf(key) + getOffset(event.key), 0, keys.length - 1, true);
54
- }
55
- function getOffset(key) {
56
- switch (key) {
57
- case "ArrowDown": return 1;
58
- case "ArrowUp": return -1;
59
- case "PageDown": return 10;
60
- case "PageUp": return -10;
61
- default: return 0;
62
- }
63
- }
64
- var absoluteKeys = new Set(["End", "Home"]);
65
- var arrowKeys = new Set(["ArrowDown", "ArrowUp"]);
66
- var negativeDefaultKeys = new Set(["ArrowUp", "End"]);
67
- var pageKeys = new Set(["PageDown", "PageUp"]);
68
- var allKeys = new Set([
69
- ...absoluteKeys,
70
- ...arrowKeys,
71
- ...pageKeys
72
- ]);
73
- export { NavigationManager };
@@ -1,135 +0,0 @@
1
- import { GroupComponent, renderGroup } from "../components/group.component.js";
2
- import { removeRow, renderRow } from "../components/row.component.js";
3
- import { on } from "@oscarpalmer/toretto/event";
4
- function getRange(state, down) {
5
- const { components, managers, options } = state;
6
- const { clientHeight, scrollTop } = components.body.elements.group;
7
- const { keys } = managers.data;
8
- const first = Math.floor(scrollTop / options.rowHeight);
9
- const last = Math.min(keys.length - managers.group.collapsed.size - 1, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
10
- const before = Math.ceil(clientHeight / options.rowHeight) * (down ? 1 : 2);
11
- const after = Math.ceil(clientHeight / options.rowHeight) * (down ? 2 : 1);
12
- const start = Math.max(0, first - before);
13
- return {
14
- end: Math.min(keys.length - managers.group.collapsed.size - 1, last + after),
15
- start
16
- };
17
- }
18
- function onScroll() {
19
- const { state } = this;
20
- if (!state.active) {
21
- requestAnimationFrame(() => {
22
- const top = state.components.body.elements.group.scrollTop;
23
- this.update(top > state.top);
24
- state.active = false;
25
- state.top = top;
26
- });
27
- state.active = true;
28
- }
29
- }
30
- var RenderManager = class {
31
- fragment;
32
- listener;
33
- pool = {
34
- cells: {},
35
- rows: []
36
- };
37
- state;
38
- visible = /* @__PURE__ */ new Map();
39
- constructor(state) {
40
- this.listener = on(state.components.body.elements.group, "scroll", onScroll.bind(this));
41
- this.state = {
42
- ...state,
43
- active: false,
44
- top: 0
45
- };
46
- }
47
- destroy() {
48
- const { listener, pool, visible } = this;
49
- listener();
50
- visible.clear();
51
- pool.cells = {};
52
- pool.rows = [];
53
- this.fragment = void 0;
54
- this.listener = void 0;
55
- this.pool = void 0;
56
- this.state = void 0;
57
- this.visible = void 0;
58
- }
59
- removeCells(fields) {
60
- const { pool, state, visible } = this;
61
- const { length } = fields;
62
- for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
63
- for (const [, key] of visible) {
64
- if (key instanceof GroupComponent) continue;
65
- const row = state.managers.row.get(key);
66
- if (row == null || row.element == null) continue;
67
- for (let index = 0; index < length; index += 1) {
68
- row.cells[fields[index]].innerHTML = "";
69
- row.cells[fields[index]].remove();
70
- delete row.cells[fields[index]];
71
- }
72
- }
73
- }
74
- getFragment() {
75
- this.fragment ??= document.createDocumentFragment();
76
- this.fragment.replaceChildren();
77
- return this.fragment;
78
- }
79
- update(down, rerender) {
80
- const { state, pool, visible } = this;
81
- const { components, managers, options } = state;
82
- components.body.elements.faker.style.height = `${(managers.data.size - managers.group.collapsed.size) * options.rowHeight}px`;
83
- const indices = /* @__PURE__ */ new Set();
84
- const range = getRange(state, down);
85
- for (let index = range.start; index <= range.end; index += 1) indices.add(index);
86
- let remove = rerender ?? false;
87
- for (const [index, key] of visible) {
88
- if (key instanceof GroupComponent) {
89
- if (remove || !indices.has(index)) {
90
- visible.delete(index);
91
- key.element?.remove();
92
- }
93
- continue;
94
- }
95
- const row = managers.row.get(key);
96
- if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
97
- visible.delete(index);
98
- if (row != null) removeRow(pool, row);
99
- }
100
- }
101
- const fragment = this.getFragment();
102
- const { keys } = managers.data;
103
- let count = 0;
104
- let offset = 0;
105
- for (let index = range.start; index <= range.end + offset; index += 1) {
106
- if (visible.has(index)) continue;
107
- const key = keys[index];
108
- if (key instanceof GroupComponent) {
109
- count += 1;
110
- renderGroup(state, key);
111
- visible.set(index, key);
112
- if (key.element != null) {
113
- key.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
114
- fragment.append(key.element);
115
- }
116
- continue;
117
- }
118
- const row = managers.row.get(key);
119
- if (row == null) continue;
120
- if (managers.group.collapsed.has(key)) {
121
- offset += 1;
122
- continue;
123
- }
124
- count += 1;
125
- renderRow(state, row);
126
- visible.set(index, key);
127
- if (row.element != null) {
128
- row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
129
- fragment.append(row.element);
130
- }
131
- }
132
- if (count > 0) components.body.elements.group[down ? "append" : "prepend"](fragment);
133
- }
134
- };
135
- export { RenderManager };
@@ -1,38 +0,0 @@
1
- import { RowComponent, removeRow, renderRow } from "../components/row.component.js";
2
- var RowManager = class {
3
- components = /* @__PURE__ */ new Map();
4
- constructor(state) {
5
- this.state = state;
6
- }
7
- destroy() {
8
- const components = [...this.components.values()];
9
- const { length } = components;
10
- for (let index = 0; index < length; index += 1) removeRow(this.state.managers.render.pool, components[index]);
11
- this.components.clear();
12
- this.components = void 0;
13
- this.state = void 0;
14
- }
15
- get(key) {
16
- let row = this.components.get(key);
17
- if (row == null) {
18
- row = new RowComponent(key);
19
- this.components.set(key, row);
20
- }
21
- return row;
22
- }
23
- has(key) {
24
- return this.components.has(key);
25
- }
26
- remove(key) {
27
- const row = this.components.get(key);
28
- if (row != null) {
29
- removeRow(this.state.managers.render.pool, row);
30
- this.components.delete(key);
31
- }
32
- }
33
- update(key) {
34
- const row = this.components.get(key);
35
- if (row != null) renderRow(this.state, row);
36
- }
37
- };
38
- export { RowManager };
@@ -1,122 +0,0 @@
1
- import { GroupComponent } from "../components/group.component.js";
2
- import { setAttribute, setAttributes } from "@oscarpalmer/toretto/attribute";
3
- import { sort } from "@oscarpalmer/atoms/array";
4
- import { compare } from "@oscarpalmer/atoms/value/compare";
5
- var SortManager = class {
6
- handlers = Object.freeze({
7
- add: (field, direction) => this.add(field, direction),
8
- flip: (field) => this.flip(field),
9
- clear: () => this.clear(),
10
- remove: (field) => this.remove(field),
11
- set: (items) => this.set(items)
12
- });
13
- items = [];
14
- constructor(state) {
15
- this.state = state;
16
- }
17
- add(field, direction) {
18
- if (this.items.findIndex((item) => item.key === field) > -1) return;
19
- this.items.push({
20
- key: field,
21
- direction: direction ?? "ascending"
22
- });
23
- this.sort();
24
- }
25
- addOrSet(event, field) {
26
- if (event.ctrlKey || event.metaKey) this.add(field);
27
- else this.set([{
28
- field,
29
- direction: "ascending"
30
- }]);
31
- }
32
- clear() {
33
- if (this.items.length > 0) {
34
- this.items.length = 0;
35
- this.sort();
36
- }
37
- }
38
- destroy() {
39
- this.handlers = void 0;
40
- this.items = void 0;
41
- this.state = void 0;
42
- }
43
- flip(field) {
44
- const item = this.items.find((item) => item.key === field);
45
- if (item == null) return;
46
- item.direction = item.direction === "ascending" ? "descending" : "ascending";
47
- this.sort();
48
- }
49
- remove(field) {
50
- const index = this.items.findIndex((item) => item.key === field);
51
- if (index > -1) {
52
- this.items.splice(index, 1);
53
- this.sort();
54
- }
55
- }
56
- removeOrClear(event, field) {
57
- if (event.ctrlKey || event.metaKey) this.remove(field);
58
- else this.clear();
59
- }
60
- set(items) {
61
- this.items.splice(0, this.items.length, ...items.map((item) => ({
62
- key: item.field,
63
- direction: item.direction
64
- })));
65
- this.sort();
66
- }
67
- sort() {
68
- const { items, state } = this;
69
- const { length } = state.managers.column.items;
70
- for (let index = 0; index < length; index += 1) {
71
- const column = state.managers.column.items[index];
72
- const sorterIndex = items.findIndex((item) => item.key === column.options.field);
73
- const sorterItem = items[sorterIndex];
74
- setAttributes(column.elements.wrapper, {
75
- "aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
76
- "data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
77
- });
78
- setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
79
- }
80
- state.managers.data.values.keys.active = items.length === 0 ? void 0 : getSortedKeys(state, items);
81
- state.managers.render.update(true, true);
82
- }
83
- toggle(event, field, direction) {
84
- switch (direction) {
85
- case "ascending":
86
- this.flip(field);
87
- return;
88
- case "descending":
89
- this.removeOrClear(event, field);
90
- return;
91
- default:
92
- this.addOrSet(event, field);
93
- return;
94
- }
95
- }
96
- };
97
- function getSortedKeys(state, sorters) {
98
- const data = state.managers.data.values.keys.active?.map((key) => key instanceof GroupComponent ? key : state.managers.data.values.objects.mapped.get(key)) ?? state.managers.data.values.objects.array.slice();
99
- if (!state.managers.group.enabled) return sort(data, sorters).map((item) => item[state.key]);
100
- return sortWithGroups(state, data, sorters).map((item) => item instanceof GroupComponent ? item : item[state.key]);
101
- }
102
- function sortWithGroups(state, data, sorters) {
103
- const { length } = sorters;
104
- return data.sort((first, second) => {
105
- const firstValue = first instanceof GroupComponent ? first.value : first[state.managers.group.field];
106
- const secondValue = second instanceof GroupComponent ? second.value : second[state.managers.group.field];
107
- const firstOrder = state.managers.group.order[firstValue];
108
- const secondOrder = state.managers.group.order[secondValue];
109
- const groupComparison = compare(firstOrder, secondOrder);
110
- if (groupComparison !== 0) return groupComparison;
111
- const firstIsGroup = first instanceof GroupComponent;
112
- const secondIsGroup = second instanceof GroupComponent;
113
- if (firstIsGroup || secondIsGroup) return firstIsGroup && secondIsGroup ? 0 : firstIsGroup ? -1 : 1;
114
- for (let index = 0; index < length; index += 1) {
115
- const sorter = sorters[index];
116
- const comparison = compare(first[sorter.key], second[sorter.key]);
117
- if (comparison !== 0) return comparison * (sorter.direction === "ascending" ? 1 : -1);
118
- }
119
- return 0;
120
- });
121
- }
122
- export { SortManager, sortWithGroups };
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes