@oscarpalmer/tabela 0.4.0 → 0.6.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 (79) hide show
  1. package/dist/components/body.component.js +33 -55
  2. package/dist/components/column.component.js +20 -25
  3. package/dist/components/footer.component.js +33 -34
  4. package/dist/components/header.component.js +21 -26
  5. package/dist/components/row.component.js +34 -36
  6. package/dist/helpers/dom.helpers.js +35 -30
  7. package/dist/index.js +5 -5
  8. package/dist/managers/column.manager.js +32 -0
  9. package/dist/managers/data.manager.js +30 -0
  10. package/dist/managers/row.manager.js +21 -0
  11. package/dist/managers/virtualization.manager.js +89 -85
  12. package/dist/models/body.model.js +0 -0
  13. package/dist/models/column.model.js +0 -1
  14. package/dist/models/data.model.js +0 -0
  15. package/dist/models/footer.model.js +0 -0
  16. package/dist/models/header.model.js +0 -0
  17. package/dist/models/tabela.options.js +0 -1
  18. package/dist/models/virtualization.model.js +0 -0
  19. package/dist/tabela.full.js +645 -0
  20. package/dist/tabela.js +45 -43
  21. package/package.json +22 -24
  22. package/src/components/body.component.ts +22 -51
  23. package/src/components/column.component.ts +14 -8
  24. package/src/components/footer.component.ts +18 -16
  25. package/src/components/header.component.ts +9 -15
  26. package/src/components/row.component.ts +39 -32
  27. package/src/helpers/dom.helpers.ts +50 -15
  28. package/src/index.ts +8 -1
  29. package/src/managers/column.manager.ts +65 -0
  30. package/src/managers/data.manager.ts +45 -0
  31. package/src/managers/row.manager.ts +32 -0
  32. package/src/managers/virtualization.manager.ts +101 -72
  33. package/src/models/body.model.ts +4 -0
  34. package/src/models/column.model.ts +1 -7
  35. package/src/models/data.model.ts +16 -0
  36. package/src/models/footer.model.ts +5 -0
  37. package/src/models/header.model.ts +4 -0
  38. package/src/models/tabela.options.ts +2 -0
  39. package/src/models/virtualization.model.ts +14 -0
  40. package/src/tabela.ts +65 -36
  41. package/types/components/body.component.d.ts +2 -13
  42. package/types/components/footer.component.d.ts +4 -7
  43. package/types/components/header.component.d.ts +4 -8
  44. package/types/components/row.component.d.ts +7 -7
  45. package/types/helpers/dom.helpers.d.ts +1 -0
  46. package/types/index.d.ts +4 -1
  47. package/types/managers/column.manager.d.ts +12 -0
  48. package/types/managers/data.manager.d.ts +11 -0
  49. package/types/managers/row.manager.d.ts +11 -0
  50. package/types/managers/virtualization.manager.d.ts +12 -12
  51. package/types/models/body.model.d.ts +4 -0
  52. package/types/models/data.model.d.ts +14 -0
  53. package/types/models/footer.model.d.ts +5 -0
  54. package/types/models/header.model.d.ts +4 -0
  55. package/types/models/tabela.options.d.ts +2 -0
  56. package/types/models/virtualization.model.d.ts +12 -0
  57. package/types/tabela.d.ts +19 -5
  58. package/dist/components/body.component.cjs +0 -58
  59. package/dist/components/column.component.cjs +0 -27
  60. package/dist/components/footer.component.cjs +0 -35
  61. package/dist/components/header.component.cjs +0 -28
  62. package/dist/components/row.component.cjs +0 -38
  63. package/dist/helpers/dom.helpers.cjs +0 -36
  64. package/dist/index.cjs +0 -5
  65. package/dist/managers/virtualization.manager.cjs +0 -88
  66. package/dist/models/column.model.cjs +0 -1
  67. package/dist/models/tabela.options.cjs +0 -1
  68. package/dist/tabela.cjs +0 -47
  69. package/types/components/body.component.d.cts +0 -98
  70. package/types/components/column.component.d.cts +0 -98
  71. package/types/components/footer.component.d.cts +0 -98
  72. package/types/components/header.component.d.cts +0 -98
  73. package/types/components/row.component.d.cts +0 -98
  74. package/types/helpers/dom.helpers.d.cts +0 -12
  75. package/types/index.d.cts +0 -99
  76. package/types/managers/virtualization.manager.d.cts +0 -98
  77. package/types/models/column.model.d.cts +0 -17
  78. package/types/models/tabela.options.d.cts +0 -18
  79. package/types/tabela.d.cts +0 -99
