@oscarpalmer/tabela 0.12.0 → 0.14.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 (65) hide show
  1. package/dist/tabela.full.js +146 -18
  2. package/package.json +45 -37
  3. package/src/components/body.component.ts +11 -7
  4. package/src/components/column.component.ts +23 -24
  5. package/src/components/footer.component.ts +7 -5
  6. package/src/components/group.component.ts +73 -9
  7. package/src/components/header.component.ts +6 -4
  8. package/src/components/row.component.ts +28 -18
  9. package/src/helpers/dom.helpers.ts +27 -29
  10. package/src/helpers/misc.helpers.ts +5 -0
  11. package/src/helpers/style.helper.ts +1 -1
  12. package/src/managers/column.manager.ts +4 -0
  13. package/src/managers/data.manager.ts +197 -124
  14. package/src/managers/event.manager.ts +27 -17
  15. package/src/managers/filter.manager.ts +49 -25
  16. package/src/managers/group.manager.ts +73 -12
  17. package/src/managers/navigation.manager.ts +48 -50
  18. package/src/managers/render.manager.ts +56 -29
  19. package/src/managers/row.manager.ts +22 -10
  20. package/src/managers/selection.manager.ts +40 -31
  21. package/src/managers/sort.manager.ts +58 -43
  22. package/src/managers/style.manager.ts +171 -0
  23. package/src/models/column.model.ts +2 -6
  24. package/src/models/data.model.ts +12 -10
  25. package/src/models/dom.model.ts +33 -0
  26. package/src/models/event.model.ts +7 -0
  27. package/src/models/filter.model.ts +20 -0
  28. package/src/models/group.model.ts +10 -2
  29. package/src/models/sort.model.ts +4 -0
  30. package/src/models/style.model.ts +51 -0
  31. package/src/models/tabela.model.ts +11 -8
  32. package/src/tabela.ts +67 -37
  33. package/types/components/body.component.d.ts +0 -6
  34. package/types/components/column.component.d.ts +0 -13
  35. package/types/components/footer.component.d.ts +0 -8
  36. package/types/components/group.component.d.ts +0 -14
  37. package/types/components/header.component.d.ts +0 -8
  38. package/types/components/row.component.d.ts +0 -11
  39. package/types/helpers/dom.helpers.d.ts +0 -10
  40. package/types/helpers/misc.helpers.d.ts +0 -2
  41. package/types/helpers/style.helper.d.ts +0 -1
  42. package/types/index.d.ts +0 -4
  43. package/types/managers/column.manager.d.ts +0 -12
  44. package/types/managers/data.manager.d.ts +0 -29
  45. package/types/managers/event.manager.d.ts +0 -7
  46. package/types/managers/filter.manager.d.ts +0 -19
  47. package/types/managers/group.manager.d.ts +0 -17
  48. package/types/managers/navigation.manager.d.ts +0 -10
  49. package/types/managers/render.manager.d.ts +0 -17
  50. package/types/managers/row.manager.d.ts +0 -13
  51. package/types/managers/selection.manager.d.ts +0 -24
  52. package/types/managers/sort.manager.d.ts +0 -28
  53. package/types/models/body.model.d.ts +0 -4
  54. package/types/models/column.model.d.ts +0 -13
  55. package/types/models/data.model.d.ts +0 -24
  56. package/types/models/filter.model.d.ts +0 -13
  57. package/types/models/footer.model.d.ts +0 -5
  58. package/types/models/group.model.d.ts +0 -4
  59. package/types/models/header.model.d.ts +0 -4
  60. package/types/models/render.model.d.ts +0 -13
  61. package/types/models/selection.model.d.ts +0 -8
  62. package/types/models/sort.model.d.ts +0 -12
  63. package/types/models/tabela.model.d.ts +0 -39
  64. package/types/models/tabela.options.d.ts +0 -10
  65. package/types/tabela.d.ts +0 -15
@@ -485,10 +485,11 @@ function createCell(width, body) {
485
485
  }
486
486
  function createElement(tagName, properties, attributes, style) {
487
487
  const element = document.createElement(tagName);
488
- const keys = Object.keys(properties);
489
- for (const key of keys) element[key] = properties[key];
490
- setAttributes(element, attributes);
491
- setStyles(element, style);
488
+ const props = properties ?? {};
489
+ const keys = Object.keys(props);
490
+ for (const key of keys) element[key] = props[key];
491
+ setAttributes(element, attributes ?? {});
492
+ setStyles(element, style ?? {});
492
493
  return element;
493
494
  }
