@3mo/data-grid
Version:
A data grid web component
101 lines (100 loc) • 4.1 kB
JavaScript
import { KeyboardController } from '@3mo/keyboard-controller';
export var DataGridSortingStrategy;
(function (DataGridSortingStrategy) {
DataGridSortingStrategy["Descending"] = "descending";
DataGridSortingStrategy["Ascending"] = "ascending";
})(DataGridSortingStrategy || (DataGridSortingStrategy = {}));
export class DataGridSortingController {
constructor(host) {
this.host = host;
}
get enabled() {
return !!this.host.sorting;
}
get() {
return this.toNormalizedRanked(this.host.sorting ?? []);
}
set(sorting) {
const normalized = this.toNormalizedRanked(sorting ?? []);
this.host.sorting = normalized;
this.host.sortingChange?.dispatch(normalized);
}
toNormalizedRanked(sorting) {
return (Array.isArray(sorting) ? sorting : [sorting])
.map((d, i) => ({ ...d, rank: i + 1 }));
}
reset() {
this.set([]);
}
/**
* Toggles the sorting strategy of the provided key path.
* If a modifier key is pressed, the sorting will be added to the existing sorting definitions.
*
* @param selector - The key path of the data to sort by
* @param strategy - The sorting strategy to use forcefully. If not provided, the strategy will be toggled between ascending, descending, and unsorted
*/
toggle(selector, strategy) {
const defaultSortingStrategy = DataGridSortingStrategy.Descending;
const sortings = this.get();
const existing = sortings.find(x => x.selector === selector);
const allowMultiple = KeyboardController.shift || KeyboardController.meta || KeyboardController.ctrl;
switch (true) {
case allowMultiple && !!strategy:
this.set([...sortings, { selector, strategy }]);
break;
case allowMultiple && existing?.selector !== selector:
this.set([...sortings, { selector, strategy: defaultSortingStrategy }]);
break;
case allowMultiple && existing?.strategy === DataGridSortingStrategy.Descending:
this.set(sortings.map(x => x.selector !== selector ? x : {
selector,
strategy: DataGridSortingStrategy.Ascending,
}));
break;
case allowMultiple:
this.set(sortings.filter(x => x.selector !== selector));
break;
case !!strategy:
this.set({ selector, strategy });
break;
case existing?.selector !== selector:
this.set({ selector, strategy: defaultSortingStrategy });
break;
case existing?.strategy === DataGridSortingStrategy.Descending:
this.set({ selector, strategy: DataGridSortingStrategy.Ascending });
break;
default:
this.reset();
break;
}
}
/**
* Sorts the provided data based on the current sorting definitions
* @param data - The data to sort
* @returns - The sorted data
*/
toSorted(data) {
return this.toSortedBy(data, d => d);
}
toSortedBy(data, extractor) {
const sorting = this.get();
if (!sorting?.length) {
return data;
}
return data.sort((a, b) => {
for (const definition of sorting) {
const { selector, strategy } = definition;
const aValue = KeyPath.get(extractor(a), selector) ?? Infinity;
const bValue = KeyPath.get(extractor(b), selector) ?? Infinity;
if (aValue < bValue) {
return strategy === DataGridSortingStrategy.Ascending ? -1 : 1;
}
else if (aValue > bValue) {
return strategy === DataGridSortingStrategy.Ascending ? 1 : -1;
}
// If values are equal, continue to the next level of sorting
}
return 0; // Items are equal in all sorting criteria
});
}
}