@oscarpalmer/tabela 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/components/body.component.d.mts +11 -0
  2. package/dist/components/body.component.mjs +28 -0
  3. package/dist/components/column.component.d.mts +16 -0
  4. package/dist/components/column.component.mjs +46 -0
  5. package/dist/components/footer.component.d.mts +13 -0
  6. package/dist/components/{footer.component.js → footer.component.mjs} +9 -6
  7. package/dist/components/group.component.d.mts +20 -0
  8. package/dist/components/group.component.mjs +57 -0
  9. package/dist/components/header.component.d.mts +13 -0
  10. package/dist/components/header.component.mjs +25 -0
  11. package/dist/components/row.component.d.mts +15 -0
  12. package/dist/components/row.component.mjs +56 -0
  13. package/dist/helpers/dom.helpers.d.mts +12 -0
  14. package/dist/helpers/dom.helpers.mjs +43 -0
  15. package/dist/helpers/misc.helpers.d.mts +12 -0
  16. package/dist/helpers/misc.helpers.mjs +20 -0
  17. package/dist/helpers/style.helper.d.mts +6 -0
  18. package/dist/helpers/style.helper.mjs +8 -0
  19. package/dist/index.d.mts +7 -0
  20. package/dist/{index.js → index.mjs} +3 -1
  21. package/dist/managers/column.manager.d.mts +17 -0
  22. package/dist/managers/{column.manager.js → column.manager.mjs} +11 -6
  23. package/dist/managers/data.manager.d.mts +27 -0
  24. package/dist/managers/data.manager.mjs +256 -0
  25. package/dist/managers/event.manager.d.mts +18 -0
  26. package/dist/managers/event.manager.mjs +79 -0
  27. package/dist/managers/filter.manager.d.mts +18 -0
  28. package/dist/managers/filter.manager.mjs +115 -0
  29. package/dist/managers/group.manager.d.mts +27 -0
  30. package/dist/managers/group.manager.mjs +93 -0
  31. package/dist/managers/navigation.manager.d.mts +15 -0
  32. package/dist/managers/navigation.manager.mjs +80 -0
  33. package/dist/managers/render.manager.d.mts +19 -0
  34. package/dist/managers/render.manager.mjs +157 -0
  35. package/dist/managers/row.manager.d.mts +19 -0
  36. package/dist/managers/row.manager.mjs +45 -0
  37. package/dist/managers/selection.manager.d.mts +23 -0
  38. package/dist/managers/{selection.manager.js → selection.manager.mjs} +38 -31
  39. package/dist/managers/sort.manager.d.mts +23 -0
  40. package/dist/managers/sort.manager.mjs +147 -0
  41. package/dist/managers/style.manager.d.mts +9 -0
  42. package/dist/managers/style.manager.mjs +181 -0
  43. package/dist/models/body.model.d.mts +7 -0
  44. package/dist/models/body.model.mjs +1 -0
  45. package/dist/models/column.model.d.mts +13 -0
  46. package/dist/models/column.model.mjs +1 -0
  47. package/dist/models/data.model.d.mts +28 -0
  48. package/dist/models/data.model.mjs +1 -0
  49. package/dist/models/dom.model.d.mts +19 -0
  50. package/dist/models/dom.model.mjs +19 -0
  51. package/dist/models/event.model.d.mts +99 -0
  52. package/dist/models/event.model.mjs +53 -0
  53. package/dist/models/filter.model.d.mts +26 -0
  54. package/dist/models/filter.model.mjs +13 -0
  55. package/dist/models/footer.model.d.mts +8 -0
  56. package/dist/models/footer.model.mjs +1 -0
  57. package/dist/models/group.model.d.mts +19 -0
  58. package/dist/models/group.model.mjs +5 -0
  59. package/dist/models/header.model.d.mts +7 -0
  60. package/dist/models/header.model.mjs +1 -0
  61. package/dist/models/render.model.d.mts +22 -0
  62. package/dist/models/render.model.mjs +1 -0
  63. package/dist/models/selection.model.d.mts +12 -0
  64. package/dist/models/selection.model.mjs +1 -0
  65. package/dist/models/sort.model.d.mts +19 -0
  66. package/dist/models/sort.model.mjs +5 -0
  67. package/dist/models/style.model.d.mts +29 -0
  68. package/dist/models/style.model.mjs +29 -0
  69. package/dist/models/tabela.model.d.mts +46 -0
  70. package/dist/models/tabela.model.mjs +1 -0
  71. package/dist/models/tabela.options.d.mts +14 -0
  72. package/dist/models/tabela.options.mjs +1 -0
  73. package/dist/tabela.d.mts +22 -0
  74. package/dist/{tabela.full.js → tabela.full.mjs} +1501 -803
  75. package/dist/tabela.mjs +126 -0
  76. package/package.json +2 -4
  77. package/src/components/column.component.ts +4 -4
  78. package/src/components/group.component.ts +6 -2
  79. package/src/components/row.component.ts +5 -5
  80. package/src/helpers/misc.helpers.ts +13 -1
  81. package/src/managers/column.manager.ts +9 -9
  82. package/src/managers/data.manager.ts +139 -53
  83. package/src/managers/event.manager.ts +52 -6
  84. package/src/managers/filter.manager.ts +36 -20
  85. package/src/managers/group.manager.ts +43 -10
  86. package/src/managers/render.manager.ts +30 -17
  87. package/src/managers/sort.manager.ts +81 -52
  88. package/src/managers/style.manager.ts +33 -0
  89. package/src/models/column.model.ts +2 -2
  90. package/src/models/data.model.ts +6 -6
  91. package/src/models/dom.model.ts +0 -2
  92. package/src/models/event.model.ts +168 -0
  93. package/src/models/filter.model.ts +2 -2
  94. package/src/models/group.model.ts +9 -0
  95. package/src/models/render.model.ts +6 -0
  96. package/src/models/sort.model.ts +7 -5
  97. package/src/tabela.ts +6 -2
  98. package/dist/components/body.component.js +0 -23
  99. package/dist/components/column.component.js +0 -41
  100. package/dist/components/group.component.js +0 -28
  101. package/dist/components/header.component.js +0 -22
  102. package/dist/components/row.component.js +0 -48
  103. package/dist/helpers/dom.helpers.js +0 -38
  104. package/dist/helpers/misc.helpers.js +0 -7
  105. package/dist/helpers/style.helper.js +0 -6
  106. package/dist/managers/data.manager.js +0 -181
  107. package/dist/managers/event.manager.js +0 -53
  108. package/dist/managers/filter.manager.js +0 -98
  109. package/dist/managers/group.manager.js +0 -46
  110. package/dist/managers/navigation.manager.js +0 -73
  111. package/dist/managers/render.manager.js +0 -135
  112. package/dist/managers/row.manager.js +0 -38
  113. package/dist/managers/sort.manager.js +0 -122
  114. package/dist/models/body.model.js +0 -0
  115. package/dist/models/column.model.js +0 -0
  116. package/dist/models/data.model.js +0 -0
  117. package/dist/models/filter.model.js +0 -0
  118. package/dist/models/footer.model.js +0 -0
  119. package/dist/models/group.model.js +0 -0
  120. package/dist/models/header.model.js +0 -0
  121. package/dist/models/render.model.js +0 -0
  122. package/dist/models/selection.model.js +0 -0
  123. package/dist/models/sort.model.js +0 -0
  124. package/dist/models/tabela.model.js +0 -0
  125. package/dist/models/tabela.options.js +0 -0
  126. package/dist/tabela.js +0 -105
@@ -1,3 +1,50 @@
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/toretto/node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
27
+ /**
28
+ * Is the value a number?
29
+ * @param value Value to check
30
+ * @returns `true` if the value is a `number`, otherwise `false`
31
+ */
32
+ function isNumber$1(value) {
33
+ return typeof value === "number" && !Number.isNaN(value);
34
+ }
35
+ /**
36
+ * Is the value a plain object?
37
+ * @param value Value to check
38
+ * @returns `true` if the value is a plain object, otherwise `false`
39
+ */
40
+ function isPlainObject$1(value) {
41
+ if (value === null || typeof value !== "object") return false;
42
+ if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
43
+ const prototype = Object.getPrototypeOf(value);
44
+ return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
45
+ }
46
+ //#endregion
47
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/array/compact.mjs
1
48
  function compact$1(array, strict) {
2
49
  if (!Array.isArray(array)) return [];
3
50
  if (strict === true) return array.filter(Boolean);
@@ -9,6 +56,8 @@ function compact$1(array, strict) {
9
56
  }
10
57
  return compacted;
11
58
  }
59
+ //#endregion
60
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
12
61
  /**
13
62
  * Get the string value from any value
14
63
  * @param value Original value
@@ -39,26 +88,107 @@ function join$1(value, delimiter) {
39
88
  function words$1(value) {
40
89
  return typeof value === "string" ? value.match(EXPRESSION_WORDS$1) ?? [] : [];
41
90
  }
42
- var EXPRESSION_WORDS$1 = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
91
+ const EXPRESSION_WORDS$1 = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
92
+ //#endregion
93
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/is.mjs
43
94
  /**
44
- * Is the value a number?
95
+ * Is the value `undefined`, `null`, or a whitespace-only string?
45
96
  * @param value Value to check
46
- * @returns `true` if the value is a `number`, otherwise `false`
97
+ * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
47
98
  */
48
- function isNumber$1(value) {
49
- return typeof value === "number" && !Number.isNaN(value);
99
+ function isNullableOrWhitespace$1(value) {
100
+ return value == null || EXPRESSION_WHITESPACE$1.test(getString$1(value));
101
+ }
102
+ const EXPRESSION_WHITESPACE$1 = /^\s*$/;
103
+ //#endregion
104
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/element-value.mjs
105
+ function setElementValue(element, first, second, third, callback) {
106
+ if (!isHTMLOrSVGElement(element)) return;
107
+ if (typeof first === "string") setElementValues(element, first, second, third, callback);
108
+ else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback);
109
+ }
110
+ function setElementValues(element, first, second, third, callback) {
111
+ if (!isHTMLOrSVGElement(element)) return;
112
+ if (typeof first === "string") {
113
+ callback(element, first, second, third);
114
+ return;
115
+ }
116
+ const isArray = Array.isArray(first);
117
+ if (!isArray && !(typeof first === "object" && first !== null)) return;
118
+ const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
119
+ name,
120
+ value
121
+ }));
122
+ const { length } = entries;
123
+ for (let index = 0; index < length; index += 1) {
124
+ const entry = entries[index];
125
+ if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value, third);
126
+ }
127
+ }
128
+ function updateElementValue(element, key, value, set, remove, isBoolean, json) {
129
+ if (isBoolean ? value == null : isNullableOrWhitespace$1(value)) remove.call(element, key);
130
+ else set.call(element, key, json ? JSON.stringify(value) : String(value));
131
+ }
132
+ //#endregion
133
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/attribute.mjs
134
+ function isAttribute(value) {
135
+ return value instanceof Attr || isPlainObject$1(value) && typeof value.name === "string" && "value" in value;
136
+ }
137
+ function updateAttribute(element, name, value, dispatch) {
138
+ const normalizedName = name.toLowerCase();
139
+ const isBoolean = booleanAttributesSet.has(normalizedName);
140
+ const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === normalizedName) : value == null ? "" : value;
141
+ if (name in element) updateProperty(element, normalizedName, next, dispatch);
142
+ updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
143
+ }
144
+ function updateProperty(element, name, value, dispatch) {
145
+ if (Object.is(element[name], value)) return;
146
+ element[name] = value;
147
+ const event = dispatch !== false && elementEvents[element.tagName]?.[name];
148
+ if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
50
149
  }
51
150
  /**
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`
151
+ * List of boolean attributes
55
152
  */
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
- }
153
+ const booleanAttributes = Object.freeze([
154
+ "async",
155
+ "autofocus",
156
+ "autoplay",
157
+ "checked",
158
+ "controls",
159
+ "default",
160
+ "defer",
161
+ "disabled",
162
+ "formnovalidate",
163
+ "hidden",
164
+ "inert",
165
+ "ismap",
166
+ "itemscope",
167
+ "loop",
168
+ "multiple",
169
+ "muted",
170
+ "nomodule",
171
+ "novalidate",
172
+ "open",
173
+ "playsinline",
174
+ "readonly",
175
+ "required",
176
+ "reversed",
177
+ "selected"
178
+ ]);
179
+ const booleanAttributesSet = new Set(booleanAttributes);
180
+ const elementEvents = {
181
+ DETAILS: { open: "toggle" },
182
+ INPUT: {
183
+ checked: "change",
184
+ value: "input"
185
+ },
186
+ SELECT: { value: "change" },
187
+ TEXTAREA: { value: "input" }
188
+ };
189
+ document.createElement("form");
190
+ //#endregion
191
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/number.mjs
62
192
  /**
63
193
  * Clamp a number between a minimum and maximum value
64
194
  * @param value Value to clamp
@@ -76,14 +206,18 @@ function clamp$1(value, minimum, maximum, loop) {
76
206
  if (value < minimum) return loop === true ? maximum : minimum;
77
207
  return value > maximum ? loop === true ? minimum : maximum : value;
78
208
  }
209
+ //#endregion
210
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/sized.mjs
79
211
  function getSizedMaximum$1(first, second) {
80
212
  let actual;
81
213
  if (typeof first === "number") actual = first;
82
214
  else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT$1;
83
215
  return clamp$1(actual, 1, MAXIMUM_ABSOLUTE$1);
84
216
  }
85
- var MAXIMUM_ABSOLUTE$1 = 16777216;
86
- var MAXIMUM_DEFAULT$1 = 1048576;
217
+ const MAXIMUM_ABSOLUTE$1 = 16777216;
218
+ const MAXIMUM_DEFAULT$1 = 1048576;
219
+ //#endregion
220
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/sized/map.mjs
87
221
  /**
88
222
  * A Map with a maximum size
89
223
  *
@@ -130,6 +264,8 @@ var SizedMap$1 = class extends Map {
130
264
  return super.set(key, value);
131
265
  }
132
266
  };
267
+ //#endregion
268
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/function/memoize.mjs
133
269
  var Memoized$1 = class {
134
270
  #state;
135
271
  /**
@@ -147,7 +283,7 @@ var Memoized$1 = class {
147
283
  constructor(callback, options) {
148
284
  const cache = new SizedMap$1(options.cacheSize);
149
285
  const getter = (...parameters) => {
150
- const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join$1(parameters.map(getString$1), "_"));
286
+ const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join$1(parameters.map(getString$1), SEPARATOR$1));
151
287
  if (cache.has(key)) return cache.get(key);
152
288
  const value = callback(...parameters);
153
289
  cache.set(key, value);
@@ -222,14 +358,17 @@ function getMemoizationOptions$1(input) {
222
358
  function memoize$1(callback, options) {
223
359
  return new Memoized$1(callback, getMemoizationOptions$1(options));
224
360
  }
225
- var DEFAULT_CACHE_SIZE$1 = 1024;
361
+ const DEFAULT_CACHE_SIZE$1 = 1024;
362
+ const SEPARATOR$1 = "_";
363
+ //#endregion
364
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/string/case.mjs
226
365
  /**
227
366
  * Convert a string to camel case _(thisIsCamelCase)_
228
367
  * @param value String to convert
229
368
  * @returns Camel-cased string
230
369
  */
231
370
  function camelCase(value) {
232
- return toCase("camel", value, true, false);
371
+ return toCase(CASE_CAMEL, value, true, false);
233
372
  }
234
373
  /**
235
374
  * Capitalize the first letter of a string _(and lowercase the rest)_
@@ -257,7 +396,7 @@ function toCaseCallback(value) {
257
396
  const partsLength = parts.length;
258
397
  const cased = [];
259
398
  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("-");
399
+ 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
400
  const itemsLength = items.length;
262
401
  const partResult = [];
263
402
  let itemCount = 0;
@@ -272,17 +411,27 @@ function toCaseCallback(value) {
272
411
  }
273
412
  return join$1(cased, delimiters[type]);
274
413
  }
275
- var caseMemoizers = {};
276
- var delimiters = {
277
- camel: "",
278
- kebab: "-",
279
- pascal: "",
280
- snake: "_"
414
+ const CASE_CAMEL = "camel";
415
+ const CASE_KEBAB = "kebab";
416
+ const CASE_PASCAL = "pascal";
417
+ const CASE_SNAKE = "snake";
418
+ const DELIMTER_EMPTY = "";
419
+ const DELIMITER_HYPHEN = "-";
420
+ const DELIMITER_UNDERSCORE = "_";
421
+ const EXPRESSION_CAMEL_CASE = /(\p{Ll})(\p{Lu})/gu;
422
+ const EXPRESSION_ACRONYM = /(\p{Lu}*)(\p{Lu})(\p{Ll}+)/gu;
423
+ const REPLACEMENT_CAMEL_CASE = "$1-$2";
424
+ const S = "s";
425
+ const caseMemoizers = {};
426
+ const delimiters = {
427
+ [CASE_CAMEL]: DELIMTER_EMPTY,
428
+ [CASE_KEBAB]: DELIMITER_HYPHEN,
429
+ [CASE_PASCAL]: DELIMTER_EMPTY,
430
+ [CASE_SNAKE]: DELIMITER_UNDERSCORE
281
431
  };
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;
432
+ let memoizedCapitalize;
433
+ //#endregion
434
+ //#region node_modules/@oscarpalmer/toretto/dist/internal/get-value.mjs
286
435
  function getBoolean(value, defaultValue) {
287
436
  return typeof value === "boolean" ? value : defaultValue ?? false;
288
437
  }
@@ -290,127 +439,16 @@ function getStyleValue(element, property, computed) {
290
439
  const name = camelCase(property);
291
440
  return computed ? getComputedStyle(element)[name] : element.style[name];
292
441
  }
293
- /**
294
- * Is the value an event target?
295
- * @param value Value to check
296
- * @returns `true` if it's an event target, otherwise `false`
297
- */
298
- function isEventTarget(value) {
299
- return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
300
- }
301
- /**
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`
305
- */
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$1.test(getString$1(value));
323
- }
324
- var EXPRESSION_WHITESPACE$1 = /^\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 isAttribute(value) {
353
- return value instanceof Attr || isPlainObject$1(value) && typeof value.name === "string" && "value" in value;
354
- }
355
- function updateAttribute(element, name, value, dispatch) {
356
- const normalizedName = name.toLowerCase();
357
- const isBoolean = booleanAttributesSet.has(normalizedName);
358
- const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === normalizedName) : value == null ? "" : value;
359
- if (name in element) updateProperty(element, normalizedName, next, dispatch);
360
- updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
361
- }
362
- function updateProperty(element, name, value, dispatch) {
363
- if (Object.is(element[name], value)) return;
364
- element[name] = value;
365
- const event = dispatch !== false && elementEvents[element.tagName]?.[name];
366
- if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
367
- }
368
- /**
369
- * List of boolean attributes
370
- */
371
- const booleanAttributes = Object.freeze([
372
- "async",
373
- "autofocus",
374
- "autoplay",
375
- "checked",
376
- "controls",
377
- "default",
378
- "defer",
379
- "disabled",
380
- "formnovalidate",
381
- "hidden",
382
- "inert",
383
- "ismap",
384
- "itemscope",
385
- "loop",
386
- "multiple",
387
- "muted",
388
- "nomodule",
389
- "novalidate",
390
- "open",
391
- "playsinline",
392
- "readonly",
393
- "required",
394
- "reversed",
395
- "selected"
396
- ]);
397
- var booleanAttributesSet = new Set(booleanAttributes);
398
- var elementEvents = {
399
- DETAILS: { open: "toggle" },
400
- INPUT: {
401
- checked: "change",
402
- value: "input"
403
- },
404
- SELECT: { value: "change" },
405
- TEXTAREA: { value: "input" }
406
- };
407
- document.createElement("form");
442
+ //#endregion
443
+ //#region node_modules/@oscarpalmer/toretto/dist/attribute/set.mjs
408
444
  function setAttribute(element, first, second, third) {
409
445
  setElementValue(element, first, second, third, updateAttribute);
410
446
  }