@@ -0,0 +1,645 @@
1
+ /**
2
+ * Get the string value from any value
3
+ * @param value Original value
4
+ * @returns String representation of the value
5
+ */
6
+ function getString(value) {
7
+ if (typeof value === "string") return value;
8
+ if (value == null) return "";
9
+ if (typeof value === "function") return getString(value());
10
+ if (typeof value !== "object") return String(value);
11
+ const asString = String(value.valueOf?.() ?? value);
12
+ return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
13
+ }
14
+ function getBoolean(value, defaultValue) {
15
+ return typeof value === "boolean" ? value : defaultValue ?? false;
16
+ }
17
+ /**
18
+ * Is the value an event target?
19
+ * @param value Value to check
20
+ * @returns `true` if it's an event target, otherwise `false`
21
+ */
22
+ function isEventTarget(value) {
23
+ return typeof value === "object" && value != null && typeof value.addEventListener === "function" && typeof value.removeEventListener === "function" && typeof value.dispatchEvent === "function";
24
+ }
25
+ /**
26
+ * Is the value an HTML or SVG element?
27
+ * @param value Value to check
28
+ * @returns `true` if it's an HTML or SVG element, otherwise `false`
29
+ */
30
+ function isHTMLOrSVGElement(value) {
31
+ return value instanceof HTMLElement || value instanceof SVGElement;
32
+ }
33
+ new Set([
34
+ Node.ELEMENT_NODE,
35
+ Node.TEXT_NODE,
36
+ Node.PROCESSING_INSTRUCTION_NODE,
37
+ Node.COMMENT_NODE,
38
+ Node.DOCUMENT_TYPE_NODE
39
+ ]);
40
+ /**
41
+ * Is the value `undefined`, `null`, or a whitespace-only string?
42
+ * @param value Value to check
43
+ * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
44
+ */
45
+ function isNullableOrWhitespace(value) {
46
+ return value == null || EXPRESSION_WHITESPACE.test(getString(value));
47
+ }
48
+ var EXPRESSION_WHITESPACE = /^\s*$/;
49
+ Object.freeze([
50
+ "async",
51
+ "autofocus",
52
+ "autoplay",
53
+ "checked",
54
+ "controls",
55
+ "default",
56
+ "defer",
57
+ "disabled",
58
+ "formnovalidate",
59
+ "hidden",
60
+ "inert",
61
+ "ismap",
62
+ "itemscope",
63
+ "loop",
64
+ "multiple",
65
+ "muted",
66
+ "nomodule",
67
+ "novalidate",
68
+ "open",
69
+ "playsinline",
70
+ "readonly",
71
+ "required",
72
+ "reversed",
73
+ "selected"
74
+ ]);
75
+ document.createElement("form");
76
+ function setElementValues(element, first, second, third, callback) {
77
+ if (!isHTMLOrSVGElement(element)) return;
78
+ if (typeof first === "string") {
79
+ callback(element, first, second, third);
80
+ return;
81
+ }
82
+ const isArray = Array.isArray(first);
83
+ if (!isArray && !(typeof first === "object" && first !== null)) return;
84
+ const entries = isArray ? first : Object.entries(first).map(([name, value]) => ({
85
+ name,
86
+ value
87
+ }));
88
+ const { length } = entries;
89
+ for (let index = 0; index < length; index += 1) {
90
+ const entry = entries[index];
91
+ if (typeof entry === "object" && typeof entry?.name === "string") callback(element, entry.name, entry.value, third);
92
+ }
93
+ }
94
+ function updateElementValue(element, key, value, set, remove, isBoolean, json) {
95
+ if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
96
+ else set.call(element, key, json ? JSON.stringify(value) : String(value));
97
+ }
98
+ /**
99
+ * Set styles on an element
100
+ * @param element Element to set the styles on
101
+ * @param styles Styles to set
102
+ */
103
+ function setStyles(element, styles) {
104
+ setElementValues(element, styles, null, null, updateStyleProperty);
105
+ }
106
+ function updateStyleProperty(element, key, value) {
107
+ updateElementValue(element, key, value, function(property, style) {
108
+ this.style[property] = style;
109
+ }, function(property) {
110
+ this.style[property] = "";
111
+ }, false, false);
112
+ }
113
+ function createCell(width, body) {
114
+ const cell = createElement("div", {
115
+ className: "tabela__cell",
116
+ role: "cell"
117
+ }, { width: `${width}px` });
118
+ if (body ?? true) cell.classList.add("tabela__cell-body");
119
+ return cell;
120
+ }
121
+ function createElement(tagName, properties, style) {
122
+ const element = document.createElement(tagName);
123
+ const keys = Object.keys(properties);
124
+ for (const key of keys) element[key] = properties[key];
125
+ setStyles(element, style);
126
+ return element;
127
+ }
128
+ function createRowGroup(withRow) {
129
+ const group = createElement("div", {
130
+ className: "tabela__rowgroup",
131
+ role: "rowgroup"
132
+ }, {});
133
+ if (!(withRow ?? true)) return group;
134
+ const row = createRow(false);
135
+ group.append(row);
136
+ return {
137
+ group,
138
+ row
139
+ };
140
+ }
141
+ function createRow(withStyle) {
142
+ const row = createElement("div", {
143
+ className: "tabela__row",
144
+ role: "row"
145
+ }, {});
146
+ if (withStyle ?? true) setStyles(row, {
147
+ inset: "0 auto auto 0",
148
+ position: "absolute"
149
+ });
150
+ return row;
151
+ }
152
+ function createFaker() {
153
+ return createElement("div", {}, {
154
+ height: "0",
155
+ inset: "0 auto auto 0",
156
+ opacity: "0",
157
+ pointerEvents: "none",
158
+ position: "absolute",
159
+ width: "1px"
160
+ });
161
+ }
162
+ var BodyComponent = class {
163
+ elements = {
164
+ faker: createFaker(),
165
+ group: void 0
166
+ };
167
+ constructor(tabela) {
168
+ this.tabela = tabela;
169
+ const group = createRowGroup(false);
170
+ this.elements.group = group;
171
+ group.className += " tabela__rowgroup-body";
172
+ group.tabIndex = 0;
173
+ setStyles(group, {
174
+ height: "100%",
175
+ overflow: "auto",
176
+ position: "relative"
177
+ });
178
+ group.append(this.elements.faker);
179
+ }
180
+ destroy() {
181
+ this.elements.faker = void 0;
182
+ this.elements.group = void 0;
183
+ }
184
+ };
185
+ var FooterComponent = class {
186
+ elements;
187
+ constructor(tabela) {
188
+ this.tabela = tabela;
189
+ const { group, row } = createRowGroup();
190
+ this.elements = {
191
+ group,
192
+ row,
193
+ cells: []
194
+ };
195
+ group.className += " tabela__rowgroup-footer";
196
+ row.className += " tabela__row-footer";
197
+ }
198
+ destroy() {
199
+ this.elements.cells.length = 0;
200
+ this.elements.group = void 0;
201
+ this.elements.row = void 0;
202
+ }
203
+ update(columns) {
204
+ const { elements } = this;
205
+ const { length } = columns;
206
+ elements.cells.length = 0;
207
+ elements.row.innerHTML = "";
208
+ for (let index = 0; index < length; index += 1) {
209
+ const cell = createCell(columns[index].options.width ?? 4, false);
210
+ cell.className += " tabela__cell-footer";
211
+ cell.innerHTML = "&nbsp;";
212
+ elements.cells.push(cell);
213
+ elements.row.append(cell);
214
+ }
215
+ }
216
+ };
217
+ var HeaderComponent = class {
218
+ elements;
219
+ constructor(tabela) {
220
+ this.tabela = tabela;
221
+ const { group, row } = createRowGroup();
222
+ this.elements = {
223
+ group,
224
+ row
225
+ };
226
+ group.className += " tabela__rowgroup-header";
227
+ row.className += " tabela__row-header";
228
+ }
229
+ destroy() {
230
+ this.elements.group = void 0;
231
+ this.elements.row = void 0;
232
+ }
233
+ update(columns) {
234
+ this.elements.row.innerHTML = "";
235
+ this.elements.row.append(...columns.map((column) => column.element));
236
+ }
237
+ };
238
+ function createHeading(title, width) {
239
+ return createElement("div", {
240
+ className: "tabela__heading",
241
+ role: "columnheader",
242
+ textContent: title
243
+ }, { width: `${width}px` });
244
+ }
245
+ var ColumnComponent = class {
246
+ element;
247
+ options;
248
+ constructor(tabela, options) {
249
+ this.tabela = tabela;
250
+ const width = Number.parseInt(getComputedStyle(tabela.element).fontSize, 10) * (options.width ?? options.title.length * 1.5);
251
+ this.options = {
252
+ ...options,
253
+ width
254
+ };
255
+ this.element = createHeading(options.title, width);
256
+ }
257
+ };
258
+ var ColumnManager = class {
259
+ components = [];
260
+ constructor(tabela, columns) {
261
+ this.tabela = tabela;
262
+ this.set(columns);
263
+ }
264
+ destroy() {
265
+ this.components.length = 0;
266
+ }
267
+ remove(value) {
268
+ const { components, tabela } = this;
269
+ const fields = (Array.isArray(value) ? value : [value]).filter((item) => typeof item === "string");
270
+ const { length } = fields;
271
+ if (length === 0) return;
272
+ for (let fieldIndex = 0; fieldIndex < length; fieldIndex += 1) {
273
+ const componentIndex = components.findIndex((component) => component.options.field === fields[fieldIndex]);
274
+ if (componentIndex > -1) components.splice(componentIndex, 1);
275
+ }
276
+ tabela.components.header.update(components);
277
+ tabela.components.footer.update(components);
278
+ tabela.managers.virtualization.removeCells(fields);
279
+ }
280
+ set(columns) {
281
+ const { components, tabela } = this;
282
+ const { footer, header } = tabela.components;
283
+ components.splice(0, components.length, ...columns.map((column) => new ColumnComponent(tabela, column)));
284
+ header.update(components);
285
+ footer.update(components);
286
+ }
287
+ };
288
+ function getArrayCallback(value) {
289
+ switch (typeof value) {
290
+ case "function": return value;
291
+ case "number":
292
+ case "string": return typeof value === "string" && value.includes(".") ? void 0 : (obj) => obj[value];
293
+ default: break;
294
+ }
295
+ }
296
+ function getArrayCallbacks(bool, key, value) {
297
+ if (typeof bool === "function") return { bool };
298
+ return {
299
+ keyed: getArrayCallback(key),
300
+ value: getArrayCallback(value)
301
+ };
302
+ }
303
+ function getMapValues(array, first, second, arrays) {
304
+ if (!Array.isArray(array)) return /* @__PURE__ */ new Map();
305
+ const { length } = array;
306
+ const callbacks = getArrayCallbacks(void 0, first, second);
307
+ const map = /* @__PURE__ */ new Map();
308
+ for (let index = 0; index < length; index += 1) {
309
+ const item = array[index];
310
+ const key = callbacks?.keyed?.(item, index, array) ?? index;
311
+ const value = callbacks?.value?.(item, index, array) ?? item;
312
+ if (arrays) {
313
+ const existing = map.get(key);
314
+ if (existing == null) map.set(key, [value]);
315
+ else existing.push(value);
316
+ } else map.set(key, value);
317
+ }
318
+ return map;
319
+ }
320
+ function toMap(array, first, second) {
321
+ return getMapValues(array, first, second, false);
322
+ }
323
+ toMap.arrays = toMapArrays;
324
+ function toMapArrays(array, first, second) {
325
+ return getMapValues(array, first, second, true);
326
+ }
327
+ var DataManager = class {
328
+ values;
329
+ get length() {
330
+ return this.values.keys.active?.length ?? this.values.keys.original.length;
331
+ }
332
+ constructor(tabela, values) {
333
+ this.tabela = tabela;
334
+ const mapped = toMap(values, tabela.key);
335
+ this.values = {
336
+ keys: { original: [...mapped.keys()] },
337
+ objects: {
338
+ mapped,
339
+ array: values
340
+ }
341
+ };
342
+ }
343
+ destroy() {
344
+ const { values } = this;
345
+ values.objects.mapped.clear();
346
+ values.keys.active = void 0;
347
+ values.keys.original.length = 0;
348
+ values.objects.array.length = 0;
349
+ }
350
+ update() {
351
+ this.tabela.components.body.elements.faker.style.height = `${this.length * this.tabela.managers.rows.height}px`;
352
+ this.tabela.managers.virtualization.update(true);
353
+ }
354
+ };
355
+ function removeRow(row, pool) {
356
+ if (row.element != null) {
357
+ row.element.innerHTML = "";
358
+ pool.rows.push(row.element);
359
+ row.element.remove();
360
+ row.element = void 0;
361
+ }
362
+ row.cells = {};
363
+ }
364
+ function renderRow(tabela, pool, row) {
365
+ const element = row.element ?? pool.rows.shift() ?? createRow();
366
+ row.element = element;
367
+ element.dataset.key = String(row.key);
368
+ element.innerHTML = "";
369
+ const columns = tabela.managers.columns.components;
370
+ const { length } = columns;
371
+ const data = tabela.managers.data.values.objects.mapped.get(row.key);
372
+ if (data == null) return;
373
+ for (let index = 0; index < length; index += 1) {
374
+ const { options } = columns[index];
375
+ pool.cells[options.field] ??= [];
376
+ const cell = pool.cells[columns[index].options.field].shift() ?? createCell(options.width);
377
+ cell.textContent = String(data[options.field]);
378
+ row.cells[options.field] = cell;
379
+ element.append(cell);
380
+ }
381
+ }
382
+ var RowComponent = class {
383
+ cells = {};
384
+ element;
385
+ constructor(key) {
386
+ this.key = key;
387
+ }
388
+ };
389
+ var RowManager = class {
390
+ components = /* @__PURE__ */ new Map();
391
+ height;
392
+ constructor(tabela, rowHeight) {
393
+ this.tabela = tabela;
394
+ this.height = rowHeight;
395
+ }
396
+ destroy() {
397
+ this.components.clear();
398
+ }
399
+ get(key) {
400
+ let row = this.components.get(key);
401
+ if (row == null) {
402
+ row = new RowComponent(key);
403
+ this.components.set(key, row);
404
+ }
405
+ return row;
406
+ }
407
+ };
408
+ function addDelegatedHandler(doc, type, name, passive) {
409
+ if (DELEGATED.has(name)) return;
410
+ DELEGATED.add(name);
411
+ doc.addEventListener(type, passive ? HANDLER_PASSIVE : HANDLER_ACTIVE, { passive });
412
+ }
413
+ function addDelegatedListener(target, type, name, listener, passive) {
414
+ target[name] ??= /* @__PURE__ */ new Set();
415
+ target[name].add(listener);
416
+ addDelegatedHandler(document, type, name, passive);
417
+ return () => {
418
+ removeDelegatedListener(target, name, listener);
419
+ };
420
+ }
421
+ function delegatedEventHandler(event) {
422
+ const key = `${EVENT_PREFIX}${event.type}${this ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
423
+ const items = event.composedPath();
424
+ const { length } = items;
425
+ let target = items[0];
426
+ Object.defineProperties(event, {
427
+ currentTarget: {
428
+ configurable: true,
429
+ get() {
430
+ return target;
431
+ }
432
+ },
433
+ target: {
434
+ configurable: true,
435
+ value: target
436
+ }
437
+ });
438
+ for (let index = 0; index < length; index += 1) {
439
+ const item = items[index];
440
+ const listeners = item[key];
441
+ if (item.disabled || listeners == null) continue;
442
+ target = item;
443
+ for (const listener of listeners) {
444
+ listener.call(item, event);
445
+ if (event.cancelBubble) return;
446
+ }
447
+ }
448
+ }
449
+ function getDelegatedName(target, type, options) {
450
+ if (isEventTarget(target) && EVENT_TYPES.has(type) && !options.capture && !options.once && options.signal == null) return `${EVENT_PREFIX}${type}${options.passive ? EVENT_SUFFIX_PASSIVE : EVENT_SUFFIX_ACTIVE}`;
451
+ }
452
+ function removeDelegatedListener(target, name, listener) {
453
+ const handlers = target[name];
454
+ if (handlers == null || !handlers.has(listener)) return false;
455
+ handlers.delete(listener);
456
+ if (handlers.size === 0) target[name] = void 0;
457
+ return true;
458
+ }
459
+ var DELEGATED = /* @__PURE__ */ new Set();
460
+ var EVENT_PREFIX = "@";
461
+ var EVENT_SUFFIX_ACTIVE = ":active";
462
+ var EVENT_SUFFIX_PASSIVE = ":passive";
463
+ var EVENT_TYPES = new Set([
464
+ "beforeinput",
465
+ "click",
466
+ "dblclick",
467
+ "contextmenu",
468
+ "focusin",
469
+ "focusout",
470
+ "input",
471
+ "keydown",
472
+ "keyup",
473
+ "mousedown",
474
+ "mousemove",
475
+ "mouseout",
476
+ "mouseover",
477
+ "mouseup",
478
+ "pointerdown",
479
+ "pointermove",
480
+ "pointerout",
481
+ "pointerover",
482
+ "pointerup",
483
+ "touchend",
484
+ "touchmove",
485
+ "touchstart"
486
+ ]);
487
+ var HANDLER_ACTIVE = delegatedEventHandler.bind(false);
488
+ var HANDLER_PASSIVE = delegatedEventHandler.bind(true);
489
+ /**
490
+ * A function that does nothing, which can be useful, I guess…
491
+ */
492
+ function noop() {}
493
+ function createEventOptions(options) {
494
+ return {
495
+ capture: getBoolean(options?.capture),
496
+ once: getBoolean(options?.once),
497
+ passive: getBoolean(options?.passive, true),
498
+ signal: options?.signal instanceof AbortSignal ? options.signal : void 0
499
+ };
500
+ }
501
+ function on(target, type, listener, options) {
502
+ if (!isEventTarget(target) || typeof type !== "string" || typeof listener !== "function") return noop;
503
+ const extended = createEventOptions(options);
504
+ const delegated = getDelegatedName(target, type, extended);
505
+ if (delegated != null) return addDelegatedListener(target, type, delegated, listener, extended.passive);
506
+ target.addEventListener(type, listener, extended);
507
+ if (extended.once) return noop;
508
+ return () => {
509
+ target.removeEventListener(type, listener, extended);
510
+ };
511
+ }
512
+ function getRange(tabela, down) {
513
+ const { components, managers } = tabela;
514
+ const { body } = components;
515
+ const { data, rows } = managers;
516
+ const { clientHeight, scrollTop } = body.elements.group;
517
+ const first = Math.floor(scrollTop / rows.height);
518
+ const last = Math.min(data.length - 1, Math.ceil((scrollTop + clientHeight) / rows.height) - 1);
519
+ const before = Math.ceil(clientHeight / rows.height) * (down ? 1 : 2);
520
+ const after = Math.ceil(clientHeight / rows.height) * (down ? 2 : 1);
521
+ const start = Math.max(0, first - before);
522
+ return {
523
+ end: Math.min(data.length - 1, last + after),
524
+ start
525
+ };
526
+ }
527
+ function onScroll() {
528
+ if (!this.state.active) {
529
+ requestAnimationFrame(() => {
530
+ const top = this.tabela.components.body.elements.group.scrollTop;
531
+ this.update(top > this.state.top);
532
+ this.state.active = false;
533
+ this.state.top = top;
534
+ });
535
+ this.state.active = true;
536
+ }
537
+ }
538
+ var VirtualizationManager = class {
539
+ fragment;
540
+ listener;
541
+ pool = {
542
+ cells: {},
543
+ rows: []
544
+ };
545
+ state = {
546
+ active: false,
547
+ top: 0
548
+ };
549
+ visible = /* @__PURE__ */ new Map();
550
+ constructor(tabela) {
551
+ this.tabela = tabela;
552
+ this.listener = on(tabela.components.body.elements.group, "scroll", onScroll.bind(this));
553
+ }
554
+ destroy() {
555
+ this.listener();
556
+ for (const [index, row] of this.visible) {
557
+ removeRow(row, this.pool);
558
+ this.visible.delete(index);
559
+ }
560
+ this.pool.cells = {};
561
+ this.pool.rows = [];
562
+ }
563
+ removeCells(fields) {
564
+ const { length } = fields;
565
+ for (let index = 0; index < length; index += 1) delete this.pool.cells[fields[index]];
566
+ for (const [, row] of this.visible) for (let index = 0; index < length; index += 1) {
567
+ row.cells[fields[index]].innerHTML = "";
568
+ row.cells[fields[index]].remove();
569
+ delete row.cells[fields[index]];
570
+ }
571
+ }
572
+ update(down) {
573
+ const { tabela } = this;
574
+ const { rows } = tabela.managers;
575
+ const indices = /* @__PURE__ */ new Set();
576
+ const range = getRange(tabela, down);
577
+ for (let index = range.start; index <= range.end; index += 1) indices.add(index);
578
+ for (const [index, row] of this.visible) if (!indices.has(index)) {
579
+ this.visible.delete(index);
580
+ removeRow(row, this.pool);
581
+ }
582
+ this.fragment ??= document.createDocumentFragment();
583
+ this.fragment.replaceChildren();
584
+ const keys = tabela.managers.data.values.keys.active ?? tabela.managers.data.values.keys.original;
585
+ let count = 0;
586
+ for (let index = range.start; index <= range.end; index += 1) {
587
+ if (this.visible.has(index)) continue;
588
+ const row = tabela.managers.rows.get(keys[index]);
589
+ if (row == null) continue;
590
+ count += 1;
591
+ renderRow(tabela, this.pool, row);
592
+ this.visible.set(index, row);
593
+ if (row.element != null) {
594
+ row.element.style.transform = `translateY(${index * rows.height}px)`;
595
+ this.fragment.append(row.element);
596
+ }
597
+ }
598
+ if (count > 0) tabela.components.body.elements.group[down ? "append" : "prepend"](this.fragment);
599
+ }
600
+ };
601
+ var Tabela = class {
602
+ components;
603
+ key;
604
+ managers;
605
+ constructor(element, options) {
606
+ this.element = element;
607
+ element.innerHTML = "";
608
+ element.role = "table";
609
+ element.classList.add("tabela");
610
+ element.setAttribute("aria-label", options.label);
611
+ this.key = options.key;
612
+ this.components = {
613
+ header: new HeaderComponent(this),
614
+ body: new BodyComponent(this),
615
+ footer: new FooterComponent(this)
616
+ };
617
+ this.managers = {
618
+ columns: new ColumnManager(this, options.columns),
619
+ data: new DataManager(this, options.data),
620
+ rows: new RowManager(this, options.rowHeight),
621
+ virtualization: new VirtualizationManager(this)
622
+ };
623
+ element.append(this.components.header.elements.group, this.components.body.elements.group, this.components.footer.elements.group);
624
+ this.managers.data.update();
625
+ }
626
+ destroy() {
627
+ const { components, element, managers } = this;
628
+ components.body.destroy();
629
+ components.footer.destroy();
630
+ components.header.destroy();
631
+ managers.columns.destroy();
632
+ managers.data.destroy();
633
+ managers.rows.destroy();
634
+ element.innerHTML = "";
635
+ element.role = "";
636
+ element.classList.remove("tabela");
637
+ element.removeAttribute("aria-label");
638
+ element.removeAttribute("role");
639
+ this.element = void 0;
640
+ }
641
+ };
642
+ function tabela(element, options) {
643
+ return new Tabela(element, options);
644
+ }
645
+ export { tabela };