494
495
  function createRowGroup(withRow) {
@@ -673,6 +674,26 @@ function getArrayCallbacks(bool, key, value) {
673
674
  value: getArrayCallback(value)
674
675
  };
675
676
  }
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
+ }
676
697
  function findValues(type, array, parameters, mapper) {
677
698
  const result = {
678
699
  matched: [],
@@ -715,6 +736,7 @@ function getParameters(original) {
715
736
  value: length === 1 && typeof original[0] !== "function" ? original[0] : original[1]
716
737
  };
717
738
  }
739
+ var FIND_VALUE_INDEX = "index";
718
740
  var UNIQUE_THRESHOLD = 100;
719
741
  function filter(array, ...parameters) {
720
742
  return findValues("all", array, parameters).matched;
@@ -812,6 +834,48 @@ function compact(array, strict) {
812
834
  }
813
835
  return compacted;
814
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];
815
879
  function select(array, ...parameters) {
816
880
  return findValues("all", array, parameters, parameters.pop()).matched;
817
881
  }
@@ -923,6 +987,7 @@ function getHandlers(owner, options) {
923
987
  function isConstructable(value) {
924
988
  return typeof value === "object" && value !== null;
925
989
  }
990
+ var COMPARE_NAME = "compare";
926
991
  /**
927
992
  * Compare two values _(for sorting purposes)_
928
993
  * @param first First value
@@ -955,7 +1020,7 @@ compare.handlers = getCompareHandlers(compare, {
955
1020
  callback: (first, second, compareStrings) => {
956
1021
  if (compareStrings) return getString(first).localeCompare(getString(second));
957
1022
  },
958
- method: "compare"
1023
+ method: COMPARE_NAME
959
1024
  });
960
1025
  compare.register = registerComparator;
961
1026
  compare.unregister = unregisterComparator;
@@ -977,7 +1042,7 @@ function unregisterComparator(constructor) {
977
1042
  function compareNumbers(first, second) {
978
1043
  const firstNumber = Number(first);
979
1044
  const secondNumber = Number(second);
980
- if (firstNumber === secondNumber) return 0;
1045
+ if (Object.is(firstNumber, secondNumber)) return 0;
981
1046
  return firstNumber > secondNumber ? 1 : -1;
982
1047
  }
983
1048
  function compareSymbols(first, second) {
@@ -1031,7 +1096,7 @@ function getSorter(value, modifier) {
1031
1096
  function sort(array, first, second) {
1032
1097
  if (!Array.isArray(array)) return [];
1033
1098
  if (array.length < 2) return array;
1034
- const modifier = (first === true || second === true ? "desc" : "asc") === "asc" ? 1 : -1;
1099
+ const modifier = (first === true || second === true ? "descending" : "ascending") === "ascending" ? 1 : -1;
1035
1100
  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);
1036
1101
  const { length } = sorters;
1037
1102
  if (length === 0) return array.sort((firstItem, secondItem) => compare(firstItem, secondItem) * modifier);
@@ -1056,6 +1121,56 @@ function sort(array, first, second) {
1056
1121
  return 0;
1057
1122
  });
1058
1123
  }
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
+ }
1059
1174
  function getMapValues(array, first, second, arrays) {
1060
1175
  if (!Array.isArray(array)) return /* @__PURE__ */ new Map();
1061
1176
  const { length } = array;
@@ -1737,7 +1852,7 @@ var Memoized = class {
1737
1852
  constructor(callback, options) {
1738
1853
  const cache = new SizedMap(options.cacheSize);
1739
1854
  const getter = (...parameters) => {
1740
- const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), "_"));
1855
+ const key = options.cacheKey?.(...parameters) ?? (parameters.length === 1 ? parameters[0] : join(parameters.map(getString), SEPARATOR));
1741
1856
  if (cache.has(key)) return cache.get(key);
1742
1857
  const value = callback(...parameters);
1743
1858
  cache.set(key, value);
@@ -1813,6 +1928,7 @@ function memoize(callback, options) {
1813
1928
  return new Memoized(callback, getMemoizationOptions(options));
1814
1929
  }
1815
1930
  var DEFAULT_CACHE_SIZE = 1024;
1931
+ var SEPARATOR = "_";
1816
1932
  /**
1817
1933
  * Check if a string ends with a specified substring
1818
1934
  * @param haystack String to look in
@@ -1821,7 +1937,7 @@ var DEFAULT_CACHE_SIZE = 1024;
1821
1937
  * @returns `true` if the string ends with the given substring, otherwise `false`
1822
1938
  */
1823
1939
  function endsWith(haystack, needle, ignoreCase) {
1824
- return match("endsWith", haystack, needle, ignoreCase === true);
1940
+ return match(MATCH_ENDS_WITH, haystack, needle, ignoreCase === true);
1825
1941
  }
1826
1942
  /**
1827
1943
  * Check if a string includes a specified substring
@@ -1831,7 +1947,7 @@ function endsWith(haystack, needle, ignoreCase) {
1831
1947
  * @returns `true` if the string includes the given substring, otherwise `false`
1832
1948
  */
1833
1949
  function includes(haystack, needle, ignoreCase) {
1834
- return match("includes", haystack, needle, ignoreCase === true);
1950
+ return match(MATCH_INCLUDES, haystack, needle, ignoreCase === true);
1835
1951
  }
1836
1952
  function match(type, haystack, needle, ignoreCase) {
1837
1953
  if (typeof haystack !== "string" || typeof needle !== "string") return false;
@@ -1849,8 +1965,11 @@ function matchCallback(haystack, needle, ignoreCase) {
1849
1965
  * @returns `true` if the string starts with the given substring, otherwise `false`
1850
1966
  */
1851
1967
  function startsWith(haystack, needle, ignoreCase) {
1852
- return match("startsWith", haystack, needle, ignoreCase === true);
1968
+ return match(MATCH_STARTS_WITH, haystack, needle, ignoreCase === true);
1853
1969
  }
1970
+ var MATCH_ENDS_WITH = "endsWith";
1971
+ var MATCH_INCLUDES = "includes";
1972
+ var MATCH_STARTS_WITH = "startsWith";
1854
1973
  var matchMemoizers = {};
1855
1974
  function equal(first, second, options) {
1856
1975
  return equalValue(first, second, getEqualOptions(options));
@@ -1948,9 +2067,9 @@ function equalValue(first, second, options) {
1948
2067
  case first instanceof ArrayBuffer && second instanceof ArrayBuffer: return equalArrayBuffer(first, second, options);
1949
2068
  case first instanceof Date && second instanceof Date: return Object.is(Number(first), Number(second));
1950
2069
  case first instanceof DataView && second instanceof DataView: return equalDataView(first, second, options);
1951
- case first instanceof Error && second instanceof Error: return equalProperties(first, second, ["name", "message"], options);
2070
+ case first instanceof Error && second instanceof Error: return equalProperties(first, second, ERROR_PROPERTIES, options);
1952
2071
  case first instanceof Map && second instanceof Map: return equalMap(first, second, options);
1953
- case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, ["source", "flags"], options);
2072
+ case first instanceof RegExp && second instanceof RegExp: return equalProperties(first, second, EXPRESSION_PROPERTIES, options);
1954
2073
  case first instanceof Set && second instanceof Set: return equalSet(first, second, options);
1955
2074
  case Array.isArray(first) && Array.isArray(second): return equalArray(first, second, options);
1956
2075
  case isPlainObject(first) && isPlainObject(second): return equalPlainObject(first, second, options);
@@ -2019,6 +2138,8 @@ function getEqualOptions(input) {
2019
2138
  }
2020
2139
  var ARRAY_PEEK_PERCENTAGE = 10;
2021
2140
  var ARRAY_THRESHOLD = 100;
2141
+ var ERROR_PROPERTIES = ["name", "message"];
2142
+ var EXPRESSION_PROPERTIES = ["source", "flags"];
2022
2143
  var FilterManager = class {
2023
2144
  handlers = Object.freeze({
2024
2145
  add: (item) => this.add(item),
@@ -2637,6 +2758,7 @@ var Tabela = class {
2637
2758
  };
2638
2759
  #element;
2639
2760
  #id = getId();
2761
+ #table;
2640
2762
  #key;
2641
2763
  #managers = {
2642
2764
  column: void 0,
@@ -2660,17 +2782,20 @@ var Tabela = class {
2660
2782
  constructor(element, options) {
2661
2783
  this.#element = element;
2662
2784
  element.innerHTML = "";
2663
- element.role = "table";
2664
2785
  element.classList.add("tabela");
2786
+ this.#table = createElement("div", {
2787
+ className: "tabela__table",
2788
+ role: "table"
2789
+ });
2665
2790
  element.setAttribute("aria-label", options.label);
2666
2791
  this.#key = options.key;
2667
2792
  this.#components.header = new HeaderComponent();
2668
2793
  this.#components.body = new BodyComponent();
2669
2794
  this.#components.footer = new FooterComponent();
2670
2795
  const state = {
2671
- element,
2672
2796
  options,
2673
2797
  components: this.#components,
2798
+ element: this.#table,
2674
2799
  id: this.#id,
2675
2800
  key: this.#key,
2676
2801
  managers: this.#managers
@@ -2685,7 +2810,7 @@ var Tabela = class {
2685
2810
  this.#managers.row = new RowManager(state);
2686
2811
  this.#managers.selection = new SelectionManager(state);
2687
2812
  this.#managers.sort = new SortManager(state);
2688
- element.append(this.#components.header.elements.group, this.#components.body.elements.group, this.#components.footer.elements.group);
2813
+ this.#table.append(this.#components.header.elements.group, this.#components.body.elements.group, this.#components.footer.elements.group);
2689
2814
  this.#managers.data.set(options.data);
2690
2815
  this.data = this.#managers.data.handlers;
2691
2816
  this.filter = this.#managers.filter.handlers;
@@ -2696,6 +2821,7 @@ var Tabela = class {
2696
2821
  const components = this.#components;
2697
2822
  const managers = this.#managers;
2698
2823
  const element = this.#element;
2824
+ const table = this.#table;
2699
2825
  components.body.destroy();
2700
2826
  components.footer.destroy();
2701
2827
  components.header.destroy();
@@ -2703,6 +2829,7 @@ var Tabela = class {
2703
2829
  managers.data.destroy();
2704
2830
  managers.event.destroy();
2705
2831
  managers.filter.destroy();
2832
+ managers.navigation.destroy();
2706
2833
  managers.render.destroy();
2707
2834
  managers.row.destroy();
2708
2835
  managers.selection.destroy();
@@ -2710,9 +2837,10 @@ var Tabela = class {
2710
2837
  element.innerHTML = "";
2711
2838
  element.role = "";
2712
2839
  element.classList.remove("tabela");
2713
- element.removeAttribute("aria-label");
2714
- element.removeAttribute("role");
2840
+ table.removeAttribute("aria-label");
2841
+ table.removeAttribute("role");
2715
2842
  this.#element = void 0;
2843
+ this.#table = void 0;
2716
2844
  }
2717
2845
  };
2718
2846
  function getId() {
package/package.json CHANGED
@@ -1,50 +1,58 @@
1
1
  {
2
+ "name": "@oscarpalmer/tabela",
3
+ "version": "0.14.0",
4
+ "description": "A modern table.",
5
+ "keywords": [],
6
+ "license": "MIT",
2
7
  "author": {
3
8
  "name": "Oscar Palmér",
4
9
  "url": "https://oscarpalmer.se"
5
10
  },
6
- "dependencies": {
7
- "@oscarpalmer/atoms": "^0.159",
8
- "@oscarpalmer/toretto": "^0.38"
9
- },
10
- "description": "A modern table.",
11
- "devDependencies": {
12
- "@oscarpalmer/oui": "^0.19",
13
- "@types/node": "^25.3",
14
- "@vitest/coverage-istanbul": "^4",
15
- "jsdom": "^28.1",
16
- "oxfmt": "^0.36",
17
- "oxlint": "^1.51",
18
- "rolldown": "1.0.0-rc.7",
19
- "tslib": "^2.8",
20
- "typescript": "^5.9",
21
- "vite": "8.0.0-beta.16",
22
- "vitest": "^4"
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/oscarpalmer/tabela.git"
23
14
  },
15
+ "files": [
16
+ "dist",
17
+ "src"
18
+ ],
19
+ "type": "module",
20
+ "module": "./dist/index.mjs",
21
+ "types": "./dist/index.d.mts",
24
22
  "exports": {
25
23
  ".": {
26
- "types": "./types/index.d.ts",
27
- "default": "./dist/index.js"
24
+ "types": "./dist/index.d.mts",
25
+ "default": "./dist/index.mjs"
28
26
  }
29
27
  },
30
- "files": ["dist", "src", "types"],
31
- "keywords": [],
32
- "license": "MIT",
33
- "module": "./dist/index.js",
34
- "name": "@oscarpalmer/tabela",
35
- "repository": {
36
- "type": "git",
37
- "url": "git+https://github.com/oscarpalmer/tabela.git"
38
- },
39
28
  "scripts": {
40
- "build": "npm run clean && npx vite build && npm run rolldown:build && npx tsc",
41
- "clean": "rm -rf ./dist && rm -rf ./types && rm -f ./tsconfig.tsbuildinfo",
42
- "rolldown:build": "npx rolldown -c",
43
- "rolldown:watch": "npx rolldown -c ./rolldown.config.js --watch",
44
- "test": "npx vitest --coverage",
45
- "watch": "npx vite build --watch"
29
+ "build": "vpx vp run tsdown:build && vpx vp pack",
30
+ "tsdown:build": "vpx tsdown -c ./tsdown.config.ts",
31
+ "tsdown:watch": "vpx tsdown -c ./tsdown.config.ts --watch",
32
+ "test": "vpx vp test run --coverage",
33
+ "test:leak": "vpx vp test run --detect-async-leaks --coverage",
34
+ "watch": "vpx vite build --watch",
35
+ "www": "concurrently \"vpx vp run www:css\" \"vpx vp run www:js\"",
36
+ "www:css": "sass --watch www/.app/css:./www/css",
37
+ "www:js": "vpx tsdown -c ./www/.app/js/tsdown.config.ts --watch"
46
38
  },
47
- "type": "module",
48
- "types": "./types/index.d.ts",
49
- "version": "0.12.0"
39
+ "dependencies": {
40
+ "@oscarpalmer/atoms": "^0.165",
41
+ "@oscarpalmer/toretto": "^0.41"
42
+ },
43
+ "devDependencies": {
44
+ "@oscarpalmer/abydon": "^0.19",
45
+ "@oscarpalmer/oui": "^0.19",
46
+ "@types/node": "^25.5",
47
+ "@vitest/coverage-istanbul": "^4.1",
48
+ "concurrently": "^9.2",
49
+ "jsdom": "^28.1",
50
+ "sass": "^1.98",
51
+ "tsdown": "^0.21",
52
+ "typescript": "^5.9",
53
+ "vite": "npm:@voidzero-dev/vite-plus-core@latest",
54
+ "vite-plus": "latest",
55
+ "vitest": "npm:@voidzero-dev/vite-plus-test@latest"
56
+ },
57
+ "packageManager": "npm@11.11.1"
50
58
  }
@@ -1,10 +1,14 @@
1
1
  import {createElement, createRowGroup} from '../helpers/dom.helpers';
2
2
  import type {BodyElements} from '../models/body.model';
3
+ import {ATTRIBUTE_DATA_EVENT, ELEMENT_DIV} from '../models/dom.model';
4
+ import {EVENT_BODY} from '../models/event.model';
5
+ import {CSS_FAKER, CSS_ROWGROUP_BODY} from '../models/style.model';
6
+ import type {State} from '../models/tabela.model';
3
7
 
4
8
  function createFaker(): HTMLDivElement {
5
- return createElement('div', {
6
- className: 'tabela__faker',
7
- }, {}, {});
9
+ return createElement(ELEMENT_DIV, {
10
+ className: CSS_FAKER,
11
+ });
8
12
  }
9
13
 
10
14
  export class BodyComponent {
@@ -13,16 +17,16 @@ export class BodyComponent {
13
17
  group: undefined as never,
14
18
  };
15
19
 
16
- constructor() {
17
- const group = createRowGroup(false);
20
+ constructor(state: State) {
21
+ const group = createRowGroup(state.options.rowHeight, false);
18
22
 
19
23
  this.elements.group = group;
20
24
 
21
- group.className += ' tabela__rowgroup--body';
25
+ group.className += ` ${CSS_ROWGROUP_BODY}`;
22
26
 
23
27
  group.tabIndex = 0;
24
28
 
25
- group.setAttribute('data-event', 'body');
29
+ group.setAttribute(ATTRIBUTE_DATA_EVENT, EVENT_BODY);
26
30
 
27
31
  group.append(this.elements.faker);
28
32
  }
@@ -1,5 +1,14 @@
1
1
  import {createElement} from '../helpers/dom.helpers';
2
2
  import type {Column, TabelaColumn} from '../models/column.model';
3
+ import {
4
+ ATTRIBUTE_DATA_EVENT,
5
+ ATTRIBUTE_DATA_FIELD,
6
+ ATTRIBUTE_ROLE,
7
+ ELEMENT_DIV,
8
+ ROLE_COLUMNHEADER,
9
+ } from '../models/dom.model';
10
+ import {EVENT_HEADING} from '../models/event.model';
11
+ import {CSS_HEADING, CSS_HEADING_CONTENT, CSS_HEADING_SORTER} from '../models/style.model';
3
12
 
4
13
  export class ColumnComponent {
5
14
  elements: ColumnElements;
@@ -8,14 +17,14 @@ export class ColumnComponent {
8
17
  constructor(column: TabelaColumn) {
9
18
  const width =
10
19
  Number.parseInt(getComputedStyle(document.body).fontSize, 10) *
11
- (column.width ?? column.title.length * 1.5);
20
+ (column.width ?? column.label.length * 1.5);
12
21
 
13
22
  this.options = {
14
23
  ...column,
15
24
  width,
16
25
  };
17
26
 
18
- this.elements = createHeading(this.options.field, this.options.title, width);
27
+ this.elements = createHeading(this.options.field, this.options.label, width);
19
28
  }
20
29
 
21
30
  destroy(): void {
@@ -36,38 +45,28 @@ type ColumnElements = {
36
45
 
37
46
  function createHeading(field: string, title: string, width: number): ColumnElements {
38
47
  const wrapper = createElement(
39
- 'div',
48
+ ELEMENT_DIV,
40
49
  {
41
- className: 'tabela__heading',
42
- role: 'columnheader',
50
+ className: CSS_HEADING,
51
+ [ATTRIBUTE_ROLE]: ROLE_COLUMNHEADER,
43
52
  },
44
53
  {
45
- 'data-event': 'heading',
46
- 'data-field': field,
54
+ [ATTRIBUTE_DATA_EVENT]: EVENT_HEADING,
55
+ [ATTRIBUTE_DATA_FIELD]: field,
47
56
  },
48
57
  {
49
58
  width: `${width}px`,
50
59
  },
51
60
  );
52
61
 
53
- const content = createElement(
54
- 'div',
55
- {
56
- className: 'tabela__heading__content',
57
- textContent: title,
58
- },
59
- {},
60
- {},
61
- );
62
+ const content = createElement(ELEMENT_DIV, {
63
+ className: CSS_HEADING_CONTENT,
64
+ textContent: title,
65
+ });
62
66
 
63
- const sorter = createElement(
64
- 'div',
65
- {
66
- className: 'tabela__heading__sorter',
67
- },
68
- {},
69
- {},
70
- );
67
+ const sorter = createElement(ELEMENT_DIV, {
68
+ className: CSS_HEADING_SORTER,
69
+ });
71
70
 
72
71
  wrapper.append(content, sorter);
73
72
 
@@ -1,12 +1,14 @@
1
1
  import {createCell, createRowGroup} from '../helpers/dom.helpers';
2
2
  import type {FooterElements} from '../models/footer.model';
3
+ import {CSS_CELL_FOOTER, CSS_ROW_FOOTER, CSS_ROWGROUP_FOOTER} from '../models/style.model';
4
+ import type {State} from '../models/tabela.model';
3
5
  import type {ColumnComponent} from './column.component';
4
6
 
5
7
  export class FooterComponent {
6
8
  readonly elements: FooterElements;
7
9
 
8
- constructor() {
9
- const {group, row} = createRowGroup();
10
+ constructor(state: State) {
11
+ const {group, row} = createRowGroup(state.options.rowHeight);
10
12
 
11
13
  this.elements = {
12
14
  group,
@@ -14,8 +16,8 @@ export class FooterComponent {
14
16
  cells: [],
15
17
  };
16
18
 
17
- group.className += ' tabela__rowgroup--footer';
18
- row.className += ' tabela__row--footer';
19
+ group.className += ` ${CSS_ROWGROUP_FOOTER}`;
20
+ row.className += ` ${CSS_ROW_FOOTER}`;
19
21
  }
20
22
 
21
23
  destroy(): void {
@@ -35,7 +37,7 @@ export class FooterComponent {
35
37
  for (let index = 0; index < length; index += 1) {
36
38
  const cell = createCell(columns[index].options.width ?? 4, false);
37
39
 
38
- cell.className += ' tabela__cell--footer';
40
+ cell.className += ` ${CSS_CELL_FOOTER}`;
39
41
  cell.innerHTML = '&nbsp;';
40
42
 
41
43
  elements.cells.push(cell);