@oscarpalmer/tabela 0.11.0 → 0.12.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.
- package/dist/components/column.component.js +4 -4
- package/dist/components/group.component.js +28 -0
- package/dist/helpers/dom.helpers.js +1 -1
- package/dist/managers/data.manager.js +76 -15
- package/dist/managers/event.manager.js +3 -0
- package/dist/managers/filter.manager.js +5 -0
- package/dist/managers/group.manager.js +46 -0
- package/dist/managers/navigation.manager.js +1 -1
- package/dist/managers/render.manager.js +35 -10
- package/dist/managers/selection.manager.js +32 -27
- package/dist/managers/sort.manager.js +29 -2
- package/dist/models/group.model.js +0 -0
- package/dist/models/selection.model.js +0 -0
- package/dist/tabela.full.js +364 -398
- package/dist/tabela.js +4 -1
- package/package.json +1 -1
- package/src/components/column.component.ts +6 -6
- package/src/components/group.component.ts +43 -0
- package/src/components/row.component.ts +2 -2
- package/src/helpers/dom.helpers.ts +3 -1
- package/src/managers/column.manager.ts +4 -4
- package/src/managers/data.manager.ts +155 -21
- package/src/managers/event.manager.ts +7 -3
- package/src/managers/filter.manager.ts +19 -11
- package/src/managers/group.manager.ts +79 -0
- package/src/managers/navigation.manager.ts +6 -5
- package/src/managers/render.manager.ts +55 -17
- package/src/managers/row.manager.ts +2 -2
- package/src/managers/selection.manager.ts +48 -41
- package/src/managers/sort.manager.ts +76 -13
- package/src/models/column.model.ts +2 -2
- package/src/models/data.model.ts +14 -3
- package/src/models/filter.model.ts +11 -3
- package/src/models/group.model.ts +4 -0
- package/src/models/render.model.ts +2 -2
- package/src/models/selection.model.ts +9 -0
- package/src/models/sort.model.ts +11 -3
- package/src/models/tabela.model.ts +7 -41
- package/src/models/tabela.options.ts +3 -2
- package/src/tabela.ts +11 -12
- package/types/components/column.component.d.ts +3 -3
- package/types/components/group.component.d.ts +14 -0
- package/types/components/row.component.d.ts +2 -2
- package/types/helpers/style.helper.d.ts +1 -1
- package/types/managers/column.manager.d.ts +5 -5
- package/types/managers/data.manager.d.ts +5 -3
- package/types/managers/event.manager.d.ts +3 -3
- package/types/managers/filter.manager.d.ts +11 -11
- package/types/managers/group.manager.d.ts +17 -0
- package/types/managers/navigation.manager.d.ts +3 -3
- package/types/managers/render.manager.d.ts +4 -3
- package/types/managers/row.manager.d.ts +3 -3
- package/types/managers/selection.manager.d.ts +12 -6
- package/types/managers/sort.manager.d.ts +10 -8
- package/types/models/column.model.d.ts +2 -2
- package/types/models/data.model.d.ts +13 -3
- package/types/models/filter.model.d.ts +10 -3
- package/types/models/group.model.d.ts +4 -0
- package/types/models/render.model.d.ts +2 -2
- package/types/models/selection.model.d.ts +8 -0
- package/types/models/sort.model.d.ts +10 -3
- package/types/models/tabela.model.d.ts +7 -37
- package/types/models/tabela.options.d.ts +3 -2
- package/types/tabela.d.ts +4 -1
package/dist/tabela.full.js
CHANGED
|
@@ -319,9 +319,9 @@ new Set([
|
|
|
319
319
|
* @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
|
|
320
320
|
*/
|
|
321
321
|
function isNullableOrWhitespace$1(value) {
|
|
322
|
-
return value == null || EXPRESSION_WHITESPACE$
|
|
322
|
+
return value == null || EXPRESSION_WHITESPACE$1.test(getString$1(value));
|
|
323
323
|
}
|
|
324
|
-
var EXPRESSION_WHITESPACE$
|
|
324
|
+
var EXPRESSION_WHITESPACE$1 = /^\s*$/;
|
|
325
325
|
function setElementValue(element, first, second, third, callback) {
|
|
326
326
|
if (!isHTMLOrSVGElement(element)) return;
|
|
327
327
|
if (typeof first === "string") setElementValues(element, first, second, third, callback);
|
|
@@ -349,52 +349,9 @@ function updateElementValue(element, key, value, set, remove, isBoolean, json) {
|
|
|
349
349
|
if (isBoolean ? value == null : isNullableOrWhitespace$1(value)) remove.call(element, key);
|
|
350
350
|
else set.call(element, key, json ? JSON.stringify(value) : String(value));
|
|
351
351
|
}
|
|
352
|
-
function badAttributeHandler(name, value) {
|
|
353
|
-
if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
|
|
354
|
-
if (EXPRESSION_CLOBBERED_NAME.test(name) && (value in document || value in formElement) || EXPRESSION_EVENT_NAME.test(name)) return true;
|
|
355
|
-
if (EXPRESSION_SKIP_NAME.test(name) || EXPRESSION_URI_VALUE.test(value) || isValidSourceAttribute(name, value)) return false;
|
|
356
|
-
return EXPRESSION_DATA_OR_SCRIPT.test(value);
|
|
357
|
-
}
|
|
358
|
-
function booleanAttributeHandler(name, value) {
|
|
359
|
-
if (typeof name !== "string" || name.trim().length === 0 || typeof value !== "string") return true;
|
|
360
|
-
const normalizedName = name.toLowerCase();
|
|
361
|
-
if (!booleanAttributesSet.has(normalizedName)) return false;
|
|
362
|
-
const normalized = value.toLowerCase();
|
|
363
|
-
return !(normalized.length === 0 || normalized === normalizedName);
|
|
364
|
-
}
|
|
365
|
-
function decodeAttribute(value) {
|
|
366
|
-
textArea ??= document.createElement("textarea");
|
|
367
|
-
textArea.innerHTML = value;
|
|
368
|
-
return decodeURIComponent(textArea.value);
|
|
369
|
-
}
|
|
370
|
-
function handleAttribute(callback, decode, first, second) {
|
|
371
|
-
let name;
|
|
372
|
-
let value;
|
|
373
|
-
if (isAttribute(first)) {
|
|
374
|
-
name = first.name;
|
|
375
|
-
value = String(first.value);
|
|
376
|
-
} else if (typeof first === "string" && typeof second === "string") {
|
|
377
|
-
name = first;
|
|
378
|
-
value = second;
|
|
379
|
-
}
|
|
380
|
-
if (decode && value != null) value = decodeAttribute(value);
|
|
381
|
-
return callback(name, value?.replace(EXPRESSION_WHITESPACE$1, ""));
|
|
382
|
-
}
|
|
383
352
|
function isAttribute(value) {
|
|
384
353
|
return value instanceof Attr || isPlainObject$1(value) && typeof value.name === "string" && "value" in value;
|
|
385
354
|
}
|
|
386
|
-
function _isBadAttribute(first, second, decode) {
|
|
387
|
-
return handleAttribute(badAttributeHandler, decode, first, second);
|
|
388
|
-
}
|
|
389
|
-
function _isEmptyNonBooleanAttribute(first, second, decode) {
|
|
390
|
-
return handleAttribute((name, value) => name != null && value != null && !booleanAttributesSet.has(name) && value.trim().length === 0, decode, first, second);
|
|
391
|
-
}
|
|
392
|
-
function _isInvalidBooleanAttribute(first, second, decode) {
|
|
393
|
-
return handleAttribute(booleanAttributeHandler, decode, first, second);
|
|
394
|
-
}
|
|
395
|
-
function isValidSourceAttribute(name, value) {
|
|
396
|
-
return EXPRESSION_SOURCE_NAME.test(name) && EXPRESSION_SOURCE_VALUE.test(value);
|
|
397
|
-
}
|
|
398
355
|
function updateAttribute(element, name, value, dispatch) {
|
|
399
356
|
const normalizedName = name.toLowerCase();
|
|
400
357
|
const isBoolean = booleanAttributesSet.has(normalizedName);
|
|
@@ -408,14 +365,6 @@ function updateProperty(element, name, value, dispatch) {
|
|
|
408
365
|
const event = dispatch !== false && elementEvents[element.tagName]?.[name];
|
|
409
366
|
if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
|
|
410
367
|
}
|
|
411
|
-
var EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
|
|
412
|
-
var EXPRESSION_DATA_OR_SCRIPT = /^(?:data|\w+script):/i;
|
|
413
|
-
var EXPRESSION_EVENT_NAME = /^on/i;
|
|
414
|
-
var EXPRESSION_SKIP_NAME = /^(aria-[-\w]+|data-[-\w.\u00B7-\uFFFF]+)$/i;
|
|
415
|
-
var EXPRESSION_SOURCE_NAME = /^src$/i;
|
|
416
|
-
var EXPRESSION_SOURCE_VALUE = /^data:/i;
|
|
417
|
-
var EXPRESSION_URI_VALUE = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i;
|
|
418
|
-
var EXPRESSION_WHITESPACE$1 = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
|
|
419
368
|
/**
|
|
420
369
|
* List of boolean attributes
|
|
421
370
|
*/
|
|
@@ -455,8 +404,7 @@ var elementEvents = {
|
|
|
455
404
|
SELECT: { value: "change" },
|
|
456
405
|
TEXTAREA: { value: "input" }
|
|
457
406
|
};
|
|
458
|
-
|
|
459
|
-
var textArea;
|
|
407
|
+
document.createElement("form");
|
|
460
408
|
function setAttribute(element, first, second, third) {
|
|
461
409
|
setElementValue(element, first, second, third, updateAttribute);
|
|
462
410
|
}
|
|
@@ -560,7 +508,7 @@ function createRow() {
|
|
|
560
508
|
return createElement("div", {
|
|
561
509
|
className: "tabela__row",
|
|
562
510
|
role: "row"
|
|
563
|
-
}, {}, {});
|
|
511
|
+
}, {}, { height: "32px" });
|
|
564
512
|
}
|
|
565
513
|
function createFaker() {
|
|
566
514
|
return createElement("div", { className: "tabela__faker" }, {}, {});
|
|
@@ -637,13 +585,13 @@ var HeaderComponent = class {
|
|
|
637
585
|
var ColumnComponent = class {
|
|
638
586
|
elements;
|
|
639
587
|
options;
|
|
640
|
-
constructor(
|
|
641
|
-
const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (
|
|
588
|
+
constructor(column) {
|
|
589
|
+
const width = Number.parseInt(getComputedStyle(document.body).fontSize, 10) * (column.width ?? column.title.length * 1.5);
|
|
642
590
|
this.options = {
|
|
643
|
-
...
|
|
591
|
+
...column,
|
|
644
592
|
width
|
|
645
593
|
};
|
|
646
|
-
this.elements = createHeading(options.field, options.title, width);
|
|
594
|
+
this.elements = createHeading(this.options.field, this.options.title, width);
|
|
647
595
|
}
|
|
648
596
|
destroy() {
|
|
649
597
|
this.elements.content.remove();
|
|
@@ -864,35 +812,8 @@ function compact(array, strict) {
|
|
|
864
812
|
}
|
|
865
813
|
return compacted;
|
|
866
814
|
}
|
|
867
|
-
function
|
|
868
|
-
|
|
869
|
-
const actualStart = Math.min(Math.max(0, start), array.length);
|
|
870
|
-
const chunked = chunk(items);
|
|
871
|
-
const lastIndex = chunked.length - 1;
|
|
872
|
-
let index = Number(chunked.length);
|
|
873
|
-
let returned;
|
|
874
|
-
while (index > 0) {
|
|
875
|
-
index -= 1;
|
|
876
|
-
const spliced = array.splice(actualStart, index === lastIndex ? actualDeleteCount : 0, ...chunked[index]);
|
|
877
|
-
if (returned == null) returned = spliced;
|
|
878
|
-
else returned.push(...spliced);
|
|
879
|
-
}
|
|
880
|
-
if (type === "insert") return array;
|
|
881
|
-
return type === "splice" ? returned : array.length;
|
|
882
|
-
}
|
|
883
|
-
function insertValues(type, array, items, start, deleteCount) {
|
|
884
|
-
const spliceArray = type === "insert" || type === "splice";
|
|
885
|
-
if (!Array.isArray(array) || typeof start !== "number" || !Array.isArray(items) || items.length === 0) return spliceArray ? [] : 0;
|
|
886
|
-
return insertChunkedValues(type, array, items, start, spliceArray ? deleteCount : 0);
|
|
887
|
-
}
|
|
888
|
-
/**
|
|
889
|
-
* Push items into an array _(at the end)_
|
|
890
|
-
* @param array Original array
|
|
891
|
-
* @param pushed Pushed items
|
|
892
|
-
* @returns New length of the array
|
|
893
|
-
*/
|
|
894
|
-
function push(array, pushed) {
|
|
895
|
-
return insertValues("push", array, pushed, array.length, 0);
|
|
815
|
+
function select(array, ...parameters) {
|
|
816
|
+
return findValues("all", array, parameters, parameters.pop()).matched;
|
|
896
817
|
}
|
|
897
818
|
function aggregate(type, array, key) {
|
|
898
819
|
const length = Array.isArray(array) ? array.length : 0;
|
|
@@ -1159,6 +1080,172 @@ toMap.arrays = toMapArrays;
|
|
|
1159
1080
|
function toMapArrays(array, first, second) {
|
|
1160
1081
|
return getMapValues(array, first, second, true);
|
|
1161
1082
|
}
|
|
1083
|
+
function groupValues(array, key, value, arrays) {
|
|
1084
|
+
if (!Array.isArray(array) || array.length === 0) return {};
|
|
1085
|
+
const { length } = array;
|
|
1086
|
+
const callbacks = getArrayCallbacks(void 0, key, value);
|
|
1087
|
+
const record = {};
|
|
1088
|
+
for (let index = 0; index < length; index += 1) {
|
|
1089
|
+
const item = array[index];
|
|
1090
|
+
const keyed = callbacks?.keyed?.(item, index, array) ?? index;
|
|
1091
|
+
const valued = callbacks?.value?.(item, index, array) ?? item;
|
|
1092
|
+
if (arrays) {
|
|
1093
|
+
const existing = record[keyed];
|
|
1094
|
+
if (existing == null) record[keyed] = [valued];
|
|
1095
|
+
else existing.push(valued);
|
|
1096
|
+
} else record[keyed] = valued;
|
|
1097
|
+
}
|
|
1098
|
+
return record;
|
|
1099
|
+
}
|
|
1100
|
+
function toRecord(array, first, second) {
|
|
1101
|
+
return groupValues(array, first, second, false);
|
|
1102
|
+
}
|
|
1103
|
+
toRecord.arrays = toRecordArrays;
|
|
1104
|
+
function toRecordArrays(array, first, second) {
|
|
1105
|
+
return groupValues(array, first, second, true);
|
|
1106
|
+
}
|
|
1107
|
+
var GroupComponent = class {
|
|
1108
|
+
element;
|
|
1109
|
+
expanded = true;
|
|
1110
|
+
filtered = 0;
|
|
1111
|
+
selected = 0;
|
|
1112
|
+
total = 0;
|
|
1113
|
+
constructor(key, label, value) {
|
|
1114
|
+
this.key = key;
|
|
1115
|
+
this.label = label;
|
|
1116
|
+
this.value = value;
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
function renderGroup(state, component) {
|
|
1120
|
+
component.element ??= createElement("div", {
|
|
1121
|
+
className: "tabela__row tabela__row--group",
|
|
1122
|
+
innerHTML: `<div class="tabela__cell tabela__cell--group" role="cell">
|
|
1123
|
+
<button class="tabela__button tabela__button--group" data-event="group" data-key="${component.key}" type="button">
|
|
1124
|
+
<span aria-hidden="true"></span>
|
|
1125
|
+
<span>Open/close</span>
|
|
1126
|
+
</button>
|
|
1127
|
+
<p>${component.label}</p>
|
|
1128
|
+
</div>`,
|
|
1129
|
+
role: "row"
|
|
1130
|
+
}, {}, { height: `${state.options.rowHeight}px` });
|
|
1131
|
+
}
|
|
1132
|
+
var SortManager = class {
|
|
1133
|
+
handlers = Object.freeze({
|
|
1134
|
+
add: (field, direction) => this.add(field, direction),
|
|
1135
|
+
flip: (field) => this.flip(field),
|
|
1136
|
+
clear: () => this.clear(),
|
|
1137
|
+
remove: (field) => this.remove(field),
|
|
1138
|
+
set: (items) => this.set(items)
|
|
1139
|
+
});
|
|
1140
|
+
items = [];
|
|
1141
|
+
constructor(state) {
|
|
1142
|
+
this.state = state;
|
|
1143
|
+
}
|
|
1144
|
+
add(field, direction) {
|
|
1145
|
+
if (this.items.findIndex((item) => item.key === field) > -1) return;
|
|
1146
|
+
this.items.push({
|
|
1147
|
+
key: field,
|
|
1148
|
+
direction: direction ?? "ascending"
|
|
1149
|
+
});
|
|
1150
|
+
this.sort();
|
|
1151
|
+
}
|
|
1152
|
+
addOrSet(event, field) {
|
|
1153
|
+
if (event.ctrlKey || event.metaKey) this.add(field);
|
|
1154
|
+
else this.set([{
|
|
1155
|
+
field,
|
|
1156
|
+
direction: "ascending"
|
|
1157
|
+
}]);
|
|
1158
|
+
}
|
|
1159
|
+
clear() {
|
|
1160
|
+
if (this.items.length > 0) {
|
|
1161
|
+
this.items.length = 0;
|
|
1162
|
+
this.sort();
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
destroy() {
|
|
1166
|
+
this.handlers = void 0;
|
|
1167
|
+
this.items = void 0;
|
|
1168
|
+
this.state = void 0;
|
|
1169
|
+
}
|
|
1170
|
+
flip(field) {
|
|
1171
|
+
const item = this.items.find((item) => item.key === field);
|
|
1172
|
+
if (item == null) return;
|
|
1173
|
+
item.direction = item.direction === "ascending" ? "descending" : "ascending";
|
|
1174
|
+
this.sort();
|
|
1175
|
+
}
|
|
1176
|
+
remove(field) {
|
|
1177
|
+
const index = this.items.findIndex((item) => item.key === field);
|
|
1178
|
+
if (index > -1) {
|
|
1179
|
+
this.items.splice(index, 1);
|
|
1180
|
+
this.sort();
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
removeOrClear(event, field) {
|
|
1184
|
+
if (event.ctrlKey || event.metaKey) this.remove(field);
|
|
1185
|
+
else this.clear();
|
|
1186
|
+
}
|
|
1187
|
+
set(items) {
|
|
1188
|
+
this.items.splice(0, this.items.length, ...items.map((item) => ({
|
|
1189
|
+
key: item.field,
|
|
1190
|
+
direction: item.direction
|
|
1191
|
+
})));
|
|
1192
|
+
this.sort();
|
|
1193
|
+
}
|
|
1194
|
+
sort() {
|
|
1195
|
+
const { items, state } = this;
|
|
1196
|
+
const { length } = state.managers.column.items;
|
|
1197
|
+
for (let index = 0; index < length; index += 1) {
|
|
1198
|
+
const column = state.managers.column.items[index];
|
|
1199
|
+
const sorterIndex = items.findIndex((item) => item.key === column.options.field);
|
|
1200
|
+
const sorterItem = items[sorterIndex];
|
|
1201
|
+
setAttributes(column.elements.wrapper, {
|
|
1202
|
+
"aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
|
|
1203
|
+
"data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
|
|
1204
|
+
});
|
|
1205
|
+
setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
|
|
1206
|
+
}
|
|
1207
|
+
state.managers.data.values.keys.active = items.length === 0 ? void 0 : getSortedKeys(state, items);
|
|
1208
|
+
state.managers.render.update(true, true);
|
|
1209
|
+
}
|
|
1210
|
+
toggle(event, field, direction) {
|
|
1211
|
+
switch (direction) {
|
|
1212
|
+
case "ascending":
|
|
1213
|
+
this.flip(field);
|
|
1214
|
+
return;
|
|
1215
|
+
case "descending":
|
|
1216
|
+
this.removeOrClear(event, field);
|
|
1217
|
+
return;
|
|
1218
|
+
default:
|
|
1219
|
+
this.addOrSet(event, field);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
function getSortedKeys(state, sorters) {
|
|
1225
|
+
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();
|
|
1226
|
+
if (!state.managers.group.enabled) return sort(data, sorters).map((item) => item[state.key]);
|
|
1227
|
+
return sortWithGroups(state, data, sorters).map((item) => item instanceof GroupComponent ? item : item[state.key]);
|
|
1228
|
+
}
|
|
1229
|
+
function sortWithGroups(state, data, sorters) {
|
|
1230
|
+
const { length } = sorters;
|
|
1231
|
+
return data.sort((first, second) => {
|
|
1232
|
+
const firstValue = first instanceof GroupComponent ? first.value : first[state.managers.group.field];
|
|
1233
|
+
const secondValue = second instanceof GroupComponent ? second.value : second[state.managers.group.field];
|
|
1234
|
+
const firstOrder = state.managers.group.order[firstValue];
|
|
1235
|
+
const secondOrder = state.managers.group.order[secondValue];
|
|
1236
|
+
const groupComparison = compare(firstOrder, secondOrder);
|
|
1237
|
+
if (groupComparison !== 0) return groupComparison;
|
|
1238
|
+
const firstIsGroup = first instanceof GroupComponent;
|
|
1239
|
+
const secondIsGroup = second instanceof GroupComponent;
|
|
1240
|
+
if (firstIsGroup || secondIsGroup) return firstIsGroup && secondIsGroup ? 0 : firstIsGroup ? -1 : 1;
|
|
1241
|
+
for (let index = 0; index < length; index += 1) {
|
|
1242
|
+
const sorter = sorters[index];
|
|
1243
|
+
const comparison = compare(first[sorter.key], second[sorter.key]);
|
|
1244
|
+
if (comparison !== 0) return comparison * (sorter.direction === "ascending" ? 1 : -1);
|
|
1245
|
+
}
|
|
1246
|
+
return 0;
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1162
1249
|
/**
|
|
1163
1250
|
* Is the value `undefined`, `null`, or a whitespace-only string?
|
|
1164
1251
|
* @param value Value to check
|
|
@@ -1184,17 +1271,41 @@ var DataManager = class {
|
|
|
1184
1271
|
array: []
|
|
1185
1272
|
}
|
|
1186
1273
|
};
|
|
1274
|
+
get keys() {
|
|
1275
|
+
return this.values.keys.active ?? this.values.keys.original;
|
|
1276
|
+
}
|
|
1187
1277
|
get size() {
|
|
1188
|
-
return this.
|
|
1278
|
+
return this.keys.length;
|
|
1189
1279
|
}
|
|
1190
1280
|
constructor(state) {
|
|
1191
1281
|
this.state = state;
|
|
1192
1282
|
}
|
|
1193
1283
|
async add(data, render) {
|
|
1194
1284
|
const { state, values } = this;
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1285
|
+
const { length } = data;
|
|
1286
|
+
const updates = [];
|
|
1287
|
+
for (let index = 0; index < length; index += 1) {
|
|
1288
|
+
const item = data[index];
|
|
1289
|
+
const key = item[state.key];
|
|
1290
|
+
if (values.objects.mapped.has(key)) {
|
|
1291
|
+
updates.push(item);
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1294
|
+
values.objects.array.push(item);
|
|
1295
|
+
values.objects.mapped.set(key, item);
|
|
1296
|
+
if (!state.managers.group.enabled) continue;
|
|
1297
|
+
const groupKey = item[state.managers.group.field];
|
|
1298
|
+
let group = state.managers.group.get(groupKey);
|
|
1299
|
+
if (group == null) {
|
|
1300
|
+
group = new GroupComponent(String(groupKey), String(groupKey), groupKey);
|
|
1301
|
+
values.objects.array.push(group);
|
|
1302
|
+
state.managers.group.add(group);
|
|
1303
|
+
}
|
|
1304
|
+
if (!group.expanded) state.managers.group.collapsed.add(key);
|
|
1305
|
+
group.total += 1;
|
|
1306
|
+
}
|
|
1307
|
+
if (updates.length > 0) this.update(updates);
|
|
1308
|
+
else if (render) this.render();
|
|
1198
1309
|
}
|
|
1199
1310
|
clear() {
|
|
1200
1311
|
if (this.values.objects.array.length > 0) this.set([]);
|
|
@@ -1211,11 +1322,10 @@ var DataManager = class {
|
|
|
1211
1322
|
}
|
|
1212
1323
|
get(active) {
|
|
1213
1324
|
const { values } = this;
|
|
1214
|
-
return active ?? false ? values.keys.active
|
|
1325
|
+
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));
|
|
1215
1326
|
}
|
|
1216
1327
|
getIndex(key) {
|
|
1217
|
-
|
|
1218
|
-
return (values.keys.active ?? values.keys.original).indexOf(key);
|
|
1328
|
+
return this.keys.indexOf(key);
|
|
1219
1329
|
}
|
|
1220
1330
|
async remove(items, render) {
|
|
1221
1331
|
const { state, values } = this;
|
|
@@ -1225,24 +1335,59 @@ var DataManager = class {
|
|
|
1225
1335
|
for (let keyIndex = 0; keyIndex < length; keyIndex += 1) {
|
|
1226
1336
|
const key = keys[keyIndex];
|
|
1227
1337
|
values.objects.mapped.delete(key);
|
|
1228
|
-
const arrayIndex = values.objects.array.findIndex((
|
|
1229
|
-
|
|
1338
|
+
const arrayIndex = values.objects.array.findIndex((item) => !(item instanceof GroupComponent) && item[state.key] === key);
|
|
1339
|
+
let item;
|
|
1340
|
+
if (arrayIndex > -1) [item] = values.objects.array.splice(arrayIndex, 1);
|
|
1230
1341
|
values.keys.original.splice(values.keys.original.indexOf(key), 1);
|
|
1231
1342
|
state.managers.row.remove(key);
|
|
1343
|
+
if (!state.managers.group.enabled || item == null) continue;
|
|
1344
|
+
state.managers.group.collapsed.delete(key);
|
|
1345
|
+
const groupKey = item[state.managers.group.field];
|
|
1346
|
+
const group = state.managers.group.get(groupKey);
|
|
1347
|
+
if (group == null) continue;
|
|
1348
|
+
group.total -= 1;
|
|
1349
|
+
if (group.total > 0) continue;
|
|
1350
|
+
const groupIndex = values.objects.array.findIndex((item) => item instanceof GroupComponent && item.value === groupKey);
|
|
1351
|
+
if (groupIndex > -1) values.objects.array.splice(groupIndex, 1);
|
|
1352
|
+
state.managers.group.remove(group);
|
|
1232
1353
|
}
|
|
1233
1354
|
if (render) this.render();
|
|
1234
1355
|
}
|
|
1235
1356
|
render() {
|
|
1236
1357
|
const { state, values } = this;
|
|
1237
|
-
|
|
1358
|
+
if (state.managers.group.enabled) sortWithGroups(state, values.objects.array, [{
|
|
1359
|
+
direction: "ascending",
|
|
1360
|
+
key: state.key
|
|
1361
|
+
}]);
|
|
1362
|
+
else sort(values.objects.array, [{
|
|
1363
|
+
direction: "ascending",
|
|
1364
|
+
key: state.key
|
|
1365
|
+
}]);
|
|
1366
|
+
values.keys.original = values.objects.array.map((item) => item instanceof GroupComponent ? item : item[state.key]);
|
|
1367
|
+
values.objects.mapped = toMap(values.objects.array.filter((item) => !(item instanceof GroupComponent)), (item) => item[state.key]);
|
|
1238
1368
|
if (Object.keys(state.managers.filter.items).length > 0) state.managers.filter.filter();
|
|
1239
1369
|
else if (state.managers.sort.items.length > 0) state.managers.sort.sort();
|
|
1240
|
-
else state.managers.render.update(true);
|
|
1370
|
+
else state.managers.render.update(true, true);
|
|
1241
1371
|
}
|
|
1242
1372
|
set(data) {
|
|
1243
1373
|
const { state, values } = this;
|
|
1244
|
-
|
|
1245
|
-
|
|
1374
|
+
const array = data.slice();
|
|
1375
|
+
if (state.managers.group.enabled) {
|
|
1376
|
+
const grouped = toRecord.arrays(data, state.managers.group.field);
|
|
1377
|
+
const entries = Object.entries(grouped);
|
|
1378
|
+
const { length } = entries;
|
|
1379
|
+
const groups = [];
|
|
1380
|
+
for (let index = 0; index < length; index += 1) {
|
|
1381
|
+
const [value, items] = entries[index];
|
|
1382
|
+
const key = String(value);
|
|
1383
|
+
const group = new GroupComponent(key, key, value);
|
|
1384
|
+
group.total = items.length;
|
|
1385
|
+
groups.push(group);
|
|
1386
|
+
array.push(group);
|
|
1387
|
+
}
|
|
1388
|
+
state.managers.group.set(groups);
|
|
1389
|
+
}
|
|
1390
|
+
values.objects.array = array;
|
|
1246
1391
|
this.render();
|
|
1247
1392
|
}
|
|
1248
1393
|
async synchronize(data, remove) {
|
|
@@ -1260,7 +1405,7 @@ var DataManager = class {
|
|
|
1260
1405
|
}
|
|
1261
1406
|
if (keys.size === 0) return;
|
|
1262
1407
|
if (remove ?? false) {
|
|
1263
|
-
const toRemove = values.keys.original.filter((key) => !keys.has(key));
|
|
1408
|
+
const toRemove = values.keys.original.filter((key) => !(key instanceof GroupComponent) && !keys.has(key));
|
|
1264
1409
|
if (toRemove.length > 0) await this.remove(toRemove, false);
|
|
1265
1410
|
}
|
|
1266
1411
|
await this.update(updated);
|
|
@@ -1450,6 +1595,9 @@ function onClick(event) {
|
|
|
1450
1595
|
const manager = mapped$1.get(table);
|
|
1451
1596
|
if (manager == null) return;
|
|
1452
1597
|
switch (target?.getAttribute("data-event")) {
|
|
1598
|
+
case "group":
|
|
1599
|
+
manager.state.managers.group.handle(target);
|
|
1600
|
+
break;
|
|
1453
1601
|
case "heading":
|
|
1454
1602
|
manager.onSort(event, target);
|
|
1455
1603
|
break;
|
|
@@ -1906,6 +2054,10 @@ var FilterManager = class {
|
|
|
1906
2054
|
const keysLength = state.managers.data.values.keys.original.length;
|
|
1907
2055
|
rowLoop: for (let keyIndex = 0; keyIndex < keysLength; keyIndex += 1) {
|
|
1908
2056
|
const key = state.managers.data.values.keys.original[keyIndex];
|
|
2057
|
+
if (key instanceof GroupComponent) {
|
|
2058
|
+
filtered.push(key);
|
|
2059
|
+
continue;
|
|
2060
|
+
}
|
|
1909
2061
|
const row = state.managers.data.values.objects.mapped.get(key);
|
|
1910
2062
|
if (row == null) continue;
|
|
1911
2063
|
filterLoop: for (let filterIndex = 0; filterIndex < filters.length; filterIndex += 1) {
|
|
@@ -1959,6 +2111,48 @@ const comparators = {
|
|
|
1959
2111
|
"starts-with": (row, filter) => startsWith(getString(row), getString(filter), true)
|
|
1960
2112
|
};
|
|
1961
2113
|
const equalizer = equal.initialize({ ignoreCase: true });
|
|
2114
|
+
var GroupManager = class {
|
|
2115
|
+
collapsed = /* @__PURE__ */ new Set();
|
|
2116
|
+
enabled = false;
|
|
2117
|
+
field;
|
|
2118
|
+
items = [];
|
|
2119
|
+
order = {};
|
|
2120
|
+
constructor(state) {
|
|
2121
|
+
this.state = state;
|
|
2122
|
+
if (isNullableOrWhitespace(state.options.grouping)) return;
|
|
2123
|
+
this.enabled = true;
|
|
2124
|
+
this.field = state.options.grouping;
|
|
2125
|
+
}
|
|
2126
|
+
add(group) {
|
|
2127
|
+
this.set([...this.items, group]);
|
|
2128
|
+
}
|
|
2129
|
+
get(value) {
|
|
2130
|
+
return this.items.find((item) => item.value === value);
|
|
2131
|
+
}
|
|
2132
|
+
handle(button) {
|
|
2133
|
+
const key = button.dataset.key;
|
|
2134
|
+
const group = this.get(key);
|
|
2135
|
+
if (group == null) return;
|
|
2136
|
+
const { collapsed, items, state } = this;
|
|
2137
|
+
group.expanded = !group.expanded;
|
|
2138
|
+
const index = items.indexOf(group);
|
|
2139
|
+
let first = state.managers.data.values.keys.original.indexOf(items[index]) + 1;
|
|
2140
|
+
const last = items[index + 1] == null ? state.managers.data.keys.length - 1 : state.managers.data.values.keys.original.indexOf(items[index + 1]) - 1;
|
|
2141
|
+
for (; first <= last; first += 1) {
|
|
2142
|
+
const key = state.managers.data.values.keys.original[first];
|
|
2143
|
+
if (group.expanded) collapsed.delete(key);
|
|
2144
|
+
else collapsed.add(key);
|
|
2145
|
+
}
|
|
2146
|
+
state.managers.render.update(true, true);
|
|
2147
|
+
}
|
|
2148
|
+
remove(group) {
|
|
2149
|
+
this.set(this.items.filter((item) => item !== group));
|
|
2150
|
+
}
|
|
2151
|
+
set(items) {
|
|
2152
|
+
this.items = sort(items, (item) => item.label);
|
|
2153
|
+
this.order = toRecord(items, "value", (_, index) => index);
|
|
2154
|
+
}
|
|
2155
|
+
};
|
|
1962
2156
|
function getKey(value) {
|
|
1963
2157
|
if (typeof value === "number") return value;
|
|
1964
2158
|
if (typeof value !== "string") return;
|
|
@@ -1978,7 +2172,7 @@ var NavigationManager = class {
|
|
|
1978
2172
|
event.preventDefault();
|
|
1979
2173
|
const { components, id, managers } = this.state;
|
|
1980
2174
|
const activeDescendant = components.body.elements.group.getAttribute("aria-activedescendant");
|
|
1981
|
-
const keys = managers.data
|
|
2175
|
+
const { keys } = managers.data;
|
|
1982
2176
|
const { length } = keys;
|
|
1983
2177
|
let next;
|
|
1984
2178
|
if (isNullableOrWhitespace(activeDescendant)) next = getDefaultIndex(event.key, length);
|
|
@@ -2079,16 +2273,17 @@ var RowComponent = class {
|
|
|
2079
2273
|
this.key = key;
|
|
2080
2274
|
}
|
|
2081
2275
|
};
|
|
2082
|
-
function getRange(down) {
|
|
2083
|
-
const { components, managers, options } =
|
|
2276
|
+
function getRange(state, down) {
|
|
2277
|
+
const { components, managers, options } = state;
|
|
2084
2278
|
const { clientHeight, scrollTop } = components.body.elements.group;
|
|
2279
|
+
const { keys } = managers.data;
|
|
2085
2280
|
const first = Math.floor(scrollTop / options.rowHeight);
|
|
2086
|
-
const last = Math.min(
|
|
2281
|
+
const last = Math.min(keys.length - managers.group.collapsed.size - 1, Math.ceil((scrollTop + clientHeight) / options.rowHeight) - 1);
|
|
2087
2282
|
const before = Math.ceil(clientHeight / options.rowHeight) * (down ? 1 : 2);
|
|
2088
2283
|
const after = Math.ceil(clientHeight / options.rowHeight) * (down ? 2 : 1);
|
|
2089
2284
|
const start = Math.max(0, first - before);
|
|
2090
2285
|
return {
|
|
2091
|
-
end: Math.min(
|
|
2286
|
+
end: Math.min(keys.length - managers.group.collapsed.size - 1, last + after),
|
|
2092
2287
|
start
|
|
2093
2288
|
};
|
|
2094
2289
|
}
|
|
@@ -2138,6 +2333,7 @@ var RenderManager = class {
|
|
|
2138
2333
|
const { length } = fields;
|
|
2139
2334
|
for (let index = 0; index < length; index += 1) delete pool.cells[fields[index]];
|
|
2140
2335
|
for (const [, key] of visible) {
|
|
2336
|
+
if (key instanceof GroupComponent) continue;
|
|
2141
2337
|
const row = state.managers.row.get(key);
|
|
2142
2338
|
if (row == null || row.element == null) continue;
|
|
2143
2339
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -2155,31 +2351,53 @@ var RenderManager = class {
|
|
|
2155
2351
|
update(down, rerender) {
|
|
2156
2352
|
const { state, pool, visible } = this;
|
|
2157
2353
|
const { components, managers, options } = state;
|
|
2158
|
-
components.body.elements.faker.style.height = `${managers.data.size * options.rowHeight}px`;
|
|
2354
|
+
components.body.elements.faker.style.height = `${(managers.data.size - managers.group.collapsed.size) * options.rowHeight}px`;
|
|
2159
2355
|
const indices = /* @__PURE__ */ new Set();
|
|
2160
|
-
const range = getRange
|
|
2356
|
+
const range = getRange(state, down);
|
|
2161
2357
|
for (let index = range.start; index <= range.end; index += 1) indices.add(index);
|
|
2162
2358
|
let remove = rerender ?? false;
|
|
2163
2359
|
for (const [index, key] of visible) {
|
|
2360
|
+
if (key instanceof GroupComponent) {
|
|
2361
|
+
if (remove || !indices.has(index)) {
|
|
2362
|
+
visible.delete(index);
|
|
2363
|
+
key.element?.remove();
|
|
2364
|
+
}
|
|
2365
|
+
continue;
|
|
2366
|
+
}
|
|
2164
2367
|
const row = managers.row.get(key);
|
|
2165
|
-
if (remove || row == null || !indices.has(index)) {
|
|
2368
|
+
if (remove || row == null || !indices.has(index) || managers.group.collapsed.has(key)) {
|
|
2166
2369
|
visible.delete(index);
|
|
2167
2370
|
if (row != null) removeRow(pool, row);
|
|
2168
2371
|
}
|
|
2169
2372
|
}
|
|
2170
2373
|
const fragment = this.getFragment();
|
|
2171
|
-
const keys = managers.data
|
|
2374
|
+
const { keys } = managers.data;
|
|
2172
2375
|
let count = 0;
|
|
2173
|
-
|
|
2376
|
+
let offset = 0;
|
|
2377
|
+
for (let index = range.start; index <= range.end + offset; index += 1) {
|
|
2174
2378
|
if (visible.has(index)) continue;
|
|
2175
2379
|
const key = keys[index];
|
|
2380
|
+
if (key instanceof GroupComponent) {
|
|
2381
|
+
count += 1;
|
|
2382
|
+
renderGroup(state, key);
|
|
2383
|
+
visible.set(index, key);
|
|
2384
|
+
if (key.element != null) {
|
|
2385
|
+
key.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
|
|
2386
|
+
fragment.append(key.element);
|
|
2387
|
+
}
|
|
2388
|
+
continue;
|
|
2389
|
+
}
|
|
2176
2390
|
const row = managers.row.get(key);
|
|
2177
2391
|
if (row == null) continue;
|
|
2392
|
+
if (managers.group.collapsed.has(key)) {
|
|
2393
|
+
offset += 1;
|
|
2394
|
+
continue;
|
|
2395
|
+
}
|
|
2178
2396
|
count += 1;
|
|
2179
2397
|
renderRow(state, row);
|
|
2180
2398
|
visible.set(index, key);
|
|
2181
2399
|
if (row.element != null) {
|
|
2182
|
-
row.element.style.transform = `translateY(${index * options.rowHeight}px)`;
|
|
2400
|
+
row.element.style.transform = `translateY(${(index - offset) * options.rowHeight}px)`;
|
|
2183
2401
|
fragment.append(row.element);
|
|
2184
2402
|
}
|
|
2185
2403
|
}
|
|
@@ -2222,181 +2440,16 @@ var RowManager = class {
|
|
|
2222
2440
|
if (row != null) renderRow(this.state, row);
|
|
2223
2441
|
}
|
|
2224
2442
|
};
|
|
2225
|
-
function isInert(item) {
|
|
2226
|
-
return (item.element.inert ?? false) || EXPRESSION_TRUEISH.test(item.element.getAttribute(ATTRIBUTE_INERT)) || item.element.parentElement != null && isInert({
|
|
2227
|
-
element: item.element.parentElement,
|
|
2228
|
-
tabIndex: TABINDEX_DEFAULT
|
|
2229
|
-
});
|
|
2230
|
-
}
|
|
2231
|
-
var ATTRIBUTE_INERT = "inert";
|
|
2232
|
-
var EXPRESSION_TRUEISH = /^(|true)$/i;
|
|
2233
|
-
[
|
|
2234
|
-
"[contenteditable]:not([contenteditable=\"false\"])",
|
|
2235
|
-
"[tabindex]:not(slot)",
|
|
2236
|
-
"a[href]",
|
|
2237
|
-
"audio[controls]",
|
|
2238
|
-
"button",
|
|
2239
|
-
"details",
|
|
2240
|
-
"details > summary:first-of-type",
|
|
2241
|
-
"input",
|
|
2242
|
-
"select",
|
|
2243
|
-
"textarea",
|
|
2244
|
-
"video[controls]"
|
|
2245
|
-
].map((selector) => `${selector}:not([inert])`).join(",");
|
|
2246
|
-
var TABINDEX_DEFAULT = -1;
|
|
2247
|
-
function handleElement(element, depth) {
|
|
2248
|
-
if (depth === 0) {
|
|
2249
|
-
const removable = element.querySelectorAll(REMOVE_SELECTOR);
|
|
2250
|
-
for (const item of removable) item.remove();
|
|
2251
|
-
}
|
|
2252
|
-
sanitizeAttributes(element, [...element.attributes]);
|
|
2253
|
-
}
|
|
2254
|
-
/**
|
|
2255
|
-
* Is the element clobbered?
|
|
2256
|
-
*
|
|
2257
|
-
* Thanks, DOMPurify _(https://github.com/cure53/DOMPurify)_
|
|
2258
|
-
*/
|
|
2259
|
-
function isClobbered(value) {
|
|
2260
|
-
return value instanceof HTMLFormElement && (typeof value.nodeName !== "string" || typeof value.textContent !== "string" || typeof value.removeChild !== "function" || !(value.attributes instanceof NamedNodeMap) || typeof value.removeAttribute !== "function" || typeof value.setAttribute !== "function" || typeof value.namespaceURI !== "string" || typeof value.insertBefore !== "function" || typeof value.hasChildNodes !== "function");
|
|
2261
|
-
}
|
|
2262
|
-
function removeNode(node) {
|
|
2263
|
-
if (typeof node.remove === "function") node.remove();
|
|
2264
|
-
}
|
|
2265
|
-
function sanitizeAttributes(element, attributes) {
|
|
2266
|
-
const { length } = attributes;
|
|
2267
|
-
for (let index = 0; index < length; index += 1) {
|
|
2268
|
-
const { name, value } = attributes[index];
|
|
2269
|
-
if (_isBadAttribute(name, value, false) || _isEmptyNonBooleanAttribute(name, value, false)) element.removeAttribute(name);
|
|
2270
|
-
else if (_isInvalidBooleanAttribute(name, value, false)) setAttribute(element, name, true);
|
|
2271
|
-
}
|
|
2272
|
-
}
|
|
2273
|
-
function sanitizeNodes(nodes, depth) {
|
|
2274
|
-
const actual = nodes.filter((node) => node instanceof Node);
|
|
2275
|
-
let { length } = nodes;
|
|
2276
|
-
for (let index = 0; index < length; index += 1) {
|
|
2277
|
-
const node = actual[index];
|
|
2278
|
-
let remove = isClobbered(node);
|
|
2279
|
-
if (!remove) switch (node.nodeType) {
|
|
2280
|
-
case Node.ELEMENT_NODE:
|
|
2281
|
-
handleElement(node, depth);
|
|
2282
|
-
break;
|
|
2283
|
-
case Node.COMMENT_NODE:
|
|
2284
|
-
remove = COMMENT_HARMFUL.test(node.data);
|
|
2285
|
-
break;
|
|
2286
|
-
case Node.DOCUMENT_TYPE_NODE:
|
|
2287
|
-
case Node.PROCESSING_INSTRUCTION_NODE:
|
|
2288
|
-
remove = true;
|
|
2289
|
-
break;
|
|
2290
|
-
}
|
|
2291
|
-
if (remove) {
|
|
2292
|
-
removeNode(node);
|
|
2293
|
-
actual.splice(index, 1);
|
|
2294
|
-
index -= 1;
|
|
2295
|
-
length -= 1;
|
|
2296
|
-
continue;
|
|
2297
|
-
}
|
|
2298
|
-
if (node.hasChildNodes()) sanitizeNodes([...node.childNodes], depth + 1);
|
|
2299
|
-
}
|
|
2300
|
-
return nodes;
|
|
2301
|
-
}
|
|
2302
|
-
var COMMENT_HARMFUL = /<[/\w]/g;
|
|
2303
|
-
var REMOVE_SELECTOR = "script, toretto-temporary";
|
|
2304
|
-
function createHtml(value) {
|
|
2305
|
-
const parsed = getParser().parseFromString(getHtml(value), PARSE_TYPE_HTML);
|
|
2306
|
-
parsed.body.normalize();
|
|
2307
|
-
sanitizeNodes([parsed.body], 0);
|
|
2308
|
-
return parsed.body.innerHTML;
|
|
2309
|
-
}
|
|
2310
|
-
function createTemplate(value, options) {
|
|
2311
|
-
const template = document.createElement(TEMPLATE_TAG);
|
|
2312
|
-
template.innerHTML = createHtml(value);
|
|
2313
|
-
if (typeof value === "string" && options.cache) templates[value] = template;
|
|
2314
|
-
return template;
|
|
2315
|
-
}
|
|
2316
|
-
function getHtml(value) {
|
|
2317
|
-
return `${TEMPORARY_ELEMENT}${typeof value === "string" ? value : value.innerHTML}${TEMPORARY_ELEMENT}`;
|
|
2318
|
-
}
|
|
2319
|
-
function getNodes(value, options) {
|
|
2320
|
-
if (typeof value !== "string" && !(value instanceof HTMLTemplateElement)) return [];
|
|
2321
|
-
const template = getTemplate(value, options);
|
|
2322
|
-
return template == null ? [] : [...template.content.cloneNode(true).childNodes];
|
|
2323
|
-
}
|
|
2324
|
-
function getOptions(input) {
|
|
2325
|
-
const options = isPlainObject$1(input) ? input : {};
|
|
2326
|
-
options.cache = typeof options.cache === "boolean" ? options.cache : true;
|
|
2327
|
-
return options;
|
|
2328
|
-
}
|
|
2329
|
-
function getParser() {
|
|
2330
|
-
parser ??= new DOMParser();
|
|
2331
|
-
return parser;
|
|
2332
|
-
}
|
|
2333
|
-
function getTemplate(value, options) {
|
|
2334
|
-
if (value instanceof HTMLTemplateElement) return createTemplate(value, options);
|
|
2335
|
-
if (value.trim().length === 0) return;
|
|
2336
|
-
let template = templates[value];
|
|
2337
|
-
if (template != null) return template;
|
|
2338
|
-
const element = EXPRESSION_ID.test(value) ? document.querySelector(`#${value}`) : null;
|
|
2339
|
-
return createTemplate(element instanceof HTMLTemplateElement ? element : value, options);
|
|
2340
|
-
}
|
|
2341
|
-
var html = ((value, options) => {
|
|
2342
|
-
return getNodes(value, getOptions(options));
|
|
2343
|
-
});
|
|
2344
|
-
html.clear = () => {
|
|
2345
|
-
templates = {};
|
|
2346
|
-
};
|
|
2347
|
-
html.remove = (template) => {
|
|
2348
|
-
if (typeof template !== "string" || templates[template] == null) return;
|
|
2349
|
-
const keys = Object.keys(templates);
|
|
2350
|
-
const { length } = keys;
|
|
2351
|
-
const updated = {};
|
|
2352
|
-
for (let index = 0; index < length; index += 1) {
|
|
2353
|
-
const key = keys[index];
|
|
2354
|
-
if (key !== template) updated[key] = templates[key];
|
|
2355
|
-
}
|
|
2356
|
-
templates = updated;
|
|
2357
|
-
};
|
|
2358
|
-
var EXPRESSION_ID = /^[a-z][\w-]*$/i;
|
|
2359
|
-
var PARSE_TYPE_HTML = "text/html";
|
|
2360
|
-
var TEMPLATE_TAG = "template";
|
|
2361
|
-
var TEMPORARY_ELEMENT = "<toretto-temporary></toretto-temporary>";
|
|
2362
|
-
var parser;
|
|
2363
|
-
var templates = {};
|
|
2364
|
-
function getSupport() {
|
|
2365
|
-
if (window == null || navigator == null) return false;
|
|
2366
|
-
if ("matchMedia" in window) {
|
|
2367
|
-
const media = matchMedia?.("(pointer: coarse)");
|
|
2368
|
-
if (typeof media?.matches === "boolean" && media.matches) return true;
|
|
2369
|
-
}
|
|
2370
|
-
if ("ontouchstart" in window) return true;
|
|
2371
|
-
if (typeof navigator.maxTouchPoints === "number" && navigator.maxTouchPoints > 0) return true;
|
|
2372
|
-
if (typeof navigator.msMaxTouchPoints === "number" && navigator.msMaxTouchPoints > 0) return true;
|
|
2373
|
-
return false;
|
|
2374
|
-
}
|
|
2375
|
-
(() => {
|
|
2376
|
-
let support = getSupport();
|
|
2377
|
-
const instance = Object.create({
|
|
2378
|
-
get() {
|
|
2379
|
-
return support;
|
|
2380
|
-
},
|
|
2381
|
-
update() {
|
|
2382
|
-
support = getSupport();
|
|
2383
|
-
return support;
|
|
2384
|
-
}
|
|
2385
|
-
});
|
|
2386
|
-
Object.defineProperty(instance, "value", { get() {
|
|
2387
|
-
return support;
|
|
2388
|
-
} });
|
|
2389
|
-
return instance;
|
|
2390
|
-
})();
|
|
2391
2443
|
const dragStyling = toggleStyles(document.body, {
|
|
2392
2444
|
userSelect: "none",
|
|
2393
2445
|
webkitUserSelect: "none"
|
|
2394
2446
|
});
|
|
2395
2447
|
var SelectionManager = class {
|
|
2396
2448
|
handlers = Object.freeze({
|
|
2449
|
+
add: (keys) => this.add(keys),
|
|
2397
2450
|
clear: () => this.clear(),
|
|
2398
|
-
|
|
2399
|
-
|
|
2451
|
+
remove: (keys) => this.remove(keys),
|
|
2452
|
+
set: (keys) => this.set(keys),
|
|
2400
2453
|
toggle: () => this.toggle()
|
|
2401
2454
|
});
|
|
2402
2455
|
items = /* @__PURE__ */ new Set();
|
|
@@ -2405,21 +2458,24 @@ var SelectionManager = class {
|
|
|
2405
2458
|
this.state = state;
|
|
2406
2459
|
mapped.set(state.element, this);
|
|
2407
2460
|
}
|
|
2461
|
+
add(keys) {
|
|
2462
|
+
const { length } = keys;
|
|
2463
|
+
let update = false;
|
|
2464
|
+
for (let index = 0; index < length; index += 1) {
|
|
2465
|
+
const key = keys[index];
|
|
2466
|
+
if (!this.items.has(key)) {
|
|
2467
|
+
this.items.add(key);
|
|
2468
|
+
update = true;
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
if (update) this.update([]);
|
|
2472
|
+
}
|
|
2408
2473
|
clear() {
|
|
2409
2474
|
if (this.items.size === 0) return;
|
|
2410
2475
|
const removed = [...this.items];
|
|
2411
2476
|
this.items.clear();
|
|
2412
2477
|
this.update(removed);
|
|
2413
2478
|
}
|
|
2414
|
-
deselect(keys) {
|
|
2415
|
-
const { length } = keys;
|
|
2416
|
-
const removed = [];
|
|
2417
|
-
for (let index = 0; index < length; index += 1) {
|
|
2418
|
-
const key = keys[index];
|
|
2419
|
-
if (this.items.delete(key)) removed.push(key);
|
|
2420
|
-
}
|
|
2421
|
-
if (removed.length > 0) this.update(removed);
|
|
2422
|
-
}
|
|
2423
2479
|
destroy() {
|
|
2424
2480
|
mapped.delete(this.state.element);
|
|
2425
2481
|
this.handlers = void 0;
|
|
@@ -2439,8 +2495,8 @@ var SelectionManager = class {
|
|
|
2439
2495
|
this.last = key;
|
|
2440
2496
|
this.state.managers.navigation.setActive(key, false);
|
|
2441
2497
|
if (event.ctrlKey || event.metaKey) {
|
|
2442
|
-
if (items.has(key)) this.
|
|
2443
|
-
else this.
|
|
2498
|
+
if (items.has(key)) this.remove([key]);
|
|
2499
|
+
else this.add([key]);
|
|
2444
2500
|
return;
|
|
2445
2501
|
}
|
|
2446
2502
|
this.set([key]);
|
|
@@ -2451,29 +2507,29 @@ var SelectionManager = class {
|
|
|
2451
2507
|
const fromKey = keyed ? from : getKey(from.getAttribute("data-key"));
|
|
2452
2508
|
const toKey = keyed ? to : getKey(to.getAttribute("data-key"));
|
|
2453
2509
|
if (fromKey === toKey) return;
|
|
2454
|
-
const keys = state.managers.data
|
|
2510
|
+
const { keys } = state.managers.data;
|
|
2455
2511
|
const fromIndex = state.managers.data.getIndex(fromKey);
|
|
2456
2512
|
const toIndex = state.managers.data.getIndex(toKey);
|
|
2457
2513
|
if (fromIndex === -1 || toIndex === -1) return;
|
|
2458
2514
|
const [start, end] = fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
|
|
2459
2515
|
const selected = [];
|
|
2460
|
-
for (let index = start; index <= end; index += 1)
|
|
2461
|
-
|
|
2516
|
+
for (let index = start; index <= end; index += 1) {
|
|
2517
|
+
const key = keys[index];
|
|
2518
|
+
if (!(key instanceof GroupComponent)) selected.push(key);
|
|
2519
|
+
}
|
|
2520
|
+
if (keyed) this.add(selected);
|
|
2462
2521
|
else this.set(selected);
|
|
2463
2522
|
this.last = toKey;
|
|
2464
2523
|
this.state.managers.navigation.setActive(toKey, false);
|
|
2465
2524
|
}
|
|
2466
|
-
|
|
2525
|
+
remove(keys) {
|
|
2467
2526
|
const { length } = keys;
|
|
2468
|
-
|
|
2527
|
+
const removed = [];
|
|
2469
2528
|
for (let index = 0; index < length; index += 1) {
|
|
2470
2529
|
const key = keys[index];
|
|
2471
|
-
if (
|
|
2472
|
-
this.items.add(key);
|
|
2473
|
-
update = true;
|
|
2474
|
-
}
|
|
2530
|
+
if (this.items.delete(key)) removed.push(key);
|
|
2475
2531
|
}
|
|
2476
|
-
if (
|
|
2532
|
+
if (removed.length > 0) this.update(removed);
|
|
2477
2533
|
}
|
|
2478
2534
|
set(keys) {
|
|
2479
2535
|
const { items } = this;
|
|
@@ -2485,9 +2541,9 @@ var SelectionManager = class {
|
|
|
2485
2541
|
}
|
|
2486
2542
|
toggle() {
|
|
2487
2543
|
const { items, state } = this;
|
|
2488
|
-
const
|
|
2489
|
-
if (items.size ===
|
|
2490
|
-
else this.
|
|
2544
|
+
const { keys } = state.managers.data;
|
|
2545
|
+
if (items.size === keys.length - state.managers.group.items.length) this.clear();
|
|
2546
|
+
else this.set(keys.filter((key) => !(key instanceof GroupComponent)));
|
|
2491
2547
|
}
|
|
2492
2548
|
update(removed) {
|
|
2493
2549
|
const items = [...removed.map((key) => ({
|
|
@@ -2573,98 +2629,6 @@ on(document, "keyup", onShiftUp);
|
|
|
2573
2629
|
on(document, "mousedown", onMouseDown);
|
|
2574
2630
|
on(document, "mousemove", onMouseMove);
|
|
2575
2631
|
on(document, "mouseup", onMouseUp);
|
|
2576
|
-
var SortManager = class {
|
|
2577
|
-
handlers = Object.freeze({
|
|
2578
|
-
add: (field, direction) => this.add(field, direction),
|
|
2579
|
-
flip: (field) => this.flip(field),
|
|
2580
|
-
clear: () => this.clear(),
|
|
2581
|
-
remove: (field) => this.remove(field),
|
|
2582
|
-
set: (items) => this.set(items)
|
|
2583
|
-
});
|
|
2584
|
-
items = [];
|
|
2585
|
-
constructor(state) {
|
|
2586
|
-
this.state = state;
|
|
2587
|
-
}
|
|
2588
|
-
add(field, direction) {
|
|
2589
|
-
if (this.items.findIndex((item) => item.key === field) > -1) return;
|
|
2590
|
-
this.items.push({
|
|
2591
|
-
key: field,
|
|
2592
|
-
direction: direction ?? "ascending"
|
|
2593
|
-
});
|
|
2594
|
-
this.sort();
|
|
2595
|
-
}
|
|
2596
|
-
addOrSet(event, field) {
|
|
2597
|
-
if (event.ctrlKey || event.metaKey) this.add(field);
|
|
2598
|
-
else this.set([{
|
|
2599
|
-
field,
|
|
2600
|
-
direction: "ascending"
|
|
2601
|
-
}]);
|
|
2602
|
-
}
|
|
2603
|
-
clear() {
|
|
2604
|
-
if (this.items.length > 0) {
|
|
2605
|
-
this.items.length = 0;
|
|
2606
|
-
this.sort();
|
|
2607
|
-
}
|
|
2608
|
-
}
|
|
2609
|
-
destroy() {
|
|
2610
|
-
this.handlers = void 0;
|
|
2611
|
-
this.items = void 0;
|
|
2612
|
-
this.state = void 0;
|
|
2613
|
-
}
|
|
2614
|
-
flip(field) {
|
|
2615
|
-
const item = this.items.find((item) => item.key === field);
|
|
2616
|
-
if (item == null) return;
|
|
2617
|
-
item.direction = item.direction === "ascending" ? "descending" : "ascending";
|
|
2618
|
-
this.sort();
|
|
2619
|
-
}
|
|
2620
|
-
remove(field) {
|
|
2621
|
-
const index = this.items.findIndex((item) => item.key === field);
|
|
2622
|
-
if (index > -1) {
|
|
2623
|
-
this.items.splice(index, 1);
|
|
2624
|
-
this.sort();
|
|
2625
|
-
}
|
|
2626
|
-
}
|
|
2627
|
-
removeOrClear(event, field) {
|
|
2628
|
-
if (event.ctrlKey || event.metaKey) this.remove(field);
|
|
2629
|
-
else this.clear();
|
|
2630
|
-
}
|
|
2631
|
-
set(items) {
|
|
2632
|
-
this.items.splice(0, this.items.length, ...items.map((item) => ({
|
|
2633
|
-
key: item.field,
|
|
2634
|
-
direction: item.direction
|
|
2635
|
-
})));
|
|
2636
|
-
this.sort();
|
|
2637
|
-
}
|
|
2638
|
-
sort() {
|
|
2639
|
-
const { items, state } = this;
|
|
2640
|
-
const { length } = state.managers.column.items;
|
|
2641
|
-
for (let index = 0; index < length; index += 1) {
|
|
2642
|
-
const column = state.managers.column.items[index];
|
|
2643
|
-
const sorterIndex = items.findIndex((item) => item.key === column.options.field);
|
|
2644
|
-
const sorterItem = items[sorterIndex];
|
|
2645
|
-
setAttributes(column.elements.wrapper, {
|
|
2646
|
-
"aria-sort": sorterItem == null ? "none" : items.length > 1 ? "other" : sorterItem.direction,
|
|
2647
|
-
"data-sort-direction": sorterItem == null ? void 0 : sorterItem.direction
|
|
2648
|
-
});
|
|
2649
|
-
setAttribute(column.elements.sorter, "data-sort-position", sorterIndex > -1 && items.length > 1 ? sorterIndex + 1 : void 0);
|
|
2650
|
-
}
|
|
2651
|
-
state.managers.data.values.keys.active = items.length === 0 ? void 0 : sort(state.managers.data.values.keys.active?.map((key) => state.managers.data.values.objects.mapped.get(key)) ?? state.managers.data.values.objects.array, items).map((row) => row[state.key]);
|
|
2652
|
-
state.managers.render.update(true, true);
|
|
2653
|
-
}
|
|
2654
|
-
toggle(event, field, direction) {
|
|
2655
|
-
switch (direction) {
|
|
2656
|
-
case "ascending":
|
|
2657
|
-
this.flip(field);
|
|
2658
|
-
return;
|
|
2659
|
-
case "descending":
|
|
2660
|
-
this.removeOrClear(event, field);
|
|
2661
|
-
return;
|
|
2662
|
-
default:
|
|
2663
|
-
this.addOrSet(event, field);
|
|
2664
|
-
return;
|
|
2665
|
-
}
|
|
2666
|
-
}
|
|
2667
|
-
};
|
|
2668
2632
|
var Tabela = class {
|
|
2669
2633
|
#components = {
|
|
2670
2634
|
header: void 0,
|
|
@@ -2679,6 +2643,7 @@ var Tabela = class {
|
|
|
2679
2643
|
data: void 0,
|
|
2680
2644
|
event: void 0,
|
|
2681
2645
|
filter: void 0,
|
|
2646
|
+
group: void 0,
|
|
2682
2647
|
navigation: void 0,
|
|
2683
2648
|
render: void 0,
|
|
2684
2649
|
row: void 0,
|
|
@@ -2714,6 +2679,7 @@ var Tabela = class {
|
|
|
2714
2679
|
this.#managers.data = new DataManager(state);
|
|
2715
2680
|
this.#managers.event = new EventManager(state);
|
|
2716
2681
|
this.#managers.filter = new FilterManager(state);
|
|
2682
|
+
this.#managers.group = new GroupManager(state);
|
|
2717
2683
|
this.#managers.navigation = new NavigationManager(state);
|
|
2718
2684
|
this.#managers.render = new RenderManager(state);
|
|
2719
2685
|
this.#managers.row = new RowManager(state);
|