@oscarpalmer/tabela 0.7.0 → 0.8.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.
@@ -1,7 +1,7 @@
1
1
  import { createElement, createRowGroup } from "../helpers/dom.helpers.js";
2
2
  import { setStyles } from "@oscarpalmer/toretto/style";
3
3
  function createFaker() {
4
- return createElement("div", {}, {
4
+ return createElement("div", {}, {}, {
5
5
  height: "0",
6
6
  inset: "0 auto auto 0",
7
7
  opacity: "0",
@@ -1,13 +1,6 @@
1
1
  import { createElement } from "../helpers/dom.helpers.js";
2
- function createHeading(title, width) {
3
- return createElement("div", {
4
- className: "tabela__heading",
5
- role: "columnheader",
6
- textContent: title
7
- }, { width: `${width}px` });
8
- }
9
2
  var ColumnComponent = class {
10
- element;
3
+ elements;
11
4
  options;
12
5
  constructor(options) {
13
6
  const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (options.width ?? options.title.length * 1.5);
@@ -15,7 +8,34 @@ var ColumnComponent = class {
15
8
  ...options,
16
9
  width
17
10
  };
18
- this.element = createHeading(options.title, width);
11
+ this.elements = createHeading(options.field, options.title, width);
12
+ }
13
+ destroy() {
14
+ this.elements.content.remove();
15
+ this.elements.wrapper.remove();
16
+ this.elements.sorter.remove();
17
+ this.elements = void 0;
18
+ this.options = void 0;
19
19
  }
20
20
  };
21
+ function createHeading(field, title, width) {
22
+ const wrapper = createElement("div", {
23
+ className: "tabela__heading",
24
+ role: "columnheader"
25
+ }, {
26
+ "data-event": "heading",
27
+ "data-field": field
28
+ }, { width: `${width}px` });
29
+ const content = createElement("div", {
30
+ className: "tabela__heading__content",
31
+ textContent: title
32
+ }, {}, {});
33
+ const sorter = createElement("div", { className: "tabela__heading__sorter" }, {}, {});
34
+ wrapper.append(content, sorter);
35
+ return {
36
+ content,
37
+ sorter,
38
+ wrapper
39
+ };
40
+ }
21
41
  export { ColumnComponent };
@@ -16,7 +16,7 @@ var HeaderComponent = class {
16
16
  }
17
17
  update(columns) {
18
18
  this.elements.row.innerHTML = "";
19
- this.elements.row.append(...columns.map((column) => column.element));
19
+ this.elements.row.append(...columns.map((column) => column.elements.wrapper));
20
20
  }
21
21
  };
22
22
  export { HeaderComponent };
@@ -1,16 +1,18 @@
1
1
  import { setStyles } from "@oscarpalmer/toretto/style";
2
+ import { setAttributes } from "@oscarpalmer/toretto/attribute";
2
3
  function createCell(width, body) {
3
4
  const cell = createElement("div", {
4
5
  className: "tabela__cell",
5
6
  role: "cell"
6
- }, { width: `${width}px` });
7
+ }, {}, { width: `${width}px` });
7
8
  if (body ?? true) cell.classList.add("tabela__cell-body");
8
9
  return cell;
9
10
  }
10
- function createElement(tagName, properties, style) {
11
+ function createElement(tagName, properties, attributes, style) {
11
12
  const element = document.createElement(tagName);
12
13
  const keys = Object.keys(properties);
13
14
  for (const key of keys) element[key] = properties[key];
15
+ setAttributes(element, attributes);
14
16
  setStyles(element, style);
15
17
  return element;
16
18
  }
@@ -18,7 +20,7 @@ function createRowGroup(withRow) {
18
20
  const group = createElement("div", {
19
21
  className: "tabela__rowgroup",
20
22
  role: "rowgroup"
21
- }, {});
23
+ }, {}, {});
22
24
  if (!(withRow ?? true)) return group;
23
25
  const row = createRow(false);
24
26
  group.append(row);
@@ -31,7 +33,7 @@ function createRow(withStyle) {
31
33
  const row = createElement("div", {
32
34
  className: "tabela__row",
33
35
  role: "row"
34
- }, {});
36
+ }, {}, {});
35
37
  if (withStyle ?? true) setStyles(row, {
36
38
  inset: "0 auto auto 0",
37
39
  position: "absolute"
@@ -1,3 +1,4 @@
1
+ import { sort } from "@oscarpalmer/atoms/array";
1
2
  import { toMap } from "@oscarpalmer/atoms/array/to-map";
2
3
  import { isPlainObject } from "@oscarpalmer/atoms/is";
3
4
  var DataManager = class {
@@ -28,8 +29,7 @@ var DataManager = class {
28
29
  const { field, values } = this;
29
30
  values.objects.array.push(...data);
30
31
  values.objects.mapped = toMap(values.objects.array, field);
31
- values.keys.original = [...values.objects.mapped.keys()];
32
- if (render) this.managers.virtualization.update(true);
32
+ if (render) this.render();
33
33
  }
34
34
  clear() {
35
35
  if (this.values.objects.array.length > 0) this.set([]);
@@ -58,16 +58,19 @@ var DataManager = class {
58
58
  values.keys.original.splice(values.keys.original.indexOf(key), 1);
59
59
  managers.row.remove(key);
60
60
  }
61
- if (render) this.managers.virtualization.update(true);
61
+ if (render) this.render();
62
+ }
63
+ render() {
64
+ const { field, managers, values } = this;
65
+ values.keys.original = sort(values.objects.array.map((item) => item[field]));
66
+ if (managers.sort.items.length > 0) managers.sort.sort();
67
+ else managers.virtualization.update(true);
62
68
  }
63
69
  set(data) {
64
70
  const { field, values } = this;
65
- const mapped = toMap(data, field);
66
- values.keys.active = void 0;
67
- values.keys.original = [...mapped.keys()];
68
- values.objects.mapped = mapped;
71
+ values.objects.mapped = toMap(data, field);
69
72
  values.objects.array = data;
70
- this.managers.virtualization.update(true);
73
+ this.render();
71
74
  }
72
75
  async synchronize(data, remove) {
73
76
  const { field, values } = this;
@@ -89,7 +92,7 @@ var DataManager = class {
89
92
  }
90
93
  await this.update(updated);
91
94
  if (add.length > 0) await this.add(add, false);
92
- if (add.length > 0 || (remove ?? false)) this.managers.virtualization.update(true);
95
+ if (add.length > 0 || (remove ?? false)) this.render();
93
96
  }
94
97
  async update(data) {
95
98
  const { field, managers, values } = this;
@@ -0,0 +1,30 @@
1
+ import { on } from "@oscarpalmer/toretto/event";
2
+ import { findAncestor } from "@oscarpalmer/toretto";
3
+ var EventManager = class {
4
+ listener;
5
+ constructor(managers, element) {
6
+ this.managers = managers;
7
+ on(element, "click", (event) => {
8
+ this.onClick(event);
9
+ }, { passive: false });
10
+ }
11
+ destroy() {
12
+ this.listener();
13
+ }
14
+ onClick(event) {
15
+ const target = findAncestor(event, "[data-event]");
16
+ if (!(target instanceof HTMLElement)) return;
17
+ switch (target?.getAttribute("data-event")) {
18
+ case "heading":
19
+ this.onSort(event, target);
20
+ break;
21
+ }
22
+ }
23
+ onSort(event, target) {
24
+ const { managers } = this;
25
+ const direction = target.getAttribute("data-sort-direction");
26
+ const field = target.getAttribute("data-field");
27
+ if (field != null) managers.sort.toggle(event, field, direction);
28
+ }
29
+ };
30
+ export { EventManager };
@@ -0,0 +1,83 @@
1
+ import { setAttribute, setAttributes } from "@oscarpalmer/toretto/attribute";
2
+ import { sort } from "@oscarpalmer/atoms/array";
3
+ var SortManager = class {
4
+ handlers = Object.freeze({
5
+ add: (field, direction) => this.add(field, direction),
6
+ flip: (field) => this.flip(field),
7
+ clear: () => this.clear(),
8
+ remove: (field) => this.remove(field),
9
+ set: (items) => this.set(items)
10
+ });
11
+ items = [];
12
+ constructor(managers) {
13
+ this.managers = managers;
14
+ }
15
+ add(field, direction) {
16
+ if (this.items.findIndex((item) => item.key === field) > -1) return;
17
+ this.items.push({
18
+ key: field,
19
+ direction: direction ?? "ascending"
20
+ });
21
+ this.sort();
22
+ }
23
+ addOrSet(event, field) {
24
+ if (event.ctrlKey || event.metaKey) this.add(field);
25
+ else this.set([{
26
+ key: field,
27
+ direction: "ascending"
28
+ }]);
29
+ }
30
+ clear() {
31
+ this.items.length = 0;
32
+ this.sort();
33
+ }
34
+ flip(field) {
35
+ const item = this.items.find((item) => item.key === field);
36
+ if (item == null) return;
37
+ item.direction = item.direction === "ascending" ? "descending" : "ascending";
38
+ this.sort();
39
+ }
40
+ remove(field) {
41
+ const index = this.items.findIndex((item) => item.key === field);
42
+ if (index > -1) {
43
+ this.items.splice(index, 1);
44
+ this.sort();
45
+ }
46
+ }
47
+ removeOrClear(event, field) {
48
+ if (event.ctrlKey || event.metaKey) this.remove(field);
49
+ else this.clear();
50
+ }
51
+ set(items) {
52
+ this.items.splice(0, this.items.length, ...items);
53
+ this.sort();
54
+ }
55
+ sort() {
56
+ const { items, managers } = this;
57
+ managers.data.values.keys.active = items.length === 0 ? void 0 : sort(managers.data.values.objects.array, items).map((row) => row[managers.data.field]);
58
+ managers.virtualization.update(true, true);
59
+ for (const column of managers.column.items) {
60
+ const sorterIndex = items.findIndex((item) => item.key === column.options.field);
61
+ const sorterItem = items[sorterIndex];
62
+ setAttributes(column.elements.wrapper, {
63
+ "aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
64
+ "data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
65
+ });
66
+ setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
67
+ }
68
+ }
69
+ toggle(event, field, direction) {
70
+ switch (direction) {
71
+ case "ascending":
72
+ this.flip(field);
73
+ return;
74
+ case "descending":
75
+ this.removeOrClear(event, field);
76
+ return;
77
+ default:
78
+ this.addOrSet(event, field);
79
+ return;
80
+ }
81
+ }
82
+ };
83
+ export { SortManager };
@@ -64,13 +64,13 @@ var VirtualizationManager = class {
64
64
  this.fragment.replaceChildren();
65
65
  return this.fragment;
66
66
  }
67
- update(down) {
67
+ update(down, rerender) {
68
68
  const { components, managers, pool, visible } = this;
69
69
  components.body.elements.faker.style.height = `${managers.data.size * managers.row.height}px`;
70
70
  const indices = /* @__PURE__ */ new Set();
71
71
  const range = getRange.call(this, down);
72
72
  for (let index = range.start; index <= range.end; index += 1) indices.add(index);
73
- let remove = false;
73
+ let remove = rerender ?? false;
74
74
  for (const [index, row] of visible) {
75
75
  if (!managers.row.has(row.key) || !indices.has(index)) remove = true;
76
76
  if (remove) {
File without changes