@oscarpalmer/tabela 0.11.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 (159) 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} +12 -9
  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} +14 -10
  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} +12 -8
  38. package/dist/managers/filter.manager.d.mts +2 -0
  39. package/dist/managers/{filter.manager.js → filter.manager.mjs} +25 -11
  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.mjs +144 -0
  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} +57 -48
  50. package/dist/managers/sort.manager.d.mts +2 -0
  51. package/dist/managers/{sort.manager.js → sort.manager.mjs} +32 -2
  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} +1407 -1124
  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 +19 -24
  89. package/src/components/footer.component.ts +8 -3
  90. package/src/components/group.component.ts +85 -0
  91. package/src/components/header.component.ts +3 -2
  92. package/src/components/row.component.ts +10 -8
  93. package/src/helpers/dom.helpers.ts +24 -20
  94. package/src/helpers/style.helper.ts +1 -1
  95. package/src/managers/column.manager.ts +8 -4
  96. package/src/managers/data.manager.ts +265 -61
  97. package/src/managers/event.manager.ts +14 -11
  98. package/src/managers/filter.manager.ts +38 -19
  99. package/src/managers/group.manager.ts +131 -0
  100. package/src/managers/navigation.manager.ts +25 -23
  101. package/src/managers/render.manager.ts +84 -32
  102. package/src/managers/row.manager.ts +23 -11
  103. package/src/managers/selection.manager.ts +68 -54
  104. package/src/managers/sort.manager.ts +81 -16
  105. package/src/managers/style.manager.ts +156 -0
  106. package/src/models/column.model.ts +2 -2
  107. package/src/models/data.model.ts +23 -9
  108. package/src/models/filter.model.ts +11 -3
  109. package/src/models/group.model.ts +8 -0
  110. package/src/models/render.model.ts +2 -2
  111. package/src/models/selection.model.ts +9 -0
  112. package/src/models/sort.model.ts +11 -3
  113. package/src/models/style.model.ts +39 -0
  114. package/src/models/tabela.model.ts +14 -46
  115. package/src/models/tabela.options.ts +3 -2
  116. package/src/tabela.ts +72 -41
  117. package/dist/helpers/style.helper.js +0 -6
  118. package/dist/managers/data.manager.js +0 -120
  119. package/dist/managers/render.manager.js +0 -110
  120. package/dist/models/body.model.js +0 -0
  121. package/dist/models/column.model.js +0 -0
  122. package/dist/models/data.model.js +0 -0
  123. package/dist/models/filter.model.js +0 -0
  124. package/dist/models/footer.model.js +0 -0
  125. package/dist/models/header.model.js +0 -0
  126. package/dist/models/render.model.js +0 -0
  127. package/dist/models/sort.model.js +0 -0
  128. package/dist/models/tabela.model.js +0 -0
  129. package/dist/models/tabela.options.js +0 -0
  130. package/dist/tabela.js +0 -102
  131. package/types/components/body.component.d.ts +0 -6
  132. package/types/components/column.component.d.ts +0 -13
  133. package/types/components/footer.component.d.ts +0 -8
  134. package/types/components/header.component.d.ts +0 -8
  135. package/types/components/row.component.d.ts +0 -11
  136. package/types/helpers/dom.helpers.d.ts +0 -10
  137. package/types/helpers/misc.helpers.d.ts +0 -2
  138. package/types/helpers/style.helper.d.ts +0 -1
  139. package/types/index.d.ts +0 -4
  140. package/types/managers/column.manager.d.ts +0 -12
  141. package/types/managers/data.manager.d.ts +0 -27
  142. package/types/managers/event.manager.d.ts +0 -7
  143. package/types/managers/filter.manager.d.ts +0 -19
  144. package/types/managers/navigation.manager.d.ts +0 -10
  145. package/types/managers/render.manager.d.ts +0 -16
  146. package/types/managers/row.manager.d.ts +0 -13
  147. package/types/managers/selection.manager.d.ts +0 -18
  148. package/types/managers/sort.manager.d.ts +0 -26
  149. package/types/models/body.model.d.ts +0 -4
  150. package/types/models/column.model.d.ts +0 -13
  151. package/types/models/data.model.d.ts +0 -14
  152. package/types/models/filter.model.d.ts +0 -6
  153. package/types/models/footer.model.d.ts +0 -5
  154. package/types/models/header.model.d.ts +0 -4
  155. package/types/models/render.model.d.ts +0 -13
  156. package/types/models/sort.model.d.ts +0 -5
  157. package/types/models/tabela.model.d.ts +0 -69
  158. package/types/models/tabela.options.d.ts +0 -9
  159. package/types/tabela.d.ts +0 -12
@@ -1,4 +1,89 @@
1
- function compact$1(array, strict) {
1
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/is.mjs
2
+ /**
3
+ * Is the value an event target?
4
+ * @param value Value to check
5
+ * @returns `true` if it's an event target, otherwise `false`
6
+ */
7
+ function isEventTarget(value) {
8
+ return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
9
+ }
10
+ /**
11
+ * Is the value an HTML or SVG element?
12
+ * @param value Value to check
13
+ * @returns `true` if it's an HTML or SVG element, otherwise `false`
14
+ */
15
+ function isHTMLOrSVGElement(value) {
16
+ return value instanceof HTMLElement || value instanceof SVGElement;
17
+ }
18
+ new Set([
19
+ Node.ELEMENT_NODE,
20
+ Node.TEXT_NODE,
21
+ Node.PROCESSING_INSTRUCTION_NODE,
22
+ Node.COMMENT_NODE,
23
+ Node.DOCUMENT_TYPE_NODE
24
+ ]);
25
+ //#endregion
26
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
27
+ /**
28
+ * Is the value a constructor function?
29
+ * @param value Value to check
30
+ * @returns `true` if the value is a constructor function, otherwise `false`
31
+ */
32
+ function isConstructor(value) {
33
+ return typeof value === "function" && value.prototype?.constructor === value;
34
+ }
35
+ /**
36
+ * Is the value a key?
37
+ * @param value Value to check
38
+ * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
39
+ */
40
+ function isKey(value) {
41
+ return typeof value === "number" || typeof value === "string";
42
+ }
43
+ /**
44
+ * Is the value a number?
45
+ * @param value Value to check
46
+ * @returns `true` if the value is a `number`, otherwise `false`
47
+ */
48
+ function isNumber(value) {
49
+ return typeof value === "number" && !Number.isNaN(value);
50
+ }
51
+ /**
52
+ * Is the value a plain object?
53
+ * @param value Value to check
54
+ * @returns `true` if the value is a plain object, otherwise `false`
55
+ */
56
+ function isPlainObject(value) {
57
+ if (value === null || typeof value !== "object") return false;
58
+ if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
59
+ const prototype = Object.getPrototypeOf(value);
60
+ return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
61
+ }
62
+ /**
63
+ * Is the value a typed array?
64
+ * @param value Value to check
65
+ * @returns `true` if the value is a typed array, otherwise `false`
66
+ */
67
+ function isTypedArray(value) {
68
+ TYPED_ARRAYS ??= new Set([
69
+ Int8Array,
70
+ Uint8Array,
71
+ Uint8ClampedArray,
72
+ Int16Array,
73
+ Uint16Array,
74
+ Int32Array,
75
+ Uint32Array,
76
+ Float32Array,
77
+ Float64Array,
78
+ BigInt64Array,
79
+ BigUint64Array
80
+ ]);
81
+ return TYPED_ARRAYS.has(value?.constructor);
82
+ }
83
+ let TYPED_ARRAYS;
84
+ //#endregion
85
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/compact.mjs
86
+ function compact(array, strict) {
2
87
  if (!Array.isArray(array)) return [];
3
88
  if (strict === true) return array.filter(Boolean);
4
89
  const { length } = array;
@@ -9,56 +94,143 @@ function compact$1(array, strict) {
9
94
  }
10
95
  return compacted;
11
96
  }
97
+ //#endregion
98
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
12
99
  /**
13
100
  * Get the string value from any value
14
101
  * @param value Original value
15
102
  * @returns String representation of the value
16
103
  */
17
- function getString$1(value) {
104
+ function getString(value) {
18
105
  if (typeof value === "string") return value;
19
106
  if (value == null) return "";
20
- if (typeof value === "function") return getString$1(value());
107
+ if (typeof value === "function") return getString(value());
21
108
  if (typeof value !== "object") return String(value);
22
109
  const asString = String(value.valueOf?.() ?? value);
23
110
  return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
24
111
  }
112
+ function ignoreKey(key) {
113
+ return EXPRESSION_IGNORED.test(key);
114
+ }
25
115
  /**
26
116
  * Join an array of values into a string
27
117
  * @param value Array of values
28
118
  * @param delimiter Delimiter to use between values
29
119
  * @returns Joined string
30
120
  */
31
- function join$1(value, delimiter) {
32
- return compact$1(value).map(getString$1).join(typeof delimiter === "string" ? delimiter : "");
121
+ function join(value, delimiter) {
122
+ return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
33
123
  }
34
124
  /**
35
125
  * Split a string into words _(and other readable parts)_
36
126
  * @param value Original string
37
127
  * @returns Array of words found in the string
38
128
  */
39
- function words$1(value) {
40
- return typeof value === "string" ? value.match(EXPRESSION_WORDS$1) ?? [] : [];
129
+ function words(value) {
130
+ return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
41
131
  }
42
- var EXPRESSION_WORDS$1 = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
132
+ const EXPRESSION_IGNORED = /(^|\.)(__proto__|constructor|prototype)(\.|$)/i;
133
+ const EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
134
+ //#endregion
135
+ //#region node_modules/@oscarpalmer/atoms/dist/is.mjs
43
136
  /**
44
- * Is the value a number?
137
+ * Is the value `undefined`, `null`, or a whitespace-only string?
45
138
  * @param value Value to check
46
- * @returns `true` if the value is a `number`, otherwise `false`
139
+ * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
47
140
  */
48
- function isNumber$1(value) {
49
- return typeof value === "number" && !Number.isNaN(value);
141
+ function isNullableOrWhitespace(value) {
142
+ return value == null || EXPRESSION_WHITESPACE.test(getString(value));
143
+ }
144
+ const EXPRESSION_WHITESPACE = /^\s*$/;
145
+ //#endregion
146
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/element-value.mjs
147
+ function setElementValue(element, first, second, third, callback) {
148
+ if (!isHTMLOrSVGElement(element)) return;
149
+ if (typeof first === "string") setElementValues(element, first, second, third, callback);
150
+ else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback);
151
+ }
152
+ function setElementValues(element, first, second, third, callback) {
153
+ if (!isHTMLOrSVGElement(element)) return;
154
+ if (typeof first === "string") {
155
+ callback(element, first, second, third);
156
+ return;
157
+ }
158
+ const isArray = Array.isArray(first);
159
+ if (!isArray && !(typeof first === "object" && first !== null)) return;
160
+ const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
161
+ name,
162
+ value
163
+ }));
164
+ const { length } = entries;
165
+ for (let index = 0; index < length; index += 1) {
166
+ const entry = entries[index];
167
+ if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value, third);
168
+ }
169
+ }
170
+ function updateElementValue(element, key, value, set, remove, isBoolean, json) {
171
+ if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
172
+ else set.call(element, key, json ? JSON.stringify(value) : String(value));
173
+ }
174
+ //#endregion
175
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/attribute.mjs
176
+ function isAttribute(value) {
177
+ return value instanceof Attr || isPlainObject(value) && typeof value.name === "string" && "value" in value;
178
+ }
179
+ function updateAttribute(element, name, value, dispatch) {
180
+ const normalizedName = name.toLowerCase();
181
+ const isBoolean = booleanAttributesSet.has(normalizedName);
182
+ const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === normalizedName) : value == null ? "" : value;
183
+ if (name in element) updateProperty(element, normalizedName, next, dispatch);
184
+ updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
185
+ }
186
+ function updateProperty(element, name, value, dispatch) {
187
+ if (Object.is(element[name], value)) return;
188
+ element[name] = value;
189
+ const event = dispatch !== false && elementEvents[element.tagName]?.[name];
190
+ if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
50
191
  }
51
192
  /**
52
- * Is the value a plain object?
53
- * @param value Value to check
54
- * @returns `true` if the value is a plain object, otherwise `false`
193
+ * List of boolean attributes
55
194
  */
56
- function isPlainObject$1(value) {
57
- if (value === null || typeof value !== "object") return false;
58
- if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
59
- const prototype = Object.getPrototypeOf(value);
60
- return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
61
- }
195
+ const booleanAttributes = Object.freeze([
196
+ "async",
197
+ "autofocus",
198
+ "autoplay",
199
+ "checked",
200
+ "controls",
201
+ "default",
202
+ "defer",
203
+ "disabled",
204
+ "formnovalidate",
205
+ "hidden",
206
+ "inert",
207
+ "ismap",
208
+ "itemscope",
209
+ "loop",
210
+ "multiple",
211
+ "muted",
212
+ "nomodule",
213
+ "novalidate",
214
+ "open",
215
+ "playsinline",
216
+ "readonly",
217
+ "required",
218
+ "reversed",
219
+ "selected"
220
+ ]);
221
+ const booleanAttributesSet = new Set(booleanAttributes);
222
+ const elementEvents = {
223
+ DETAILS: { open: "toggle" },
224
+ INPUT: {
225
+ checked: "change",
226
+ value: "input"
227
+ },
228
+ SELECT: { value: "change" },
229
+ TEXTAREA: { value: "input" }
230
+ };
231
+ document.createElement("form");
232
+ //#endregion
233
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/number.mjs
62
234
  /**
63
235
  * Clamp a number between a minimum and maximum value
64
236
  * @param value Value to clamp
@@ -67,29 +239,59 @@ function isPlainObject$1(value) {
67
239
  * @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
68
240
  * @returns Clamped value
69
241
  */
70
- function clamp$1(value, minimum, maximum, loop) {
242
+ function clamp(value, minimum, maximum, loop) {
71
243
  if (![
72
244
  value,
73
245
  minimum,
74
246
  maximum
75
- ].every(isNumber$1)) return NaN;
247
+ ].every(isNumber)) return NaN;
76
248
  if (value < minimum) return loop === true ? maximum : minimum;
77
249
  return value > maximum ? loop === true ? minimum : maximum : value;
78
250
  }