411
447
  function setAttributes(element, attributes, dispatch) {
412
448
  setElementValues(element, attributes, null, dispatch, updateAttribute);
413
449
  }
450
+ //#endregion
451
+ //#region node_modules/@oscarpalmer/toretto/dist/style.mjs
414
452
  /**
415
453
  * Get styles from an element
416
454
  * @param element Element to get the styles from
@@ -475,12 +513,57 @@ function updateStyleProperty(element, key, value) {
475
513
  this.style[property] = "";
476
514
  }, false, false);
477
515
  }
516
+ //#endregion
517
+ //#region src/models/dom.model.ts
518
+ const ARIA_ACTIVEDESCENDANT = "aria-activedescendant";
519
+ const ARIA_LABEL = "aria-label";
520
+ const ARIA_SELECTED = "aria-selected";
521
+ const ARIA_SORT = "aria-sort";
522
+ const ATTRIBUTE_DATA_ACTIVE = "data-active";
523
+ const ATTRIBUTE_DATA_EVENT = "data-event";
524
+ const ATTRIBUTE_DATA_KEY = "data-key";
525
+ const ATTRIBUTE_DATA_SORT_DIRECTION = "data-sort-direction";
526
+ const ATTRIBUTE_DATA_SORT_POSITION = "data-sort-position";
527
+ const ATTRIBUTE_ROLE = "role";
528
+ const ROLE_CELL = "cell";
529
+ const ROLE_COLUMNHEADER = "columnheader";
530
+ const ROLE_ROWGROUP = "rowgroup";
531
+ const ROLE_TABLE = "table";
532
+ //#endregion
533
+ //#region src/models/style.model.ts
534
+ const CSS_BUTTON = "tabela__button";
535
+ const CSS_BUTTON_GROUP = "tabela__button--group";
536
+ const CSS_CELL = "tabela__cell";
537
+ const CSS_CELL_BODY = "tabela__cell--body";
538
+ const CSS_CELL_FOOTER = "tabela__cell--footer";
539
+ const CSS_CELL_GROUP = "tabela__cell--group";
540
+ const CSS_FAKER = "tabela__faker";
541
+ const CSS_GROUP_SELECTED = "tabela__group__selected";
542
+ const CSS_GROUP_TOTAL = "tabela__group__total";
543
+ const CSS_HEADING = "tabela__heading";
544
+ const CSS_HEADING_CONTENT = "tabela__heading__content";
545
+ const CSS_HEADING_SORTER = "tabela__heading__sorter";
546
+ const CSS_ROW = "tabela__row";
547
+ const CSS_ROW_BODY = "tabela__row--body";
548
+ const CSS_ROW_FOOTER = "tabela__row--footer";
549
+ const CSS_ROW_GROUP = "tabela__row--group tabela__group";
550
+ const CSS_ROW_HEADER = "tabela__row--header";
551
+ const CSS_ROW_SELECTED = "tabela__row--selected";
552
+ const CSS_ROWGROUP = "tabela__rowgroup";
553
+ const CSS_ROWGROUP_BODY = "tabela__rowgroup--body";
554
+ const CSS_ROWGROUP_FOOTER = "tabela__rowgroup--footer";
555
+ const CSS_ROWGROUP_HEADER = "tabela__rowgroup--header";
556
+ const CSS_SELECTION = "tabela__selection";
557
+ const CSS_TABLE = "tabela__table";
558
+ const CSS_WRAPPER = "tabela";
559
+ //#endregion
560
+ //#region src/helpers/dom.helpers.ts
478
561
  function createCell(width, body) {
479
562
  const cell = createElement("div", {
480
- className: "tabela__cell",
481
- role: "cell"
563
+ className: CSS_CELL,
564
+ role: ROLE_CELL
482
565
  }, {}, { width: `${width}px` });
483
- if (body ?? true) cell.classList.add("tabela__cell--body");
566
+ if (body ?? true) cell.classList.add(CSS_CELL_BODY);
484
567
  return cell;
485
568
  }
486
569
  function createElement(tagName, properties, attributes, style) {
@@ -492,39 +575,92 @@ function createElement(tagName, properties, attributes, style) {
492
575
  setStyles(element, style ?? {});
493
576
  return element;
494
577
  }
495
- function createRowGroup(withRow) {
578
+ function createRowGroup(height, withRow) {
496
579
  const group = createElement("div", {
497
- className: "tabela__rowgroup",
498
- role: "rowgroup"
499
- }, {}, {});
580
+ className: CSS_ROWGROUP,
581
+ role: ROLE_ROWGROUP
582
+ });
500
583
  if (!(withRow ?? true)) return group;
501
- const row = createRow();
584
+ const row = createRow(height);
502
585
  group.append(row);
503
586
  return {
504
587
  group,
505
588
  row
506
589
  };
507
590
  }
508
- function createRow() {
591
+ function createRow(height) {
509
592
  return createElement("div", {
510
- className: "tabela__row",
593
+ className: CSS_ROW,
511
594
  role: "row"
512
- }, {}, { height: "32px" });
513
- }
595
+ }, {}, { height: `${height}px` });
596
+ }
597
+ //#endregion
598
+ //#region src/models/event.model.ts
599
+ const EVENT_BODY = "body";
600
+ const EVENT_DATA_ADD = "data:add";
601
+ const EVENT_DATA_CLEAR = "data:clear";
602
+ const EVENT_DATA_FILTERED = "data:filtered";
603
+ const EVENT_DATA_REMOVE = "data:remove";
604
+ const EVENT_DATA_SORTED = "data:sorted";
605
+ const EVENT_DATA_SYNCHRONIZE = "data:synchronize";
606
+ const EVENT_DATA_UPDATE = "data:update";
607
+ const EVENT_GROUP = "group";
608
+ const EVENT_GROUP_ADD = "group:add";
609
+ const EVENT_GROUP_CLEAR = "group:clear";
610
+ const EVENT_GROUP_REMOVE = "group:remove";
611
+ const EVENT_GROUP_TOGGLE = "group:toggle";
612
+ const EVENT_GROUP_UPDATE = "group:update";
613
+ const EVENT_HEADING = "heading";
614
+ const EVENT_SORT_ADD = "sort:add";
615
+ const EVENT_SORT_CLEAR = "sort:clear";
616
+ const EVENT_SORT_FLIP = "sort:flip";
617
+ const EVENT_SORT_REMOVE = "sort:remove";
618
+ const EVENT_SORT_SET = "sort:set";
619
+ const EVENTS_NAMES = new Set([
620
+ EVENT_DATA_ADD,
621
+ EVENT_DATA_CLEAR,
622
+ EVENT_DATA_FILTERED,
623
+ EVENT_DATA_REMOVE,
624
+ EVENT_DATA_SORTED,
625
+ EVENT_DATA_SYNCHRONIZE,
626
+ EVENT_DATA_UPDATE,
627
+ "filter:add",
628
+ "filter:clear",
629
+ "filter:remove",
630
+ EVENT_GROUP_ADD,
631
+ EVENT_GROUP_CLEAR,
632
+ EVENT_GROUP_REMOVE,
633
+ EVENT_GROUP_TOGGLE,
634
+ EVENT_GROUP_UPDATE,
635
+ "navigation:active",
636
+ "render:begin",
637
+ "render:end",
638
+ "selection:add",
639
+ "selection:clear",
640
+ "selection:remove",
641
+ "selection:toggle",
642
+ EVENT_SORT_ADD,
643
+ EVENT_SORT_CLEAR,
644
+ EVENT_SORT_FLIP,
645
+ EVENT_SORT_REMOVE,
646
+ EVENT_SORT_SET
647
+ ]);
648
+ //#endregion
649
+ //#region src/components/body.component.ts
514
650
  function createFaker() {
515
- return createElement("div", { className: "tabela__faker" }, {}, {});
651
+ return createElement("div", { className: CSS_FAKER });
516
652
  }
517
653
  var BodyComponent = class {
518
654
  elements = {
519
655
  faker: createFaker(),
520
656
  group: void 0
521
657
  };
522
- constructor() {
523
- const group = createRowGroup(false);
658
+ constructor(state) {
659
+ const group = createRowGroup(state.options.rowHeight, false);
524
660
  this.elements.group = group;
525
- group.className += " tabela__rowgroup--body";
661
+ group.className += ` ${CSS_ROWGROUP_BODY}`;
526
662
  group.tabIndex = 0;
527
- group.setAttribute("data-event", "body");
663
+ group.setAttribute(ATTRIBUTE_DATA_EVENT, EVENT_BODY);
528
664
  group.append(this.elements.faker);
529
665
  }
530
666
  destroy() {
@@ -532,17 +668,19 @@ var BodyComponent = class {
532
668
  this.elements.group = void 0;
533
669
  }
534
670
  };
671
+ //#endregion
672
+ //#region src/components/footer.component.ts
535
673
  var FooterComponent = class {
536
674
  elements;
537
- constructor() {
538
- const { group, row } = createRowGroup();
675
+ constructor(state) {
676
+ const { group, row } = createRowGroup(state.options.rowHeight);
539
677
  this.elements = {
540
678
  group,
541
679
  row,
542
680
  cells: []
543
681
  };
544
- group.className += " tabela__rowgroup--footer";
545
- row.className += " tabela__row--footer";
682
+ group.className += ` ${CSS_ROWGROUP_FOOTER}`;
683
+ row.className += ` ${CSS_ROW_FOOTER}`;
546
684
  }
547
685
  destroy() {
548
686
  this.elements.cells.length = 0;
@@ -556,23 +694,25 @@ var FooterComponent = class {
556
694
  elements.row.innerHTML = "";
557
695
  for (let index = 0; index < length; index += 1) {
558
696
  const cell = createCell(columns[index].options.width ?? 4, false);
559
- cell.className += " tabela__cell--footer";
697
+ cell.className += ` ${CSS_CELL_FOOTER}`;
560
698
  cell.innerHTML = "&nbsp;";
561
699
  elements.cells.push(cell);
562
700
  elements.row.append(cell);
563
701
  }
564
702
  }
565
703
  };
704
+ //#endregion
705
+ //#region src/components/header.component.ts
566
706
  var HeaderComponent = class {
567
707
  elements;
568
- constructor() {
569
- const { group, row } = createRowGroup();
708
+ constructor(state) {
709
+ const { group, row } = createRowGroup(state.options.rowHeight);
570
710
  this.elements = {
571
711
  group,
572
712
  row
573
713
  };
574
- group.className += " tabela__rowgroup--header";
575
- row.className += " tabela__row--header";
714
+ group.className += ` ${CSS_ROWGROUP_HEADER}`;
715
+ row.className += ` ${CSS_ROW_HEADER}`;
576
716
  }
577
717
  destroy() {
578
718
  this.elements.group = void 0;
@@ -583,16 +723,18 @@ var HeaderComponent = class {
583
723
  this.elements.row.append(...columns.map((column) => column.elements.wrapper));
584
724
  }
585
725
  };
726
+ //#endregion
727
+ //#region src/components/column.component.ts
586
728
  var ColumnComponent = class {
587
729
  elements;
588
730
  options;
589
731
  constructor(column) {
590
- const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (column.width ?? column.title.length * 1.5);
732
+ const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (column.width ?? column.label.length * 1.5);
591
733
  this.options = {
592
734
  ...column,
593
735
  width
594
736
  };
595
- this.elements = createHeading(this.options.field, this.options.title, width);
737
+ this.elements = createHeading(this.options.key, this.options.label, width);
596
738
  }
597
739
  destroy() {
598
740
  this.elements.content.remove();
@@ -602,19 +744,19 @@ var ColumnComponent = class {
602
744
  this.options = void 0;
603
745
  }
604
746
  };
605
- function createHeading(field, title, width) {
747
+ function createHeading(key, title, width) {
606
748
  const wrapper = createElement("div", {
607
- className: "tabela__heading",
608
- role: "columnheader"
749
+ className: CSS_HEADING,
750
+ [ATTRIBUTE_ROLE]: ROLE_COLUMNHEADER
609
751
  }, {
610
- "data-event": "heading",
611
- "data-field": field
752
+ [ATTRIBUTE_DATA_EVENT]: EVENT_HEADING,
753
+ [ATTRIBUTE_DATA_KEY]: key
612
754
  }, { width: `${width}px` });
613
755
  const content = createElement("div", {
614
- className: "tabela__heading__content",
756
+ className: CSS_HEADING_CONTENT,
615
757
  textContent: title
616
- }, {}, {});
617
- const sorter = createElement("div", { className: "tabela__heading__sorter" }, {}, {});
758
+ });
759
+ const sorter = createElement("div", { className: CSS_HEADING_SORTER });
618
760
  wrapper.append(content, sorter);
619
761
  return {
620
762
  content,
@@ -622,6 +764,8 @@ function createHeading(field, title, width) {
622
764
  wrapper
623
765
  };
624
766
  }
767
+ //#endregion
768
+ //#region src/managers/column.manager.ts
625
769
  var ColumnManager = class {
626
770
  items = [];
627
771
  constructor(state) {
@@ -634,14 +778,17 @@ var ColumnManager = class {
634
778
  this.items = void 0;
635
779
  this.state = void 0;
636
780
  }
781
+ get(key) {
782
+ return this.items.find((item) => item.options.key === key);
783
+ }
637
784
  remove(value) {
638
785
  const { items, state } = this;
639
786
  const { components, managers } = state;
640
- const fields = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string");
641
- const { length } = fields;
787
+ const keys = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string");
788
+ const { length } = keys;
642
789
  if (length === 0) return;
643
- for (let fieldIndex = 0; fieldIndex < length; fieldIndex += 1) {
644
- const itemIndex = items.findIndex((component) => component.options.field === fields[fieldIndex]);
790
+ for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
791
+ const itemIndex = items.findIndex((component) => component.options.key === keys[keyIndex]);
645
792
  if (itemIndex > -1) {
646
793
  items[itemIndex].destroy();
647
794
  items.splice(itemIndex, 1);
@@ -649,16 +796,54 @@ var ColumnManager = class {
649
796
  }
650
797
  components.header.update(items);
651
798
  components.footer.update(items);
652
- managers.render.removeCells(fields);
799
+ managers.render.removeCells(keys);
800
+ }
801
+ set(columns) {
802
+ const { items, state } = this;
803
+ const { footer, header } = state.components;
804
+ items.splice(0, items.length, ...columns.map((column) => new ColumnComponent(column)));
805
+ header.update(items);
806
+ footer.update(items);
807
+ }
808
+ };
809
+ //#endregion
810
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/chunk.mjs
811
+ /**
812
+ * Chunk an array into smaller arrays
813
+ * @param array Array to chunk
814
+ * @param size Size of each chunk _(minimum is `1`, maximum is `5000`; defaults to `5000`)_
815
+ * @returns Array of arrays
816
+ */
817
+ function chunk(array, size) {
818
+ if (!Array.isArray(array)) return [];
819
+ if (array.length === 0) return [];
820
+ const { length } = array;
821
+ const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
822
+ if (length <= actualSize) return [array];
823
+ const chunks = [];
824
+ let index = 0;
825
+ while (index < length) {
826
+ chunks.push(array.slice(index, index + actualSize));
827
+ index += actualSize;
653
828
  }
654
- set(columns) {
655
- const { items, state } = this;
656
- const { footer, header } = state.components;
657
- items.splice(0, items.length, ...columns.map((column) => new ColumnComponent(column)));
658
- header.update(items);
659
- footer.update(items);
829
+ return chunks;
830
+ }
831
+ const MAX_SIZE = 5e3;
832
+ //#endregion
833
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/compact.mjs
834
+ function compact(array, strict) {
835
+ if (!Array.isArray(array)) return [];
836
+ if (strict === true) return array.filter(Boolean);
837
+ const { length } = array;
838
+ const compacted = [];
839
+ for (let index = 0; index < length; index += 1) {
840
+ const item = array[index];
841
+ if (item != null) compacted.push(item);
660
842
  }
661
- };
843
+ return compacted;
844
+ }
845
+ //#endregion
846
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/callbacks.mjs
662
847
  function getArrayCallback(value) {
663
848
  switch (typeof value) {
664
849
  case "function": return value;
@@ -674,26 +859,8 @@ function getArrayCallbacks(bool, key, value) {
674
859
  value: getArrayCallback(value)
675
860
  };
676
861
  }
677
- function findValue(type, array, parameters) {
678
- const findIndex = type === FIND_VALUE_INDEX;
679
- if (!Array.isArray(array) || array.length === 0) return findIndex ? -1 : void 0;
680
- const { bool, key, value } = getParameters(parameters);
681
- const callbacks = getArrayCallbacks(bool, key);
682
- if (callbacks?.bool == null && callbacks?.keyed == null) return findIndex ? array.indexOf(value) : array.find((item) => Object.is(item, value));
683
- if (callbacks.bool != null) {
684
- const index = array.findIndex(callbacks.bool);
685
- return findIndex ? index : array[index];
686
- }
687
- return findValueInArray(array, callbacks.keyed, value, findIndex);
688
- }
689
- function findValueInArray(array, callback, value, findIndex) {
690
- const { length } = array;
691
- for (let index = 0; index < length; index += 1) {
692
- const item = array[index];
693
- if (Object.is(callback?.(item, index, array), value)) return findIndex ? index : item;
694
- }
695
- return findIndex ? -1 : void 0;
696
- }
862
+ //#endregion
863
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/find.mjs
697
864
  function findValues(type, array, parameters, mapper) {
698
865
  const result = {
699
866
  matched: [],
@@ -736,15 +903,9 @@ function getParameters(original) {
736
903
  value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
737
904
  };
738
905
  }
739
- var FIND_VALUE_INDEX = "index";
740
- var UNIQUE_THRESHOLD = 100;
741
- function filter(array, ...parameters) {
742
- return findValues("all", array, parameters).matched;
743
- }
744
- filter.remove = removeFiltered;
745
- function removeFiltered(array, ...parameters) {
746
- return findValues("all", array, parameters).notMatched;
747
- }
906
+ const UNIQUE_THRESHOLD = 100;
907
+ //#endregion
908
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
748
909
  /**
749
910
  * Is the value a constructor function?
750
911
  * @param value Value to check
@@ -801,84 +962,14 @@ function isTypedArray(value) {
801
962
  ]);
802
963
  return TYPED_ARRAYS.has(value?.constructor);
803
964
  }
804
- var TYPED_ARRAYS;
805
- /**
806
- * Chunk an array into smaller arrays
807
- * @param array Array to chunk
808
- * @param size Size of each chunk _(minimum is `1`, maximum is `5000`; defaults to `5000`)_
809
- * @returns Array of arrays
810
- */
811
- function chunk(array, size) {
812
- if (!Array.isArray(array)) return [];
813
- if (array.length === 0) return [];
814
- const { length } = array;
815
- const actualSize = typeof size === "number" && size > 0 && size <= MAX_SIZE ? size : MAX_SIZE;
816
- if (length <= actualSize) return [array];
817
- const chunks = [];
818
- let index = 0;
819
- while (index < length) {
820
- chunks.push(array.slice(index, index + actualSize));
821
- index += actualSize;
822
- }
823
- return chunks;
824
- }
825
- var MAX_SIZE = 5e3;
826
- function compact(array, strict) {
827
- if (!Array.isArray(array)) return [];
828
- if (strict === true) return array.filter(Boolean);
829
- const { length } = array;
830
- const compacted = [];
831
- for (let index = 0; index < length; index += 1) {
832
- const item = array[index];
833
- if (item != null) compacted.push(item);
834
- }
835
- return compacted;
836
- }
837
- function indexOf(array, ...parameters) {
838
- return findValue(FIND_VALUE_INDEX, array, parameters);
839
- }
840
- function getName(start, haystack, needle) {
841
- if (start === 0) return haystack === needle ? POSITION_SAME : POSITION_START;
842
- return start + needle === haystack ? POSITION_END : POSITION_INSIDE;
843
- }
844
- function getPosition$1(haystack, needle, key) {
845
- if (!Array.isArray(haystack) || !Array.isArray(needle)) return invalid;
846
- const haystackLength = haystack.length;
847
- const needleLength = needle.length;
848
- if (haystackLength === 0 || needleLength === 0) return outside;
849
- if (needleLength > haystackLength) return outside;
850
- const callback = getArrayCallback(key);
851
- const limit = haystackLength - needleLength + 1;
852
- let needleValues = callback == null ? needle : needle.slice();
853
- if (callback != null) for (let needleIndex = 0; needleIndex < needleLength; needleIndex += 1) needleValues[needleIndex] = callback(needle[needleIndex], needleIndex, needle);
854
- for (let haystackIndex = 0; haystackIndex < limit; haystackIndex += 1) {
855
- let haystackItem = haystack[haystackIndex];
856
- let haystackValue = callback?.(haystackItem, haystackIndex, haystack) ?? haystackItem;
857
- if (!Object.is(haystackValue, needleValues[0])) continue;
858
- if (needleLength === 1) return [haystackIndex, getName(haystackIndex, haystackLength, needleLength)];
859
- for (let needleIndex = 1; needleIndex < needleLength; needleIndex += 1) {
860
- haystackItem = haystack[haystackIndex + needleIndex];
861
- haystackValue = callback?.(haystackItem, haystackIndex + needleIndex, haystack) ?? haystackItem;
862
- if (!Object.is(haystackValue, needleValues[needleIndex])) break;
863
- if (needleIndex === needleLength - 1) return [haystackIndex, getName(haystackIndex, haystackLength, needleLength)];
864
- }
865
- }
866
- return outside;
867
- }
868
- function indexOfArray(haystack, needle, key) {
869
- return getPosition$1(haystack, needle, key)[0];
870
- }
871
- var POSITION_END = "end";
872
- var POSITION_INSIDE = "inside";
873
- var POSITION_INVALID = "invalid";
874
- var POSITION_OUTSIDE = "outside";
875
- var POSITION_SAME = "same";
876
- var POSITION_START = "start";
877
- var invalid = [-1, POSITION_INVALID];
878
- var outside = [-1, POSITION_OUTSIDE];
965
+ let TYPED_ARRAYS;
966
+ //#endregion
967
+ //#region node_modules/@oscarpalmer/atoms/dist/array/select.mjs
879
968
  function select(array, ...parameters) {
880
969
  return findValues("all", array, parameters, parameters.pop()).matched;
881
970
  }
971
+ //#endregion
972
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/math/aggregate.mjs
882
973
  function aggregate(type, array, key) {
883
974
  const length = Array.isArray(array) ? array.length : 0;
884
975
  if (length === 0) return {
@@ -917,12 +1008,14 @@ function getAggregated(type, array, key) {
917
1008
  const aggregated = aggregate(type, array, key);
918
1009
  return aggregated.count > 0 ? aggregated.value : NaN;
919
1010
  }
920
- var aggregators = {
1011
+ const aggregators = {
921
1012
  average: calculateSum,
922
1013
  max: (current, value, notNumber) => notNumber || value > current ? value : current,
923
1014
  min: (current, value, notNumber) => notNumber || value < current ? value : current,
924
1015
  sum: calculateSum
925
1016
  };
1017
+ //#endregion
1018
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
926
1019
  /**
927
1020
  * Get the string value from any value
928
1021
  * @param value Original value
@@ -936,6 +1029,9 @@ function getString(value) {
936
1029
  const asString = String(value.valueOf?.() ?? value);
937
1030
  return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
938
1031
  }
1032
+ function ignoreKey(key) {
1033
+ return EXPRESSION_IGNORED.test(key);
1034
+ }
939
1035
  /**
940
1036
  * Join an array of values into a string
941
1037
  * @param value Array of values
@@ -953,7 +1049,10 @@ function join(value, delimiter) {
953
1049
  function words(value) {
954
1050
  return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
955
1051
  }
956
- var EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
1052
+ const EXPRESSION_IGNORED = /(^|\.)(__proto__|constructor|prototype)(\.|$)/i;
1053
+ const EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
1054
+ //#endregion
1055
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/handlers.mjs
957
1056
  function getCompareHandlers(owner, options) {
958
1057
  const { get, register, unregister } = getHandlers(owner, options);
959
1058
  return {
@@ -987,7 +1086,9 @@ function getHandlers(owner, options) {
987
1086
  function isConstructable(value) {
988
1087
  return typeof value === "object" && value !== null;
989
1088
  }
990
- var COMPARE_NAME = "compare";
1089
+ //#endregion
1090
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/compare.mjs
1091
+ const COMPARE_NAME = "compare";
991
1092
  /**
992
1093
  * Compare two values _(for sorting purposes)_
993
1094
  * @param first First value
@@ -1058,119 +1159,82 @@ function getComparisonParts(value) {
1058
1159
  if (Array.isArray(value)) return value;
1059
1160
  return typeof value === "object" ? [value] : words(getString(value));
1060
1161
  }
1061
- var comparators$1 = {
1162
+ const comparators$1 = {
1062
1163
  bigint: compareNumbers,
1063
1164
  boolean: compareNumbers,
1064
1165
  number: compareNumbers,
1065
1166
  symbol: compareSymbols
1066
1167
  };
1067
- function getCallback(value, key, forObject) {
1068
- if (key != null) return;
1069
- if (forObject && typeof value.value === "function") return value.value;
1070
- return typeof value === "function" ? value : void 0;
1071
- }
1072
- function getKey$1(value, forObject) {
1073
- if (forObject && typeof value.key === "string") return value.key;
1074
- return typeof value === "string" ? value : void 0;
1168
+ //#endregion
1169
+ //#region node_modules/@oscarpalmer/atoms/dist/array/sort.mjs
1170
+ function getComparisonSorter(callback, modifier) {
1171
+ return {
1172
+ modifier,
1173
+ compare: { simple: callback },
1174
+ get: false,
1175
+ identifier: String(callback)
1176
+ };
1075
1177
  }
1076
- function getModifier(value, modifier, forObject) {
1077
- if (!forObject || typeof value.direction !== "string") return modifier;
1078
- if (value.direction === "ascending") return 1;
1079
- return value.direction === "descending" ? -1 : modifier;
1178
+ function getObjectSorter(obj, modifier) {
1179
+ let sorter;
1180
+ if (typeof obj.comparison === "function") sorter = getComparisonSorter(obj.comparison, modifier);
1181
+ else if (typeof obj.key === "string") {
1182
+ sorter = getValueSorter(obj.key, modifier);
1183
+ if (typeof obj.compare === "function") sorter.compare = { complex: obj.compare };
1184
+ } else if (typeof obj.value === "function") sorter = getValueSorter(obj.value, modifier);
1185
+ if (sorter != null && typeof obj.direction === "string") sorter.modifier = modifiers[obj.direction] ?? modifier;
1186
+ return sorter;
1080
1187
  }
1081
1188
  function getSorter(value, modifier) {
1082
- const forObject = isPlainObject(value);
1083
- const sorter = {
1084
- identifier: "",
1085
- modifier
1086
- };
1087
- sorter.compare = forObject && typeof value.compare === "function" ? value.compare : void 0;
1088
- sorter.key = getKey$1(value, forObject);
1089
- sorter.modifier = getModifier(value, modifier, forObject);
1090
- sorter.callback = getCallback(value, sorter.key, forObject);
1091
- if (sorter.key != null || sorter.callback != null) {
1092
- sorter.identifier = `${sorter.key ?? sorter.callback}`;
1093
- return sorter;
1189
+ switch (true) {
1190
+ case typeof value === "function": return getComparisonSorter(value, modifier);
1191
+ case typeof value === "string": return getValueSorter(value, modifier);
1192
+ case isPlainObject(value): return getObjectSorter(value, modifier);
1193
+ default: break;
1094
1194
  }
1095
1195
  }
1196
+ function getValueSorter(value, modifier) {
1197
+ return {
1198
+ modifier,
1199
+ get: true,
1200
+ identifier: String(value),
1201
+ value: typeof value === "function" ? value : (item) => item[value]
1202
+ };
1203
+ }
1096
1204
  function sort(array, first, second) {
1097
1205
  if (!Array.isArray(array)) return [];
1098
1206
  if (array.length < 2) return array;
1099
- const modifier = (first === true || second === true ? "descending" : "ascending") === "ascending" ? 1 : -1;
1207
+ const modifier = modifiers[first === true || second === true ? SORT_DIRECTION_DESCENDING : SORT_DIRECTION_ASCENDING];
1100
1208
  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);
1101
1209
  const { length } = sorters;
1102
- if (length === 0) return array.sort((firstItem, secondItem) => compare(firstItem, secondItem) * modifier);
1210
+ if (length === 0) return array.sort((first, second) => compare(first, second) * modifier);
1103
1211
  if (length === 1) {
1104
1212
  const sorter = sorters[0];
1105
- const { callback, key } = sorter;
1106
1213
  return array.sort((firstItem, secondItem) => {
1107
- const firstValue = key == null ? callback?.(firstItem) : firstItem[key];
1108
- const secondValue = key == null ? callback?.(secondItem) : secondItem[key];
1109
- return (sorter.compare?.(firstItem, firstValue, secondItem, secondValue) ?? compare(firstValue, secondValue)) * sorter.modifier;
1214
+ const firstValue = sorter.get ? sorter.value(firstItem) : firstItem;
1215
+ const secondValue = sorter.get ? sorter.value(secondItem) : secondItem;
1216
+ return (sorter.compare?.complex?.(firstItem, firstValue, secondItem, secondValue) ?? sorter.compare?.simple?.(firstItem, secondItem) ?? compare(firstValue, secondValue)) * sorter.modifier;
1110
1217
  });
1111
1218
  }
1112
1219
  return array.sort((firstItem, secondItem) => {
1113
1220
  for (let index = 0; index < length; index += 1) {
1114
1221
  const sorter = sorters[index];
1115
- const { callback, key } = sorter;
1116
- const firstValue = key == null ? callback?.(firstItem) : firstItem[key];
1117
- const secondValue = key == null ? callback?.(secondItem) : secondItem[key];
1118
- const compared = (sorter.compare?.(firstItem, firstValue, secondItem, secondValue) ?? compare(firstValue, secondValue)) * sorter.modifier;
1119
- if (compared !== 0) return compared;
1222
+ const firstValue = sorter.value?.(firstItem) ?? firstItem;
1223
+ const secondValue = sorter.value?.(secondItem) ?? secondItem;
1224
+ const comparison = (sorter.compare?.complex?.(firstItem, firstValue, secondItem, secondValue) ?? sorter.compare?.simple?.(firstItem, secondItem) ?? compare(firstValue, secondValue)) * sorter.modifier;
1225
+ if (comparison !== 0) return comparison;
1120
1226
  }
1121
1227
  return 0;
1122
1228
  });
1123
1229
  }
1124
- function swap(array, first, second, third) {
1125
- if (!Array.isArray(array)) return [];
1126
- if (array.length === 0) return array;
1127
- if (Array.isArray(first) && Array.isArray(second)) return swapArrays(array, first, second, third);
1128
- return swapValues(array, first, second, third);
1129
- }
1130
- swap.indices = swapIndices;
1131
- function swapArrays(array, from, to, key) {
1132
- if (from.length === 0 || to.length === 0) return array;
1133
- if (from.length === 1 && to.length === 1) return swapValues(array, from[0], to[0], key);
1134
- const fromIndex = indexOfArray(array, from, key);
1135
- const toIndex = indexOfArray(array, to, key);
1136
- if (fromIndex === -1 || toIndex === -1) return array;
1137
- const first = fromIndex < toIndex ? from : to;
1138
- const second = fromIndex < toIndex ? to : from;
1139
- const firstIndex = first === from ? fromIndex : toIndex;
1140
- const secondIndex = first === from ? toIndex : fromIndex;
1141
- const firstEnd = firstIndex + first.length - 1;
1142
- if (firstIndex <= secondIndex + second.length - 1 && firstEnd >= secondIndex) return array;
1143
- array.splice(firstIndex, first.length, ...second);
1144
- array.splice(secondIndex, second.length, ...first);
1145
- return array;
1146
- }
1147
- /**
1148
- * Swap two indiced items in an array
1149
- *
1150
- * If either index is out of bounds, the array will be returned unchanged
1151
- * @param array Array of items to swap
1152
- * @param first First index _(can be negative to count from the end)_
1153
- * @param second Second index _(can be negative to count from the end)_
1154
- * @returns Original array with items swapped _(or unchanged if unable to swap)_
1155
- */
1156
- function swapIndices(array, first, second) {
1157
- if (!Array.isArray(array) || array.length === 0) return [];
1158
- if (typeof first !== "number" || typeof second !== "number") return array;
1159
- const firstIndex = first < 0 ? array.length + first : first;
1160
- const secondIndex = second < 0 ? array.length + second : second;
1161
- if (firstIndex === secondIndex || firstIndex >= array.length || secondIndex >= array.length) return array;
1162
- const temp = array[firstIndex];
1163
- array[firstIndex] = array[secondIndex];
1164
- array[secondIndex] = temp;
1165
- return array;
1166
- }
1167
- function swapValues(array, from, to, key) {
1168
- const callback = getArrayCallback(key);
1169
- const first = callback == null ? array.indexOf(from) : indexOf(array, callback, callback(from, void 0, []));
1170
- const second = callback == null ? array.indexOf(to) : indexOf(array, callback, callback(to, void 0, []));
1171
- if (first === second || first === -1 || second === -1) return array;
1172
- return swapIndices(array, first, second);
1173
- }
1230
+ const SORT_DIRECTION_ASCENDING = "ascending";
1231
+ const SORT_DIRECTION_DESCENDING = "descending";
1232
+ const modifiers = {
1233
+ [SORT_DIRECTION_ASCENDING]: 1,
1234
+ [SORT_DIRECTION_DESCENDING]: -1
1235
+ };
1236
+ //#endregion
1237
+ //#region node_modules/@oscarpalmer/atoms/dist/array/to-map.mjs
1174
1238
  function getMapValues(array, first, second, arrays) {
1175
1239
  if (!Array.isArray(array)) return /* @__PURE__ */ new Map();
1176
1240
  const { length } = array;
@@ -1195,6 +1259,8 @@ toMap.arrays = toMapArrays;
1195
1259
  function toMapArrays(array, first, second) {
1196
1260
  return getMapValues(array, first, second, true);
1197
1261
  }
1262
+ //#endregion
1263
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/array/group.mjs
1198
1264
  function groupValues(array, key, value, arrays) {
1199
1265
  if (!Array.isArray(array) || array.length === 0) return {};
1200
1266
  const { length } = array;
@@ -1212,6 +1278,8 @@ function groupValues(array, key, value, arrays) {
1212
1278
  }
1213
1279
  return record;
1214
1280
  }
1281
+ //#endregion
1282
+ //#region node_modules/@oscarpalmer/atoms/dist/array/to-record.mjs
1215
1283
  function toRecord(array, first, second) {
1216
1284
  return groupValues(array, first, second, false);
1217
1285
  }
@@ -1219,89 +1287,312 @@ toRecord.arrays = toRecordArrays;
1219
1287
  function toRecordArrays(array, first, second) {
1220
1288
  return groupValues(array, first, second, true);
1221
1289
  }
1290
+ //#endregion
1291
+ //#region node_modules/@oscarpalmer/atoms/dist/is.mjs
1292
+ /**
1293
+ * Is the value `undefined`, `null`, or a whitespace-only string?
1294
+ * @param value Value to check
1295
+ * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
1296
+ */
1297
+ function isNullableOrWhitespace(value) {
1298
+ return value == null || EXPRESSION_WHITESPACE.test(getString(value));
1299
+ }
1300
+ const EXPRESSION_WHITESPACE = /^\s*$/;
1301
+ //#endregion
1302
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/function/timer.mjs
1303
+ function getInterval(value) {
1304
+ return typeof value === "number" && value > 0 ? value : 0;
1305
+ }
1306
+ function getTimer(type, callback, time) {
1307
+ const interval = getInterval(time);
1308
+ function run(now) {
1309
+ start ??= now;
1310
+ if (interval === 0 || now - start >= interval - OFFSET) {
1311
+ if (throttle) start = now;
1312
+ callback(...args);
1313
+ } else frame = requestAnimationFrame(run);
1314
+ }
1315
+ const throttle = type === TIMER_THROTTLE;
1316
+ let args;
1317
+ let frame;
1318
+ let start;
1319
+ const timer = (...parameters) => {
1320
+ timer.cancel();
1321
+ args = parameters;
1322
+ frame = requestAnimationFrame(run);
1323
+ };
1324
+ timer.cancel = () => {
1325
+ cancelAnimationFrame(frame);
1326
+ };
1327
+ return timer;
1328
+ }
1329
+ const OFFSET = 5;
1330
+ const TIMER_THROTTLE = "throttle";
1331
+ const TIMER_WAIT = "wait";
1332
+ //#endregion
1333
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/models.mjs
1334
+ const PROMISE_ABORT_EVENT = "abort";
1335
+ const PROMISE_ABORT_OPTIONS = { once: true };
1336
+ //#endregion
1337
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/helpers.mjs
1338
+ function getNumberOrDefault(value) {
1339
+ return typeof value === "number" && value > 0 ? value : 0;
1340
+ }
1341
+ function getPromiseOptions(input) {
1342
+ if (typeof input === "number") return { time: getNumberOrDefault(input) };
1343
+ if (input instanceof AbortSignal) return {
1344
+ signal: input,
1345
+ time: 0
1346
+ };
1347
+ const options = typeof input === "object" && input !== null ? input : {};
1348
+ return {
1349
+ signal: options.signal instanceof AbortSignal ? options.signal : void 0,
1350
+ time: getNumberOrDefault(options.time)
1351
+ };
1352
+ }
1353
+ //#endregion
1354
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/misc.mjs
1355
+ function settlePromise(aborter, settler, value, signal) {
1356
+ signal?.removeEventListener(PROMISE_ABORT_EVENT, aborter);
1357
+ settler(value);
1358
+ }
1359
+ //#endregion
1360
+ //#region node_modules/@oscarpalmer/atoms/dist/promise/delay.mjs
1361
+ function delay(options) {
1362
+ const { signal, time } = getPromiseOptions(options);
1363
+ if (signal?.aborted ?? false) return Promise.reject(signal.reason);
1364
+ function abort() {
1365
+ timer.cancel();
1366
+ rejector(signal.reason);
1367
+ }
1368
+ const timer = getTimer(TIMER_WAIT, () => {
1369
+ settlePromise(abort, resolver, void 0, signal);
1370
+ }, time);
1371
+ signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS);
1372
+ let rejector;
1373
+ let resolver;
1374
+ return new Promise((resolve, reject) => {
1375
+ rejector = reject;
1376
+ resolver = resolve;
1377
+ if (time === 0) settlePromise(abort, resolve, void 0, signal);
1378
+ else timer();
1379
+ });
1380
+ }
1381
+ //#endregion
1382
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/misc.mjs
1383
+ function findKey(needle, haystack) {
1384
+ const keys = Object.keys(haystack);
1385
+ const index = keys.map((key) => key.toLowerCase()).indexOf(needle.toLowerCase());
1386
+ return index > -1 ? keys[index] : needle;
1387
+ }
1388
+ function getNestedValue(data, path, ignoreCase) {
1389
+ if (typeof data !== "object" || data === null || typeof path !== "string" || path.trim().length === 0) return {
1390
+ exists: false,
1391
+ value: void 0
1392
+ };
1393
+ const shouldIgnoreCase = ignoreCase === true;
1394
+ const paths = getPaths(path, shouldIgnoreCase);
1395
+ if (typeof paths === "string") return handleValue(data, paths, null, true, shouldIgnoreCase);
1396
+ const { length } = paths;
1397
+ let current = data;
1398
+ for (let index = 0; index < length; index += 1) {
1399
+ const part = paths[index];
1400
+ const handled = handleValue(current, part, null, true, shouldIgnoreCase);
1401
+ if (!handled.exists) return handled;
1402
+ current = handled.value;
1403
+ }
1404
+ return {
1405
+ exists: true,
1406
+ value: current
1407
+ };
1408
+ }
1409
+ function getPaths(path, lowercase) {
1410
+ const normalized = lowercase ? path.toLowerCase() : path;
1411
+ if (!EXPRESSION_NESTED.test(normalized)) return normalized;
1412
+ return normalized.replace(EXPRESSION_BRACKET, ".$1").replace(EXPRESSION_DOTS, "").split(".");
1413
+ }
1414
+ function handleValue(data, path, value, get, ignoreCase) {
1415
+ if (typeof data === "object" && data !== null && !ignoreKey(path)) {
1416
+ const key = ignoreCase ? findKey(path, data) : path;
1417
+ if (get) return {
1418
+ exists: key in data,
1419
+ value: data[key]
1420
+ };
1421
+ data[key] = typeof value === "function" ? value(data[key]) : value;
1422
+ }
1423
+ if (get) return {
1424
+ exists: false,
1425
+ value: void 0
1426
+ };
1427
+ }
1428
+ const EXPRESSION_BRACKET = /\[(\w+)\]/g;
1429
+ const EXPRESSION_DOTS = /^\.|\.$/g;
1430
+ const EXPRESSION_NESTED = /\.|\[\w+\]/;
1431
+ //#endregion
1432
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/get.mjs
1433
+ function getValue(data, path, ignoreCase) {
1434
+ return getNestedValue(data, path, ignoreCase === true).value;
1435
+ }
1436
+ //#endregion
1437
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/has.mjs
1438
+ function hasValue(data, path, ignoreCase) {
1439
+ return getNestedValue(data, path, ignoreCase === true).exists;
1440
+ }
1441
+ hasValue.get = getWithHasValue;
1442
+ function getWithHasValue(data, path, ignoreCase) {
1443
+ return getNestedValue(data, path, ignoreCase === true);
1444
+ }
1445
+ //#endregion
1446
+ //#region src/models/group.model.ts
1447
+ const GROUP_KEY_EXPRESSION = /^group:(.+)$/;
1448
+ const GROUP_KEY_PREFIX = "group:";
1449
+ //#endregion
1450
+ //#region src/components/group.component.ts
1222
1451
  var GroupComponent = class {
1223
1452
  element;
1224
1453
  expanded = true;
1225
1454
  filtered = 0;
1455
+ key;
1226
1456
  selected = 0;
1227
1457
  total = 0;
1228
- constructor(key, label, value) {
1229
- this.key = key;
1458
+ value;
1459
+ constructor(label, value) {
1230
1460
  this.label = label;
1231
- this.value = value;
1461
+ const stringified = getString(value);
1462
+ this.key = `${GROUP_KEY_PREFIX}${stringified}`;
1463
+ this.value = {
1464
+ stringified,
1465
+ original: value
1466
+ };
1232
1467
  }
1233
1468
  };
1469
+ function removeGroup(group) {
1470
+ if (group.element == null) return;
1471
+ group.element.innerHTML = "";
1472
+ group.element.remove();
1473
+ }
1234
1474
  function renderGroup(state, component) {
1235
1475
  component.element ??= createElement("div", {
1236
- className: "tabela__row tabela__row--group",
1237
- innerHTML: `<div class="tabela__cell tabela__cell--group" role="cell">
1238
- <button class="tabela__button tabela__button--group" data-event="group" data-key="${component.key}" type="button">
1476
+ className: `${CSS_ROW} ${CSS_ROW_GROUP}`,
1477
+ innerHTML: `<div class="${CSS_CELL} ${CSS_CELL_GROUP}" role="${ROLE_CELL}">
1478
+ <button class="${CSS_BUTTON} ${CSS_BUTTON_GROUP}" ${ATTRIBUTE_DATA_EVENT}="${EVENT_GROUP}" ${ATTRIBUTE_DATA_KEY}="${state.prefix}_${component.key}" type="button">
1239
1479
  <span aria-hidden="true"></span>
1240
1480
  <span>Open/close</span>
1241
1481
  </button>
1242
1482
  <p>${component.label}</p>
1483
+ <span class="${CSS_GROUP_TOTAL}">${component.total}</span>
1484
+ <span class="${CSS_GROUP_SELECTED}">${component.selected === 0 ? "" : component.selected}</span>
1243
1485
  </div>`,
1244
- role: "row"
1486
+ [ATTRIBUTE_ROLE]: "row"
1245
1487
  }, {}, { height: `${state.options.rowHeight}px` });
1246
1488
  }
1489
+ function updateGroup(state, component, emit) {
1490
+ if (component.element == null) return;
1491
+ const selected = component.element.querySelector(selectedSelector);
1492
+ const total = component.element.querySelector(totalSelector);
1493
+ if (selected != null) selected.textContent = component.selected === 0 ? "" : String(component.selected);
1494
+ if (total != null) total.textContent = String(component.total);
1495
+ if (emit) state.managers.event.emit(EVENT_GROUP_UPDATE, [component]);
1496
+ }
1497
+ const selectedSelector = `.${CSS_GROUP_SELECTED}`;
1498
+ const totalSelector = `.${CSS_GROUP_TOTAL}`;
1499
+ //#endregion
1500
+ //#region src/helpers/misc.helpers.ts
1501
+ function getGroup(group) {
1502
+ return { value: group.value.original };
1503
+ }
1504
+ function getKey(value) {
1505
+ if (typeof value === "number") return value;
1506
+ if (typeof value !== "string") return;
1507
+ return integerExpression.test(value) ? Number.parseInt(value, 10) : value;
1508
+ }
1509
+ function isEvent(value) {
1510
+ return EVENTS_NAMES.has(value);
1511
+ }
1512
+ function isGroupKey(key) {
1513
+ return typeof key === "string" && GROUP_KEY_EXPRESSION.test(key);
1514
+ }
1515
+ const integerExpression = /^\d+$/;
1516
+ //#endregion
1517
+ //#region src/models/sort.model.ts
1518
+ const SORT_ASCENDING = "ascending";
1519
+ const SORT_DESCENDING = "descending";
1520
+ //#endregion
1521
+ //#region src/managers/sort.manager.ts
1247
1522
  var SortManager = class {
1248
- handlers = Object.freeze({
1523
+ handlers = {
1249
1524
  add: (field, direction) => this.add(field, direction),
1250
1525
  flip: (field) => this.flip(field),
1251
1526
  clear: () => this.clear(),
1252
1527
  remove: (field) => this.remove(field),
1253
- set: (items) => this.set(items)
1254
- });
1528
+ set: (items) => this.set(items, true)
1529
+ };
1255
1530
  items = [];
1256
1531
  constructor(state) {
1257
1532
  this.state = state;
1258
1533
  }
1259
- add(field, direction) {
1260
- if (this.items.findIndex((item) => item.key === field) > -1) return;
1534
+ add(key, direction) {
1535
+ if (this.items.findIndex((item) => item.key === key) > -1) return;
1261
1536
  this.items.push({
1262
- key: field,
1537
+ key,
1263
1538
  direction: direction ?? "ascending"
1264
1539
  });
1540
+ this.state.managers.event.emit(EVENT_SORT_ADD, [{
1541
+ key,
1542
+ direction: direction ?? "ascending"
1543
+ }]);
1265
1544
  this.sort();
1266
1545
  }
1267
- addOrSet(event, field) {
1268
- if (event.ctrlKey || event.metaKey) this.add(field);
1546
+ addOrSet(event, key) {
1547
+ if (event.ctrlKey || event.metaKey) this.add(key);
1269
1548
  else this.set([{
1270
- field,
1271
- direction: "ascending"
1272
- }]);
1549
+ key,
1550
+ direction: SORT_ASCENDING
1551
+ }], false);
1273
1552
  }
1274
1553
  clear() {
1275
- if (this.items.length > 0) {
1276
- this.items.length = 0;
1277
- this.sort();
1278
- }
1554
+ if (this.items.length === 0) return;
1555
+ this.items.length = 0;
1556
+ this.state.managers.event.emit(EVENT_SORT_CLEAR);
1557
+ this.sort();
1279
1558
  }
1280
1559
  destroy() {
1281
1560
  this.handlers = void 0;
1282
1561
  this.items = void 0;
1283
1562
  this.state = void 0;
1284
1563
  }
1285
- flip(field) {
1286
- const item = this.items.find((item) => item.key === field);
1564
+ flip(key) {
1565
+ const item = this.items.find((item) => item.key === key);
1287
1566
  if (item == null) return;
1288
- item.direction = item.direction === "ascending" ? "descending" : "ascending";
1567
+ item.direction = item.direction === "ascending" ? SORT_DESCENDING : SORT_ASCENDING;
1568
+ this.state.managers.event.emit(EVENT_SORT_FLIP, [{
1569
+ key,
1570
+ direction: item.direction
1571
+ }]);
1289
1572
  this.sort();
1290
1573
  }
1291
- remove(field) {
1292
- const index = this.items.findIndex((item) => item.key === field);
1293
- if (index > -1) {
1294
- this.items.splice(index, 1);
1295
- this.sort();
1296
- }
1297
- }
1298
- removeOrClear(event, field) {
1299
- if (event.ctrlKey || event.metaKey) this.remove(field);
1300
- else this.clear();
1574
+ remove(key) {
1575
+ const index = this.items.findIndex((item) => item.key === key);
1576
+ if (index === -1) return;
1577
+ const spliced = this.items.splice(index, 1);
1578
+ this.state.managers.event.emit(EVENT_SORT_REMOVE, spliced);
1579
+ if (this.items.length === 0) this.state.managers.event.emit(EVENT_SORT_CLEAR);
1580
+ this.sort();
1301
1581
  }
1302
- set(items) {
1303
- this.items.splice(0, this.items.length, ...items.map((item) => ({
1304
- key: item.field,
1582
+ set(items, set) {
1583
+ const removed = this.items.splice(0, this.items.length, ...items.map((item) => ({
1584
+ key: item.key,
1585
+ direction: item.direction
1586
+ })));
1587
+ if (set) this.state.managers.event.emit(EVENT_SORT_SET, {
1588
+ removed,
1589
+ added: items.map((item) => ({
1590
+ key: item.key,
1591
+ direction: item.direction
1592
+ }))
1593
+ });
1594
+ else this.state.managers.event.emit(EVENT_SORT_ADD, items.map((item) => ({
1595
+ key: item.key,
1305
1596
  direction: item.direction
1306
1597
  })));
1307
1598
  this.sort();
@@ -1311,239 +1602,305 @@ var SortManager = class {
1311
1602
  const { length } = state.managers.column.items;
1312
1603
  for (let index = 0; index < length; index += 1) {
1313
1604
  const column = state.managers.column.items[index];
1314
- const sorterIndex = items.findIndex((item) => item.key === column.options.field);
1605
+ const sorterIndex = items.findIndex((item) => item.key === column.options.key);
1315
1606
  const sorterItem = items[sorterIndex];
1316
1607
  setAttributes(column.elements.wrapper, {
1317
- "aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
1318
- "data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
1608
+ [ARIA_SORT]: sorterItem == null ? SORT_NONE : items.length > 1 ? SORT_OTHER : sorterItem.direction,
1609
+ [ATTRIBUTE_DATA_SORT_DIRECTION]: sorterItem == null ? void 0 : sorterItem.direction
1319
1610
  });
1320
- setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
1611
+ setAttribute(column.elements.sorter, ATTRIBUTE_DATA_SORT_POSITION, sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
1321
1612
  }
1322
- state.managers.data.values.keys.active = items.length === 0 ? void 0 : getSortedKeys(state, items);
1613
+ state.managers.data.state.keys.active = items.length === 0 ? void 0 : getSortedItems(state, items);
1614
+ state.managers.event.emit(EVENT_DATA_SORTED, state.managers.data.get(true));
1323
1615
  state.managers.render.update(true, true);
1324
1616
  }
1325
- toggle(event, field, direction) {
1617
+ toggle(event, key, direction) {
1326
1618
  switch (direction) {
1327
- case "ascending":
1328
- this.flip(field);
1619
+ case SORT_ASCENDING:
1620
+ this.flip(key);
1329
1621
  return;
1330
- case "descending":
1331
- this.removeOrClear(event, field);
1622
+ case SORT_DESCENDING:
1623
+ this.remove(key);
1332
1624
  return;
1333
1625
  default:
1334
- this.addOrSet(event, field);
1626
+ this.addOrSet(event, key);
1335
1627
  return;
1336
1628
  }
1337
1629
  }
1338
1630
  };
1339
- function getSortedKeys(state, sorters) {
1340
- const data = state.managers.data.values.keys.active?.map((key) => key instanceof GroupComponent ? key : state.managers.data.values.objects.mapped.get(key)) ?? state.managers.data.values.objects.array.slice();
1341
- if (!state.managers.group.enabled) return sort(data, sorters).map((item) => item[state.key]);
1342
- return sortWithGroups(state, data, sorters).map((item) => item instanceof GroupComponent ? item : item[state.key]);
1631
+ function getSortedItems(state, sorters) {
1632
+ const data = state.managers.data.state.keys.active?.map((key) => isGroupKey(key) ? key : state.managers.data.state.values.mapped.get(key)) ?? state.managers.data.state.values.array;
1633
+ if (!state.managers.group.enabled) return sort(data, sorters).map((item) => getValue(item, state.key));
1634
+ return sortWithGroups(state, data, sorters).map((item) => isGroupKey(item) ? item : getValue(item, state.key));
1343
1635
  }
1344
1636
  function sortWithGroups(state, data, sorters) {
1345
1637
  const { length } = sorters;
1346
1638
  return data.sort((first, second) => {
1347
- const firstValue = first instanceof GroupComponent ? first.value : first[state.managers.group.field];
1348
- const secondValue = second instanceof GroupComponent ? second.value : second[state.managers.group.field];
1639
+ const firstIsGroup = isGroupKey(first);
1640
+ const secondIsGroup = isGroupKey(second);
1641
+ const firstValue = firstIsGroup ? state.managers.group.getForKey(first).value.stringified : getValue(first, state.managers.group.key);
1642
+ const secondValue = secondIsGroup ? state.managers.group.getForKey(second).value.stringified : getValue(second, state.managers.group.key);
1349
1643
  const firstOrder = state.managers.group.order[firstValue];
1350
1644
  const secondOrder = state.managers.group.order[secondValue];
1351
1645
  const groupComparison = compare(firstOrder, secondOrder);
1352
1646
  if (groupComparison !== 0) return groupComparison;
1353
- const firstIsGroup = first instanceof GroupComponent;
1354
- const secondIsGroup = second instanceof GroupComponent;
1355
1647
  if (firstIsGroup || secondIsGroup) return firstIsGroup && secondIsGroup ? 0 : firstIsGroup ? -1 : 1;
1356
1648
  for (let index = 0; index < length; index += 1) {
1357
1649
  const sorter = sorters[index];
1358
- const comparison = compare(first[sorter.key], second[sorter.key]);
1650
+ const comparison = compare(getValue(first, sorter.key), getValue(second, sorter.key));
1359
1651
  if (comparison !== 0) return comparison * (sorter.direction === "ascending" ? 1 : -1);
1360
1652
  }
1361
1653
  return 0;
1362
1654
  });
1363
1655
  }
1364
- /**
1365
- * Is the value `undefined`, `null`, or a whitespace-only string?
1366
- * @param value Value to check
1367
- * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
1368
- */
1369
- function isNullableOrWhitespace(value) {
1370
- return value == null || EXPRESSION_WHITESPACE.test(getString(value));
1371
- }
1372
- var EXPRESSION_WHITESPACE = /^\s*$/;
1656
+ const SORT_NONE = "none";
1657
+ const SORT_OTHER = "other";
1658
+ //#endregion
1659
+ //#region src/managers/data.manager.ts
1373
1660
  var DataManager = class {
1374
- handlers = Object.freeze({
1375
- add: (data) => void this.add(data, true),
1376
- clear: () => void this.clear(),
1661
+ handlers = {
1662
+ add: (data) => this.add(data, true),
1663
+ clear: () => this.clear(),
1377
1664
  get: (active) => this.get(active),
1378
- remove: (items) => void this.remove(items, true),
1379
- synchronize: (data, remove) => void this.synchronize(data, remove),
1380
- update: (data) => void this.update(data)
1381
- });
1382
- values = {
1383
- keys: { original: [] },
1384
- objects: {
1385
- mapped: /* @__PURE__ */ new Map(),
1386
- array: []
1387
- }
1665
+ remove: (items) => this.remove(items, true),
1666
+ synchronize: (data, remove) => this.synchronize(data, remove === true),
1667
+ update: (data) => this.update(data, true)
1388
1668
  };
1669
+ state;
1389
1670
  get keys() {
1390
- return this.values.keys.active ?? this.values.keys.original;
1671
+ return this.state.keys.active ?? this.state.keys.original;
1391
1672
  }
1392
1673
  get size() {
1393
1674
  return this.keys.length;
1394
1675
  }
1395
1676
  constructor(state) {
1396
- this.state = state;
1677
+ this.state = {
1678
+ ...state,
1679
+ keys: { original: [] },
1680
+ values: {
1681
+ array: [],
1682
+ mapped: /* @__PURE__ */ new Map()
1683
+ }
1684
+ };
1397
1685
  }
1398
1686
  async add(data, render) {
1399
- const { state, values } = this;
1400
- const { length } = data;
1401
- const updates = [];
1687
+ const { state } = this;
1688
+ const addedData = [];
1689
+ const updatedData = [];
1690
+ const addedGroups = [];
1691
+ const updatedGroups = [];
1692
+ let groupColumn;
1693
+ let { length } = data;
1402
1694
  for (let index = 0; index < length; index += 1) {
1403
1695
  const item = data[index];
1404
- const key = item[state.key];
1405
- if (values.objects.mapped.has(key)) {
1406
- updates.push(item);
1696
+ const key = getValue(item, state.key);
1697
+ if (state.values.mapped.has(key)) {
1698
+ updatedData.push(item);
1407
1699
  continue;
1408
1700
  }
1409
- values.objects.array.push(item);
1410
- values.objects.mapped.set(key, item);
1701
+ addedData.push(item);
1702
+ state.values.array.push(item);
1703
+ state.values.mapped.set(key, item);
1411
1704
  if (!state.managers.group.enabled) continue;
1412
- const groupKey = item[state.managers.group.field];
1413
- let group = state.managers.group.get(groupKey);
1705
+ const groupValue = getValue(item, state.managers.group.key);
1706
+ let group = state.managers.group.getForValue(groupValue);
1414
1707
  if (group == null) {
1415
- group = new GroupComponent(String(groupKey), String(groupKey), groupKey);
1416
- values.objects.array.push(group);
1417
- state.managers.group.add(group);
1418
- }
1708
+ groupColumn ??= state.managers.column.get(state.managers.group.key);
1709
+ group = new GroupComponent(`${groupColumn?.options.label ?? state.managers.group.key}: ${groupValue}`, groupValue);
1710
+ state.values.array.push(group.key);
1711
+ state.managers.group.add(group, false);
1712
+ addedGroups.push(group);
1713
+ } else if (!addedGroups.includes(group) && !updatedGroups.includes(group)) updatedGroups.push(group);
1419
1714
  if (!group.expanded) state.managers.group.collapsed.add(key);
1420
1715
  group.total += 1;
1421
1716
  }
1422
- if (updates.length > 0) this.update(updates);
1423
- else if (render) this.render();
1717
+ length = addedGroups.length;
1718
+ if (length > 0) {
1719
+ state.managers.event.emit(EVENT_GROUP_ADD, addedGroups.map(getGroup));
1720
+ for (let index = 0; index < length; index += 1) updateGroup(state, addedGroups[index], false);
1721
+ }
1722
+ length = updatedGroups.length;
1723
+ if (length > 0) {
1724
+ for (let index = 0; index < length; index += 1) updateGroup(state, updatedGroups[index], false);
1725
+ state.managers.event.emit(EVENT_GROUP_UPDATE, updatedGroups.map(getGroup));
1726
+ }
1727
+ await this.update(updatedData, addedData.length === 0);
1728
+ if (addedData.length === 0) return;
1729
+ state.managers.event.emit(EVENT_DATA_ADD, addedData);
1730
+ if (render) this.render();
1424
1731
  }
1425
- clear() {
1426
- if (this.values.objects.array.length > 0) this.set([]);
1732
+ async clear() {
1733
+ if (this.state.values.array.length > 0) return this.removeItems([], true, true).then(() => void 0);
1427
1734
  }
1428
1735
  destroy() {
1429
- const { values } = this;
1430
- values.objects.mapped.clear();
1431
- values.keys.active = void 0;
1432
- values.keys.original.length = 0;
1433
- values.objects.array.length = 0;
1736
+ const { state } = this;
1737
+ state.values.mapped.clear();
1738
+ state.keys.active = void 0;
1739
+ state.keys.original.length = 0;
1740
+ state.values.array.length = 0;
1434
1741
  this.handlers = void 0;
1435
1742
  this.state = void 0;
1436
- this.values = void 0;
1437
1743
  }
1438
1744
  get(active) {
1439
- const { values } = this;
1440
- return active ?? false ? select(values.keys.active ?? [], (key) => !(key instanceof GroupComponent), (key) => values.objects.mapped.get(key)) : values.objects.array.filter((item) => !(item instanceof GroupComponent));
1745
+ const { state } = this;
1746
+ return (active ?? false) && state.keys.active != null ? select(state.keys.active, (key) => !isGroupKey(key), (key) => state.values.mapped.get(key)) : state.values.array.filter((item) => !isGroupKey(item));
1441
1747
  }
1442
- getIndex(key) {
1443
- return this.keys.indexOf(key);
1748
+ getIndex(item) {
1749
+ return this.keys.indexOf(item);
1444
1750
  }
1445
1751
  async remove(items, render) {
1446
- const { state, values } = this;
1447
- const keys = items.map((value) => isPlainObject(value) ? value[state.key] : value).filter((key) => values.objects.mapped.has(key));
1752
+ const { state } = this;
1753
+ const keys = items.map((value) => isPlainObject(value) ? getValue(value, state.key) : value).filter((key) => !isGroupKey(key));
1448
1754
  const { length } = keys;
1449
- if (length === 0) return;
1450
- for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
1451
- const key = keys[keyIndex];
1452
- values.objects.mapped.delete(key);
1453
- const arrayIndex = values.objects.array.findIndex((item) => !(item instanceof GroupComponent) && item[state.key] === key);
1454
- let item;
1455
- if (arrayIndex > -1) [item] = values.objects.array.splice(arrayIndex, 1);
1456
- values.keys.original.splice(values.keys.original.indexOf(key), 1);
1457
- state.managers.row.remove(key);
1458
- if (!state.managers.group.enabled || item == null) continue;
1459
- state.managers.group.collapsed.delete(key);
1460
- const groupKey = item[state.managers.group.field];
1461
- const group = state.managers.group.get(groupKey);
1462
- if (group == null) continue;
1463
- group.total -= 1;
1464
- if (group.total > 0) continue;
1465
- const groupIndex = values.objects.array.findIndex((item) => item instanceof GroupComponent && item.value === groupKey);
1466
- if (groupIndex > -1) values.objects.array.splice(groupIndex, 1);
1467
- state.managers.group.remove(group);
1755
+ return length === 0 ? render ? void 0 : [] : this.removeItems(keys, false, render);
1756
+ }
1757
+ async removeItems(keys, clear, render) {
1758
+ const { state } = this;
1759
+ if (clear) {
1760
+ state.keys.active = void 0;
1761
+ state.keys.original = [];
1762
+ state.values.array = [];
1763
+ state.values.mapped.clear();
1764
+ state.managers.row.clear();
1765
+ if (state.managers.group.enabled) state.managers.group.clear();
1766
+ state.managers.event.emit(EVENT_DATA_CLEAR);
1767
+ this.render();
1768
+ return render ? void 0 : [];
1769
+ }
1770
+ const removedGroups = [];
1771
+ const updatedGroups = [];
1772
+ const removedData = [];
1773
+ const chunked = chunk(keys);
1774
+ const chunkedLength = chunked.length;
1775
+ for (let chunkedIndex = 0; chunkedIndex < chunkedLength; chunkedIndex += 1) {
1776
+ const chunk = chunked[chunkedIndex];
1777
+ const chunkLength = chunk.length;
1778
+ for (let keyIndex = 0; keyIndex < chunkLength; keyIndex += 1) {
1779
+ const key = chunk[keyIndex];
1780
+ const dataIndex = state.keys.original.indexOf(key);
1781
+ let dataValue;
1782
+ [dataValue] = state.values.array.splice(dataIndex, 1);
1783
+ removedData.push(dataValue);
1784
+ state.keys.original.splice(dataIndex, 1);
1785
+ state.managers.row.remove(key);
1786
+ state.values.mapped.delete(key);
1787
+ if (!state.managers.group.enabled || isGroupKey(key)) continue;
1788
+ state.managers.group.collapsed.delete(key);
1789
+ const groupValue = getValue(dataValue, state.managers.group.key);
1790
+ const group = state.managers.group.getForValue(groupValue);
1791
+ if (group == null) continue;
1792
+ group.total -= 1;
1793
+ if (group.total > 0) {
1794
+ updatedGroups.push(group);
1795
+ continue;
1796
+ }
1797
+ let groupIndex = updatedGroups.indexOf(group);
1798
+ if (groupIndex > -1) updatedGroups.splice(groupIndex, 1);
1799
+ groupIndex = state.values.array.indexOf(group.key);
1800
+ if (groupIndex > -1) {
1801
+ state.keys.original.splice(groupIndex, 1);
1802
+ state.values.array.splice(groupIndex, 1);
1803
+ }
1804
+ removedGroups.push(group);
1805
+ state.managers.group.remove(group, false);
1806
+ if (keys.length >= 1e4) await delay(25);
1807
+ }
1808
+ }
1809
+ let { length } = updatedGroups;
1810
+ if (length > 0) {
1811
+ for (let index = 0; index < length; index += 1) updateGroup(state, updatedGroups[index], false);
1812
+ state.managers.event.emit(EVENT_GROUP_UPDATE, updatedGroups.map(getGroup));
1468
1813
  }
1814
+ length = removedGroups.length;
1815
+ if (length > 0) state.managers.event.emit(EVENT_GROUP_REMOVE, removedGroups.map(getGroup));
1816
+ state.managers.event.emit(EVENT_DATA_REMOVE, removedData);
1469
1817
  if (render) this.render();
1818
+ return render ? void 0 : removedData;
1470
1819
  }
1471
1820
  render() {
1472
- const { state, values } = this;
1473
- if (state.managers.group.enabled) sortWithGroups(state, values.objects.array, [{
1474
- direction: "ascending",
1821
+ const { state } = this;
1822
+ if (state.managers.group.enabled) sortWithGroups(state, state.values.array, [{
1823
+ direction: SORT_ASCENDING,
1475
1824
  key: state.key
1476
1825
  }]);
1477
- else sort(values.objects.array, [{
1478
- direction: "ascending",
1826
+ else sort(state.values.array, [{
1827
+ direction: SORT_ASCENDING,
1479
1828
  key: state.key
1480
1829
  }]);
1481
- values.keys.original = values.objects.array.map((item) => item instanceof GroupComponent ? item : item[state.key]);
1482
- values.objects.mapped = toMap(values.objects.array.filter((item) => !(item instanceof GroupComponent)), (item) => item[state.key]);
1830
+ state.keys.active = void 0;
1831
+ state.keys.original = state.values.array.map((item) => typeof item === "string" ? item : getValue(item, state.key));
1832
+ state.values.mapped = toMap(state.values.array.filter((item) => !isGroupKey(item)), (item) => getValue(item, state.key));
1483
1833
  if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
1484
1834
  else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
1485
1835
  else state.managers.render.update(true, true);
1486
1836
  }
1487
1837
  set(data) {
1488
- const { state, values } = this;
1838
+ const { state } = this;
1489
1839
  const array = data.slice();
1490
1840
  if (state.managers.group.enabled) {
1491
- const grouped = toRecord.arrays(data, state.managers.group.field);
1841
+ const column = state.managers.column.get(state.managers.group.key);
1842
+ const grouped = toRecord.arrays(data, state.managers.group.key);
1492
1843
  const entries = Object.entries(grouped);
1493
1844
  const { length } = entries;
1494
1845
  const groups = [];
1495
1846
  for (let index = 0; index < length; index += 1) {
1496
1847
  const [value, items] = entries[index];
1497
- const key = String(value);
1498
- const group = new GroupComponent(key, key, value);
1848
+ const group = new GroupComponent(`${column?.options.label ?? state.managers.group.key}: ${value}`, value);
1499
1849
  group.total = items.length;
1500
1850
  groups.push(group);
1501
- array.push(group);
1851
+ array.push(group.key);
1502
1852
  }
1503
1853
  state.managers.group.set(groups);
1504
1854
  }
1505
- values.objects.array = array;
1855
+ state.values.array = array;
1506
1856
  this.render();
1507
1857
  }
1508
1858
  async synchronize(data, remove) {
1509
- const { state, values } = this;
1510
- const add = [];
1859
+ const { state } = this;
1860
+ const added = [];
1511
1861
  const updated = [];
1512
1862
  const keys = /* @__PURE__ */ new Set([]);
1513
1863
  const { length } = data;
1514
1864
  for (let index = 0; index < length; index += 1) {
1515
1865
  const object = data[index];
1516
- const key = object[state.key];
1517
- if (values.objects.mapped.has(key)) updated.push(object);
1518
- else add.push(object);
1866
+ const key = getValue(object, state.key);
1867
+ if (state.values.mapped.has(key)) updated.push(object);
1868
+ else added.push(object);
1519
1869
  keys.add(key);
1520
1870
  }
1521
1871
  if (keys.size === 0) return;
1522
- if (remove ?? false) {
1523
- const toRemove = values.keys.original.filter((key) => !(key instanceof GroupComponent) && !keys.has(key));
1524
- if (toRemove.length > 0) await this.remove(toRemove, false);
1872
+ let removed = [];
1873
+ if (remove) {
1874
+ const toRemove = state.keys.original.filter((key) => !isGroupKey(key) && !keys.has(key));
1875
+ if (toRemove.length > 0) removed = await this.remove(toRemove, false);
1525
1876
  }
1526
- await this.update(updated);
1527
- if (add.length > 0) await this.add(add, false);
1528
- if (add.length > 0 || (remove ?? false)) this.render();
1877
+ await this.update(updated, added.length === 0);
1878
+ await this.add(added, false);
1879
+ state.managers.event.emit(EVENT_DATA_SYNCHRONIZE, {
1880
+ added,
1881
+ removed,
1882
+ updated
1883
+ });
1884
+ if (added.length > 0 || remove) this.render();
1529
1885
  }
1530
- async update(data) {
1531
- const { state, values } = this;
1886
+ async update(data, render) {
1887
+ const { state } = this;
1532
1888
  const { length } = data;
1889
+ const updated = [];
1533
1890
  for (let index = 0; index < length; index += 1) {
1534
- const object = data[index];
1535
- const key = object[state.key];
1536
- const value = values.objects.mapped.get(key);
1537
- if (value != null) {
1538
- values.objects.mapped.set(key, {
1539
- ...value,
1540
- ...object
1541
- });
1542
- state.managers.row.update(key);
1543
- }
1891
+ const item = data[index];
1892
+ const key = getValue(item, state.key);
1893
+ const existing = state.keys.original.indexOf(key);
1894
+ if (existing === -1) continue;
1895
+ Object.assign(state.values.array[existing], item);
1896
+ updated.push(state.values.array[existing]);
1897
+ if (render && state.managers.render.visible.keys.has(key)) state.managers.row.update(key);
1544
1898
  }
1899
+ if (updated.length > 0) state.managers.event.emit(EVENT_DATA_UPDATE, updated);
1545
1900
  }
1546
1901
  };
1902
+ //#endregion
1903
+ //#region node_modules/@oscarpalmer/toretto/dist/event/delegation.mjs
1547
1904
  function addDelegatedHandler(doc, type, name, passive) {
1548
1905
  if (DELEGATED.has(name)) return;
1549
1906
  DELEGATED.add(name);
@@ -1595,11 +1952,11 @@ function removeDelegatedListener(target, name, listener) {
1595
1952
  if (handlers.size === 0) target[name] = void 0;
1596
1953
  return true;
1597
1954
  }
1598
- var DELEGATED = /* @__PURE__ */ new Set();
1599
- var EVENT_PREFIX = "@";
1600
- var EVENT_SUFFIX_ACTIVE = ":active";
1601
- var EVENT_SUFFIX_PASSIVE = ":passive";
1602
- var EVENT_TYPES = new Set([
1955
+ const DELEGATED = /* @__PURE__ */ new Set();
1956
+ const EVENT_PREFIX = "@";
1957
+ const EVENT_SUFFIX_ACTIVE = ":active";
1958
+ const EVENT_SUFFIX_PASSIVE = ":passive";
1959
+ const EVENT_TYPES = new Set([
1603
1960
  "beforeinput",
1604
1961
  "click",
1605
1962
  "dblclick",
@@ -1623,12 +1980,16 @@ var EVENT_TYPES = new Set([
1623
1980
  "touchmove",
1624
1981
  "touchstart"
1625
1982
  ]);
1626
- var HANDLER_ACTIVE = delegatedEventHandler.bind(false);
1627
- var HANDLER_PASSIVE = delegatedEventHandler.bind(true);
1983
+ const HANDLER_ACTIVE = delegatedEventHandler.bind(false);
1984
+ const HANDLER_PASSIVE = delegatedEventHandler.bind(true);
1985
+ //#endregion
1986
+ //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/function/misc.mjs
1628
1987
  /**
1629
1988
  * A function that does nothing, which can be useful, I guess…
1630
1989
  */
1631
1990
  function noop() {}
1991
+ //#endregion
1992
+ //#region node_modules/@oscarpalmer/toretto/dist/event/index.mjs
1632
1993
  function createEventOptions(options) {
1633
1994
  return {
1634
1995
  capture: getBoolean(options?.capture),
@@ -1668,6 +2029,8 @@ function on(target, type, listener, options) {
1668
2029
  target.removeEventListener(type, listener, extended);
1669
2030
  };
1670
2031
  }
2032
+ //#endregion
2033
+ //#region node_modules/@oscarpalmer/toretto/dist/find/relative.mjs
1671
2034
  function findAncestor(origin, selector) {
1672
2035
  const element = getElement(origin);
1673
2036
  if (element == null || selector == null) return null;
@@ -1688,32 +2051,53 @@ function getElement(origin) {
1688
2051
  if (origin instanceof Element) return origin;
1689
2052
  return origin instanceof Event && origin.target instanceof Element ? origin.target : void 0;
1690
2053
  }
2054
+ //#endregion
2055
+ //#region src/managers/event.manager.ts
1691
2056
  var EventManager = class {
2057
+ events = {};
2058
+ handlers = {
2059
+ subscribe: (name, callback) => this.subscribe(name, callback),
2060
+ unsubscribe: (name, callback) => this.unsubscribe(name, callback)
2061
+ };
1692
2062
  constructor(state) {
1693
2063
  this.state = state;
1694
2064
  mapped$1.set(state.element, this);
1695
2065
  }
2066
+ emit(name, ...parameters) {
2067
+ if (this.events[name] == null) return;
2068
+ const handlers = [...this.events[name]];
2069
+ const { length } = handlers;
2070
+ for (let index = 0; index < length; index += 1) handlers[index](...parameters);
2071
+ }
1696
2072
  destroy() {
1697
2073
  mapped$1.delete(this.state.element);
1698
2074
  this.state = void 0;
1699
2075
  }
1700
2076
  onSort(event, target) {
1701
- const direction = target.getAttribute("data-sort-direction");
1702
- const field = target.getAttribute("data-field");
1703
- if (field != null) this.state.managers.sort.toggle(event, field, direction);
2077
+ const direction = target.getAttribute(ATTRIBUTE_DATA_SORT_DIRECTION);
2078
+ const key = target.getAttribute(ATTRIBUTE_DATA_KEY);
2079
+ if (key != null) this.state.managers.sort.toggle(event, key, direction);
2080
+ }
2081
+ subscribe(name, callback) {
2082
+ if (!isEvent(name) || typeof callback !== "function") return;
2083
+ this.events[name] ??= /* @__PURE__ */ new Set();
2084
+ this.events[name].add(callback);
2085
+ }
2086
+ unsubscribe(name, callback) {
2087
+ if (isEvent(name) && typeof callback === "function") this.events[name]?.delete(callback);
1704
2088
  }
1705
2089
  };
1706
2090
  function onClick(event) {
1707
- const target = findAncestor(event, "[data-event]");
1708
- const table = findAncestor(event, ".tabela");
2091
+ const target = findAncestor(event, eventAttribute);
2092
+ const table = findAncestor(event, tableClassName);
1709
2093
  if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
1710
2094
  const manager = mapped$1.get(table);
1711
2095
  if (manager == null) return;
1712
- switch (target?.getAttribute("data-event")) {
1713
- case "group":
2096
+ switch (target?.getAttribute(ATTRIBUTE_DATA_EVENT)) {
2097
+ case EVENT_GROUP:
1714
2098
  manager.state.managers.group.handle(target);
1715
2099
  break;
1716
- case "heading":
2100
+ case EVENT_HEADING:
1717
2101
  manager.onSort(event, target);
1718
2102
  break;
1719
2103
  case "row":
@@ -1723,21 +2107,24 @@ function onClick(event) {
1723
2107
  }
1724
2108
  }
1725
2109
  function onKeydown(event) {
1726
- const target = findAncestor(event, "[data-event]");
1727
- const table = findAncestor(event, ".tabela");
2110
+ const target = findAncestor(event, eventAttribute);
2111
+ const table = findAncestor(event, tableClassName);
1728
2112
  if (!(target instanceof HTMLElement) || !(table instanceof HTMLElement)) return;
1729
2113
  const manager = mapped$1.get(table);
1730
2114
  if (manager == null) return;
1731
- switch (target?.getAttribute("data-event")) {
1732
- case "body":
1733
- manager.state.managers.navigation.handle(event);
1734
- break;
1735
- default: break;
2115
+ if (event.key === " ") {
2116
+ event.preventDefault();
2117
+ return;
1736
2118
  }
2119
+ manager.state.managers.navigation.handle(event);
1737
2120
  }
2121
+ const eventAttribute = `[${ATTRIBUTE_DATA_EVENT}]`;
1738
2122
  const mapped$1 = /* @__PURE__ */ new WeakMap();
2123
+ const tableClassName = `.${CSS_TABLE}`;
1739
2124
  on(document, "click", onClick);
1740
2125
  on(document, "keydown", onKeydown, { passive: false });
2126
+ //#endregion
2127
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/number.mjs
1741
2128
  /**
1742
2129
  * Clamp a number between a minimum and maximum value
1743
2130
  * @param value Value to clamp
@@ -1775,20 +2162,24 @@ function getNumber(value) {
1775
2162
  if (isBinary || EXPRESSION_OCTAL.test(trimmed)) return Number.parseInt(trimmed.slice(2), isBinary ? 2 : OCTAL_VALUE);
1776
2163
  return Number(EXPRESSION_HEX.test(trimmed) ? trimmed : trimmed.replace(EXPRESSION_UNDERSCORE, ""));
1777
2164
  }
1778
- var EXPRESSION_BINARY = /^0b[01]+$/i;
1779
- var EXPRESSION_HEX = /^0x[0-9a-f]+$/i;
1780
- var EXPRESSION_OCTAL = /^0o[0-7]+$/i;
1781
- var EXPRESSION_UNDERSCORE = /_/g;
1782
- var EXPRESSION_ZEROISH = /^\s*0+\s*$/;
1783
- var OCTAL_VALUE = 8;
2165
+ const EXPRESSION_BINARY = /^0b[01]+$/i;
2166
+ const EXPRESSION_HEX = /^0x[0-9a-f]+$/i;
2167
+ const EXPRESSION_OCTAL = /^0o[0-7]+$/i;
2168
+ const EXPRESSION_UNDERSCORE = /_/g;
2169
+ const EXPRESSION_ZEROISH = /^\s*0+\s*$/;
2170
+ const OCTAL_VALUE = 8;
2171
+ //#endregion
2172
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/sized.mjs
1784
2173
  function getSizedMaximum(first, second) {
1785
2174
  let actual;
1786
2175
  if (typeof first === "number") actual = first;
1787
2176
  else actual = typeof second === "number" ? second : MAXIMUM_DEFAULT;
1788
2177
  return clamp(actual, 1, MAXIMUM_ABSOLUTE);
1789
2178
  }
1790
- var MAXIMUM_ABSOLUTE = 16777216;
1791
- var MAXIMUM_DEFAULT = 1048576;
2179
+ const MAXIMUM_ABSOLUTE = 16777216;
2180
+ const MAXIMUM_DEFAULT = 1048576;
2181
+ //#endregion
2182
+ //#region node_modules/@oscarpalmer/atoms/dist/sized/map.mjs
1792
2183
  /**
1793
2184
  * A Map with a maximum size
1794
2185
  *
@@ -1835,6 +2226,8 @@ var SizedMap = class extends Map {
1835
2226
  return super.set(key, value);
1836
2227
  }
1837
2228
  };
2229
+ //#endregion
2230
+ //#region node_modules/@oscarpalmer/atoms/dist/function/memoize.mjs
1838
2231
  var Memoized = class {
1839
2232
  #state;
1840
2233
  /**
@@ -1927,8 +2320,10 @@ function getMemoizationOptions(input) {
1927
2320
  function memoize(callback, options) {
1928
2321
  return new Memoized(callback, getMemoizationOptions(options));
1929
2322
  }
1930
- var DEFAULT_CACHE_SIZE = 1024;
1931
- var SEPARATOR = "_";
2323
+ const DEFAULT_CACHE_SIZE = 1024;
2324
+ const SEPARATOR = "_";
2325
+ //#endregion
2326
+ //#region node_modules/@oscarpalmer/atoms/dist/string/match.mjs
1932
2327
  /**
1933
2328
  * Check if a string ends with a specified substring
1934
2329
  * @param haystack String to look in
@@ -1967,10 +2362,12 @@ function matchCallback(haystack, needle, ignoreCase) {
1967
2362
  function startsWith(haystack, needle, ignoreCase) {
1968
2363
  return match(MATCH_STARTS_WITH, haystack, needle, ignoreCase === true);
1969
2364
  }
1970
- var MATCH_ENDS_WITH = "endsWith";
1971
- var MATCH_INCLUDES = "includes";
1972
- var MATCH_STARTS_WITH = "startsWith";
1973
- var matchMemoizers = {};
2365
+ const MATCH_ENDS_WITH = "endsWith";
2366
+ const MATCH_INCLUDES = "includes";
2367
+ const MATCH_STARTS_WITH = "startsWith";
2368
+ const matchMemoizers = {};
2369
+ //#endregion
2370
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/value/equal.mjs
1974
2371
  function equal(first, second, options) {
1975
2372
  return equalValue(first, second, getEqualOptions(options));
1976
2373
  }
@@ -2136,32 +2533,48 @@ function getEqualOptions(input) {
2136
2533
  options.relaxedNullish = input.relaxedNullish === true;
2137
2534
  return options;
2138
2535
  }
2139
- var ARRAY_PEEK_PERCENTAGE = 10;
2140
- var ARRAY_THRESHOLD = 100;
2141
- var ERROR_PROPERTIES = ["name", "message"];
2142
- var EXPRESSION_PROPERTIES = ["source", "flags"];
2536
+ const ARRAY_PEEK_PERCENTAGE = 10;
2537
+ const ARRAY_THRESHOLD = 100;
2538
+ const ERROR_PROPERTIES = ["name", "message"];
2539
+ const EXPRESSION_PROPERTIES = ["source", "flags"];
2540
+ //#endregion
2541
+ //#region src/models/filter.model.ts
2542
+ const FILTER_CONTAINS = "contains";
2543
+ const FILTER_ENDS_WITH = "ends-with";
2544
+ const FILTER_EQUALS = "equals";
2545
+ const FILTER_GREATER_THAN = "greater-than";
2546
+ const FILTER_GREATER_THAN_OR_EQUAL = "greater-than-or-equal";
2547
+ const FILTER_LESS_THAN = "less-than";
2548
+ const FILTER_LESS_THAN_OR_EQUAL = "less-than-or-equal";
2549
+ const FILTER_NOT_CONTAINS = "not-contains";
2550
+ const FILTER_NOT_EQUALS = "not-equals";
2551
+ const FILTER_STARTS_WITH = "starts-with";
2552
+ //#endregion
2553
+ //#region src/managers/filter.manager.ts
2143
2554
  var FilterManager = class {
2144
- handlers = Object.freeze({
2555
+ handlers = {
2145
2556
  add: (item) => this.add(item),
2146
2557
  clear: () => this.clear(),
2147
2558
  remove: (value) => this.remove(value),
2148
2559
  set: (items) => this.set(items)
2149
- });
2560
+ };
2150
2561
  items = {};
2151
2562
  constructor(state) {
2152
2563
  this.state = state;
2153
2564
  }
2154
2565
  add(item) {
2155
- if (this.items[item.field] == null) this.items[item.field] = [];
2156
- else if (this.items[item.field].findIndex((existing) => equal(existing, item)) !== -1) return;
2157
- this.items[item.field].push(item);
2566
+ const { items, state } = this;
2567
+ if (items[item.key] == null) items[item.key] = [];
2568
+ else if (items[item.key].findIndex((existing) => equal(existing, item)) > -1) return;
2569
+ items[item.key].push(item);
2570
+ state.managers.event.emit("filter:add", [item]);
2158
2571
  this.filter();
2159
2572
  }
2160
2573
  clear() {
2161
- if (Object.keys(this.items).length > 0) {
2162
- this.items = {};
2163
- this.filter();
2164
- }
2574
+ if (Object.keys(this.items).length === 0) return;
2575
+ this.items = {};
2576
+ this.state.managers.event.emit("filter:clear");
2577
+ this.filter();
2165
2578
  }
2166
2579
  destroy() {
2167
2580
  this.handlers = void 0;
@@ -2172,39 +2585,51 @@ var FilterManager = class {
2172
2585
  const { state } = this;
2173
2586
  const filtered = [];
2174
2587
  const filters = Object.entries(this.items);
2175
- const keysLength = state.managers.data.values.keys.original.length;
2176
- rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
2177
- const key = state.managers.data.values.keys.original[keyIndex];
2178
- if (key instanceof GroupComponent) {
2179
- filtered.push(key);
2588
+ const itemsLength = state.managers.data.state.keys.original.length;
2589
+ rowLoop: for (let itemIndex = 0; itemIndex < itemsLength; itemIndex += 1) {
2590
+ const item = state.managers.data.state.keys.original[itemIndex];
2591
+ if (isGroupKey(item)) {
2592
+ filtered.push(item);
2180
2593
  continue;
2181
2594
  }
2182
- const row = state.managers.data.values.objects.mapped.get(key);
2595
+ const row = state.managers.data.state.values.mapped.get(item);
2183
2596
  if (row == null) continue;
2184
2597
  filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
2185
- const [field, items] = filters[filterIndex];
2186
- const value = row[field];
2598
+ const [key, items] = filters[filterIndex];
2599
+ const value = row[key];
2187
2600
  for (let itemIndex = 0; itemIndex < items.length; itemIndex += 1) {
2188
2601
  const filter = items[itemIndex];
2189
2602
  if (comparators[filter.comparison](value, filter.value)) continue filterLoop;
2190
2603
  }
2191
2604
  continue rowLoop;
2192
2605
  }
2193
- filtered.push(key);
2606
+ filtered.push(item);
2194
2607
  }
2195
- state.managers.data.values.keys.active = filtered;
2608
+ state.managers.data.state.keys.active = filtered;
2196
2609
  if (state.managers.sort.items.length > 0) state.managers.sort.sort();
2197
2610
  else state.managers.render.update(true, true);
2198
2611
  }
2199
2612
  remove(value) {
2613
+ const removed = [];
2200
2614
  if (typeof value === "string") {
2201
2615
  if (this.items[value] == null) return;
2202
- this.items = {};
2616
+ const keyed = {};
2617
+ const keys = Object.keys(this.items);
2618
+ const { length } = keys;
2619
+ for (let index = 0; index < length; index += 1) {
2620
+ const key = keys[index];
2621
+ if (key === value) removed.push(...this.items[key]);
2622
+ else keyed[key] = this.items[key];
2623
+ }
2624
+ this.items = keyed;
2203
2625
  } else {
2204
- const { field } = value;
2205
- if (this.items[field] == null) return;
2206
- if (this.items[field].findIndex((item) => equal(item, value)) === -1) return;
2626
+ const { key } = value;
2627
+ if (this.items[key] == null) return;
2628
+ const index = this.items[key].findIndex((item) => equal(item, value));
2629
+ if (index === -1) return;
2630
+ removed.push(this.items[key][index]);
2207
2631
  }
2632
+ this.state.managers.event.emit("filter:remove", removed);
2208
2633
  this.filter();
2209
2634
  }
2210
2635
  set(items) {
@@ -2212,74 +2637,111 @@ var FilterManager = class {
2212
2637
  const { length } = items;
2213
2638
  for (let index = 0; index < length; index += 1) {
2214
2639
  const item = items[index];
2215
- keyed[item.field] ??= [];
2216
- keyed[item.field].push(item);
2640
+ keyed[item.key] ??= [];
2641
+ keyed[item.key].push(item);
2217
2642
  }
2218
2643
  this.items = keyed;
2219
2644
  this.filter();
2220
2645
  }
2221
2646
  };
2222
2647
  const comparators = {
2223
- contains: (row, filter) => includes(getString(row), getString(filter), true),
2224
- "ends-with": (row, filter) => endsWith(getString(row), getString(filter), true),
2225
- equals: (row, filter) => equalizer(row, filter),
2226
- "greater-than": (row, filter) => getNumber(row) > getNumber(filter),
2227
- "greater-than-or-equal": (row, filter) => getNumber(row) >= getNumber(filter),
2228
- "less-than": (row, filter) => getNumber(row) < getNumber(filter),
2229
- "less-than-or-equal": (row, filter) => getNumber(row) <= getNumber(filter),
2230
- "not-contains": (row, filter) => !includes(getString(row), getString(filter), true),
2231
- "not-equals": (row, filter) => !equalizer(row, filter),
2232
- "starts-with": (row, filter) => startsWith(getString(row), getString(filter), true)
2648
+ [FILTER_CONTAINS]: (row, filter) => includes(getString(row), getString(filter), true),
2649
+ [FILTER_ENDS_WITH]: (row, filter) => endsWith(getString(row), getString(filter), true),
2650
+ [FILTER_EQUALS]: (row, filter) => equalizer(row, filter),
2651
+ [FILTER_GREATER_THAN]: (row, filter) => getNumber(row) > getNumber(filter),
2652
+ [FILTER_GREATER_THAN_OR_EQUAL]: (row, filter) => getNumber(row) >= getNumber(filter),
2653
+ [FILTER_LESS_THAN]: (row, filter) => getNumber(row) < getNumber(filter),
2654
+ [FILTER_LESS_THAN_OR_EQUAL]: (row, filter) => getNumber(row) <= getNumber(filter),
2655
+ [FILTER_NOT_CONTAINS]: (row, filter) => !includes(getString(row), getString(filter), true),
2656
+ [FILTER_NOT_EQUALS]: (row, filter) => !equalizer(row, filter),
2657
+ [FILTER_STARTS_WITH]: (row, filter) => startsWith(getString(row), getString(filter), true)
2233
2658
  };
2234
2659
  const equalizer = equal.initialize({ ignoreCase: true });
2660
+ //#endregion
2661
+ //#region src/managers/group.manager.ts
2235
2662
  var GroupManager = class {
2236
2663
  collapsed = /* @__PURE__ */ new Set();
2237
2664
  enabled = false;
2238
- field;
2665
+ key;
2666
+ handlers = { set: (group) => {
2667
+ if (group === this.key) return;
2668
+ this.enabled = !isNullableOrWhitespace(group);
2669
+ this.key = group ?? "";
2670
+ this.state.managers.data.set(this.state.managers.data.get());
2671
+ } };
2239
2672
  items = [];
2673
+ mapped = /* @__PURE__ */ new Map();
2240
2674
  order = {};
2241
2675
  constructor(state) {
2242
2676
  this.state = state;
2243
2677
  if (isNullableOrWhitespace(state.options.grouping)) return;
2244
2678
  this.enabled = true;
2245
- this.field = state.options.grouping;
2679
+ this.key = state.options.grouping;
2246
2680
  }
2247
- add(group) {
2681
+ add(group, emit) {
2248
2682
  this.set([...this.items, group]);
2683
+ if (emit) this.state.managers.event.emit(EVENT_GROUP_ADD, [getGroup(group)]);
2684
+ }
2685
+ clear() {
2686
+ if (this.items.length === 0) return;
2687
+ const groups = this.items.splice(0);
2688
+ const { length } = groups;
2689
+ for (let index = 0; index < length; index += 1) this.remove(groups[index], false);
2690
+ this.collapsed.clear();
2691
+ this.set([]);
2692
+ this.state.managers.event.emit(EVENT_GROUP_CLEAR);
2693
+ }
2694
+ destroy() {
2695
+ const groups = this.items.splice(0);
2696
+ const { length } = groups;
2697
+ for (let index = 0; index < length; index += 1) removeGroup(groups[index]);
2698
+ this.collapsed.clear();
2699
+ this.handlers = void 0;
2700
+ this.state = void 0;
2701
+ }
2702
+ getForKey(key) {
2703
+ return this.mapped.get(key);
2249
2704
  }
2250
- get(value) {
2251
- return this.items.find((item) => item.value === value);
2705
+ getForValue(value) {
2706
+ const asString = getString(value);
2707
+ return this.items.find((item) => item.value.stringified === asString);
2252
2708
  }
2253
2709
  handle(button) {
2254
- const key = button.dataset.key;
2255
- const group = this.get(key);
2710
+ const key = button.dataset.key?.replace(`${this.state.prefix}_`, "");
2711
+ const group = this.getForKey(key ?? "");
2256
2712
  if (group == null) return;
2257
2713
  const { collapsed, items, state } = this;
2258
2714
  group.expanded = !group.expanded;
2259
2715
  const index = items.indexOf(group);
2260
- let first = state.managers.data.values.keys.original.indexOf(items[index]) + 1;
2261
- const last = items[index + 1] == null ? state.managers.data.keys.length - 1 : state.managers.data.values.keys.original.indexOf(items[index + 1]) - 1;
2716
+ let first = state.managers.data.state.keys.original.indexOf(group.key) + 1;
2717
+ const last = items[index + 1] == null ? state.managers.data.state.keys.original.length - 1 : state.managers.data.state.keys.original.indexOf(items[index + 1].key) - 1;
2262
2718
  for (; first <= last; first += 1) {
2263
- const key = state.managers.data.values.keys.original[first];
2719
+ const key = state.managers.data.state.keys.original[first];
2264
2720
  if (group.expanded) collapsed.delete(key);
2265
2721
  else collapsed.add(key);
2266
2722
  }
2267
- state.managers.render.update(true, true);
2723
+ state.managers.event.emit(EVENT_GROUP_TOGGLE, {
2724
+ collapsed: group.expanded ? [] : [getGroup(group)],
2725
+ expanded: group.expanded ? [getGroup(group)] : []
2726
+ });
2727
+ if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
2728
+ else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
2729
+ else state.managers.render.update(true, true);
2268
2730
  }
2269
- remove(group) {
2731
+ remove(group, update) {
2732
+ removeGroup(group);
2733
+ if (!update) return;
2270
2734
  this.set(this.items.filter((item) => item !== group));
2735
+ this.state.managers.event.emit(EVENT_GROUP_REMOVE, [getGroup(group)]);
2271
2736
  }
2272
2737
  set(items) {
2273
- this.items = sort(items, (item) => item.label);
2274
- this.order = toRecord(items, "value", (_, index) => index);
2738
+ this.items = sort(items, (first, second) => compare(first.label, second.label));
2739
+ this.mapped = toMap(items, (group) => group.key);
2740
+ this.order = toRecord(items, (group) => group.value.stringified, (_, index) => index);
2275
2741
  }
2276
2742
  };
2277
- function getKey(value) {
2278
- if (typeof value === "number") return value;
2279
- if (typeof value !== "string") return;
2280
- return integerExpression.test(value) ? Number.parseInt(value, 10) : value;
2281
- }
2282
- const integerExpression = /^\d+$/;
2743
+ //#endregion
2744
+ //#region src/managers/navigation.manager.ts
2283
2745
  var NavigationManager = class {
2284
2746
  active;
2285
2747
  constructor(state) {
@@ -2291,64 +2753,70 @@ var NavigationManager = class {
2291
2753
  handle(event) {
2292
2754
  if (!allKeys.has(event.key)) return;
2293
2755
  event.preventDefault();
2294
- const { components, id, managers } = this.state;
2295
- const activeDescendant = components.body.elements.group.getAttribute("aria-activedescendant");
2756
+ const { components, managers } = this.state;
2757
+ const activeDescendant = components.body.elements.group.getAttribute(ARIA_ACTIVEDESCENDANT);
2296
2758
  const { keys } = managers.data;
2297
2759
  const { length } = keys;
2298
2760
  let next;
2299
2761
  if (isNullableOrWhitespace(activeDescendant)) next = getDefaultIndex(event.key, length);
2300
- else next = getIndex(event, activeDescendant, id, keys);
2762
+ else next = getIndex(this.state, event, activeDescendant);
2301
2763
  if (next != null) this.setActive(keys.at(next));
2302
2764
  }
2303
- setActive(key, scroll) {
2304
- const { components, managers, options } = this.state;
2305
- this.active = key;
2306
- const active = components.body.elements.group.querySelectorAll("[data-active=\"true\"]");
2307
- for (const item of active) item.setAttribute("data-active", "false");
2308
- const row = managers.row.get(key);
2309
- if (row != null) {
2310
- row.element?.setAttribute("data-active", "true");
2311
- if (scroll ?? true) if (row.element == null) components.body.elements.group.scrollTo({
2312
- top: managers.data.getIndex(key) * options.rowHeight,
2765
+ setActive(item, scroll) {
2766
+ const { components, managers, options, prefix } = this.state;
2767
+ this.active = item;
2768
+ const active = components.body.elements.group.querySelectorAll(attributeDataActiveTrue);
2769
+ for (const item of active) item.setAttribute(ATTRIBUTE_DATA_ACTIVE, "false");
2770
+ const component = isGroupKey(item) ? managers.group.getForKey(item) : managers.row.get(item, false);
2771
+ if (component != null) {
2772
+ component.element?.setAttribute(ATTRIBUTE_DATA_ACTIVE, "true");
2773
+ if (scroll ?? true) if (component.element == null) components.body.elements.group.scrollTo({
2774
+ top: managers.data.getIndex(item) * options.rowHeight,
2313
2775
  behavior: "smooth"
2314
2776
  });
2315
- else row.element.scrollIntoView({ block: "nearest" });
2777
+ else component.element.scrollIntoView({ block: "nearest" });
2316
2778
  }
2317
- components.body.elements.group.setAttribute("aria-activedescendant", row == null ? "" : `tabela_${this.state.id}_row_${key}`);
2779
+ components.body.elements.group.setAttribute(ARIA_ACTIVEDESCENDANT, component == null ? "" : `${prefix}${component.key}`);
2318
2780
  }
2319
2781
  };
2320
2782
  function getDefaultIndex(key, max) {
2321
2783
  switch (true) {
2322
2784
  case negativeDefaultKeys.has(key): return -1;
2323
- case key === "PageDown": return Math.min(9, max - 1);
2324
- case key === "PageUp": return max < 10 ? 0 : max - 10;
2785
+ case key === KEY_PAGE_DOWN: return Math.min(9, max - 1);
2786
+ case key === KEY_PAGE_UP: return max < 10 ? 0 : max - 10;
2325
2787
  default: return 0;
2326
2788
  }
2327
2789
  }
2328
- function getIndex(event, active, id, keys) {
2329
- const key = getKey(active.replace(`tabela_${id}_row_`, ""));
2790
+ function getIndex(state, event, active) {
2791
+ const key = getKey(active.replace(state.prefix, ""));
2330
2792
  if (key == null) return;
2331
- if (absoluteKeys.has(event.key)) return event.key === "Home" ? 0 : keys.length - 1;
2332
- return clamp(keys.indexOf(key) + getOffset(event.key), 0, keys.length - 1, true);
2333
- }
2334
- function getOffset(key) {
2335
- switch (key) {
2336
- case "ArrowDown": return 1;
2337
- case "ArrowUp": return -1;
2338
- case "PageDown": return 10;
2339
- case "PageUp": return -10;
2340
- default: return 0;
2341
- }
2342
- }
2343
- const absoluteKeys = new Set(["End", "Home"]);
2344
- const arrowKeys = new Set(["ArrowDown", "ArrowUp"]);
2345
- const negativeDefaultKeys = new Set(["ArrowUp", "End"]);
2346
- const pageKeys = new Set(["PageDown", "PageUp"]);
2793
+ if (absoluteKeys.has(event.key)) return event.key === KEY_HOME ? 0 : state.managers.data.size - 1;
2794
+ return clamp(state.managers.data.getIndex(key) + (offset[event.key] ?? 0), 0, state.managers.data.size - 1, true);
2795
+ }
2796
+ const KEY_ARROW_DOWN = "ArrowDown";
2797
+ const KEY_ARROW_UP = "ArrowUp";
2798
+ const KEY_END = "End";
2799
+ const KEY_HOME = "Home";
2800
+ const KEY_PAGE_DOWN = "PageDown";
2801
+ const KEY_PAGE_UP = "PageUp";
2802
+ const absoluteKeys = new Set([KEY_END, KEY_HOME]);
2803
+ const arrowKeys = new Set([KEY_ARROW_DOWN, KEY_ARROW_UP]);
2804
+ const attributeDataActiveTrue = `[${ATTRIBUTE_DATA_ACTIVE}="true"]`;
2805
+ const negativeDefaultKeys = new Set([KEY_ARROW_UP, KEY_END]);
2806
+ const offset = {
2807
+ [KEY_ARROW_DOWN]: 1,
2808
+ [KEY_ARROW_UP]: -1,
2809
+ [KEY_PAGE_DOWN]: 10,
2810
+ [KEY_PAGE_UP]: -10
2811
+ };
2812
+ const pageKeys = new Set([KEY_PAGE_DOWN, KEY_PAGE_UP]);
2347
2813
  const allKeys = new Set([
2348
2814
  ...absoluteKeys,
2349
2815
  ...arrowKeys,
2350
2816
  ...pageKeys
2351
2817
  ]);
2818
+ //#endregion
2819
+ //#region src/components/row.component.ts
2352
2820
  function removeRow(pool, row) {
2353
2821
  if (row.element != null) {
2354
2822
  row.element.innerHTML = "";
@@ -2359,31 +2827,33 @@ function removeRow(pool, row) {
2359
2827
  row.cells = {};
2360
2828
  }
2361
2829
  function renderRow(state, row) {
2362
- const element = row.element ?? state.managers.render.pool.rows.shift() ?? createRow();
2830
+ const { managers, options, prefix } = state;
2831
+ const element = row.element ?? managers.render.pool.rows.shift() ?? createRow(options.rowHeight);
2363
2832
  row.element = element;
2364
2833
  element.innerHTML = "";
2365
- const selected = state.managers.selection.items.has(row.key);
2834
+ const selected = managers.selection.items.has(row.key);
2366
2835
  const key = String(row.key);
2367
2836
  setAttributes(element, {
2368
- "aria-selected": String(selected),
2369
- "data-active": String(state.managers.navigation.active === row.key),
2370
- "data-event": "row",
2371
- "data-key": key,
2372
- id: `tabela_${state.id}_row_${key}`
2837
+ [ARIA_SELECTED]: String(selected),
2838
+ [ATTRIBUTE_DATA_ACTIVE]: String(managers.navigation.active === row.key),
2839
+ [ATTRIBUTE_DATA_EVENT]: "row",
2840
+ [ATTRIBUTE_DATA_KEY]: key,
2841
+ id: `${prefix}${key}`
2373
2842
  });
2374
- element.classList.add("tabela__row--body");
2375
- if (selected) element.classList.add("tabela__row--selected");
2376
- else element.classList.remove("tabela__row--selected");
2377
- const columns = state.managers.column.items;
2843
+ element.classList.add(CSS_ROW_BODY);
2844
+ if (selected) element.classList.add(CSS_ROW_SELECTED);
2845
+ else element.classList.remove(CSS_ROW_SELECTED);
2846
+ const columns = managers.column.items;
2378
2847
  const { length } = columns;
2379
- const data = state.managers.data.values.objects.mapped.get(row.key);
2848
+ const data = managers.data.state.values.mapped.get(row.key);
2380
2849
  if (data == null) return;
2381
2850
  for (let index = 0; index < length; index += 1) {
2382
2851
  const { options } = columns[index];
2383
- state.managers.render.pool.cells[options.field] ??= [];
2384
- const cell = state.managers.render.pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
2385
- cell.textContent = String(data[options.field]);
2386
- row.cells[options.field] = cell;
2852
+ const { key, width } = options;
2853
+ managers.render.pool.cells[key] ??= [];
2854
+ const cell = managers.render.pool.cells[key].shift() ?? createCell(width);
2855
+ cell.textContent = String(getValue(data, key));
2856
+ row.cells[key] = cell;
2387
2857
  element.append(cell);
2388
2858
  }
2389
2859
  }
@@ -2394,17 +2864,21 @@ var RowComponent = class {
2394
2864
  this.key = key;
2395
2865
  }
2396
2866
  };
2867
+ //#endregion
2868
+ //#region src/managers/render.manager.ts
2397
2869
  function getRange(state, down) {
2398
- const { components, managers, options } = state;
2399
- const { clientHeight, scrollTop } = components.body.elements.group;
2870
+ const { element, managers, options } = state;
2871
+ const { clientHeight, scrollTop } = element;
2400
2872
  const { keys } = managers.data;
2401
- const first = Math.floor(scrollTop / options.rowHeight);
2402
- const last = Math.min(keys.length - managers.group.collapsed.size - 1, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
2403
- const before = Math.ceil(clientHeight / options.rowHeight) * (down ? 1 : 2);
2404
- const after = Math.ceil(clientHeight / options.rowHeight) * (down ? 2 : 1);
2405
- const start = Math.max(0, first - before);
2873
+ const firstIndex = Math.floor(scrollTop / options.rowHeight);
2874
+ const lastIndex = keys.length - managers.group.collapsed.size - 1;
2875
+ const last = Math.min(lastIndex, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
2876
+ const visible = clientHeight / options.rowHeight;
2877
+ const before = Math.ceil(visible) * (down ? 1 : 2);
2878
+ const after = Math.ceil(visible) * (down ? 2 : 1);
2879
+ const start = Math.max(0, firstIndex - before);
2406
2880
  return {
2407
- end: Math.min(keys.length - managers.group.collapsed.size - 1, last + after),
2881
+ end: Math.min(lastIndex, last + after),
2408
2882
  start
2409
2883
  };
2410
2884
  }
@@ -2412,7 +2886,7 @@ function onScroll() {
2412
2886
  const { state } = this;
2413
2887
  if (!state.active) {
2414
2888
  requestAnimationFrame(() => {
2415
- const top = state.components.body.elements.group.scrollTop;
2889
+ const top = state.element.scrollTop;
2416
2890
  this.update(top > state.top);
2417
2891
  state.active = false;
2418
2892
  state.top = top;
@@ -2428,9 +2902,12 @@ var RenderManager = class {
2428
2902
  rows: []
2429
2903
  };
2430
2904
  state;
2431
- visible = /* @__PURE__ */ new Map();
2905
+ visible = {
2906
+ indiced: /* @__PURE__ */ new Map(),
2907
+ keys: /* @__PURE__ */ new Set()
2908
+ };
2432
2909
  constructor(state) {
2433
- this.listener = on(state.components.body.elements.group, "scroll", onScroll.bind(this));
2910
+ this.listener = on(state.element, "scroll", onScroll.bind(this));
2434
2911
  this.state = {
2435
2912
  ...state,
2436
2913
  active: false,
@@ -2440,7 +2917,13 @@ var RenderManager = class {
2440
2917
  destroy() {
2441
2918
  const { listener, pool, visible } = this;
2442
2919
  listener();
2443
- visible.clear();
2920
+ visible.indiced.clear();
2921
+ visible.keys.clear();
2922
+ const cells = Object.values(pool.cells).flat();
2923
+ let { length } = cells;
2924
+ for (let index = 0; index < length; index += 1) cells[index].remove();
2925
+ length = pool.rows.length;
2926
+ for (let index = 0; index < length; index += 1) pool.rows[index].remove();
2444
2927
  pool.cells = {};
2445
2928
  pool.rows = [];
2446
2929
  this.fragment = void 0;
@@ -2449,18 +2932,18 @@ var RenderManager = class {
2449
2932
  this.state = void 0;
2450
2933
  this.visible = void 0;
2451
2934
  }
2452
- removeCells(fields) {
2935
+ removeCells(keys) {
2453
2936
  const { pool, state, visible } = this;
2454
- const { length } = fields;
2455
- for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
2456
- for (const [, key] of visible) {
2457
- if (key instanceof GroupComponent) continue;
2458
- const row = state.managers.row.get(key);
2937
+ const { length } = keys;
2938
+ for (let index = 0; index < length; index += 1) delete pool.cells[keys[index]];
2939
+ for (const [, key] of visible.indiced) {
2940
+ if (isGroupKey(key)) continue;
2941
+ const row = state.managers.row.get(key, false);
2459
2942
  if (row == null || row.element == null) continue;
2460
2943
  for (let index = 0; index < length; index += 1) {
2461
- row.cells[fields[index]].innerHTML = "";
2462
- row.cells[fields[index]].remove();
2463
- delete row.cells[fields[index]];
2944
+ row.cells[keys[index]].innerHTML = "";
2945
+ row.cells[keys[index]].remove();
2946
+ delete row.cells[keys[index]];
2464
2947
  }
2465
2948
  }
2466
2949
  }
@@ -2477,17 +2960,19 @@ var RenderManager = class {
2477
2960
  const range = getRange(state, down);
2478
2961
  for (let index = range.start; index <= range.end; index += 1) indices.add(index);
2479
2962
  let remove = rerender ?? false;
2480
- for (const [index, key] of visible) {
2481
- if (key instanceof GroupComponent) {
2963
+ for (const [index, key] of visible.indiced) {
2964
+ if (isGroupKey(key)) {
2482
2965
  if (remove || !indices.has(index)) {
2483
- visible.delete(index);
2484
- key.element?.remove();
2966
+ visible.indiced.delete(index);
2967
+ visible.keys.delete(key);
2968
+ state.managers.group.getForKey(key)?.element?.remove();
2485
2969
  }
2486
2970
  continue;
2487
2971
  }
2488
- const row = managers.row.get(key);
2972
+ const row = managers.row.get(key, false);
2489
2973
  if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
2490
- visible.delete(index);
2974
+ visible.indiced.delete(index);
2975
+ visible.keys.delete(key);
2491
2976
  if (row != null) removeRow(pool, row);
2492
2977
  }
2493
2978
  }
@@ -2496,19 +2981,22 @@ var RenderManager = class {
2496
2981
  let count = 0;
2497
2982
  let offset = 0;
2498
2983
  for (let index = range.start; index <= range.end + offset; index += 1) {
2499
- if (visible.has(index)) continue;
2984
+ if (visible.indiced.has(index)) continue;
2500
2985
  const key = keys[index];
2501
- if (key instanceof GroupComponent) {
2986
+ if (isGroupKey(key)) {
2987
+ const group = managers.group.getForKey(key);
2988
+ if (group == null) continue;
2502
2989
  count += 1;
2503
- renderGroup(state, key);
2504
- visible.set(index, key);
2505
- if (key.element != null) {
2506
- key.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
2507
- fragment.append(key.element);
2990
+ renderGroup(state, group);
2991
+ visible.indiced.set(index, group.key);
2992
+ visible.keys.add(group.key);
2993
+ if (group.element != null) {
2994
+ group.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
2995
+ fragment.append(group.element);
2508
2996
  }
2509
2997
  continue;
2510
2998
  }
2511
- const row = managers.row.get(key);
2999
+ const row = managers.row.get(key, true);
2512
3000
  if (row == null) continue;
2513
3001
  if (managers.group.collapsed.has(key)) {
2514
3002
  offset += 1;
@@ -2516,31 +3004,40 @@ var RenderManager = class {
2516
3004
  }
2517
3005
  count += 1;
2518
3006
  renderRow(state, row);
2519
- visible.set(index, key);
3007
+ visible.indiced.set(index, key);
3008
+ visible.keys.add(key);
2520
3009
  if (row.element != null) {
2521
3010
  row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
2522
3011
  fragment.append(row.element);
2523
3012
  }
2524
3013
  }
2525
- if (count > 0) components.body.elements.group[down ? "append" : "prepend"](fragment);
3014
+ if (count === 0) return;
3015
+ if (down) components.body.elements.group.append(fragment);
3016
+ else components.body.elements.group.prepend(fragment);
2526
3017
  }
2527
3018
  };
3019
+ //#endregion
3020
+ //#region src/managers/row.manager.ts
2528
3021
  var RowManager = class {
2529
3022
  components = /* @__PURE__ */ new Map();
2530
3023
  constructor(state) {
2531
3024
  this.state = state;
2532
3025
  }
3026
+ clear() {
3027
+ const { components } = this;
3028
+ const rows = [...components.values()];
3029
+ const { length } = rows;
3030
+ for (let index = 0; index < length; index += 1) this.removeRow(rows[index]);
3031
+ components.clear();
3032
+ }
2533
3033
  destroy() {
2534
- const components = [...this.components.values()];
2535
- const { length } = components;
2536
- for (let index = 0; index < length; index += 1) removeRow(this.state.managers.render.pool, components[index]);
2537
- this.components.clear();
3034
+ this.clear();
2538
3035
  this.components = void 0;
2539
3036
  this.state = void 0;
2540
3037
  }
2541
- get(key) {
3038
+ get(key, create) {
2542
3039
  let row = this.components.get(key);
2543
- if (row == null) {
3040
+ if (row == null && create) {
2544
3041
  row = new RowComponent(key);
2545
3042
  this.components.set(key, row);
2546
3043
  }
@@ -2551,28 +3048,33 @@ var RowManager = class {
2551
3048
  }
2552
3049
  remove(key) {
2553
3050
  const row = this.components.get(key);
2554
- if (row != null) {
2555
- removeRow(this.state.managers.render.pool, row);
2556
- this.components.delete(key);
2557
- }
3051
+ if (row != null) this.removeRow(row);
3052
+ }
3053
+ removeRow(row) {
3054
+ if (row.element != null) removeRow(this.state.managers.render.pool, row);
3055
+ this.components.delete(row.key);
2558
3056
  }
2559
3057
  update(key) {
2560
3058
  const row = this.components.get(key);
2561
- if (row != null) renderRow(this.state, row);
3059
+ if (row?.element != null) renderRow(this.state, row);
2562
3060
  }
2563
3061
  };
2564
- const dragStyling = toggleStyles(document.body, {
3062
+ //#endregion
3063
+ //#region src/helpers/style.helper.ts
3064
+ const preventSelection = toggleStyles(document.body, {
2565
3065
  userSelect: "none",
2566
3066
  webkitUserSelect: "none"
2567
3067
  });
3068
+ //#endregion
3069
+ //#region src/managers/selection.manager.ts
2568
3070
  var SelectionManager = class {
2569
- handlers = Object.freeze({
3071
+ handlers = {
2570
3072
  add: (keys) => this.add(keys),
2571
3073
  clear: () => this.clear(),
2572
3074
  remove: (keys) => this.remove(keys),
2573
3075
  set: (keys) => this.set(keys),
2574
3076
  toggle: () => this.toggle()
2575
- });
3077
+ };
2576
3078
  items = /* @__PURE__ */ new Set();
2577
3079
  last;
2578
3080
  constructor(state) {
@@ -2605,7 +3107,7 @@ var SelectionManager = class {
2605
3107
  this.state = void 0;
2606
3108
  }
2607
3109
  handle(event, target) {
2608
- const key = getKey(target.getAttribute("data-key"));
3110
+ const key = getKey(target.getAttribute(ATTRIBUTE_DATA_KEY));
2609
3111
  if (key == null) return;
2610
3112
  const { items } = this;
2611
3113
  if (event.shiftKey) {
@@ -2625,8 +3127,8 @@ var SelectionManager = class {
2625
3127
  range(from, to) {
2626
3128
  const { state } = this;
2627
3129
  const keyed = isKey(from) && isKey(to);
2628
- const fromKey = keyed ? from : getKey(from.getAttribute("data-key"));
2629
- const toKey = keyed ? to : getKey(to.getAttribute("data-key"));
3130
+ const fromKey = keyed ? from : getKey(from.getAttribute(ATTRIBUTE_DATA_KEY));
3131
+ const toKey = keyed ? to : getKey(to.getAttribute(ATTRIBUTE_DATA_KEY));
2630
3132
  if (fromKey === toKey) return;
2631
3133
  const { keys } = state.managers.data;
2632
3134
  const fromIndex = state.managers.data.getIndex(fromKey);
@@ -2636,7 +3138,7 @@ var SelectionManager = class {
2636
3138
  const selected = [];
2637
3139
  for (let index = start; index <= end; index += 1) {
2638
3140
  const key = keys[index];
2639
- if (!(key instanceof GroupComponent)) selected.push(key);
3141
+ if (!isGroupKey(key)) selected.push(key);
2640
3142
  }
2641
3143
  if (keyed) this.add(selected);
2642
3144
  else this.set(selected);
@@ -2664,9 +3166,10 @@ var SelectionManager = class {
2664
3166
  const { items, state } = this;
2665
3167
  const { keys } = state.managers.data;
2666
3168
  if (items.size === keys.length - state.managers.group.items.length) this.clear();
2667
- else this.set(keys.filter((key) => !(key instanceof GroupComponent)));
3169
+ else this.set(keys.filter((key) => !isGroupKey(key)));
2668
3170
  }
2669
3171
  update(removed) {
3172
+ const { state } = this;
2670
3173
  const items = [...removed.map((key) => ({
2671
3174
  key,
2672
3175
  removed: true
@@ -2674,28 +3177,28 @@ var SelectionManager = class {
2674
3177
  key,
2675
3178
  removed: false
2676
3179
  }))];
2677
- const { length } = items;
3180
+ let { length } = items;
2678
3181
  for (let index = 0; index < length; index += 1) {
2679
3182
  const { key, removed } = items[index];
2680
- const row = this.state.managers.row.get(key);
2681
- if (row == null || row.element == null) continue;
2682
- setAttribute(row.element, "aria-selected", String(!removed));
2683
- if (removed) row.element.classList.remove("tabela__row--selected");
2684
- else row.element.classList.add("tabela__row--selected");
3183
+ const element = state.managers.row.get(key, false)?.element;
3184
+ if (element == null) continue;
3185
+ setAttribute(element, ARIA_SELECTED, String(!removed));
3186
+ if (removed) element.classList.remove(CSS_ROW_SELECTED);
3187
+ else element.classList.add(CSS_ROW_SELECTED);
2685
3188
  }
2686
3189
  }
2687
3190
  };
2688
3191
  function getPlaceholder() {
2689
- placeholder ??= createElement("div", { className: "tabela__selection--placeholder" }, {}, {});
3192
+ placeholder ??= createElement("div", { className: CSS_SELECTION });
2690
3193
  return placeholder;
2691
3194
  }
2692
3195
  function onMouseDown(event) {
2693
3196
  if (shifted) {
2694
- const row = findAncestor(event.target, ".tabela__row--body");
3197
+ const row = findAncestor(event.target, `.${CSS_ROW_BODY}`);
2695
3198
  if (!(row instanceof HTMLElement)) return;
2696
3199
  startElement = row;
2697
3200
  startPosition = getPosition(event);
2698
- dragStyling.set();
3201
+ preventSelection.set();
2699
3202
  }
2700
3203
  }
2701
3204
  function onMouseMove(event) {
@@ -2716,14 +3219,14 @@ function onMouseUp(event) {
2716
3219
  if (startElement == null) return;
2717
3220
  if (!event.shiftKey) {
2718
3221
  shifted = false;
2719
- dragStyling.remove();
3222
+ preventSelection.remove();
2720
3223
  }
2721
3224
  getPlaceholder().remove();
2722
- const row = findAncestor(event.target, ".tabela__row--body");
3225
+ const row = findAncestor(event.target, bodyRowSelector);
2723
3226
  if (row instanceof HTMLElement) {
2724
3227
  endElement = row;
2725
- const endTable = findAncestor(endElement, ".tabela");
2726
- const startTable = findAncestor(startElement, ".tabela");
3228
+ const endTable = findAncestor(endElement, tableSelector);
3229
+ const startTable = findAncestor(startElement, tableSelector);
2727
3230
  if (startTable != null && startTable === endTable) mapped.get(startTable)?.range(startElement, endElement);
2728
3231
  }
2729
3232
  endElement = void 0;
@@ -2731,7 +3234,7 @@ function onMouseUp(event) {
2731
3234
  startPosition = void 0;
2732
3235
  }
2733
3236
  function onShift(event, value) {
2734
- if (event.key === "Shift") shifted = value;
3237
+ if (event.key === KEY_SHIFT) shifted = value;
2735
3238
  }
2736
3239
  function onShiftDown(event) {
2737
3240
  onShift(event, true);
@@ -2739,7 +3242,10 @@ function onShiftDown(event) {
2739
3242
  function onShiftUp(event) {
2740
3243
  onShift(event, false);
2741
3244
  }
3245
+ const KEY_SHIFT = "Shift";
2742
3246
  const mapped = /* @__PURE__ */ new WeakMap();
3247
+ const bodyRowSelector = `.${CSS_ROW_BODY}`;
3248
+ const tableSelector = `.${CSS_TABLE}`;
2743
3249
  let shifted = false;
2744
3250
  let endElement;
2745
3251
  let placeholder;
@@ -2750,15 +3256,191 @@ on(document, "keyup", onShiftUp);
2750
3256
  on(document, "mousedown", onMouseDown);
2751
3257
  on(document, "mousemove", onMouseMove);
2752
3258
  on(document, "mouseup", onMouseUp);
3259
+ //#endregion
3260
+ //#region src/managers/style.manager.ts
3261
+ var StyleManager = class {
3262
+ constructor(state) {
3263
+ this.state = state;
3264
+ if (appended) return;
3265
+ appended = true;
3266
+ const style = document.createElement("style");
3267
+ style.textContent = styling;
3268
+ document.head.appendChild(style);
3269
+ }
3270
+ };
3271
+ const styling = `/** Table */
3272
+
3273
+ :where(.${CSS_WRAPPER}) {
3274
+ flex: 1;
3275
+ position: relative;
3276
+ background-color: var(--oui-absolute);
3277
+ border: 1px solid grey;
3278
+ }
3279
+
3280
+ :where(.${CSS_TABLE}) {
3281
+ min-height: 24em;
3282
+ display: flex;
3283
+ flex-flow: column nowrap;
3284
+ flex: 1;
3285
+ overflow: auto;
3286
+ position: absolute;
3287
+ inset: 0;
3288
+ }
3289
+
3290
+ /** Row group */
3291
+
3292
+ :where(.${CSS_ROWGROUP_HEADER}),
3293
+ :where(.${CSS_ROWGROUP_FOOTER}) {
3294
+ background-color: white;
3295
+ position: sticky;
3296
+ left: 0;
3297
+ z-index: 10;
3298
+ }
3299
+
3300
+ :where(.${CSS_ROWGROUP_HEADER}) {
3301
+ top: 0;
3302
+ }
3303
+
3304
+ :where(.${CSS_ROWGROUP_FOOTER}) {
3305
+ bottom: 0;
3306
+ }
3307
+
3308
+ :where(.${CSS_ROWGROUP_BODY}) {
3309
+ display: flex;
3310
+ flex-flow: column nowrap;
3311
+ flex: 1;
3312
+ }
3313
+
3314
+ :where(.${CSS_ROWGROUP_BODY}:focus) {
3315
+ outline: none;
3316
+ }
3317
+
3318
+ :where(.${CSS_WRAPPER}:has(.${CSS_ROWGROUP_BODY}:focus-visible)) {
3319
+ outline: 2px solid var(--oui-blue-6);
3320
+ outline-offset: 2px;
3321
+ }
3322
+
3323
+ /** Row */
3324
+
3325
+ :where(.${CSS_ROW}) {
3326
+ width: 100%;
3327
+ display: flex;
3328
+ flex-flow: row nowrap;
3329
+ }
3330
+
3331
+ :where(.${CSS_ROW}:last-child .${CSS_CELL}) {
3332
+ border-bottom-width: 0;
3333
+ }
3334
+
3335
+ :where(.${CSS_ROW}--body),
3336
+ :where(.${CSS_ROW}--group) {
3337
+ flex: 1;
3338
+ position: absolute;
3339
+ }
3340
+
3341
+ :where(.${CSS_ROW_SELECTED}) {
3342
+ background-color: var(--oui-blue-1);
3343
+ color: var(--oui-blue-9);
3344
+ }
3345
+
3346
+ :where(.${CSS_WRAPPER}:has(.${CSS_ROWGROUP_BODY}:focus-visible) .${CSS_ROW}[data-active="true"]) {
3347
+ outline: 2px solid var(--oui-blue-6);
3348
+ outline-offset: 2px;
3349
+ }
3350
+
3351
+ /** Cells */
3352
+
3353
+ :where(.${CSS_CELL}),
3354
+ :where(.${CSS_HEADING}) {
3355
+ padding: 0.5em;
3356
+ border-color: gray;
3357
+ border-style: solid;
3358
+ border-width: 0 1px 1px 0;
3359
+ line-height: 1;
3360
+ }
3361
+
3362
+ :where(.${CSS_WRAPPER} .${CSS_CELL}:last-child),
3363
+ :where(.${CSS_ROW} .${CSS_HEADING}:last-child) {
3364
+ flex: 1;
3365
+ border-right-width: 0;
3366
+ }
3367
+
3368
+ :where(.${CSS_CELL}) {
3369
+ overflow: hidden;
3370
+ text-overflow: ellipsis;
3371
+ white-space: nowrap;
3372
+ }
3373
+
3374
+ :where(.${CSS_HEADING}) {
3375
+ display: flex;
3376
+ flex-flow: row nowrap;
3377
+ align-items: center;
3378
+ justify-content: space-between;
3379
+ gap: 0.5em;
3380
+ cursor: pointer;
3381
+ }
3382
+
3383
+ :where(.${CSS_HEADING_CONTENT}) {
3384
+ overflow: hidden;
3385
+ white-space: nowrap;
3386
+ text-overflow: ellipsis;
3387
+ }
3388
+
3389
+ :where(.${CSS_HEADING}[data-sort-direction] .${CSS_HEADING_SORTER})::after {
3390
+ width: 1em;
3391
+ height: 1em;
3392
+ display: inline-flex;
3393
+ font-size: .75em;
3394
+ font-weight: bold;
3395
+ }
3396
+
3397
+ :where(.${CSS_HEADING}[data-sort-direction="ascending"] .${CSS_HEADING_SORTER})::after {
3398
+ content: '\\21C8';
3399
+ }
3400
+
3401
+ :where(.${CSS_HEADING}[data-sort-direction="descending"] .${CSS_HEADING_SORTER})::after {
3402
+ content: '\\21CA';
3403
+ }
3404
+
3405
+ :where(.${CSS_CELL_FOOTER}) {
3406
+ border-top-width: 1px;
3407
+ border-bottom-width: 0;
3408
+ }
3409
+
3410
+ :where(.${CSS_CELL_GROUP}) {
3411
+ padding: 0;
3412
+ display: flex;
3413
+ flex-flow: row nowrap;
3414
+ align-items: center;
3415
+ gap: 0.5em;
3416
+ }
3417
+
3418
+ :where(.${CSS_CELL_GROUP} .${CSS_BUTTON}) {
3419
+ margin: 0 0 0 .25rem;
3420
+ }
3421
+
3422
+ /** Misc. */
3423
+
3424
+ :where(.${CSS_BUTTON}) {
3425
+ font-size: .75rem;
3426
+ font-weight: bold;
3427
+ }
3428
+
3429
+ :where(.${CSS_SELECTION}) {
3430
+ background-color: color-mix(in oklch, var(--oui-blue-6), transparent);
3431
+ border: 1px solid var(--oui-blue-6);
3432
+ border-radius: .25rem;
3433
+ position: fixed;
3434
+ z-index: 1000;
3435
+ }
3436
+ `.replace(/^\s+|\s+|\s+$/g, " ");
3437
+ let appended = false;
3438
+ //#endregion
3439
+ //#region src/tabela.ts
2753
3440
  var Tabela = class {
2754
- #components = {
2755
- header: void 0,
2756
- body: void 0,
2757
- footer: void 0
2758
- };
3441
+ #components;
2759
3442
  #element;
2760
3443
  #id = getId();
2761
- #table;
2762
3444
  #key;
2763
3445
  #managers = {
2764
3446
  column: void 0,
@@ -2770,50 +3452,58 @@ var Tabela = class {
2770
3452
  render: void 0,
2771
3453
  row: void 0,
2772
3454
  selection: void 0,
2773
- sort: void 0
3455
+ sort: void 0,
3456
+ style: void 0
2774
3457
  };
3458
+ #prefix = `tabela_${this.#id}_`;
3459
+ #state;
3460
+ #table;
2775
3461
  data;
3462
+ events;
2776
3463
  filter;
3464
+ group;
2777
3465
  selection;
2778
3466
  sort;
2779
- get key() {
2780
- return this.#key;
2781
- }
2782
3467
  constructor(element, options) {
2783
3468
  this.#element = element;
2784
3469
  element.innerHTML = "";
2785
- element.classList.add("tabela");
3470
+ element.classList.add(CSS_WRAPPER);
2786
3471
  this.#table = createElement("div", {
2787
- className: "tabela__table",
2788
- role: "table"
2789
- });
2790
- element.setAttribute("aria-label", options.label);
3472
+ className: CSS_TABLE,
3473
+ role: ROLE_TABLE
3474
+ }, { [ARIA_LABEL]: options.label });
2791
3475
  this.#key = options.key;
2792
- this.#components.header = new HeaderComponent();
2793
- this.#components.body = new BodyComponent();
2794
- this.#components.footer = new FooterComponent();
2795
- const state = {
3476
+ this.#components = {};
3477
+ this.#state = {
2796
3478
  options,
2797
3479
  components: this.#components,
2798
3480
  element: this.#table,
2799
3481
  id: this.#id,
2800
3482
  key: this.#key,
2801
- managers: this.#managers
3483
+ managers: this.#managers,
3484
+ prefix: this.#prefix
2802
3485
  };
2803
- this.#managers.column = new ColumnManager(state);
2804
- this.#managers.data = new DataManager(state);
2805
- this.#managers.event = new EventManager(state);
2806
- this.#managers.filter = new FilterManager(state);
2807
- this.#managers.group = new GroupManager(state);
2808
- this.#managers.navigation = new NavigationManager(state);
2809
- this.#managers.render = new RenderManager(state);
2810
- this.#managers.row = new RowManager(state);
2811
- this.#managers.selection = new SelectionManager(state);
2812
- this.#managers.sort = new SortManager(state);
3486
+ this.#components.body = new BodyComponent(this.#state);
3487
+ this.#components.footer = new FooterComponent(this.#state);
3488
+ this.#components.header = new HeaderComponent(this.#state);
3489
+ this.#managers.column = new ColumnManager(this.#state);
3490
+ this.#managers.data = new DataManager(this.#state);
3491
+ this.#managers.event = new EventManager(this.#state);
3492
+ this.#managers.filter = new FilterManager(this.#state);
3493
+ this.#managers.group = new GroupManager(this.#state);
3494
+ this.#managers.navigation = new NavigationManager(this.#state);
3495
+ this.#managers.render = new RenderManager(this.#state);
3496
+ this.#managers.row = new RowManager(this.#state);
3497
+ this.#managers.selection = new SelectionManager(this.#state);
3498
+ this.#managers.sort = new SortManager(this.#state);
3499
+ this.#managers.style = new StyleManager(this.#state);
2813
3500
  this.#table.append(this.#components.header.elements.group, this.#components.body.elements.group, this.#components.footer.elements.group);
3501
+ element.append(this.#table);
2814
3502
  this.#managers.data.set(options.data);
2815
3503
  this.data = this.#managers.data.handlers;
3504
+ this.events = this.#managers.event.handlers;
2816
3505
  this.filter = this.#managers.filter.handlers;
3506
+ this.group = this.#managers.group.handlers;
2817
3507
  this.selection = this.#managers.selection.handlers;
2818
3508
  this.sort = this.#managers.sort.handlers;
2819
3509
  }
@@ -2829,16 +3519,21 @@ var Tabela = class {
2829
3519
  managers.data.destroy();
2830
3520
  managers.event.destroy();
2831
3521
  managers.filter.destroy();
3522
+ managers.group.destroy();
2832
3523
  managers.navigation.destroy();
2833
3524
  managers.render.destroy();
2834
3525
  managers.row.destroy();
2835
3526
  managers.selection.destroy();
2836
3527
  managers.sort.destroy();
2837
3528
  element.innerHTML = "";
2838
- element.role = "";
2839
- element.classList.remove("tabela");
2840
- table.removeAttribute("aria-label");
2841
- table.removeAttribute("role");
3529
+ table.innerHTML = "";
3530
+ element.classList.remove(CSS_WRAPPER);
3531
+ table.removeAttribute(ARIA_LABEL);
3532
+ table.removeAttribute(ATTRIBUTE_ROLE);
3533
+ this.#state.components = void 0;
3534
+ this.#state.managers = void 0;
3535
+ this.#state.element = void 0;
3536
+ this.#state.options = void 0;
2842
3537
  this.#element = void 0;
2843
3538
  this.#table = void 0;
2844
3539
  }
@@ -2848,7 +3543,10 @@ function getId() {
2848
3543
  return id;
2849
3544
  }
2850
3545
  let id = 0;
3546
+ //#endregion
3547
+ //#region src/index.ts
2851
3548
  function tabela(element, options) {
2852
3549
  return new Tabela(element, options);
2853
3550
  }
3551
+ //#endregion
2854
3552
  export { tabela };