79
- function getSizedMaximum$1(first, second) {
251
+ /**
252
+ * Get the number value from an unknown value _(based on Lodash)_
253
+ * @param value Original value
254
+ * @returns Original value as a number, or `NaN` if the value is unable to be parsed
255
+ */
256
+ function getNumber(value) {
257
+ if (typeof value === "number") return value;
258
+ if (typeof value === "bigint" || typeof value === "boolean") return Number(value);
259
+ if (value == null || typeof value === "symbol") return NaN;
260
+ if (typeof value === "function") return getNumber(value());
261
+ let parsed = value.valueOf();
262
+ if (typeof parsed === "object") parsed = parsed.toString();
263
+ if (typeof parsed !== "string") return getNumber(parsed);
264
+ const trimmed = parsed.trim();
265
+ if (trimmed.length === 0) return NaN;
266
+ if (EXPRESSION_ZEROISH.test(parsed)) return 0;
267
+ const isBinary = EXPRESSION_BINARY.test(trimmed);
268
+ if (isBinary || EXPRESSION_OCTAL.test(trimmed)) return Number.parseInt(trimmed.slice(2), isBinary ? 2 : OCTAL_VALUE);
269
+ return Number(EXPRESSION_HEX.test(trimmed) ? trimmed : trimmed.replace(EXPRESSION_UNDERSCORE, ""));
270
+ }
271
+ const EXPRESSION_BINARY = /^0b[01]+$/i;
272
+ const EXPRESSION_HEX = /^0x[0-9a-f]+$/i;
273
+ const EXPRESSION_OCTAL = /^0o[0-7]+$/i;
274
+ const EXPRESSION_UNDERSCORE = /_/g;
275
+ const EXPRESSION_ZEROISH = /^\s*0+\s*$/;
276
+ const OCTAL_VALUE = 8;
277
+ //#endregion
278
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/sized.mjs
279
+ function getSizedMaximum(first, second) {
80
280
  let actual;
81
281
  if (typeof first === "number") actual = first;
82
- else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT$1;
83
- return clamp$1(actual, 1, MAXIMUM_ABSOLUTE$1);
282
+ else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
283
+ return clamp(actual, 1, MAXIMUM_ABSOLUTE);
84
284
  }
85
- var MAXIMUM_ABSOLUTE$1 = 16777216;
86
- var MAXIMUM_DEFAULT$1 = 1048576;
285
+ const MAXIMUM_ABSOLUTE = 16777216;
286
+ const MAXIMUM_DEFAULT = 1048576;
287
+ //#endregion
288
+ //#region node_modules/@oscarpalmer/atoms/dist/sized/map.mjs
87
289
  /**
88
290
  * A Map with a maximum size
89
291
  *
90
292
  * Behavior is similar to a _LRU_-cache, where the least recently used entries are removed
91
293
  */
92
- var SizedMap$1 = class extends Map {
294
+ var SizedMap = class extends Map {
93
295
  /**
94
296
  * The maximum size of the Map
95
297
  */
@@ -104,7 +306,7 @@ var SizedMap$1 = class extends Map {
104
306
  return this.#maximumSize;
105
307
  }
106
308
  constructor(first, second) {
107
- const maximum = getSizedMaximum$1(first, second);
309
+ const maximum = getSizedMaximum(first, second);
108
310
  super();
109
311
  this.#maximumSize = maximum;
110
312
  if (Array.isArray(first)) {
@@ -130,7 +332,9 @@ var SizedMap$1 = class extends Map {
130
332
  return super.set(key, value);
131
333
  }
132
334
  };
133
- var Memoized$1 = class {
335
+ //#endregion
336
+ //#region node_modules/@oscarpalmer/atoms/dist/function/memoize.mjs
337
+ var Memoized = class {
134
338
  #state;
135
339
  /**
136
340
  * Maximum cache size
@@ -145,9 +349,9 @@ var Memoized$1 = class {
145
349
  return this.#state.cache?.size ?? NaN;
146
350
  }
147
351
  constructor(callback, options) {
148
- const cache = new SizedMap$1(options.cacheSize);
352
+ const cache = new SizedMap(options.cacheSize);
149
353
  const getter = (...parameters) => {
150
- const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join$1(parameters.map(getString$1), "_"));
354
+ const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), SEPARATOR));
151
355
  if (cache.has(key)) return cache.get(key);
152
356
  const value = callback(...parameters);
153
357
  cache.set(key, value);
@@ -206,11 +410,11 @@ var Memoized$1 = class {
206
410
  return this.#state.getter(...parameters);
207
411
  }
208
412
  };
209
- function getMemoizationOptions$1(input) {
210
- const { cacheKey, cacheSize } = isPlainObject$1(input) ? input : {};
413
+ function getMemoizationOptions(input) {
414
+ const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
211
415
  return {
212
416
  cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
213
- cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE$1
417
+ cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
214
418
  };
215
419
  }
216
420
  /**
@@ -219,17 +423,20 @@ function getMemoizationOptions$1(input) {
219
423
  * @param options Memoization options
220
424
  * @returns Memoized instance
221
425
  */
222
- function memoize$1(callback, options) {
223
- return new Memoized$1(callback, getMemoizationOptions$1(options));
426
+ function memoize(callback, options) {
427
+ return new Memoized(callback, getMemoizationOptions(options));
224
428
  }
225
- var DEFAULT_CACHE_SIZE$1 = 1024;
429
+ const DEFAULT_CACHE_SIZE = 1024;
430
+ const SEPARATOR = "_";
431
+ //#endregion
432
+ //#region node_modules/@oscarpalmer/atoms/dist/string/case.mjs
226
433
  /**
227
434
  * Convert a string to camel case _(thisIsCamelCase)_
228
435
  * @param value String to convert
229
436
  * @returns Camel-cased string
230
437
  */
231
438
  function camelCase(value) {
232
- return toCase("camel", value, true, false);
439
+ return toCase(CASE_CAMEL, value, true, false);
233
440
  }
234
441
  /**
235
442
  * Capitalize the first letter of a string _(and lowercase the rest)_
@@ -238,11 +445,11 @@ function camelCase(value) {
238
445
  */
239
446
  function capitalize(value) {
240
447
  if (typeof value !== "string" || value.length === 0) return "";
241
- memoizedCapitalize ??= memoize$1((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
448
+ memoizedCapitalize ??= memoize((v) => v.length === 1 ? v.toLocaleUpperCase() : `${v.charAt(0).toLocaleUpperCase()}${v.slice(1).toLocaleLowerCase()}`);
242
449
  return memoizedCapitalize.run(value);
243
450
  }
244
451
  function toCase(type, value, capitalizeAny, capitalizeFirst) {
245
- caseMemoizers[type] ??= memoize$1(toCaseCallback.bind({
452
+ caseMemoizers[type] ??= memoize(toCaseCallback.bind({
246
453
  type,
247
454
  capitalizeAny,
248
455
  capitalizeFirst
@@ -253,11 +460,11 @@ function toCaseCallback(value) {
253
460
  if (typeof value !== "string") return "";
254
461
  if (value.length < 1) return value;
255
462
  const { capitalizeAny, capitalizeFirst, type } = this;
256
- const parts = words$1(value);
463
+ const parts = words(value);
257
464
  const partsLength = parts.length;
258
465
  const cased = [];
259
466
  for (let partIndex = 0; partIndex < partsLength; partIndex += 1) {
260
- const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === "s" ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, REPLACEMENT_CAMEL_CASE).split("-");
467
+ const items = parts[partIndex].replace(EXPRESSION_ACRONYM, (full, one, two, three) => three === S ? full : `${one}-${two}${three}`).replace(EXPRESSION_CAMEL_CASE, REPLACEMENT_CAMEL_CASE).split("-");
261
468
  const itemsLength = items.length;
262
469
  const partResult = [];
263
470
  let itemCount = 0;
@@ -268,21 +475,31 @@ function toCaseCallback(value) {
268
475
  else partResult.push(capitalize(item));
269
476
  itemCount += 1;
270
477
  }
271
- cased.push(join$1(partResult, delimiters[type]));
272
- }
273
- return join$1(cased, delimiters[type]);
274
- }
275
- var caseMemoizers = {};
276
- var delimiters = {
277
- camel: "",
278
- kebab: "-",
279
- pascal: "",
280
- snake: "_"
478
+ cased.push(join(partResult, delimiters[type]));
479
+ }
480
+ return join(cased, delimiters[type]);
481
+ }
482
+ const CASE_CAMEL = "camel";
483
+ const CASE_KEBAB = "kebab";
484
+ const CASE_PASCAL = "pascal";
485
+ const CASE_SNAKE = "snake";
486
+ const DELIMTER_EMPTY = "";
487
+ const DELIMITER_HYPHEN = "-";
488
+ const DELIMITER_UNDERSCORE = "_";
489
+ const EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
490
+ const EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
491
+ const REPLACEMENT_CAMEL_CASE = "$1-$2";
492
+ const S = "s";
493
+ const caseMemoizers = {};
494
+ const delimiters = {
495
+ [CASE_CAMEL]: DELIMTER_EMPTY,
496
+ [CASE_KEBAB]: DELIMITER_HYPHEN,
497
+ [CASE_PASCAL]: DELIMTER_EMPTY,
498
+ [CASE_SNAKE]: DELIMITER_UNDERSCORE
281
499
  };
282
- var EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
283
- var EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
284
- var REPLACEMENT_CAMEL_CASE = "$1-$2";
285
- var memoizedCapitalize;
500
+ let memoizedCapitalize;
501
+ //#endregion
502
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/get-value.mjs
286
503
  function getBoolean(value, defaultValue) {
287
504
  return typeof value === "boolean" ? value : defaultValue ?? false;
288
505
  }
@@ -290,203 +507,40 @@ function getStyleValue(element, property, computed) {
290
507
  const name = camelCase(property);
291
508
  return computed ? getComputedStyle(element)[name] : element.style[name];
292
509
  }
510
+ //#endregion
511
+ //#region node_modules/@oscarpalmer/toretto/dist/attribute/set.mjs
512
+ function setAttribute(element, first, second, third) {
513
+ setElementValue(element, first, second, third, updateAttribute);
514
+ }
515
+ function setAttributes(element, attributes, dispatch) {
516
+ setElementValues(element, attributes, null, dispatch, updateAttribute);
517
+ }
518
+ //#endregion
519
+ //#region node_modules/@oscarpalmer/toretto/dist/style.mjs
293
520
  /**
294
- * Is the value an event target?
295
- * @param value Value to check
296
- * @returns `true` if it's an event target, otherwise `false`
521
+ * Get styles from an element
522
+ * @param element Element to get the styles from
523
+ * @param properties Styles to get
524
+ * @param computed Get the computed styles? _(defaults to `false`)_
525
+ * @returns Style values
297
526
  */
298
- function isEventTarget(value) {
299
- return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
527
+ function getStyles(element, properties, computed) {
528
+ const styles = {};
529
+ if (!(isHTMLOrSVGElement(element) && Array.isArray(properties))) return styles;
530
+ const { length } = properties;
531
+ for (let index = 0; index < length; index += 1) {
532
+ const property = properties[index];
533
+ if (typeof property === "string") styles[property] = getStyleValue(element, property, computed === true);
534
+ }
535
+ return styles;
300
536
  }
301
537
  /**
302
- * Is the value an HTML or SVG element?
303
- * @param value Value to check
304
- * @returns `true` if it's an HTML or SVG element, otherwise `false`
538
+ * Set styles on an element
539
+ * @param element Element to set the styles on
540
+ * @param styles Styles to set
305
541
  */
306
- function isHTMLOrSVGElement(value) {
307
- return value instanceof HTMLElement || value instanceof SVGElement;
308
- }
309
- new Set([
310
- Node.ELEMENT_NODE,
311
- Node.TEXT_NODE,
312
- Node.PROCESSING_INSTRUCTION_NODE,
313
- Node.COMMENT_NODE,
314
- Node.DOCUMENT_TYPE_NODE
315
- ]);
316
- /**
317
- * Is the value `undefined`, `null`, or a whitespace-only string?
318
- * @param value Value to check
319
- * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
320
- */
321
- function isNullableOrWhitespace$1(value) {
322
- return value == null || EXPRESSION_WHITESPACE$2.test(getString$1(value));
323
- }
324
- var EXPRESSION_WHITESPACE$2 = /^\s*$/;
325
- function setElementValue(element, first, second, third, callback) {
326
- if (!isHTMLOrSVGElement(element)) return;
327
- if (typeof first === "string") setElementValues(element, first, second, third, callback);
328
- else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback);
329
- }
330
- function setElementValues(element, first, second, third, callback) {
331
- if (!isHTMLOrSVGElement(element)) return;
332
- if (typeof first === "string") {
333
- callback(element, first, second, third);
334
- return;
335
- }
336
- const isArray = Array.isArray(first);
337
- if (!isArray && !(typeof first === "object" && first !== null)) return;
338
- const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
339
- name,
340
- value
341
- }));
342
- const { length } = entries;
343
- for (let index = 0; index < length; index += 1) {
344
- const entry = entries[index];
345
- if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value, third);
346
- }
347
- }
348
- function updateElementValue(element, key, value, set, remove, isBoolean, json) {
349
- if (isBoolean ? value == null : isNullableOrWhitespace$1(value)) remove.call(element, key);
350
- else set.call(element, key, json ? JSON.stringify(value) : String(value));
351
- }
352
- function badAttributeHandler(name, value) {
353
- if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
354
- if (EXPRESSION_CLOBBERED_NAME.test(name) && (value in document || value in formElement) || EXPRESSION_EVENT_NAME.test(name)) return true;
355
- if (EXPRESSION_SKIP_NAME.test(name) || EXPRESSION_URI_VALUE.test(value) || isValidSourceAttribute(name, value)) return false;
356
- return EXPRESSION_DATA_OR_SCRIPT.test(value);
357
- }
358
- function booleanAttributeHandler(name, value) {
359
- if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
360
- const normalizedName = name.toLowerCase();
361
- if (!booleanAttributesSet.has(normalizedName)) return false;
362
- const normalized = value.toLowerCase();
363
- return !(normalized.length === 0 || normalized === normalizedName);
364
- }
365
- function decodeAttribute(value) {
366
- textArea ??= document.createElement("textarea");
367
- textArea.innerHTML = value;
368
- return decodeURIComponent(textArea.value);
369
- }
370
- function handleAttribute(callback, decode, first, second) {
371
- let name;
372
- let value;
373
- if (isAttribute(first)) {
374
- name = first.name;
375
- value = String(first.value);
376
- } else if (typeof first === "string" && typeof second === "string") {
377
- name = first;
378
- value = second;
379
- }
380
- if (decode && value != null) value = decodeAttribute(value);
381
- return callback(name, value?.replace(EXPRESSION_WHITESPACE$1, ""));
382
- }
383
- function isAttribute(value) {
384
- return value instanceof Attr || isPlainObject$1(value) && typeof value.name === "string" && "value" in value;
385
- }
386
- function _isBadAttribute(first, second, decode) {
387
- return handleAttribute(badAttributeHandler, decode, first, second);
388
- }
389
- function _isEmptyNonBooleanAttribute(first, second, decode) {
390
- return handleAttribute((name, value) => name != null && value != null && !booleanAttributesSet.has(name) && value.trim().length === 0, decode, first, second);
391
- }
392
- function _isInvalidBooleanAttribute(first, second, decode) {
393
- return handleAttribute(booleanAttributeHandler, decode, first, second);
394
- }
395
- function isValidSourceAttribute(name, value) {
396
- return EXPRESSION_SOURCE_NAME.test(name) && EXPRESSION_SOURCE_VALUE.test(value);
397
- }
398
- function updateAttribute(element, name, value, dispatch) {
399
- const normalizedName = name.toLowerCase();
400
- const isBoolean = booleanAttributesSet.has(normalizedName);
401
- const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === normalizedName) : value == null ? "" : value;
402
- if (name in element) updateProperty(element, normalizedName, next, dispatch);
403
- updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
404
- }
405
- function updateProperty(element, name, value, dispatch) {
406
- if (Object.is(element[name], value)) return;
407
- element[name] = value;
408
- const event = dispatch !== false && elementEvents[element.tagName]?.[name];
409
- if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
410
- }
411
- var EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
412
- var EXPRESSION_DATA_OR_SCRIPT = /^(?:data|\w+script):/i;
413
- var EXPRESSION_EVENT_NAME = /^on/i;
414
- var EXPRESSION_SKIP_NAME = /^(aria-[-\w]+|data-[-\w.\u00B7-\uFFFF]+)$/i;
415
- var EXPRESSION_SOURCE_NAME = /^src$/i;
416
- var EXPRESSION_SOURCE_VALUE = /^data:/i;
417
- var EXPRESSION_URI_VALUE = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
418
- var EXPRESSION_WHITESPACE$1 = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
419
- /**
420
- * List of boolean attributes
421
- */
422
- const booleanAttributes = Object.freeze([
423
- "async",
424
- "autofocus",
425
- "autoplay",
426
- "checked",
427
- "controls",
428
- "default",
429
- "defer",
430
- "disabled",
431
- "formnovalidate",
432
- "hidden",
433
- "inert",
434
- "ismap",
435
- "itemscope",
436
- "loop",
437
- "multiple",
438
- "muted",
439
- "nomodule",
440
- "novalidate",
441
- "open",
442
- "playsinline",
443
- "readonly",
444
- "required",
445
- "reversed",
446
- "selected"
447
- ]);
448
- var booleanAttributesSet = new Set(booleanAttributes);
449
- var elementEvents = {
450
- DETAILS: { open: "toggle" },
451
- INPUT: {
452
- checked: "change",
453
- value: "input"
454
- },
455
- SELECT: { value: "change" },
456
- TEXTAREA: { value: "input" }
457
- };
458
- var formElement = document.createElement("form");
459
- var textArea;
460
- function setAttribute(element, first, second, third) {
461
- setElementValue(element, first, second, third, updateAttribute);
462
- }
463
- function setAttributes(element, attributes, dispatch) {
464
- setElementValues(element, attributes, null, dispatch, updateAttribute);
465
- }
466
- /**
467
- * Get styles from an element
468
- * @param element Element to get the styles from
469
- * @param properties Styles to get
470
- * @param computed Get the computed styles? _(defaults to `false`)_
471
- * @returns Style values
472
- */
473
- function getStyles(element, properties, computed) {
474
- const styles = {};
475
- if (!(isHTMLOrSVGElement(element) && Array.isArray(properties))) return styles;
476
- const { length } = properties;
477
- for (let index = 0; index < length; index += 1) {
478
- const property = properties[index];
479
- if (typeof property === "string") styles[property] = getStyleValue(element, property, computed === true);
480
- }
481
- return styles;
482
- }
483
- /**
484
- * Set styles on an element
485
- * @param element Element to set the styles on
486
- * @param styles Styles to set
487
- */
488
- function setStyles(element, styles) {
489
- setElementValues(element, styles, null, null, updateStyleProperty);
542
+ function setStyles(element, styles) {
543
+ setElementValues(element, styles, null, null, updateStyleProperty);
490
544
  }
491
545
  /**
492
546
  * Toggle styles for an element
@@ -527,27 +581,52 @@ function updateStyleProperty(element, key, value) {
527
581
  this.style[property] = "";
528
582
  }, false, false);
529
583
  }
584
+ //#endregion
585
+ //#region src/models/style.model.ts
586
+ const CSS_TABELA = "tabela";
587
+ const CSS_TABELA_CELL = "tabela__cell";
588
+ const CSS_TABELA_CELL_BODY = "tabela__cell--body";
589
+ const CSS_TABELA_CELL_FOOTER = "tabela__cell--footer";
590
+ const CSS_TABELA_FAKER = "tabela__faker";
591
+ const CSS_TABELA_HEADING = "tabela__heading";
592
+ const CSS_TABELA_HEADING_CONTENT = "tabela__heading__content";
593
+ const CSS_TABELA_HEADING_SORTER = "tabela__heading__sorter";
594
+ const CSS_TABELA_ROW = "tabela__row";
595
+ const CSS_TABELA_ROW_BODY = "tabela__row--body";
596
+ const CSS_TABELA_ROW_FOOTER = "tabela__row--footer";
597
+ const CSS_TABELA_ROW_GROUP = "tabela__row--group tabela__group";
598
+ const CSS_TABELA_ROW_HEADER = "tabela__row--header";
599
+ const CSS_TABELA_ROW_SELECTED = "tabela__row--selected";
600
+ const CSS_TABELA_ROWGROUP = "tabela__rowgroup";
601
+ const CSS_TABELA_ROWGROUP_BODY = "tabela__rowgroup--body";
602
+ const CSS_TABELA_ROWGROUP_FOOTER = "tabela__rowgroup--footer";
603
+ const CSS_TABELA_ROWGROUP_HEADER = "tabela__rowgroup--header";
604
+ const CSS_TABELA_SELECTION = "tabela__selection";
605
+ const CSS_TABELA_TABLE = "tabela__table";
606
+ //#endregion
607
+ //#region src/helpers/dom.helpers.ts
530
608
  function createCell(width, body) {
531
609
  const cell = createElement("div", {
532
- className: "tabela__cell",
610
+ className: CSS_TABELA_CELL,
533
611
  role: "cell"
534
612
  }, {}, { width: `${width}px` });
535
- if (body ?? true) cell.classList.add("tabela__cell--body");
613
+ if (body ?? true) cell.classList.add(CSS_TABELA_CELL_BODY);
536
614
  return cell;
537
615
  }
538
616
  function createElement(tagName, properties, attributes, style) {
539
617
  const element = document.createElement(tagName);
540
- const keys = Object.keys(properties);
541
- for (const key of keys) element[key] = properties[key];
542
- setAttributes(element, attributes);
543
- setStyles(element, style);
618
+ const props = properties ?? {};
619
+ const keys = Object.keys(props);
620
+ for (const key of keys) element[key] = props[key];
621
+ setAttributes(element, attributes ?? {});
622
+ setStyles(element, style ?? {});
544
623
  return element;
545
624
  }
546
625
  function createRowGroup(withRow) {
547
626
  const group = createElement("div", {
548
- className: "tabela__rowgroup",
627
+ className: CSS_TABELA_ROWGROUP,
549
628
  role: "rowgroup"
550
- }, {}, {});
629
+ });
551
630
  if (!(withRow ?? true)) return group;
552
631
  const row = createRow();
553
632
  group.append(row);
@@ -558,12 +637,14 @@ function createRowGroup(withRow) {
558
637
  }
559
638
  function createRow() {
560
639
  return createElement("div", {
561
- className: "tabela__row",
640
+ className: CSS_TABELA_ROW,
562
641
  role: "row"
563
- }, {}, {});
642
+ }, {}, { height: "32px" });
564
643
  }
644
+ //#endregion
645
+ //#region src/components/body.component.ts
565
646
  function createFaker() {
566
- return createElement("div", { className: "tabela__faker" }, {}, {});
647
+ return createElement("div", { className: CSS_TABELA_FAKER });
567
648
  }
568
649
  var BodyComponent = class {
569
650
  elements = {
@@ -573,7 +654,7 @@ var BodyComponent = class {
573
654
  constructor() {
574
655
  const group = createRowGroup(false);
575
656
  this.elements.group = group;
576
- group.className += " tabela__rowgroup--body";
657
+ group.className += ` ${CSS_TABELA_ROWGROUP_BODY}`;
577
658
  group.tabIndex = 0;
578
659
  group.setAttribute("data-event", "body");
579
660
  group.append(this.elements.faker);
@@ -583,6 +664,8 @@ var BodyComponent = class {
583
664
  this.elements.group = void 0;
584
665
  }
585
666
  };
667
+ //#endregion
668
+ //#region src/components/footer.component.ts
586
669
  var FooterComponent = class {
587
670
  elements;
588
671
  constructor() {
@@ -592,8 +675,8 @@ var FooterComponent = class {
592
675
  row,
593
676
  cells: []
594
677
  };
595
- group.className += " tabela__rowgroup--footer";
596
- row.className += " tabela__row--footer";
678
+ group.className += ` ${CSS_TABELA_ROWGROUP_FOOTER}`;
679
+ row.className += ` ${CSS_TABELA_ROW_FOOTER}`;
597
680
  }
598
681
  destroy() {
599
682
  this.elements.cells.length = 0;
@@ -607,13 +690,15 @@ var FooterComponent = class {
607
690
  elements.row.innerHTML = "";
608
691
  for (let index = 0; index < length; index += 1) {
609
692
  const cell = createCell(columns[index].options.width ?? 4, false);
610
- cell.className += " tabela__cell--footer";
693
+ cell.className += ` ${CSS_TABELA_CELL_FOOTER}`;
611
694
  cell.innerHTML = "&nbsp;";
612
695
  elements.cells.push(cell);
613
696
  elements.row.append(cell);
614
697
  }
615
698
  }
616
699
  };
700
+ //#endregion
701
+ //#region src/components/header.component.ts
617
702
  var HeaderComponent = class {
618
703
  elements;
619
704
  constructor() {
@@ -622,8 +707,8 @@ var HeaderComponent = class {
622
707
  group,
623
708
  row
624
709
  };
625
- group.className += " tabela__rowgroup--header";
626
- row.className += " tabela__row--header";
710
+ group.className += ` ${CSS_TABELA_ROWGROUP_HEADER}`;
711
+ row.className += ` ${CSS_TABELA_ROW_HEADER}`;
627
712
  }
628
713
  destroy() {
629
714
  this.elements.group = void 0;
@@ -634,16 +719,18 @@ var HeaderComponent = class {
634
719
  this.elements.row.append(...columns.map((column) => column.elements.wrapper));
635
720
  }
636
721
  };
722
+ //#endregion
723
+ //#region src/components/column.component.ts
637
724
  var ColumnComponent = class {
638
725
  elements;
639
726
  options;
640
- constructor(options) {
641
- const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (options.width ?? options.title.length * 1.5);
727
+ constructor(column) {
728
+ const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (column.width ?? column.title.length * 1.5);
642
729
  this.options = {
643
- ...options,
730
+ ...column,
644
731
  width
645
732
  };
646
- this.elements = createHeading(options.field, options.title, width);
733
+ this.elements = createHeading(this.options.field, this.options.title, width);
647
734
  }
648
735
  destroy() {
649
736
  this.elements.content.remove();
@@ -655,17 +742,17 @@ var ColumnComponent = class {
655
742
  };
656
743
  function createHeading(field, title, width) {
657
744
  const wrapper = createElement("div", {
658
- className: "tabela__heading",
745
+ className: CSS_TABELA_HEADING,
659
746
  role: "columnheader"
660
747
  }, {
661
748
  "data-event": "heading",
662
749
  "data-field": field
663
750
  }, { width: `${width}px` });
664
751
  const content = createElement("div", {
665
- className: "tabela__heading__content",
752
+ className: CSS_TABELA_HEADING_CONTENT,
666
753
  textContent: title
667
- }, {}, {});
668
- const sorter = createElement("div", { className: "tabela__heading__sorter" }, {}, {});
754
+ });
755
+ const sorter = createElement("div", { className: CSS_TABELA_HEADING_SORTER });
669
756
  wrapper.append(content, sorter);
670
757
  return {
671
758
  content,
@@ -673,6 +760,8 @@ function createHeading(field, title, width) {
673
760
  wrapper
674
761
  };
675
762
  }
763
+ //#endregion
764
+ //#region src/managers/column.manager.ts
676
765
  var ColumnManager = class {
677
766
  items = [];
678
767
  constructor(state) {
@@ -685,6 +774,9 @@ var ColumnManager = class {
685
774
  this.items = void 0;
686
775
  this.state = void 0;
687
776
  }
777
+ get(field) {
778
+ return this.items.find((item) => item.options.field === field);
779
+ }
688
780
  remove(value) {
689
781
  const { items, state } = this;
690
782
  const { components, managers } = state;
@@ -710,6 +802,31 @@ var ColumnManager = class {
710
802
  footer.update(items);
711
803
  }
712
804
  };
805
+ //#endregion
806
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/chunk.mjs
807
+ /**
808
+ * Chunk an array into smaller arrays
809
+ * @param array Array to chunk
810
+ * @param size Size of each chunk _(minimum is `1`, maximum is `5000`; defaults to `5000`)_
811
+ * @returns Array of arrays
812
+ */
813
+ function chunk(array, size) {
814
+ if (!Array.isArray(array)) return [];
815
+ if (array.length === 0) return [];
816
+ const { length } = array;
817
+ const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
818
+ if (length <= actualSize) return [array];
819
+ const chunks = [];
820
+ let index = 0;
821
+ while (index < length) {
822
+ chunks.push(array.slice(index, index + actualSize));
823
+ index += actualSize;
824
+ }
825
+ return chunks;
826
+ }
827
+ const MAX_SIZE = 5e3;
828
+ //#endregion
829
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/callbacks.mjs
713
830
  function getArrayCallback(value) {
714
831
  switch (typeof value) {
715
832
  case "function": return value;
@@ -725,6 +842,8 @@ function getArrayCallbacks(bool, key, value) {
725
842
  value: getArrayCallback(value)
726
843
  };
727
844
  }
845
+ //#endregion
846
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/find.mjs
728
847
  function findValues(type, array, parameters, mapper) {
729
848
  const result = {
730
849
  matched: [],
@@ -767,133 +886,14 @@ function getParameters(original) {
767
886
  value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
768
887
  };
769
888
  }
770
- var UNIQUE_THRESHOLD = 100;
771
- function filter(array, ...parameters) {
772
- return findValues("all", array, parameters).matched;
773
- }
774
- filter.remove = removeFiltered;
775
- function removeFiltered(array, ...parameters) {
776
- return findValues("all", array, parameters).notMatched;
777
- }
778
- /**
779
- * Is the value a constructor function?
780
- * @param value Value to check
781
- * @returns `true` if the value is a constructor function, otherwise `false`
782
- */
783
- function isConstructor(value) {
784
- return typeof value === "function" && value.prototype?.constructor === value;
785
- }
786
- /**
787
- * Is the value a key?
788
- * @param value Value to check
789
- * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
790
- */
791
- function isKey(value) {
792
- return typeof value === "number" || typeof value === "string";
793
- }
794
- /**
795
- * Is the value a number?
796
- * @param value Value to check
797
- * @returns `true` if the value is a `number`, otherwise `false`
798
- */
799
- function isNumber(value) {
800
- return typeof value === "number" && !Number.isNaN(value);
801
- }
802
- /**
803
- * Is the value a plain object?
804
- * @param value Value to check
805
- * @returns `true` if the value is a plain object, otherwise `false`
806
- */
807
- function isPlainObject(value) {
808
- if (value === null || typeof value !== "object") return false;
809
- if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
810
- const prototype = Object.getPrototypeOf(value);
811
- return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
812
- }
813
- /**
814
- * Is the value a typed array?
815
- * @param value Value to check
816
- * @returns `true` if the value is a typed array, otherwise `false`
817
- */
818
- function isTypedArray(value) {
819
- TYPED_ARRAYS ??= new Set([
820
- Int8Array,
821
- Uint8Array,
822
- Uint8ClampedArray,
823
- Int16Array,
824
- Uint16Array,
825
- Int32Array,
826
- Uint32Array,
827
- Float32Array,
828
- Float64Array,
829
- BigInt64Array,
830
- BigUint64Array
831
- ]);
832
- return TYPED_ARRAYS.has(value?.constructor);
833
- }
834
- var TYPED_ARRAYS;
835
- /**
836
- * Chunk an array into smaller arrays
837
- * @param array Array to chunk
838
- * @param size Size of each chunk _(minimum is `1`, maximum is `5000`; defaults to `5000`)_
839
- * @returns Array of arrays
840
- */
841
- function chunk(array, size) {
842
- if (!Array.isArray(array)) return [];
843
- if (array.length === 0) return [];
844
- const { length } = array;
845
- const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
846
- if (length <= actualSize) return [array];
847
- const chunks = [];
848
- let index = 0;
849
- while (index < length) {
850
- chunks.push(array.slice(index, index + actualSize));
851
- index += actualSize;
852
- }
853
- return chunks;
854
- }
855
- var MAX_SIZE = 5e3;
856
- function compact(array, strict) {
857
- if (!Array.isArray(array)) return [];
858
- if (strict === true) return array.filter(Boolean);
859
- const { length } = array;
860
- const compacted = [];
861
- for (let index = 0; index < length; index += 1) {
862
- const item = array[index];
863
- if (item != null) compacted.push(item);
864
- }
865
- return compacted;
866
- }
867
- function insertChunkedValues(type, array, items, start, deleteCount) {
868
- const actualDeleteCount = deleteCount < 0 ? 0 : deleteCount;
869
- const actualStart = Math.min(Math.max(0, start), array.length);
870
- const chunked = chunk(items);
871
- const lastIndex = chunked.length - 1;
872
- let index = Number(chunked.length);
873
- let returned;
874
- while (index > 0) {
875
- index -= 1;
876
- const spliced = array.splice(actualStart, index === lastIndex ? actualDeleteCount : 0, ...chunked[index]);
877
- if (returned == null) returned = spliced;
878
- else returned.push(...spliced);
879
- }
880
- if (type === "insert") return array;
881
- return type === "splice" ? returned : array.length;
882
- }
883
- function insertValues(type, array, items, start, deleteCount) {
884
- const spliceArray = type === "insert" || type === "splice";
885
- if (!Array.isArray(array) || typeof start !== "number" || !Array.isArray(items) || items.length === 0) return spliceArray ? [] : 0;
886
- return insertChunkedValues(type, array, items, start, spliceArray ? deleteCount : 0);
887
- }
888
- /**
889
- * Push items into an array _(at the end)_
890
- * @param array Original array
891
- * @param pushed Pushed items
892
- * @returns New length of the array
893
- */
894
- function push(array, pushed) {
895
- return insertValues("push", array, pushed, array.length, 0);
889
+ const UNIQUE_THRESHOLD = 100;
890
+ //#endregion
891
+ //#region node_modules/@oscarpalmer/atoms/dist/array/select.mjs
892
+ function select(array, ...parameters) {
893
+ return findValues("all", array, parameters, parameters.pop()).matched;
896
894
  }
895
+ //#endregion
896
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/math/aggregate.mjs
897
897
  function aggregate(type, array, key) {
898
898
  const length = Array.isArray(array) ? array.length : 0;
899
899
  if (length === 0) return {
@@ -932,43 +932,14 @@ function getAggregated(type, array, key) {
932
932
  const aggregated = aggregate(type, array, key);
933
933
  return aggregated.count > 0 ? aggregated.value : NaN;
934
934
  }
935
- var aggregators = {
935
+ const aggregators = {
936
936
  average: calculateSum,
937
937
  max: (current, value, notNumber) => notNumber || value > current ? value : current,
938
938
  min: (current, value, notNumber) => notNumber || value < current ? value : current,
939
939
  sum: calculateSum
940
940
  };
941
- /**
942
- * Get the string value from any value
943
- * @param value Original value
944
- * @returns String representation of the value
945
- */
946
- function getString(value) {
947
- if (typeof value === "string") return value;
948
- if (value == null) return "";
949
- if (typeof value === "function") return getString(value());
950
- if (typeof value !== "object") return String(value);
951
- const asString = String(value.valueOf?.() ?? value);
952
- return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
953
- }
954
- /**
955
- * Join an array of values into a string
956
- * @param value Array of values
957
- * @param delimiter Delimiter to use between values
958
- * @returns Joined string
959
- */
960
- function join(value, delimiter) {
961
- return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
962
- }
963
- /**
964
- * Split a string into words _(and other readable parts)_
965
- * @param value Original string
966
- * @returns Array of words found in the string
967
- */
968
- function words(value) {
969
- return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
970
- }
971
- var EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
941
+ //#endregion
942
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/handlers.mjs
972
943
  function getCompareHandlers(owner, options) {
973
944
  const { get, register, unregister } = getHandlers(owner, options);
974
945
  return {
@@ -1002,6 +973,9 @@ function getHandlers(owner, options) {
1002
973
  function isConstructable(value) {
1003
974
  return typeof value === "object" && value !== null;
1004
975
  }
976
+ //#endregion
977
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/compare.mjs
978
+ const COMPARE_NAME = "compare";
1005
979
  /**
1006
980
  * Compare two values _(for sorting purposes)_
1007
981
  * @param first First value
@@ -1034,7 +1008,7 @@ compare.handlers = getCompareHandlers(compare, {
1034
1008
  callback: (first, second, compareStrings) => {
1035
1009
  if (compareStrings) return getString(first).localeCompare(getString(second));
1036
1010
  },
1037
- method: "compare"
1011
+ method: COMPARE_NAME
1038
1012
  });
1039
1013
  compare.register = registerComparator;
1040
1014
  compare.unregister = unregisterComparator;
@@ -1056,7 +1030,7 @@ function unregisterComparator(constructor) {
1056
1030
  function compareNumbers(first, second) {
1057
1031
  const firstNumber = Number(first);
1058
1032
  const secondNumber = Number(second);
1059
- if (firstNumber === secondNumber) return 0;
1033
+ if (Object.is(firstNumber, secondNumber)) return 0;
1060
1034
  return firstNumber > secondNumber ? 1 : -1;
1061
1035
  }
1062
1036
  function compareSymbols(first, second) {
@@ -1072,12 +1046,14 @@ function getComparisonParts(value) {
1072
1046
  if (Array.isArray(value)) return value;
1073
1047
  return typeof value === "object" ? [value] : words(getString(value));
1074
1048
  }
1075
- var comparators$1 = {
1049
+ const comparators$1 = {
1076
1050
  bigint: compareNumbers,
1077
1051
  boolean: compareNumbers,
1078
1052
  number: compareNumbers,
1079
1053
  symbol: compareSymbols
1080
1054
  };
1055
+ //#endregion
1056
+ //#region node_modules/@oscarpalmer/atoms/dist/array/sort.mjs
1081
1057
  function getCallback(value, key, forObject) {
1082
1058
  if (key != null) return;
1083
1059
  if (forObject && typeof value.value === "function") return value.value;
@@ -1110,7 +1086,7 @@ function getSorter(value, modifier) {
1110
1086
  function sort(array, first, second) {
1111
1087
  if (!Array.isArray(array)) return [];
1112
1088
  if (array.length < 2) return array;
1113
- const modifier = (first === true || second === true ? "desc" : "asc") === "asc" ? 1 : -1;
1089
+ const modifier = (first === true || second === true ? "descending" : "ascending") === "ascending" ? 1 : -1;
1114
1090
  const sorters = (Array.isArray(first) ? first : [first]).map((item) => getSorter(item, modifier)).filter((sorter) => sorter != null).filter((current, index, filtered) => filtered.findIndex((next) => next.identifier === current.identifier) === index);
1115
1091
  const { length } = sorters;
1116
1092
  if (length === 0) return array.sort((firstItem, secondItem) => compare(firstItem, secondItem) * modifier);
@@ -1135,6 +1111,8 @@ function sort(array, first, second) {
1135
1111
  return 0;
1136
1112
  });
1137
1113
  }
1114
+ //#endregion
1115
+ //#region node_modules/@oscarpalmer/atoms/dist/array/to-map.mjs
1138
1116
  function getMapValues(array, first, second, arrays) {
1139
1117
  if (!Array.isArray(array)) return /* @__PURE__ */ new Map();
1140
1118
  const { length } = array;
@@ -1159,15 +1137,346 @@ toMap.arrays = toMapArrays;
1159
1137
  function toMapArrays(array, first, second) {
1160
1138
  return getMapValues(array, first, second, true);
1161
1139
  }
1162
- /**
1163
- * Is the value `undefined`, `null`, or a whitespace-only string?
1164
- * @param value Value to check
1165
- * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
1166
- */
1167
- function isNullableOrWhitespace(value) {
1168
- return value == null || EXPRESSION_WHITESPACE.test(getString(value));
1140
+ //#endregion
1141
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/group.mjs
1142
+ function groupValues(array, key, value, arrays) {
1143
+ if (!Array.isArray(array) || array.length === 0) return {};
1144
+ const { length } = array;
1145
+ const callbacks = getArrayCallbacks(void 0, key, value);
1146
+ const record = {};
1147
+ for (let index = 0; index < length; index += 1) {
1148
+ const item = array[index];
1149
+ const keyed = callbacks?.keyed?.(item, index, array) ?? index;
1150
+ const valued = callbacks?.value?.(item, index, array) ?? item;
1151
+ if (arrays) {
1152
+ const existing = record[keyed];
1153
+ if (existing == null) record[keyed] = [valued];
1154
+ else existing.push(valued);
1155
+ } else record[keyed] = valued;
1156
+ }
1157
+ return record;
1158
+ }
1159
+ //#endregion
1160
+ //#region node_modules/@oscarpalmer/atoms/dist/array/to-record.mjs
1161
+ function toRecord(array, first, second) {
1162
+ return groupValues(array, first, second, false);
1163
+ }
1164
+ toRecord.arrays = toRecordArrays;
1165
+ function toRecordArrays(array, first, second) {
1166
+ return groupValues(array, first, second, true);
1167
+ }
1168
+ //#endregion
1169
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/function/timer.mjs
1170
+ function getInterval(value) {
1171
+ return typeof value === "number" && value > 0 ? value : 0;
1172
+ }
1173
+ function getTimer(type, callback, time) {
1174
+ const interval = getInterval(time);
1175
+ function run(now) {
1176
+ start ??= now;
1177
+ if (interval === 0 || now - start >= interval - OFFSET) {
1178
+ if (throttle) start = now;
1179
+ callback(...args);
1180
+ } else frame = requestAnimationFrame(run);
1181
+ }
1182
+ const throttle = type === TIMER_THROTTLE;
1183
+ let args;
1184
+ let frame;
1185
+ let start;
1186
+ const timer = (...parameters) => {
1187
+ timer.cancel();
1188
+ args = parameters;
1189
+ frame = requestAnimationFrame(run);
1190
+ };
1191
+ timer.cancel = () => {
1192
+ cancelAnimationFrame(frame);
1193
+ };
1194
+ return timer;
1195
+ }
1196
+ const OFFSET = 5;
1197
+ const TIMER_THROTTLE = "throttle";
1198
+ const TIMER_WAIT = "wait";
1199
+ //#endregion
1200
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/models.mjs
1201
+ const PROMISE_ABORT_EVENT = "abort";
1202
+ const PROMISE_ABORT_OPTIONS = { once: true };
1203
+ //#endregion
1204
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/helpers.mjs
1205
+ function getNumberOrDefault(value) {
1206
+ return typeof value === "number" && value > 0 ? value : 0;
1207
+ }
1208
+ function getPromiseOptions(input) {
1209
+ if (typeof input === "number") return { time: getNumberOrDefault(input) };
1210
+ if (input instanceof AbortSignal) return {
1211
+ signal: input,
1212
+ time: 0
1213
+ };
1214
+ const options = typeof input === "object" && input !== null ? input : {};
1215
+ return {
1216
+ signal: options.signal instanceof AbortSignal ? options.signal : void 0,
1217
+ time: getNumberOrDefault(options.time)
1218
+ };
1219
+ }
1220
+ //#endregion
1221
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/misc.mjs
1222
+ function settlePromise(aborter, settler, value, signal) {
1223
+ signal?.removeEventListener(PROMISE_ABORT_EVENT, aborter);
1224
+ settler(value);
1225
+ }
1226
+ //#endregion
1227
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/delay.mjs
1228
+ function delay(options) {
1229
+ const { signal, time } = getPromiseOptions(options);
1230
+ if (signal?.aborted ?? false) return Promise.reject(signal.reason);
1231
+ function abort() {
1232
+ timer.cancel();
1233
+ rejector(signal.reason);
1234
+ }
1235
+ const timer = getTimer(TIMER_WAIT, () => {
1236
+ settlePromise(abort, resolver, void 0, signal);
1237
+ }, time);
1238
+ signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS);
1239
+ let rejector;
1240
+ let resolver;
1241
+ return new Promise((resolve, reject) => {
1242
+ rejector = reject;
1243
+ resolver = resolve;
1244
+ if (time === 0) settlePromise(abort, resolve, void 0, signal);
1245
+ else timer();
1246
+ });
1247
+ }
1248
+ //#endregion
1249
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/misc.mjs
1250
+ function findKey(needle, haystack) {
1251
+ const keys = Object.keys(haystack);
1252
+ const index = keys.map((key) => key.toLowerCase()).indexOf(needle.toLowerCase());
1253
+ return index > -1 ? keys[index] : needle;
1254
+ }
1255
+ function getNestedValue(data, path, ignoreCase) {
1256
+ if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return {
1257
+ exists: false,
1258
+ value: void 0
1259
+ };
1260
+ const shouldIgnoreCase = ignoreCase === true;
1261
+ const paths = getPaths(path, shouldIgnoreCase);
1262
+ if (typeof paths === "string") return handleValue(data, paths, null, true, shouldIgnoreCase);
1263
+ const { length } = paths;
1264
+ let current = data;
1265
+ for (let index = 0; index < length; index += 1) {
1266
+ const part = paths[index];
1267
+ const handled = handleValue(current, part, null, true, shouldIgnoreCase);
1268
+ if (!handled.exists) return handled;
1269
+ current = handled.value;
1270
+ }
1271
+ return {
1272
+ exists: true,
1273
+ value: current
1274
+ };
1275
+ }
1276
+ function getPaths(path, lowercase) {
1277
+ const normalized = lowercase ? path.toLowerCase() : path;
1278
+ if (!EXPRESSION_NESTED.test(normalized)) return normalized;
1279
+ return normalized.replace(EXPRESSION_BRACKET, ".$1").replace(EXPRESSION_DOTS, "").split(".");
1280
+ }
1281
+ function handleValue(data, path, value, get, ignoreCase) {
1282
+ if (typeof data === "object" && data !== null && !ignoreKey(path)) {
1283
+ const key = ignoreCase ? findKey(path, data) : path;
1284
+ if (get) return {
1285
+ exists: key in data,
1286
+ value: data[key]
1287
+ };
1288
+ data[key] = typeof value === "function" ? value(data[key]) : value;
1289
+ }
1290
+ if (get) return {
1291
+ exists: false,
1292
+ value: void 0
1293
+ };
1294
+ }
1295
+ const EXPRESSION_BRACKET = /\[(\w+)\]/g;
1296
+ const EXPRESSION_DOTS = /^\.|\.$/g;
1297
+ const EXPRESSION_NESTED = /\.|\[\w+\]/;
1298
+ //#endregion
1299
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/get.mjs
1300
+ function getValue(data, path, ignoreCase) {
1301
+ return getNestedValue(data, path, ignoreCase === true).value;
1302
+ }
1303
+ //#endregion
1304
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/has.mjs
1305
+ function hasValue(data, path, ignoreCase) {
1306
+ return getNestedValue(data, path, ignoreCase === true).exists;
1307
+ }
1308
+ hasValue.get = getWithHasValue;
1309
+ function getWithHasValue(data, path, ignoreCase) {
1310
+ return getNestedValue(data, path, ignoreCase === true);
1311
+ }
1312
+ //#endregion
1313
+ //#region src/components/group.component.ts
1314
+ var GroupComponent = class {
1315
+ element;
1316
+ expanded = true;
1317
+ filtered = 0;
1318
+ key;
1319
+ selected = 0;
1320
+ total = 0;
1321
+ value;
1322
+ constructor(label, value) {
1323
+ this.label = label;
1324
+ const stringified = getString(value);
1325
+ this.key = `group:${stringified}`;
1326
+ this.value = {
1327
+ stringified,
1328
+ original: value
1329
+ };
1330
+ }
1331
+ };
1332
+ function removeGroup(group) {
1333
+ if (group.element == null) return;
1334
+ group.element.innerHTML = "";
1335
+ group.element.remove();
1336
+ }
1337
+ function renderGroup(state, component) {
1338
+ component.element ??= createElement("div", {
1339
+ className: `${CSS_TABELA_ROW} ${CSS_TABELA_ROW_GROUP}`,
1340
+ innerHTML: `<div class="tabela__cell tabela__cell--group" role="cell">
1341
+ <button class="tabela__button tabela__button--group" data-event="group" data-key="tabela_${state.id}_${component.key}" type="button">
1342
+ <span aria-hidden="true"></span>
1343
+ <span>Open/close</span>
1344
+ </button>
1345
+ <p>${component.label}</p>
1346
+ <span class="tabela__group__total">${component.total}</span>
1347
+ <span class="tabela__group__selected">${component.selected === 0 ? "" : component.selected}</span>
1348
+ </div>`,
1349
+ role: "row"
1350
+ }, {}, { height: `${state.options.rowHeight}px` });
1351
+ }
1352
+ function updateGroup(state, component) {
1353
+ if (component.element == null) return;
1354
+ const selected = component.element.querySelector(".tabela__group__selected");
1355
+ const total = component.element.querySelector(".tabela__group__total");
1356
+ if (selected != null) selected.textContent = component.selected === 0 ? "" : String(component.selected);
1357
+ if (total != null) total.textContent = String(component.total);
1358
+ }
1359
+ //#endregion
1360
+ //#region src/managers/sort.manager.ts
1361
+ var SortManager = class {
1362
+ handlers = Object.freeze({
1363
+ add: (field, direction) => this.add(field, direction),
1364
+ flip: (field) => this.flip(field),
1365
+ clear: () => this.clear(),
1366
+ remove: (field) => this.remove(field),
1367
+ set: (items) => this.set(items)
1368
+ });
1369
+ items = [];
1370
+ constructor(state) {
1371
+ this.state = state;
1372
+ }
1373
+ add(field, direction) {
1374
+ if (this.items.findIndex((item) => item.key === field) > -1) return;
1375
+ this.items.push({
1376
+ key: field,
1377
+ direction: direction ?? "ascending"
1378
+ });
1379
+ this.sort();
1380
+ }
1381
+ addOrSet(event, field) {
1382
+ if (event.ctrlKey || event.metaKey) this.add(field);
1383
+ else this.set([{
1384
+ field,
1385
+ direction: "ascending"
1386
+ }]);
1387
+ }
1388
+ clear() {
1389
+ if (this.items.length > 0) {
1390
+ this.items.length = 0;
1391
+ this.sort();
1392
+ }
1393
+ }
1394
+ destroy() {
1395
+ this.handlers = void 0;
1396
+ this.items = void 0;
1397
+ this.state = void 0;
1398
+ }
1399
+ flip(field) {
1400
+ const item = this.items.find((item) => item.key === field);
1401
+ if (item == null) return;
1402
+ item.direction = item.direction === "ascending" ? "descending" : "ascending";
1403
+ this.sort();
1404
+ }
1405
+ remove(field) {
1406
+ const index = this.items.findIndex((item) => item.key === field);
1407
+ if (index > -1) {
1408
+ this.items.splice(index, 1);
1409
+ this.sort();
1410
+ }
1411
+ }
1412
+ removeOrClear(event, field) {
1413
+ if (event.ctrlKey || event.metaKey) this.remove(field);
1414
+ else this.clear();
1415
+ }
1416
+ set(items) {
1417
+ this.items.splice(0, this.items.length, ...items.map((item) => ({
1418
+ key: item.field,
1419
+ direction: item.direction
1420
+ })));
1421
+ this.sort();
1422
+ }
1423
+ sort() {
1424
+ const { items, state } = this;
1425
+ const { length } = state.managers.column.items;
1426
+ for (let index = 0; index < length; index += 1) {
1427
+ const column = state.managers.column.items[index];
1428
+ const sorterIndex = items.findIndex((item) => item.key === column.options.field);
1429
+ const sorterItem = items[sorterIndex];
1430
+ setAttributes(column.elements.wrapper, {
1431
+ "aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
1432
+ "data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
1433
+ });
1434
+ setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
1435
+ }
1436
+ state.managers.data.state.items.active = items.length === 0 ? void 0 : getSortedItems(state, items);
1437
+ state.managers.render.update(true, true);
1438
+ }
1439
+ toggle(event, field, direction) {
1440
+ switch (direction) {
1441
+ case "ascending":
1442
+ this.flip(field);
1443
+ return;
1444
+ case "descending":
1445
+ this.removeOrClear(event, field);
1446
+ return;
1447
+ default:
1448
+ this.addOrSet(event, field);
1449
+ return;
1450
+ }
1451
+ }
1452
+ };
1453
+ function getSortedItems(state, sorters) {
1454
+ const data = state.managers.data.state.items.active?.map((key) => key instanceof GroupComponent ? key : state.managers.data.state.values.mapped.get(key)) ?? state.managers.data.state.values.array.slice();
1455
+ if (!state.managers.group.enabled) return sort(data, sorters).map((item) => getValue(item, state.key));
1456
+ return sortWithGroups(state, data, sorters).map((item) => item instanceof GroupComponent ? item : getValue(item, state.key));
1457
+ }
1458
+ function sortWithGroups(state, data, sorters) {
1459
+ const { length } = sorters;
1460
+ return data.sort((first, second) => {
1461
+ const firstValue = first instanceof GroupComponent ? first.value.stringified : getValue(first, state.managers.group.field);
1462
+ const secondValue = second instanceof GroupComponent ? second.value.stringified : getValue(second, state.managers.group.field);
1463
+ const firstOrder = state.managers.group.order[firstValue];
1464
+ const secondOrder = state.managers.group.order[secondValue];
1465
+ const groupComparison = compare(firstOrder, secondOrder);
1466
+ if (groupComparison !== 0) return groupComparison;
1467
+ const firstIsGroup = first instanceof GroupComponent;
1468
+ const secondIsGroup = second instanceof GroupComponent;
1469
+ if (firstIsGroup || secondIsGroup) return firstIsGroup && secondIsGroup ? 0 : firstIsGroup ? -1 : 1;
1470
+ for (let index = 0; index < length; index += 1) {
1471
+ const sorter = sorters[index];
1472
+ const comparison = compare(getValue(first, sorter.key), getValue(second, sorter.key));
1473
+ if (comparison !== 0) return comparison * (sorter.direction === "ascending" ? 1 : -1);
1474
+ }
1475
+ return 0;
1476
+ });
1169
1477
  }
1170
- var EXPRESSION_WHITESPACE = /^\s*$/;
1478
+ //#endregion
1479
+ //#region src/managers/data.manager.ts
1171
1480
  var DataManager = class {
1172
1481
  handlers = Object.freeze({
1173
1482
  add: (data) => void this.add(data, true),
@@ -1177,90 +1486,185 @@ var DataManager = class {
1177
1486
  synchronize: (data, remove) => void this.synchronize(data, remove),
1178
1487
  update: (data) => void this.update(data)
1179
1488
  });
1180
- values = {
1181
- keys: { original: [] },
1182
- objects: {
1183
- mapped: /* @__PURE__ */ new Map(),
1184
- array: []
1185
- }
1186
- };
1489
+ state;
1490
+ get items() {
1491
+ return this.state.items.active ?? this.state.items.original;
1492
+ }
1187
1493
  get size() {
1188
- return this.values.keys.active?.length ?? this.values.keys.original.length;
1494
+ return this.items.length;
1189
1495
  }
1190
1496
  constructor(state) {
1191
- this.state = state;
1497
+ this.state = {
1498
+ ...state,
1499
+ items: { original: [] },
1500
+ values: {
1501
+ array: [],
1502
+ mapped: /* @__PURE__ */ new Map()
1503
+ }
1504
+ };
1192
1505
  }
1193
1506
  async add(data, render) {
1194
- const { state, values } = this;
1195
- push(values.objects.array, data);
1196
- values.objects.mapped = toMap(values.objects.array, state.key);
1197
- if (render) this.render();
1507
+ const { state } = this;
1508
+ const groups = [];
1509
+ const updates = [];
1510
+ let groupColumn;
1511
+ let { length } = data;
1512
+ for (let index = 0; index < length; index += 1) {
1513
+ const item = data[index];
1514
+ const key = getValue(item, state.key);
1515
+ if (state.values.mapped.has(key)) {
1516
+ updates.push(item);
1517
+ continue;
1518
+ }
1519
+ state.values.array.push(item);
1520
+ state.values.mapped.set(key, item);
1521
+ if (!state.managers.group.enabled) continue;
1522
+ const groupValue = getValue(item, state.managers.group.field);
1523
+ let group = state.managers.group.get(groupValue);
1524
+ if (group == null) {
1525
+ groupColumn ??= state.managers.column.get(state.managers.group.field);
1526
+ group = new GroupComponent(`${groupColumn?.options.title ?? state.managers.group.field}: ${groupValue}`, groupValue);
1527
+ state.values.array.push(group);
1528
+ state.managers.group.add(group);
1529
+ }
1530
+ if (!group.expanded) state.managers.group.collapsed.add(key);
1531
+ group.total += 1;
1532
+ groups.push(group);
1533
+ }
1534
+ length = groups.length;
1535
+ for (let index = 0; index < length; index += 1) updateGroup(state, groups[index]);
1536
+ if (updates.length > 0) this.update(updates);
1537
+ else if (render) this.render();
1198
1538
  }
1199
1539
  clear() {
1200
- if (this.values.objects.array.length > 0) this.set([]);
1540
+ if (this.state.values.array.length > 0) this.removeItems([], true, true);
1201
1541
  }
1202
1542
  destroy() {
1203
- const { values } = this;
1204
- values.objects.mapped.clear();
1205
- values.keys.active = void 0;
1206
- values.keys.original.length = 0;
1207
- values.objects.array.length = 0;
1543
+ const { state } = this;
1544
+ state.values.mapped.clear();
1545
+ state.items.active = void 0;
1546
+ state.items.original.length = 0;
1547
+ state.values.array.length = 0;
1208
1548
  this.handlers = void 0;
1209
1549
  this.state = void 0;
1210
- this.values = void 0;
1211
1550
  }
1212
1551
  get(active) {
1213
- const { values } = this;
1214
- return active ?? false ? values.keys.active?.map((key) => values.objects.mapped.get(key)) ?? [] : values.objects.array;
1552
+ const { state } = this;
1553
+ return active ?? false ? select(state.items.active ?? [], (key) => !(key instanceof GroupComponent), (key) => state.values.mapped.get(key)) : state.values.array.filter((item) => !(item instanceof GroupComponent));
1215
1554
  }
1216
- getIndex(key) {
1217
- const { values } = this;
1218
- return (values.keys.active ?? values.keys.original).indexOf(key);
1555
+ getIndex(item) {
1556
+ if (item instanceof GroupComponent) return this.items.indexOf(item);
1557
+ return this.items.findIndex((value) => value instanceof GroupComponent ? value.key === item : value === item);
1219
1558
  }
1220
1559
  async remove(items, render) {
1221
- const { state, values } = this;
1222
- const keys = items.map((value) => isPlainObject(value) ? value[state.key] : value).filter((key) => values.objects.mapped.has(key));
1560
+ const { state } = this;
1561
+ const keys = items.map((value) => isPlainObject(value) ? getValue(value, state.key) : value);
1223
1562
  const { length } = keys;
1224
- if (length === 0) return;
1225
- for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
1226
- const key = keys[keyIndex];
1227
- values.objects.mapped.delete(key);
1228
- const arrayIndex = values.objects.array.findIndex((object) => object[state.key] === key);
1229
- if (arrayIndex > -1) values.objects.array.splice(arrayIndex, 1);
1230
- values.keys.original.splice(values.keys.original.indexOf(key), 1);
1231
- state.managers.row.remove(key);
1563
+ if (length > 0) return this.removeItems(keys, false, render === true);
1564
+ }
1565
+ async removeItems(items, clear, render) {
1566
+ const { state } = this;
1567
+ if (clear) {
1568
+ state.items.active = void 0;
1569
+ state.items.original = [];
1570
+ state.values.array = [];
1571
+ state.values.mapped.clear();
1572
+ state.managers.row.clear();
1573
+ if (state.managers.group.enabled) state.managers.group.clear();
1574
+ return this.render();
1232
1575
  }
1233
- if (render) this.render();
1576
+ const groups = [];
1577
+ const chunked = chunk(items);
1578
+ const chunkedLength = chunked.length;
1579
+ for (let chunkedIndex = 0; chunkedIndex < chunkedLength; chunkedIndex += 1) {
1580
+ const chunk = chunked[chunkedIndex];
1581
+ const chunkLength = chunk.length;
1582
+ for (let itemIndex = 0; itemIndex < chunkLength; itemIndex += 1) {
1583
+ const item = chunk[itemIndex];
1584
+ const dataIndex = state.items.original.indexOf(item);
1585
+ let dataValue;
1586
+ [dataValue] = state.values.array.splice(dataIndex, 1);
1587
+ state.items.original.splice(dataIndex, 1);
1588
+ state.managers.row.remove(item);
1589
+ state.values.mapped.delete(item);
1590
+ if (!state.managers.group.enabled || item instanceof GroupComponent) continue;
1591
+ state.managers.group.collapsed.delete(item);
1592
+ const groupKey = getValue(dataValue, state.managers.group.field);
1593
+ const group = state.managers.group.get(groupKey);
1594
+ if (group == null) continue;
1595
+ group.total -= 1;
1596
+ if (group.total > 0) {
1597
+ groups.push(group);
1598
+ continue;
1599
+ }
1600
+ let groupIndex = groups.indexOf(group);
1601
+ if (groupIndex > -1) groups.splice(groupIndex, 1);
1602
+ groupIndex = state.values.array.indexOf(group);
1603
+ if (groupIndex > -1) {
1604
+ state.items.original.splice(groupIndex, 1);
1605
+ state.values.array.splice(groupIndex, 1);
1606
+ }
1607
+ state.managers.group.remove(group);
1608
+ if (items.length >= 1e4) await delay(25);
1609
+ }
1610
+ }
1611
+ const { length } = groups;
1612
+ for (let index = 0; index < length; index += 1) updateGroup(state, groups[index]);
1613
+ if (render) return this.render();
1234
1614
  }
1235
1615
  render() {
1236
- const { state, values } = this;
1237
- values.keys.original = sort(values.objects.array.map((item) => item[state.key]));
1616
+ const { state } = this;
1617
+ if (state.managers.group.enabled) sortWithGroups(state, state.values.array, [{
1618
+ direction: "ascending",
1619
+ key: state.key
1620
+ }]);
1621
+ else sort(state.values.array, [{
1622
+ direction: "ascending",
1623
+ key: state.key
1624
+ }]);
1625
+ state.items.original = state.values.array.map((item) => item instanceof GroupComponent ? item : getValue(item, state.key));
1626
+ state.values.mapped = toMap(state.values.array.filter((item) => !(item instanceof GroupComponent)), (item) => getValue(item, state.key));
1238
1627
  if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
1239
1628
  else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
1240
- else state.managers.render.update(true);
1629
+ else state.managers.render.update(true, true);
1241
1630
  }
1242
1631
  set(data) {
1243
- const { state, values } = this;
1244
- values.objects.mapped = toMap(data, state.key);
1245
- values.objects.array = data;
1632
+ const { state } = this;
1633
+ const array = data.slice();
1634
+ if (state.managers.group.enabled) {
1635
+ const column = state.managers.column.get(state.managers.group.field);
1636
+ const grouped = toRecord.arrays(data, state.managers.group.field);
1637
+ const entries = Object.entries(grouped);
1638
+ const { length } = entries;
1639
+ const groups = [];
1640
+ for (let index = 0; index < length; index += 1) {
1641
+ const [value, items] = entries[index];
1642
+ const group = new GroupComponent(`${column?.options.title ?? state.managers.group.field}: ${value}`, value);
1643
+ group.total = items.length;
1644
+ groups.push(group);
1645
+ array.push(group);
1646
+ }
1647
+ state.managers.group.set(groups);
1648
+ }
1649
+ state.values.array = array;
1246
1650
  this.render();
1247
1651
  }
1248
1652
  async synchronize(data, remove) {
1249
- const { state, values } = this;
1653
+ const { state } = this;
1250
1654
  const add = [];
1251
1655
  const updated = [];
1252
1656
  const keys = /* @__PURE__ */ new Set([]);
1253
1657
  const { length } = data;
1254
1658
  for (let index = 0; index < length; index += 1) {
1255
1659
  const object = data[index];
1256
- const key = object[state.key];
1257
- if (values.objects.mapped.has(key)) updated.push(object);
1660
+ const key = getValue(object, state.key);
1661
+ if (state.values.mapped.has(key)) updated.push(object);
1258
1662
  else add.push(object);
1259
1663
  keys.add(key);
1260
1664
  }
1261
1665
  if (keys.size === 0) return;
1262
1666
  if (remove ?? false) {
1263
- const toRemove = values.keys.original.filter((key) => !keys.has(key));
1667
+ const toRemove = state.items.original.filter((key) => !(key instanceof GroupComponent) && !keys.has(key));
1264
1668
  if (toRemove.length > 0) await this.remove(toRemove, false);
1265
1669
  }
1266
1670
  await this.update(updated);
@@ -1268,14 +1672,14 @@ var DataManager = class {
1268
1672
  if (add.length > 0 || (remove ?? false)) this.render();
1269
1673
  }
1270
1674
  async update(data) {
1271
- const { state, values } = this;
1675
+ const { state } = this;
1272
1676
  const { length } = data;
1273
1677
  for (let index = 0; index < length; index += 1) {
1274
1678
  const object = data[index];
1275
- const key = object[state.key];
1276
- const value = values.objects.mapped.get(key);
1679
+ const key = getValue(object, state.key);
1680
+ const value = state.values.mapped.get(key);
1277
1681
  if (value != null) {
1278
- values.objects.mapped.set(key, {
1682
+ state.values.mapped.set(key, {
1279
1683
  ...value,
1280
1684
  ...object
1281
1685
  });
@@ -1284,6 +1688,8 @@ var DataManager = class {
1284
1688
  }
1285
1689
  }
1286
1690
  };
1691
+ //#endregion
1692
+ //#region node_modules/@oscarpalmer/toretto/dist/event/delegation.mjs
1287
1693
  function addDelegatedHandler(doc, type, name, passive) {
1288
1694
  if (DELEGATED.has(name)) return;
1289
1695
  DELEGATED.add(name);
@@ -1335,11 +1741,11 @@ function removeDelegatedListener(target, name, listener) {
1335
1741
  if (handlers.size === 0) target[name] = void 0;
1336
1742
  return true;
1337
1743
  }
1338
- var DELEGATED = /* @__PURE__ */ new Set();
1339
- var EVENT_PREFIX = "@";
1340
- var EVENT_SUFFIX_ACTIVE = ":active";
1341
- var EVENT_SUFFIX_PASSIVE = ":passive";
1342
- var EVENT_TYPES = new Set([
1744
+ const DELEGATED = /* @__PURE__ */ new Set();
1745
+ const EVENT_PREFIX = "@";
1746
+ const EVENT_SUFFIX_ACTIVE = ":active";
1747
+ const EVENT_SUFFIX_PASSIVE = ":passive";
1748
+ const EVENT_TYPES = new Set([
1343
1749
  "beforeinput",
1344
1750
  "click",
1345
1751
  "dblclick",
@@ -1363,12 +1769,16 @@ var EVENT_TYPES = new Set([
1363
1769
  "touchmove",
1364
1770
  "touchstart"
1365
1771
  ]);
1366
- var HANDLER_ACTIVE = delegatedEventHandler.bind(false);
1367
- var HANDLER_PASSIVE = delegatedEventHandler.bind(true);
1772
+ const HANDLER_ACTIVE = delegatedEventHandler.bind(false);
1773
+ const HANDLER_PASSIVE = delegatedEventHandler.bind(true);
1774
+ //#endregion
1775
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/function/misc.mjs
1368
1776
  /**
1369
1777
  * A function that does nothing, which can be useful, I guess…
1370
1778
  */
1371
1779
  function noop() {}
1780
+ //#endregion
1781
+ //#region node_modules/@oscarpalmer/toretto/dist/event/index.mjs
1372
1782
  function createEventOptions(options) {
1373
1783
  return {
1374
1784
  capture: getBoolean(options?.capture),
@@ -1408,6 +1818,8 @@ function on(target, type, listener, options) {
1408
1818
  target.removeEventListener(type, listener, extended);
1409
1819
  };
1410
1820
  }
1821
+ //#endregion
1822
+ //#region node_modules/@oscarpalmer/toretto/dist/find/relative.mjs
1411
1823
  function findAncestor(origin, selector) {
1412
1824
  const element = getElement(origin);
1413
1825
  if (element == null || selector == null) return null;
@@ -1428,243 +1840,59 @@ function getElement(origin) {
1428
1840
  if (origin instanceof Element) return origin;
1429
1841
  return origin instanceof Event && origin.target instanceof Element ? origin.target : void 0;
1430
1842
  }
1843
+ //#endregion
1844
+ //#region src/managers/event.manager.ts
1431
1845
  var EventManager = class {
1432
1846
  constructor(state) {
1433
1847
  this.state = state;
1434
- mapped$1.set(state.element, this);
1435
- }
1436
- destroy() {
1437
- mapped$1.delete(this.state.element);
1438
- this.state = void 0;
1439
- }
1440
- onSort(event, target) {
1441
- const direction = target.getAttribute("data-sort-direction");
1442
- const field = target.getAttribute("data-field");
1443
- if (field != null) this.state.managers.sort.toggle(event, field, direction);
1444
- }
1445
- };
1446
- function onClick(event) {
1447
- const target = findAncestor(event, "[data-event]");
1448
- const table = findAncestor(event, ".tabela");
1449
- if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
1450
- const manager = mapped$1.get(table);
1451
- if (manager == null) return;
1452
- switch (target?.getAttribute("data-event")) {
1453
- case "heading":
1454
- manager.onSort(event, target);
1455
- break;
1456
- case "row":
1457
- manager.state.managers.selection.handle(event, target);
1458
- break;
1459
- default: break;
1460
- }
1461
- }
1462
- function onKeydown(event) {
1463
- const target = findAncestor(event, "[data-event]");
1464
- const table = findAncestor(event, ".tabela");
1465
- if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
1466
- const manager = mapped$1.get(table);
1467
- if (manager == null) return;
1468
- switch (target?.getAttribute("data-event")) {
1469
- case "body":
1470
- manager.state.managers.navigation.handle(event);
1471
- break;
1472
- default: break;
1473
- }
1474
- }
1475
- const mapped$1 = /* @__PURE__ */ new WeakMap();
1476
- on(document, "click", onClick);
1477
- on(document, "keydown", onKeydown, { passive: false });
1478
- /**
1479
- * Clamp a number between a minimum and maximum value
1480
- * @param value Value to clamp
1481
- * @param minimum Minimum value
1482
- * @param maximum Maximum value
1483
- * @param loop If `true`, the value will loop around when smaller than the minimum or larger than the maximum _(defaults to `false`)_
1484
- * @returns Clamped value
1485
- */
1486
- function clamp(value, minimum, maximum, loop) {
1487
- if (![
1488
- value,
1489
- minimum,
1490
- maximum
1491
- ].every(isNumber)) return NaN;
1492
- if (value < minimum) return loop === true ? maximum : minimum;
1493
- return value > maximum ? loop === true ? minimum : maximum : value;
1494
- }
1495
- /**
1496
- * Get the number value from an unknown value _(based on Lodash)_
1497
- * @param value Original value
1498
- * @returns Original value as a number, or `NaN` if the value is unable to be parsed
1499
- */
1500
- function getNumber(value) {
1501
- if (typeof value === "number") return value;
1502
- if (typeof value === "bigint" || typeof value === "boolean") return Number(value);
1503
- if (value == null || typeof value === "symbol") return NaN;
1504
- if (typeof value === "function") return getNumber(value());
1505
- let parsed = value.valueOf();
1506
- if (typeof parsed === "object") parsed = parsed.toString();
1507
- if (typeof parsed !== "string") return getNumber(parsed);
1508
- const trimmed = parsed.trim();
1509
- if (trimmed.length === 0) return NaN;
1510
- if (EXPRESSION_ZEROISH.test(parsed)) return 0;
1511
- const isBinary = EXPRESSION_BINARY.test(trimmed);
1512
- if (isBinary || EXPRESSION_OCTAL.test(trimmed)) return Number.parseInt(trimmed.slice(2), isBinary ? 2 : OCTAL_VALUE);
1513
- return Number(EXPRESSION_HEX.test(trimmed) ? trimmed : trimmed.replace(EXPRESSION_UNDERSCORE, ""));
1514
- }
1515
- var EXPRESSION_BINARY = /^0b[01]+$/i;
1516
- var EXPRESSION_HEX = /^0x[0-9a-f]+$/i;
1517
- var EXPRESSION_OCTAL = /^0o[0-7]+$/i;
1518
- var EXPRESSION_UNDERSCORE = /_/g;
1519
- var EXPRESSION_ZEROISH = /^\s*0+\s*$/;
1520
- var OCTAL_VALUE = 8;
1521
- function getSizedMaximum(first, second) {
1522
- let actual;
1523
- if (typeof first === "number") actual = first;
1524
- else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
1525
- return clamp(actual, 1, MAXIMUM_ABSOLUTE);
1526
- }
1527
- var MAXIMUM_ABSOLUTE = 16777216;
1528
- var MAXIMUM_DEFAULT = 1048576;
1529
- /**
1530
- * A Map with a maximum size
1531
- *
1532
- * Behavior is similar to a _LRU_-cache, where the least recently used entries are removed
1533
- */
1534
- var SizedMap = class extends Map {
1535
- /**
1536
- * The maximum size of the Map
1537
- */
1538
- #maximumSize;
1539
- /**
1540
- * Is the Map full?
1541
- */
1542
- get full() {
1543
- return this.size >= this.#maximumSize;
1544
- }
1545
- get maximum() {
1546
- return this.#maximumSize;
1547
- }
1548
- constructor(first, second) {
1549
- const maximum = getSizedMaximum(first, second);
1550
- super();
1551
- this.#maximumSize = maximum;
1552
- if (Array.isArray(first)) {
1553
- const { length } = first;
1554
- if (length <= maximum) for (let index = 0; index < length; index += 1) this.set(...first[index]);
1555
- else for (let index = 0; index < maximum; index += 1) this.set(...first[length - maximum + index]);
1556
- }
1557
- }
1558
- /**
1559
- * @inheritdoc
1560
- */
1561
- get(key) {
1562
- const value = super.get(key);
1563
- if (value !== void 0 || this.has(key)) this.set(key, value);
1564
- return value;
1565
- }
1566
- /**
1567
- * @inheritdoc
1568
- */
1569
- set(key, value) {
1570
- if (this.has(key)) this.delete(key);
1571
- else if (this.size >= this.#maximumSize) this.delete(this.keys().next().value);
1572
- return super.set(key, value);
1573
- }
1574
- };
1575
- var Memoized = class {
1576
- #state;
1577
- /**
1578
- * Maximum cache size
1579
- */
1580
- get maximum() {
1581
- return this.#state.cache?.maximum ?? NaN;
1582
- }
1583
- /**
1584
- * Current cache size
1585
- */
1586
- get size() {
1587
- return this.#state.cache?.size ?? NaN;
1588
- }
1589
- constructor(callback, options) {
1590
- const cache = new SizedMap(options.cacheSize);
1591
- const getter = (...parameters) => {
1592
- const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), "_"));
1593
- if (cache.has(key)) return cache.get(key);
1594
- const value = callback(...parameters);
1595
- cache.set(key, value);
1596
- return value;
1597
- };
1598
- this.#state = {
1599
- cache,
1600
- getter
1601
- };
1602
- }
1603
- /**
1604
- * Clear the cache
1605
- */
1606
- clear() {
1607
- this.#state.cache?.clear();
1608
- }
1609
- /**
1610
- * Delete a result from the cache
1611
- * @param key Key to delete
1612
- * @returns `true` if the key existed and was removed, otherwise `false`
1613
- */
1614
- delete(key) {
1615
- return this.#state.cache?.delete(key) ?? false;
1616
- }
1617
- /**
1618
- * Destroy the instance _(clearing its cache and removing its callback)_
1619
- */
1620
- destroy() {
1621
- this.#state.cache?.clear();
1622
- this.#state.cache = void 0;
1623
- this.#state.getter = void 0;
1624
- }
1625
- /**
1626
- * Get a result from the cache
1627
- * @param key Key to get
1628
- * @returns Cached result or `undefined` if it does not exist
1629
- */
1630
- get(key) {
1631
- return this.#state.cache?.get(key);
1848
+ mapped$1.set(state.element, this);
1632
1849
  }
1633
- /**
1634
- * Does the result exist?
1635
- * @param key Key to check
1636
- * @returns `true` if the result exists, otherwise `false`
1637
- */
1638
- has(key) {
1639
- return this.#state.cache?.has(key) ?? false;
1850
+ destroy() {
1851
+ mapped$1.delete(this.state.element);
1852
+ this.state = void 0;
1640
1853
  }
1641
- /**
1642
- * Run the callback with the provided parameters
1643
- * @param parameters Parameters to pass to the callback
1644
- * @returns Cached or computed _(then cached)_ result
1645
- */
1646
- run(...parameters) {
1647
- if (this.#state.cache == null || this.#state.getter == null) throw new Error("The Memoized instance has been destroyed");
1648
- return this.#state.getter(...parameters);
1854
+ onSort(event, target) {
1855
+ const direction = target.getAttribute("data-sort-direction");
1856
+ const field = target.getAttribute("data-field");
1857
+ if (field != null) this.state.managers.sort.toggle(event, field, direction);
1649
1858
  }
1650
1859
  };
1651
- function getMemoizationOptions(input) {
1652
- const { cacheKey, cacheSize } = isPlainObject(input) ? input : {};
1653
- return {
1654
- cacheKey: typeof cacheKey === "function" ? cacheKey : void 0,
1655
- cacheSize: typeof cacheSize === "number" && cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE
1656
- };
1860
+ function onClick(event) {
1861
+ const target = findAncestor(event, "[data-event]");
1862
+ const table = findAncestor(event, ".tabela__table");
1863
+ if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
1864
+ const manager = mapped$1.get(table);
1865
+ if (manager == null) return;
1866
+ switch (target?.getAttribute("data-event")) {
1867
+ case "group":
1868
+ manager.state.managers.group.handle(target);
1869
+ break;
1870
+ case "heading":
1871
+ manager.onSort(event, target);
1872
+ break;
1873
+ case "row":
1874
+ manager.state.managers.selection.handle(event, target);
1875
+ break;
1876
+ default: break;
1877
+ }
1657
1878
  }
1658
- /**
1659
- * Memoize a function, caching and retrieving results based on the first parameter
1660
- * @param callback Callback to memoize
1661
- * @param options Memoization options
1662
- * @returns Memoized instance
1663
- */
1664
- function memoize(callback, options) {
1665
- return new Memoized(callback, getMemoizationOptions(options));
1879
+ function onKeydown(event) {
1880
+ const target = findAncestor(event, "[data-event]");
1881
+ const table = findAncestor(event, ".tabela__table");
1882
+ if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
1883
+ const manager = mapped$1.get(table);
1884
+ if (manager == null) return;
1885
+ if (event.key === " ") {
1886
+ event.preventDefault();
1887
+ return;
1888
+ }
1889
+ manager.state.managers.navigation.handle(event);
1666
1890
  }
1667
- var DEFAULT_CACHE_SIZE = 1024;
1891
+ const mapped$1 = /* @__PURE__ */ new WeakMap();
1892
+ on(document, "click", onClick);
1893
+ on(document, "keydown", onKeydown, { passive: false });
1894
+ //#endregion
1895
+ //#region node_modules/@oscarpalmer/atoms/dist/string/match.mjs
1668
1896
  /**
1669
1897
  * Check if a string ends with a specified substring
1670
1898
  * @param haystack String to look in
@@ -1673,7 +1901,7 @@ var DEFAULT_CACHE_SIZE = 1024;
1673
1901
  * @returns `true` if the string ends with the given substring, otherwise `false`
1674
1902
  */
1675
1903
  function endsWith(haystack, needle, ignoreCase) {
1676
- return match("endsWith", haystack, needle, ignoreCase === true);
1904
+ return match(MATCH_ENDS_WITH, haystack, needle, ignoreCase === true);
1677
1905
  }
1678
1906
  /**
1679
1907
  * Check if a string includes a specified substring
@@ -1683,7 +1911,7 @@ function endsWith(haystack, needle, ignoreCase) {
1683
1911
  * @returns `true` if the string includes the given substring, otherwise `false`
1684
1912
  */
1685
1913
  function includes(haystack, needle, ignoreCase) {
1686
- return match("includes", haystack, needle, ignoreCase === true);
1914
+ return match(MATCH_INCLUDES, haystack, needle, ignoreCase === true);
1687
1915
  }
1688
1916
  function match(type, haystack, needle, ignoreCase) {
1689
1917
  if (typeof haystack !== "string" || typeof needle !== "string") return false;
@@ -1701,9 +1929,14 @@ function matchCallback(haystack, needle, ignoreCase) {
1701
1929
  * @returns `true` if the string starts with the given substring, otherwise `false`
1702
1930
  */
1703
1931
  function startsWith(haystack, needle, ignoreCase) {
1704
- return match("startsWith", haystack, needle, ignoreCase === true);
1705
- }
1706
- var matchMemoizers = {};
1932
+ return match(MATCH_STARTS_WITH, haystack, needle, ignoreCase === true);
1933
+ }
1934
+ const MATCH_ENDS_WITH = "endsWith";
1935
+ const MATCH_INCLUDES = "includes";
1936
+ const MATCH_STARTS_WITH = "startsWith";
1937
+ const matchMemoizers = {};
1938
+ //#endregion
1939
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/equal.mjs
1707
1940
  function equal(first, second, options) {
1708
1941
  return equalValue(first, second, getEqualOptions(options));
1709
1942
  }
@@ -1800,9 +2033,9 @@ function equalValue(first, second, options) {
1800
2033
  case first instanceof ArrayBuffer && second instanceof ArrayBuffer: return equalArrayBuffer(first, second, options);
1801
2034
  case first instanceof Date && second instanceof Date: return Object.is(Number(first), Number(second));
1802
2035
  case first instanceof DataView && second instanceof DataView: return equalDataView(first, second, options);
1803
- case first instanceof Error && second instanceof Error: return equalProperties(first, second, ["name", "message"], options);
2036
+ case first instanceof Error && second instanceof Error: return equalProperties(first, second, ERROR_PROPERTIES, options);
1804
2037
  case first instanceof Map && second instanceof Map: return equalMap(first, second, options);
1805
- case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, ["source", "flags"], options);
2038
+ case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, EXPRESSION_PROPERTIES, options);
1806
2039
  case first instanceof Set && second instanceof Set: return equalSet(first, second, options);
1807
2040
  case Array.isArray(first) && Array.isArray(second): return equalArray(first, second, options);
1808
2041
  case isPlainObject(first) && isPlainObject(second): return equalPlainObject(first, second, options);
@@ -1869,8 +2102,12 @@ function getEqualOptions(input) {
1869
2102
  options.relaxedNullish = input.relaxedNullish === true;
1870
2103
  return options;
1871
2104
  }
1872
- var ARRAY_PEEK_PERCENTAGE = 10;
1873
- var ARRAY_THRESHOLD = 100;
2105
+ const ARRAY_PEEK_PERCENTAGE = 10;
2106
+ const ARRAY_THRESHOLD = 100;
2107
+ const ERROR_PROPERTIES = ["name", "message"];
2108
+ const EXPRESSION_PROPERTIES = ["source", "flags"];
2109
+ //#endregion
2110
+ //#region src/managers/filter.manager.ts
1874
2111
  var FilterManager = class {
1875
2112
  handlers = Object.freeze({
1876
2113
  add: (item) => this.add(item),
@@ -1884,7 +2121,7 @@ var FilterManager = class {
1884
2121
  }
1885
2122
  add(item) {
1886
2123
  if (this.items[item.field] == null) this.items[item.field] = [];
1887
- else if (this.items[item.field].findIndex((existing) => equal(existing, item)) !== -1) return;
2124
+ else if (this.items[item.field].findIndex((existing) => equal(existing, item)) > -1) return;
1888
2125
  this.items[item.field].push(item);
1889
2126
  this.filter();
1890
2127
  }
@@ -1903,10 +2140,14 @@ var FilterManager = class {
1903
2140
  const { state } = this;
1904
2141
  const filtered = [];
1905
2142
  const filters = Object.entries(this.items);
1906
- const keysLength = state.managers.data.values.keys.original.length;
1907
- rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
1908
- const key = state.managers.data.values.keys.original[keyIndex];
1909
- const row = state.managers.data.values.objects.mapped.get(key);
2143
+ const itemsLength = state.managers.data.state.items.original.length;
2144
+ rowLoop: for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
2145
+ const item = state.managers.data.state.items.original[itemIndex];
2146
+ if (item instanceof GroupComponent) {
2147
+ filtered.push(item);
2148
+ continue;
2149
+ }
2150
+ const row = state.managers.data.state.values.mapped.get(item);
1910
2151
  if (row == null) continue;
1911
2152
  filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
1912
2153
  const [field, items] = filters[filterIndex];
@@ -1917,16 +2158,23 @@ var FilterManager = class {
1917
2158
  }
1918
2159
  continue rowLoop;
1919
2160
  }
1920
- filtered.push(key);
2161
+ filtered.push(item);
1921
2162
  }
1922
- state.managers.data.values.keys.active = filtered;
2163
+ state.managers.data.state.items.active = filtered;
1923
2164
  if (state.managers.sort.items.length > 0) state.managers.sort.sort();
1924
2165
  else state.managers.render.update(true, true);
1925
2166
  }
1926
2167
  remove(value) {
1927
2168
  if (typeof value === "string") {
1928
2169
  if (this.items[value] == null) return;
1929
- this.items = {};
2170
+ const keyed = {};
2171
+ const filters = Object.keys(this.items);
2172
+ const { length } = filters;
2173
+ for (let index = 0; index < length; index += 1) {
2174
+ const field = filters[index];
2175
+ if (field !== value) keyed[field] = this.items[field];
2176
+ }
2177
+ this.items = keyed;
1930
2178
  } else {
1931
2179
  const { field } = value;
1932
2180
  if (this.items[field] == null) return;
@@ -1959,12 +2207,83 @@ const comparators = {
1959
2207
  "starts-with": (row, filter) => startsWith(getString(row), getString(filter), true)
1960
2208
  };
1961
2209
  const equalizer = equal.initialize({ ignoreCase: true });
2210
+ //#endregion
2211
+ //#region src/managers/group.manager.ts
2212
+ var GroupManager = class {
2213
+ collapsed = /* @__PURE__ */ new Set();
2214
+ enabled = false;
2215
+ field;
2216
+ handlers = Object.freeze({ set: (group) => {
2217
+ if (group === this.field) return;
2218
+ this.enabled = !isNullableOrWhitespace(group);
2219
+ this.field = group ?? "";
2220
+ this.state.managers.data.set(this.state.managers.data.get());
2221
+ } });
2222
+ items = [];
2223
+ order = {};
2224
+ constructor(state) {
2225
+ this.state = state;
2226
+ if (isNullableOrWhitespace(state.options.grouping)) return;
2227
+ this.enabled = true;
2228
+ this.field = state.options.grouping;
2229
+ }
2230
+ add(group) {
2231
+ this.set([...this.items, group]);
2232
+ }
2233
+ clear() {
2234
+ const groups = this.items.splice(0);
2235
+ const { length } = groups;
2236
+ for (let index = 0; index < length; index += 1) this.remove(groups[index]);
2237
+ }
2238
+ destroy() {
2239
+ const groups = this.items.splice(0);
2240
+ const { length } = groups;
2241
+ for (let index = 0; index < length; index += 1) removeGroup(groups[index]);
2242
+ this.collapsed.clear();
2243
+ this.handlers = void 0;
2244
+ this.state = void 0;
2245
+ }
2246
+ get(value) {
2247
+ const asString = getString(value);
2248
+ return this.items.find((item) => item.value.stringified === asString);
2249
+ }
2250
+ handle(button) {
2251
+ const value = button.dataset.key?.replace(`tabela_${this.state.id}_group:`, "");
2252
+ const group = this.get(value);
2253
+ if (group == null) return;
2254
+ const { collapsed, items, state } = this;
2255
+ group.expanded = !group.expanded;
2256
+ const index = items.indexOf(group);
2257
+ let first = state.managers.data.state.items.original.indexOf(items[index]) + 1;
2258
+ const last = items[index + 1] == null ? state.managers.data.state.items.original.length - 1 : state.managers.data.state.items.original.indexOf(items[index + 1]) - 1;
2259
+ for (; first <= last; first += 1) {
2260
+ const key = state.managers.data.state.items.original[first];
2261
+ if (group.expanded) collapsed.delete(key);
2262
+ else collapsed.add(key);
2263
+ }
2264
+ if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
2265
+ else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
2266
+ else state.managers.render.update(true, true);
2267
+ }
2268
+ remove(group) {
2269
+ removeGroup(group);
2270
+ this.set(this.items.filter((item) => item !== group));
2271
+ }
2272
+ set(items) {
2273
+ this.items = sort(items, (item) => item.label);
2274
+ this.order = toRecord(items, (group) => group.value.stringified, (_, index) => index);
2275
+ }
2276
+ };
2277
+ //#endregion
2278
+ //#region src/helpers/misc.helpers.ts
1962
2279
  function getKey(value) {
1963
2280
  if (typeof value === "number") return value;
1964
2281
  if (typeof value !== "string") return;
1965
2282
  return integerExpression.test(value) ? Number.parseInt(value, 10) : value;
1966
2283
  }
1967
2284
  const integerExpression = /^\d+$/;
2285
+ //#endregion
2286
+ //#region src/managers/navigation.manager.ts
1968
2287
  var NavigationManager = class {
1969
2288
  active;
1970
2289
  constructor(state) {
@@ -1978,28 +2297,28 @@ var NavigationManager = class {
1978
2297
  event.preventDefault();
1979
2298
  const { components, id, managers } = this.state;
1980
2299
  const activeDescendant = components.body.elements.group.getAttribute("aria-activedescendant");
1981
- const keys = managers.data.values.keys.active ?? managers.data.values.keys.original;
1982
- const { length } = keys;
2300
+ const { items } = managers.data;
2301
+ const { length } = items;
1983
2302
  let next;
1984
2303
  if (isNullableOrWhitespace(activeDescendant)) next = getDefaultIndex(event.key, length);
1985
- else next = getIndex(event, activeDescendant, id, keys);
1986
- if (next != null) this.setActive(keys.at(next));
2304
+ else next = getIndex(this.state, event, activeDescendant, id);
2305
+ if (next != null) this.setActive(items.at(next));
1987
2306
  }
1988
- setActive(key, scroll) {
1989
- const { components, managers, options } = this.state;
1990
- this.active = key;
2307
+ setActive(item, scroll) {
2308
+ const { components, id, managers, options } = this.state;
2309
+ this.active = item;
1991
2310
  const active = components.body.elements.group.querySelectorAll("[data-active=\"true\"]");
1992
2311
  for (const item of active) item.setAttribute("data-active", "false");
1993
- const row = managers.row.get(key);
1994
- if (row != null) {
1995
- row.element?.setAttribute("data-active", "true");
1996
- if (scroll ?? true) if (row.element == null) components.body.elements.group.scrollTo({
1997
- top: managers.data.getIndex(key) * options.rowHeight,
2312
+ const component = item instanceof GroupComponent ? item : managers.row.get(item, false);
2313
+ if (component != null) {
2314
+ component.element?.setAttribute("data-active", "true");
2315
+ if (scroll ?? true) if (component.element == null) components.body.elements.group.scrollTo({
2316
+ top: managers.data.getIndex(item) * options.rowHeight,
1998
2317
  behavior: "smooth"
1999
2318
  });
2000
- else row.element.scrollIntoView({ block: "nearest" });
2319
+ else component.element.scrollIntoView({ block: "nearest" });
2001
2320
  }
2002
- components.body.elements.group.setAttribute("aria-activedescendant", row == null ? "" : `tabela_${this.state.id}_row_${key}`);
2321
+ components.body.elements.group.setAttribute("aria-activedescendant", component == null ? "" : `tabela_${id}_${component.key}`);
2003
2322
  }
2004
2323
  };
2005
2324
  function getDefaultIndex(key, max) {
@@ -2010,11 +2329,11 @@ function getDefaultIndex(key, max) {
2010
2329
  default: return 0;
2011
2330
  }
2012
2331
  }
2013
- function getIndex(event, active, id, keys) {
2014
- const key = getKey(active.replace(`tabela_${id}_row_`, ""));
2332
+ function getIndex(state, event, active, id) {
2333
+ const key = getKey(active.replace(`tabela_${id}_`, ""));
2015
2334
  if (key == null) return;
2016
- if (absoluteKeys.has(event.key)) return event.key === "Home" ? 0 : keys.length - 1;
2017
- return clamp(keys.indexOf(key) + getOffset(event.key), 0, keys.length - 1, true);
2335
+ if (absoluteKeys.has(event.key)) return event.key === "Home" ? 0 : state.managers.data.size - 1;
2336
+ return clamp(state.managers.data.getIndex(key) + getOffset(event.key), 0, state.managers.data.size - 1, true);
2018
2337
  }
2019
2338
  function getOffset(key) {
2020
2339
  switch (key) {
@@ -2034,6 +2353,8 @@ const allKeys = new Set([
2034
2353
  ...arrowKeys,
2035
2354
  ...pageKeys
2036
2355
  ]);
2356
+ //#endregion
2357
+ //#region src/components/row.component.ts
2037
2358
  function removeRow(pool, row) {
2038
2359
  if (row.element != null) {
2039
2360
  row.element.innerHTML = "";
@@ -2054,20 +2375,20 @@ function renderRow(state, row) {
2054
2375
  "data-active": String(state.managers.navigation.active === row.key),
2055
2376
  "data-event": "row",
2056
2377
  "data-key": key,
2057
- id: `tabela_${state.id}_row_${key}`
2378
+ id: `tabela_${state.id}_${key}`
2058
2379
  });
2059
- element.classList.add("tabela__row--body");
2060
- if (selected) element.classList.add("tabela__row--selected");
2061
- else element.classList.remove("tabela__row--selected");
2380
+ element.classList.add(CSS_TABELA_ROW_BODY);
2381
+ if (selected) element.classList.add(CSS_TABELA_ROW_SELECTED);
2382
+ else element.classList.remove(CSS_TABELA_ROW_SELECTED);
2062
2383
  const columns = state.managers.column.items;
2063
2384
  const { length } = columns;
2064
- const data = state.managers.data.values.objects.mapped.get(row.key);
2385
+ const data = state.managers.data.state.values.mapped.get(row.key);
2065
2386
  if (data == null) return;
2066
2387
  for (let index = 0; index < length; index += 1) {
2067
2388
  const { options } = columns[index];
2068
2389
  state.managers.render.pool.cells[options.field] ??= [];
2069
2390
  const cell = state.managers.render.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
2070
- cell.textContent = String(data[options.field]);
2391
+ cell.textContent = String(getValue(data, options.field));
2071
2392
  row.cells[options.field] = cell;
2072
2393
  element.append(cell);
2073
2394
  }
@@ -2079,16 +2400,21 @@ var RowComponent = class {
2079
2400
  this.key = key;
2080
2401
  }
2081
2402
  };
2082
- function getRange(down) {
2083
- const { components, managers, options } = this.state;
2084
- const { clientHeight, scrollTop } = components.body.elements.group;
2085
- const first = Math.floor(scrollTop / options.rowHeight);
2086
- const last = Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
2087
- const before = Math.ceil(clientHeight / options.rowHeight) * (down ? 1 : 2);
2088
- const after = Math.ceil(clientHeight / options.rowHeight) * (down ? 2 : 1);
2089
- const start = Math.max(0, first - before);
2403
+ //#endregion
2404
+ //#region src/managers/render.manager.ts
2405
+ function getRange(state, down) {
2406
+ const { element, managers, options } = state;
2407
+ const { clientHeight, scrollTop } = element;
2408
+ const { items } = managers.data;
2409
+ const firstIndex = Math.floor(scrollTop / options.rowHeight);
2410
+ const lastIndex = items.length - managers.group.collapsed.size - 1;
2411
+ const last = Math.min(lastIndex, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
2412
+ const visible = clientHeight / options.rowHeight;
2413
+ const before = Math.ceil(visible) * (down ? 1 : 2);
2414
+ const after = Math.ceil(visible) * (down ? 2 : 1);
2415
+ const start = Math.max(0, firstIndex - before);
2090
2416
  return {
2091
- end: Math.min((managers.data.values.keys.active?.length ?? managers.data.values.keys.original.length) - 1, last + after),
2417
+ end: Math.min(lastIndex, last + after),
2092
2418
  start
2093
2419
  };
2094
2420
  }
@@ -2096,7 +2422,7 @@ function onScroll() {
2096
2422
  const { state } = this;
2097
2423
  if (!state.active) {
2098
2424
  requestAnimationFrame(() => {
2099
- const top = state.components.body.elements.group.scrollTop;
2425
+ const top = state.element.scrollTop;
2100
2426
  this.update(top > state.top);
2101
2427
  state.active = false;
2102
2428
  state.top = top;
@@ -2114,7 +2440,7 @@ var RenderManager = class {
2114
2440
  state;
2115
2441
  visible = /* @__PURE__ */ new Map();
2116
2442
  constructor(state) {
2117
- this.listener = on(state.components.body.elements.group, "scroll", onScroll.bind(this));
2443
+ this.listener = on(state.element, "scroll", onScroll.bind(this));
2118
2444
  this.state = {
2119
2445
  ...state,
2120
2446
  active: false,
@@ -2125,6 +2451,11 @@ var RenderManager = class {
2125
2451
  const { listener, pool, visible } = this;
2126
2452
  listener();
2127
2453
  visible.clear();
2454
+ const cells = Object.values(pool.cells).flat();
2455
+ let { length } = cells;
2456
+ for (let index = 0; index < length; index += 1) cells[index].remove();
2457
+ length = pool.rows.length;
2458
+ for (let index = 0; index < length; index += 1) pool.rows[index].remove();
2128
2459
  pool.cells = {};
2129
2460
  pool.rows = [];
2130
2461
  this.fragment = void 0;
@@ -2138,7 +2469,8 @@ var RenderManager = class {
2138
2469
  const { length } = fields;
2139
2470
  for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
2140
2471
  for (const [, key] of visible) {
2141
- const row = state.managers.row.get(key);
2472
+ if (key instanceof GroupComponent) continue;
2473
+ const row = state.managers.row.get(key, false);
2142
2474
  if (row == null || row.element == null) continue;
2143
2475
  for (let index = 0; index < length; index += 1) {
2144
2476
  row.cells[fields[index]].innerHTML = "";
@@ -2155,53 +2487,81 @@ var RenderManager = class {
2155
2487
  update(down, rerender) {
2156
2488
  const { state, pool, visible } = this;
2157
2489
  const { components, managers, options } = state;
2158
- components.body.elements.faker.style.height = `${managers.data.size * options.rowHeight}px`;
2490
+ components.body.elements.faker.style.height = `${(managers.data.size - managers.group.collapsed.size) * options.rowHeight}px`;
2159
2491
  const indices = /* @__PURE__ */ new Set();
2160
- const range = getRange.call(this, down);
2492
+ const range = getRange(state, down);
2161
2493
  for (let index = range.start; index <= range.end; index += 1) indices.add(index);
2162
2494
  let remove = rerender ?? false;
2163
2495
  for (const [index, key] of visible) {
2164
- const row = managers.row.get(key);
2165
- if (remove || row == null || !indices.has(index)) {
2496
+ if (key instanceof GroupComponent) {
2497
+ if (remove || !indices.has(index)) {
2498
+ visible.delete(index);
2499
+ key.element?.remove();
2500
+ }
2501
+ continue;
2502
+ }
2503
+ const row = managers.row.get(key, false);
2504
+ if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
2166
2505
  visible.delete(index);
2167
2506
  if (row != null) removeRow(pool, row);
2168
2507
  }
2169
2508
  }
2170
2509
  const fragment = this.getFragment();
2171
- const keys = managers.data.values.keys.active ?? managers.data.values.keys.original;
2510
+ const { items } = managers.data;
2172
2511
  let count = 0;
2173
- for (let index = range.start; index <= range.end; index += 1) {
2512
+ let offset = 0;
2513
+ for (let index = range.start; index <= range.end + offset; index += 1) {
2174
2514
  if (visible.has(index)) continue;
2175
- const key = keys[index];
2176
- const row = managers.row.get(key);
2515
+ const item = items[index];
2516
+ if (item instanceof GroupComponent) {
2517
+ count += 1;
2518
+ renderGroup(state, item);
2519
+ visible.set(index, item);
2520
+ if (item.element != null) {
2521
+ item.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
2522
+ fragment.append(item.element);
2523
+ }
2524
+ continue;
2525
+ }
2526
+ const row = managers.row.get(item, true);
2177
2527
  if (row == null) continue;
2528
+ if (managers.group.collapsed.has(item)) {
2529
+ offset += 1;
2530
+ continue;
2531
+ }
2178
2532
  count += 1;
2179
2533
  renderRow(state, row);
2180
- visible.set(index, key);
2534
+ visible.set(index, item);
2181
2535
  if (row.element != null) {
2182
- row.element.style.transform = `translateY(${index * options.rowHeight}px)`;
2536
+ row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
2183
2537
  fragment.append(row.element);
2184
2538
  }
2185
2539
  }
2186
2540
  if (count > 0) components.body.elements.group[down ? "append" : "prepend"](fragment);
2187
2541
  }
2188
2542
  };
2543
+ //#endregion
2544
+ //#region src/managers/row.manager.ts
2189
2545
  var RowManager = class {
2190
2546
  components = /* @__PURE__ */ new Map();
2191
2547
  constructor(state) {
2192
2548
  this.state = state;
2193
2549
  }
2550
+ clear() {
2551
+ const { components } = this;
2552
+ const rows = [...components.values()];
2553
+ const { length } = rows;
2554
+ for (let index = 0; index < length; index += 1) this.removeRow(rows[index]);
2555
+ components.clear();
2556
+ }
2194
2557
  destroy() {
2195
- const components = [...this.components.values()];
2196
- const { length } = components;
2197
- for (let index = 0; index < length; index += 1) removeRow(this.state.managers.render.pool, components[index]);
2198
- this.components.clear();
2558
+ this.clear();
2199
2559
  this.components = void 0;
2200
2560
  this.state = void 0;
2201
2561
  }
2202
- get(key) {
2562
+ get(key, create) {
2203
2563
  let row = this.components.get(key);
2204
- if (row == null) {
2564
+ if (row == null && create) {
2205
2565
  row = new RowComponent(key);
2206
2566
  this.components.set(key, row);
2207
2567
  }
@@ -2212,191 +2572,31 @@ var RowManager = class {
2212
2572
  }
2213
2573
  remove(key) {
2214
2574
  const row = this.components.get(key);
2215
- if (row != null) {
2216
- removeRow(this.state.managers.render.pool, row);
2217
- this.components.delete(key);
2218
- }
2575
+ if (row != null) this.removeRow(row);
2576
+ }
2577
+ removeRow(row) {
2578
+ if (row.element != null) removeRow(this.state.managers.render.pool, row);
2579
+ this.components.delete(row.key);
2219
2580
  }
2220
2581
  update(key) {
2221
2582
  const row = this.components.get(key);
2222
2583
  if (row != null) renderRow(this.state, row);
2223
2584
  }
2224
2585
  };
2225
- function isInert(item) {
2226
- return (item.element.inert ?? false) || EXPRESSION_TRUEISH.test(item.element.getAttribute(ATTRIBUTE_INERT)) || item.element.parentElement != null && isInert({
2227
- element: item.element.parentElement,
2228
- tabIndex: TABINDEX_DEFAULT
2229
- });
2230
- }
2231
- var ATTRIBUTE_INERT = "inert";
2232
- var EXPRESSION_TRUEISH = /^(|true)$/i;
2233
- [
2234
- "[contenteditable]:not([contenteditable=\"false\"])",
2235
- "[tabindex]:not(slot)",
2236
- "a[href]",
2237
- "audio[controls]",
2238
- "button",
2239
- "details",
2240
- "details > summary:first-of-type",
2241
- "input",
2242
- "select",
2243
- "textarea",
2244
- "video[controls]"
2245
- ].map((selector) => `${selector}:not([inert])`).join(",");
2246
- var TABINDEX_DEFAULT = -1;
2247
- function handleElement(element, depth) {
2248
- if (depth === 0) {
2249
- const removable = element.querySelectorAll(REMOVE_SELECTOR);
2250
- for (const item of removable) item.remove();
2251
- }
2252
- sanitizeAttributes(element, [...element.attributes]);
2253
- }
2254
- /**
2255
- * Is the element clobbered?
2256
- *
2257
- * Thanks, DOMPurify _(https://github.com/cure53/DOMPurify)_
2258
- */
2259
- function isClobbered(value) {
2260
- return value instanceof HTMLFormElement && (typeof value.nodeName !== "string" || typeof value.textContent !== "string" || typeof value.removeChild !== "function" || !(value.attributes instanceof NamedNodeMap) || typeof value.removeAttribute !== "function" || typeof value.setAttribute !== "function" || typeof value.namespaceURI !== "string" || typeof value.insertBefore !== "function" || typeof value.hasChildNodes !== "function");
2261
- }
2262
- function removeNode(node) {
2263
- if (typeof node.remove === "function") node.remove();
2264
- }
2265
- function sanitizeAttributes(element, attributes) {
2266
- const { length } = attributes;
2267
- for (let index = 0; index < length; index += 1) {
2268
- const { name, value } = attributes[index];
2269
- if (_isBadAttribute(name, value, false) || _isEmptyNonBooleanAttribute(name, value, false)) element.removeAttribute(name);
2270
- else if (_isInvalidBooleanAttribute(name, value, false)) setAttribute(element, name, true);
2271
- }
2272
- }
2273
- function sanitizeNodes(nodes, depth) {
2274
- const actual = nodes.filter((node) => node instanceof Node);
2275
- let { length } = nodes;
2276
- for (let index = 0; index < length; index += 1) {
2277
- const node = actual[index];
2278
- let remove = isClobbered(node);
2279
- if (!remove) switch (node.nodeType) {
2280
- case Node.ELEMENT_NODE:
2281
- handleElement(node, depth);
2282
- break;
2283
- case Node.COMMENT_NODE:
2284
- remove = COMMENT_HARMFUL.test(node.data);
2285
- break;
2286
- case Node.DOCUMENT_TYPE_NODE:
2287
- case Node.PROCESSING_INSTRUCTION_NODE:
2288
- remove = true;
2289
- break;
2290
- }
2291
- if (remove) {
2292
- removeNode(node);
2293
- actual.splice(index, 1);
2294
- index -= 1;
2295
- length -= 1;
2296
- continue;
2297
- }
2298
- if (node.hasChildNodes()) sanitizeNodes([...node.childNodes], depth + 1);
2299
- }
2300
- return nodes;
2301
- }
2302
- var COMMENT_HARMFUL = /<[/\w]/g;
2303
- var REMOVE_SELECTOR = "script, toretto-temporary";
2304
- function createHtml(value) {
2305
- const parsed = getParser().parseFromString(getHtml(value), PARSE_TYPE_HTML);
2306
- parsed.body.normalize();
2307
- sanitizeNodes([parsed.body], 0);
2308
- return parsed.body.innerHTML;
2309
- }
2310
- function createTemplate(value, options) {
2311
- const template = document.createElement(TEMPLATE_TAG);
2312
- template.innerHTML = createHtml(value);
2313
- if (typeof value === "string" && options.cache) templates[value] = template;
2314
- return template;
2315
- }
2316
- function getHtml(value) {
2317
- return `${TEMPORARY_ELEMENT}${typeof value === "string" ? value : value.innerHTML}${TEMPORARY_ELEMENT}`;
2318
- }
2319
- function getNodes(value, options) {
2320
- if (typeof value !== "string" && !(value instanceof HTMLTemplateElement)) return [];
2321
- const template = getTemplate(value, options);
2322
- return template == null ? [] : [...template.content.cloneNode(true).childNodes];
2323
- }
2324
- function getOptions(input) {
2325
- const options = isPlainObject$1(input) ? input : {};
2326
- options.cache = typeof options.cache === "boolean" ? options.cache : true;
2327
- return options;
2328
- }
2329
- function getParser() {
2330
- parser ??= new DOMParser();
2331
- return parser;
2332
- }
2333
- function getTemplate(value, options) {
2334
- if (value instanceof HTMLTemplateElement) return createTemplate(value, options);
2335
- if (value.trim().length === 0) return;
2336
- let template = templates[value];
2337
- if (template != null) return template;
2338
- const element = EXPRESSION_ID.test(value) ? document.querySelector(`#${value}`) : null;
2339
- return createTemplate(element instanceof HTMLTemplateElement ? element : value, options);
2340
- }
2341
- var html = ((value, options) => {
2342
- return getNodes(value, getOptions(options));
2343
- });
2344
- html.clear = () => {
2345
- templates = {};
2346
- };
2347
- html.remove = (template) => {
2348
- if (typeof template !== "string" || templates[template] == null) return;
2349
- const keys = Object.keys(templates);
2350
- const { length } = keys;
2351
- const updated = {};
2352
- for (let index = 0; index < length; index += 1) {
2353
- const key = keys[index];
2354
- if (key !== template) updated[key] = templates[key];
2355
- }
2356
- templates = updated;
2357
- };
2358
- var EXPRESSION_ID = /^[a-z][\w-]*$/i;
2359
- var PARSE_TYPE_HTML = "text/html";
2360
- var TEMPLATE_TAG = "template";
2361
- var TEMPORARY_ELEMENT = "<toretto-temporary></toretto-temporary>";
2362
- var parser;
2363
- var templates = {};
2364
- function getSupport() {
2365
- if (window == null || navigator == null) return false;
2366
- if ("matchMedia" in window) {
2367
- const media = matchMedia?.("(pointer: coarse)");
2368
- if (typeof media?.matches === "boolean" && media.matches) return true;
2369
- }
2370
- if ("ontouchstart" in window) return true;
2371
- if (typeof navigator.maxTouchPoints === "number" && navigator.maxTouchPoints > 0) return true;
2372
- if (typeof navigator.msMaxTouchPoints === "number" && navigator.msMaxTouchPoints > 0) return true;
2373
- return false;
2374
- }
2375
- (() => {
2376
- let support = getSupport();
2377
- const instance = Object.create({
2378
- get() {
2379
- return support;
2380
- },
2381
- update() {
2382
- support = getSupport();
2383
- return support;
2384
- }
2385
- });
2386
- Object.defineProperty(instance, "value", { get() {
2387
- return support;
2388
- } });
2389
- return instance;
2390
- })();
2391
- const dragStyling = toggleStyles(document.body, {
2586
+ //#endregion
2587
+ //#region src/helpers/style.helper.ts
2588
+ const preventSelection = toggleStyles(document.body, {
2392
2589
  userSelect: "none",
2393
2590
  webkitUserSelect: "none"
2394
2591
  });
2592
+ //#endregion
2593
+ //#region src/managers/selection.manager.ts
2395
2594
  var SelectionManager = class {
2396
2595
  handlers = Object.freeze({
2596
+ add: (keys) => this.add(keys),
2397
2597
  clear: () => this.clear(),
2398
- deselect: (keys) => this.deselect(keys),
2399
- select: (keys) => this.select(keys),
2598
+ remove: (keys) => this.remove(keys),
2599
+ set: (keys) => this.set(keys),
2400
2600
  toggle: () => this.toggle()
2401
2601
  });
2402
2602
  items = /* @__PURE__ */ new Set();
@@ -2405,21 +2605,24 @@ var SelectionManager = class {
2405
2605
  this.state = state;
2406
2606
  mapped.set(state.element, this);
2407
2607
  }
2608
+ add(keys) {
2609
+ const { length } = keys;
2610
+ let update = false;
2611
+ for (let index = 0; index < length; index += 1) {
2612
+ const key = keys[index];
2613
+ if (!this.items.has(key)) {
2614
+ this.items.add(key);
2615
+ update = true;
2616
+ }
2617
+ }
2618
+ if (update) this.update([]);
2619
+ }
2408
2620
  clear() {
2409
2621
  if (this.items.size === 0) return;
2410
2622
  const removed = [...this.items];
2411
2623
  this.items.clear();
2412
2624
  this.update(removed);
2413
2625
  }
2414
- deselect(keys) {
2415
- const { length } = keys;
2416
- const removed = [];
2417
- for (let index = 0; index < length; index += 1) {
2418
- const key = keys[index];
2419
- if (this.items.delete(key)) removed.push(key);
2420
- }
2421
- if (removed.length > 0) this.update(removed);
2422
- }
2423
2626
  destroy() {
2424
2627
  mapped.delete(this.state.element);
2425
2628
  this.handlers = void 0;
@@ -2439,8 +2642,8 @@ var SelectionManager = class {
2439
2642
  this.last = key;
2440
2643
  this.state.managers.navigation.setActive(key, false);
2441
2644
  if (event.ctrlKey || event.metaKey) {
2442
- if (items.has(key)) this.deselect([key]);
2443
- else this.select([key]);
2645
+ if (items.has(key)) this.remove([key]);
2646
+ else this.add([key]);
2444
2647
  return;
2445
2648
  }
2446
2649
  this.set([key]);
@@ -2451,29 +2654,29 @@ var SelectionManager = class {
2451
2654
  const fromKey = keyed ? from : getKey(from.getAttribute("data-key"));
2452
2655
  const toKey = keyed ? to : getKey(to.getAttribute("data-key"));
2453
2656
  if (fromKey === toKey) return;
2454
- const keys = state.managers.data.values.keys.active ?? state.managers.data.values.keys.original;
2657
+ const { items } = state.managers.data;
2455
2658
  const fromIndex = state.managers.data.getIndex(fromKey);
2456
2659
  const toIndex = state.managers.data.getIndex(toKey);
2457
2660
  if (fromIndex === -1 || toIndex === -1) return;
2458
2661
  const [start, end] = fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
2459
2662
  const selected = [];
2460
- for (let index = start; index <= end; index += 1) selected.push(keys[index]);
2461
- if (keyed) this.select(selected);
2663
+ for (let index = start; index <= end; index += 1) {
2664
+ const item = items[index];
2665
+ if (!(item instanceof GroupComponent)) selected.push(item);
2666
+ }
2667
+ if (keyed) this.add(selected);
2462
2668
  else this.set(selected);
2463
2669
  this.last = toKey;
2464
2670
  this.state.managers.navigation.setActive(toKey, false);
2465
2671
  }
2466
- select(keys) {
2672
+ remove(keys) {
2467
2673
  const { length } = keys;
2468
- let update = false;
2674
+ const removed = [];
2469
2675
  for (let index = 0; index < length; index += 1) {
2470
2676
  const key = keys[index];
2471
- if (!this.items.has(key)) {
2472
- this.items.add(key);
2473
- update = true;
2474
- }
2677
+ if (this.items.delete(key)) removed.push(key);
2475
2678
  }
2476
- if (update) this.update([]);
2679
+ if (removed.length > 0) this.update(removed);
2477
2680
  }
2478
2681
  set(keys) {
2479
2682
  const { items } = this;
@@ -2485,11 +2688,12 @@ var SelectionManager = class {
2485
2688
  }
2486
2689
  toggle() {
2487
2690
  const { items, state } = this;
2488
- const all = state.managers.data.values.keys.active ?? state.managers.data.values.keys.original;
2489
- if (items.size === all.length) this.clear();
2490
- else this.select(all);
2691
+ const data = state.managers.data.items;
2692
+ if (items.size === data.length - state.managers.group.items.length) this.clear();
2693
+ else this.set(data.filter((key) => !(key instanceof GroupComponent)));
2491
2694
  }
2492
2695
  update(removed) {
2696
+ const { state } = this;
2493
2697
  const items = [...removed.map((key) => ({
2494
2698
  key,
2495
2699
  removed: true
@@ -2497,28 +2701,28 @@ var SelectionManager = class {
2497
2701
  key,
2498
2702
  removed: false
2499
2703
  }))];
2500
- const { length } = items;
2704
+ let { length } = items;
2501
2705
  for (let index = 0; index < length; index += 1) {
2502
2706
  const { key, removed } = items[index];
2503
- const row = this.state.managers.row.get(key);
2504
- if (row == null || row.element == null) continue;
2505
- setAttribute(row.element, "aria-selected", String(!removed));
2506
- if (removed) row.element.classList.remove("tabela__row--selected");
2507
- else row.element.classList.add("tabela__row--selected");
2707
+ const element = state.managers.row.get(key, false)?.element;
2708
+ if (element == null) continue;
2709
+ setAttribute(element, "aria-selected", String(!removed));
2710
+ if (removed) element.classList.remove(CSS_TABELA_ROW_SELECTED);
2711
+ else element.classList.add(CSS_TABELA_ROW_SELECTED);
2508
2712
  }
2509
2713
  }
2510
2714
  };
2511
2715
  function getPlaceholder() {
2512
- placeholder ??= createElement("div", { className: "tabela__selection--placeholder" }, {}, {});
2716
+ placeholder ??= createElement("div", { className: CSS_TABELA_SELECTION }, {}, {});
2513
2717
  return placeholder;
2514
2718
  }
2515
2719
  function onMouseDown(event) {
2516
2720
  if (shifted) {
2517
- const row = findAncestor(event.target, ".tabela__row--body");
2721
+ const row = findAncestor(event.target, `.${CSS_TABELA_ROW_BODY}`);
2518
2722
  if (!(row instanceof HTMLElement)) return;
2519
2723
  startElement = row;
2520
2724
  startPosition = getPosition(event);
2521
- dragStyling.set();
2725
+ preventSelection.set();
2522
2726
  }
2523
2727
  }
2524
2728
  function onMouseMove(event) {
@@ -2539,14 +2743,14 @@ function onMouseUp(event) {
2539
2743
  if (startElement == null) return;
2540
2744
  if (!event.shiftKey) {
2541
2745
  shifted = false;
2542
- dragStyling.remove();
2746
+ preventSelection.remove();
2543
2747
  }
2544
2748
  getPlaceholder().remove();
2545
2749
  const row = findAncestor(event.target, ".tabela__row--body");
2546
2750
  if (row instanceof HTMLElement) {
2547
2751
  endElement = row;
2548
- const endTable = findAncestor(endElement, ".tabela");
2549
- const startTable = findAncestor(startElement, ".tabela");
2752
+ const endTable = findAncestor(endElement, ".tabela__table");
2753
+ const startTable = findAncestor(startElement, ".tabela__table");
2550
2754
  if (startTable != null && startTable === endTable) mapped.get(startTable)?.range(startElement, endElement);
2551
2755
  }
2552
2756
  endElement = void 0;
@@ -2573,120 +2777,179 @@ on(document, "keyup", onShiftUp);
2573
2777
  on(document, "mousedown", onMouseDown);
2574
2778
  on(document, "mousemove", onMouseMove);
2575
2779
  on(document, "mouseup", onMouseUp);
2576
- var SortManager = class {
2577
- handlers = Object.freeze({
2578
- add: (field, direction) => this.add(field, direction),
2579
- flip: (field) => this.flip(field),
2580
- clear: () => this.clear(),
2581
- remove: (field) => this.remove(field),
2582
- set: (items) => this.set(items)
2583
- });
2584
- items = [];
2780
+ //#endregion
2781
+ //#region src/managers/style.manager.ts
2782
+ var StyleManager = class {
2585
2783
  constructor(state) {
2586
2784
  this.state = state;
2587
- }
2588
- add(field, direction) {
2589
- if (this.items.findIndex((item) => item.key === field) > -1) return;
2590
- this.items.push({
2591
- key: field,
2592
- direction: direction ?? "ascending"
2593
- });
2594
- this.sort();
2595
- }
2596
- addOrSet(event, field) {
2597
- if (event.ctrlKey || event.metaKey) this.add(field);
2598
- else this.set([{
2599
- field,
2600
- direction: "ascending"
2601
- }]);
2602
- }
2603
- clear() {
2604
- if (this.items.length > 0) {
2605
- this.items.length = 0;
2606
- this.sort();
2607
- }
2608
- }
2609
- destroy() {
2610
- this.handlers = void 0;
2611
- this.items = void 0;
2612
- this.state = void 0;
2613
- }
2614
- flip(field) {
2615
- const item = this.items.find((item) => item.key === field);
2616
- if (item == null) return;
2617
- item.direction = item.direction === "ascending" ? "descending" : "ascending";
2618
- this.sort();
2619
- }
2620
- remove(field) {
2621
- const index = this.items.findIndex((item) => item.key === field);
2622
- if (index > -1) {
2623
- this.items.splice(index, 1);
2624
- this.sort();
2625
- }
2626
- }
2627
- removeOrClear(event, field) {
2628
- if (event.ctrlKey || event.metaKey) this.remove(field);
2629
- else this.clear();
2630
- }
2631
- set(items) {
2632
- this.items.splice(0, this.items.length, ...items.map((item) => ({
2633
- key: item.field,
2634
- direction: item.direction
2635
- })));
2636
- this.sort();
2637
- }
2638
- sort() {
2639
- const { items, state } = this;
2640
- const { length } = state.managers.column.items;
2641
- for (let index = 0; index < length; index += 1) {
2642
- const column = state.managers.column.items[index];
2643
- const sorterIndex = items.findIndex((item) => item.key === column.options.field);
2644
- const sorterItem = items[sorterIndex];
2645
- setAttributes(column.elements.wrapper, {
2646
- "aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
2647
- "data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
2648
- });
2649
- setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
2650
- }
2651
- state.managers.data.values.keys.active = items.length === 0 ? void 0 : sort(state.managers.data.values.keys.active?.map((key) => state.managers.data.values.objects.mapped.get(key)) ?? state.managers.data.values.objects.array, items).map((row) => row[state.key]);
2652
- state.managers.render.update(true, true);
2653
- }
2654
- toggle(event, field, direction) {
2655
- switch (direction) {
2656
- case "ascending":
2657
- this.flip(field);
2658
- return;
2659
- case "descending":
2660
- this.removeOrClear(event, field);
2661
- return;
2662
- default:
2663
- this.addOrSet(event, field);
2664
- return;
2665
- }
2785
+ if (appended) return;
2786
+ appended = true;
2787
+ const style = document.createElement("style");
2788
+ style.textContent = styling;
2789
+ document.head.appendChild(style);
2666
2790
  }
2667
2791
  };
2792
+ const styling = `/** Table */
2793
+
2794
+ :where(.tabela) {
2795
+ flex: 1;
2796
+ position: relative;
2797
+ background-color: var(--oui-absolute);
2798
+ border: 1px solid grey;
2799
+ }
2800
+
2801
+ :where(.tabela__table) {
2802
+ min-height: 24em;
2803
+ display: flex;
2804
+ flex-flow: column nowrap;
2805
+ flex: 1;
2806
+ overflow: auto;
2807
+ position: absolute;
2808
+ inset: 0;
2809
+ }
2810
+
2811
+ /** Row group */
2812
+
2813
+ :where(.tabela__rowgroup--header),
2814
+ :where(.tabela__rowgroup--footer) {
2815
+ background-color: white;
2816
+ position: sticky;
2817
+ left: 0;
2818
+ z-index: 10;
2819
+ }
2820
+
2821
+ :where(.tabela__rowgroup--header) {
2822
+ top: 0;
2823
+ }
2824
+
2825
+ :where(.tabela__rowgroup--footer) {
2826
+ bottom: 0;
2827
+ }
2828
+
2829
+ :where(.tabela__rowgroup--body) {
2830
+ display: flex;
2831
+ flex-flow: column nowrap;
2832
+ flex: 1;
2833
+ }
2834
+
2835
+ :where(.tabela__rowgroup--body:focus) {
2836
+ outline: none;
2837
+ }
2838
+
2839
+ :where(.tabela:has(.tabela__rowgroup--body:focus-visible)) {
2840
+ outline: 2px solid var(--oui-blue-6);
2841
+ outline-offset: 2px;
2842
+ }
2843
+
2844
+ /** Row */
2845
+
2846
+ :where(.tabela__row) {
2847
+ width: 100%;
2848
+ display: flex;
2849
+ flex-flow: row nowrap;
2850
+ }
2851
+
2852
+ :where(.tabela__row:last-child .tabela__cell) {
2853
+ border-bottom-width: 0;
2854
+ }
2855
+
2856
+ :where(.tabela__row--body),
2857
+ :where(.tabela__row--group) {
2858
+ flex: 1;
2859
+ position: absolute;
2860
+ }
2861
+
2862
+ :where(.tabela__row--selected) {
2863
+ background-color: var(--oui-blue-1);
2864
+ color: var(--oui-blue-9);
2865
+ }
2866
+
2867
+ :where(.tabela:has(.tabela__rowgroup--body:focus-visible) .tabela__row[data-active="true"]) {
2868
+ outline: 2px solid var(--oui-blue-6);
2869
+ outline-offset: 2px;
2870
+ }
2871
+
2872
+ /** Cells */
2873
+
2874
+ :where(.tabela__cell),
2875
+ :where(.tabela__heading) {
2876
+ padding: 0.5em;
2877
+ border-color: gray;
2878
+ border-style: solid;
2879
+ border-width: 0 1px 1px 0;
2880
+ line-height: 1;
2881
+ }
2882
+
2883
+ :where(.tabela__row .tabela__cell:last-child),
2884
+ :where(.tabela__row .tabela__heading:last-child) {
2885
+ flex: 1;
2886
+ border-right-width: 0;
2887
+ }
2888
+
2889
+ :where(.tabela__cell) {
2890
+ overflow: hidden;
2891
+ text-overflow: ellipsis;
2892
+ white-space: nowrap;
2893
+ }
2894
+
2895
+ :where(.tabela__cell--footer) {
2896
+ border-top-width: 1px;
2897
+ border-bottom-width: 0;
2898
+ }
2899
+
2900
+ :where(.tabela__cell--group) {
2901
+ padding: 0;
2902
+ display: flex;
2903
+ flex-flow: row nowrap;
2904
+ align-items: center;
2905
+ gap: 0.5em;
2906
+ }
2907
+
2908
+ :where(.tabela__cell--group .tabela__button) {
2909
+ margin: 0 0 0 .25rem;
2910
+ }
2911
+
2912
+ /** Misc. */
2913
+
2914
+ :where(.tabela__button) {
2915
+ font-size: .75rem;
2916
+ font-weight: bold;
2917
+ }
2918
+
2919
+ :where(.tabela__selection) {
2920
+ background-color: color-mix(in oklch, var(--oui-blue-6), transparent);
2921
+ border: 1px solid var(--oui-blue-6);
2922
+ border-radius: .25rem;
2923
+ position: fixed;
2924
+ z-index: 1000;
2925
+ }
2926
+ `.replace(/^\s+|\s+|\s+$/g, " ");
2927
+ let appended = false;
2928
+ //#endregion
2929
+ //#region src/tabela.ts
2668
2930
  var Tabela = class {
2669
- #components = {
2670
- header: void 0,
2671
- body: void 0,
2672
- footer: void 0
2673
- };
2931
+ #components;
2674
2932
  #element;
2675
2933
  #id = getId();
2934
+ #table;
2676
2935
  #key;
2677
2936
  #managers = {
2678
2937
  column: void 0,
2679
2938
  data: void 0,
2680
2939
  event: void 0,
2681
2940
  filter: void 0,
2941
+ group: void 0,
2682
2942
  navigation: void 0,
2683
2943
  render: void 0,
2684
2944
  row: void 0,
2685
2945
  selection: void 0,
2686
- sort: void 0
2946
+ sort: void 0,
2947
+ style: void 0
2687
2948
  };
2949
+ #state;
2688
2950
  data;
2689
2951
  filter;
2952
+ group;
2690
2953
  selection;
2691
2954
  sort;
2692
2955
  get key() {
@@ -2695,34 +2958,42 @@ var Tabela = class {
2695
2958
  constructor(element, options) {
2696
2959
  this.#element = element;
2697
2960
  element.innerHTML = "";
2698
- element.role = "table";
2699
- element.classList.add("tabela");
2700
- element.setAttribute("aria-label", options.label);
2961
+ element.classList.add(CSS_TABELA);
2962
+ this.#table = createElement("div", {
2963
+ className: CSS_TABELA_TABLE,
2964
+ role: "table"
2965
+ }, { "aria-label": options.label });
2701
2966
  this.#key = options.key;
2702
- this.#components.header = new HeaderComponent();
2703
- this.#components.body = new BodyComponent();
2704
- this.#components.footer = new FooterComponent();
2705
- const state = {
2706
- element,
2967
+ this.#components = {
2968
+ body: new BodyComponent(),
2969
+ footer: new FooterComponent(),
2970
+ header: new HeaderComponent()
2971
+ };
2972
+ this.#state = {
2707
2973
  options,
2708
2974
  components: this.#components,
2975
+ element: this.#table,
2709
2976
  id: this.#id,
2710
2977
  key: this.#key,
2711
2978
  managers: this.#managers
2712
2979
  };
2713
- this.#managers.column = new ColumnManager(state);
2714
- this.#managers.data = new DataManager(state);
2715
- this.#managers.event = new EventManager(state);
2716
- this.#managers.filter = new FilterManager(state);
2717
- this.#managers.navigation = new NavigationManager(state);
2718
- this.#managers.render = new RenderManager(state);
2719
- this.#managers.row = new RowManager(state);
2720
- this.#managers.selection = new SelectionManager(state);
2721
- this.#managers.sort = new SortManager(state);
2722
- element.append(this.#components.header.elements.group, this.#components.body.elements.group, this.#components.footer.elements.group);
2980
+ this.#managers.column = new ColumnManager(this.#state);
2981
+ this.#managers.data = new DataManager(this.#state);
2982
+ this.#managers.event = new EventManager(this.#state);
2983
+ this.#managers.filter = new FilterManager(this.#state);
2984
+ this.#managers.group = new GroupManager(this.#state);
2985
+ this.#managers.navigation = new NavigationManager(this.#state);
2986
+ this.#managers.render = new RenderManager(this.#state);
2987
+ this.#managers.row = new RowManager(this.#state);
2988
+ this.#managers.selection = new SelectionManager(this.#state);
2989
+ this.#managers.sort = new SortManager(this.#state);
2990
+ this.#managers.style = new StyleManager(this.#state);
2991
+ this.#table.append(this.#components.header.elements.group, this.#components.body.elements.group, this.#components.footer.elements.group);
2992
+ element.append(this.#table);
2723
2993
  this.#managers.data.set(options.data);
2724
2994
  this.data = this.#managers.data.handlers;
2725
2995
  this.filter = this.#managers.filter.handlers;
2996
+ this.group = this.#managers.group.handlers;
2726
2997
  this.selection = this.#managers.selection.handlers;
2727
2998
  this.sort = this.#managers.sort.handlers;
2728
2999
  }
@@ -2730,6 +3001,7 @@ var Tabela = class {
2730
3001
  const components = this.#components;
2731
3002
  const managers = this.#managers;
2732
3003
  const element = this.#element;
3004
+ const table = this.#table;
2733
3005
  components.body.destroy();
2734
3006
  components.footer.destroy();
2735
3007
  components.header.destroy();
@@ -2737,16 +3009,24 @@ var Tabela = class {
2737
3009
  managers.data.destroy();
2738
3010
  managers.event.destroy();
2739
3011
  managers.filter.destroy();
3012
+ managers.group.destroy();
3013
+ managers.navigation.destroy();
2740
3014
  managers.render.destroy();
2741
3015
  managers.row.destroy();
2742
3016
  managers.selection.destroy();
2743
3017
  managers.sort.destroy();
2744
3018
  element.innerHTML = "";
2745
- element.role = "";
2746
- element.classList.remove("tabela");
2747
- element.removeAttribute("aria-label");
2748
- element.removeAttribute("role");
3019
+ table.innerHTML = "";
3020
+ table.role = "";
3021
+ element.classList.remove(CSS_TABELA);
3022
+ table.removeAttribute("aria-label");
3023
+ table.removeAttribute("role");
3024
+ this.#state.components = void 0;
3025
+ this.#state.managers = void 0;
3026
+ this.#state.element = void 0;
3027
+ this.#state.options = void 0;
2749
3028
  this.#element = void 0;
3029
+ this.#table = void 0;
2750
3030
  }
2751
3031
  };
2752
3032
  function getId() {
@@ -2754,7 +3034,10 @@ function getId() {
2754
3034
  return id;
2755
3035
  }
2756
3036
  let id = 0;
3037
+ //#endregion
3038
+ //#region src/index.ts
2757
3039
  function tabela(element, options) {
2758
3040
  return new Tabela(element, options);
2759
3041
  }
3042
+ //#endregion
2760
3043
  export { tabela };